1 /* 2 ** Copyright 2002/03, Thomas Kurschel. All rights reserved. 3 ** Distributed under the terms of the OpenBeOS License. 4 */ 5 6 /* 7 Part of Open SCSI bus manager 8 9 CCB manager 10 11 As allocation of ccb can be on the paging path we must use a 12 locked pool. 13 */ 14 15 #include "scsi_internal.h" 16 17 18 19 // ccb are relatively large, so don't make it too small to not waste memory 20 #define CCB_CHUNK_SIZE 16*1024 21 22 // maximum number of CCBs - probably, we want to make that editable 23 // it must be at least 1 for normal use and 1 for stand-by autosense request 24 #define CCB_NUM_MAX 128 25 26 27 scsi_ccb * 28 scsi_alloc_ccb(scsi_device_info *device) 29 { 30 scsi_ccb *ccb; 31 32 SHOW_FLOW0( 3, "" ); 33 34 ccb = (scsi_ccb *)locked_pool->alloc(device->bus->ccb_pool); 35 ccb->state = SCSI_STATE_FINISHED; 36 ccb->device = device; 37 ccb->target_id = device->target_id; 38 ccb->target_lun = device->target_lun; 39 40 // reset some very important fields 41 // TODO: should we better omit that to find bugs easier? 42 ccb->sg_list = NULL; 43 ccb->io_operation = NULL; 44 ccb->sort = -1; 45 46 SHOW_FLOW(3, "path=%d", ccb->path_id); 47 48 return ccb; 49 } 50 51 52 void 53 scsi_free_ccb(scsi_ccb *ccb) 54 { 55 SHOW_FLOW0( 3, "" ); 56 57 if (ccb->state != SCSI_STATE_FINISHED) 58 panic("Tried to free ccb that's still in use (state %d)\n", ccb->state); 59 60 ccb->state = SCSI_STATE_FREE; 61 62 locked_pool->free(ccb->bus->ccb_pool, ccb); 63 } 64 65 66 static status_t 67 ccb_low_alloc_hook(void *block, void *arg) 68 { 69 scsi_ccb *ccb = (scsi_ccb *)block; 70 scsi_bus_info *bus = (scsi_bus_info *)arg; 71 status_t res; 72 73 ccb->bus = bus; 74 ccb->path_id = bus->path_id; 75 ccb->state = SCSI_STATE_FREE; 76 77 if ((res = ccb->completion_sem = create_sem(0, "ccb_sem")) < 0) 78 return res; 79 80 return B_OK; 81 } 82 83 84 static void 85 ccb_low_free_hook(void *block, void *arg) 86 { 87 scsi_ccb *ccb = (scsi_ccb *)block; 88 89 delete_sem(ccb->completion_sem); 90 } 91 92 93 status_t 94 scsi_init_ccb_alloc(scsi_bus_info *bus) 95 { 96 // initially, we want no CCB allocated as the path_id of 97 // the bus is not ready yet so the CCB cannot be initialized 98 // correctly 99 bus->ccb_pool = locked_pool->create(sizeof(scsi_ccb), sizeof(uint32) - 1, 0, 100 CCB_CHUNK_SIZE, CCB_NUM_MAX, 0, "scsi_ccb_pool", B_CONTIGUOUS, 101 ccb_low_alloc_hook, ccb_low_free_hook, bus); 102 103 if (bus->ccb_pool == NULL) 104 return B_NO_MEMORY; 105 106 return B_OK; 107 } 108 109 110 void 111 scsi_uninit_ccb_alloc(scsi_bus_info *bus) 112 { 113 locked_pool->destroy(bus->ccb_pool); 114 } 115 116