1 /* 2 * Copyright 2008-2010, Haiku Inc. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Lotz <mmlr@mlotz.ch> 7 */ 8 9 #include <ByteOrder.h> 10 #include <KernelExport.h> 11 #include <Drivers.h> 12 #include <malloc.h> 13 #include <stdio.h> 14 #include <string.h> 15 #include "usb_disk.h" 16 #include "usb_disk_scsi.h" 17 18 19 #define DRIVER_NAME "usb_disk" 20 #define DEVICE_NAME_BASE "disk/usb/" 21 #define DEVICE_NAME DEVICE_NAME_BASE"%" B_PRIu32 "/%d/raw" 22 23 24 //#define TRACE_USB_DISK 25 #ifdef TRACE_USB_DISK 26 #define TRACE(x...) dprintf(DRIVER_NAME": "x) 27 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME": "x) 28 #else 29 #define TRACE(x...) /* nothing */ 30 #define TRACE_ALWAYS(x...) dprintf(DRIVER_NAME": "x) 31 #endif 32 33 34 int32 api_version = B_CUR_DRIVER_API_VERSION; 35 static usb_module_info *gUSBModule = NULL; 36 static disk_device *gDeviceList = NULL; 37 static uint32 gDeviceCount = 0; 38 static uint32 gLunCount = 0; 39 static mutex gDeviceListLock; 40 static char **gDeviceNames = NULL; 41 42 static uint8 kDeviceIcon[] = { 43 0x6e, 0x63, 0x69, 0x66, 0x0a, 0x04, 0x01, 0x73, 0x05, 0x01, 0x02, 0x01, 44 0x06, 0x02, 0xb1, 0xf8, 0x5d, 0x3a, 0x2f, 0xbf, 0xbe, 0xdb, 0x67, 0xb6, 45 0x98, 0x06, 0x4b, 0x22, 0x15, 0x47, 0x13, 0x02, 0x00, 0xed, 0xed, 0xed, 46 0xff, 0xab, 0xbc, 0xc6, 0x02, 0x01, 0x06, 0x02, 0xb9, 0x82, 0x56, 0x32, 47 0x7d, 0xfb, 0xb8, 0x06, 0x39, 0xbe, 0xd9, 0xb5, 0x4b, 0x7d, 0x31, 0x4a, 48 0xa4, 0xe7, 0x00, 0xd1, 0xde, 0xe4, 0xff, 0x7a, 0x9c, 0xae, 0x02, 0x00, 49 0x16, 0x02, 0x38, 0xe9, 0xaa, 0x3b, 0x7b, 0x1d, 0xbf, 0xb0, 0xa6, 0x3d, 50 0x16, 0x76, 0x4b, 0x84, 0x81, 0x48, 0x37, 0x36, 0x00, 0x99, 0xff, 0x53, 51 0x02, 0x00, 0x16, 0x02, 0xba, 0x38, 0x9a, 0xb8, 0xef, 0x79, 0x3e, 0x34, 52 0x8b, 0xbf, 0x56, 0x52, 0x48, 0x2c, 0x61, 0x4c, 0x4e, 0xec, 0x00, 0x40, 53 0xff, 0x01, 0x05, 0xff, 0x05, 0x46, 0x02, 0x01, 0x16, 0x02, 0x35, 0xc2, 54 0x71, 0x3a, 0xf6, 0x84, 0xb9, 0xf3, 0x5b, 0x34, 0x81, 0xa0, 0x49, 0xc0, 55 0x57, 0x49, 0x6e, 0x51, 0xff, 0xf3, 0x00, 0x52, 0x02, 0x01, 0x06, 0x02, 56 0x38, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x80, 0x00, 57 0x49, 0xa0, 0x00, 0x49, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0x06, 58 0xe3, 0x06, 0x0c, 0x06, 0x09, 0xab, 0xaa, 0x03, 0x3e, 0x5e, 0x3c, 0x5f, 59 0x3e, 0x5e, 0x60, 0x4d, 0x5a, 0x4a, 0x60, 0x47, 0x56, 0x42, 0x50, 0x45, 60 0x4c, 0x43, 0x2a, 0x54, 0x36, 0x5d, 0x36, 0x5d, 0x3a, 0x60, 0x06, 0x08, 61 0xfb, 0xea, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x37, 0x59, 62 0x37, 0x59, 0x38, 0x5a, 0x3b, 0x59, 0x3a, 0x5a, 0x3b, 0x59, 0x58, 0x3c, 63 0x52, 0x36, 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x06, 0x05, 64 0xab, 0x03, 0x27, 0x49, 0x26, 0x48, 0x27, 0x49, 0x32, 0x56, 0x52, 0x36, 65 0x43, 0x29, 0x27, 0x45, 0x27, 0x45, 0x26, 0x46, 0x0a, 0x05, 0xc2, 0x1c, 66 0xb8, 0xf9, 0x4f, 0x25, 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x51, 0x39, 67 0x0a, 0x04, 0xc5, 0x50, 0xbb, 0xc0, 0xc2, 0x1c, 0xb8, 0xf9, 0x4f, 0x25, 68 0xc9, 0x4c, 0xb7, 0xc4, 0x0a, 0x04, 0x51, 0x39, 0xc5, 0x50, 0xbb, 0xc0, 69 0xc9, 0x4c, 0xb7, 0xc4, 0x5a, 0x30, 0x0a, 0x04, 0x4f, 0x2f, 0x51, 0x31, 70 0x53, 0x2f, 0x51, 0x2d, 0x06, 0x04, 0xee, 0x4f, 0x35, 0x53, 0x30, 0x51, 71 0x32, 0x55, 0x2e, 0x58, 0x2c, 0x54, 0x31, 0x56, 0x2f, 0x52, 0x33, 0x06, 72 0x04, 0xee, 0x31, 0x58, 0x40, 0x47, 0x39, 0x4e, 0x47, 0x40, 0x50, 0x38, 73 0x41, 0x48, 0x48, 0x41, 0x3a, 0x4f, 0x08, 0x02, 0x3a, 0x40, 0x3e, 0x3c, 74 0x02, 0x04, 0x3e, 0x3a, 0xbe, 0x48, 0x3a, 0xbf, 0x9f, 0x3a, 0x41, 0x3d, 75 0x41, 0xbd, 0xe2, 0x41, 0xbf, 0x39, 0x3e, 0x40, 0xbf, 0x9f, 0x40, 0xbe, 76 0x48, 0x40, 0x3b, 0x3d, 0x3b, 0xbf, 0x39, 0x3b, 0xbd, 0xe2, 0x06, 0x05, 77 0xbe, 0x02, 0x32, 0x56, 0x36, 0x5a, 0x36, 0x5a, 0x37, 0x5b, 0x3a, 0x5a, 78 0x39, 0x5b, 0x3a, 0x5a, 0x58, 0x3c, 0x52, 0x36, 0x11, 0x0a, 0x00, 0x01, 79 0x00, 0x00, 0x0a, 0x01, 0x01, 0x03, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 80 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 81 0xc5, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x02, 0x01, 0x04, 0x02, 0x3f, 82 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 83 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x03, 0x01, 0x05, 0x02, 0x3f, 0xe9, 84 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 85 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x01, 0x12, 0x3f, 0xe9, 0x8e, 86 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0xb0, 0x64, 87 0x46, 0x78, 0x3b, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x04, 0x01, 0x02, 88 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 89 0x8e, 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x05, 0x01, 0x0b, 0x02, 90 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 91 0xc6, 0xb0, 0x64, 0x46, 0x78, 0x3b, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 92 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 93 0x5b, 0x2d, 0x45, 0x43, 0x93, 0x0a, 0x01, 0x01, 0x06, 0x02, 0x3f, 0xe9, 94 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc7, 0x7d, 95 0x8b, 0x44, 0x36, 0x9a, 0x0a, 0x06, 0x02, 0x07, 0x08, 0x02, 0x3f, 0xe9, 96 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x4d, 97 0xd9, 0x45, 0xc0, 0xc5, 0x0a, 0x01, 0x01, 0x09, 0x12, 0x3f, 0x6c, 0x5c, 98 0xba, 0xea, 0x46, 0x3a, 0xea, 0x46, 0x3f, 0x6c, 0x5c, 0xc5, 0x19, 0x6c, 99 0x46, 0x6b, 0x36, 0x01, 0x17, 0x8c, 0x22, 0x04, 0x0a, 0x07, 0x01, 0x09, 100 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 101 0x8e, 0xc6, 0x4d, 0xd9, 0x45, 0xc0, 0xc5, 0x01, 0x17, 0x88, 0x22, 0x04, 102 0x0a, 0x08, 0x01, 0x09, 0x12, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 103 0x54, 0xe2, 0x3f, 0xe9, 0x8e, 0xc6, 0x01, 0xed, 0x46, 0x11, 0xa8, 0x01, 104 0x17, 0x85, 0x22, 0x04, 0x0a, 0x01, 0x01, 0x0a, 0x12, 0x3f, 0xe9, 0x8e, 105 0xbb, 0x54, 0xe2, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 0xc6, 0x59, 0xd0, 106 0x46, 0xdb, 0x8c, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 0x06, 0x01, 0x0a, 107 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 0xe2, 0x3f, 0xe9, 108 0x8e, 0xc6, 0x99, 0xc6, 0x45, 0x5e, 0x3a, 0x0a, 0x01, 0x01, 0x0a, 0x12, 109 0x3f, 0x21, 0x43, 0xba, 0xaa, 0x52, 0x3a, 0xaa, 0x52, 0x3f, 0x21, 0x43, 110 0xc7, 0xd2, 0xa7, 0x49, 0x5f, 0xed, 0x01, 0x17, 0x84, 0x00, 0x04, 0x0a, 111 0x09, 0x01, 0x0a, 0x02, 0x3f, 0xe9, 0x8e, 0xbb, 0x54, 0xe2, 0x3b, 0x54, 112 0xe2, 0x3f, 0xe9, 0x8e, 0xc8, 0xa5, 0xc8, 0x48, 0xeb, 0x05 113 }; 114 115 116 // 117 //#pragma mark - Forward Declarations 118 // 119 120 121 static void usb_disk_callback(void *cookie, status_t status, void *data, 122 size_t actualLength); 123 124 status_t usb_disk_mass_storage_reset(disk_device *device); 125 uint8 usb_disk_get_max_lun(disk_device *device); 126 void usb_disk_reset_recovery(disk_device *device); 127 status_t usb_disk_transfer_data(disk_device *device, bool directionIn, 128 void *data, size_t dataLength); 129 status_t usb_disk_receive_csw(disk_device *device, 130 command_status_wrapper *status); 131 status_t usb_disk_operation(device_lun *lun, uint8 operation, 132 uint8 opLength, uint32 logicalBlockAddress, 133 uint16 transferLength, void *data, size_t *dataLength, 134 bool directionIn); 135 136 status_t usb_disk_request_sense(device_lun *lun); 137 status_t usb_disk_mode_sense(device_lun *lun); 138 status_t usb_disk_test_unit_ready(device_lun *lun); 139 status_t usb_disk_inquiry(device_lun *lun); 140 status_t usb_disk_reset_capacity(device_lun *lun); 141 status_t usb_disk_update_capacity(device_lun *lun); 142 status_t usb_disk_synchronize(device_lun *lun, bool force); 143 144 145 // 146 //#pragma mark - Device Allocation Helper Functions 147 // 148 149 150 void 151 usb_disk_free_device_and_luns(disk_device *device) 152 { 153 mutex_lock(&device->lock); 154 mutex_destroy(&device->lock); 155 delete_sem(device->notify); 156 for (uint8 i = 0; i < device->lun_count; i++) 157 free(device->luns[i]); 158 free(device->luns); 159 free(device); 160 } 161 162 163 // 164 //#pragma mark - Bulk-only Mass Storage Functions 165 // 166 167 168 status_t 169 usb_disk_mass_storage_reset(disk_device *device) 170 { 171 return gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_OUT 172 | USB_REQTYPE_CLASS, REQUEST_MASS_STORAGE_RESET, 0x0000, 173 device->interface, 0, NULL, NULL); 174 } 175 176 177 uint8 178 usb_disk_get_max_lun(disk_device *device) 179 { 180 uint8 result = 0; 181 size_t actualLength = 0; 182 183 // devices that do not support multiple LUNs may stall this request 184 if (gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_IN 185 | USB_REQTYPE_CLASS, REQUEST_GET_MAX_LUN, 0x0000, device->interface, 186 1, &result, &actualLength) != B_OK || actualLength != 1) 187 return 0; 188 189 if (result > MAX_LOGICAL_UNIT_NUMBER) { 190 // invalid max lun 191 return 0; 192 } 193 194 return result; 195 } 196 197 198 void 199 usb_disk_reset_recovery(disk_device *device) 200 { 201 usb_disk_mass_storage_reset(device); 202 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 203 gUSBModule->clear_feature(device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 204 } 205 206 207 status_t 208 usb_disk_transfer_data(disk_device *device, bool directionIn, void *data, 209 size_t dataLength) 210 { 211 status_t result = gUSBModule->queue_bulk(directionIn ? device->bulk_in 212 : device->bulk_out, data, dataLength, usb_disk_callback, device); 213 if (result != B_OK) { 214 TRACE_ALWAYS("failed to queue data transfer\n"); 215 return result; 216 } 217 218 do { 219 result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 220 10 * 1000 * 1000); 221 if (result == B_TIMED_OUT) { 222 // Cancel the transfer and collect the sem that should now be 223 // released through the callback on cancel. Handling of device 224 // reset is done in usb_disk_operation() when it detects that 225 // the transfer failed. 226 gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in 227 : device->bulk_out); 228 acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0); 229 } 230 } while (result == B_INTERRUPTED); 231 232 if (result != B_OK) { 233 TRACE_ALWAYS("acquire_sem failed while waiting for data transfer\n"); 234 return result; 235 } 236 237 return B_OK; 238 } 239 240 241 status_t 242 usb_disk_receive_csw(disk_device *device, command_status_wrapper *status) 243 { 244 status_t result = usb_disk_transfer_data(device, true, status, 245 sizeof(command_status_wrapper)); 246 if (result != B_OK) 247 return result; 248 249 if (device->status != B_OK 250 || device->actual_length != sizeof(command_status_wrapper)) { 251 // receiving the command status wrapper failed 252 return B_ERROR; 253 } 254 255 return B_OK; 256 } 257 258 259 status_t 260 usb_disk_operation(device_lun *lun, uint8 operation, uint8 opLength, 261 uint32 logicalBlockAddress, uint16 transferLength, void *data, 262 size_t *dataLength, bool directionIn) 263 { 264 TRACE("operation: lun: %u; op: %u; oplen: %u; lba: %lu; tlen: %u; data: " 265 "%p; dlen: %p (%lu); in: %c\n", 266 lun->logical_unit_number, operation, opLength, logicalBlockAddress, 267 transferLength, data, dataLength, dataLength ? *dataLength : 0, 268 directionIn ? 'y' : 'n'); 269 270 disk_device *device = lun->device; 271 command_block_wrapper command; 272 command.signature = CBW_SIGNATURE; 273 command.tag = device->current_tag++; 274 command.data_transfer_length = (dataLength != NULL ? *dataLength : 0); 275 command.flags = (directionIn ? CBW_DATA_INPUT : CBW_DATA_OUTPUT); 276 command.lun = lun->logical_unit_number; 277 command.command_block_length 278 = device->is_atapi ? ATAPI_COMMAND_LENGTH : opLength; 279 memset(command.command_block, 0, sizeof(command.command_block)); 280 281 switch (opLength) { 282 case 6: 283 { 284 scsi_command_6 *commandBlock 285 = (scsi_command_6 *)command.command_block; 286 commandBlock->operation = operation; 287 commandBlock->lun = lun->logical_unit_number << 5; 288 commandBlock->allocation_length = (uint8)transferLength; 289 if (operation == SCSI_MODE_SENSE_6) { 290 // we hijack the lba argument to transport the desired page 291 commandBlock->reserved[1] = (uint8)logicalBlockAddress; 292 } 293 break; 294 } 295 296 case 10: 297 { 298 scsi_command_10 *commandBlock 299 = (scsi_command_10 *)command.command_block; 300 commandBlock->operation = operation; 301 commandBlock->lun_flags = lun->logical_unit_number << 5; 302 commandBlock->logical_block_address = htonl(logicalBlockAddress); 303 commandBlock->transfer_length = htons(transferLength); 304 break; 305 } 306 307 default: 308 TRACE_ALWAYS("unsupported operation length %d\n", opLength); 309 return B_BAD_VALUE; 310 } 311 312 status_t result = usb_disk_transfer_data(device, false, &command, 313 sizeof(command_block_wrapper)); 314 if (result != B_OK) 315 return result; 316 317 if (device->status != B_OK || 318 device->actual_length != sizeof(command_block_wrapper)) { 319 // sending the command block wrapper failed 320 TRACE_ALWAYS("sending the command block wrapper failed\n"); 321 usb_disk_reset_recovery(device); 322 return B_ERROR; 323 } 324 325 size_t transferedData = 0; 326 if (data != NULL && dataLength != NULL && *dataLength > 0) { 327 // we have data to transfer in a data stage 328 result = usb_disk_transfer_data(device, directionIn, data, 329 *dataLength); 330 if (result != B_OK) 331 return result; 332 333 transferedData = device->actual_length; 334 if (device->status != B_OK || transferedData != *dataLength) { 335 // sending or receiving of the data failed 336 if (device->status == B_DEV_STALLED) { 337 TRACE("stall while transfering data\n"); 338 gUSBModule->clear_feature(directionIn ? device->bulk_in 339 : device->bulk_out, USB_FEATURE_ENDPOINT_HALT); 340 } else { 341 TRACE_ALWAYS("sending or receiving of the data failed\n"); 342 usb_disk_reset_recovery(device); 343 return B_ERROR; 344 } 345 } 346 } 347 348 command_status_wrapper status; 349 result = usb_disk_receive_csw(device, &status); 350 if (result != B_OK) { 351 // in case of a stall or error clear the stall and try again 352 gUSBModule->clear_feature(device->bulk_in, USB_FEATURE_ENDPOINT_HALT); 353 result = usb_disk_receive_csw(device, &status); 354 } 355 356 if (result != B_OK) { 357 TRACE_ALWAYS("receiving the command status wrapper failed\n"); 358 usb_disk_reset_recovery(device); 359 return result; 360 } 361 362 if (status.signature != CSW_SIGNATURE || status.tag != command.tag) { 363 // the command status wrapper is not valid 364 TRACE_ALWAYS("command status wrapper is not valid\n"); 365 usb_disk_reset_recovery(device); 366 return B_ERROR; 367 } 368 369 switch (status.status) { 370 case CSW_STATUS_COMMAND_PASSED: 371 case CSW_STATUS_COMMAND_FAILED: 372 { 373 // The residue from "status.data_residue" is not maintained 374 // correctly by some devices, so calculate it instead. 375 uint32 residue = command.data_transfer_length - transferedData; 376 377 if (dataLength != NULL) { 378 *dataLength -= residue; 379 if (transferedData < *dataLength) { 380 TRACE_ALWAYS("less data transfered than indicated\n"); 381 *dataLength = transferedData; 382 } 383 } 384 385 if (status.status == CSW_STATUS_COMMAND_PASSED) { 386 // the operation is complete and has succeeded 387 return B_OK; 388 } else { 389 if (operation == SCSI_REQUEST_SENSE_6) 390 return B_ERROR; 391 392 // the operation is complete but has failed at the SCSI level 393 if (operation != SCSI_TEST_UNIT_READY_6) { 394 TRACE_ALWAYS("operation 0x%02x failed at the SCSI level\n", 395 operation); 396 } 397 398 result = usb_disk_request_sense(lun); 399 return result == B_OK ? B_ERROR : result; 400 } 401 } 402 403 case CSW_STATUS_PHASE_ERROR: 404 { 405 // a protocol or device error occured 406 TRACE_ALWAYS("phase error in operation 0x%02x\n", operation); 407 usb_disk_reset_recovery(device); 408 return B_ERROR; 409 } 410 411 default: 412 { 413 // command status wrapper is not meaningful 414 TRACE_ALWAYS("command status wrapper has invalid status\n"); 415 usb_disk_reset_recovery(device); 416 return B_ERROR; 417 } 418 } 419 } 420 421 422 // 423 //#pragma mark - Helper/Convenience Functions 424 // 425 426 427 status_t 428 usb_disk_request_sense(device_lun *lun) 429 { 430 size_t dataLength = sizeof(scsi_request_sense_6_parameter); 431 scsi_request_sense_6_parameter parameter; 432 status_t result = usb_disk_operation(lun, SCSI_REQUEST_SENSE_6, 6, 0, 433 dataLength, ¶meter, &dataLength, true); 434 if (result != B_OK) { 435 TRACE_ALWAYS("getting request sense data failed\n"); 436 return result; 437 } 438 439 if (parameter.sense_key > SCSI_SENSE_KEY_NOT_READY 440 && parameter.sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) { 441 TRACE_ALWAYS("request_sense: key: 0x%02x; asc: 0x%02x; ascq: " 442 "0x%02x;\n", parameter.sense_key, parameter.additional_sense_code, 443 parameter.additional_sense_code_qualifier); 444 } 445 446 switch (parameter.sense_key) { 447 case SCSI_SENSE_KEY_NO_SENSE: 448 case SCSI_SENSE_KEY_RECOVERED_ERROR: 449 return B_OK; 450 451 case SCSI_SENSE_KEY_HARDWARE_ERROR: 452 case SCSI_SENSE_KEY_MEDIUM_ERROR: 453 TRACE_ALWAYS("request_sense: media or hardware error\n"); 454 return B_DEV_UNREADABLE; 455 456 case SCSI_SENSE_KEY_ILLEGAL_REQUEST: 457 TRACE_ALWAYS("request_sense: illegal request\n"); 458 return B_DEV_INVALID_IOCTL; 459 460 case SCSI_SENSE_KEY_UNIT_ATTENTION: 461 if (parameter.additional_sense_code 462 != SCSI_ASC_MEDIUM_NOT_PRESENT) { 463 TRACE_ALWAYS("request_sense: media changed\n"); 464 lun->media_changed = true; 465 lun->media_present = true; 466 467 return B_DEV_MEDIA_CHANGED; 468 } 469 // fall through 470 471 case SCSI_SENSE_KEY_NOT_READY: 472 TRACE("request_sense: device not ready (asc 0x%02x ascq 0x%02x)\n", 473 parameter.additional_sense_code, 474 parameter.additional_sense_code_qualifier); 475 lun->media_present = false; 476 usb_disk_reset_capacity(lun); 477 return B_DEV_NO_MEDIA; 478 479 case SCSI_SENSE_KEY_DATA_PROTECT: 480 TRACE_ALWAYS("request_sense: write protected\n"); 481 return B_READ_ONLY_DEVICE; 482 483 case SCSI_SENSE_KEY_ABORTED_COMMAND: 484 TRACE_ALWAYS("request_sense: command aborted\n"); 485 return B_CANCELED; 486 } 487 488 return B_ERROR; 489 } 490 491 492 status_t 493 usb_disk_mode_sense(device_lun *lun) 494 { 495 size_t dataLength = sizeof(scsi_mode_sense_6_parameter); 496 scsi_mode_sense_6_parameter parameter; 497 status_t result = usb_disk_operation(lun, SCSI_MODE_SENSE_6, 6, 498 SCSI_MODE_PAGE_DEVICE_CONFIGURATION, dataLength, ¶meter, 499 &dataLength, true); 500 if (result != B_OK) { 501 TRACE_ALWAYS("getting mode sense data failed\n"); 502 return result; 503 } 504 505 lun->write_protected 506 = (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT) 507 != 0; 508 TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no"); 509 return B_OK; 510 } 511 512 513 status_t 514 usb_disk_test_unit_ready(device_lun *lun) 515 { 516 // if unsupported we assume the unit is fixed and therefore always ok 517 if (!lun->device->tur_supported) 518 return B_OK; 519 520 status_t result; 521 if (lun->device->is_atapi) { 522 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 1, 523 NULL, NULL, false); 524 } else { 525 result = usb_disk_operation(lun, SCSI_TEST_UNIT_READY_6, 6, 0, 0, 526 NULL, NULL, true); 527 } 528 529 if (result == B_DEV_INVALID_IOCTL) { 530 lun->device->tur_supported = false; 531 return B_OK; 532 } 533 534 return result; 535 } 536 537 538 status_t 539 usb_disk_inquiry(device_lun *lun) 540 { 541 size_t dataLength = sizeof(scsi_inquiry_6_parameter); 542 scsi_inquiry_6_parameter parameter; 543 status_t result = B_ERROR; 544 for (uint32 tries = 0; tries < 3; tries++) { 545 result = usb_disk_operation(lun, SCSI_INQUIRY_6, 6, 0, dataLength, 546 ¶meter, &dataLength, true); 547 if (result == B_OK) 548 break; 549 } 550 if (result != B_OK) { 551 TRACE_ALWAYS("getting inquiry data failed\n"); 552 lun->device_type = B_DISK; 553 lun->removable = true; 554 return result; 555 } 556 557 TRACE("peripherial_device_type 0x%02x\n", 558 parameter.peripherial_device_type); 559 TRACE("peripherial_qualifier 0x%02x\n", 560 parameter.peripherial_qualifier); 561 TRACE("removable_medium %s\n", 562 parameter.removable_medium ? "yes" : "no"); 563 TRACE("version 0x%02x\n", parameter.version); 564 TRACE("response_data_format 0x%02x\n", parameter.response_data_format); 565 TRACE_ALWAYS("vendor_identification \"%.8s\"\n", 566 parameter.vendor_identification); 567 TRACE_ALWAYS("product_identification \"%.16s\"\n", 568 parameter.product_identification); 569 TRACE_ALWAYS("product_revision_level \"%.4s\"\n", 570 parameter.product_revision_level); 571 lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */ 572 lun->removable = (parameter.removable_medium == 1); 573 return B_OK; 574 } 575 576 577 status_t 578 usb_disk_reset_capacity(device_lun *lun) 579 { 580 lun->block_size = 512; 581 lun->block_count = 0; 582 return B_OK; 583 } 584 585 586 status_t 587 usb_disk_update_capacity(device_lun *lun) 588 { 589 size_t dataLength = sizeof(scsi_read_capacity_10_parameter); 590 scsi_read_capacity_10_parameter parameter; 591 status_t result = B_ERROR; 592 593 // Retry reading the capacity up to three times. The first try might only 594 // yield a unit attention telling us that the device or media status 595 // changed, which is more or less expected if it is the first operation 596 // on the device or the device only clears the unit atention for capacity 597 // reads. 598 for (int32 i = 0; i < 3; i++) { 599 result = usb_disk_operation(lun, SCSI_READ_CAPACITY_10, 10, 0, 0, 600 ¶meter, &dataLength, true); 601 if (result == B_OK) 602 break; 603 } 604 605 if (result != B_OK) { 606 TRACE_ALWAYS("failed to update capacity\n"); 607 lun->media_present = false; 608 lun->media_changed = false; 609 usb_disk_reset_capacity(lun); 610 return result; 611 } 612 613 lun->media_present = true; 614 lun->media_changed = false; 615 lun->block_size = ntohl(parameter.logical_block_length); 616 lun->block_count = ntohl(parameter.last_logical_block_address) + 1; 617 return B_OK; 618 } 619 620 621 status_t 622 usb_disk_synchronize(device_lun *lun, bool force) 623 { 624 if (lun->device->sync_support == 0) { 625 // this device reported an illegal request when syncing or repeatedly 626 // returned an other error, it apparently does not support syncing... 627 return B_UNSUPPORTED; 628 } 629 630 if (!lun->should_sync && !force) 631 return B_OK; 632 633 status_t result = usb_disk_operation(lun, SCSI_SYNCHRONIZE_CACHE_10, 10, 634 0, 0, NULL, NULL, false); 635 636 if (result == B_OK) { 637 lun->device->sync_support = SYNC_SUPPORT_RELOAD; 638 lun->should_sync = false; 639 return B_OK; 640 } 641 642 if (result == B_DEV_INVALID_IOCTL) 643 lun->device->sync_support = 0; 644 else 645 lun->device->sync_support--; 646 647 return result; 648 } 649 650 651 // 652 //#pragma mark - Device Attach/Detach Notifications and Callback 653 // 654 655 656 static void 657 usb_disk_callback(void *cookie, status_t status, void *data, 658 size_t actualLength) 659 { 660 //TRACE("callback()\n"); 661 disk_device *device = (disk_device *)cookie; 662 device->status = status; 663 device->actual_length = actualLength; 664 release_sem(device->notify); 665 } 666 667 668 static status_t 669 usb_disk_device_added(usb_device newDevice, void **cookie) 670 { 671 TRACE("device_added(0x%08lx)\n", newDevice); 672 disk_device *device = (disk_device *)malloc(sizeof(disk_device)); 673 device->device = newDevice; 674 device->removed = false; 675 device->open_count = 0; 676 device->interface = 0xff; 677 device->current_tag = 0; 678 device->sync_support = SYNC_SUPPORT_RELOAD; 679 device->tur_supported = true; 680 device->is_atapi = false; 681 device->luns = NULL; 682 683 // scan through the interfaces to find our bulk-only data interface 684 const usb_configuration_info *configuration 685 = gUSBModule->get_configuration(newDevice); 686 if (configuration == NULL) { 687 free(device); 688 return B_ERROR; 689 } 690 691 for (size_t i = 0; i < configuration->interface_count; i++) { 692 usb_interface_info *interface = configuration->interface[i].active; 693 if (interface == NULL) 694 continue; 695 696 if (interface->descr->interface_class == 0x08 /* mass storage */ 697 && (interface->descr->interface_subclass == 0x06 /* SCSI */ 698 || interface->descr->interface_subclass == 0x02 /* ATAPI */ 699 || interface->descr->interface_subclass == 0x05 /* ATAPI */) 700 && interface->descr->interface_protocol == 0x50 /* bulk-only */) { 701 702 bool hasIn = false; 703 bool hasOut = false; 704 for (size_t j = 0; j < interface->endpoint_count; j++) { 705 usb_endpoint_info *endpoint = &interface->endpoint[j]; 706 if (endpoint == NULL 707 || endpoint->descr->attributes != USB_ENDPOINT_ATTR_BULK) 708 continue; 709 710 if (!hasIn && (endpoint->descr->endpoint_address 711 & USB_ENDPOINT_ADDR_DIR_IN) != 0) { 712 device->bulk_in = endpoint->handle; 713 hasIn = true; 714 } else if (!hasOut && (endpoint->descr->endpoint_address 715 & USB_ENDPOINT_ADDR_DIR_IN) == 0) { 716 device->bulk_out = endpoint->handle; 717 hasOut = true; 718 } 719 720 if (hasIn && hasOut) 721 break; 722 } 723 724 if (!(hasIn && hasOut)) 725 continue; 726 727 device->interface = interface->descr->interface_number; 728 device->is_atapi = interface->descr->interface_subclass != 0x06; 729 break; 730 } 731 } 732 733 if (device->interface == 0xff) { 734 TRACE_ALWAYS("no valid bulk-only interface found\n"); 735 free(device); 736 return B_ERROR; 737 } 738 739 mutex_init(&device->lock, "usb_disk device lock"); 740 741 device->notify = create_sem(0, "usb_disk callback notify"); 742 if (device->notify < B_OK) { 743 mutex_destroy(&device->lock); 744 status_t result = device->notify; 745 free(device); 746 return result; 747 } 748 749 device->lun_count = usb_disk_get_max_lun(device) + 1; 750 device->luns = (device_lun **)malloc(device->lun_count 751 * sizeof(device_lun *)); 752 for (uint8 i = 0; i < device->lun_count; i++) 753 device->luns[i] = NULL; 754 755 status_t result = B_OK; 756 757 TRACE_ALWAYS("device reports a lun count of %d\n", device->lun_count); 758 for (uint8 i = 0; i < device->lun_count; i++) { 759 // create the individual luns present on this device 760 device_lun *lun = (device_lun *)malloc(sizeof(device_lun)); 761 if (lun == NULL) { 762 result = B_NO_MEMORY; 763 break; 764 } 765 766 device->luns[i] = lun; 767 lun->device = device; 768 lun->logical_unit_number = i; 769 lun->should_sync = false; 770 lun->media_present = true; 771 lun->media_changed = true; 772 usb_disk_reset_capacity(lun); 773 774 // initialize this lun 775 result = usb_disk_inquiry(lun); 776 for (uint32 tries = 0; tries < 8; tries++) { 777 TRACE("usb lun %"B_PRIu8" inquiry attempt %"B_PRIu32" begin\n", 778 i, tries); 779 status_t ready = usb_disk_test_unit_ready(lun); 780 if (ready == B_OK || ready == B_DEV_NO_MEDIA) { 781 if (lun->device_type == B_CD) 782 lun->write_protected = true; 783 // TODO: check for write protection; disabled since some 784 // devices lock up when getting the mode sense 785 else if (/*usb_disk_mode_sense(lun) != B_OK*/true) 786 lun->write_protected = false; 787 788 TRACE("usb lun %"B_PRIu8" ready. write protected = %c%s\n", i, 789 lun->write_protected ? 'y' : 'n', 790 ready == B_DEV_NO_MEDIA ? " (no media inserted)" : ""); 791 792 break; 793 } 794 TRACE("usb lun %"B_PRIu8" inquiry attempt %"B_PRIu32" failed\n", 795 i, tries); 796 797 bigtime_t snoozeTime = 1000000 * tries; 798 TRACE("snoozing %"B_PRIu64" microseconds for usb lun\n", 799 snoozeTime); 800 snooze(snoozeTime); 801 } 802 803 if (result != B_OK) 804 break; 805 } 806 807 if (result != B_OK) { 808 TRACE_ALWAYS("failed to initialize logical units\n"); 809 usb_disk_free_device_and_luns(device); 810 return result; 811 } 812 813 mutex_lock(&gDeviceListLock); 814 device->device_number = 0; 815 disk_device *other = gDeviceList; 816 while (other != NULL) { 817 if (other->device_number >= device->device_number) 818 device->device_number = other->device_number + 1; 819 820 other = (disk_device *)other->link; 821 } 822 823 device->link = (void *)gDeviceList; 824 gDeviceList = device; 825 gLunCount += device->lun_count; 826 for (uint8 i = 0; i < device->lun_count; i++) 827 sprintf(device->luns[i]->name, DEVICE_NAME, device->device_number, i); 828 mutex_unlock(&gDeviceListLock); 829 830 TRACE("new device: 0x%08lx\n", (uint32)device); 831 *cookie = (void *)device; 832 return B_OK; 833 } 834 835 836 static status_t 837 usb_disk_device_removed(void *cookie) 838 { 839 TRACE("device_removed(0x%08lx)\n", (uint32)cookie); 840 disk_device *device = (disk_device *)cookie; 841 842 mutex_lock(&gDeviceListLock); 843 if (gDeviceList == device) { 844 gDeviceList = (disk_device *)device->link; 845 } else { 846 disk_device *element = gDeviceList; 847 while (element) { 848 if (element->link == device) { 849 element->link = device->link; 850 break; 851 } 852 853 element = (disk_device *)element->link; 854 } 855 } 856 gLunCount -= device->lun_count; 857 gDeviceCount--; 858 859 device->removed = true; 860 gUSBModule->cancel_queued_transfers(device->bulk_in); 861 gUSBModule->cancel_queued_transfers(device->bulk_out); 862 if (device->open_count == 0) 863 usb_disk_free_device_and_luns(device); 864 865 mutex_unlock(&gDeviceListLock); 866 return B_OK; 867 } 868 869 870 // 871 //#pragma mark - Partial Buffer Functions 872 // 873 874 875 static bool 876 usb_disk_needs_partial_buffer(device_lun *lun, off_t position, size_t length, 877 uint32 &blockPosition, uint16 &blockCount) 878 { 879 blockPosition = (uint32)(position / lun->block_size); 880 if ((off_t)blockPosition * lun->block_size != position) 881 return true; 882 883 blockCount = (uint16)(length / lun->block_size); 884 if ((size_t)blockCount * lun->block_size != length) 885 return true; 886 887 return false; 888 } 889 890 891 static status_t 892 usb_disk_block_read(device_lun *lun, uint32 blockPosition, uint16 blockCount, 893 void *buffer, size_t *length) 894 { 895 status_t result = usb_disk_operation(lun, SCSI_READ_10, 10, blockPosition, 896 blockCount, buffer, length, true); 897 return result; 898 } 899 900 901 static status_t 902 usb_disk_block_write(device_lun *lun, uint32 blockPosition, uint16 blockCount, 903 void *buffer, size_t *length) 904 { 905 status_t result = usb_disk_operation(lun, SCSI_WRITE_10, 10, blockPosition, 906 blockCount, buffer, length, false); 907 if (result == B_OK) 908 lun->should_sync = true; 909 return result; 910 } 911 912 913 static status_t 914 usb_disk_prepare_partial_buffer(device_lun *lun, off_t position, size_t length, 915 void *&partialBuffer, void *&blockBuffer, uint32 &blockPosition, 916 uint16 &blockCount) 917 { 918 blockPosition = (uint32)(position / lun->block_size); 919 blockCount = (uint16)((uint32)((position + length + lun->block_size - 1) 920 / lun->block_size) - blockPosition); 921 size_t blockLength = blockCount * lun->block_size; 922 blockBuffer = malloc(blockLength); 923 if (blockBuffer == NULL) { 924 TRACE_ALWAYS("no memory to allocate partial buffer\n"); 925 return B_NO_MEMORY; 926 } 927 928 status_t result = usb_disk_block_read(lun, blockPosition, blockCount, 929 blockBuffer, &blockLength); 930 if (result != B_OK) { 931 TRACE_ALWAYS("block read failed when filling partial buffer\n"); 932 free(blockBuffer); 933 return result; 934 } 935 936 off_t offset = position - (blockPosition * lun->block_size); 937 partialBuffer = (uint8 *)blockBuffer + offset; 938 return B_OK; 939 } 940 941 942 // 943 //#pragma mark - Driver Hooks 944 // 945 946 947 static status_t 948 usb_disk_open(const char *name, uint32 flags, void **cookie) 949 { 950 TRACE("open(%s)\n", name); 951 if (strncmp(name, DEVICE_NAME_BASE, strlen(DEVICE_NAME_BASE)) != 0) 952 return B_NAME_NOT_FOUND; 953 954 int32 lastPart = 0; 955 size_t nameLength = strlen(name); 956 for (int32 i = nameLength - 1; i >= 0; i--) { 957 if (name[i] == '/') { 958 lastPart = i; 959 break; 960 } 961 } 962 963 char rawName[nameLength + 4]; 964 strncpy(rawName, name, lastPart + 1); 965 rawName[lastPart + 1] = 0; 966 strcat(rawName, "raw"); 967 TRACE("opening raw device %s for %s\n", rawName, name); 968 969 mutex_lock(&gDeviceListLock); 970 disk_device *device = gDeviceList; 971 while (device) { 972 for (uint8 i = 0; i < device->lun_count; i++) { 973 device_lun *lun = device->luns[i]; 974 if (strncmp(rawName, lun->name, 32) == 0) { 975 // found the matching device/lun 976 if (device->removed) { 977 mutex_unlock(&gDeviceListLock); 978 return B_ERROR; 979 } 980 981 device->open_count++; 982 *cookie = lun; 983 mutex_unlock(&gDeviceListLock); 984 return B_OK; 985 } 986 } 987 988 device = (disk_device *)device->link; 989 } 990 991 mutex_unlock(&gDeviceListLock); 992 return B_NAME_NOT_FOUND; 993 } 994 995 996 static status_t 997 usb_disk_close(void *cookie) 998 { 999 TRACE("close()\n"); 1000 device_lun *lun = (device_lun *)cookie; 1001 disk_device *device = lun->device; 1002 1003 mutex_lock(&device->lock); 1004 if (!device->removed) 1005 usb_disk_synchronize(lun, false); 1006 mutex_unlock(&device->lock); 1007 1008 return B_OK; 1009 } 1010 1011 1012 static status_t 1013 usb_disk_free(void *cookie) 1014 { 1015 TRACE("free()\n"); 1016 mutex_lock(&gDeviceListLock); 1017 1018 device_lun *lun = (device_lun *)cookie; 1019 disk_device *device = lun->device; 1020 device->open_count--; 1021 if (device->open_count == 0 && device->removed) { 1022 // we can simply free the device here as it has been removed from 1023 // the device list in the device removed notification hook 1024 usb_disk_free_device_and_luns(device); 1025 } 1026 1027 mutex_unlock(&gDeviceListLock); 1028 return B_OK; 1029 } 1030 1031 1032 static status_t 1033 usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length) 1034 { 1035 device_lun *lun = (device_lun *)cookie; 1036 disk_device *device = lun->device; 1037 mutex_lock(&device->lock); 1038 if (device->removed) { 1039 mutex_unlock(&device->lock); 1040 return B_DEV_NOT_READY; 1041 } 1042 1043 status_t result = B_DEV_INVALID_IOCTL; 1044 switch (op) { 1045 case B_GET_MEDIA_STATUS: 1046 { 1047 *(status_t *)buffer = usb_disk_test_unit_ready(lun); 1048 TRACE("B_GET_MEDIA_STATUS: 0x%08lx\n", *(status_t *)buffer); 1049 result = B_OK; 1050 break; 1051 } 1052 1053 case B_GET_GEOMETRY: 1054 { 1055 if (lun->media_changed) { 1056 result = usb_disk_update_capacity(lun); 1057 if (result != B_OK) 1058 break; 1059 } 1060 1061 device_geometry *geometry = (device_geometry *)buffer; 1062 geometry->bytes_per_sector = lun->block_size; 1063 geometry->cylinder_count = lun->block_count; 1064 geometry->sectors_per_track = geometry->head_count = 1; 1065 geometry->device_type = lun->device_type; 1066 geometry->removable = lun->removable; 1067 geometry->read_only = lun->write_protected; 1068 geometry->write_once = (lun->device_type == B_WORM); 1069 TRACE("B_GET_GEOMETRY: %ld sectors at %ld bytes per sector\n", 1070 geometry->cylinder_count, geometry->bytes_per_sector); 1071 result = B_OK; 1072 break; 1073 } 1074 1075 case B_FLUSH_DRIVE_CACHE: 1076 TRACE("B_FLUSH_DRIVE_CACHE\n"); 1077 result = usb_disk_synchronize(lun, true); 1078 break; 1079 1080 case B_EJECT_DEVICE: 1081 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 2, 1082 NULL, NULL, false); 1083 break; 1084 1085 case B_LOAD_MEDIA: 1086 result = usb_disk_operation(lun, SCSI_START_STOP_UNIT_6, 6, 0, 3, 1087 NULL, NULL, false); 1088 break; 1089 1090 #if HAIKU_TARGET_PLATFORM_HAIKU 1091 case B_GET_ICON: 1092 // We don't support this legacy ioctl anymore, but the two other 1093 // icon ioctls below instead. 1094 break; 1095 1096 case B_GET_ICON_NAME: 1097 result = user_strlcpy((char *)buffer, 1098 "devices/drive-removable-media-usb", B_FILE_NAME_LENGTH); 1099 break; 1100 1101 case B_GET_VECTOR_ICON: 1102 { 1103 if (length != sizeof(device_icon)) { 1104 result = B_BAD_VALUE; 1105 break; 1106 } 1107 1108 device_icon iconData; 1109 if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK) { 1110 result = B_BAD_ADDRESS; 1111 break; 1112 } 1113 1114 if (iconData.icon_size >= (int32)sizeof(kDeviceIcon)) { 1115 if (user_memcpy(iconData.icon_data, kDeviceIcon, 1116 sizeof(kDeviceIcon)) != B_OK) { 1117 result = B_BAD_ADDRESS; 1118 break; 1119 } 1120 } 1121 1122 iconData.icon_size = sizeof(kDeviceIcon); 1123 result = user_memcpy(buffer, &iconData, sizeof(device_icon)); 1124 break; 1125 } 1126 #endif 1127 1128 default: 1129 TRACE_ALWAYS("unhandled ioctl %" B_PRId32 "\n", op); 1130 break; 1131 } 1132 1133 mutex_unlock(&device->lock); 1134 return result; 1135 } 1136 1137 1138 static status_t 1139 usb_disk_read(void *cookie, off_t position, void *buffer, size_t *length) 1140 { 1141 if (buffer == NULL || length == NULL) 1142 return B_BAD_VALUE; 1143 1144 TRACE("read(%lld, %ld)\n", position, *length); 1145 device_lun *lun = (device_lun *)cookie; 1146 disk_device *device = lun->device; 1147 mutex_lock(&device->lock); 1148 if (device->removed) { 1149 *length = 0; 1150 mutex_unlock(&device->lock); 1151 return B_DEV_NOT_READY; 1152 } 1153 1154 status_t result = B_ERROR; 1155 uint32 blockPosition = 0; 1156 uint16 blockCount = 0; 1157 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, *length, 1158 blockPosition, blockCount); 1159 if (needsPartial) { 1160 void *partialBuffer = NULL; 1161 void *blockBuffer = NULL; 1162 result = usb_disk_prepare_partial_buffer(lun, position, *length, 1163 partialBuffer, blockBuffer, blockPosition, blockCount); 1164 if (result == B_OK) { 1165 memcpy(buffer, partialBuffer, *length); 1166 free(blockBuffer); 1167 } 1168 } else { 1169 result = usb_disk_block_read(lun, blockPosition, blockCount, buffer, 1170 length); 1171 } 1172 1173 mutex_unlock(&device->lock); 1174 if (result == B_OK) { 1175 TRACE("read successful with %ld bytes\n", *length); 1176 return B_OK; 1177 } 1178 1179 *length = 0; 1180 TRACE_ALWAYS("read fails with 0x%08" B_PRIx32 "\n", result); 1181 return result; 1182 } 1183 1184 1185 static status_t 1186 usb_disk_write(void *cookie, off_t position, const void *buffer, 1187 size_t *length) 1188 { 1189 if (buffer == NULL || length == NULL) 1190 return B_BAD_VALUE; 1191 1192 TRACE("write(%lld, %ld)\n", position, *length); 1193 device_lun *lun = (device_lun *)cookie; 1194 disk_device *device = lun->device; 1195 mutex_lock(&device->lock); 1196 if (device->removed) { 1197 *length = 0; 1198 mutex_unlock(&device->lock); 1199 return B_DEV_NOT_READY; 1200 } 1201 1202 status_t result = B_ERROR; 1203 uint32 blockPosition = 0; 1204 uint16 blockCount = 0; 1205 bool needsPartial = usb_disk_needs_partial_buffer(lun, position, 1206 *length, blockPosition, blockCount); 1207 if (needsPartial) { 1208 void *partialBuffer = NULL; 1209 void *blockBuffer = NULL; 1210 result = usb_disk_prepare_partial_buffer(lun, position, *length, 1211 partialBuffer, blockBuffer, blockPosition, blockCount); 1212 if (result == B_OK) { 1213 memcpy(partialBuffer, buffer, *length); 1214 size_t blockLength = blockCount * lun->block_size; 1215 result = usb_disk_block_write(lun, blockPosition, blockCount, 1216 blockBuffer, &blockLength); 1217 free(blockBuffer); 1218 } 1219 } else { 1220 result = usb_disk_block_write(lun, blockPosition, blockCount, 1221 (void *)buffer, length); 1222 } 1223 1224 mutex_unlock(&device->lock); 1225 if (result == B_OK) { 1226 TRACE("write successful with %ld bytes\n", *length); 1227 return B_OK; 1228 } 1229 1230 *length = 0; 1231 TRACE_ALWAYS("write fails with 0x%08" B_PRIx32 "\n", result); 1232 return result; 1233 } 1234 1235 1236 // 1237 //#pragma mark - Driver Entry Points 1238 // 1239 1240 1241 status_t 1242 init_hardware() 1243 { 1244 TRACE("init_hardware()\n"); 1245 return B_OK; 1246 } 1247 1248 1249 status_t 1250 init_driver() 1251 { 1252 TRACE("init_driver()\n"); 1253 static usb_notify_hooks notifyHooks = { 1254 &usb_disk_device_added, 1255 &usb_disk_device_removed 1256 }; 1257 1258 static usb_support_descriptor supportedDevices[] = { 1259 { 0x08 /* mass storage */, 0x06 /* SCSI */, 0x50 /* bulk */, 0, 0 }, 1260 { 0x08 /* mass storage */, 0x02 /* ATAPI */, 0x50 /* bulk */, 0, 0 }, 1261 { 0x08 /* mass storage */, 0x05 /* ATAPI */, 0x50 /* bulk */, 0, 0 } 1262 }; 1263 1264 gDeviceList = NULL; 1265 gDeviceCount = 0; 1266 gLunCount = 0; 1267 mutex_init(&gDeviceListLock, "usb_disk device list lock"); 1268 1269 TRACE("trying module %s\n", B_USB_MODULE_NAME); 1270 status_t result = get_module(B_USB_MODULE_NAME, 1271 (module_info **)&gUSBModule); 1272 if (result < B_OK) { 1273 TRACE_ALWAYS("getting module failed 0x%08" B_PRIx32 "\n", result); 1274 mutex_destroy(&gDeviceListLock); 1275 return result; 1276 } 1277 1278 gUSBModule->register_driver(DRIVER_NAME, supportedDevices, 3, NULL); 1279 gUSBModule->install_notify(DRIVER_NAME, ¬ifyHooks); 1280 return B_OK; 1281 } 1282 1283 1284 void 1285 uninit_driver() 1286 { 1287 TRACE("uninit_driver()\n"); 1288 gUSBModule->uninstall_notify(DRIVER_NAME); 1289 mutex_lock(&gDeviceListLock); 1290 1291 if (gDeviceNames) { 1292 for (int32 i = 0; gDeviceNames[i]; i++) 1293 free(gDeviceNames[i]); 1294 free(gDeviceNames); 1295 gDeviceNames = NULL; 1296 } 1297 1298 mutex_destroy(&gDeviceListLock); 1299 put_module(B_USB_MODULE_NAME); 1300 } 1301 1302 1303 const char ** 1304 publish_devices() 1305 { 1306 TRACE("publish_devices()\n"); 1307 if (gDeviceNames) { 1308 for (int32 i = 0; gDeviceNames[i]; i++) 1309 free(gDeviceNames[i]); 1310 free(gDeviceNames); 1311 gDeviceNames = NULL; 1312 } 1313 1314 gDeviceNames = (char **)malloc(sizeof(char *) * (gLunCount + 1)); 1315 if (gDeviceNames == NULL) 1316 return NULL; 1317 1318 int32 index = 0; 1319 mutex_lock(&gDeviceListLock); 1320 disk_device *device = gDeviceList; 1321 while (device) { 1322 for (uint8 i = 0; i < device->lun_count; i++) 1323 gDeviceNames[index++] = strdup(device->luns[i]->name); 1324 1325 device = (disk_device *)device->link; 1326 } 1327 1328 gDeviceNames[index++] = NULL; 1329 mutex_unlock(&gDeviceListLock); 1330 return (const char **)gDeviceNames; 1331 } 1332 1333 1334 device_hooks * 1335 find_device(const char *name) 1336 { 1337 TRACE("find_device()\n"); 1338 static device_hooks hooks = { 1339 &usb_disk_open, 1340 &usb_disk_close, 1341 &usb_disk_free, 1342 &usb_disk_ioctl, 1343 &usb_disk_read, 1344 &usb_disk_write, 1345 NULL, 1346 NULL, 1347 NULL, 1348 NULL 1349 }; 1350 1351 return &hooks; 1352 } 1353