xref: /haiku/headers/os/drivers/bus/SCSI.h (revision c42a837e85acd1df39bb9560e63aeeb620fe114a)
10d59a3d2SAxel Dörfler /*
26be1e37dSAxel Dörfler  * Copyright 2004-2007, 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
910d59a3d2SAxel Dörfler 	SCSI_DEVICE_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>
970d59a3d2SAxel Dörfler #include <device_manager.h>
980d59a3d2SAxel Dörfler 
990d59a3d2SAxel Dörfler 
1000d59a3d2SAxel Dörfler #define SCSI_MAX_CDB_SIZE 16	// max size of cdb
1010d59a3d2SAxel Dörfler #define SCSI_MAX_SENSE_SIZE	64	// max size of sense data
1020d59a3d2SAxel Dörfler #define SCSI_SIM_PRIV	1536	// SIM private data; this may be a bit much but
1030d59a3d2SAxel Dörfler 								// we currently need that for the compatibility layer
1040d59a3d2SAxel Dörfler 
1050d59a3d2SAxel Dörfler // bus/device handle
1060d59a3d2SAxel Dörfler typedef struct scsi_bus_info *scsi_bus;
1070d59a3d2SAxel Dörfler typedef struct scsi_device_info *scsi_device;
1080d59a3d2SAxel Dörfler 
1090d59a3d2SAxel Dörfler 
1100d59a3d2SAxel Dörfler // structure of one scsi i/o CCB (command control block)
1116be1e37dSAxel Dörfler typedef struct scsi_ccb {
1120d59a3d2SAxel Dörfler 	struct scsi_ccb *next, *prev;	// internal
1130d59a3d2SAxel Dörfler 
1140d59a3d2SAxel Dörfler 	uchar		subsys_status;		// Returned subsystem status
1150d59a3d2SAxel Dörfler 	uchar		device_status;		// Returned scsi device status
1160d59a3d2SAxel Dörfler 
1170d59a3d2SAxel Dörfler 	uchar		path_id;			// Path ID for the request
1180d59a3d2SAxel Dörfler 	uchar		target_id;			// Target device ID
1190d59a3d2SAxel Dörfler 	uchar		target_lun;			// Target LUN number
1200d59a3d2SAxel Dörfler 	uint32		flags;				// Flags for operation of the subsystem
1210d59a3d2SAxel Dörfler 
1220d59a3d2SAxel Dörfler 	// released once after asynchronous execution of request;
1230d59a3d2SAxel Dörfler 	// initialised by alloc_ccb, can be replaced for action but
1240d59a3d2SAxel Dörfler 	// must be restored before returning via free_ccb
1250d59a3d2SAxel Dörfler 	sem_id		completion_sem;
1260d59a3d2SAxel Dörfler 
1270d59a3d2SAxel Dörfler 	uint8		cdb[SCSI_MAX_CDB_SIZE];  // command data block
1286be1e37dSAxel Dörfler 	uchar		cdb_length;			// length of command in bytes
1290d59a3d2SAxel Dörfler 	int64		sort;				// value of command to sort on (<0 means n/a)
1300d59a3d2SAxel Dörfler 	bigtime_t	timeout;			// timeout - 0 = use default
1310d59a3d2SAxel Dörfler 
1320d59a3d2SAxel Dörfler 	uchar		*data;				// pointer to data
1336be1e37dSAxel Dörfler 	const physical_entry *sg_list;	// scatter/gather list
1346be1e37dSAxel Dörfler 	uint16		sg_count;			// number of S/G entries
1356be1e37dSAxel Dörfler 	uint32		data_length;		// length of data
1360d59a3d2SAxel Dörfler 	int32		data_resid;			// data transfer residual length: 2's comp
1370d59a3d2SAxel Dörfler 
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 
1580d59a3d2SAxel Dörfler 	// private SIM data
1590d59a3d2SAxel Dörfler 	uchar		sim_state;			// set to zero when request is submitted first time
1600d59a3d2SAxel Dörfler 	uchar		sim_priv[SCSI_SIM_PRIV];	/* SIM private data area */
1610d59a3d2SAxel Dörfler } scsi_ccb;
1620d59a3d2SAxel Dörfler 
1630d59a3d2SAxel Dörfler 
1640d59a3d2SAxel Dörfler // Defines for the subsystem status field
1650d59a3d2SAxel Dörfler 
1660d59a3d2SAxel Dörfler #define	SCSI_REQ_INPROG			0x00	/* request is in progress */
1670d59a3d2SAxel Dörfler #define SCSI_REQ_CMP 			0x01	/* request completed w/out error */
1680d59a3d2SAxel Dörfler #define SCSI_REQ_ABORTED		0x02	/* request aborted by the host */
1690d59a3d2SAxel Dörfler #define SCSI_UA_ABORT			0x03	/* Unable to Abort request */
1700d59a3d2SAxel Dörfler #define SCSI_REQ_CMP_ERR		0x04	/* request completed with an err */
1710d59a3d2SAxel Dörfler #define SCSI_BUSY				0x05	/* subsystem is busy */
1720d59a3d2SAxel Dörfler #define SCSI_REQ_INVALID		0x06	/* request is invalid */
1730d59a3d2SAxel Dörfler #define SCSI_PATH_INVALID		0x07	/* Path ID supplied is invalid */
1740d59a3d2SAxel Dörfler #define SCSI_DEV_NOT_THERE		0x08	/* SCSI device not installed/there */
1750d59a3d2SAxel Dörfler #define SCSI_UA_TERMIO			0x09	/* Unable to Terminate I/O req */
1760d59a3d2SAxel Dörfler #define SCSI_SEL_TIMEOUT		0x0A	/* Target selection timeout */
1770d59a3d2SAxel Dörfler #define SCSI_CMD_TIMEOUT		0x0B	/* Command timeout */
1780d59a3d2SAxel Dörfler #define SCSI_MSG_REJECT_REC		0x0D	/* Message reject received */
1790d59a3d2SAxel Dörfler #define SCSI_SCSI_BUS_RESET		0x0E	/* SCSI bus reset sent/received */
1800d59a3d2SAxel Dörfler #define SCSI_UNCOR_PARITY		0x0F	/* Uncorrectable parity err occurred */
1810d59a3d2SAxel Dörfler #define SCSI_AUTOSENSE_FAIL		0x10	/* Autosense: Request sense cmd fail */
1820d59a3d2SAxel Dörfler #define SCSI_NO_HBA				0x11	/* No HBA detected Error */
1830d59a3d2SAxel Dörfler #define SCSI_DATA_RUN_ERR		0x12	/* Data overrun/underrun error */
1840d59a3d2SAxel Dörfler #define SCSI_UNEXP_BUSFREE		0x13	/* Unexpected BUS free */
1850d59a3d2SAxel Dörfler #define SCSI_SEQUENCE_FAIL		0x14	/* Target bus phase sequence failure */
1860d59a3d2SAxel Dörfler #define SCSI_PROVIDE_FAIL		0x16	/* Unable to provide requ. capability */
1870d59a3d2SAxel Dörfler #define SCSI_BDR_SENT			0x17	/* A SCSI BDR msg was sent to target */
1880d59a3d2SAxel Dörfler #define SCSI_REQ_TERMIO			0x18	/* request terminated by the host */
1890d59a3d2SAxel Dörfler #define SCSI_HBA_ERR			0x19	/* Unrecoverable host bus adaptor err*/
1900d59a3d2SAxel Dörfler #define SCSI_BUS_RESET_DENIED	0x1A	/* SCSI bus reset denied */
1910d59a3d2SAxel Dörfler 
1920d59a3d2SAxel Dörfler #define SCSI_IDE				0x33	/* Initiator Detected Error Received */
1930d59a3d2SAxel Dörfler #define SCSI_RESRC_UNAVAIL		0x34	/* Resource unavailable */
1940d59a3d2SAxel Dörfler #define SCSI_UNACKED_EVENT		0x35	/* Unacknowledged event by host */
1950d59a3d2SAxel Dörfler #define SCSI_LUN_INVALID		0x38	/* LUN supplied is invalid */
1960d59a3d2SAxel Dörfler #define SCSI_TID_INVALID		0x39	/* Target ID supplied is invalid */
1970d59a3d2SAxel Dörfler #define SCSI_FUNC_NOTAVAIL		0x3A	/* The requ. func is not available */
1980d59a3d2SAxel Dörfler #define SCSI_NO_NEXUS			0x3B	/* Nexus is not established */
1990d59a3d2SAxel Dörfler #define SCSI_IID_INVALID		0x3C	/* The initiator ID is invalid */
2000d59a3d2SAxel Dörfler #define SCSI_CDB_RECVD			0x3D	/* The SCSI CDB has been received */
2010d59a3d2SAxel Dörfler #define SCSI_LUN_ALLREADY_ENAB	0x3E	/* LUN already enabled */
2020d59a3d2SAxel Dörfler #define SCSI_SCSI_BUSY			0x3F	/* SCSI bus busy */
2030d59a3d2SAxel Dörfler 
2040d59a3d2SAxel Dörfler #define SCSI_AUTOSNS_VALID		0x80	/* Autosense data valid for target */
2050d59a3d2SAxel Dörfler 
2060d59a3d2SAxel Dörfler #define SCSI_SUBSYS_STATUS_MASK 0x3F	/* Mask bits for just the status # */
2070d59a3d2SAxel Dörfler 
2080d59a3d2SAxel Dörfler 
2090d59a3d2SAxel Dörfler // Defines for the flags field
2100d59a3d2SAxel Dörfler 
2110d59a3d2SAxel Dörfler #define SCSI_DIR_RESV			0x00000000	/* Data direction (00: reserved) */
2120d59a3d2SAxel Dörfler #define SCSI_DIR_IN				0x00000040	/* Data direction (01: DATA IN) */
2130d59a3d2SAxel Dörfler #define SCSI_DIR_OUT			0x00000080	/* Data direction (10: DATA OUT) */
2140d59a3d2SAxel Dörfler #define SCSI_DIR_NONE			0x000000C0	/* Data direction (11: no data) */
2150d59a3d2SAxel Dörfler #define SCSI_DIR_MASK			0x000000C0
2160d59a3d2SAxel Dörfler 
2170d59a3d2SAxel Dörfler #define SCSI_DIS_AUTOSENSE		0x00000020	/* Disable autosense feature */
2180d59a3d2SAxel Dörfler #define SCSI_ORDERED_QTAG		0x00000010	// ordered queue (cannot overtake/be overtaken)
2190d59a3d2SAxel Dörfler #define SCSI_DMA_SAFE			0x00000008	// set if data buffer is DMA approved
2200d59a3d2SAxel Dörfler 
2210d59a3d2SAxel Dörfler #define SCSI_DIS_DISCONNECT		0x00008000	/* Disable disconnect */
2220d59a3d2SAxel Dörfler #define SCSI_INITIATE_SYNC		0x00004000	/* Attempt Sync data xfer, and SDTR */
2230d59a3d2SAxel Dörfler #define SCSI_DIS_SYNC			0x00002000	/* Disable sync, go to async */
2240d59a3d2SAxel Dörfler #define SCSI_ENG_SYNC			0x00000200	/* Flush resid bytes before cmplt */
2250d59a3d2SAxel Dörfler 
2260d59a3d2SAxel Dörfler 
2270d59a3d2SAxel Dörfler // Defines for the Path Inquiry CCB fields
2280d59a3d2SAxel Dörfler 
2290d59a3d2SAxel Dörfler // flags in hba_inquiry
2300d59a3d2SAxel Dörfler #define SCSI_PI_MDP_ABLE		0x80	/* Supports MDP message */
2310d59a3d2SAxel Dörfler #define SCSI_PI_WIDE_32			0x40	/* Supports 32 bit wide SCSI */
2320d59a3d2SAxel Dörfler #define SCSI_PI_WIDE_16			0x20	/* Supports 16 bit wide SCSI */
2330d59a3d2SAxel Dörfler #define SCSI_PI_SDTR_ABLE		0x10	/* Supports SDTR message */
2340d59a3d2SAxel Dörfler #define SCSI_PI_TAG_ABLE		0x02	/* Supports tag queue message */
2350d59a3d2SAxel Dörfler #define SCSI_PI_SOFT_RST		0x01	/* Supports soft reset */
2360d59a3d2SAxel Dörfler 
2370d59a3d2SAxel Dörfler // flags in hba_misc
2380d59a3d2SAxel Dörfler #define SCSI_PIM_SCANHILO		0x80	/* Bus scans from ID 7 to ID 0 */
2390d59a3d2SAxel Dörfler #define SCSI_PIM_NOREMOVE		0x40	/* Removable dev not included in scan */
2400d59a3d2SAxel Dörfler 
2410d59a3d2SAxel Dörfler // sizes of inquiry fields
2420d59a3d2SAxel Dörfler #define SCSI_VUHBA		14				/* Vendor Unique HBA length */
2430d59a3d2SAxel Dörfler #define SCSI_SIM_ID		16				/* ASCII string len for SIM ID */
2440d59a3d2SAxel Dörfler #define SCSI_HBA_ID		16				/* ASCII string len for HBA ID */
2450d59a3d2SAxel Dörfler #define SCSI_FAM_ID		16				/* ASCII string len for FAMILY ID */
2460d59a3d2SAxel Dörfler #define SCSI_TYPE_ID	16				/* ASCII string len for TYPE ID */
2470d59a3d2SAxel Dörfler #define SCSI_VERS		 8				/* ASCII string len for SIM & HBA vers */
2480d59a3d2SAxel Dörfler 
2490d59a3d2SAxel Dörfler 
2500d59a3d2SAxel Dörfler // Path inquiry, extended by BeOS XPT_EXTENDED_PATH_INQ parameters
2516be1e37dSAxel Dörfler typedef struct {
2520d59a3d2SAxel Dörfler 	uchar		version_num;			/* Version number for the SIM/HBA */
2530d59a3d2SAxel Dörfler 	uchar		hba_inquiry;			/* Mimic of INQ byte 7 for the HBA */
2540d59a3d2SAxel Dörfler 	uchar		hba_misc;				/* Misc HBA feature flags */
2550d59a3d2SAxel Dörfler 	uint32		sim_priv;				/* Size of SIM private data area */
2560d59a3d2SAxel Dörfler 	uchar		vuhba_flags[SCSI_VUHBA];/* Vendor unique capabilities */
2570d59a3d2SAxel Dörfler 	uchar		initiator_id;			/* ID of the HBA on the SCSI bus */
2580d59a3d2SAxel Dörfler 	uint32		hba_queue_size;			// size of adapaters command queue
2590d59a3d2SAxel Dörfler 	char		sim_vid[SCSI_SIM_ID];	/* Vendor ID of the SIM */
2600d59a3d2SAxel Dörfler 	char		hba_vid[SCSI_HBA_ID];	/* Vendor ID of the HBA */
2610d59a3d2SAxel Dörfler 
2620d59a3d2SAxel Dörfler 	char		sim_version[SCSI_VERS];	/* SIM version number */
2630d59a3d2SAxel Dörfler 	char		hba_version[SCSI_VERS];	/* HBA version number */
2640d59a3d2SAxel Dörfler 	char		controller_family[SCSI_FAM_ID]; /* Controller family */
2650d59a3d2SAxel Dörfler 	char		controller_type[SCSI_TYPE_ID]; /* Controller type */
2660d59a3d2SAxel Dörfler } scsi_path_inquiry;
2670d59a3d2SAxel Dörfler 
2680d59a3d2SAxel Dörfler 
2690d59a3d2SAxel Dörfler // Device node
2700d59a3d2SAxel Dörfler 
2710d59a3d2SAxel Dörfler // target (uint8)
2720d59a3d2SAxel Dörfler #define SCSI_DEVICE_TARGET_ID_ITEM "scsi/target_id"
2730d59a3d2SAxel Dörfler // lun (uint8)
2740d59a3d2SAxel Dörfler #define SCSI_DEVICE_TARGET_LUN_ITEM "scsi/target_lun"
2750d59a3d2SAxel Dörfler // node type
2760d59a3d2SAxel Dörfler #define SCSI_DEVICE_TYPE_NAME "scsi/device/v1"
2770d59a3d2SAxel Dörfler // device inquiry data (raw scsi_res_inquiry)
2780d59a3d2SAxel Dörfler #define SCSI_DEVICE_INQUIRY_ITEM "scsi/device_inquiry"
2790d59a3d2SAxel Dörfler // device type (uint8)
2800d59a3d2SAxel Dörfler #define SCSI_DEVICE_TYPE_ITEM "scsi/type"
2810d59a3d2SAxel Dörfler // vendor name (string)
2820d59a3d2SAxel Dörfler #define SCSI_DEVICE_VENDOR_ITEM "scsi/vendor"
2830d59a3d2SAxel Dörfler // product name (string)
2840d59a3d2SAxel Dörfler #define SCSI_DEVICE_PRODUCT_ITEM "scsi/product"
2850d59a3d2SAxel Dörfler // revision (string)
2860d59a3d2SAxel Dörfler #define SCSI_DEVICE_REVISION_ITEM "scsi/revision"
2870d59a3d2SAxel Dörfler 
2880d59a3d2SAxel Dörfler // directory containing links to peripheral drivers
2890d59a3d2SAxel Dörfler #define SCSI_PERIPHERAL_DRIVERS_DIR "scsi"
2900d59a3d2SAxel Dörfler 
2910d59a3d2SAxel Dörfler // bus manager device interface for peripheral driver
2920d59a3d2SAxel Dörfler typedef struct scsi_device_interface {
293b83a8af4SAxel Dörfler 	driver_module_info info;
2940d59a3d2SAxel Dörfler 
2950d59a3d2SAxel Dörfler 	// get CCB
2960d59a3d2SAxel Dörfler 	// warning: if pool of CCBs is exhausted, this call is delayed until a
2970d59a3d2SAxel Dörfler 	// CCB is freed, so don't try to allocate more then one CCB at once!
2980d59a3d2SAxel Dörfler 	scsi_ccb *(*alloc_ccb)(scsi_device device);
2990d59a3d2SAxel Dörfler 	// free CCB
3000d59a3d2SAxel Dörfler 	void (*free_ccb)(scsi_ccb *ccb);
3010d59a3d2SAxel Dörfler 
3020d59a3d2SAxel Dörfler 	// execute command asynchronously
3030d59a3d2SAxel Dörfler 	// when it's finished, the semaphore of the ccb is released
3040d59a3d2SAxel Dörfler 	// you must provide a S/G list if data_len != 0
3050d59a3d2SAxel Dörfler 	void (*async_io)(scsi_ccb *ccb);
3060d59a3d2SAxel Dörfler 	// execute command synchronously
3070d59a3d2SAxel Dörfler 	// you don't need to provide a S/G list nor have to lock data
3080d59a3d2SAxel Dörfler 	void (*sync_io)(scsi_ccb *ccb);
3090d59a3d2SAxel Dörfler 
3100d59a3d2SAxel Dörfler 	// abort request
3110d59a3d2SAxel Dörfler 	uchar (*abort)(scsi_ccb *ccb_to_abort);
3120d59a3d2SAxel Dörfler 	// reset device
3130d59a3d2SAxel Dörfler 	uchar (*reset_device)(scsi_device device);
3140d59a3d2SAxel Dörfler 	// terminate request
3150d59a3d2SAxel Dörfler 	uchar (*term_io)(scsi_ccb *ccb_to_terminate);
316c9fc73fcSAxel Dörfler 
317c9fc73fcSAxel Dörfler 	status_t (*ioctl)(scsi_device device, uint32 op, void *buffer, size_t length);
3180d59a3d2SAxel Dörfler } scsi_device_interface;
3190d59a3d2SAxel Dörfler 
3200d59a3d2SAxel Dörfler #define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
3210d59a3d2SAxel Dörfler 
3220d59a3d2SAxel Dörfler 
3230d59a3d2SAxel Dörfler // Bus node
3240d59a3d2SAxel Dörfler 
3250d59a3d2SAxel Dörfler // attributes:
3260d59a3d2SAxel Dörfler 
3270d59a3d2SAxel Dörfler // path (uint8)
3280d59a3d2SAxel Dörfler #define SCSI_BUS_PATH_ID_ITEM "scsi/path_id"
3290d59a3d2SAxel Dörfler // node type
3300d59a3d2SAxel Dörfler #define SCSI_BUS_TYPE_NAME "scsi/bus"
3310d59a3d2SAxel Dörfler 
3320d59a3d2SAxel Dörfler // SCSI bus node driver.
3330d59a3d2SAxel Dörfler // This interface can be used by peripheral drivers to access the
3340d59a3d2SAxel Dörfler // bus directly.
3350d59a3d2SAxel Dörfler typedef struct scsi_bus_interface {
336b83a8af4SAxel Dörfler 	bus_module_info info;
3370d59a3d2SAxel Dörfler 
3380d59a3d2SAxel Dörfler 	// get information about host controller
3390d59a3d2SAxel Dörfler 	uchar (*path_inquiry)(scsi_bus bus, scsi_path_inquiry *inquiry_data);
3400d59a3d2SAxel Dörfler 	// reset SCSI bus
3410d59a3d2SAxel Dörfler 	uchar (*reset_bus)(scsi_bus bus);
3420d59a3d2SAxel Dörfler } scsi_bus_interface;
3430d59a3d2SAxel Dörfler 
3440d59a3d2SAxel Dörfler // name of SCSI bus node driver
3450d59a3d2SAxel Dörfler #define SCSI_BUS_MODULE_NAME "bus_managers/scsi/bus/v1"
3460d59a3d2SAxel Dörfler 
3470d59a3d2SAxel Dörfler 
3480d59a3d2SAxel Dörfler // Interface for SIM
3490d59a3d2SAxel Dörfler 
3500d59a3d2SAxel Dörfler // cookie for dpc
3510d59a3d2SAxel Dörfler typedef struct scsi_dpc_info *scsi_dpc_cookie;
3520d59a3d2SAxel Dörfler 
3530d59a3d2SAxel Dörfler // Bus manager interface used by SCSI controller drivers.
3540d59a3d2SAxel Dörfler // SCSI controller drivers get this interface passed via their init_device
3550d59a3d2SAxel Dörfler // method. Further, they must specify this driver as their fixed consumer.
3560d59a3d2SAxel Dörfler typedef struct scsi_for_sim_interface {
357b83a8af4SAxel Dörfler 	driver_module_info info;
3580d59a3d2SAxel Dörfler 
3590d59a3d2SAxel Dörfler 	// put request into wait queue because of overflow
3600d59a3d2SAxel Dörfler 	// bus_overflow: true - too many bus requests
3610d59a3d2SAxel Dörfler 	//               false - too many device requests
3620d59a3d2SAxel Dörfler 	// bus/device won't receive requests until cont_sent_bus/cont_send_device
3630d59a3d2SAxel Dörfler 	// is called or a request is finished via finished();
3640d59a3d2SAxel Dörfler 	// to avoid race conditions (reporting a full and a available bus at once)
3650d59a3d2SAxel Dörfler 	// the SIM should synchronize calls to requeue, resubmit and finished
3660d59a3d2SAxel Dörfler 	void (*requeue)(scsi_ccb *ccb, bool bus_overflow);
3670d59a3d2SAxel Dörfler 	// resubmit request ASAP
3680d59a3d2SAxel Dörfler 	// to be used if execution of request went wrong and must be retried
3690d59a3d2SAxel Dörfler 	void (*resubmit)(scsi_ccb *ccb);
3700d59a3d2SAxel Dörfler 	// mark request as being finished
3710d59a3d2SAxel Dörfler 	// num_requests: number of requests that were handled by device
3720d59a3d2SAxel Dörfler 	//               when the request was sent (read: how full was the device
3730d59a3d2SAxel Dörfler 	//               queue); needed to find out how large the device queue is;
3740d59a3d2SAxel Dörfler 	//               e.g. if three were already running plus this request makes
3750d59a3d2SAxel Dörfler 	//               num_requests=4
3760d59a3d2SAxel Dörfler 	void (*finished)(scsi_ccb *ccb, uint num_requests);
3770d59a3d2SAxel Dörfler 
3780d59a3d2SAxel Dörfler 	// following functions return error on invalid arguments only
3790d59a3d2SAxel Dörfler 	status_t (*alloc_dpc)(scsi_dpc_cookie *dpc);
3800d59a3d2SAxel Dörfler 	status_t (*free_dpc)(scsi_dpc_cookie dpc);
3810d59a3d2SAxel Dörfler 	status_t (*schedule_dpc)(scsi_bus cookie, scsi_dpc_cookie dpc, /*int flags,*/
3820d59a3d2SAxel Dörfler 		void (*func)( void * ), void *arg);
3830d59a3d2SAxel Dörfler 
3840d59a3d2SAxel Dörfler 	// block entire bus (can be nested)
3850d59a3d2SAxel Dörfler 	// no more request will be submitted to this bus
3860d59a3d2SAxel Dörfler 	void (*block_bus)(scsi_bus bus);
3870d59a3d2SAxel Dörfler 	// unblock entire bus
3880d59a3d2SAxel Dörfler 	// requests will be submitted to bus ASAP
3890d59a3d2SAxel Dörfler 	void (*unblock_bus)(scsi_bus bus);
3900d59a3d2SAxel Dörfler 	// block one device
3910d59a3d2SAxel Dörfler 	// no more requests will be submitted to this device
3920d59a3d2SAxel Dörfler 	void (*block_device)(scsi_device device);
3930d59a3d2SAxel Dörfler 	// unblock device
3940d59a3d2SAxel Dörfler 	// requests for this device will be submitted ASAP
3950d59a3d2SAxel Dörfler 	void (*unblock_device)(scsi_device device);
3960d59a3d2SAxel Dörfler 
3970d59a3d2SAxel Dörfler 	// terminate bus overflow condition (see "requeue")
3980d59a3d2SAxel Dörfler 	void (*cont_send_bus)(scsi_bus bus);
3990d59a3d2SAxel Dörfler 	// terminate device overflow condition (see "requeue")
4000d59a3d2SAxel Dörfler 	void (*cont_send_device)(scsi_device device);
4010d59a3d2SAxel Dörfler } scsi_for_sim_interface;
4020d59a3d2SAxel Dörfler 
4030d59a3d2SAxel Dörfler 
4040d59a3d2SAxel Dörfler #define SCSI_FOR_SIM_MODULE_NAME "bus_managers/scsi/sim/v1"
4050d59a3d2SAxel Dörfler 
4060d59a3d2SAxel Dörfler 
4070d59a3d2SAxel Dörfler // SIM Node
4080d59a3d2SAxel Dörfler 
4090d59a3d2SAxel Dörfler // attributes:
4100d59a3d2SAxel Dörfler 
4110d59a3d2SAxel Dörfler // node type
4120d59a3d2SAxel Dörfler #define SCSI_SIM_TYPE_NAME "bus/scsi/v1"
4130d59a3d2SAxel Dörfler // controller name (required, string)
4140d59a3d2SAxel Dörfler #define SCSI_DESCRIPTION_CONTROLLER_NAME "controller_name"
4150d59a3d2SAxel Dörfler 
416*c42a837eSMarcus Overhagen typedef void * scsi_sim_cookie;
4170d59a3d2SAxel Dörfler 
4180d59a3d2SAxel Dörfler // SIM interface
4190d59a3d2SAxel Dörfler // SCSI controller drivers must provide this interface
4200d59a3d2SAxel Dörfler typedef struct scsi_sim_interface {
421b83a8af4SAxel Dörfler 	driver_module_info info;
4220d59a3d2SAxel Dörfler 
4230d59a3d2SAxel Dörfler 	// execute request
4240d59a3d2SAxel Dörfler 	void (*scsi_io)( scsi_sim_cookie cookie, scsi_ccb *ccb );
4250d59a3d2SAxel Dörfler 	// abort request
4260d59a3d2SAxel Dörfler 	uchar (*abort)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort );
4270d59a3d2SAxel Dörfler 	// reset device
4280d59a3d2SAxel Dörfler 	uchar (*reset_device)( scsi_sim_cookie cookie, uchar target_id, uchar target_lun );
4290d59a3d2SAxel Dörfler 	// terminate request
4300d59a3d2SAxel Dörfler 	uchar (*term_io)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate );
4310d59a3d2SAxel Dörfler 
4320d59a3d2SAxel Dörfler 	// get information about bus
4330d59a3d2SAxel Dörfler 	uchar (*path_inquiry)( scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data );
4340d59a3d2SAxel Dörfler 	// scan bus
4350d59a3d2SAxel Dörfler 	// this is called immediately before the SCSI bus manager scans the bus
4360d59a3d2SAxel Dörfler 	uchar (*scan_bus)( scsi_sim_cookie cookie );
4370d59a3d2SAxel Dörfler 	// reset bus
4380d59a3d2SAxel Dörfler 	uchar (*reset_bus)( scsi_sim_cookie cookie );
4390d59a3d2SAxel Dörfler 
4400d59a3d2SAxel Dörfler 	// get restrictions of one device
4410d59a3d2SAxel Dörfler 	// (used for non-SCSI transport protocols and bug fixes)
4420d59a3d2SAxel Dörfler 	void (*get_restrictions)(
4430d59a3d2SAxel Dörfler 		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
4490d59a3d2SAxel Dörfler 											// SCSI_REQ_CMP_ERR/SCSI_DEVICE_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