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