10d59a3d2SAxel Dörfler /* 2368167edSAxel Dörfler * Copyright 2004-2008, Haiku, Inc. All RightsReserved. 3b83a8af4SAxel Dörfler * Copyright 2002/03, Thomas Kurschel. All rights reserved. 4c9fc73fcSAxel Dörfler * 5b83a8af4SAxel Dörfler * Distributed under the terms of the MIT License. 60d59a3d2SAxel Dörfler */ 76be1e37dSAxel Dörfler #ifndef _SCSI_BUSMANAGER_H 86be1e37dSAxel Dörfler #define _SCSI_BUSMANAGER_H 90d59a3d2SAxel Dörfler 100d59a3d2SAxel Dörfler /* 110d59a3d2SAxel Dörfler SCSI bus manager interface 120d59a3d2SAxel Dörfler 130d59a3d2SAxel Dörfler The bus manager interface is _based_ on CAM, but I've modified it because :- 140d59a3d2SAxel Dörfler - HBA engine, target mode and queue freezing (and probably other features) 150d59a3d2SAxel Dörfler aren't supported (at least the first two aren't supported by linux too ;) 160d59a3d2SAxel Dörfler - Asynchronous events aren't supported (no OS/driver I know uses them) 170d59a3d2SAxel Dörfler - P/T/L was defined by number not by handle, requiring many redundant tests 180d59a3d2SAxel Dörfler and thus making adding/removing of devices/busses very hard, especially if 190d59a3d2SAxel Dörfler PnP is to be supported 200d59a3d2SAxel Dörfler - single entry system as proposed by CAM involves extra tests and overhead 210d59a3d2SAxel Dörfler because of generalized data structure 220d59a3d2SAxel Dörfler 230d59a3d2SAxel Dörfler 240d59a3d2SAxel Dörfler For peripheral driver writers: 250d59a3d2SAxel Dörfler 260d59a3d2SAxel Dörfler Something about requests involving data transfer: you can either specify 270d59a3d2SAxel Dörfler the virtual address in <data> of CCB (in which case it must be continuous), 280d59a3d2SAxel Dörfler or store a pointer to a S/G list that contains physical addresses in 296be1e37dSAxel Dörfler <sg_list>/<sg_count>. If <sg_list> is non-Null, <data> is ignored. 300d59a3d2SAxel Dörfler The S/G list must be in kernel space because the request can be executed 310d59a3d2SAxel Dörfler in a different thread context. This is also the reason why the S/G list has 320d59a3d2SAxel Dörfler to contain physical addresses. For obvious reason, the data buffer specified 330d59a3d2SAxel Dörfler by <sg_list> must be locked, but <data> doesn't need to be. 340d59a3d2SAxel Dörfler 350d59a3d2SAxel Dörfler You can either execute the request synchronously ("sync_io") or 360d59a3d2SAxel Dörfler asynchronously ("async_io"; you have to acquire <completion_sem> to find 370d59a3d2SAxel Dörfler out when the request is finished). In the first case you can use either 380d59a3d2SAxel Dörfler <data> or <sg_list>, in the latter <sg_list> only. 390d59a3d2SAxel Dörfler 400d59a3d2SAxel Dörfler The SCSI bus manager takes care that the controller can access the data 410d59a3d2SAxel Dörfler via DMA by copying it into a buffer if necessary. For the paging path, 420d59a3d2SAxel Dörfler this can lead to problems (if the system writes a page to disk and the SCSI 430d59a3d2SAxel Dörfler bus manager has to allocate a buffer during execution you are in trouble), 440d59a3d2SAxel Dörfler therefore the blk_man takes care that is not necessary for reads/writes. 450d59a3d2SAxel Dörfler To safe some microseconds, you should set the SCSI_DMA_SAFE flag for these 460d59a3d2SAxel Dörfler requests, so the SCSI bus manager ommittes the test. 470d59a3d2SAxel Dörfler 480d59a3d2SAxel Dörfler Effectively, using synchronous execution and specifying the address via 490d59a3d2SAxel Dörfler <data> is a safe bet. 500d59a3d2SAxel Dörfler 510d59a3d2SAxel Dörfler 520d59a3d2SAxel Dörfler For SIM writers: 530d59a3d2SAxel Dörfler 540d59a3d2SAxel Dörfler Requests sent by peripheral drivers are forwarded to the <scsi_io> entry 550d59a3d2SAxel Dörfler of the SIM. You should return as soon as some waiting is required. 560d59a3d2SAxel Dörfler Usually, the controller raises an IRQ when a request can be continued 570d59a3d2SAxel Dörfler or is finished. As interrupt handlers must be as fast as possible, you 580d59a3d2SAxel Dörfler can schedule a DPC in the handler (<schedule_dpc>) which executed by a 590d59a3d2SAxel Dörfler high priority service thread that is spawned by the SCSI bus manager 600d59a3d2SAxel Dörfler for each bus. This service thread also takes care to submit waiting 610d59a3d2SAxel Dörfler requests. 620d59a3d2SAxel Dörfler 630d59a3d2SAxel Dörfler You can specify a maximum number of concurrent requests per bus via 640d59a3d2SAxel Dörfler path_inquiry (<hba_queue_size>) for the bus. The device limit is 650d59a3d2SAxel Dörfler determined via INQUIRY. If you need a lower/dynamic limit, you can refuse 660d59a3d2SAxel Dörfler a request by <requeue>. If <bus_overflow> is true, no further requests 670d59a3d2SAxel Dörfler to the bus will be sent, if <bus_overflow> is false, no further requests 680d59a3d2SAxel Dörfler to the device will be sent. To terminate the overflow condition, call 690d59a3d2SAxel Dörfler <cont_send_device>/<cont_send_bus>. It also terminated when a request 700d59a3d2SAxel Dörfler for the bus/device is finished via <finished> or <resubmit>. 710d59a3d2SAxel Dörfler Because of the asynchronous nature, requests may still arrive after the 720d59a3d2SAxel Dörfler overflow condition being signalled, so you should add a safety test to 730d59a3d2SAxel Dörfler <scsi_io>. 740d59a3d2SAxel Dörfler 750d59a3d2SAxel Dörfler If a problem occurs during execution, you can ask for a restart via 760d59a3d2SAxel Dörfler <resubmit>. The request in question will be submitted as soon as possible. 770d59a3d2SAxel Dörfler 780d59a3d2SAxel Dörfler If you want to be not disturbed, you can block further requests via 790d59a3d2SAxel Dörfler <block_bus>/<block_device>. As said above, you must have a safety test 800d59a3d2SAxel Dörfler at <scsi_io> though. 810d59a3d2SAxel Dörfler 820d59a3d2SAxel Dörfler If the SIM uses a non-SCSI protocol, it can ask the SCSI bus manager 830d59a3d2SAxel Dörfler to emulate unsupported SCSI commands by translating them other (supported) 840d59a3d2SAxel Dörfler commands. The bus manager calls <get_restriction> during detection for 850d59a3d2SAxel Dörfler each device, setting <is_atapi> on return makes the bus manager translate 860d59a3d2SAxel Dörfler READ6/WRITE6 commands to READ10/WRITE10 commands, MODE REQUEST6/SENSE6 870d59a3d2SAxel Dörfler to MODE REQUEST10/SENSE10 and fix the version fields of INQUIRY results, 880d59a3d2SAxel Dörfler so ATAPI devices can be used like standard SCSI devices. Further, the 890d59a3d2SAxel Dörfler SCSI bus manager can emulate auto-sense by executing a REQUEST SENSE 900d59a3d2SAxel Dörfler if <subsys_status> is SCSI_REQ_CMP_ERR and <device_status> is 91f0d174e9SMarcus Overhagen SCSI_STATUS_CHECK_CONDITION when a request is finished. This emulation 920d59a3d2SAxel Dörfler may be enhanced/generalized in the future. 930d59a3d2SAxel Dörfler */ 940d59a3d2SAxel Dörfler 950d59a3d2SAxel Dörfler 960d59a3d2SAxel Dörfler #include <KernelExport.h> 97*77463640SAugustin Cavalier 98*77463640SAugustin Cavalier #ifdef _KERNEL_MODE 99*77463640SAugustin Cavalier #include <condition_variable.h> 1000d59a3d2SAxel Dörfler #include <device_manager.h> 101*77463640SAugustin Cavalier #endif 1020d59a3d2SAxel Dörfler 1030d59a3d2SAxel Dörfler 1040d59a3d2SAxel Dörfler typedef struct scsi_bus_info *scsi_bus; 1050d59a3d2SAxel Dörfler typedef struct scsi_device_info *scsi_device; 1060d59a3d2SAxel Dörfler 1070d59a3d2SAxel Dörfler 108*77463640SAugustin Cavalier #if defined(__cplusplus) && defined(_KERNEL_MODE) 1090d59a3d2SAxel Dörfler // structure of one scsi i/o CCB (command control block) 1106be1e37dSAxel Dörfler typedef struct scsi_ccb { 1110d59a3d2SAxel Dörfler struct scsi_ccb *next, *prev; // internal 1120d59a3d2SAxel Dörfler 1130d59a3d2SAxel Dörfler uchar subsys_status; // Returned subsystem status 1140d59a3d2SAxel Dörfler uchar device_status; // Returned scsi device status 1150d59a3d2SAxel Dörfler 1160d59a3d2SAxel Dörfler uchar path_id; // Path ID for the request 1170d59a3d2SAxel Dörfler uchar target_id; // Target device ID 1180d59a3d2SAxel Dörfler uchar target_lun; // Target LUN number 1190d59a3d2SAxel Dörfler uint32 flags; // Flags for operation of the subsystem 1200d59a3d2SAxel Dörfler 121*77463640SAugustin Cavalier // notified after asynchronous execution of request 122*77463640SAugustin Cavalier ConditionVariable completion_cond; 1230d59a3d2SAxel Dörfler 124*77463640SAugustin Cavalier #define SCSI_MAX_CDB_SIZE 16 1250d59a3d2SAxel Dörfler uint8 cdb[SCSI_MAX_CDB_SIZE]; // command data block 1266be1e37dSAxel Dörfler uchar cdb_length; // length of command in bytes 1270d59a3d2SAxel Dörfler int64 sort; // value of command to sort on (<0 means n/a) 1280d59a3d2SAxel Dörfler bigtime_t timeout; // timeout - 0 = use default 1290d59a3d2SAxel Dörfler 1300d59a3d2SAxel Dörfler uchar *data; // pointer to data 1316be1e37dSAxel Dörfler const physical_entry *sg_list; // scatter/gather list 1326be1e37dSAxel Dörfler uint16 sg_count; // number of S/G entries 1336be1e37dSAxel Dörfler uint32 data_length; // length of data 1340d59a3d2SAxel Dörfler int32 data_resid; // data transfer residual length: 2's comp 13524593e2cSAxel Dörfler void *io_operation; 1360d59a3d2SAxel Dörfler 137*77463640SAugustin Cavalier #define SCSI_MAX_SENSE_SIZE 64 1380d59a3d2SAxel Dörfler uchar sense[SCSI_MAX_SENSE_SIZE]; // autosense data 1390d59a3d2SAxel Dörfler uchar sense_resid; // autosense resid length: 2's comp 1400d59a3d2SAxel Dörfler 1410d59a3d2SAxel Dörfler // private 1420d59a3d2SAxel Dörfler bool ordered : 1; // request cannot overtake/be overtaken by others 1430d59a3d2SAxel Dörfler bool buffered : 1; // data is buffered to make it DMA safe 1440d59a3d2SAxel Dörfler bool emulated : 1; // command is executed as part of emulation 1450d59a3d2SAxel Dörfler 1460d59a3d2SAxel Dörfler scsi_bus bus; // associated bus 1470d59a3d2SAxel Dörfler scsi_device device; // associated device 1480d59a3d2SAxel Dörfler struct dma_buffer *dma_buffer; // used dma buffer, or NULL 1490d59a3d2SAxel Dörfler uchar state; // bus manager state 1500d59a3d2SAxel Dörfler 1510d59a3d2SAxel Dörfler // original data before command emulation was applied 1520d59a3d2SAxel Dörfler uint8 orig_cdb[SCSI_MAX_CDB_SIZE]; 1536be1e37dSAxel Dörfler uchar orig_cdb_length; 1540d59a3d2SAxel Dörfler const physical_entry *orig_sg_list; 1556be1e37dSAxel Dörfler uint16 orig_sg_count; 1566be1e37dSAxel Dörfler uint32 orig_data_length; 1570d59a3d2SAxel Dörfler } scsi_ccb; 158*77463640SAugustin Cavalier #else 159*77463640SAugustin Cavalier typedef struct scsi_ccb scsi_ccb; 160*77463640SAugustin Cavalier #endif 1610d59a3d2SAxel Dörfler 1620d59a3d2SAxel Dörfler 1630d59a3d2SAxel Dörfler // Defines for the subsystem status field 1640d59a3d2SAxel Dörfler 1650d59a3d2SAxel Dörfler #define SCSI_REQ_INPROG 0x00 /* request is in progress */ 1660d59a3d2SAxel Dörfler #define SCSI_REQ_CMP 0x01 /* request completed w/out error */ 1670d59a3d2SAxel Dörfler #define SCSI_REQ_ABORTED 0x02 /* request aborted by the host */ 1680d59a3d2SAxel Dörfler #define SCSI_UA_ABORT 0x03 /* Unable to Abort request */ 1690d59a3d2SAxel Dörfler #define SCSI_REQ_CMP_ERR 0x04 /* request completed with an err */ 1700d59a3d2SAxel Dörfler #define SCSI_BUSY 0x05 /* subsystem is busy */ 1710d59a3d2SAxel Dörfler #define SCSI_REQ_INVALID 0x06 /* request is invalid */ 1720d59a3d2SAxel Dörfler #define SCSI_PATH_INVALID 0x07 /* Path ID supplied is invalid */ 1730d59a3d2SAxel Dörfler #define SCSI_DEV_NOT_THERE 0x08 /* SCSI device not installed/there */ 1740d59a3d2SAxel Dörfler #define SCSI_UA_TERMIO 0x09 /* Unable to Terminate I/O req */ 1750d59a3d2SAxel Dörfler #define SCSI_SEL_TIMEOUT 0x0A /* Target selection timeout */ 1760d59a3d2SAxel Dörfler #define SCSI_CMD_TIMEOUT 0x0B /* Command timeout */ 1770d59a3d2SAxel Dörfler #define SCSI_MSG_REJECT_REC 0x0D /* Message reject received */ 1780d59a3d2SAxel Dörfler #define SCSI_SCSI_BUS_RESET 0x0E /* SCSI bus reset sent/received */ 1790d59a3d2SAxel Dörfler #define SCSI_UNCOR_PARITY 0x0F /* Uncorrectable parity err occurred */ 1800d59a3d2SAxel Dörfler #define SCSI_AUTOSENSE_FAIL 0x10 /* Autosense: Request sense cmd fail */ 1810d59a3d2SAxel Dörfler #define SCSI_NO_HBA 0x11 /* No HBA detected Error */ 1820d59a3d2SAxel Dörfler #define SCSI_DATA_RUN_ERR 0x12 /* Data overrun/underrun error */ 1830d59a3d2SAxel Dörfler #define SCSI_UNEXP_BUSFREE 0x13 /* Unexpected BUS free */ 1840d59a3d2SAxel Dörfler #define SCSI_SEQUENCE_FAIL 0x14 /* Target bus phase sequence failure */ 1850d59a3d2SAxel Dörfler #define SCSI_PROVIDE_FAIL 0x16 /* Unable to provide requ. capability */ 1860d59a3d2SAxel Dörfler #define SCSI_BDR_SENT 0x17 /* A SCSI BDR msg was sent to target */ 1870d59a3d2SAxel Dörfler #define SCSI_REQ_TERMIO 0x18 /* request terminated by the host */ 1880d59a3d2SAxel Dörfler #define SCSI_HBA_ERR 0x19 /* Unrecoverable host bus adaptor err*/ 1890d59a3d2SAxel Dörfler #define SCSI_BUS_RESET_DENIED 0x1A /* SCSI bus reset denied */ 1900d59a3d2SAxel Dörfler 1910d59a3d2SAxel Dörfler #define SCSI_IDE 0x33 /* Initiator Detected Error Received */ 1920d59a3d2SAxel Dörfler #define SCSI_RESRC_UNAVAIL 0x34 /* Resource unavailable */ 1930d59a3d2SAxel Dörfler #define SCSI_UNACKED_EVENT 0x35 /* Unacknowledged event by host */ 1940d59a3d2SAxel Dörfler #define SCSI_LUN_INVALID 0x38 /* LUN supplied is invalid */ 1950d59a3d2SAxel Dörfler #define SCSI_TID_INVALID 0x39 /* Target ID supplied is invalid */ 1960d59a3d2SAxel Dörfler #define SCSI_FUNC_NOTAVAIL 0x3A /* The requ. func is not available */ 1970d59a3d2SAxel Dörfler #define SCSI_NO_NEXUS 0x3B /* Nexus is not established */ 1980d59a3d2SAxel Dörfler #define SCSI_IID_INVALID 0x3C /* The initiator ID is invalid */ 1990d59a3d2SAxel Dörfler #define SCSI_CDB_RECVD 0x3D /* The SCSI CDB has been received */ 2000d59a3d2SAxel Dörfler #define SCSI_LUN_ALLREADY_ENAB 0x3E /* LUN already enabled */ 2010d59a3d2SAxel Dörfler #define SCSI_SCSI_BUSY 0x3F /* SCSI bus busy */ 2020d59a3d2SAxel Dörfler 2030d59a3d2SAxel Dörfler #define SCSI_AUTOSNS_VALID 0x80 /* Autosense data valid for target */ 2040d59a3d2SAxel Dörfler 2050d59a3d2SAxel Dörfler #define SCSI_SUBSYS_STATUS_MASK 0x3F /* Mask bits for just the status # */ 2060d59a3d2SAxel Dörfler 2070d59a3d2SAxel Dörfler 2080d59a3d2SAxel Dörfler // Defines for the flags field 2090d59a3d2SAxel Dörfler 2100d59a3d2SAxel Dörfler #define SCSI_DIR_RESV 0x00000000 /* Data direction (00: reserved) */ 2110d59a3d2SAxel Dörfler #define SCSI_DIR_IN 0x00000040 /* Data direction (01: DATA IN) */ 2120d59a3d2SAxel Dörfler #define SCSI_DIR_OUT 0x00000080 /* Data direction (10: DATA OUT) */ 2130d59a3d2SAxel Dörfler #define SCSI_DIR_NONE 0x000000C0 /* Data direction (11: no data) */ 2140d59a3d2SAxel Dörfler #define SCSI_DIR_MASK 0x000000C0 2150d59a3d2SAxel Dörfler 2160d59a3d2SAxel Dörfler #define SCSI_DIS_AUTOSENSE 0x00000020 /* Disable autosense feature */ 2170d59a3d2SAxel Dörfler #define SCSI_ORDERED_QTAG 0x00000010 // ordered queue (cannot overtake/be overtaken) 2180d59a3d2SAxel Dörfler #define SCSI_DMA_SAFE 0x00000008 // set if data buffer is DMA approved 2190d59a3d2SAxel Dörfler 2200d59a3d2SAxel Dörfler #define SCSI_DIS_DISCONNECT 0x00008000 /* Disable disconnect */ 2210d59a3d2SAxel Dörfler #define SCSI_INITIATE_SYNC 0x00004000 /* Attempt Sync data xfer, and SDTR */ 2220d59a3d2SAxel Dörfler #define SCSI_DIS_SYNC 0x00002000 /* Disable sync, go to async */ 2230d59a3d2SAxel Dörfler #define SCSI_ENG_SYNC 0x00000200 /* Flush resid bytes before cmplt */ 2240d59a3d2SAxel Dörfler 2250d59a3d2SAxel Dörfler 2260d59a3d2SAxel Dörfler // Defines for the Path Inquiry CCB fields 2270d59a3d2SAxel Dörfler 2280d59a3d2SAxel Dörfler // flags in hba_inquiry 2290d59a3d2SAxel Dörfler #define SCSI_PI_MDP_ABLE 0x80 /* Supports MDP message */ 2300d59a3d2SAxel Dörfler #define SCSI_PI_WIDE_32 0x40 /* Supports 32 bit wide SCSI */ 2310d59a3d2SAxel Dörfler #define SCSI_PI_WIDE_16 0x20 /* Supports 16 bit wide SCSI */ 2320d59a3d2SAxel Dörfler #define SCSI_PI_SDTR_ABLE 0x10 /* Supports SDTR message */ 2330d59a3d2SAxel Dörfler #define SCSI_PI_TAG_ABLE 0x02 /* Supports tag queue message */ 2340d59a3d2SAxel Dörfler #define SCSI_PI_SOFT_RST 0x01 /* Supports soft reset */ 2350d59a3d2SAxel Dörfler 2360d59a3d2SAxel Dörfler // flags in hba_misc 2370d59a3d2SAxel Dörfler #define SCSI_PIM_SCANHILO 0x80 /* Bus scans from ID 7 to ID 0 */ 2380d59a3d2SAxel Dörfler #define SCSI_PIM_NOREMOVE 0x40 /* Removable dev not included in scan */ 2390d59a3d2SAxel Dörfler 2400d59a3d2SAxel Dörfler // sizes of inquiry fields 2410d59a3d2SAxel Dörfler #define SCSI_VUHBA 14 /* Vendor Unique HBA length */ 2420d59a3d2SAxel Dörfler #define SCSI_SIM_ID 16 /* ASCII string len for SIM ID */ 2430d59a3d2SAxel Dörfler #define SCSI_HBA_ID 16 /* ASCII string len for HBA ID */ 2440d59a3d2SAxel Dörfler #define SCSI_FAM_ID 16 /* ASCII string len for FAMILY ID */ 2450d59a3d2SAxel Dörfler #define SCSI_TYPE_ID 16 /* ASCII string len for TYPE ID */ 2460d59a3d2SAxel Dörfler #define SCSI_VERS 8 /* ASCII string len for SIM & HBA vers */ 2470d59a3d2SAxel Dörfler 2480d59a3d2SAxel Dörfler 2490d59a3d2SAxel Dörfler // Path inquiry, extended by BeOS XPT_EXTENDED_PATH_INQ parameters 2506be1e37dSAxel Dörfler typedef struct { 2510d59a3d2SAxel Dörfler uchar version_num; /* Version number for the SIM/HBA */ 2520d59a3d2SAxel Dörfler uchar hba_inquiry; /* Mimic of INQ byte 7 for the HBA */ 2530d59a3d2SAxel Dörfler uchar hba_misc; /* Misc HBA feature flags */ 2540d59a3d2SAxel Dörfler uchar vuhba_flags[SCSI_VUHBA];/* Vendor unique capabilities */ 2550d59a3d2SAxel Dörfler uchar initiator_id; /* ID of the HBA on the SCSI bus */ 256786a38f5SJérôme Duval uint32 hba_queue_size; // size of adapters command queue 2570d59a3d2SAxel Dörfler char sim_vid[SCSI_SIM_ID]; /* Vendor ID of the SIM */ 2580d59a3d2SAxel Dörfler char hba_vid[SCSI_HBA_ID]; /* Vendor ID of the HBA */ 2590d59a3d2SAxel Dörfler 2600d59a3d2SAxel Dörfler char sim_version[SCSI_VERS]; /* SIM version number */ 2610d59a3d2SAxel Dörfler char hba_version[SCSI_VERS]; /* HBA version number */ 2620d59a3d2SAxel Dörfler char controller_family[SCSI_FAM_ID]; /* Controller family */ 2630d59a3d2SAxel Dörfler char controller_type[SCSI_TYPE_ID]; /* Controller type */ 2640d59a3d2SAxel Dörfler } scsi_path_inquiry; 2650d59a3d2SAxel Dörfler 2660d59a3d2SAxel Dörfler 2670d59a3d2SAxel Dörfler // Device node 2680d59a3d2SAxel Dörfler 2690d59a3d2SAxel Dörfler // target (uint8) 2700d59a3d2SAxel Dörfler #define SCSI_DEVICE_TARGET_ID_ITEM "scsi/target_id" 2710d59a3d2SAxel Dörfler // lun (uint8) 2720d59a3d2SAxel Dörfler #define SCSI_DEVICE_TARGET_LUN_ITEM "scsi/target_lun" 2730d59a3d2SAxel Dörfler // node type 2740d59a3d2SAxel Dörfler #define SCSI_DEVICE_TYPE_NAME "scsi/device/v1" 2750d59a3d2SAxel Dörfler // device inquiry data (raw scsi_res_inquiry) 2760d59a3d2SAxel Dörfler #define SCSI_DEVICE_INQUIRY_ITEM "scsi/device_inquiry" 2770d59a3d2SAxel Dörfler // device type (uint8) 2780d59a3d2SAxel Dörfler #define SCSI_DEVICE_TYPE_ITEM "scsi/type" 2790d59a3d2SAxel Dörfler // vendor name (string) 2800d59a3d2SAxel Dörfler #define SCSI_DEVICE_VENDOR_ITEM "scsi/vendor" 2810d59a3d2SAxel Dörfler // product name (string) 2820d59a3d2SAxel Dörfler #define SCSI_DEVICE_PRODUCT_ITEM "scsi/product" 2830d59a3d2SAxel Dörfler // revision (string) 2840d59a3d2SAxel Dörfler #define SCSI_DEVICE_REVISION_ITEM "scsi/revision" 2850d59a3d2SAxel Dörfler 286402a4a4eSMarcus Overhagen // maximum targets on scsi bus 287402a4a4eSMarcus Overhagen #define SCSI_DEVICE_MAX_TARGET_COUNT "scsi/max_target_count" 288a0f12421SJérôme Duval // maximum luns on scsi bus 289a0f12421SJérôme Duval #define SCSI_DEVICE_MAX_LUN_COUNT "scsi/max_lun_count" 290402a4a4eSMarcus Overhagen 2910d59a3d2SAxel Dörfler // directory containing links to peripheral drivers 2920d59a3d2SAxel Dörfler #define SCSI_PERIPHERAL_DRIVERS_DIR "scsi" 2930d59a3d2SAxel Dörfler 2940d59a3d2SAxel Dörfler // bus manager device interface for peripheral driver 2950d59a3d2SAxel Dörfler typedef struct scsi_device_interface { 296b83a8af4SAxel Dörfler driver_module_info info; 2970d59a3d2SAxel Dörfler 2980d59a3d2SAxel Dörfler scsi_ccb *(*alloc_ccb)(scsi_device device); 2990d59a3d2SAxel Dörfler void (*free_ccb)(scsi_ccb *ccb); 3000d59a3d2SAxel Dörfler 3010d59a3d2SAxel Dörfler // execute command asynchronously 302*77463640SAugustin Cavalier // when it's finished, the condvar of the ccb is released 3030d59a3d2SAxel Dörfler // you must provide a S/G list if data_len != 0 3040d59a3d2SAxel Dörfler void (*async_io)(scsi_ccb *ccb); 3050d59a3d2SAxel Dörfler // execute command synchronously 3060d59a3d2SAxel Dörfler // you don't need to provide a S/G list nor have to lock data 3070d59a3d2SAxel Dörfler void (*sync_io)(scsi_ccb *ccb); 3080d59a3d2SAxel Dörfler 3090d59a3d2SAxel Dörfler // abort request 3100d59a3d2SAxel Dörfler uchar (*abort)(scsi_ccb *ccb_to_abort); 3110d59a3d2SAxel Dörfler // reset device 3120d59a3d2SAxel Dörfler uchar (*reset_device)(scsi_device device); 3130d59a3d2SAxel Dörfler // terminate request 3140d59a3d2SAxel Dörfler uchar (*term_io)(scsi_ccb *ccb_to_terminate); 315c9fc73fcSAxel Dörfler 316c9fc73fcSAxel Dörfler status_t (*ioctl)(scsi_device device, uint32 op, void *buffer, size_t length); 3170d59a3d2SAxel Dörfler } scsi_device_interface; 3180d59a3d2SAxel Dörfler 319368167edSAxel Dörfler #define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/device/driver_v1" 3200d59a3d2SAxel Dörfler 3210d59a3d2SAxel Dörfler 3220d59a3d2SAxel Dörfler // Bus node 3230d59a3d2SAxel Dörfler 3240d59a3d2SAxel Dörfler // attributes: 3250d59a3d2SAxel Dörfler 3260d59a3d2SAxel Dörfler // path (uint8) 3270d59a3d2SAxel Dörfler #define SCSI_BUS_PATH_ID_ITEM "scsi/path_id" 3280d59a3d2SAxel Dörfler // node type 3290d59a3d2SAxel Dörfler #define SCSI_BUS_TYPE_NAME "scsi/bus" 3300d59a3d2SAxel Dörfler 3310d59a3d2SAxel Dörfler // SCSI bus node driver. 3320d59a3d2SAxel Dörfler // This interface can be used by peripheral drivers to access the 3330d59a3d2SAxel Dörfler // bus directly. 3340d59a3d2SAxel Dörfler typedef struct scsi_bus_interface { 335368167edSAxel Dörfler driver_module_info info; 3360d59a3d2SAxel Dörfler 3370d59a3d2SAxel Dörfler // get information about host controller 3380d59a3d2SAxel Dörfler uchar (*path_inquiry)(scsi_bus bus, scsi_path_inquiry *inquiry_data); 3390d59a3d2SAxel Dörfler // reset SCSI bus 3400d59a3d2SAxel Dörfler uchar (*reset_bus)(scsi_bus bus); 3410d59a3d2SAxel Dörfler } scsi_bus_interface; 3420d59a3d2SAxel Dörfler 3430d59a3d2SAxel Dörfler // name of SCSI bus node driver 344368167edSAxel Dörfler #define SCSI_BUS_MODULE_NAME "bus_managers/scsi/bus/driver_v1" 3450d59a3d2SAxel Dörfler 3460d59a3d2SAxel Dörfler 3470d59a3d2SAxel Dörfler // Interface for SIM 3480d59a3d2SAxel Dörfler 3490d59a3d2SAxel Dörfler // cookie for dpc 3500d59a3d2SAxel Dörfler typedef struct scsi_dpc_info *scsi_dpc_cookie; 3510d59a3d2SAxel Dörfler 3520d59a3d2SAxel Dörfler // Bus manager interface used by SCSI controller drivers. 3530d59a3d2SAxel Dörfler // SCSI controller drivers get this interface passed via their init_device 3540d59a3d2SAxel Dörfler // method. Further, they must specify this driver as their fixed consumer. 3550d59a3d2SAxel Dörfler typedef struct scsi_for_sim_interface { 356b83a8af4SAxel Dörfler driver_module_info info; 3570d59a3d2SAxel Dörfler 3580d59a3d2SAxel Dörfler // put request into wait queue because of overflow 3590d59a3d2SAxel Dörfler // bus_overflow: true - too many bus requests 3600d59a3d2SAxel Dörfler // false - too many device requests 3610d59a3d2SAxel Dörfler // bus/device won't receive requests until cont_sent_bus/cont_send_device 3620d59a3d2SAxel Dörfler // is called or a request is finished via finished(); 3630d59a3d2SAxel Dörfler // to avoid race conditions (reporting a full and a available bus at once) 3640d59a3d2SAxel Dörfler // the SIM should synchronize calls to requeue, resubmit and finished 3650d59a3d2SAxel Dörfler void (*requeue)(scsi_ccb *ccb, bool bus_overflow); 3660d59a3d2SAxel Dörfler // resubmit request ASAP 3670d59a3d2SAxel Dörfler // to be used if execution of request went wrong and must be retried 3680d59a3d2SAxel Dörfler void (*resubmit)(scsi_ccb *ccb); 3690d59a3d2SAxel Dörfler // mark request as being finished 3700d59a3d2SAxel Dörfler // num_requests: number of requests that were handled by device 3710d59a3d2SAxel Dörfler // when the request was sent (read: how full was the device 3720d59a3d2SAxel Dörfler // queue); needed to find out how large the device queue is; 3730d59a3d2SAxel Dörfler // e.g. if three were already running plus this request makes 3740d59a3d2SAxel Dörfler // num_requests=4 3750d59a3d2SAxel Dörfler void (*finished)(scsi_ccb *ccb, uint num_requests); 3760d59a3d2SAxel Dörfler 3770d59a3d2SAxel Dörfler // following functions return error on invalid arguments only 3780d59a3d2SAxel Dörfler status_t (*alloc_dpc)(scsi_dpc_cookie *dpc); 3790d59a3d2SAxel Dörfler status_t (*free_dpc)(scsi_dpc_cookie dpc); 3800d59a3d2SAxel Dörfler status_t (*schedule_dpc)(scsi_bus cookie, scsi_dpc_cookie dpc, /*int flags,*/ 3810d59a3d2SAxel Dörfler void (*func)( void * ), void *arg); 3820d59a3d2SAxel Dörfler 3830d59a3d2SAxel Dörfler // block entire bus (can be nested) 3840d59a3d2SAxel Dörfler // no more request will be submitted to this bus 3850d59a3d2SAxel Dörfler void (*block_bus)(scsi_bus bus); 3860d59a3d2SAxel Dörfler // unblock entire bus 3870d59a3d2SAxel Dörfler // requests will be submitted to bus ASAP 3880d59a3d2SAxel Dörfler void (*unblock_bus)(scsi_bus bus); 3890d59a3d2SAxel Dörfler // block one device 3900d59a3d2SAxel Dörfler // no more requests will be submitted to this device 3910d59a3d2SAxel Dörfler void (*block_device)(scsi_device device); 3920d59a3d2SAxel Dörfler // unblock device 3930d59a3d2SAxel Dörfler // requests for this device will be submitted ASAP 3940d59a3d2SAxel Dörfler void (*unblock_device)(scsi_device device); 3950d59a3d2SAxel Dörfler 3960d59a3d2SAxel Dörfler // terminate bus overflow condition (see "requeue") 3970d59a3d2SAxel Dörfler void (*cont_send_bus)(scsi_bus bus); 3980d59a3d2SAxel Dörfler // terminate device overflow condition (see "requeue") 3990d59a3d2SAxel Dörfler void (*cont_send_device)(scsi_device device); 4000d59a3d2SAxel Dörfler } scsi_for_sim_interface; 4010d59a3d2SAxel Dörfler 4020d59a3d2SAxel Dörfler 403368167edSAxel Dörfler #define SCSI_FOR_SIM_MODULE_NAME "bus_managers/scsi/sim/driver_v1" 4040d59a3d2SAxel Dörfler 4050d59a3d2SAxel Dörfler 4060d59a3d2SAxel Dörfler // SIM Node 4070d59a3d2SAxel Dörfler 4080d59a3d2SAxel Dörfler // attributes: 4090d59a3d2SAxel Dörfler 4100d59a3d2SAxel Dörfler // node type 4110d59a3d2SAxel Dörfler #define SCSI_SIM_TYPE_NAME "bus/scsi/v1" 4120d59a3d2SAxel Dörfler // controller name (required, string) 4130d59a3d2SAxel Dörfler #define SCSI_DESCRIPTION_CONTROLLER_NAME "controller_name" 4140d59a3d2SAxel Dörfler 415c42a837eSMarcus Overhagen typedef void *scsi_sim_cookie; 4160d59a3d2SAxel Dörfler 4170d59a3d2SAxel Dörfler // SIM interface 4180d59a3d2SAxel Dörfler // SCSI controller drivers must provide this interface 4190d59a3d2SAxel Dörfler typedef struct scsi_sim_interface { 420b83a8af4SAxel Dörfler driver_module_info info; 4210d59a3d2SAxel Dörfler 422368167edSAxel Dörfler void (*set_scsi_bus)(scsi_sim_cookie cookie, scsi_bus bus); 423368167edSAxel Dörfler 4240d59a3d2SAxel Dörfler // execute request 4250d59a3d2SAxel Dörfler void (*scsi_io)(scsi_sim_cookie cookie, scsi_ccb *ccb); 4260d59a3d2SAxel Dörfler // abort request 4270d59a3d2SAxel Dörfler uchar (*abort)(scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort); 4280d59a3d2SAxel Dörfler // reset device 4290d59a3d2SAxel Dörfler uchar (*reset_device)(scsi_sim_cookie cookie, uchar target_id, uchar target_lun); 4300d59a3d2SAxel Dörfler // terminate request 4310d59a3d2SAxel Dörfler uchar (*term_io)(scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate); 4320d59a3d2SAxel Dörfler 4330d59a3d2SAxel Dörfler // get information about bus 4340d59a3d2SAxel Dörfler uchar (*path_inquiry)(scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data); 4350d59a3d2SAxel Dörfler // scan bus 4360d59a3d2SAxel Dörfler // this is called immediately before the SCSI bus manager scans the bus 4370d59a3d2SAxel Dörfler uchar (*scan_bus)(scsi_sim_cookie cookie); 4380d59a3d2SAxel Dörfler // reset bus 4390d59a3d2SAxel Dörfler uchar (*reset_bus)(scsi_sim_cookie cookie); 4400d59a3d2SAxel Dörfler 4410d59a3d2SAxel Dörfler // get restrictions of one device 4420d59a3d2SAxel Dörfler // (used for non-SCSI transport protocols and bug fixes) 443368167edSAxel Dörfler void (*get_restrictions)(scsi_sim_cookie cookie, 4440d59a3d2SAxel Dörfler uchar target_id, // target id 4450d59a3d2SAxel Dörfler bool *is_atapi, // set to true if this is an ATAPI device that 4460d59a3d2SAxel Dörfler // needs some commands emulated 4470d59a3d2SAxel Dörfler bool *no_autosense, // set to true if there is no autosense; 4480d59a3d2SAxel Dörfler // the SCSI bus manager will request sense on 449f0d174e9SMarcus Overhagen // SCSI_REQ_CMP_ERR/SCSI_STATUS_CHECK_CONDITION 4500d59a3d2SAxel Dörfler uint32 *max_blocks ); // maximum number of blocks per transfer if > 0; 4510d59a3d2SAxel Dörfler // used for buggy devices that cannot handle 4520d59a3d2SAxel Dörfler // large transfers (read: ATAPI ZIP drives) 453c9fc73fcSAxel Dörfler 454c9fc73fcSAxel Dörfler status_t (*ioctl)(scsi_sim_cookie, uint8 targetID, uint32 op, void *buffer, size_t length); 4550d59a3d2SAxel Dörfler } scsi_sim_interface; 4560d59a3d2SAxel Dörfler 4570d59a3d2SAxel Dörfler 4586be1e37dSAxel Dörfler #endif /* _SCSI_BUSMANAGER_H */ 459