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:
Volker Ruppert 2015-09-19 12:45:54 +00:00
parent 12cace4c5a
commit 6cbd6e247a
2 changed files with 116 additions and 33 deletions

View File

@ -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:

View File

@ -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;