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