Some work on the USB floppy emulation.

- Removed USB device type handling from constructor and init code, since we
  only the 'floppy' type here.
- Write commands now using the device buffer for one sector.
TODO: support for starting without media and runtime media change.
This commit is contained in:
Volker Ruppert 2015-08-16 06:44:16 +00:00
parent 5bc1717adc
commit 823ba769fb
3 changed files with 38 additions and 30 deletions

View File

@ -276,29 +276,27 @@ static Bit8u bx_cbi_dev_mode_sense_cur[] = {
0x00, 0x00, 0x00 // reserved 0x00, 0x00, 0x00 // reserved
}; };
usb_cbi_device_c::usb_cbi_device_c(usbdev_type type, const char *filename) usb_cbi_device_c::usb_cbi_device_c(const char *filename)
{ {
char tmpfname[BX_PATHNAME_LEN]; char tmpfname[BX_PATHNAME_LEN];
char *ptr1, *ptr2; char *ptr1, *ptr2;
d.type = type; d.type = USB_DEV_TYPE_FLOPPY;
d.maxspeed = USB_SPEED_FULL; d.maxspeed = USB_SPEED_FULL;
memset((void*)&s, 0, sizeof(s)); memset((void*)&s, 0, sizeof(s));
if (d.type == USB_DEV_TYPE_FLOPPY) { strcpy(d.devname, "BOCHS USB CBI FLOPPY");
strcpy(d.devname, "BOCHS USB CBI FLOPPY"); strcpy(tmpfname, filename);
strcpy(tmpfname, filename); ptr1 = strtok(tmpfname, ":");
ptr1 = strtok(tmpfname, ":"); ptr2 = strtok(NULL, ":");
ptr2 = strtok(NULL, ":"); if ((ptr2 == NULL) || (strlen(ptr1) < 2)) {
if ((ptr2 == NULL) || (strlen(ptr1) < 2)) { s.image_mode = BX_HDIMAGE_MODE_FLAT;
s.image_mode = BX_HDIMAGE_MODE_FLAT; s.fname = filename;
s.fname = filename; } else {
} else { s.image_mode = SIM->hdimage_get_mode(ptr1);
s.image_mode = SIM->hdimage_get_mode(ptr1); s.fname = filename+strlen(ptr1)+1;
s.fname = filename+strlen(ptr1)+1; if ((s.image_mode != BX_HDIMAGE_MODE_FLAT) &&
if ((s.image_mode != BX_HDIMAGE_MODE_FLAT) && (s.image_mode != BX_HDIMAGE_MODE_VVFAT)) {
(s.image_mode != BX_HDIMAGE_MODE_VVFAT)) { BX_PANIC(("USB floppy only supports image modes 'flat' and 'vvfat'"));
BX_PANIC(("USB floppy only supports image modes 'flat' and 'vvfat'"));
}
} }
} }
@ -337,14 +335,17 @@ bx_bool usb_cbi_device_c::set_option(const char *option)
bx_bool usb_cbi_device_c::init() bx_bool usb_cbi_device_c::init()
{ {
if (d.type == USB_DEV_TYPE_FLOPPY) { if ((strlen(s.fname) > 0) && (strcmp(s.fname, "none"))) {
s.hdimage = DEV_hdimage_init_image(s.image_mode, 1474560, ""); s.hdimage = DEV_hdimage_init_image(s.image_mode, 1474560, "");
if ((s.hdimage->open(s.fname)) < 0) { if ((s.hdimage->open(s.fname)) < 0) {
BX_PANIC(("could not open floppy drive image file '%s'", s.fname)); BX_PANIC(("could not open floppy drive image file '%s'", s.fname));
return 0; return 0;
} }
sprintf(s.info_txt, "USB CBI: path='%s', mode='%s'", s.fname, hdimage_mode_names[s.image_mode]); } else {
BX_ERROR(("USB floppy without media not supported yet"));
return 0;
} }
sprintf(s.info_txt, "USB CBI: path='%s', mode='%s'", s.fname, hdimage_mode_names[s.image_mode]);
d.connected = 1; d.connected = 1;
s.dev_buffer = new Bit8u[CBI_MAX_SECTORS * 512]; s.dev_buffer = new Bit8u[CBI_MAX_SECTORS * 512];
@ -661,8 +662,8 @@ bx_bool usb_cbi_device_c::handle_command(Bit8u *command)
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.hdimage->lseek(lba * 512, SEEK_SET) < 0) if (s.hdimage->lseek(lba * 512, SEEK_SET) < 0)
BX_ERROR(("could not lseek() floppy drive image file")); BX_ERROR(("could not lseek() floppy drive image file"));
s.usb_len = (count * 512); s.data_len = (count * 512);
s.data_len = s.usb_len; s.usb_len = 0;
break; break;
case UFI_READ_CAPACITY: case UFI_READ_CAPACITY:
@ -784,12 +785,15 @@ int usb_cbi_device_c::handle_data(USBPacket *p)
bx_gui->statusbar_setitem(s.statusbar_id, 1, 1); // write bx_gui->statusbar_setitem(s.statusbar_id, 1, 1); // write
if (len > (int) s.data_len) if (len > (int) s.data_len)
goto fail; goto fail;
if (len > 0) if (len > 0) {
// This will write so many bytes to the "disk". memcpy(s.usb_buf+s.usb_len, data, len);
// I don't know if the actual hardware waits for a 512 byte block s.usb_len += len;
// before it writes it... s.data_len -= len;
s.hdimage->write((bx_ptr_t) data, len); }
s.data_len -= len; if ((s.data_len == 0) || (s.usb_len >= 512)) {
s.hdimage->write((bx_ptr_t) s.usb_buf, 512);
s.usb_len = 0;
}
ret = len; ret = len;
if (ret > 0) usb_dump_packet(data, ret); if (ret > 0) usb_dump_packet(data, ret);

View File

@ -49,7 +49,7 @@ class device_image_t;
class usb_cbi_device_c : public usb_device_c { class usb_cbi_device_c : public usb_device_c {
public: public:
usb_cbi_device_c(usbdev_type type, const char *filename); usb_cbi_device_c(const char *filename);
virtual ~usb_cbi_device_c(void); virtual ~usb_cbi_device_c(void);
virtual bx_bool init(); virtual bx_bool init();

View File

@ -130,9 +130,13 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void **
return type; return type;
} }
} else if (!strncmp(devname, "floppy", 6)) { } else if (!strncmp(devname, "floppy", 6)) {
if ((dnlen > 7) && (devname[6] == ':')) { if ((dnlen == 6) || (devname[6] == ':')) {
type = USB_DEV_TYPE_FLOPPY; type = USB_DEV_TYPE_FLOPPY;
*device = new usb_cbi_device_c(type, devname+7); if (dnlen > 7) {
*device = new usb_cbi_device_c(devname+7);
} else {
*device = new usb_cbi_device_c(devname+dnlen);
}
} else { } else {
hub->panic("USB device 'floppy' needs a filename separated with a colon"); hub->panic("USB device 'floppy' needs a filename separated with a colon");
return type; return type;