USB floppy command FORMAT UNIT implemented and read commands fixed. Formatting
media in USB floppy works now with XP guest.
This commit is contained in:
parent
12cace4c5a
commit
6cbd6e247a
@ -46,7 +46,7 @@
|
|||||||
#define LOG_THIS
|
#define LOG_THIS
|
||||||
|
|
||||||
// maximum size of the read buffer in sectors
|
// maximum size of the read buffer in sectors
|
||||||
#define CBI_MAX_SECTORS 16
|
#define CBI_MAX_SECTORS 18
|
||||||
|
|
||||||
// Set this to zero if you only support CB interface. Set to 1 if you support CBI.
|
// Set this to zero if you only support CB interface. Set to 1 if you support CBI.
|
||||||
#define USB_CBI_USE_INTERRUPT 1
|
#define USB_CBI_USE_INTERRUPT 1
|
||||||
@ -423,6 +423,7 @@ void usb_cbi_device_c::register_state_specific(bx_list_c *parent)
|
|||||||
rt_config->set_restore_handler(this, usb_cbi_restore_handler);
|
rt_config->set_restore_handler(this, usb_cbi_restore_handler);
|
||||||
new bx_shadow_num_c(list, "usb_len", &s.usb_len);
|
new bx_shadow_num_c(list, "usb_len", &s.usb_len);
|
||||||
new bx_shadow_num_c(list, "data_len", &s.data_len);
|
new bx_shadow_num_c(list, "data_len", &s.data_len);
|
||||||
|
new bx_shadow_num_c(list, "sector", &s.sector);
|
||||||
new bx_shadow_num_c(list, "sector_count", &s.sector_count);
|
new bx_shadow_num_c(list, "sector_count", &s.sector_count);
|
||||||
new bx_shadow_num_c(list, "cur_command", &s.cur_command);
|
new bx_shadow_num_c(list, "cur_command", &s.cur_command);
|
||||||
new bx_shadow_num_c(list, "fail_count", &s.fail_count);
|
new bx_shadow_num_c(list, "fail_count", &s.fail_count);
|
||||||
@ -703,24 +704,21 @@ bx_bool usb_cbi_device_c::handle_command(Bit8u *command)
|
|||||||
(command[8] << 8) |
|
(command[8] << 8) |
|
||||||
(command[9] << 0));
|
(command[9] << 0));
|
||||||
case UFI_READ_10:
|
case UFI_READ_10:
|
||||||
BX_DEBUG(("UFI_READ%i COMMAND (lba = %i, count = %i)", (s.cur_command == UFI_READ_12) ? 12 : 10, lba, count));
|
BX_DEBUG(("UFI_READ_%i COMMAND (lba = %i, count = %i)", (s.cur_command == UFI_READ_12) ? 12 : 10, lba, count));
|
||||||
if (!s.inserted) {
|
if (!s.inserted) {
|
||||||
s.sense = 2;
|
s.sense = 2;
|
||||||
s.asc = 0x3a;
|
s.asc = 0x3a;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (count > CBI_MAX_SECTORS) {
|
s.sector = lba;
|
||||||
s.sector_count = count - CBI_MAX_SECTORS;
|
s.sector_count = count;
|
||||||
count = CBI_MAX_SECTORS;
|
s.data_len = (count * 512);
|
||||||
}
|
|
||||||
if (s.hdimage->lseek(lba * 512, SEEK_SET) < 0) {
|
|
||||||
BX_ERROR(("could not lseek() floppy drive image file"));
|
|
||||||
s.usb_len = 0;
|
s.usb_len = 0;
|
||||||
} else {
|
|
||||||
s.usb_len = (unsigned) s.hdimage->read((bx_ptr_t) s.usb_buf, count * 512);
|
|
||||||
bx_gui->statusbar_setitem(s.statusbar_id, 1); // read
|
bx_gui->statusbar_setitem(s.statusbar_id, 1); // read
|
||||||
|
if (s.hdimage->lseek(s.sector * 512, SEEK_SET) < 0) {
|
||||||
|
BX_ERROR(("could not lseek() floppy drive image file"));
|
||||||
|
ret = 0;
|
||||||
}
|
}
|
||||||
s.data_len = s.usb_len;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UFI_WRITE_12:
|
case UFI_WRITE_12:
|
||||||
@ -729,7 +727,7 @@ bx_bool usb_cbi_device_c::handle_command(Bit8u *command)
|
|||||||
(command[8] << 8) |
|
(command[8] << 8) |
|
||||||
(command[9] << 0));
|
(command[9] << 0));
|
||||||
case UFI_WRITE_10:
|
case UFI_WRITE_10:
|
||||||
BX_DEBUG(("UFI_WRITE%i COMMAND (lba = %i, count = %i)", (s.cur_command == UFI_WRITE_12) ? 12 : 10, lba, count));
|
BX_DEBUG(("UFI_WRITE_%i COMMAND (lba = %i, count = %i)", (s.cur_command == UFI_WRITE_12) ? 12 : 10, lba, count));
|
||||||
if (!s.inserted) {
|
if (!s.inserted) {
|
||||||
s.sense = 2;
|
s.sense = 2;
|
||||||
s.asc = 0x3a;
|
s.asc = 0x3a;
|
||||||
@ -830,8 +828,18 @@ bx_bool usb_cbi_device_c::handle_command(Bit8u *command)
|
|||||||
// However, we'll allow the command to return valid return.
|
// However, we'll allow the command to return valid return.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UFI_REZERO:
|
|
||||||
case UFI_FORMAT_UNIT:
|
case UFI_FORMAT_UNIT:
|
||||||
|
BX_DEBUG(("UFI_FORMAT_UNIT COMMAND (track = %i)", command[2]));
|
||||||
|
if (!s.inserted) {
|
||||||
|
s.sense = 2;
|
||||||
|
s.asc = 0x3a;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
s.sector = command[2] * 36;
|
||||||
|
s.data_len = (unsigned) ((command[7] << 8) | command[8]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case UFI_REZERO:
|
||||||
case UFI_SEND_DIAGNOSTIC:
|
case UFI_SEND_DIAGNOSTIC:
|
||||||
case UFI_SEEK_10:
|
case UFI_SEEK_10:
|
||||||
case UFI_WRITE_VERIFY:
|
case UFI_WRITE_VERIFY:
|
||||||
@ -850,9 +858,9 @@ int usb_cbi_device_c::handle_data(USBPacket *p)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
Bit8u devep = p->devep;
|
Bit8u devep = p->devep;
|
||||||
Bit8u *data = p->data;
|
Bit8u *data = p->data, *tmpbuf;
|
||||||
int len = p->len;
|
int len = p->len, len1, len2;
|
||||||
Bit32u count;
|
Bit32u count, max_sectors, offset;
|
||||||
|
|
||||||
switch (p->pid) {
|
switch (p->pid) {
|
||||||
case USB_TOKEN_OUT:
|
case USB_TOKEN_OUT:
|
||||||
@ -884,6 +892,35 @@ int usb_cbi_device_c::handle_data(USBPacket *p)
|
|||||||
if (ret > 0) usb_dump_packet(data, ret);
|
if (ret > 0) usb_dump_packet(data, ret);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case UFI_FORMAT_UNIT:
|
||||||
|
if (s.wp)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
if (len > (int) s.data_len)
|
||||||
|
goto fail;
|
||||||
|
BX_DEBUG(("FORMAT UNIT: single track = %i, side = %i", (data[1] >> 4) & 1, data[1] & 1));
|
||||||
|
bx_gui->statusbar_setitem(s.statusbar_id, 1, 1); // write
|
||||||
|
if ((data[1] >> 4) & 1) {
|
||||||
|
offset = s.sector * 512;
|
||||||
|
if (data[1] & 1) {
|
||||||
|
offset += (18 * 512);
|
||||||
|
}
|
||||||
|
if (s.hdimage->lseek(offset, SEEK_SET) < 0) {
|
||||||
|
BX_ERROR(("could not lseek() floppy drive image file"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
memset(s.dev_buffer, 0xff, 18 * 512);
|
||||||
|
if (s.hdimage->write((bx_ptr_t) s.dev_buffer, 18 * 512) < 0) {
|
||||||
|
BX_ERROR(("write error"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
BX_ERROR(("FORMAT UNIT with no SINGLE TRACK bit set not yet supported"));
|
||||||
|
}
|
||||||
|
usb_dump_packet(data, len);
|
||||||
|
ret = len;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@ -896,6 +933,65 @@ int usb_cbi_device_c::handle_data(USBPacket *p)
|
|||||||
switch (s.cur_command) {
|
switch (s.cur_command) {
|
||||||
case UFI_READ_10:
|
case UFI_READ_10:
|
||||||
case UFI_READ_12:
|
case UFI_READ_12:
|
||||||
|
if (len > (int) s.data_len)
|
||||||
|
len = s.data_len;
|
||||||
|
tmpbuf = data;
|
||||||
|
len1 = len;
|
||||||
|
while (len1 > 0) {
|
||||||
|
if (s.usb_len > 0) {
|
||||||
|
len2 = (len1 > (int)s.usb_len) ? s.usb_len : len1;
|
||||||
|
memcpy(tmpbuf, s.dev_buffer, len2);
|
||||||
|
tmpbuf += len2;
|
||||||
|
len1 -= len2;
|
||||||
|
s.data_len -= len2;
|
||||||
|
s.usb_len -= len2;
|
||||||
|
if (s.usb_len > 0) {
|
||||||
|
memcpy(s.dev_buffer, s.dev_buffer+len2, s.usb_len);
|
||||||
|
} else {
|
||||||
|
s.usb_buf = s.dev_buffer;
|
||||||
|
}
|
||||||
|
if (len1 == 0) break;
|
||||||
|
}
|
||||||
|
if ((int)s.usb_len < len1) {
|
||||||
|
count = s.sector_count;
|
||||||
|
max_sectors = CBI_MAX_SECTORS - (s.usb_len + 511) / 512;
|
||||||
|
if (count > max_sectors) {
|
||||||
|
count = max_sectors;
|
||||||
|
}
|
||||||
|
s.sector_count -= count;
|
||||||
|
ret = s.hdimage->read((bx_ptr_t) s.usb_buf, count * 512);
|
||||||
|
if (ret > 0) {
|
||||||
|
s.usb_len += ret;
|
||||||
|
s.usb_buf += ret;
|
||||||
|
} else {
|
||||||
|
BX_ERROR(("read error"));
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (len1 <= (int)s.usb_len) {
|
||||||
|
memcpy(tmpbuf, s.dev_buffer, len1);
|
||||||
|
s.data_len -= len1;
|
||||||
|
if (s.data_len > 0) {
|
||||||
|
if ((int)s.usb_len > len1) {
|
||||||
|
s.usb_len -= len1;
|
||||||
|
memmove(s.dev_buffer, s.dev_buffer+len1, s.usb_len);
|
||||||
|
s.usb_buf -= len1;
|
||||||
|
} else {
|
||||||
|
s.usb_len = 0;
|
||||||
|
s.usb_buf = s.dev_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len1 = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (s.data_len > 0) {
|
||||||
|
bx_gui->statusbar_setitem(s.statusbar_id, 1); // read
|
||||||
|
}
|
||||||
|
ret = len;
|
||||||
|
usb_dump_packet(data, ret);
|
||||||
|
break;
|
||||||
|
|
||||||
case UFI_READ_CAPACITY:
|
case UFI_READ_CAPACITY:
|
||||||
case UFI_MODE_SENSE:
|
case UFI_MODE_SENSE:
|
||||||
case UFI_READ_FORMAT_CAPACITIES:
|
case UFI_READ_FORMAT_CAPACITIES:
|
||||||
@ -907,21 +1003,7 @@ int usb_cbi_device_c::handle_data(USBPacket *p)
|
|||||||
s.usb_buf += len;
|
s.usb_buf += len;
|
||||||
s.data_len -= len;
|
s.data_len -= len;
|
||||||
ret = len;
|
ret = len;
|
||||||
if ((s.data_len == 0) && (s.sector_count > 0)) {
|
usb_dump_packet(data, ret);
|
||||||
count = s.sector_count;
|
|
||||||
if (count > CBI_MAX_SECTORS) {
|
|
||||||
s.sector_count = count - CBI_MAX_SECTORS;
|
|
||||||
count = CBI_MAX_SECTORS;
|
|
||||||
} else {
|
|
||||||
s.sector_count = 0;
|
|
||||||
}
|
|
||||||
s.usb_buf = s.dev_buffer;
|
|
||||||
s.usb_len = (unsigned) s.hdimage->read((bx_ptr_t) s.usb_buf, count * 512);
|
|
||||||
s.data_len = s.usb_len;
|
|
||||||
bx_gui->statusbar_setitem(s.statusbar_id, 1); // read
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret > 0) usb_dump_packet(data, ret);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UFI_START_STOP_UNIT:
|
case UFI_START_STOP_UNIT:
|
||||||
|
@ -70,6 +70,7 @@ private:
|
|||||||
Bit32u usb_len;
|
Bit32u usb_len;
|
||||||
Bit8u *usb_buf;
|
Bit8u *usb_buf;
|
||||||
Bit32u data_len;
|
Bit32u data_len;
|
||||||
|
Bit32u sector;
|
||||||
Bit32u sector_count;
|
Bit32u sector_count;
|
||||||
Bit8u image_mode;
|
Bit8u image_mode;
|
||||||
device_image_t *hdimage;
|
device_image_t *hdimage;
|
||||||
|
Loading…
Reference in New Issue
Block a user