Implement support for ATAPI command set devices. It's used by some USB CD drives

and easy to implement since ATAPI basically is SCSI anyway and we don't use many
problematic commands. Only tested for the 0x05 subclass, but 0x02 should work
the same.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36162 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2010-04-11 17:13:49 +00:00
parent a2224f75d9
commit 8f4f2bf933
2 changed files with 33 additions and 15 deletions

View File

@ -273,7 +273,8 @@ usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength,
command.data_transfer_length = (dataLength != NULL ? *dataLength : 0);
command.flags = (directionIn ? CBW_DATA_INPUT : CBW_DATA_OUTPUT);
command.lun = lun->logical_unit_number;
command.command_block_length = opLength;
command.command_block_length
= device->is_atapi ? ATAPI_COMMAND_LENGTH : opLength;
memset(command.command_block, 0, sizeof(command.command_block));
switch (opLength) {
@ -492,7 +493,7 @@ usb_disk_mode_sense(device_lun *lun)
lun->write_protected
= (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) != 0;
TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no");
TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no");
return B_OK;
}
@ -504,8 +505,14 @@ usb_disk_test_unit_ready(device_lun *lun)
if (!lun->device->tur_supported)
return B_OK;
status_t result = usb_disk_operation(lun, SCSI_TEST_UNIT_READY_6, 6, 0, 0,
NULL, NULL, true);
status_t result;
if (lun->device->is_atapi) {
result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 1,
NULL, NULL, false);
} else {
result = usb_disk_operation(lun, SCSI_TEST_UNIT_READY_6, 6, 0, 0,
NULL, NULL, true);
}
if (result == B_DEV_INVALID_IOCTL) {
lun->device->tur_supported = false;
@ -539,10 +546,10 @@ usb_disk_inquiry(device_lun *lun)
TRACE("peripherial_qualifier 0x%02x\n", parameter.peripherial_qualifier);
TRACE("removable_medium %s\n", parameter.removable_medium ? "yes" : "no");
TRACE("version 0x%02x\n", parameter.version);
TRACE("response_data_format 0x%02x\n", parameter.response_data_format);
TRACE_ALWAYS("vendor_identification \"%.8s\"\n", parameter.vendor_identification);
TRACE_ALWAYS("product_identification \"%.16s\"\n", parameter.product_identification);
TRACE_ALWAYS("product_revision_level \"%.4s\"\n", parameter.product_revision_level);
TRACE("response_data_format 0x%02x\n", parameter.response_data_format);
TRACE_ALWAYS("vendor_identification \"%.8s\"\n", parameter.vendor_identification);
TRACE_ALWAYS("product_identification \"%.16s\"\n", parameter.product_identification);
TRACE_ALWAYS("product_revision_level \"%.4s\"\n", parameter.product_revision_level);
lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */
lun->removable = (parameter.removable_medium == 1);
return B_OK;
@ -652,6 +659,7 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
device->current_tag = 0;
device->sync_support = SYNC_SUPPORT_RELOAD;
device->tur_supported = true;
device->is_atapi = false;
device->luns = NULL;
// scan through the interfaces to find our bulk-only data interface
@ -667,7 +675,9 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
continue;
if (interface->descr->interface_class == 0x08 /* mass storage */
&& interface->descr->interface_subclass == 0x06 /* SCSI */
&& (interface->descr->interface_subclass == 0x06 /* SCSI */
|| interface->descr->interface_subclass == 0x02 /* ATAPI */
|| interface->descr->interface_subclass == 0x05 /* ATAPI */)
&& interface->descr->interface_protocol == 0x50 /* bulk-only */) {
bool hasIn = false;
@ -696,6 +706,7 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
continue;
device->interface = interface->descr->interface_number;
device->is_atapi = interface->descr->interface_subclass != 0x06;
break;
}
}
@ -746,8 +757,11 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
status_t ready = usb_disk_test_unit_ready(lun);
if (ready == B_OK || ready == B_DEV_NO_MEDIA) {
if (ready == B_OK) {
// TODO: check for write protection
//if (usb_disk_mode_sense(lun) != B_OK)
if (lun->device_type == B_CD)
lun->write_protected = true;
// TODO: check for write protection; disabled since
// some devices lock up when getting the mode sense
else if (/*usb_disk_mode_sense(lun) != B_OK*/true)
lun->write_protected = false;
}
@ -1193,7 +1207,7 @@ usb_disk_write(void *cookie, off_t position, const void *buffer,
//
status_t
status_t
init_hardware()
{
TRACE("init_hardware()\n");
@ -1210,8 +1224,10 @@ init_driver()
&usb_disk_device_removed
};
static usb_support_descriptor supportedDevices = {
0x08 /* mass storage */, 0x06 /* SCSI */, 0x50 /* bulk only */, 0, 0
static usb_support_descriptor supportedDevices[] = {
{ 0x08 /* mass storage */, 0x06 /* SCSI */, 0x50 /* bulk */, 0, 0 },
{ 0x08 /* mass storage */, 0x02 /* ATAPI */, 0x50 /* bulk */, 0, 0 },
{ 0x08 /* mass storage */, 0x05 /* ATAPI */, 0x50 /* bulk */, 0, 0 }
};
gDeviceList = NULL;
@ -1228,7 +1244,7 @@ init_driver()
return result;
}
gUSBModule->register_driver(DRIVER_NAME, &supportedDevices, 1, NULL);
gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 3, NULL);
gUSBModule->install_notify(DRIVER_NAME, &notifyHooks);
return B_OK;
}

View File

@ -15,6 +15,7 @@
#define REQUEST_MASS_STORAGE_RESET 0xff
#define REQUEST_GET_MAX_LUN 0xfe
#define MAX_LOGICAL_UNIT_NUMBER 15
#define ATAPI_COMMAND_LENGTH 12
#define CBW_SIGNATURE 0x43425355
#define CBW_DATA_OUTPUT 0x00
@ -45,6 +46,7 @@ typedef struct disk_device_s {
uint32 current_tag;
uint8 sync_support;
bool tur_supported;
bool is_atapi;
// used to store callback information
sem_id notify;