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: stable/10/sys/cam/cam.h 311402 2017-01-05 11:20:31Z mav $
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/*
84311402Smav * The generation number is incremented every time 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. */
125311402Smav	SF_QUIET_IR		= 0x04,	/* Be quiet about Illegal Request responses */
126236814Smav	SF_PRINT_ALWAYS		= 0x08,	/* Always print error status. */
127236814Smav	SF_NO_RECOVERY		= 0x10,	/* Don't do active error recovery. */
128278440Smav	SF_NO_RETRY		= 0x20,	/* Don't do any retries. */
129278440Smav	SF_RETRY_BUSY		= 0x40	/* Retry BUSY status. */
130236814Smav};
131236814Smav
13239212Sgibbs/* CAM  Status field values */
13339212Sgibbstypedef enum {
134255870Sscottl	/* CCB request is in progress */
135255870Sscottl	CAM_REQ_INPROG		= 0x00,
13639212Sgibbs
137255870Sscottl	/* CCB request completed without error */
138255870Sscottl	CAM_REQ_CMP		= 0x01,
13939212Sgibbs
140255870Sscottl	/* CCB request aborted by the host */
141255870Sscottl	CAM_REQ_ABORTED		= 0x02,
14239212Sgibbs
143255870Sscottl	/* Unable to abort CCB request */
144255870Sscottl	CAM_UA_ABORT		= 0x03,
14556143Smjacob
146255870Sscottl	/* CCB request completed with an error */
147255870Sscottl	CAM_REQ_CMP_ERR		= 0x04,
148255870Sscottl
149255870Sscottl	/* CAM subsystem is busy */
150255870Sscottl	CAM_BUSY		= 0x05,
151255870Sscottl
152255870Sscottl	/* CCB request was invalid */
153255870Sscottl	CAM_REQ_INVALID		= 0x06,
154255870Sscottl
155255870Sscottl	/* Supplied Path ID is invalid */
156255870Sscottl	CAM_PATH_INVALID	= 0x07,
157255870Sscottl
158255870Sscottl	/* SCSI Device Not Installed/there */
159255870Sscottl	CAM_DEV_NOT_THERE	= 0x08,
160255870Sscottl
161255870Sscottl	/* Unable to terminate I/O CCB request */
162255870Sscottl	CAM_UA_TERMIO		= 0x09,
163255870Sscottl
164255870Sscottl	/* Target Selection Timeout */
165255870Sscottl	CAM_SEL_TIMEOUT		= 0x0a,
166255870Sscottl
167255870Sscottl	/* Command timeout */
168255870Sscottl	CAM_CMD_TIMEOUT		= 0x0b,
169255870Sscottl
170255870Sscottl	/* SCSI error, look at error code in CCB */
171255870Sscottl	CAM_SCSI_STATUS_ERROR	= 0x0c,
172255870Sscottl
173255870Sscottl	/* Message Reject Received */
174255870Sscottl	CAM_MSG_REJECT_REC	= 0x0d,
175255870Sscottl
176255870Sscottl	/* SCSI Bus Reset Sent/Received */
177255870Sscottl	CAM_SCSI_BUS_RESET	= 0x0e,
178255870Sscottl
179255870Sscottl	/* Uncorrectable parity error occurred */
180255870Sscottl	CAM_UNCOR_PARITY	= 0x0f,
181255870Sscottl
182255870Sscottl	/* Autosense: request sense cmd fail */
183255870Sscottl	CAM_AUTOSENSE_FAIL	= 0x10,
184255870Sscottl
185255870Sscottl	/* No HBA Detected error */
186255870Sscottl	CAM_NO_HBA		= 0x11,
187255870Sscottl
188255870Sscottl	/* Data Overrun error */
189255870Sscottl	CAM_DATA_RUN_ERR	= 0x12,
190255870Sscottl
191255870Sscottl	/* Unexpected Bus Free */
192255870Sscottl	CAM_UNEXP_BUSFREE	= 0x13,
193255870Sscottl
194255870Sscottl	/* Target Bus Phase Sequence Failure */
195255870Sscottl	CAM_SEQUENCE_FAIL	= 0x14,
196255870Sscottl
197255870Sscottl	/* CCB length supplied is inadequate */
198255870Sscottl	CAM_CCB_LEN_ERR		= 0x15,
199255870Sscottl
200255870Sscottl	/* Unable to provide requested capability*/
201255870Sscottl	CAM_PROVIDE_FAIL	= 0x16,
202255870Sscottl
203255870Sscottl	/* A SCSI BDR msg was sent to target */
204255870Sscottl	CAM_BDR_SENT		= 0x17,
205255870Sscottl
206255870Sscottl	/* CCB request terminated by the host */
207255870Sscottl	CAM_REQ_TERMIO		= 0x18,
208255870Sscottl
209255870Sscottl	/* Unrecoverable Host Bus Adapter Error */
210255870Sscottl	CAM_UNREC_HBA_ERROR	= 0x19,
211255870Sscottl
212255870Sscottl	/* Request was too large for this host */
213255870Sscottl	CAM_REQ_TOO_BIG		= 0x1a,
214255870Sscottl
215255870Sscottl	/*
216255870Sscottl	 * This request should be requeued to preserve
217255870Sscottl	 * transaction ordering.  This typically occurs
218255870Sscottl	 * when the SIM recognizes an error that should
219255870Sscottl	 * freeze the queue and must place additional
220255870Sscottl	 * requests for the target at the sim level
221255870Sscottl	 * back into the XPT queue.
222255870Sscottl	 */
223255870Sscottl	CAM_REQUEUE_REQ		= 0x1b,
224255870Sscottl
225255870Sscottl	/* ATA error, look at error code in CCB */
226255870Sscottl	CAM_ATA_STATUS_ERROR	= 0x1c,
227255870Sscottl
228255870Sscottl	/* Initiator/Target Nexus lost. */
229255870Sscottl	CAM_SCSI_IT_NEXUS_LOST	= 0x1d,
230255870Sscottl
231255870Sscottl	/* SMP error, look at error code in CCB */
232255870Sscottl	CAM_SMP_STATUS_ERROR	= 0x1e,
233255870Sscottl
234255870Sscottl	/*
235255870Sscottl	 * Command completed without error but  exceeded the soft
236255870Sscottl	 * timeout threshold.
237255870Sscottl	 */
238255870Sscottl	CAM_REQ_SOFTTIMEOUT	= 0x1f,
239255870Sscottl
240255870Sscottl	/*
241255870Sscottl	 * 0x20 - 0x32 are unassigned
242255870Sscottl	 */
243255870Sscottl
244255870Sscottl	/* Initiator Detected Error */
245255870Sscottl	CAM_IDE			= 0x33,
246255870Sscottl
247255870Sscottl	/* Resource Unavailable */
248255870Sscottl	CAM_RESRC_UNAVAIL	= 0x34,
249255870Sscottl
250255870Sscottl	/* Unacknowledged Event by Host */
251255870Sscottl	CAM_UNACKED_EVENT	= 0x35,
252255870Sscottl
253255870Sscottl	/* Message Received in Host Target Mode */
254255870Sscottl	CAM_MESSAGE_RECV	= 0x36,
255255870Sscottl
256255870Sscottl	/* Invalid CDB received in Host Target Mode */
257255870Sscottl	CAM_INVALID_CDB		= 0x37,
258255870Sscottl
259255870Sscottl	/* Lun supplied is invalid */
260255870Sscottl	CAM_LUN_INVALID		= 0x38,
261255870Sscottl
262255870Sscottl	/* Target ID supplied is invalid */
263255870Sscottl	CAM_TID_INVALID		= 0x39,
264255870Sscottl
265255870Sscottl	/* The requested function is not available */
266255870Sscottl	CAM_FUNC_NOTAVAIL	= 0x3a,
267255870Sscottl
268255870Sscottl	/* Nexus is not established */
269255870Sscottl	CAM_NO_NEXUS		= 0x3b,
270255870Sscottl
271255870Sscottl	/* The initiator ID is invalid */
272255870Sscottl	CAM_IID_INVALID		= 0x3c,
273255870Sscottl
274255870Sscottl	/* The SCSI CDB has been received */
275255870Sscottl	CAM_CDB_RECVD		= 0x3d,
276255870Sscottl
277255870Sscottl	/* The LUN is already enabled for target mode */
278255870Sscottl	CAM_LUN_ALRDY_ENA	= 0x3e,
279255870Sscottl
280255870Sscottl	/* SCSI Bus Busy */
281255870Sscottl	CAM_SCSI_BUSY		= 0x3f,
282255870Sscottl
283255870Sscottl
284255870Sscottl	/*
285255870Sscottl	 * Flags
286255870Sscottl	 */
287255870Sscottl
288255870Sscottl	/* The DEV queue is frozen w/this err */
289255870Sscottl	CAM_DEV_QFRZN		= 0x40,
290255870Sscottl
291255870Sscottl	/* Autosense data valid for target */
292255870Sscottl	CAM_AUTOSNS_VALID	= 0x80,
293255870Sscottl
294255870Sscottl	/* SIM ready to take more commands */
295255870Sscottl	CAM_RELEASE_SIMQ	= 0x100,
296255870Sscottl
297255870Sscottl	/* SIM has this command in it's queue */
298255870Sscottl	CAM_SIM_QUEUED		= 0x200,
299255870Sscottl
300255870Sscottl	/* Quality of service data is valid */
301255870Sscottl	CAM_QOS_VALID		= 0x400,
302255870Sscottl
303255870Sscottl	/* Mask bits for just the status # */
304255870Sscottl	CAM_STATUS_MASK = 0x3F,
305255870Sscottl
306255870Sscottl	/*
307255870Sscottl	 * Target Specific Adjunct Status
308255870Sscottl	 */
309255870Sscottl
310255870Sscottl	/* sent sense with status */
311255870Sscottl	CAM_SENT_SENSE		= 0x40000000
31239212Sgibbs} cam_status;
31339212Sgibbs
31474840Skentypedef enum {
31574840Sken	CAM_ESF_NONE		= 0x00,
31674840Sken	CAM_ESF_COMMAND		= 0x01,
31774840Sken	CAM_ESF_CAM_STATUS	= 0x02,
31874840Sken	CAM_ESF_PROTO_STATUS	= 0x04,
31974840Sken	CAM_ESF_ALL		= 0xff
32074840Sken} cam_error_string_flags;
32174840Sken
32274840Skentypedef enum {
32374840Sken	CAM_EPF_NONE		= 0x00,
32474840Sken	CAM_EPF_MINIMAL		= 0x01,
32574840Sken	CAM_EPF_NORMAL		= 0x02,
32674840Sken	CAM_EPF_ALL		= 0x03,
32774840Sken	CAM_EPF_LEVEL_MASK	= 0x0f
32874840Sken	/* All bits above bit 3 are protocol-specific */
32974840Sken} cam_error_proto_flags;
33074840Sken
33174840Skentypedef enum {
33274840Sken	CAM_ESF_PRINT_NONE	= 0x00,
33374840Sken	CAM_ESF_PRINT_STATUS	= 0x10,
33474840Sken	CAM_ESF_PRINT_SENSE	= 0x20
33574840Sken} cam_error_scsi_flags;
33674840Sken
337198849Smavtypedef enum {
338216088Sken	CAM_ESMF_PRINT_NONE	= 0x00,
339216088Sken	CAM_ESMF_PRINT_STATUS	= 0x10,
340216088Sken	CAM_ESMF_PRINT_FULL_CMD	= 0x20,
341216088Sken} cam_error_smp_flags;
342216088Sken
343216088Skentypedef enum {
344198849Smav	CAM_EAF_PRINT_NONE	= 0x00,
345198849Smav	CAM_EAF_PRINT_STATUS	= 0x10,
346198849Smav	CAM_EAF_PRINT_RESULT	= 0x20
347198849Smav} cam_error_ata_flags;
348198849Smav
349284435Skentypedef enum {
350284435Sken	CAM_STRVIS_FLAG_NONE		= 0x00,
351284435Sken	CAM_STRVIS_FLAG_NONASCII_MASK	= 0x03,
352284435Sken	CAM_STRVIS_FLAG_NONASCII_TRIM	= 0x00,
353284435Sken	CAM_STRVIS_FLAG_NONASCII_RAW	= 0x01,
354284435Sken	CAM_STRVIS_FLAG_NONASCII_SPC	= 0x02,
355284435Sken	CAM_STRVIS_FLAG_NONASCII_ESC	= 0x03
356284435Sken} cam_strvis_flags;
357284435Sken
35874840Skenstruct cam_status_entry
35974840Sken{
36074840Sken	cam_status  status_code;
36174840Sken	const char *status_text;
36274840Sken};
36374840Sken
36474840Skenextern const struct cam_status_entry cam_status_table[];
36574840Skenextern const int num_cam_status_entries;
366248922Ssmh#ifdef _KERNEL
367248922Ssmhextern int cam_sort_io_queues;
368248922Ssmh#endif
36974840Skenunion ccb;
370284435Skenstruct sbuf;
37174840Sken
37289114Smsmith#ifdef SYSCTL_DECL	/* from sysctl.h */
37389114SmsmithSYSCTL_DECL(_kern_cam);
37489114Smsmith#endif
37589114Smsmith
37639212Sgibbs__BEGIN_DECLS
37739212Sgibbstypedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
37839212Sgibbs
37939212Sgibbscaddr_t	cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
38039212Sgibbs		       int entry_size, cam_quirkmatch_t *comp_func);
38139212Sgibbs
38239212Sgibbsvoid	cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
383284435Skenvoid	cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
384284435Sken			uint32_t flags);
38539212Sgibbs
38639212Sgibbsint	cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
38774840Skenconst struct cam_status_entry*
38874840Sken	cam_fetch_status_entry(cam_status status);
38974840Sken#ifdef _KERNEL
39074840Skenchar *	cam_error_string(union ccb *ccb, char *str, int str_len,
39174840Sken			 cam_error_string_flags flags,
39274840Sken			 cam_error_proto_flags proto_flags);
39374840Skenvoid	cam_error_print(union ccb *ccb, cam_error_string_flags flags,
39474840Sken			cam_error_proto_flags proto_flags);
39574840Sken#else /* _KERNEL */
39674840Skenstruct cam_device;
39774840Sken
39874840Skenchar *	cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
39974840Sken			 int str_len, cam_error_string_flags flags,
40074840Sken			 cam_error_proto_flags proto_flags);
40174840Skenvoid	cam_error_print(struct cam_device *device, union ccb *ccb,
40274840Sken			cam_error_string_flags flags,
40374840Sken			cam_error_proto_flags proto_flags, FILE *ofile);
40474840Sken#endif /* _KERNEL */
40539212Sgibbs__END_DECLS
40639212Sgibbs
40755206Speter#ifdef _KERNEL
40839212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo);
40939212Sgibbs
41039212Sgibbsstatic __inline void cam_init_pinfo(cam_pinfo *pinfo)
41139212Sgibbs{
41239212Sgibbs	pinfo->priority = CAM_PRIORITY_NONE;
41339212Sgibbs	pinfo->index = CAM_UNQUEUED_INDEX;
41439212Sgibbs}
41555206Speter#endif
41639212Sgibbs
41739212Sgibbs#endif /* _CAM_CAM_H */
418