1139743Simp/*-
239212Sgibbs * Data structures and definitions for the CAM system.
339212Sgibbs *
439212Sgibbs * Copyright (c) 1997 Justin T. Gibbs.
539212Sgibbs * All rights reserved.
639212Sgibbs *
739212Sgibbs * Redistribution and use in source and binary forms, with or without
839212Sgibbs * modification, are permitted provided that the following conditions
939212Sgibbs * are met:
1039212Sgibbs * 1. Redistributions of source code must retain the above copyright
1139212Sgibbs *    notice, this list of conditions, and the following disclaimer,
1239212Sgibbs *    without modification, immediately at the beginning of the file.
1339212Sgibbs * 2. The name of the author may not be used to endorse or promote products
1439212Sgibbs *    derived from this software without specific prior written permission.
1539212Sgibbs *
1639212Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1739212Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1839212Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1939212Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2039212Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2139212Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2239212Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2339212Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2439212Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2539212Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2639212Sgibbs * SUCH DAMAGE.
2739212Sgibbs *
2850477Speter * $FreeBSD$
2939212Sgibbs */
3039212Sgibbs
3139212Sgibbs#ifndef _CAM_CAM_H
3239212Sgibbs#define _CAM_CAM_H 1
3339212Sgibbs
3455206Speter#ifdef _KERNEL
3539212Sgibbs#include <opt_cam.h>
3655206Speter#endif
3739212Sgibbs
3839212Sgibbs#include <sys/cdefs.h>
3939212Sgibbs
4039212Sgibbstypedef u_int path_id_t;
4139212Sgibbstypedef u_int target_id_t;
4239212Sgibbstypedef u_int lun_id_t;
43255870Sscottltypedef union {
44255870Sscottl	u_int64_t	lun64;
45255870Sscottl	u_int8_t	lun[8];
46255870Sscottl} lun64_id_t;
4739212Sgibbs
4839212Sgibbs#define	CAM_XPT_PATH_ID	((path_id_t)~0)
4939212Sgibbs#define	CAM_BUS_WILDCARD ((path_id_t)~0)
5039212Sgibbs#define	CAM_TARGET_WILDCARD ((target_id_t)~0)
5139212Sgibbs#define	CAM_LUN_WILDCARD ((lun_id_t)~0)
5239212Sgibbs
53259204Snwhitehorn#define CAM_EXTLUN_BYTE_SWIZZLE(lun) (	\
54259204Snwhitehorn	((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \
55259204Snwhitehorn	((((u_int64_t)lun) & 0x0000ffff00000000L) >> 16) | \
56259204Snwhitehorn	((((u_int64_t)lun) & 0x00000000ffff0000L) << 16) | \
57259204Snwhitehorn	((((u_int64_t)lun) & 0x000000000000ffffL) << 48))
58259204Snwhitehorn
5939212Sgibbs/*
6039212Sgibbs * Maximum length for a CAM CDB.
6139212Sgibbs */
6239212Sgibbs#define CAM_MAX_CDBLEN 16
6339212Sgibbs
6439212Sgibbs/*
6539212Sgibbs * Definition of a CAM peripheral driver entry.  Peripheral drivers instantiate
6639212Sgibbs * one of these for each device they wish to communicate with and pass it into
6739212Sgibbs * the xpt layer when they wish to schedule work on that device via the
6858111Sn_hibma * xpt_schedule API.
6939212Sgibbs */
7039212Sgibbsstruct cam_periph;
7139212Sgibbs
7239212Sgibbs/*
73203108Smav * Priority information for a CAM structure.
7439212Sgibbs */
75203108Smavtypedef enum {
76203108Smav    CAM_RL_HOST,
77203108Smav    CAM_RL_BUS,
78203108Smav    CAM_RL_XPT,
79203108Smav    CAM_RL_DEV,
80203108Smav    CAM_RL_NORMAL,
81203108Smav    CAM_RL_VALUES
82203108Smav} cam_rl;
83203108Smav/*
84203108Smav * The generation number is incremented everytime a new entry is entered into
85203108Smav * the queue giving round robin per priority level scheduling.
86203108Smav */
8739212Sgibbstypedef struct {
8839212Sgibbs	u_int32_t priority;
89203108Smav#define CAM_PRIORITY_HOST	((CAM_RL_HOST << 8) + 0x80)
90203108Smav#define CAM_PRIORITY_BUS	((CAM_RL_BUS << 8) + 0x80)
91203108Smav#define CAM_PRIORITY_XPT	((CAM_RL_XPT << 8) + 0x80)
92203108Smav#define CAM_PRIORITY_DEV	((CAM_RL_DEV << 8) + 0x80)
93249466Smav#define CAM_PRIORITY_OOB	(CAM_RL_DEV << 8)
94203108Smav#define CAM_PRIORITY_NORMAL	((CAM_RL_NORMAL << 8) + 0x80)
9539212Sgibbs#define CAM_PRIORITY_NONE	(u_int32_t)-1
9639212Sgibbs	u_int32_t generation;
9739212Sgibbs	int       index;
9839212Sgibbs#define CAM_UNQUEUED_INDEX	-1
9939212Sgibbs#define CAM_ACTIVE_INDEX	-2
10039212Sgibbs#define CAM_DONEQ_INDEX		-3
101253958Smav#define CAM_EXTRAQ_INDEX	INT_MAX
10239212Sgibbs} cam_pinfo;
10339212Sgibbs
10445441Sgibbs/*
10545441Sgibbs * Macro to compare two generation numbers.  It is used like this:
10645441Sgibbs *
10745441Sgibbs *	if (GENERATIONCMP(a, >=, b))
10845441Sgibbs *		...;
10945441Sgibbs *
11045441Sgibbs * GERERATIONCMP uses modular arithmetic to guard against wraps
11145441Sgibbs * wraps in the generation number.
11245441Sgibbs */
11345441Sgibbs#define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0)
11445441Sgibbs
11574840Sken/* CAM flags XXX Move to cam_periph.h ??? */
11639212Sgibbstypedef enum {
11739212Sgibbs	CAM_FLAG_NONE		= 0x00,
11874840Sken	CAM_EXPECT_INQ_CHANGE	= 0x01,
11974840Sken	CAM_RETRY_SELTO		= 0x02 /* Retry Selection Timeouts */
12039212Sgibbs} cam_flags;
12139212Sgibbs
122236814Smavenum {
123236814Smav	SF_RETRY_UA		= 0x01,	/* Retry UNIT ATTENTION conditions. */
124236814Smav	SF_NO_PRINT		= 0x02,	/* Never print error status. */
125236814Smav	SF_QUIET_IR		= 0x04,	/* Be quiet about Illegal Request reponses */
126236814Smav	SF_PRINT_ALWAYS		= 0x08,	/* Always print error status. */
127236814Smav	SF_NO_RECOVERY		= 0x10,	/* Don't do active error recovery. */
128236814Smav	SF_NO_RETRY		= 0x20	/* Don't do any retries. */
129236814Smav};
130236814Smav
13139212Sgibbs/* CAM  Status field values */
13239212Sgibbstypedef enum {
133255870Sscottl	/* CCB request is in progress */
134255870Sscottl	CAM_REQ_INPROG		= 0x00,
13539212Sgibbs
136255870Sscottl	/* CCB request completed without error */
137255870Sscottl	CAM_REQ_CMP		= 0x01,
13839212Sgibbs
139255870Sscottl	/* CCB request aborted by the host */
140255870Sscottl	CAM_REQ_ABORTED		= 0x02,
14139212Sgibbs
142255870Sscottl	/* Unable to abort CCB request */
143255870Sscottl	CAM_UA_ABORT		= 0x03,
14456143Smjacob
145255870Sscottl	/* CCB request completed with an error */
146255870Sscottl	CAM_REQ_CMP_ERR		= 0x04,
147255870Sscottl
148255870Sscottl	/* CAM subsystem is busy */
149255870Sscottl	CAM_BUSY		= 0x05,
150255870Sscottl
151255870Sscottl	/* CCB request was invalid */
152255870Sscottl	CAM_REQ_INVALID		= 0x06,
153255870Sscottl
154255870Sscottl	/* Supplied Path ID is invalid */
155255870Sscottl	CAM_PATH_INVALID	= 0x07,
156255870Sscottl
157255870Sscottl	/* SCSI Device Not Installed/there */
158255870Sscottl	CAM_DEV_NOT_THERE	= 0x08,
159255870Sscottl
160255870Sscottl	/* Unable to terminate I/O CCB request */
161255870Sscottl	CAM_UA_TERMIO		= 0x09,
162255870Sscottl
163255870Sscottl	/* Target Selection Timeout */
164255870Sscottl	CAM_SEL_TIMEOUT		= 0x0a,
165255870Sscottl
166255870Sscottl	/* Command timeout */
167255870Sscottl	CAM_CMD_TIMEOUT		= 0x0b,
168255870Sscottl
169255870Sscottl	/* SCSI error, look at error code in CCB */
170255870Sscottl	CAM_SCSI_STATUS_ERROR	= 0x0c,
171255870Sscottl
172255870Sscottl	/* Message Reject Received */
173255870Sscottl	CAM_MSG_REJECT_REC	= 0x0d,
174255870Sscottl
175255870Sscottl	/* SCSI Bus Reset Sent/Received */
176255870Sscottl	CAM_SCSI_BUS_RESET	= 0x0e,
177255870Sscottl
178255870Sscottl	/* Uncorrectable parity error occurred */
179255870Sscottl	CAM_UNCOR_PARITY	= 0x0f,
180255870Sscottl
181255870Sscottl	/* Autosense: request sense cmd fail */
182255870Sscottl	CAM_AUTOSENSE_FAIL	= 0x10,
183255870Sscottl
184255870Sscottl	/* No HBA Detected error */
185255870Sscottl	CAM_NO_HBA		= 0x11,
186255870Sscottl
187255870Sscottl	/* Data Overrun error */
188255870Sscottl	CAM_DATA_RUN_ERR	= 0x12,
189255870Sscottl
190255870Sscottl	/* Unexpected Bus Free */
191255870Sscottl	CAM_UNEXP_BUSFREE	= 0x13,
192255870Sscottl
193255870Sscottl	/* Target Bus Phase Sequence Failure */
194255870Sscottl	CAM_SEQUENCE_FAIL	= 0x14,
195255870Sscottl
196255870Sscottl	/* CCB length supplied is inadequate */
197255870Sscottl	CAM_CCB_LEN_ERR		= 0x15,
198255870Sscottl
199255870Sscottl	/* Unable to provide requested capability*/
200255870Sscottl	CAM_PROVIDE_FAIL	= 0x16,
201255870Sscottl
202255870Sscottl	/* A SCSI BDR msg was sent to target */
203255870Sscottl	CAM_BDR_SENT		= 0x17,
204255870Sscottl
205255870Sscottl	/* CCB request terminated by the host */
206255870Sscottl	CAM_REQ_TERMIO		= 0x18,
207255870Sscottl
208255870Sscottl	/* Unrecoverable Host Bus Adapter Error */
209255870Sscottl	CAM_UNREC_HBA_ERROR	= 0x19,
210255870Sscottl
211255870Sscottl	/* Request was too large for this host */
212255870Sscottl	CAM_REQ_TOO_BIG		= 0x1a,
213255870Sscottl
214255870Sscottl	/*
215255870Sscottl	 * This request should be requeued to preserve
216255870Sscottl	 * transaction ordering.  This typically occurs
217255870Sscottl	 * when the SIM recognizes an error that should
218255870Sscottl	 * freeze the queue and must place additional
219255870Sscottl	 * requests for the target at the sim level
220255870Sscottl	 * back into the XPT queue.
221255870Sscottl	 */
222255870Sscottl	CAM_REQUEUE_REQ		= 0x1b,
223255870Sscottl
224255870Sscottl	/* ATA error, look at error code in CCB */
225255870Sscottl	CAM_ATA_STATUS_ERROR	= 0x1c,
226255870Sscottl
227255870Sscottl	/* Initiator/Target Nexus lost. */
228255870Sscottl	CAM_SCSI_IT_NEXUS_LOST	= 0x1d,
229255870Sscottl
230255870Sscottl	/* SMP error, look at error code in CCB */
231255870Sscottl	CAM_SMP_STATUS_ERROR	= 0x1e,
232255870Sscottl
233255870Sscottl	/*
234255870Sscottl	 * Command completed without error but  exceeded the soft
235255870Sscottl	 * timeout threshold.
236255870Sscottl	 */
237255870Sscottl	CAM_REQ_SOFTTIMEOUT	= 0x1f,
238255870Sscottl
239255870Sscottl	/*
240255870Sscottl	 * 0x20 - 0x32 are unassigned
241255870Sscottl	 */
242255870Sscottl
243255870Sscottl	/* Initiator Detected Error */
244255870Sscottl	CAM_IDE			= 0x33,
245255870Sscottl
246255870Sscottl	/* Resource Unavailable */
247255870Sscottl	CAM_RESRC_UNAVAIL	= 0x34,
248255870Sscottl
249255870Sscottl	/* Unacknowledged Event by Host */
250255870Sscottl	CAM_UNACKED_EVENT	= 0x35,
251255870Sscottl
252255870Sscottl	/* Message Received in Host Target Mode */
253255870Sscottl	CAM_MESSAGE_RECV	= 0x36,
254255870Sscottl
255255870Sscottl	/* Invalid CDB received in Host Target Mode */
256255870Sscottl	CAM_INVALID_CDB		= 0x37,
257255870Sscottl
258255870Sscottl	/* Lun supplied is invalid */
259255870Sscottl	CAM_LUN_INVALID		= 0x38,
260255870Sscottl
261255870Sscottl	/* Target ID supplied is invalid */
262255870Sscottl	CAM_TID_INVALID		= 0x39,
263255870Sscottl
264255870Sscottl	/* The requested function is not available */
265255870Sscottl	CAM_FUNC_NOTAVAIL	= 0x3a,
266255870Sscottl
267255870Sscottl	/* Nexus is not established */
268255870Sscottl	CAM_NO_NEXUS		= 0x3b,
269255870Sscottl
270255870Sscottl	/* The initiator ID is invalid */
271255870Sscottl	CAM_IID_INVALID		= 0x3c,
272255870Sscottl
273255870Sscottl	/* The SCSI CDB has been received */
274255870Sscottl	CAM_CDB_RECVD		= 0x3d,
275255870Sscottl
276255870Sscottl	/* The LUN is already enabled for target mode */
277255870Sscottl	CAM_LUN_ALRDY_ENA	= 0x3e,
278255870Sscottl
279255870Sscottl	/* SCSI Bus Busy */
280255870Sscottl	CAM_SCSI_BUSY		= 0x3f,
281255870Sscottl
282255870Sscottl
283255870Sscottl	/*
284255870Sscottl	 * Flags
285255870Sscottl	 */
286255870Sscottl
287255870Sscottl	/* The DEV queue is frozen w/this err */
288255870Sscottl	CAM_DEV_QFRZN		= 0x40,
289255870Sscottl
290255870Sscottl	/* Autosense data valid for target */
291255870Sscottl	CAM_AUTOSNS_VALID	= 0x80,
292255870Sscottl
293255870Sscottl	/* SIM ready to take more commands */
294255870Sscottl	CAM_RELEASE_SIMQ	= 0x100,
295255870Sscottl
296255870Sscottl	/* SIM has this command in it's queue */
297255870Sscottl	CAM_SIM_QUEUED		= 0x200,
298255870Sscottl
299255870Sscottl	/* Quality of service data is valid */
300255870Sscottl	CAM_QOS_VALID		= 0x400,
301255870Sscottl
302255870Sscottl	/* Mask bits for just the status # */
303255870Sscottl	CAM_STATUS_MASK = 0x3F,
304255870Sscottl
305255870Sscottl	/*
306255870Sscottl	 * Target Specific Adjunct Status
307255870Sscottl	 */
308255870Sscottl
309255870Sscottl	/* sent sense with status */
310255870Sscottl	CAM_SENT_SENSE		= 0x40000000
31139212Sgibbs} cam_status;
31239212Sgibbs
31374840Skentypedef enum {
31474840Sken	CAM_ESF_NONE		= 0x00,
31574840Sken	CAM_ESF_COMMAND		= 0x01,
31674840Sken	CAM_ESF_CAM_STATUS	= 0x02,
31774840Sken	CAM_ESF_PROTO_STATUS	= 0x04,
31874840Sken	CAM_ESF_ALL		= 0xff
31974840Sken} cam_error_string_flags;
32074840Sken
32174840Skentypedef enum {
32274840Sken	CAM_EPF_NONE		= 0x00,
32374840Sken	CAM_EPF_MINIMAL		= 0x01,
32474840Sken	CAM_EPF_NORMAL		= 0x02,
32574840Sken	CAM_EPF_ALL		= 0x03,
32674840Sken	CAM_EPF_LEVEL_MASK	= 0x0f
32774840Sken	/* All bits above bit 3 are protocol-specific */
32874840Sken} cam_error_proto_flags;
32974840Sken
33074840Skentypedef enum {
33174840Sken	CAM_ESF_PRINT_NONE	= 0x00,
33274840Sken	CAM_ESF_PRINT_STATUS	= 0x10,
33374840Sken	CAM_ESF_PRINT_SENSE	= 0x20
33474840Sken} cam_error_scsi_flags;
33574840Sken
336198849Smavtypedef enum {
337216088Sken	CAM_ESMF_PRINT_NONE	= 0x00,
338216088Sken	CAM_ESMF_PRINT_STATUS	= 0x10,
339216088Sken	CAM_ESMF_PRINT_FULL_CMD	= 0x20,
340216088Sken} cam_error_smp_flags;
341216088Sken
342216088Skentypedef enum {
343198849Smav	CAM_EAF_PRINT_NONE	= 0x00,
344198849Smav	CAM_EAF_PRINT_STATUS	= 0x10,
345198849Smav	CAM_EAF_PRINT_RESULT	= 0x20
346198849Smav} cam_error_ata_flags;
347198849Smav
34874840Skenstruct cam_status_entry
34974840Sken{
35074840Sken	cam_status  status_code;
35174840Sken	const char *status_text;
35274840Sken};
35374840Sken
35474840Skenextern const struct cam_status_entry cam_status_table[];
35574840Skenextern const int num_cam_status_entries;
356248922Ssmh#ifdef _KERNEL
357248922Ssmhextern int cam_sort_io_queues;
358248922Ssmh#endif
35974840Skenunion ccb;
36074840Sken
36189114Smsmith#ifdef SYSCTL_DECL	/* from sysctl.h */
36289114SmsmithSYSCTL_DECL(_kern_cam);
36389114Smsmith#endif
36489114Smsmith
36539212Sgibbs__BEGIN_DECLS
36639212Sgibbstypedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
36739212Sgibbs
36839212Sgibbscaddr_t	cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
36939212Sgibbs		       int entry_size, cam_quirkmatch_t *comp_func);
37039212Sgibbs
37139212Sgibbsvoid	cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
37239212Sgibbs
37339212Sgibbsint	cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
37474840Skenconst struct cam_status_entry*
37574840Sken	cam_fetch_status_entry(cam_status status);
37674840Sken#ifdef _KERNEL
37774840Skenchar *	cam_error_string(union ccb *ccb, char *str, int str_len,
37874840Sken			 cam_error_string_flags flags,
37974840Sken			 cam_error_proto_flags proto_flags);
38074840Skenvoid	cam_error_print(union ccb *ccb, cam_error_string_flags flags,
38174840Sken			cam_error_proto_flags proto_flags);
38274840Sken#else /* _KERNEL */
38374840Skenstruct cam_device;
38474840Sken
38574840Skenchar *	cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
38674840Sken			 int str_len, cam_error_string_flags flags,
38774840Sken			 cam_error_proto_flags proto_flags);
38874840Skenvoid	cam_error_print(struct cam_device *device, union ccb *ccb,
38974840Sken			cam_error_string_flags flags,
39074840Sken			cam_error_proto_flags proto_flags, FILE *ofile);
39174840Sken#endif /* _KERNEL */
39239212Sgibbs__END_DECLS
39339212Sgibbs
39455206Speter#ifdef _KERNEL
39539212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo);
39639212Sgibbs
39739212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo)
39839212Sgibbs{
39939212Sgibbs	pinfo->priority = CAM_PRIORITY_NONE;
40039212Sgibbs	pinfo->index = CAM_UNQUEUED_INDEX;
40139212Sgibbs}
40255206Speter#endif
40339212Sgibbs
40439212Sgibbs#endif /* _CAM_CAM_H */
405