xref: /haiku/src/add-ons/kernel/bus_managers/scsi/ccb.cpp (revision 820dca4df6c7bf955c46e8f6521b9408f50b2900)
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