1/*	$FreeBSD: releng/11.0/sys/cam/scsi/scsi_low.h 298810 2016-04-29 21:05:48Z pfg $	*/
2/*	$NecBSD: scsi_low.h,v 1.24.10.5 2001/06/26 07:31:46 honda Exp $	*/
3/*	$NetBSD$	*/
4
5#define	SCSI_LOW_DIAGNOSTIC
6#define	SCSI_LOW_ALT_QTAG_ALLOCATE
7
8/*-
9 * [NetBSD for NEC PC-98 series]
10 *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
11 *	NetBSD/pc98 porting staff. All rights reserved.
12 *  Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
13 *	Naofumi HONDA. All rights reserved.
14 *
15 * [Ported for FreeBSD CAM]
16 *  Copyright (c) 2000, 2001
17 *      MITSUNAGA Noriaki, NOKUBI Hirotaka and TAKAHASHI Yoshihiro.
18 *      All rights reserved.
19 *
20 *  Redistribution and use in source and binary forms, with or without
21 *  modification, are permitted provided that the following conditions
22 *  are met:
23 *  1. Redistributions of source code must retain the above copyright
24 *     notice, this list of conditions and the following disclaimer.
25 *  2. Redistributions in binary form must reproduce the above copyright
26 *     notice, this list of conditions and the following disclaimer in the
27 *     documentation and/or other materials provided with the distribution.
28 *  3. The name of the author may not be used to endorse or promote products
29 *     derived from this software without specific prior written permission.
30 *
31 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
32 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
40 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGE.
42 */
43
44#ifndef	_SCSI_LOW_H_
45#define	_SCSI_LOW_H_
46
47/******** includes *******************************/
48
49#include <sys/bus.h>
50#include <sys/kdb.h>
51#include <cam/cam.h>
52#include <cam/cam_ccb.h>
53#include <cam/cam_sim.h>
54#include <cam/cam_xpt_sim.h>
55#include <cam/cam_debug.h>
56
57#include <cam/scsi/scsi_dvcfg.h>
58#include <i386/isa/ccbque.h>
59
60/******** functions macro ************************/
61
62#undef	MSG_IDENTIFY
63
64/*================================================
65 * Generic Scsi Low header file
66 ================================================*/
67/*************************************************
68 * Scsi low definitions
69 *************************************************/
70#define	SCSI_LOW_SYNC		DVF_SCSI_SYNC
71#define	SCSI_LOW_DISC		DVF_SCSI_DISC
72#define	SCSI_LOW_WAIT		DVF_SCSI_WAIT
73#define	SCSI_LOW_LINK		DVF_SCSI_LINK
74#define	SCSI_LOW_QTAG		DVF_SCSI_QTAG
75#define	SCSI_LOW_NOPARITY	DVF_SCSI_NOPARITY
76#define	SCSI_LOW_SAVESP		DVF_SCSI_SAVESP
77#define	SCSI_LOW_DEFCFG		DVF_SCSI_DEFCFG
78#define	SCSI_LOW_BITS		DVF_SCSI_BITS
79
80#define	SCSI_LOW_PERIOD(n)	DVF_SCSI_PERIOD(n)
81#define	SCSI_LOW_OFFSET(n)	DVF_SCSI_OFFSET(n)
82
83/* host scsi id and targets macro */
84#ifndef	SCSI_LOW_NTARGETS
85#define	SCSI_LOW_NTARGETS			8
86#endif	/* SCSI_LOW_NTARGETS */
87#define	SCSI_LOW_NCCB				128
88
89#define	SCSI_LOW_MAX_RETRY			3
90#define	SCSI_LOW_MAX_SELECTION_RETRY		10
91
92/* timeout control macro */
93#define	SCSI_LOW_TIMEOUT_HZ			10
94#define SCSI_LOW_MIN_TOUT			12
95#define SCSI_LOW_TIMEOUT_CHECK_INTERVAL 	1
96#define	SCSI_LOW_POWDOWN_TC			15
97#define	SCSI_LOW_MAX_PHCHANGES			256
98#define	SCSI2_RESET_DELAY			5000000
99
100/* msg */
101#define	SCSI_LOW_MAX_MSGLEN			32
102#define	SCSI_LOW_MSG_LOG_DATALEN  		8
103
104/*************************************************
105 * Scsi Data Pointer
106 *************************************************/
107/* scsi pointer */
108struct sc_p {
109	u_int8_t *scp_data;
110	int scp_datalen;
111
112	u_int8_t *scp_cmd;
113	int scp_cmdlen;
114
115	u_int8_t scp_direction;
116#define	SCSI_LOW_RWUNK	(-1)
117#define	SCSI_LOW_WRITE	0
118#define	SCSI_LOW_READ	1
119	u_int8_t scp_status;
120	u_int8_t scp_spare[2];
121};
122
123/*************************************************
124 * Command Control Block Structure
125 *************************************************/
126typedef int scsi_low_tag_t;
127struct targ_info;
128
129#define	SCSI_LOW_UNKLUN	((u_int) -1)
130#define	SCSI_LOW_UNKTAG	((scsi_low_tag_t) -1)
131
132struct slccb {
133	TAILQ_ENTRY(slccb) ccb_chain;
134
135	void *osdep;			/* os depend structure */
136
137	struct targ_info *ti;		/* targ_info */
138	struct lun_info *li;		/* lun info */
139	struct buf *bp;			/* io bufs */
140
141	scsi_low_tag_t ccb_tag;		/* effective qtag */
142	scsi_low_tag_t ccb_otag;	/* allocated qtag */
143
144	/*****************************************
145	 * Scsi data pointers (original and saved)
146	 *****************************************/
147	struct sc_p ccb_scp;		/* given */
148	struct sc_p ccb_sscp;		/* saved scsi data pointer */
149	int ccb_datalen;		/* transferred data counter */
150
151	/*****************************************
152	 * Msgout
153	 *****************************************/
154	u_int ccb_msgoutflag;
155	u_int ccb_omsgoutflag;
156
157	/*****************************************
158	 * Error or Timeout counters
159	 *****************************************/
160	u_int ccb_flags;
161#define	CCB_INTERNAL	0x0001
162#define	CCB_SENSE	0x0002
163#define	CCB_CLEARQ	0x0004
164#define	CCB_DISCQ	0x0008
165#define	CCB_STARTQ	0x0010
166#define	CCB_POLLED	0x0100	/* polling ccb */
167#define	CCB_NORETRY	0x0200	/* do NOT retry */
168#define	CCB_AUTOSENSE	0x0400	/* do a sense after CA */
169#define	CCB_URGENT	0x0800	/* an urgent ccb */
170#define	CCB_NOSDONE	0x1000	/* do not call an os done routine */
171#define	CCB_SCSIIO	0x2000	/* a normal scsi io coming from upper layer */
172#define	CCB_SILENT	0x4000	/* no terminate messages */
173
174	u_int ccb_error;
175
176	int ccb_rcnt;			/* retry counter */
177	int ccb_selrcnt;		/* selection retry counter */
178	int ccb_tc;			/* timer counter */
179	int ccb_tcmax;			/* max timeout */
180
181	/*****************************************
182	 * Sense data buffer
183	 *****************************************/
184	u_int8_t ccb_scsi_cmd[12];
185	struct scsi_sense_data ccb_sense;
186};
187
188/*************************************************
189 * Slccb functions
190 *************************************************/
191GENERIC_CCB_ASSERT(scsi_low, slccb)
192
193/*************************************************
194 * Target and Lun structures
195 *************************************************/
196struct scsi_low_softc;
197LIST_HEAD(scsi_low_softc_tab, scsi_low_softc);
198TAILQ_HEAD(targ_info_tab, targ_info);
199LIST_HEAD(lun_info_tab, lun_info);
200
201struct lun_info {
202	int li_lun;
203	struct targ_info *li_ti;		/* my target */
204
205	LIST_ENTRY(lun_info) lun_chain;		/* targ_info link */
206
207	struct slccbtab li_discq;			/* disconnect queue */
208
209	/*
210	 * qtag control
211	 */
212	int li_maxnexus;
213	int li_maxnqio;
214	int li_nqio;
215	int li_disc;
216
217#define	SCSI_LOW_MAXNEXUS (sizeof(u_int) * NBBY)
218	u_int li_qtagbits;
219
220#ifdef	SCSI_LOW_ALT_QTAG_ALLOCATE
221	u_int8_t li_qtagarray[SCSI_LOW_MAXNEXUS];
222	u_int li_qd;
223#endif	/* SCSI_LOW_ALT_QTAG_ALLOCATE */
224
225#define	SCSI_LOW_QFLAG_CA_QCLEAR	0x01
226	u_int li_qflags;
227
228	/*
229	 * lun state
230	 */
231#define	SCSI_LOW_LUN_SLEEP	0x00
232#define	SCSI_LOW_LUN_START	0x01
233#define	SCSI_LOW_LUN_INQ	0x02
234#define	SCSI_LOW_LUN_MODEQ	0x03
235#define	SCSI_LOW_LUN_OK		0x04
236	u_int li_state;				/* target lun state */
237
238	/*
239	 * lun control flags
240 	 */
241	u_int li_flags_valid;	/* valid flags */
242#define	SCSI_LOW_LUN_FLAGS_USER_VALID	0x0001
243#define	SCSI_LOW_LUN_FLAGS_DISK_VALID	0x0002
244#define	SCSI_LOW_LUN_FLAGS_QUIRKS_VALID	0x0004
245#define	SCSI_LOW_LUN_FLAGS_ALL_VALID \
246	(SCSI_LOW_LUN_FLAGS_USER_VALID | \
247	 SCSI_LOW_LUN_FLAGS_DISK_VALID | SCSI_LOW_LUN_FLAGS_QUIRKS_VALID)
248
249	u_int li_flags;		/* real lun control flags */
250	u_int li_cfgflags;	/* lun control flags given by user */
251	u_int li_diskflags;	/* lun control flags given by hardware info */
252	u_int li_quirks;	/* lun control flags given by upper layer */
253
254	/* inq buffer */
255	struct scsi_low_inq_data {
256		u_int8_t sd_type;
257		u_int8_t sd_sp1;
258		u_int8_t sd_version;
259		u_int8_t sd_resp;
260		u_int8_t sd_len;
261		u_int8_t sd_sp2[2];
262		u_int8_t sd_support;
263	} __packed li_inq;
264
265	/* modeq buffer */
266	struct scsi_low_mode_sense_data {
267		u_int8_t sms_header[4];
268		struct {
269			u_int8_t cmp_page;
270			u_int8_t cmp_length;
271			u_int8_t cmp_rlec;
272			u_int8_t cmp_qc;
273			u_int8_t cmp_eca;
274			u_int8_t cmp_spare[3];
275		} __packed sms_cmp;
276
277	} li_sms;
278};
279
280struct scsi_low_msg_log {
281	int slml_ptr;
282	struct {
283		u_int8_t msg[2];
284	} slml_msg[SCSI_LOW_MSG_LOG_DATALEN];
285};
286
287struct targ_info {
288	TAILQ_ENTRY(targ_info) ti_chain;	/* targ_info link */
289
290	struct scsi_low_softc *ti_sc;		/* our softc */
291	u_int ti_id;				/* scsi id */
292
293	/*
294	 * Lun chain
295	 */
296	struct lun_info_tab ti_litab;		/* lun chain */
297
298	/*
299	 * total disconnected nexus
300	 */
301	int ti_disc;
302
303	/*
304	 * Scsi phase control
305 	 */
306
307#define	PH_NULL		0x00
308#define	PH_ARBSTART	0x01
309#define	PH_SELSTART	0x02
310#define	PH_SELECTED	0x03
311#define	PH_CMD		0x04
312#define	PH_DATA		0x05
313#define	PH_MSGIN	0x06
314#define	PH_MSGOUT	0x07
315#define	PH_STAT		0x08
316#define	PH_DISC		0x09
317#define	PH_RESEL	0x0a
318	u_int ti_phase;				/* scsi phase */
319	u_int ti_ophase;			/* old scsi phase */
320
321	/*
322	 * Msg in
323 	 */
324	u_int ti_msginptr;			/* msgin ptr */
325	u_int ti_msginlen;			/* expected msg length */
326	int ti_msgin_parity_error;		/* parity error detected */
327	u_int8_t ti_msgin[SCSI_LOW_MAX_MSGLEN];	/* msgin buffer */
328
329	/*
330	 * Msg out
331 	 */
332	u_int ti_msgflags;			/* msgs to be asserted */
333	u_int ti_omsgflags;			/* msgs asserted */
334	u_int ti_emsgflags;			/* a msg currently asserted */
335#define	SCSI_LOW_MSG_RESET	0x00000001
336#define	SCSI_LOW_MSG_REJECT	0x00000002
337#define	SCSI_LOW_MSG_PARITY	0x00000004
338#define	SCSI_LOW_MSG_ERROR	0x00000008
339#define	SCSI_LOW_MSG_IDENTIFY	0x00000010
340#define	SCSI_LOW_MSG_ABORT	0x00000020
341#define	SCSI_LOW_MSG_TERMIO	0x00000040
342#define	SCSI_LOW_MSG_SIMPLE_QTAG	0x00000080
343#define	SCSI_LOW_MSG_ORDERED_QTAG	0x00000100
344#define	SCSI_LOW_MSG_HEAD_QTAG		0x00000200
345#define	SCSI_LOW_MSG_ABORT_QTAG 0x00000400
346#define	SCSI_LOW_MSG_CLEAR_QTAG 0x00000800
347#define	SCSI_LOW_MSG_WIDE	0x00001000
348#define	SCSI_LOW_MSG_SYNCH	0x00002000
349#define	SCSI_LOW_MSG_NOOP	0x00004000
350#define	SCSI_LOW_MSG_LAST	0x00008000
351#define	SCSI_LOW_MSG_ALL	0xffffffff
352
353	/* msgout buffer */
354	u_int8_t ti_msgoutstr[SCSI_LOW_MAX_MSGLEN];	/* scsi msgout */
355	u_int ti_msgoutlen;			/* msgout strlen */
356
357	/*
358	 * target initialize msgout
359 	 */
360	u_int ti_setup_msg;		/* setup msgout requests */
361	u_int ti_setup_msg_done;
362
363	/*
364	 * synch and wide data info
365 	 */
366	u_int ti_flags_valid;	/* valid flags */
367#define	SCSI_LOW_TARG_FLAGS_USER_VALID		0x0001
368#define	SCSI_LOW_TARG_FLAGS_DISK_VALID		0x0002
369#define	SCSI_LOW_TARG_FLAGS_QUIRKS_VALID	0x0004
370#define	SCSI_LOW_TARG_FLAGS_ALL_VALID \
371	(SCSI_LOW_TARG_FLAGS_USER_VALID | \
372	 SCSI_LOW_TARG_FLAGS_DISK_VALID | SCSI_LOW_TARG_FLAGS_QUIRKS_VALID)
373
374	u_int ti_diskflags;	/* given target disk flags */
375	u_int ti_quirks;	/* given target quirk */
376
377	struct synch {
378		u_int8_t offset;
379		u_int8_t period;
380	} ti_osynch, ti_maxsynch;		/* synch data */
381
382#define	SCSI_LOW_BUS_WIDTH_8	0
383#define	SCSI_LOW_BUS_WIDTH_16	1
384#define	SCSI_LOW_BUS_WIDTH_32	2
385	u_int ti_owidth, ti_width;
386
387	/*
388	 * lun info size.
389 	 */
390	int ti_lunsize;
391
392#ifdef	SCSI_LOW_DIAGNOSTIC
393	struct scsi_low_msg_log ti_log_msgout;
394	struct scsi_low_msg_log ti_log_msgin;
395#endif	/* SCSI_LOW_DIAGNOSTIC */
396};
397
398/*************************************************
399 * COMMON HEADER STRUCTURE
400 *************************************************/
401struct scsi_low_softc;
402struct proc;
403typedef struct scsi_low_softc *sc_low_t;
404
405#define	SCSI_LOW_START_OK	0
406#define	SCSI_LOW_START_FAIL	1
407#define	SCSI_LOW_INFO_ALLOC	0
408#define	SCSI_LOW_INFO_REVOKE	1
409#define	SCSI_LOW_INFO_DEALLOC	2
410#define	SCSI_LOW_POWDOWN	1
411#define	SCSI_LOW_ENGAGE		2
412
413#define	SC_LOW_INIT_T (int (*)(sc_low_t, int))
414#define	SC_LOW_BUSRST_T (void (*)(sc_low_t))
415#define	SC_LOW_TARG_INIT_T (int (*)(sc_low_t, struct targ_info *, int))
416#define	SC_LOW_LUN_INIT_T (int (*)(sc_low_t, struct targ_info *, struct lun_info *, int))
417#define	SC_LOW_SELECT_T (int (*)(sc_low_t, struct slccb *))
418#define	SC_LOW_ATTEN_T (void (*)(sc_low_t))
419#define	SC_LOW_NEXUS_T (int (*)(sc_low_t))
420#define	SC_LOW_MSG_T (int (*)(sc_low_t, struct targ_info *, u_int))
421#define	SC_LOW_POLL_T (int (*)(void *))
422#define	SC_LOW_POWER_T (int (*)(sc_low_t, u_int))
423#define	SC_LOW_TIMEOUT_T (int (*)(sc_low_t))
424
425struct scsi_low_funcs {
426	int (*scsi_low_init)(sc_low_t, int);
427	void (*scsi_low_bus_reset)(sc_low_t);
428	int (*scsi_low_targ_init)(sc_low_t, struct targ_info *, int);
429	int (*scsi_low_lun_init)(sc_low_t, struct targ_info *, struct lun_info *, int);
430	int (*scsi_low_start_bus)(sc_low_t, struct slccb *);
431	int (*scsi_low_establish_lun_nexus)(sc_low_t);
432	int (*scsi_low_establish_ccb_nexus)(sc_low_t);
433	void (*scsi_low_attention)(sc_low_t);
434	int (*scsi_low_msg)(sc_low_t, struct targ_info *, u_int);
435	int (*scsi_low_timeout)(sc_low_t);
436	int (*scsi_low_poll)(void *);
437	int (*scsi_low_power)(sc_low_t, u_int);
438	int (*scsi_low_ioctl)(sc_low_t, u_long, caddr_t, int, struct proc *);
439};
440
441struct scsi_low_softc {
442	device_t sl_dev;
443
444	struct cam_sim *sl_sim;
445	struct cam_path *sl_path;
446
447	int sl_poll_count;
448
449	struct mtx sl_lock;
450	struct callout sl_engage_timer;
451	struct callout sl_timeout_timer;
452#ifdef	SCSI_LOW_POWFUNC
453	struct callout sl_recover_timer;
454#endif
455
456	/* our chain */
457	LIST_ENTRY(scsi_low_softc) sl_chain;
458
459	/* my targets */
460	struct targ_info *sl_ti[SCSI_LOW_NTARGETS];
461	struct targ_info_tab sl_titab;
462
463	/* current active T_L_Q nexus */
464	struct targ_info *sl_Tnexus;		/* Target nexus */
465	struct lun_info *sl_Lnexus;		/* Lun nexus */
466	struct slccb *sl_Qnexus;			/* Qtag nexus */
467	int sl_nexus_call;
468
469	/* ccb start queue */
470	struct slccbtab sl_start;
471
472	/* retry limit and phase change counter */
473	int sl_max_retry;
474	int sl_ph_count;
475	int sl_timeout_count;
476
477	/* selection & total num disconnect targets */
478	int sl_nio;
479	int sl_disc;
480	int sl_retry_sel;
481	struct slccb *sl_selid;
482
483	/* attention */
484	int sl_atten;			/* ATN asserted */
485	int sl_clear_atten;		/* negate ATN required */
486
487	/* scsi phase suggested by scsi msg */
488	u_int sl_msgphase;
489#define	MSGPH_NULL	0x00		/* no msg */
490#define	MSGPH_DISC	0x01		/* disconnect msg */
491#define	MSGPH_CMDC	0x02		/* cmd complete msg */
492#define	MSGPH_ABORT	0x03		/* abort seq */
493#define	MSGPH_TERM	0x04		/* current io terminate */
494#define	MSGPH_LCTERM	0x05		/* cmd link terminated */
495#define	MSGPH_RESET	0x06		/* reset target */
496
497	/* error */
498	u_int sl_error;			/* error flags */
499#define	FATALIO		0x0001		/* generic io error & retry io */
500#define	ABORTIO		0x0002		/* generic io error & terminate io */
501#define	TIMEOUTIO	0x0004		/* watch dog timeout */
502#define	SELTIMEOUTIO	0x0008		/* selection timeout */
503#define	PDMAERR		0x0010		/* dma xfer error */
504#define	MSGERR		0x0020		/* msgsys error */
505#define	PARITYERR	0x0040		/* parity error */
506#define	BUSYERR		0x0080		/* target busy error */
507#define	STATERR		0x0100		/* status error */
508#define	UACAERR		0x0200		/* target CA state, no sense check */
509#define	SENSEIO		0x1000		/* cmd not excuted but sense data ok */
510#define	SENSEERR	0x2000		/* cmd not excuted and sense data bad */
511#define	UBFERR		0x4000		/* unexpected bus free */
512#define	PENDINGIO	0x8000		/* ccb start not yet */
513#define	SCSI_LOW_ERRORBITS "\020\017ubferr\016senseerr\015senseio\012uacaerr\011staterr\010busy\007parity\006msgerr\005pdmaerr\004seltimeout\003timeout\002abort\001fatal"
514
515	/* current scsi data pointer */
516	struct sc_p sl_scp;
517
518	/* power control */
519	u_int sl_active;		/* host is busy state */
520	int sl_powc;			/* power down timer counter */
521	u_int sl_rstep;			/* resume step */
522
523	/* configuration flags */
524	u_int sl_flags;
525#define	HW_POWDOWN	0x0001
526#define	HW_RESUME	0x0002
527#define	HW_PDMASTART	0x0004
528#define	HW_INACTIVE	0x0008
529#define	HW_POWERCTRL	0x0010
530#define	HW_INITIALIZING 0x0020
531#define	HW_READ_PADDING		0x1000
532#define	HW_WRITE_PADDING	0x2000
533
534	u_int sl_cfgflags;
535#define	CFG_NODISC		0x0001
536#define	CFG_NOPARITY		0x0002
537#define	CFG_NOATTEN		0x0004
538#define	CFG_ASYNC		0x0008
539#define	CFG_NOQTAG		0x0010
540
541	int sl_show_result;
542#define	SHOW_SYNCH_NEG	0x0001
543#define	SHOW_WIDE_NEG	0x0002
544#define	SHOW_CALCF_RES	0x0010
545#define	SHOW_PROBE_RES	0x0020
546#define	SHOW_ALL_NEG	-1
547
548	/* host informations */
549	u_int sl_hostid;
550	int sl_nluns;
551	int sl_ntargs;
552	int sl_openings;
553
554	/* interface functions */
555	struct scsi_low_funcs *sl_funcs;
556
557	/* targinfo size */
558	int sl_targsize;
559};
560
561#define	SCSI_LOW_LOCK(sl)		mtx_lock(&(sl)->sl_lock)
562#define	SCSI_LOW_UNLOCK(sl)		mtx_unlock(&(sl)->sl_lock)
563#define	SCSI_LOW_ASSERT_LOCKED(sl)	mtx_assert(&(sl)->sl_lock, MA_OWNED)
564
565/*************************************************
566 * SCSI LOW service functions
567 *************************************************/
568/*
569 * Scsi low attachment function.
570 */
571int scsi_low_attach(struct scsi_low_softc *, int, int, int, int, int);
572int scsi_low_detach(struct scsi_low_softc *);
573
574/*
575 * Scsi low interface activate or deactivate functions
576 */
577int scsi_low_is_busy(struct scsi_low_softc *);
578int scsi_low_activate(struct scsi_low_softc *);
579int scsi_low_deactivate(struct scsi_low_softc *);
580
581/*
582 * Scsi phase "bus service" functions.
583 * These functions are corresponding to each scsi bus phaeses.
584 */
585/* bus idle phase (other initiators or targets release bus) */
586void scsi_low_bus_idle(struct scsi_low_softc *);
587
588/* arbitration and selection phase */
589void scsi_low_arbit_fail(struct scsi_low_softc *, struct slccb *);
590static __inline void scsi_low_arbit_win(struct scsi_low_softc *);
591
592/* msgout phase */
593#define	SCSI_LOW_MSGOUT_INIT		0x00000001
594#define	SCSI_LOW_MSGOUT_UNIFY		0x00000002
595int scsi_low_msgout(struct scsi_low_softc *, struct targ_info *, u_int);
596
597/* msgin phase */
598#define SCSI_LOW_DATA_PE	0x80000000
599int scsi_low_msgin(struct scsi_low_softc *, struct targ_info *, u_int);
600
601/* statusin phase */
602static __inline int scsi_low_statusin(struct scsi_low_softc *, struct targ_info *, u_int);
603
604/* data phase */
605int scsi_low_data(struct scsi_low_softc *, struct targ_info *, struct buf **, int);
606static __inline void scsi_low_data_finish(struct scsi_low_softc *);
607
608/* cmd phase */
609int scsi_low_cmd(struct scsi_low_softc *, struct targ_info *);
610
611/* reselection phase */
612struct targ_info *scsi_low_reselected(struct scsi_low_softc *, u_int);
613
614/* disconnection phase */
615int scsi_low_disconnected(struct scsi_low_softc *, struct targ_info *);
616
617/*
618 * Scsi bus restart function.
619 * Canncel all established nexuses => scsi system initialized => restart jobs.
620 */
621#define	SCSI_LOW_RESTART_HARD	1
622#define	SCSI_LOW_RESTART_SOFT	0
623int scsi_low_restart(struct scsi_low_softc *, int, u_char *);
624
625/*
626 * Scsi utility fucntions
627 */
628/* print current status */
629void scsi_low_print(struct scsi_low_softc *, struct targ_info *);
630
631/* bus reset utility */
632void scsi_low_bus_reset(struct scsi_low_softc *);
633
634/*************************************************
635 * Message macro defs
636 *************************************************/
637#define	SCSI_LOW_SETUP_PHASE(ti, phase)			\
638{							\
639	(ti)->ti_ophase = ti->ti_phase;			\
640	(ti)->ti_phase = (phase);			\
641}
642
643#define	SCSI_LOW_SETUP_MSGPHASE(slp, PHASE)		\
644{							\
645	(slp)->sl_msgphase = (PHASE);			\
646}
647
648#define	SCSI_LOW_ASSERT_ATN(slp)			\
649{							\
650	(slp)->sl_atten = 1;				\
651}
652
653#define	SCSI_LOW_DEASSERT_ATN(slp)			\
654{							\
655	(slp)->sl_atten = 0;				\
656}
657
658/*************************************************
659 * Inline functions
660 *************************************************/
661static __inline void scsi_low_attention(struct scsi_low_softc *);
662static __inline int scsi_low_is_msgout_continue(struct targ_info *, u_int);
663static __inline int scsi_low_assert_msg(struct scsi_low_softc *, struct targ_info *, u_int, int);
664static __inline int scsi_low_is_disconnect_ok(struct slccb *);
665
666static __inline int
667scsi_low_is_msgout_continue(ti, mask)
668	struct targ_info *ti;
669	u_int mask;
670{
671
672	return ((ti->ti_msgflags & (~mask)) != 0);
673}
674
675static __inline int
676scsi_low_is_disconnect_ok(cb)
677	struct slccb *cb;
678{
679
680	return ((cb->li->li_flags & SCSI_LOW_DISC) != 0 &&
681		    (cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) == 0);
682}
683
684static __inline void
685scsi_low_attention(slp)
686	struct scsi_low_softc *slp;
687{
688
689	if (slp->sl_atten != 0)
690		return;
691
692	(*slp->sl_funcs->scsi_low_attention) (slp);
693	SCSI_LOW_ASSERT_ATN(slp);
694}
695
696static __inline int
697scsi_low_assert_msg(slp, ti, msg, now)
698	struct scsi_low_softc *slp;
699	struct targ_info *ti;
700	u_int msg;
701	int now;
702{
703
704	ti->ti_msgflags |= msg;
705	if (now != 0)
706		scsi_low_attention(slp);
707	return 0;
708}
709
710static __inline void
711scsi_low_arbit_win(slp)
712	struct scsi_low_softc *slp;
713{
714
715	slp->sl_selid = NULL;
716}
717
718static __inline void
719scsi_low_data_finish(slp)
720	struct scsi_low_softc *slp;
721{
722
723	if (slp->sl_Qnexus != NULL)
724	{
725		slp->sl_Qnexus->ccb_datalen = slp->sl_scp.scp_datalen;
726	}
727}
728
729static __inline int
730scsi_low_statusin(slp, ti, c)
731	struct scsi_low_softc *slp;
732	struct targ_info *ti;
733	u_int c;
734{
735
736	slp->sl_ph_count ++;
737	if ((c & SCSI_LOW_DATA_PE) != 0)
738	{
739		scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 0);
740		return EIO;
741	}
742	slp->sl_scp.scp_status = (u_int8_t) c;
743	return 0;
744}
745
746/*************************************************
747 * Message out defs
748 *************************************************/
749/* XXX: use scsi_message.h */
750#define	ST_GOOD		0x00
751#define	ST_CHKCOND	0x02
752#define	ST_MET		0x04
753#define	ST_BUSY		0x08
754#define	ST_INTERGOOD	0x10
755#define	ST_INTERMET	0x14
756#define	ST_CONFLICT	0x18
757#define	ST_CMDTERM	0x22
758#define	ST_QUEFULL	0x28
759#define	ST_UNKNOWN	0xff
760
761#define	MSG_COMP	0x00
762#define	MSG_EXTEND	0x01
763
764#define	MKMSG_EXTEND(XLEN, XCODE) ((((u_int)(XLEN)) << NBBY) | ((u_int)(XCODE)))
765#define	MSG_EXTEND_MDPCODE	0x00
766#define	MSG_EXTEND_MDPLEN	0x05
767#define	MSG_EXTEND_SYNCHCODE	0x01
768#define	MSG_EXTEND_SYNCHLEN	0x03
769#define	MSG_EXTEND_WIDECODE	0x03
770#define	MSG_EXTEND_WIDELEN	0x02
771
772#define	MSG_SAVESP	0x02
773#define	MSG_RESTORESP	0x03
774#define	MSG_DISCON	0x04
775#define	MSG_I_ERROR	0x05
776#define	MSG_ABORT	0x06
777#define	MSG_REJECT	0x07
778#define	MSG_NOOP	0x08
779#define	MSG_PARITY	0x09
780#define	MSG_LCOMP	0x0a
781#define	MSG_LCOMP_F	0x0b
782#define	MSG_RESET	0x0c
783#define	MSG_ABORT_QTAG	0x0d
784#define	MSG_CLEAR_QTAG	0x0e
785#define	MSG_TERM_IO	0x11
786#define	MSG_SIMPLE_QTAG	0x20
787#define	MSG_HEAD_QTAG	0x21
788#define	MSG_ORDERED_QTAG	0x22
789#define	MSG_IDENTIFY	  	0x80
790#define	MSG_IDENTIFY_DISCPRIV	0x40
791#endif	/* !_SCSI_LOW_H_ */
792