Adding mode sense command to retrieve the write protected status. Doesn't work

yet, so not enabled for now.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30082 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz
2009-04-09 20:47:10 +00:00
parent 3c2a04f4c9
commit ac0a972985
3 changed files with 52 additions and 2 deletions
@@ -134,6 +134,7 @@ status_t usb_disk_operation(device_lun *lun, uint8 operation,
bool directionIn);
status_t usb_disk_request_sense(device_lun *lun);
status_t usb_disk_mode_sense(device_lun *lun);
status_t usb_disk_test_unit_ready(device_lun *lun);
status_t usb_disk_inquiry(device_lun *lun);
status_t usb_disk_reset_capacity(device_lun *lun);
@@ -280,6 +281,10 @@ usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength,
commandBlock->operation = operation;
commandBlock->lun = lun->logical_unit_number << 5;
commandBlock->allocation_length = (uint8)transferLength;
if (operation == SCSI_MODE_SENSE_6) {
// we hijack the lba argument to transport the desired page
commandBlock->reserved[1] = (uint8)logicalBlockAddress;
}
break;
}
@@ -464,6 +469,26 @@ usb_disk_request_sense(device_lun *lun)
}
status_t
usb_disk_mode_sense(device_lun *lun)
{
uint32 dataLength = sizeof(scsi_mode_sense_6_parameter);
scsi_mode_sense_6_parameter parameter;
status_t result = usb_disk_operation(lun, SCSI_MODE_SENSE_6, 6,
SCSI_MODE_PAGE_DEVICE_CONFIGURATION, dataLength, &parameter,
&dataLength, true);
if (result != B_OK) {
TRACE_ALWAYS("getting mode sense data failed\n");
return result;
}
lun->write_protected
= (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) != 0;
TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no");
return B_OK;
}
status_t
usb_disk_test_unit_ready(device_lun *lun)
{
@@ -699,8 +724,16 @@ usb_disk_device_added(usb_device newDevice, void **cookie)
result = usb_disk_inquiry(lun);
for (uint32 tries = 0; tries < 3; tries++) {
status_t ready = usb_disk_test_unit_ready(lun);
if (ready == B_OK || ready == B_DEV_NO_MEDIA)
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)
lun->write_protected = false;
}
break;
}
snooze(10000);
}
@@ -956,7 +989,7 @@ usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
geometry->sectors_per_track = geometry->head_count = 1;
geometry->device_type = lun->device_type;
geometry->removable = lun->removable;
geometry->read_only = (lun->device_type == B_CD);
geometry->read_only = lun->write_protected;
geometry->write_once = (lun->device_type == B_WORM);
TRACE("B_GET_GEOMETRY: %ld sectors at %ld bytes per sector\n",
geometry->cylinder_count, geometry->bytes_per_sector);
@@ -69,6 +69,7 @@ struct device_lun_s {
uint32 block_size;
uint8 device_type;
bool removable;
bool write_protected;
};
@@ -13,6 +13,7 @@ typedef enum {
SCSI_TEST_UNIT_READY_6 = 0x00,
SCSI_REQUEST_SENSE_6 = 0x03,
SCSI_INQUIRY_6 = 0x12,
SCSI_MODE_SENSE_6 = 0x1a,
SCSI_START_STOP_UNIT_6 = 0x1b,
SCSI_READ_CAPACITY_10 = 0x25,
SCSI_READ_10 = 0x28,
@@ -69,6 +70,17 @@ typedef struct scsi_inquiry_6_parameter_s {
char product_revision_level[4];
} _PACKED scsi_inquiry_6_parameter;
typedef struct scsi_mode_sense_6_parameter_s {
uint8 data_length;
uint8 medium_type;
uint8 device_specific;
uint8 block_descriptor_length;
uint8 densitiy;
uint8 num_blocks[3];
uint8 reserved;
uint8 block_length[3];
} _PACKED scsi_mode_sense_6_parameter;
typedef struct scsi_read_capacity_10_parameter_s {
uint32 last_logical_block_address;
uint32 logical_block_length;
@@ -87,4 +99,8 @@ typedef enum {
SCSI_SENSE_KEY_ABORTED_COMMAND = 0x0b,
} scsi_sense_key;
// mode sense page code/parameter
#define SCSI_MODE_PAGE_DEVICE_CONFIGURATION 0x10
#define SCSI_DEVICE_SPECIFIC_WRITE_PROTECT 0x80
#endif // _USB_DISK_SCSI_H_