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 137 if (res < B_OK) 138 goto err3; 139 140 spinlock_irq_init(&bus->dpc_lock); 141 142 res = scsi_init_ccb_alloc(bus); 143 if (res < B_OK) 144 goto err2; 145 146 bus->service_thread = spawn_kernel_thread(scsi_service_threadproc, 147 "scsi_bus_service", BUS_SERVICE_PRIORITY, bus); 148 149 if (bus->service_thread < 0) { 150 res = bus->service_thread; 151 goto err1; 152 } 153 154 resume_thread(bus->service_thread); 155 156 return bus; 157 158 err1: 159 scsi_uninit_ccb_alloc(bus); 160 err2: 161 DELETE_BEN(&bus->mutex); 162 err3: 163 delete_sem(bus->start_service); 164 err4: 165 delete_sem(bus->scan_lun_lock); 166 err6: 167 free(bus); 168 return NULL; 169 } 170 171 172 static status_t 173 scsi_destroy_bus(scsi_bus_info *bus) 174 { 175 int32 retcode; 176 177 // noone is using this bus now, time to clean it up 178 bus->shutting_down = true; 179 release_sem(bus->start_service); 180 181 wait_for_thread(bus->service_thread, &retcode); 182 183 delete_sem(bus->start_service); 184 DELETE_BEN(&bus->mutex); 185 delete_sem(bus->scan_lun_lock); 186 187 scsi_uninit_ccb_alloc(bus); 188 189 return B_OK; 190 } 191 192 193 static status_t 194 scsi_init_bus(device_node *node, void **cookie) 195 { 196 uint8 path_id; 197 scsi_bus_info *bus; 198 status_t res; 199 200 SHOW_FLOW0( 3, "" ); 201 202 if (pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &path_id, false) != B_OK) 203 return B_ERROR; 204 205 bus = scsi_create_bus(node, path_id); 206 if (bus == NULL) 207 return B_NO_MEMORY; 208 209 // extract controller/protocoll restrictions from node 210 if (pnp->get_attr_uint32(node, B_DMA_ALIGNMENT, &bus->dma_params.alignment, 211 true) != B_OK) 212 bus->dma_params.alignment = 0; 213 if (pnp->get_attr_uint32(node, B_DMA_MAX_TRANSFER_BLOCKS, 214 &bus->dma_params.max_blocks, true) != B_OK) 215 bus->dma_params.max_blocks = 0xffffffff; 216 if (pnp->get_attr_uint32(node, B_DMA_BOUNDARY, 217 &bus->dma_params.dma_boundary, true) != B_OK) 218 bus->dma_params.dma_boundary = ~0; 219 if (pnp->get_attr_uint32(node, B_DMA_MAX_SEGMENT_BLOCKS, 220 &bus->dma_params.max_sg_block_size, true) != B_OK) 221 bus->dma_params.max_sg_block_size = 0xffffffff; 222 if (pnp->get_attr_uint32(node, B_DMA_MAX_SEGMENT_COUNT, 223 &bus->dma_params.max_sg_blocks, true) != B_OK) 224 bus->dma_params.max_sg_blocks = ~0; 225 226 // do some sanity check: 227 bus->dma_params.max_sg_block_size &= ~bus->dma_params.alignment; 228 229 if (bus->dma_params.alignment > B_PAGE_SIZE) { 230 SHOW_ERROR(0, "Alignment (0x%" B_PRIx32 ") must be less then " 231 "B_PAGE_SIZE", bus->dma_params.alignment); 232 res = B_ERROR; 233 goto err; 234 } 235 236 if (bus->dma_params.max_sg_block_size < 1) { 237 SHOW_ERROR(0, "Max s/g block size (0x%" B_PRIx32 ") is too small", 238 bus->dma_params.max_sg_block_size); 239 res = B_ERROR; 240 goto err; 241 } 242 243 if (bus->dma_params.dma_boundary < B_PAGE_SIZE - 1) { 244 SHOW_ERROR(0, "DMA boundary (0x%" B_PRIx32 ") must be at least " 245 "B_PAGE_SIZE", bus->dma_params.dma_boundary); 246 res = B_ERROR; 247 goto err; 248 } 249 250 if (bus->dma_params.max_blocks < 1 || bus->dma_params.max_sg_blocks < 1) { 251 SHOW_ERROR(0, "Max blocks (%" B_PRIu32 ") and max s/g blocks (%" 252 B_PRIu32 ") must be at least 1", bus->dma_params.max_blocks, 253 bus->dma_params.max_sg_blocks); 254 res = B_ERROR; 255 goto err; 256 } 257 258 { 259 device_node *parent = pnp->get_parent_node(node); 260 pnp->get_driver(parent, (driver_module_info **)&bus->interface, 261 (void **)&bus->sim_cookie); 262 pnp->put_node(parent); 263 264 bus->interface->set_scsi_bus(bus->sim_cookie, bus); 265 } 266 267 // cache inquiry data 268 scsi_inquiry_path(bus, &bus->inquiry_data); 269 270 // get max. number of commands on bus 271 bus->left_slots = bus->inquiry_data.hba_queue_size; 272 SHOW_FLOW( 3, "Bus has %d slots", bus->left_slots ); 273 274 *cookie = bus; 275 276 return B_OK; 277 278 err: 279 scsi_destroy_bus(bus); 280 return res; 281 } 282 283 284 static void 285 scsi_uninit_bus(scsi_bus_info *bus) 286 { 287 scsi_destroy_bus(bus); 288 } 289 290 291 uchar 292 scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data) 293 { 294 SHOW_FLOW(4, "path_id=%d", bus->path_id); 295 return bus->interface->path_inquiry(bus->sim_cookie, inquiry_data); 296 } 297 298 299 static uchar 300 scsi_reset_bus(scsi_bus_info *bus) 301 { 302 return bus->interface->reset_bus(bus->sim_cookie); 303 } 304 305 306 static status_t 307 scsi_bus_module_init(void) 308 { 309 SHOW_FLOW0(4, ""); 310 return init_temp_sg(); 311 } 312 313 314 static status_t 315 scsi_bus_module_uninit(void) 316 { 317 SHOW_INFO0(4, ""); 318 319 uninit_temp_sg(); 320 return B_OK; 321 } 322 323 324 static status_t 325 std_ops(int32 op, ...) 326 { 327 switch (op) { 328 case B_MODULE_INIT: 329 return scsi_bus_module_init(); 330 case B_MODULE_UNINIT: 331 return scsi_bus_module_uninit(); 332 333 default: 334 return B_ERROR; 335 } 336 } 337 338 339 scsi_bus_interface scsi_bus_module = { 340 { 341 { 342 SCSI_BUS_MODULE_NAME, 343 0, 344 std_ops 345 }, 346 347 NULL, // supported devices 348 NULL, // register node 349 scsi_init_bus, 350 (void (*)(void *))scsi_uninit_bus, 351 (status_t (*)(void *))scsi_scan_bus, 352 (status_t (*)(void *))scsi_scan_bus, 353 NULL 354 }, 355 356 scsi_inquiry_path, 357 scsi_reset_bus, 358 }; 359