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 //! Main file. 9 10 11 #include "scsi_periph_int.h" 12 13 #include <module.h> 14 15 #include <string.h> 16 17 18 device_manager_info* gDeviceManager; 19 20 21 status_t 22 periph_simple_exec(scsi_periph_device_info* device, void* cdb, uchar cdbLength, 23 void* data, size_t dataLength, int ccb_flags) 24 { 25 SHOW_FLOW0( 0, "" ); 26 27 scsi_ccb* ccb = device->scsi->alloc_ccb(device->scsi_device); 28 if (ccb == NULL) 29 return B_NO_MEMORY; 30 31 ccb->flags = ccb_flags; 32 33 memcpy(ccb->cdb, cdb, cdbLength); 34 ccb->cdb_length = cdbLength; 35 36 ccb->sort = -1; 37 ccb->timeout = device->std_timeout; 38 39 ccb->data = (uint8*)data; 40 ccb->sg_list = NULL; 41 ccb->data_length = dataLength; 42 43 status_t status = periph_safe_exec(device, ccb); 44 45 device->scsi->free_ccb(ccb); 46 47 return status; 48 } 49 50 51 status_t 52 periph_safe_exec(scsi_periph_device_info *device, scsi_ccb *request) 53 { 54 err_res res; 55 int retries = 0; 56 57 do { 58 device->scsi->sync_io(request); 59 60 // ask generic peripheral layer what to do now 61 res = periph_check_error(device, request); 62 if (res.action == err_act_start) { 63 // backup request, as we need it temporarily for sending "start" 64 // (we cannot allocate a new cdb as there may be no more cdb and 65 // waiting for one to become empty may lead to deadlock if everyone 66 // does that) 67 uint32 backup_flags; 68 uint8 backup_cdb[SCSI_MAX_CDB_SIZE]; 69 uchar backup_cdb_len; 70 int64 backup_sort; 71 bigtime_t backup_timeout; 72 uchar *backup_data; 73 const physical_entry *backup_sg_list; 74 uint16 backup_sg_count; 75 uint32 backup_data_len; 76 77 backup_flags = request->flags; 78 memcpy(backup_cdb, request->cdb, SCSI_MAX_CDB_SIZE); 79 backup_cdb_len = request->cdb_length; 80 backup_sort = request->sort; 81 backup_timeout = request->timeout; 82 backup_data = request->data; 83 backup_sg_list = request->sg_list; 84 backup_sg_count = request->sg_count; 85 backup_data_len = request->data_length; 86 87 SHOW_INFO0( 2, "Sending start to init LUN" ); 88 89 res = periph_send_start_stop(device, request, 1, device->removable); 90 91 request->flags = backup_flags; 92 memcpy(request->cdb, backup_cdb, SCSI_MAX_CDB_SIZE); 93 request->cdb_length = backup_cdb_len; 94 request->sort = backup_sort; 95 request->timeout = backup_timeout; 96 request->data = backup_data; 97 request->sg_list = backup_sg_list; 98 request->sg_count = backup_sg_count; 99 request->data_length = backup_data_len; 100 101 if (res.action == err_act_ok) 102 res.action = err_act_retry; 103 } 104 } while ((res.action == err_act_retry && retries++ < 3) 105 || (res.action == err_act_many_retries && retries++ < 30)); 106 107 return res.error_code; 108 } 109 110 111 module_dependency module_dependencies[] = { 112 {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager}, 113 {} 114 }; 115 116 117 static scsi_periph_interface sSCSIPeripheralModule = { 118 { 119 SCSI_PERIPH_MODULE_NAME, 120 0, 121 NULL 122 }, 123 124 periph_register_device, 125 periph_unregister_device, 126 127 periph_safe_exec, 128 periph_simple_exec, 129 130 periph_handle_open, 131 periph_handle_close, 132 periph_handle_free, 133 134 periph_io, 135 periph_ioctl, 136 periph_check_capacity, 137 138 periph_media_changed_public, 139 periph_check_error, 140 periph_send_start_stop, 141 periph_get_media_status, 142 periph_synchronize_cache, 143 144 periph_compose_device_name 145 }; 146 147 scsi_periph_interface *modules[] = { 148 &sSCSIPeripheralModule, 149 NULL 150 }; 151