1 /* 2 * Copyright 2002/03, Thomas Kurschel. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 /* 7 Part of Open SCSI bus manager 8 9 Bus node layer. 10 11 Whenever a controller driver publishes a new controller, a new SCSI bus 12 for public and internal use is registered in turn. After that, this 13 bus is told to rescan for devices. For each device, there is a 14 device registered for peripheral drivers. (see devices.c) 15 */ 16 17 #include "scsi_internal.h" 18 19 #include <string.h> 20 #include <malloc.h> 21 22 23 // bus service should hurry up a bit - good controllers don't take much time 24 // but are very happy to be busy; don't make it realtime though as we 25 // don't really need that but would risk to steel processing power of 26 // realtime-demanding threads 27 #define BUS_SERVICE_PRIORITY B_URGENT_DISPLAY_PRIORITY 28 29 30 /** implementation of service thread: 31 * it handles DPC and pending requests 32 */ 33 34 static void 35 scsi_do_service(scsi_bus_info *bus) 36 { 37 while (true) { 38 SHOW_FLOW0( 3, "" ); 39 40 // handle DPCs first as they are more urgent 41 if (scsi_check_exec_dpc(bus)) 42 continue; 43 44 if (scsi_check_exec_service(bus)) 45 continue; 46 47 break; 48 } 49 } 50 51 52 /** main loop of service thread */ 53 54 static int32 55 scsi_service_threadproc(void *arg) 56 { 57 scsi_bus_info *bus = (scsi_bus_info *)arg; 58 int32 processed_notifications = 0; 59 60 SHOW_FLOW(3, "bus = %p", bus); 61 62 while (true) { 63 // we handle multiple requests in scsi_do_service at once; 64 // to save time, we will acquire all notifications that are sent 65 // up to now at once. 66 // (Sadly, there is no "set semaphore to zero" function, so this 67 // is a poor-man emulation) 68 acquire_sem_etc(bus->start_service, processed_notifications + 1, 0, 0); 69 70 SHOW_FLOW0( 3, "1" ); 71 72 if (bus->shutting_down) 73 break; 74 75 // get number of notifications _before_ servicing to make sure no new 76 // notifications are sent after do_service() 77 get_sem_count(bus->start_service, &processed_notifications); 78 79 scsi_do_service(bus); 80 } 81 82 return 0; 83 } 84 85 86 static scsi_bus_info * 87 scsi_create_bus(device_node *node, uint8 path_id) 88 { 89 scsi_bus_info *bus; 90 int res; 91 92 SHOW_FLOW0(3, ""); 93 94 bus = (scsi_bus_info *)malloc(sizeof(*bus)); 95 if (bus == NULL) 96 return NULL; 97 98 memset(bus, 0, sizeof(*bus)); 99 100 bus->path_id = path_id; 101 102 if (pnp->get_attr_uint32(node, SCSI_DEVICE_MAX_TARGET_COUNT, &bus->max_target_count, true) != B_OK) 103 bus->max_target_count = MAX_TARGET_ID + 1; 104 if (pnp->get_attr_uint32(node, SCSI_DEVICE_MAX_LUN_COUNT, &bus->max_lun_count, true) != B_OK) 105 bus->max_lun_count = MAX_LUN_ID + 1; 106 107 // our scsi_ccb only has a uchar for target_id 108 if (bus->max_target_count > 256) 109 bus->max_target_count = 256; 110 // our scsi_ccb only has a uchar for target_lun 111 if (bus->max_lun_count > 256) 112 bus->max_lun_count = 256; 113 114 bus->node = node; 115 bus->lock_count = bus->blocked[0] = bus->blocked[1] = 0; 116 bus->sim_overflow = 0; 117 bus->shutting_down = false; 118 119 bus->waiting_devices = NULL; 120 //bus->resubmitted_req = NULL; 121 122 bus->dpc_list = NULL; 123 124 if ((bus->scan_lun_lock = create_sem(1, "scsi_scan_lun_lock")) < 0) { 125 res = bus->scan_lun_lock; 126 goto err6; 127 } 128 129 bus->start_service = create_sem(0, "scsi_start_service"); 130 if (bus->start_service < 0) { 131 res = bus->start_service; 132 goto err4; 133 } 134 135 res = INIT_BEN(&bus->mutex, "scsi_bus_mutex"); 136 if (res < B_OK) 137 goto err3; 138 139 spinlock_irq_init(&bus->dpc_lock); 140 141 res = scsi_init_ccb_alloc(bus); 142 if (res < B_OK) 143 goto err2; 144 145 bus->service_thread = spawn_kernel_thread(scsi_service_threadproc, 146 "scsi_bus_service", BUS_SERVICE_PRIORITY, bus); 147 148 if (bus->service_thread < 0) { 149 res = bus->service_thread; 150 goto err1; 151 } 152 153 resume_thread(bus->service_thread); 154 155 return bus; 156 157 err1: 158 scsi_uninit_ccb_alloc(bus); 159 err2: 160 DELETE_BEN(&bus->mutex); 161 err3: 162 delete_sem(bus->start_service); 163 err4: 164 delete_sem(bus->scan_lun_lock); 165 err6: 166 free(bus); 167 return NULL; 168 } 169 170 171 static status_t 172 scsi_destroy_bus(scsi_bus_info *bus) 173 { 174 int32 retcode; 175 176 // noone is using this bus now, time to clean it up 177 bus->shutting_down = true; 178 release_sem(bus->start_service); 179 180 wait_for_thread(bus->service_thread, &retcode); 181 182 delete_sem(bus->start_service); 183 DELETE_BEN(&bus->mutex); 184 delete_sem(bus->scan_lun_lock); 185 186 scsi_uninit_ccb_alloc(bus); 187 188 return B_OK; 189 } 190 191 192 static status_t 193 scsi_init_bus(device_node *node, void **cookie) 194 { 195 uint8 path_id; 196 scsi_bus_info *bus; 197 status_t res; 198 199 SHOW_FLOW0( 3, "" ); 200 201 if (pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &path_id, false) != B_OK) 202 return B_ERROR; 203 204 bus = scsi_create_bus(node, path_id); 205 if (bus == NULL) 206 return B_NO_MEMORY; 207 208 // extract controller/protocoll restrictions from node 209 if (pnp->get_attr_uint32(node, B_DMA_ALIGNMENT, &bus->dma_params.alignment, 210 true) != B_OK) 211 bus->dma_params.alignment = 0; 212 if (pnp->get_attr_uint32(node, B_DMA_MAX_TRANSFER_BLOCKS, 213 &bus->dma_params.max_blocks, true) != B_OK) 214 bus->dma_params.max_blocks = 0xffffffff; 215 if (pnp->get_attr_uint32(node, B_DMA_BOUNDARY, 216 &bus->dma_params.dma_boundary, true) != B_OK) 217 bus->dma_params.dma_boundary = ~0; 218 if (pnp->get_attr_uint32(node, B_DMA_MAX_SEGMENT_BLOCKS, 219 &bus->dma_params.max_sg_block_size, true) != B_OK) 220 bus->dma_params.max_sg_block_size = 0xffffffff; 221 if (pnp->get_attr_uint32(node, B_DMA_MAX_SEGMENT_COUNT, 222 &bus->dma_params.max_sg_blocks, true) != B_OK) 223 bus->dma_params.max_sg_blocks = ~0; 224 225 // do some sanity check: 226 bus->dma_params.max_sg_block_size &= ~bus->dma_params.alignment; 227 228 if (bus->dma_params.alignment > B_PAGE_SIZE) { 229 SHOW_ERROR(0, "Alignment (0x%" B_PRIx32 ") must be less then " 230 "B_PAGE_SIZE", bus->dma_params.alignment); 231 res = B_ERROR; 232 goto err; 233 } 234 235 if (bus->dma_params.max_sg_block_size < 1) { 236 SHOW_ERROR(0, "Max s/g block size (0x%" B_PRIx32 ") is too small", 237 bus->dma_params.max_sg_block_size); 238 res = B_ERROR; 239 goto err; 240 } 241 242 if (bus->dma_params.dma_boundary < B_PAGE_SIZE - 1) { 243 SHOW_ERROR(0, "DMA boundary (0x%" B_PRIx32 ") must be at least " 244 "B_PAGE_SIZE", bus->dma_params.dma_boundary); 245 res = B_ERROR; 246 goto err; 247 } 248 249 if (bus->dma_params.max_blocks < 1 || bus->dma_params.max_sg_blocks < 1) { 250 SHOW_ERROR(0, "Max blocks (%" B_PRIu32 ") and max s/g blocks (%" 251 B_PRIu32 ") must be at least 1", bus->dma_params.max_blocks, 252 bus->dma_params.max_sg_blocks); 253 res = B_ERROR; 254 goto err; 255 } 256 257 { 258 device_node *parent = pnp->get_parent_node(node); 259 pnp->get_driver(parent, (driver_module_info **)&bus->interface, 260 (void **)&bus->sim_cookie); 261 pnp->put_node(parent); 262 263 bus->interface->set_scsi_bus(bus->sim_cookie, bus); 264 } 265 266 // cache inquiry data 267 scsi_inquiry_path(bus, &bus->inquiry_data); 268 269 // get max. number of commands on bus 270 bus->left_slots = bus->inquiry_data.hba_queue_size; 271 SHOW_FLOW( 3, "Bus has %d slots", bus->left_slots ); 272 273 *cookie = bus; 274 275 return B_OK; 276 277 err: 278 scsi_destroy_bus(bus); 279 return res; 280 } 281 282 283 static void 284 scsi_uninit_bus(scsi_bus_info *bus) 285 { 286 scsi_destroy_bus(bus); 287 } 288 289 290 uchar 291 scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data) 292 { 293 SHOW_FLOW(4, "path_id=%d", bus->path_id); 294 return bus->interface->path_inquiry(bus->sim_cookie, inquiry_data); 295 } 296 297 298 static uchar 299 scsi_reset_bus(scsi_bus_info *bus) 300 { 301 return bus->interface->reset_bus(bus->sim_cookie); 302 } 303 304 305 static status_t 306 scsi_bus_module_init(void) 307 { 308 SHOW_FLOW0(4, ""); 309 return init_temp_sg(); 310 } 311 312 313 static status_t 314 scsi_bus_module_uninit(void) 315 { 316 SHOW_INFO0(4, ""); 317 318 uninit_temp_sg(); 319 return B_OK; 320 } 321 322 323 static status_t 324 std_ops(int32 op, ...) 325 { 326 switch (op) { 327 case B_MODULE_INIT: 328 return scsi_bus_module_init(); 329 case B_MODULE_UNINIT: 330 return scsi_bus_module_uninit(); 331 332 default: 333 return B_ERROR; 334 } 335 } 336 337 338 scsi_bus_interface scsi_bus_module = { 339 { 340 { 341 SCSI_BUS_MODULE_NAME, 342 0, 343 std_ops 344 }, 345 346 NULL, // supported devices 347 NULL, // register node 348 scsi_init_bus, 349 (void (*)(void *))scsi_uninit_bus, 350 (status_t (*)(void *))scsi_scan_bus, 351 (status_t (*)(void *))scsi_scan_bus, 352 NULL 353 }, 354 355 scsi_inquiry_path, 356 scsi_reset_bus, 357 }; 358