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%x) must be less then B_PAGE_SIZE", 221 (int)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%x) is too small", 228 (int)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%x) must be at least B_PAGE_SIZE", 235 (int)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 (%d) and max s/g blocks (%d) must be at least 1", 242 (int)bus->dma_params.max_blocks, (int)bus->dma_params.max_sg_blocks); 243 res = B_ERROR; 244 goto err; 245 } 246 247 { 248 device_node *parent = pnp->get_parent_node(node); 249 pnp->get_driver(parent, (driver_module_info **)&bus->interface, 250 (void **)&bus->sim_cookie); 251 pnp->put_node(parent); 252 253 bus->interface->set_scsi_bus(bus->sim_cookie, bus); 254 } 255 256 // cache inquiry data 257 scsi_inquiry_path(bus, &bus->inquiry_data); 258 259 // get max. number of commands on bus 260 bus->left_slots = bus->inquiry_data.hba_queue_size; 261 SHOW_FLOW( 3, "Bus has %d slots", bus->left_slots ); 262 263 *cookie = bus; 264 265 return B_OK; 266 267 err: 268 scsi_destroy_bus(bus); 269 return res; 270 } 271 272 273 static void 274 scsi_uninit_bus(scsi_bus_info *bus) 275 { 276 scsi_destroy_bus(bus); 277 } 278 279 280 uchar 281 scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data) 282 { 283 SHOW_FLOW(4, "path_id=%d", bus->path_id); 284 return bus->interface->path_inquiry(bus->sim_cookie, inquiry_data); 285 } 286 287 288 static uchar 289 scsi_reset_bus(scsi_bus_info *bus) 290 { 291 return bus->interface->reset_bus(bus->sim_cookie); 292 } 293 294 295 static status_t 296 scsi_bus_module_init(void) 297 { 298 SHOW_FLOW0(4, ""); 299 return init_temp_sg(); 300 } 301 302 303 static status_t 304 scsi_bus_module_uninit(void) 305 { 306 SHOW_INFO0(4, ""); 307 308 uninit_temp_sg(); 309 return B_OK; 310 } 311 312 313 static status_t 314 std_ops(int32 op, ...) 315 { 316 switch (op) { 317 case B_MODULE_INIT: 318 return scsi_bus_module_init(); 319 case B_MODULE_UNINIT: 320 return scsi_bus_module_uninit(); 321 322 default: 323 return B_ERROR; 324 } 325 } 326 327 328 scsi_bus_interface scsi_bus_module = { 329 { 330 { 331 SCSI_BUS_MODULE_NAME, 332 0, 333 std_ops 334 }, 335 336 NULL, // supported devices 337 NULL, // register node 338 scsi_init_bus, 339 (void (*)(void *))scsi_uninit_bus, 340 (status_t (*)(void *))scsi_scan_bus, 341 (status_t (*)(void *))scsi_scan_bus, 342 NULL 343 }, 344 345 scsi_inquiry_path, 346 scsi_reset_bus, 347 }; 348