** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the MIT License.
*/
Part of Open SCSI bus manager
Handling of bus/device blocking. Inline functions defined
here don't wake service thread if required and don't lock bus, so
everyone using them must take care of that himself.
*/
#ifndef __BLOCKING_H__
#define __BLOCKING_H__
#include "dl_list.h"
void scsi_add_queued_request( scsi_ccb *request );
void scsi_add_queued_request_first( scsi_ccb *request );
void scsi_remove_queued_request( scsi_ccb *request );
static inline void scsi_add_req_queue_first( scsi_ccb *request )
{
scsi_device_info *device = request->device;
SHOW_FLOW( 3, "request=%p", request );
ADD_CDL_LIST_HEAD( request, scsi_ccb, device->queued_reqs, );
}
static inline void scsi_add_req_queue_last( scsi_ccb *request )
{
scsi_device_info *device = request->device;
SHOW_FLOW( 3, "request=%p", request );
ADD_CDL_LIST_TAIL( request, scsi_ccb, device->queued_reqs, );
}
static inline void scsi_remove_req_queue( scsi_ccb *request )
{
scsi_device_info *device = request->device;
SHOW_FLOW( 3, "request=%p", request );
REMOVE_CDL_LIST( request, device->queued_reqs, );
}
static inline void scsi_add_device_queue_first( scsi_device_info *device )
{
SHOW_FLOW0( 3, "" );
if( DEVICE_IN_WAIT_QUEUE( device ))
return;
SHOW_FLOW0( 3, "was not in wait queue - adding" );
ADD_CDL_LIST_HEAD( device, scsi_device_info, device->bus->waiting_devices, waiting_ );
}
static inline void scsi_add_device_queue_last( scsi_device_info *device )
{
SHOW_FLOW0( 3, "" );
if( DEVICE_IN_WAIT_QUEUE( device ))
return;
SHOW_FLOW0( 3, "was not in wait queue - adding" );
ADD_CDL_LIST_TAIL( device, scsi_device_info, device->bus->waiting_devices, waiting_ );
}
static inline void scsi_remove_device_queue( scsi_device_info *device )
{
SHOW_FLOW0( 3, "" );
if( !DEVICE_IN_WAIT_QUEUE( device ))
return;
SHOW_FLOW0( 3, "was in wait queue - removing from it" );
REMOVE_CDL_LIST( device, device->bus->waiting_devices, waiting_ );
device->waiting_next = NULL;
}
static inline void scsi_set_device_overflow( scsi_device_info *device )
{
device->lock_count += device->sim_overflow ^ 1;
device->sim_overflow = 1;
}
static inline void scsi_set_bus_overflow( scsi_bus_info *bus )
{
bus->lock_count += bus->sim_overflow ^ 1;
bus->sim_overflow = 1;
}
static inline void scsi_clear_device_overflow( scsi_device_info *device )
{
device->lock_count -= device->sim_overflow;
device->sim_overflow = 0;
}
static inline void scsi_clear_bus_overflow( scsi_bus_info *bus )
{
bus->lock_count -= bus->sim_overflow;
bus->sim_overflow = 0;
}
static inline bool scsi_can_service_bus( scsi_bus_info *bus )
{
return (bus->lock_count == 0) & (bus->waiting_devices != NULL);
}
static inline void scsi_unblock_bus_noresume( scsi_bus_info *bus, bool by_SIM )
{
if( bus->blocked[by_SIM] > 0 ) {
--bus->blocked[by_SIM];
--bus->lock_count;
} else {
panic( "Tried to unblock bus %d which wasn't blocked",
bus->path_id );
}
}
static inline void scsi_unblock_device_noresume( scsi_device_info *device, bool by_SIM )
{
if( device->blocked[by_SIM] > 0 ) {
--device->blocked[by_SIM];
--device->lock_count;
} else {
panic( "Tried to unblock device %d/%d/%d which wasn't blocked",
device->bus->path_id, device->target_id, device->target_lun );
}
}
static inline void scsi_block_bus_nolock( scsi_bus_info *bus, bool by_SIM )
{
++bus->blocked[by_SIM];
++bus->lock_count;
}
static inline void scsi_block_device_nolock( scsi_device_info *device, bool by_SIM )
{
++device->blocked[by_SIM];
++device->lock_count;
scsi_remove_device_queue( device );
}
void scsi_block_bus( scsi_bus_info *bus );
void scsi_unblock_bus( scsi_bus_info *bus );
void scsi_block_device( scsi_device_info *device );
void scsi_unblock_device( scsi_device_info *device );
void scsi_cont_send_bus( scsi_bus_info *bus );
void scsi_cont_send_device( scsi_device_info *device );
#endif