1 /* 2 * Copyright 2004-2008, Haiku, Inc. All RightsReserved. 3 * Copyright 2002-2003, Thomas Kurschel. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 //! Handling of block device (currently, only a capacity check is provided) 9 10 11 #include "scsi_periph_int.h" 12 #include <string.h> 13 14 15 status_t 16 periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) 17 { 18 scsi_res_read_capacity capacityResult; 19 scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb; 20 uint64 capacity; 21 uint32 blockSize; 22 status_t res; 23 24 SHOW_FLOW(3, "%p, %p", device, request); 25 26 // driver doesn't support capacity callback - seems to be no block 27 // device driver, so ignore 28 if (device->callbacks->set_capacity == NULL) 29 return B_OK; 30 31 request->flags = SCSI_DIR_IN; 32 33 request->data = (uint8*)&capacityResult; 34 request->data_length = sizeof(capacityResult); 35 request->cdb_length = sizeof(scsi_cmd_read_capacity); 36 request->timeout = device->std_timeout; 37 request->sort = -1; 38 request->sg_list = NULL; 39 40 memset(cmd, 0, sizeof(*cmd)); 41 cmd->opcode = SCSI_OP_READ_CAPACITY; 42 // we don't set PMI (partial medium indicator) as we want the whole capacity; 43 // in this case, all other parameters must be zero 44 45 res = periph_safe_exec(device, request); 46 47 if (res == B_DEV_MEDIA_CHANGED) { 48 // in this case, the error handler has already called check_capacity 49 // recursively, so we ignore our (invalid) result 50 SHOW_FLOW0( 3, "ignore result because medium change" ); 51 return B_DEV_MEDIA_CHANGED; 52 } 53 54 ACQUIRE_BEN(&device->mutex); 55 56 if (res == B_OK && request->data_resid == 0) { 57 capacity = B_BENDIAN_TO_HOST_INT32(capacityResult.lba); 58 59 // the command returns the index of the _last_ block, 60 // i.e. the size is one larger 61 ++capacity; 62 63 blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size); 64 } else { 65 capacity = 0; 66 blockSize = 0; 67 } 68 69 SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, blockSize); 70 71 device->block_size = blockSize; 72 73 device->callbacks->set_capacity(device->periph_device, 74 capacity, blockSize); 75 76 /* device->byte2blk_shift = log2( device->block_size ); 77 if( device->byte2blk_shift < 0 ) { 78 // this may be too restrictive... 79 device->capacity = -1; 80 return ERR_DEV_GENERAL; 81 }*/ 82 83 RELEASE_BEN(&device->mutex); 84 85 SHOW_FLOW(3, "done (%s)", strerror(res)); 86 87 return res; 88 } 89 90