2 ** Copyright 2002/03, Thomas Kurschel. All rights reserved.
3 ** Distributed under the terms of the MIT License.
7 Part of Open SCSI bus manager
9 Handling of bus/device blocking. Inline functions defined
10 here don't wake service thread if required and don't lock bus, so
11 everyone using them must take care of that himself.
14 #ifndef __BLOCKING_H__
15 #define __BLOCKING_H__
19 void scsi_add_queued_request( scsi_ccb
*request
);
20 void scsi_add_queued_request_first( scsi_ccb
*request
);
21 void scsi_remove_queued_request( scsi_ccb
*request
);
24 static inline void scsi_add_req_queue_first( scsi_ccb
*request
)
26 scsi_device_info
*device
= request
->device
;
28 SHOW_FLOW( 3, "request=%p", request
);
30 ADD_CDL_LIST_HEAD( request
, scsi_ccb
, device
->queued_reqs
, );
33 static inline void scsi_add_req_queue_last( scsi_ccb
*request
)
35 scsi_device_info
*device
= request
->device
;
37 SHOW_FLOW( 3, "request=%p", request
);
39 ADD_CDL_LIST_TAIL( request
, scsi_ccb
, device
->queued_reqs
, );
42 static inline void scsi_remove_req_queue( scsi_ccb
*request
)
44 scsi_device_info
*device
= request
->device
;
46 SHOW_FLOW( 3, "request=%p", request
);
48 REMOVE_CDL_LIST( request
, device
->queued_reqs
, );
51 // ignored, if device is already queued
52 static inline void scsi_add_device_queue_first( scsi_device_info
*device
)
56 if( DEVICE_IN_WAIT_QUEUE( device
))
59 SHOW_FLOW0( 3, "was not in wait queue - adding" );
61 ADD_CDL_LIST_HEAD( device
, scsi_device_info
, device
->bus
->waiting_devices
, waiting_
);
64 // ignored, if device is already queued
65 static inline void scsi_add_device_queue_last( scsi_device_info
*device
)
69 if( DEVICE_IN_WAIT_QUEUE( device
))
72 SHOW_FLOW0( 3, "was not in wait queue - adding" );
74 ADD_CDL_LIST_TAIL( device
, scsi_device_info
, device
->bus
->waiting_devices
, waiting_
);
77 // ignored, if device is not in queue
78 static inline void scsi_remove_device_queue( scsi_device_info
*device
)
82 if( !DEVICE_IN_WAIT_QUEUE( device
))
85 SHOW_FLOW0( 3, "was in wait queue - removing from it" );
87 REMOVE_CDL_LIST( device
, device
->bus
->waiting_devices
, waiting_
);
89 // reset next link so we can see that it's not in device queue
90 device
->waiting_next
= NULL
;
93 // set overflow bit of device; this will not remove device from bus queue!
94 // (multiple calls are ignored gracefully)
95 static inline void scsi_set_device_overflow( scsi_device_info
*device
)
97 device
->lock_count
+= device
->sim_overflow
^ 1;
98 device
->sim_overflow
= 1;
101 // set overflow bit of bus
102 // (multiple calls are ignored gracefully)
103 static inline void scsi_set_bus_overflow( scsi_bus_info
*bus
)
105 bus
->lock_count
+= bus
->sim_overflow
^ 1;
106 bus
->sim_overflow
= 1;
109 // clear overflow bit of device; this will not add device to bus queue!
110 // (multiple calls are ignored gracefully)
111 static inline void scsi_clear_device_overflow( scsi_device_info
*device
)
113 device
->lock_count
-= device
->sim_overflow
;
114 device
->sim_overflow
= 0;
117 // clear overflow bit of bus
118 // (multiple calls are ignored gracefully)
119 static inline void scsi_clear_bus_overflow( scsi_bus_info
*bus
)
121 bus
->lock_count
-= bus
->sim_overflow
;
122 bus
->sim_overflow
= 0;
125 // check whether bus has some pending requests it can process now
126 static inline bool scsi_can_service_bus( scsi_bus_info
*bus
)
128 // bus must not be blocked and requests pending
129 return (bus
->lock_count
== 0) & (bus
->waiting_devices
!= NULL
);
133 // lock must be hold; service thread is not informed
134 static inline void scsi_unblock_bus_noresume( scsi_bus_info
*bus
, bool by_SIM
)
136 if( bus
->blocked
[by_SIM
] > 0 ) {
137 --bus
->blocked
[by_SIM
];
140 panic( "Tried to unblock bus %d which wasn't blocked",
147 // lock must be hold; device is not added to queue and service thread is not informed
148 static inline void scsi_unblock_device_noresume( scsi_device_info
*device
, bool by_SIM
)
150 if( device
->blocked
[by_SIM
] > 0 ) {
151 --device
->blocked
[by_SIM
];
152 --device
->lock_count
;
154 panic( "Tried to unblock device %d/%d/%d which wasn't blocked",
155 device
->bus
->path_id
, device
->target_id
, device
->target_lun
);
162 static inline void scsi_block_bus_nolock( scsi_bus_info
*bus
, bool by_SIM
)
164 ++bus
->blocked
[by_SIM
];
171 static inline void scsi_block_device_nolock( scsi_device_info
*device
, bool by_SIM
)
173 ++device
->blocked
[by_SIM
];
174 ++device
->lock_count
;
176 // remove device from bus queue as it cannot be processed anymore
177 scsi_remove_device_queue( device
);
181 void scsi_block_bus( scsi_bus_info
*bus
);
182 void scsi_unblock_bus( scsi_bus_info
*bus
);
183 void scsi_block_device( scsi_device_info
*device
);
184 void scsi_unblock_device( scsi_device_info
*device
);
186 void scsi_cont_send_bus( scsi_bus_info
*bus
);
187 void scsi_cont_send_device( scsi_device_info
*device
);