cam.h revision 311402
1234027Sstas/*-
2234027Sstas * Data structures and definitions for the CAM system.
3234027Sstas *
4234027Sstas * Copyright (c) 1997 Justin T. Gibbs.
5234027Sstas * All rights reserved.
6234027Sstas *
7234027Sstas * Redistribution and use in source and binary forms, with or without
8234027Sstas * modification, are permitted provided that the following conditions
9234027Sstas * are met:
10234027Sstas * 1. Redistributions of source code must retain the above copyright
11234027Sstas *    notice, this list of conditions, and the following disclaimer,
12234027Sstas *    without modification, immediately at the beginning of the file.
13234027Sstas * 2. The name of the author may not be used to endorse or promote products
14233294Sstas *    derived from this software without specific prior written permission.
15233294Sstas *
16233294Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
20233294Sstas * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26233294Sstas * SUCH DAMAGE.
27233294Sstas *
28233294Sstas * $FreeBSD: stable/10/sys/cam/cam.h 311402 2017-01-05 11:20:31Z mav $
29233294Sstas */
30233294Sstas
31233294Sstas#ifndef _CAM_CAM_H
32233294Sstas#define _CAM_CAM_H 1
33233294Sstas
34233294Sstas#ifdef _KERNEL
35233294Sstas#include <opt_cam.h>
36233294Sstas#endif
37233294Sstas
38233294Sstas#include <sys/cdefs.h>
39233294Sstas
40233294Sstastypedef u_int path_id_t;
41233294Sstastypedef u_int target_id_t;
42233294Sstastypedef u_int lun_id_t;
43233294Sstastypedef union {
44233294Sstas	u_int64_t	lun64;
45233294Sstas	u_int8_t	lun[8];
46233294Sstas} lun64_id_t;
47233294Sstas
48233294Sstas#define	CAM_XPT_PATH_ID	((path_id_t)~0)
49233294Sstas#define	CAM_BUS_WILDCARD ((path_id_t)~0)
50233294Sstas#define	CAM_TARGET_WILDCARD ((target_id_t)~0)
51233294Sstas#define	CAM_LUN_WILDCARD ((lun_id_t)~0)
52233294Sstas
53233294Sstas#define CAM_EXTLUN_BYTE_SWIZZLE(lun) (	\
54233294Sstas	((((u_int64_t)lun) & 0xffff000000000000L) >> 48) | \
55233294Sstas	((((u_int64_t)lun) & 0x0000ffff00000000L) >> 16) | \
56233294Sstas	((((u_int64_t)lun) & 0x00000000ffff0000L) << 16) | \
57233294Sstas	((((u_int64_t)lun) & 0x000000000000ffffL) << 48))
58233294Sstas
59233294Sstas/*
60233294Sstas * Maximum length for a CAM CDB.
61233294Sstas */
62233294Sstas#define CAM_MAX_CDBLEN 16
63233294Sstas
64233294Sstas/*
65233294Sstas * Definition of a CAM peripheral driver entry.  Peripheral drivers instantiate
66233294Sstas * one of these for each device they wish to communicate with and pass it into
67233294Sstas * the xpt layer when they wish to schedule work on that device via the
68233294Sstas * xpt_schedule API.
69233294Sstas */
70233294Sstasstruct cam_periph;
71233294Sstas
72233294Sstas/*
73233294Sstas * Priority information for a CAM structure.
74233294Sstas */
75233294Sstastypedef enum {
76233294Sstas    CAM_RL_HOST,
77233294Sstas    CAM_RL_BUS,
78233294Sstas    CAM_RL_XPT,
79233294Sstas    CAM_RL_DEV,
80233294Sstas    CAM_RL_NORMAL,
81233294Sstas    CAM_RL_VALUES
82233294Sstas} cam_rl;
83233294Sstas/*
84233294Sstas * The generation number is incremented every time a new entry is entered into
85233294Sstas * the queue giving round robin per priority level scheduling.
86233294Sstas */
87233294Sstastypedef struct {
88233294Sstas	u_int32_t priority;
89233294Sstas#define CAM_PRIORITY_HOST	((CAM_RL_HOST << 8) + 0x80)
90233294Sstas#define CAM_PRIORITY_BUS	((CAM_RL_BUS << 8) + 0x80)
91233294Sstas#define CAM_PRIORITY_XPT	((CAM_RL_XPT << 8) + 0x80)
92233294Sstas#define CAM_PRIORITY_DEV	((CAM_RL_DEV << 8) + 0x80)
93233294Sstas#define CAM_PRIORITY_OOB	(CAM_RL_DEV << 8)
94233294Sstas#define CAM_PRIORITY_NORMAL	((CAM_RL_NORMAL << 8) + 0x80)
95233294Sstas#define CAM_PRIORITY_NONE	(u_int32_t)-1
96233294Sstas	u_int32_t generation;
97233294Sstas	int       index;
98233294Sstas#define CAM_UNQUEUED_INDEX	-1
99233294Sstas#define CAM_ACTIVE_INDEX	-2
100233294Sstas#define CAM_DONEQ_INDEX		-3
101233294Sstas#define CAM_EXTRAQ_INDEX	INT_MAX
102233294Sstas} cam_pinfo;
103233294Sstas
104233294Sstas/*
105233294Sstas * Macro to compare two generation numbers.  It is used like this:
106233294Sstas *
107233294Sstas *	if (GENERATIONCMP(a, >=, b))
108233294Sstas *		...;
109233294Sstas *
110233294Sstas * GERERATIONCMP uses modular arithmetic to guard against wraps
111233294Sstas * wraps in the generation number.
112233294Sstas */
113233294Sstas#define GENERATIONCMP(x, op, y) ((int32_t)((x) - (y)) op 0)
114233294Sstas
115233294Sstas/* CAM flags XXX Move to cam_periph.h ??? */
116233294Sstastypedef enum {
117233294Sstas	CAM_FLAG_NONE		= 0x00,
118233294Sstas	CAM_EXPECT_INQ_CHANGE	= 0x01,
119233294Sstas	CAM_RETRY_SELTO		= 0x02 /* Retry Selection Timeouts */
120233294Sstas} cam_flags;
121233294Sstas
122233294Sstasenum {
123233294Sstas	SF_RETRY_UA		= 0x01,	/* Retry UNIT ATTENTION conditions. */
124233294Sstas	SF_NO_PRINT		= 0x02,	/* Never print error status. */
125233294Sstas	SF_QUIET_IR		= 0x04,	/* Be quiet about Illegal Request responses */
126233294Sstas	SF_PRINT_ALWAYS		= 0x08,	/* Always print error status. */
127233294Sstas	SF_NO_RECOVERY		= 0x10,	/* Don't do active error recovery. */
128233294Sstas	SF_NO_RETRY		= 0x20,	/* Don't do any retries. */
129233294Sstas	SF_RETRY_BUSY		= 0x40	/* Retry BUSY status. */
130233294Sstas};
131233294Sstas
132233294Sstas/* CAM  Status field values */
133233294Sstastypedef enum {
134233294Sstas	/* CCB request is in progress */
135233294Sstas	CAM_REQ_INPROG		= 0x00,
136233294Sstas
137233294Sstas	/* CCB request completed without error */
138233294Sstas	CAM_REQ_CMP		= 0x01,
139233294Sstas
140233294Sstas	/* CCB request aborted by the host */
141233294Sstas	CAM_REQ_ABORTED		= 0x02,
142233294Sstas
143233294Sstas	/* Unable to abort CCB request */
144233294Sstas	CAM_UA_ABORT		= 0x03,
145233294Sstas
146233294Sstas	/* CCB request completed with an error */
147233294Sstas	CAM_REQ_CMP_ERR		= 0x04,
148233294Sstas
149233294Sstas	/* CAM subsystem is busy */
150233294Sstas	CAM_BUSY		= 0x05,
151233294Sstas
152233294Sstas	/* CCB request was invalid */
153233294Sstas	CAM_REQ_INVALID		= 0x06,
154233294Sstas
155233294Sstas	/* Supplied Path ID is invalid */
156233294Sstas	CAM_PATH_INVALID	= 0x07,
157233294Sstas
158233294Sstas	/* SCSI Device Not Installed/there */
159233294Sstas	CAM_DEV_NOT_THERE	= 0x08,
160233294Sstas
161233294Sstas	/* Unable to terminate I/O CCB request */
162233294Sstas	CAM_UA_TERMIO		= 0x09,
163233294Sstas
164233294Sstas	/* Target Selection Timeout */
165233294Sstas	CAM_SEL_TIMEOUT		= 0x0a,
166233294Sstas
167233294Sstas	/* Command timeout */
168233294Sstas	CAM_CMD_TIMEOUT		= 0x0b,
169233294Sstas
170233294Sstas	/* SCSI error, look at error code in CCB */
171233294Sstas	CAM_SCSI_STATUS_ERROR	= 0x0c,
172233294Sstas
173178825Sdfr	/* Message Reject Received */
174178825Sdfr	CAM_MSG_REJECT_REC	= 0x0d,
175178825Sdfr
176178825Sdfr	/* SCSI Bus Reset Sent/Received */
177178825Sdfr	CAM_SCSI_BUS_RESET	= 0x0e,
178178825Sdfr
179178825Sdfr	/* Uncorrectable parity error occurred */
180178825Sdfr	CAM_UNCOR_PARITY	= 0x0f,
181178825Sdfr
182178825Sdfr	/* Autosense: request sense cmd fail */
183178825Sdfr	CAM_AUTOSENSE_FAIL	= 0x10,
184178825Sdfr
185178825Sdfr	/* No HBA Detected error */
186178825Sdfr	CAM_NO_HBA		= 0x11,
187178825Sdfr
188178825Sdfr	/* Data Overrun error */
189178825Sdfr	CAM_DATA_RUN_ERR	= 0x12,
190178825Sdfr
191178825Sdfr	/* Unexpected Bus Free */
192178825Sdfr	CAM_UNEXP_BUSFREE	= 0x13,
193178825Sdfr
194178825Sdfr	/* Target Bus Phase Sequence Failure */
195178825Sdfr	CAM_SEQUENCE_FAIL	= 0x14,
196178825Sdfr
197178825Sdfr	/* CCB length supplied is inadequate */
198178825Sdfr	CAM_CCB_LEN_ERR		= 0x15,
199178825Sdfr
200178825Sdfr	/* Unable to provide requested capability*/
201178825Sdfr	CAM_PROVIDE_FAIL	= 0x16,
202178825Sdfr
203178825Sdfr	/* A SCSI BDR msg was sent to target */
204178825Sdfr	CAM_BDR_SENT		= 0x17,
205178825Sdfr
206178825Sdfr	/* CCB request terminated by the host */
207178825Sdfr	CAM_REQ_TERMIO		= 0x18,
208178825Sdfr
209178825Sdfr	/* Unrecoverable Host Bus Adapter Error */
210178825Sdfr	CAM_UNREC_HBA_ERROR	= 0x19,
211178825Sdfr
212178825Sdfr	/* Request was too large for this host */
213178825Sdfr	CAM_REQ_TOO_BIG		= 0x1a,
214178825Sdfr
215178825Sdfr	/*
216178825Sdfr	 * This request should be requeued to preserve
217178825Sdfr	 * transaction ordering.  This typically occurs
218178825Sdfr	 * when the SIM recognizes an error that should
219178825Sdfr	 * freeze the queue and must place additional
220178825Sdfr	 * requests for the target at the sim level
221178825Sdfr	 * back into the XPT queue.
222178825Sdfr	 */
223178825Sdfr	CAM_REQUEUE_REQ		= 0x1b,
224178825Sdfr
225178825Sdfr	/* ATA error, look at error code in CCB */
226178825Sdfr	CAM_ATA_STATUS_ERROR	= 0x1c,
227178825Sdfr
228178825Sdfr	/* Initiator/Target Nexus lost. */
229178825Sdfr	CAM_SCSI_IT_NEXUS_LOST	= 0x1d,
230178825Sdfr
231178825Sdfr	/* SMP error, look at error code in CCB */
232178825Sdfr	CAM_SMP_STATUS_ERROR	= 0x1e,
233178825Sdfr
234178825Sdfr	/*
235178825Sdfr	 * Command completed without error but  exceeded the soft
236178825Sdfr	 * timeout threshold.
237178825Sdfr	 */
238178825Sdfr	CAM_REQ_SOFTTIMEOUT	= 0x1f,
239178825Sdfr
240178825Sdfr	/*
241178825Sdfr	 * 0x20 - 0x32 are unassigned
242178825Sdfr	 */
243178825Sdfr
244178825Sdfr	/* Initiator Detected Error */
245178825Sdfr	CAM_IDE			= 0x33,
246178825Sdfr
247178825Sdfr	/* Resource Unavailable */
248178825Sdfr	CAM_RESRC_UNAVAIL	= 0x34,
249178825Sdfr
250178825Sdfr	/* Unacknowledged Event by Host */
251178825Sdfr	CAM_UNACKED_EVENT	= 0x35,
252178825Sdfr
253178825Sdfr	/* Message Received in Host Target Mode */
254178825Sdfr	CAM_MESSAGE_RECV	= 0x36,
255178825Sdfr
256178825Sdfr	/* Invalid CDB received in Host Target Mode */
257178825Sdfr	CAM_INVALID_CDB		= 0x37,
258178825Sdfr
259178825Sdfr	/* Lun supplied is invalid */
260178825Sdfr	CAM_LUN_INVALID		= 0x38,
261178825Sdfr
262178825Sdfr	/* Target ID supplied is invalid */
263178825Sdfr	CAM_TID_INVALID		= 0x39,
264178825Sdfr
265178825Sdfr	/* The requested function is not available */
266178825Sdfr	CAM_FUNC_NOTAVAIL	= 0x3a,
267178825Sdfr
268178825Sdfr	/* Nexus is not established */
269178825Sdfr	CAM_NO_NEXUS		= 0x3b,
270178825Sdfr
271178825Sdfr	/* The initiator ID is invalid */
272178825Sdfr	CAM_IID_INVALID		= 0x3c,
273178825Sdfr
274178825Sdfr	/* The SCSI CDB has been received */
275178825Sdfr	CAM_CDB_RECVD		= 0x3d,
276178825Sdfr
277178825Sdfr	/* The LUN is already enabled for target mode */
278178825Sdfr	CAM_LUN_ALRDY_ENA	= 0x3e,
279178825Sdfr
280178825Sdfr	/* SCSI Bus Busy */
281178825Sdfr	CAM_SCSI_BUSY		= 0x3f,
282178825Sdfr
283178825Sdfr
284178825Sdfr	/*
285178825Sdfr	 * Flags
286178825Sdfr	 */
287178825Sdfr
288178825Sdfr	/* The DEV queue is frozen w/this err */
289178825Sdfr	CAM_DEV_QFRZN		= 0x40,
290178825Sdfr
291178825Sdfr	/* Autosense data valid for target */
292178825Sdfr	CAM_AUTOSNS_VALID	= 0x80,
293178825Sdfr
294178825Sdfr	/* SIM ready to take more commands */
295178825Sdfr	CAM_RELEASE_SIMQ	= 0x100,
296178825Sdfr
297178825Sdfr	/* SIM has this command in it's queue */
298178825Sdfr	CAM_SIM_QUEUED		= 0x200,
299178825Sdfr
300178825Sdfr	/* Quality of service data is valid */
301178825Sdfr	CAM_QOS_VALID		= 0x400,
302178825Sdfr
303178825Sdfr	/* Mask bits for just the status # */
304178825Sdfr	CAM_STATUS_MASK = 0x3F,
305178825Sdfr
306178825Sdfr	/*
307178825Sdfr	 * Target Specific Adjunct Status
308178825Sdfr	 */
309178825Sdfr
310178825Sdfr	/* sent sense with status */
311178825Sdfr	CAM_SENT_SENSE		= 0x40000000
312178825Sdfr} cam_status;
313178825Sdfr
314178825Sdfrtypedef enum {
315178825Sdfr	CAM_ESF_NONE		= 0x00,
316178825Sdfr	CAM_ESF_COMMAND		= 0x01,
317178825Sdfr	CAM_ESF_CAM_STATUS	= 0x02,
318178825Sdfr	CAM_ESF_PROTO_STATUS	= 0x04,
319178825Sdfr	CAM_ESF_ALL		= 0xff
320178825Sdfr} cam_error_string_flags;
321178825Sdfr
322178825Sdfrtypedef enum {
323178825Sdfr	CAM_EPF_NONE		= 0x00,
324178825Sdfr	CAM_EPF_MINIMAL		= 0x01,
325178825Sdfr	CAM_EPF_NORMAL		= 0x02,
326178825Sdfr	CAM_EPF_ALL		= 0x03,
327178825Sdfr	CAM_EPF_LEVEL_MASK	= 0x0f
328178825Sdfr	/* All bits above bit 3 are protocol-specific */
329178825Sdfr} cam_error_proto_flags;
330178825Sdfr
331178825Sdfrtypedef enum {
332178825Sdfr	CAM_ESF_PRINT_NONE	= 0x00,
333178825Sdfr	CAM_ESF_PRINT_STATUS	= 0x10,
334178825Sdfr	CAM_ESF_PRINT_SENSE	= 0x20
335178825Sdfr} cam_error_scsi_flags;
336178825Sdfr
337178825Sdfrtypedef enum {
338178825Sdfr	CAM_ESMF_PRINT_NONE	= 0x00,
339178825Sdfr	CAM_ESMF_PRINT_STATUS	= 0x10,
340178825Sdfr	CAM_ESMF_PRINT_FULL_CMD	= 0x20,
341178825Sdfr} cam_error_smp_flags;
342178825Sdfr
343178825Sdfrtypedef enum {
344178825Sdfr	CAM_EAF_PRINT_NONE	= 0x00,
345178825Sdfr	CAM_EAF_PRINT_STATUS	= 0x10,
346178825Sdfr	CAM_EAF_PRINT_RESULT	= 0x20
347178825Sdfr} cam_error_ata_flags;
348178825Sdfr
349178825Sdfrtypedef enum {
350142403Snectar	CAM_STRVIS_FLAG_NONE		= 0x00,
351142403Snectar	CAM_STRVIS_FLAG_NONASCII_MASK	= 0x03,
352142403Snectar	CAM_STRVIS_FLAG_NONASCII_TRIM	= 0x00,
353142403Snectar	CAM_STRVIS_FLAG_NONASCII_RAW	= 0x01,
354142403Snectar	CAM_STRVIS_FLAG_NONASCII_SPC	= 0x02,
355142403Snectar	CAM_STRVIS_FLAG_NONASCII_ESC	= 0x03
356142403Snectar} cam_strvis_flags;
357142403Snectar
358142403Snectarstruct cam_status_entry
359142403Snectar{
360142403Snectar	cam_status  status_code;
361142403Snectar	const char *status_text;
362142403Snectar};
363142403Snectar
364142403Snectarextern const struct cam_status_entry cam_status_table[];
365142403Snectarextern const int num_cam_status_entries;
366142403Snectar#ifdef _KERNEL
367127808Snectarextern int cam_sort_io_queues;
368127808Snectar#endif
369127808Snectarunion ccb;
370127808Snectarstruct sbuf;
371127808Snectar
372127808Snectar#ifdef SYSCTL_DECL	/* from sysctl.h */
373127808SnectarSYSCTL_DECL(_kern_cam);
374127808Snectar#endif
375127808Snectar
376127808Snectar__BEGIN_DECLS
377127808Snectartypedef int (cam_quirkmatch_t)(caddr_t, caddr_t);
378127808Snectar
379120945Snectarcaddr_t	cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
380120945Snectar		       int entry_size, cam_quirkmatch_t *comp_func);
381120945Snectar
382120945Snectarvoid	cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
383120945Snectarvoid	cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
384120945Snectar			uint32_t flags);
385120945Snectar
386120945Snectarint	cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len);
387120945Snectarconst struct cam_status_entry*
388120945Snectar	cam_fetch_status_entry(cam_status status);
389120945Snectar#ifdef _KERNEL
390120945Snectarchar *	cam_error_string(union ccb *ccb, char *str, int str_len,
391120945Snectar			 cam_error_string_flags flags,
392120945Snectar			 cam_error_proto_flags proto_flags);
393120945Snectarvoid	cam_error_print(union ccb *ccb, cam_error_string_flags flags,
394120945Snectar			cam_error_proto_flags proto_flags);
395120945Snectar#else /* _KERNEL */
396120945Snectarstruct cam_device;
397120945Snectar
398120945Snectarchar *	cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
399120945Snectar			 int str_len, cam_error_string_flags flags,
400120945Snectar			 cam_error_proto_flags proto_flags);
401107207Snectarvoid	cam_error_print(struct cam_device *device, union ccb *ccb,
402107207Snectar			cam_error_string_flags flags,
403107207Snectar			cam_error_proto_flags proto_flags, FILE *ofile);
404107207Snectar#endif /* _KERNEL */
405107207Snectar__END_DECLS
406107207Snectar
407107207Snectar#ifdef _KERNEL
408107207Snectarstatic __inline void cam_init_pinfo(cam_pinfo *pinfo);
409107207Snectar
410107207Snectarstatic __inline void cam_init_pinfo(cam_pinfo *pinfo)
411107207Snectar{
412107207Snectar	pinfo->priority = CAM_PRIORITY_NONE;
413107207Snectar	pinfo->index = CAM_UNQUEUED_INDEX;
414107207Snectar}
415102644Snectar#endif
416102644Snectar
417102644Snectar#endif /* _CAM_CAM_H */
418102644Snectar