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;
42259397Snwhitehorntypedef u_int64_t lun_id_t;
4339212Sgibbs
4439212Sgibbs#define	CAM_XPT_PATH_ID	((path_id_t)~0)
4539212Sgibbs#define	CAM_BUS_WILDCARD ((path_id_t)~0)
4639212Sgibbs#define	CAM_TARGET_WILDCARD ((target_id_t)~0)
47259397Snwhitehorn#define	CAM_LUN_WILDCARD (~(u_int)0)
4839212Sgibbs
49257345Snwhitehorn#define CAM_EXTLUN_BYTE_SWIZZLE(lun) (	\
50257345Snwhitehorn	((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \
51257345Snwhitehorn	((((u_int64_t)lun) & 0x0000ffff00000000L) >> 16) | \
52257345Snwhitehorn	((((u_int64_t)lun) & 0x00000000ffff0000L) << 16) | \
53257345Snwhitehorn	((((u_int64_t)lun) & 0x000000000000ffffL) << 48))
54257345Snwhitehorn
5539212Sgibbs/*
5639212Sgibbs * Maximum length for a CAM CDB.
5739212Sgibbs */
5839212Sgibbs#define CAM_MAX_CDBLEN 16
5939212Sgibbs
6039212Sgibbs/*
6139212Sgibbs * Definition of a CAM peripheral driver entry.  Peripheral drivers instantiate
6239212Sgibbs * one of these for each device they wish to communicate with and pass it into
6339212Sgibbs * the xpt layer when they wish to schedule work on that device via the
6458111Sn_hibma * xpt_schedule API.
6539212Sgibbs */
6639212Sgibbsstruct cam_periph;
6739212Sgibbs
6839212Sgibbs/*
69203108Smav * Priority information for a CAM structure.
7039212Sgibbs */
71203108Smavtypedef enum {
72203108Smav    CAM_RL_HOST,
73203108Smav    CAM_RL_BUS,
74203108Smav    CAM_RL_XPT,
75203108Smav    CAM_RL_DEV,
76203108Smav    CAM_RL_NORMAL,
77203108Smav    CAM_RL_VALUES
78203108Smav} cam_rl;
79203108Smav/*
80298810Spfg * The generation number is incremented every time a new entry is entered into
81203108Smav * the queue giving round robin per priority level scheduling.
82203108Smav */
8339212Sgibbstypedef struct {
8439212Sgibbs	u_int32_t priority;
85203108Smav#define CAM_PRIORITY_HOST	((CAM_RL_HOST << 8) + 0x80)
86203108Smav#define CAM_PRIORITY_BUS	((CAM_RL_BUS << 8) + 0x80)
87203108Smav#define CAM_PRIORITY_XPT	((CAM_RL_XPT << 8) + 0x80)
88203108Smav#define CAM_PRIORITY_DEV	((CAM_RL_DEV << 8) + 0x80)
89249466Smav#define CAM_PRIORITY_OOB	(CAM_RL_DEV << 8)
90203108Smav#define CAM_PRIORITY_NORMAL	((CAM_RL_NORMAL << 8) + 0x80)
9139212Sgibbs#define CAM_PRIORITY_NONE	(u_int32_t)-1
9239212Sgibbs	u_int32_t generation;
9339212Sgibbs	int       index;
9439212Sgibbs#define CAM_UNQUEUED_INDEX	-1
9539212Sgibbs#define CAM_ACTIVE_INDEX	-2
9639212Sgibbs#define CAM_DONEQ_INDEX		-3
97253958Smav#define CAM_EXTRAQ_INDEX	INT_MAX
9839212Sgibbs} cam_pinfo;
9939212Sgibbs
10045441Sgibbs/*
10145441Sgibbs * Macro to compare two generation numbers.  It is used like this:
10245441Sgibbs *
10345441Sgibbs *	if (GENERATIONCMP(a, >=, b))
10445441Sgibbs *		...;
10545441Sgibbs *
10645441Sgibbs * GERERATIONCMP uses modular arithmetic to guard against wraps
10745441Sgibbs * wraps in the generation number.
10845441Sgibbs */
10945441Sgibbs#define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0)
11045441Sgibbs
11174840Sken/* CAM flags XXX Move to cam_periph.h ??? */
11239212Sgibbstypedef enum {
11339212Sgibbs	CAM_FLAG_NONE		= 0x00,
11474840Sken	CAM_EXPECT_INQ_CHANGE	= 0x01,
11574840Sken	CAM_RETRY_SELTO		= 0x02 /* Retry Selection Timeouts */
11639212Sgibbs} cam_flags;
11739212Sgibbs
118236814Smavenum {
119236814Smav	SF_RETRY_UA		= 0x01,	/* Retry UNIT ATTENTION conditions. */
120236814Smav	SF_NO_PRINT		= 0x02,	/* Never print error status. */
121298810Spfg	SF_QUIET_IR		= 0x04,	/* Be quiet about Illegal Request responses */
122236814Smav	SF_PRINT_ALWAYS		= 0x08,	/* Always print error status. */
123236814Smav	SF_NO_RECOVERY		= 0x10,	/* Don't do active error recovery. */
124278111Smav	SF_NO_RETRY		= 0x20,	/* Don't do any retries. */
125278111Smav	SF_RETRY_BUSY		= 0x40	/* Retry BUSY status. */
126236814Smav};
127236814Smav
12839212Sgibbs/* CAM  Status field values */
12939212Sgibbstypedef enum {
130255870Sscottl	/* CCB request is in progress */
131255870Sscottl	CAM_REQ_INPROG		= 0x00,
13239212Sgibbs
133255870Sscottl	/* CCB request completed without error */
134255870Sscottl	CAM_REQ_CMP		= 0x01,
13539212Sgibbs
136255870Sscottl	/* CCB request aborted by the host */
137255870Sscottl	CAM_REQ_ABORTED		= 0x02,
13839212Sgibbs
139255870Sscottl	/* Unable to abort CCB request */
140255870Sscottl	CAM_UA_ABORT		= 0x03,
14156143Smjacob
142255870Sscottl	/* CCB request completed with an error */
143255870Sscottl	CAM_REQ_CMP_ERR		= 0x04,
144255870Sscottl
145255870Sscottl	/* CAM subsystem is busy */
146255870Sscottl	CAM_BUSY		= 0x05,
147255870Sscottl
148255870Sscottl	/* CCB request was invalid */
149255870Sscottl	CAM_REQ_INVALID		= 0x06,
150255870Sscottl
151255870Sscottl	/* Supplied Path ID is invalid */
152255870Sscottl	CAM_PATH_INVALID	= 0x07,
153255870Sscottl
154255870Sscottl	/* SCSI Device Not Installed/there */
155255870Sscottl	CAM_DEV_NOT_THERE	= 0x08,
156255870Sscottl
157255870Sscottl	/* Unable to terminate I/O CCB request */
158255870Sscottl	CAM_UA_TERMIO		= 0x09,
159255870Sscottl
160255870Sscottl	/* Target Selection Timeout */
161255870Sscottl	CAM_SEL_TIMEOUT		= 0x0a,
162255870Sscottl
163255870Sscottl	/* Command timeout */
164255870Sscottl	CAM_CMD_TIMEOUT		= 0x0b,
165255870Sscottl
166255870Sscottl	/* SCSI error, look at error code in CCB */
167255870Sscottl	CAM_SCSI_STATUS_ERROR	= 0x0c,
168255870Sscottl
169255870Sscottl	/* Message Reject Received */
170255870Sscottl	CAM_MSG_REJECT_REC	= 0x0d,
171255870Sscottl
172255870Sscottl	/* SCSI Bus Reset Sent/Received */
173255870Sscottl	CAM_SCSI_BUS_RESET	= 0x0e,
174255870Sscottl
175255870Sscottl	/* Uncorrectable parity error occurred */
176255870Sscottl	CAM_UNCOR_PARITY	= 0x0f,
177255870Sscottl
178255870Sscottl	/* Autosense: request sense cmd fail */
179255870Sscottl	CAM_AUTOSENSE_FAIL	= 0x10,
180255870Sscottl
181255870Sscottl	/* No HBA Detected error */
182255870Sscottl	CAM_NO_HBA		= 0x11,
183255870Sscottl
184255870Sscottl	/* Data Overrun error */
185255870Sscottl	CAM_DATA_RUN_ERR	= 0x12,
186255870Sscottl
187255870Sscottl	/* Unexpected Bus Free */
188255870Sscottl	CAM_UNEXP_BUSFREE	= 0x13,
189255870Sscottl
190255870Sscottl	/* Target Bus Phase Sequence Failure */
191255870Sscottl	CAM_SEQUENCE_FAIL	= 0x14,
192255870Sscottl
193255870Sscottl	/* CCB length supplied is inadequate */
194255870Sscottl	CAM_CCB_LEN_ERR		= 0x15,
195255870Sscottl
196255870Sscottl	/* Unable to provide requested capability*/
197255870Sscottl	CAM_PROVIDE_FAIL	= 0x16,
198255870Sscottl
199255870Sscottl	/* A SCSI BDR msg was sent to target */
200255870Sscottl	CAM_BDR_SENT		= 0x17,
201255870Sscottl
202255870Sscottl	/* CCB request terminated by the host */
203255870Sscottl	CAM_REQ_TERMIO		= 0x18,
204255870Sscottl
205255870Sscottl	/* Unrecoverable Host Bus Adapter Error */
206255870Sscottl	CAM_UNREC_HBA_ERROR	= 0x19,
207255870Sscottl
208255870Sscottl	/* Request was too large for this host */
209255870Sscottl	CAM_REQ_TOO_BIG		= 0x1a,
210255870Sscottl
211255870Sscottl	/*
212255870Sscottl	 * This request should be requeued to preserve
213255870Sscottl	 * transaction ordering.  This typically occurs
214255870Sscottl	 * when the SIM recognizes an error that should
215255870Sscottl	 * freeze the queue and must place additional
216255870Sscottl	 * requests for the target at the sim level
217255870Sscottl	 * back into the XPT queue.
218255870Sscottl	 */
219255870Sscottl	CAM_REQUEUE_REQ		= 0x1b,
220255870Sscottl
221255870Sscottl	/* ATA error, look at error code in CCB */
222255870Sscottl	CAM_ATA_STATUS_ERROR	= 0x1c,
223255870Sscottl
224255870Sscottl	/* Initiator/Target Nexus lost. */
225255870Sscottl	CAM_SCSI_IT_NEXUS_LOST	= 0x1d,
226255870Sscottl
227255870Sscottl	/* SMP error, look at error code in CCB */
228255870Sscottl	CAM_SMP_STATUS_ERROR	= 0x1e,
229255870Sscottl
230255870Sscottl	/*
231255870Sscottl	 * Command completed without error but  exceeded the soft
232255870Sscottl	 * timeout threshold.
233255870Sscottl	 */
234255870Sscottl	CAM_REQ_SOFTTIMEOUT	= 0x1f,
235255870Sscottl
236255870Sscottl	/*
237255870Sscottl	 * 0x20 - 0x32 are unassigned
238255870Sscottl	 */
239255870Sscottl
240255870Sscottl	/* Initiator Detected Error */
241255870Sscottl	CAM_IDE			= 0x33,
242255870Sscottl
243255870Sscottl	/* Resource Unavailable */
244255870Sscottl	CAM_RESRC_UNAVAIL	= 0x34,
245255870Sscottl
246255870Sscottl	/* Unacknowledged Event by Host */
247255870Sscottl	CAM_UNACKED_EVENT	= 0x35,
248255870Sscottl
249255870Sscottl	/* Message Received in Host Target Mode */
250255870Sscottl	CAM_MESSAGE_RECV	= 0x36,
251255870Sscottl
252255870Sscottl	/* Invalid CDB received in Host Target Mode */
253255870Sscottl	CAM_INVALID_CDB		= 0x37,
254255870Sscottl
255255870Sscottl	/* Lun supplied is invalid */
256255870Sscottl	CAM_LUN_INVALID		= 0x38,
257255870Sscottl
258255870Sscottl	/* Target ID supplied is invalid */
259255870Sscottl	CAM_TID_INVALID		= 0x39,
260255870Sscottl
261255870Sscottl	/* The requested function is not available */
262255870Sscottl	CAM_FUNC_NOTAVAIL	= 0x3a,
263255870Sscottl
264255870Sscottl	/* Nexus is not established */
265255870Sscottl	CAM_NO_NEXUS		= 0x3b,
266255870Sscottl
267255870Sscottl	/* The initiator ID is invalid */
268255870Sscottl	CAM_IID_INVALID		= 0x3c,
269255870Sscottl
270255870Sscottl	/* The SCSI CDB has been received */
271255870Sscottl	CAM_CDB_RECVD		= 0x3d,
272255870Sscottl
273255870Sscottl	/* The LUN is already enabled for target mode */
274255870Sscottl	CAM_LUN_ALRDY_ENA	= 0x3e,
275255870Sscottl
276255870Sscottl	/* SCSI Bus Busy */
277255870Sscottl	CAM_SCSI_BUSY		= 0x3f,
278255870Sscottl
279255870Sscottl
280255870Sscottl	/*
281255870Sscottl	 * Flags
282255870Sscottl	 */
283255870Sscottl
284255870Sscottl	/* The DEV queue is frozen w/this err */
285255870Sscottl	CAM_DEV_QFRZN		= 0x40,
286255870Sscottl
287255870Sscottl	/* Autosense data valid for target */
288255870Sscottl	CAM_AUTOSNS_VALID	= 0x80,
289255870Sscottl
290255870Sscottl	/* SIM ready to take more commands */
291255870Sscottl	CAM_RELEASE_SIMQ	= 0x100,
292255870Sscottl
293255870Sscottl	/* SIM has this command in it's queue */
294255870Sscottl	CAM_SIM_QUEUED		= 0x200,
295255870Sscottl
296255870Sscottl	/* Quality of service data is valid */
297255870Sscottl	CAM_QOS_VALID		= 0x400,
298255870Sscottl
299255870Sscottl	/* Mask bits for just the status # */
300255870Sscottl	CAM_STATUS_MASK = 0x3F,
301255870Sscottl
302255870Sscottl	/*
303255870Sscottl	 * Target Specific Adjunct Status
304255870Sscottl	 */
305255870Sscottl
306255870Sscottl	/* sent sense with status */
307255870Sscottl	CAM_SENT_SENSE		= 0x40000000
30839212Sgibbs} cam_status;
30939212Sgibbs
31074840Skentypedef enum {
31174840Sken	CAM_ESF_NONE		= 0x00,
31274840Sken	CAM_ESF_COMMAND		= 0x01,
31374840Sken	CAM_ESF_CAM_STATUS	= 0x02,
31474840Sken	CAM_ESF_PROTO_STATUS	= 0x04,
31574840Sken	CAM_ESF_ALL		= 0xff
31674840Sken} cam_error_string_flags;
31774840Sken
31874840Skentypedef enum {
31974840Sken	CAM_EPF_NONE		= 0x00,
32074840Sken	CAM_EPF_MINIMAL		= 0x01,
32174840Sken	CAM_EPF_NORMAL		= 0x02,
32274840Sken	CAM_EPF_ALL		= 0x03,
32374840Sken	CAM_EPF_LEVEL_MASK	= 0x0f
32474840Sken	/* All bits above bit 3 are protocol-specific */
32574840Sken} cam_error_proto_flags;
32674840Sken
32774840Skentypedef enum {
32874840Sken	CAM_ESF_PRINT_NONE	= 0x00,
32974840Sken	CAM_ESF_PRINT_STATUS	= 0x10,
33074840Sken	CAM_ESF_PRINT_SENSE	= 0x20
33174840Sken} cam_error_scsi_flags;
33274840Sken
333198849Smavtypedef enum {
334216088Sken	CAM_ESMF_PRINT_NONE	= 0x00,
335216088Sken	CAM_ESMF_PRINT_STATUS	= 0x10,
336216088Sken	CAM_ESMF_PRINT_FULL_CMD	= 0x20,
337216088Sken} cam_error_smp_flags;
338216088Sken
339216088Skentypedef enum {
340198849Smav	CAM_EAF_PRINT_NONE	= 0x00,
341198849Smav	CAM_EAF_PRINT_STATUS	= 0x10,
342198849Smav	CAM_EAF_PRINT_RESULT	= 0x20
343198849Smav} cam_error_ata_flags;
344198849Smav
345284192Skentypedef enum {
346284192Sken	CAM_STRVIS_FLAG_NONE		= 0x00,
347284192Sken	CAM_STRVIS_FLAG_NONASCII_MASK	= 0x03,
348284192Sken	CAM_STRVIS_FLAG_NONASCII_TRIM	= 0x00,
349284192Sken	CAM_STRVIS_FLAG_NONASCII_RAW	= 0x01,
350284192Sken	CAM_STRVIS_FLAG_NONASCII_SPC	= 0x02,
351284192Sken	CAM_STRVIS_FLAG_NONASCII_ESC	= 0x03
352284192Sken} cam_strvis_flags;
353284192Sken
35474840Skenstruct cam_status_entry
35574840Sken{
35674840Sken	cam_status  status_code;
35774840Sken	const char *status_text;
35874840Sken};
35974840Sken
36074840Skenextern const struct cam_status_entry cam_status_table[];
36174840Skenextern const int num_cam_status_entries;
362248922Ssmh#ifdef _KERNEL
363248922Ssmhextern int cam_sort_io_queues;
364248922Ssmh#endif
36574840Skenunion ccb;
366284192Skenstruct sbuf;
36774840Sken
36889114Smsmith#ifdef SYSCTL_DECL	/* from sysctl.h */
36989114SmsmithSYSCTL_DECL(_kern_cam);
37089114Smsmith#endif
37189114Smsmith
37239212Sgibbs__BEGIN_DECLS
37339212Sgibbstypedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
37439212Sgibbs
37539212Sgibbscaddr_t	cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
37639212Sgibbs		       int entry_size, cam_quirkmatch_t *comp_func);
37739212Sgibbs
37839212Sgibbsvoid	cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
379284192Skenvoid	cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
380284192Sken			uint32_t flags);
38139212Sgibbs
38239212Sgibbsint	cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
38374840Skenconst struct cam_status_entry*
38474840Sken	cam_fetch_status_entry(cam_status status);
38574840Sken#ifdef _KERNEL
38674840Skenchar *	cam_error_string(union ccb *ccb, char *str, int str_len,
38774840Sken			 cam_error_string_flags flags,
38874840Sken			 cam_error_proto_flags proto_flags);
38974840Skenvoid	cam_error_print(union ccb *ccb, cam_error_string_flags flags,
39074840Sken			cam_error_proto_flags proto_flags);
39174840Sken#else /* _KERNEL */
39274840Skenstruct cam_device;
39374840Sken
39474840Skenchar *	cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
39574840Sken			 int str_len, cam_error_string_flags flags,
39674840Sken			 cam_error_proto_flags proto_flags);
39774840Skenvoid	cam_error_print(struct cam_device *device, union ccb *ccb,
39874840Sken			cam_error_string_flags flags,
39974840Sken			cam_error_proto_flags proto_flags, FILE *ofile);
40074840Sken#endif /* _KERNEL */
40139212Sgibbs__END_DECLS
40239212Sgibbs
40355206Speter#ifdef _KERNEL
40439212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo);
40539212Sgibbs
40639212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo)
40739212Sgibbs{
40839212Sgibbs	pinfo->priority = CAM_PRIORITY_NONE;
40939212Sgibbs	pinfo->index = CAM_UNQUEUED_INDEX;
41039212Sgibbs}
41155206Speter#endif
41239212Sgibbs
41339212Sgibbs#endif /* _CAM_CAM_H */
414