status_t periph_simple_exec(scsi_periph_device_info* device, void* cdb, uchar cdbLength, void* data, size_t dataLength, int ccb_flags) { SHOW_FLOW0( 0, "" ); scsi_ccb* ccb = device->scsi->alloc_ccb(device->scsi_device); if (ccb == NULL) return B_NO_MEMORY; ccb->flags = ccb_flags; memcpy(ccb->cdb, cdb, cdbLength); ccb->cdb_length = cdbLength; ccb->sort = -1; ccb->timeout = device->std_timeout; ccb->data = (uint8*)data; ccb->sg_list = NULL; ccb->data_length = dataLength; status_t status = periph_safe_exec(device, ccb); device->scsi->free_ccb(ccb); return status; }
static status_t vpd_page_inquiry(scsi_periph_device_info *device, uint8 page, void* data, uint16 length) { SHOW_FLOW0(0, ""); scsi_ccb* ccb = device->scsi->alloc_ccb(device->scsi_device); if (ccb == NULL) return B_NO_MEMORY; scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)ccb->cdb; memset(cmd, 0, sizeof(scsi_cmd_inquiry)); cmd->opcode = SCSI_OP_INQUIRY; cmd->lun = ccb->target_lun; cmd->evpd = 1; cmd->page_code = page; cmd->allocation_length = length; ccb->flags = SCSI_DIR_IN; ccb->cdb_length = sizeof(scsi_cmd_inquiry); ccb->sort = -1; ccb->timeout = device->std_timeout; ccb->data = (uint8*)data; ccb->sg_list = NULL; ccb->data_length = length; status_t status = periph_safe_exec(device, ccb); device->scsi->free_ccb(ccb); return status; }
status_t periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request) { scsi_res_read_capacity capacityResult; scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb; uint64 capacity; uint32 blockSize; status_t res; SHOW_FLOW(3, "%p, %p", device, request); // driver doesn't support capacity callback - seems to be no block // device driver, so ignore if (device->callbacks->set_capacity == NULL) return B_OK; request->flags = SCSI_DIR_IN; request->data = (uint8*)&capacityResult; request->data_length = sizeof(capacityResult); request->cdb_length = sizeof(scsi_cmd_read_capacity); request->timeout = device->std_timeout; request->sort = -1; request->sg_list = NULL; memset(cmd, 0, sizeof(*cmd)); cmd->opcode = SCSI_OP_READ_CAPACITY; // we don't set PMI (partial medium indicator) as we want the whole capacity; // in this case, all other parameters must be zero res = periph_safe_exec(device, request); if (res == B_DEV_MEDIA_CHANGED) { // in this case, the error handler has already called check_capacity // recursively, so we ignore our (invalid) result SHOW_FLOW0( 3, "ignore result because medium change" ); return B_DEV_MEDIA_CHANGED; } ACQUIRE_BEN(&device->mutex); if (res == B_OK && request->data_resid == 0) { capacity = B_BENDIAN_TO_HOST_INT32(capacityResult.lba); // the command returns the index of the _last_ block, // i.e. the size is one larger ++capacity; blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size); } else { capacity = 0; blockSize = 0; } SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, blockSize); device->block_size = blockSize; device->callbacks->set_capacity(device->periph_device, capacity, blockSize); /* device->byte2blk_shift = log2( device->block_size ); if( device->byte2blk_shift < 0 ) { // this may be too restrictive... device->capacity = -1; return ERR_DEV_GENERAL; }*/ RELEASE_BEN(&device->mutex); SHOW_FLOW(3, "done (%s)", strerror(res)); return res; }