From 39890d308d7d8fb2d1c3c33dbc7df45e2accd694 Mon Sep 17 00:00:00 2001 From: Volker Ruppert Date: Tue, 21 Jan 2014 20:56:50 +0000 Subject: [PATCH] Connecting USB CD-ROM without media present now supported TODO #1: implement seek timing similar to ATA/ATAPI TODO #2: implement asynchronus i/o in lowlevel cdrom --- bochs/iodev/hdimage/cdrom.cc | 6 +++--- bochs/iodev/usb/scsi_device.cc | 25 +++++++++++++++++++------ bochs/iodev/usb/scsi_device.h | 4 ++-- bochs/iodev/usb/usb_common.cc | 18 ++++++++++++------ bochs/iodev/usb/usb_msd.cc | 22 +++++++++++----------- bochs/iodev/usb/usb_msd.h | 4 ++-- 6 files changed, 49 insertions(+), 30 deletions(-) diff --git a/bochs/iodev/hdimage/cdrom.cc b/bochs/iodev/hdimage/cdrom.cc index 39535deb3..d3a621c68 100644 --- a/bochs/iodev/hdimage/cdrom.cc +++ b/bochs/iodev/hdimage/cdrom.cc @@ -2,7 +2,7 @@ // $Id$ ///////////////////////////////////////////////////////////////////////// // -// Copyright (C) 2002-2013 The Bochs Project +// Copyright (C) 2002-2014 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -69,11 +69,11 @@ bx_bool cdrom_base_c::insert_cdrom(const char *dev) // Load CD-ROM. Returns 0 if CD is not ready. if (dev != NULL) path = strdup(dev); - BX_INFO(("load cdrom with path=%s", path)); + BX_INFO(("load cdrom with path='%s'", path)); // all platforms except win32 fd = open(path, O_RDONLY); if (fd < 0) { - BX_ERROR(("open cd failed for %s: %s", path, strerror(errno))); + BX_ERROR(("open cd failed for '%s': %s", path, strerror(errno))); return 0; } // do fstat to determine if it's a file or a device, then set using_file. diff --git a/bochs/iodev/usb/scsi_device.cc b/bochs/iodev/usb/scsi_device.cc index 2f1b1d447..7eefbee5f 100644 --- a/bochs/iodev/usb/scsi_device.cc +++ b/bochs/iodev/usb/scsi_device.cc @@ -9,7 +9,7 @@ // // Written by Paul Brook // -// Copyright (C) 2007-2013 The Bochs Project +// Copyright (C) 2007-2014 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -78,8 +78,8 @@ scsi_device_t::scsi_device_t(cdrom_base_c *_cdrom, int _tcq, dev = _dev; cluster_size = 4; locked = 0; - inserted = 1; - max_lba = cdrom->capacity() - 1; + inserted = 0; + max_lba = 0; sprintf(drive_serial_str, "%d", serial_number++); put("SCSICD"); @@ -643,13 +643,13 @@ Bit32s scsi_device_t::scsi_send_command(Bit32u tag, Bit8u *buf, int lun) // The normal LEN field for this command is zero memset(outbuf, 0, 8); if (type == SCSIDEV_TYPE_CDROM) { - nb_sectors = cdrom->capacity(); + nb_sectors = max_lba; } else { nb_sectors = hdimage->hd_size / 512; + nb_sectors--; } /* Returned value is the address of the last sector. */ if (nb_sectors) { - nb_sectors--; outbuf[0] = (Bit8u)((nb_sectors >> 24) & 0xff); outbuf[1] = (Bit8u)((nb_sectors >> 16) & 0xff); outbuf[2] = (Bit8u)((nb_sectors >> 8) & 0xff); @@ -693,6 +693,8 @@ Bit32s scsi_device_t::scsi_send_command(Bit32u tag, Bit8u *buf, int lun) int start_track, format, msf, toclen = 0; if (type == SCSIDEV_TYPE_CDROM) { + if (!inserted) + goto notready; msf = buf[1] & 2; format = buf[2] & 0xf; start_track = buf[6]; @@ -754,9 +756,10 @@ Bit32s scsi_device_t::scsi_send_command(Bit32u tag, Bit8u *buf, int lun) // Current/Max Cap Header if (type == SCSIDEV_TYPE_CDROM) { - nb_sectors = cdrom->capacity(); + nb_sectors = max_lba; } else { nb_sectors = (hdimage->hd_size / 512); + nb_sectors--; } /* Returned value is the address of the last sector.  */ outbuf[4] = (Bit8u)((nb_sectors >> 24) & 0xff); @@ -794,4 +797,14 @@ Bit32s scsi_device_t::scsi_send_command(Bit32u tag, Bit8u *buf, int lun) } } +void scsi_device_t::set_inserted(bx_bool value) +{ + inserted = value; + if (inserted) { + max_lba = cdrom->capacity() - 1; + } else { + max_lba = 0; + } +} + #endif // BX_SUPPORT_PCI && BX_SUPPORT_PCIUSB diff --git a/bochs/iodev/usb/scsi_device.h b/bochs/iodev/usb/scsi_device.h index 5c52d1875..e544716d6 100644 --- a/bochs/iodev/usb/scsi_device.h +++ b/bochs/iodev/usb/scsi_device.h @@ -9,7 +9,7 @@ // // Written by Paul Brook // -// Copyright (C) 2007-2013 The Bochs Project +// Copyright (C) 2007-2014 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -84,7 +84,7 @@ public: int scsi_write_data(Bit32u tag); Bit8u* scsi_get_buf(Bit32u tag); const char *get_serial_number() {return drive_serial_str;} - void set_inserted(bx_bool value) {inserted = value;} + void set_inserted(bx_bool value); bx_bool get_inserted() {return inserted;} protected: diff --git a/bochs/iodev/usb/usb_common.cc b/bochs/iodev/usb/usb_common.cc index 8005abd79..e8447aa8e 100644 --- a/bochs/iodev/usb/usb_common.cc +++ b/bochs/iodev/usb/usb_common.cc @@ -6,7 +6,7 @@ // // Copyright (c) 2005 Fabrice Bellard // Copyright (C) 2009 Benjamin D Lunt (fys at frontiernet net) -// 2009-2013 The Bochs Project +// 2009-2014 The Bochs Project // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -73,8 +73,10 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void ** int ports; usb_device_c **device = (usb_device_c**)dev; const char *devname = NULL; + size_t dnlen; devname = ((bx_param_string_c*)portconf->get_by_name("device"))->getptr(); + dnlen = strlen(devname); if (!strcmp(devname, "mouse")) { type = USB_DEV_TYPE_MOUSE; *device = new usb_hid_device_c(type); @@ -85,7 +87,7 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void ** type = USB_DEV_TYPE_KEYPAD; *device = new usb_hid_device_c(type); } else if (!strncmp(devname, "disk", 4)) { - if ((strlen(devname) > 5) && (devname[4] == ':')) { + if ((dnlen > 5) && (devname[4] == ':')) { type = USB_DEV_TYPE_DISK; *device = new usb_msd_device_c(type, devname+5); } else { @@ -93,9 +95,13 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void ** return type; } } else if (!strncmp(devname, "cdrom", 5)) { - if ((strlen(devname) > 6) && (devname[5] == ':')) { + if ((dnlen == 5) || (devname[5] == ':')) { type = USB_DEV_TYPE_CDROM; - *device = new usb_msd_device_c(type, devname+6); + if (dnlen > 6) { + *device = new usb_msd_device_c(type, devname+6); + } else { + *device = new usb_msd_device_c(type, devname+dnlen); + } } else { hub->panic("USB device 'cdrom' needs a filename separated with a colon"); return type; @@ -103,7 +109,7 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void ** } else if (!strncmp(devname, "hub", 3)) { type = USB_DEV_TYPE_HUB; ports = 4; - if (strlen(devname) > 3) { + if (dnlen > 3) { if (devname[3] == ':') { ports = atoi(&devname[4]); if ((ports < 2) || (ports > BX_N_USB_HUB_PORTS)) { @@ -115,7 +121,7 @@ int bx_usb_devctl_c::init_device(bx_list_c *portconf, logfunctions *hub, void ** } *device = new usb_hub_device_c(ports); } else if (!strncmp(devname, "printer", 7)) { - if ((strlen(devname) > 8) && (devname[7] == ':')) { + if ((dnlen > 8) && (devname[7] == ':')) { type = USB_DEV_TYPE_PRINTER; *device = new usb_printer_device_c(type, devname+8); } else { diff --git a/bochs/iodev/usb/usb_msd.cc b/bochs/iodev/usb/usb_msd.cc index 71fb3347c..e4cb0fe30 100644 --- a/bochs/iodev/usb/usb_msd.cc +++ b/bochs/iodev/usb/usb_msd.cc @@ -6,7 +6,7 @@ // // Copyright (c) 2006 CodeSourcery. // Written by Paul Brook -// Copyright (C) 2009-2013 The Bochs Project +// Copyright (C) 2009-2014 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -180,7 +180,7 @@ usb_msd_device_c::usb_msd_device_c(usbdev_type type, const char *filename) "Status", "CD-ROM media status (inserted / ejected)", media_status_names, - BX_EJECTED, + BX_INSERTED, BX_EJECTED); status->set_handler(cd_param_handler); status->set_ask_format("Is the device inserted or ejected? [%s] "); @@ -232,13 +232,12 @@ bx_bool usb_msd_device_c::init() sprintf(s.info_txt, "USB HD: path='%s', mode='%s'", s.fname, hdimage_mode_names[s.image_mode]); } else if (d.type == USB_DEV_TYPE_CDROM) { s.cdrom = DEV_hdimage_init_cdrom(s.fname); - if (!s.cdrom->insert_cdrom()) { - BX_ERROR(("could not open cdrom image file '%s'", s.fname)); - return 0; + s.scsi_dev = new scsi_device_t(s.cdrom, 0, usb_msd_command_complete, (void*)this); + if (set_inserted(1)) { + sprintf(s.info_txt, "USB CD: path='%s'", s.fname); } else { - s.scsi_dev = new scsi_device_t(s.cdrom, 0, usb_msd_command_complete, (void*)this); + sprintf(s.info_txt, "USB CD: media not present"); } - sprintf(s.info_txt, "USB CD: path='%s'", s.fname); } s.scsi_dev->register_state(s.sr_list, "scsidev"); s.mode = USB_MSDM_CBW; @@ -649,20 +648,21 @@ void usb_msd_device_c::cancel_packet(USBPacket *p) s.scsi_len = 0; } -void usb_msd_device_c::set_inserted(bx_bool value) +bx_bool usb_msd_device_c::set_inserted(bx_bool value) { const char *path; if (value) { path = SIM->get_param_string("path", s.config)->getptr(); if (!s.cdrom->insert_cdrom(path)) { - SIM->get_param_bool("status", s.config)->set(0); - return; + SIM->get_param_enum("status", s.config)->set(BX_EJECTED); + return 0; } } else { s.cdrom->eject_cdrom(); } s.scsi_dev->set_inserted(value); + return value; } bx_bool usb_msd_device_c::get_inserted() @@ -689,7 +689,7 @@ const char *usb_msd_device_c::cd_param_string_handler(bx_param_string_c *param, param->set("none"); } } else { - SIM->get_param_bool("status", param->get_parent())->set(0); + SIM->get_param_enum("status", param->get_parent())->set(BX_EJECTED); } } else { BX_PANIC(("cd_param_string_handler: cdrom not found")); diff --git a/bochs/iodev/usb/usb_msd.h b/bochs/iodev/usb/usb_msd.h index 9475118c7..0c40040ef 100644 --- a/bochs/iodev/usb/usb_msd.h +++ b/bochs/iodev/usb/usb_msd.h @@ -6,7 +6,7 @@ // // Copyright (c) 2006 CodeSourcery. // Written by Paul Brook -// Copyright (C) 2009-2013 The Bochs Project +// Copyright (C) 2009-2014 The Bochs Project // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -44,7 +44,7 @@ public: virtual int handle_data(USBPacket *p); virtual void register_state_specific(bx_list_c *parent); virtual void cancel_packet(USBPacket *p); - void set_inserted(bx_bool value); + bx_bool set_inserted(bx_bool value); bx_bool get_inserted(); protected: