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
This commit is contained in:
Volker Ruppert 2014-01-21 20:56:50 +00:00
parent d591c1dd34
commit 39890d308d
6 changed files with 49 additions and 30 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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