Deleted Added
sdiff udiff text old ( 163896 ) new ( 168752 )
full compact
1/* $NecBSD: scsi_low.c,v 1.24.10.8 2001/06/26 07:39:44 honda Exp $ */
2/* $NetBSD$ */
3
4#include <sys/cdefs.h>
5__FBSDID("$FreeBSD: head/sys/cam/scsi/scsi_low.c 168752 2007-04-15 08:49:19Z scottl $");
6
7#define SCSI_LOW_STATICS
8#define SCSI_LOW_DEBUG
9#define SCSI_LOW_NEGOTIATE_BEFORE_SENSE
10#define SCSI_LOW_START_UP_CHECK
11
12/* #define SCSI_LOW_INFO_DETAIL */
13
14/* #define SCSI_LOW_QCLEAR_AFTER_CA */
15/* #define SCSI_LOW_FLAGS_QUIRKS_OK */
16
17#ifdef __NetBSD__
18#define SCSI_LOW_TARGET_OPEN
19#endif /* __NetBSD__ */
20
21#ifdef __FreeBSD__
22#define SCSI_LOW_FLAGS_QUIRKS_OK
23#endif /* __FreeBSD__ */
24
25/*-
26 * [NetBSD for NEC PC-98 series]
27 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
28 * NetBSD/pc98 porting staff. All rights reserved.
29 * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001
30 * Naofumi HONDA. All rights reserved.
31 *
32 * [Ported for FreeBSD CAM]
33 * Copyright (c) 2000, 2001
34 * MITSUNAGA Noriaki, NOKUBI Hirotaka and TAKAHASHI Yoshihiro.
35 * All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. The name of the author may not be used to endorse or promote products
46 * derived from this software without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
49 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
50 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
51 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
52 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
53 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
54 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
56 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
57 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
58 * POSSIBILITY OF SUCH DAMAGE.
59 */
60
61/* <On the nexus establishment>
62 * When our host is reselected,
63 * nexus establish processes are little complicated.
64 * Normal steps are followings:
65 * 1) Our host selected by target => target nexus (slp->sl_Tnexus)
66 * 2) Identify msgin => lun nexus (slp->sl_Lnexus)
67 * 3) Qtag msg => ccb nexus (slp->sl_Qnexus)
68 */
69#include "opt_ddb.h"
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/kernel.h>
74
75#ifdef __FreeBSD__
76#if __FreeBSD_version >= 500001
77#include <sys/bio.h>
78#else
79#include <machine/clock.h>
80#endif
81#endif /* __FreeBSD__ */
82
83#include <sys/buf.h>
84#include <sys/queue.h>
85#include <sys/malloc.h>
86#include <sys/errno.h>
87
88#ifdef __NetBSD__
89#include <sys/device.h>
90#include <vm/vm.h>
91
92#include <machine/bus.h>
93#include <machine/intr.h>
94#include <machine/dvcfg.h>
95
96#include <dev/cons.h>
97
98#include <dev/scsipi/scsipi_all.h>
99#include <dev/scsipi/scsipiconf.h>
100#include <dev/scsipi/scsipi_disk.h>
101#include <dev/scsipi/scsi_all.h>
102#include <dev/scsipi/scsiconf.h>
103#include <sys/scsiio.h>
104
105#include <i386/Cbus/dev/scsi_low.h>
106#endif /* __NetBSD__ */
107
108#ifdef __FreeBSD__
109#include <cam/cam.h>
110#include <cam/cam_ccb.h>
111#include <cam/cam_sim.h>
112#include <cam/cam_debug.h>
113#include <cam/cam_periph.h>
114#include <cam/cam_xpt_periph.h>
115
116#include <cam/scsi/scsi_all.h>
117#include <cam/scsi/scsi_message.h>
118
119#include <cam/scsi/scsi_low.h>
120
121#include <sys/cons.h>
122#endif /* __FreeBSD__ */
123
124/**************************************************************
125 * Constants
126 **************************************************************/
127#define SCSI_LOW_POLL_HZ 1000
128
129/* functions return values */
130#define SCSI_LOW_START_NO_QTAG 0
131#define SCSI_LOW_START_QTAG 1
132
133#define SCSI_LOW_DONE_COMPLETE 0
134#define SCSI_LOW_DONE_RETRY 1
135
136/* internal disk flags */
137#define SCSI_LOW_DISK_DISC 0x00000001
138#define SCSI_LOW_DISK_QTAG 0x00000002
139#define SCSI_LOW_DISK_LINK 0x00000004
140#define SCSI_LOW_DISK_PARITY 0x00000008
141#define SCSI_LOW_DISK_SYNC 0x00010000
142#define SCSI_LOW_DISK_WIDE_16 0x00020000
143#define SCSI_LOW_DISK_WIDE_32 0x00040000
144#define SCSI_LOW_DISK_WIDE (SCSI_LOW_DISK_WIDE_16 | SCSI_LOW_DISK_WIDE_32)
145#define SCSI_LOW_DISK_LFLAGS 0x0000ffff
146#define SCSI_LOW_DISK_TFLAGS 0xffff0000
147
148MALLOC_DEFINE(M_SCSILOW, "SCSI low", "SCSI low buffers");
149
150/**************************************************************
151 * Declarations
152 **************************************************************/
153/* static */ void scsi_low_info(struct scsi_low_softc *, struct targ_info *, u_char *);
154static void scsi_low_engage(void *);
155static struct slccb *scsi_low_establish_ccb(struct targ_info *, struct lun_info *, scsi_low_tag_t);
156static int scsi_low_done(struct scsi_low_softc *, struct slccb *);
157static int scsi_low_setup_done(struct scsi_low_softc *, struct slccb *);
158static void scsi_low_bus_release(struct scsi_low_softc *, struct targ_info *);
159static void scsi_low_twiddle_wait(void);
160static struct lun_info *scsi_low_alloc_li(struct targ_info *, int, int);
161static struct targ_info *scsi_low_alloc_ti(struct scsi_low_softc *, int);
162static void scsi_low_calcf_lun(struct lun_info *);
163static void scsi_low_calcf_target(struct targ_info *);
164static void scsi_low_calcf_show(struct lun_info *);
165static void scsi_low_reset_nexus(struct scsi_low_softc *, int);
166static void scsi_low_reset_nexus_target(struct scsi_low_softc *, struct targ_info *, int);
167static void scsi_low_reset_nexus_lun(struct scsi_low_softc *, struct lun_info *, int);
168static int scsi_low_init(struct scsi_low_softc *, u_int);
169static void scsi_low_start(struct scsi_low_softc *);
170static void scsi_low_free_ti(struct scsi_low_softc *);
171
172static int scsi_low_alloc_qtag(struct slccb *);
173static int scsi_low_dealloc_qtag(struct slccb *);
174static int scsi_low_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *, u_int, u_int);
175static int scsi_low_message_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, u_int);
176static void scsi_low_unit_ready_cmd(struct slccb *);
177static void scsi_low_timeout(void *);
178static int scsi_low_timeout_check(struct scsi_low_softc *);
179#ifdef SCSI_LOW_START_UP_CHECK
180static int scsi_low_start_up(struct scsi_low_softc *);
181#endif /* SCSI_LOW_START_UP_CHECK */
182static int scsi_low_abort_ccb(struct scsi_low_softc *, struct slccb *);
183static struct slccb *scsi_low_revoke_ccb(struct scsi_low_softc *, struct slccb *, int);
184
185int scsi_low_version_major = 2;
186int scsi_low_version_minor = 17;
187
188static struct scsi_low_softc_tab sl_tab = LIST_HEAD_INITIALIZER(sl_tab);
189
190/**************************************************************
191 * Debug, Run test and Statics
192 **************************************************************/
193#ifdef SCSI_LOW_INFO_DETAIL
194#define SCSI_LOW_INFO(slp, ti, s) scsi_low_info((slp), (ti), (s))
195#else /* !SCSI_LOW_INFO_DETAIL */
196#define SCSI_LOW_INFO(slp, ti, s) printf("%s: %s\n", (slp)->sl_xname, (s))
197#endif /* !SCSI_LOW_INFO_DETAIL */
198
199#ifdef SCSI_LOW_STATICS
200static struct scsi_low_statics {
201 int nexus_win;
202 int nexus_fail;
203 int nexus_disconnected;
204 int nexus_reselected;
205 int nexus_conflict;
206} scsi_low_statics;
207#endif /* SCSI_LOW_STATICS */
208
209#ifdef SCSI_LOW_DEBUG
210#define SCSI_LOW_DEBUG_DONE 0x00001
211#define SCSI_LOW_DEBUG_DISC 0x00002
212#define SCSI_LOW_DEBUG_SENSE 0x00004
213#define SCSI_LOW_DEBUG_CALCF 0x00008
214#define SCSI_LOW_DEBUG_ACTION 0x10000
215int scsi_low_debug = 0;
216
217#define SCSI_LOW_MAX_ATTEN_CHECK 32
218#define SCSI_LOW_ATTEN_CHECK 0x0001
219#define SCSI_LOW_CMDLNK_CHECK 0x0002
220#define SCSI_LOW_ABORT_CHECK 0x0004
221#define SCSI_LOW_NEXUS_CHECK 0x0008
222int scsi_low_test = 0;
223int scsi_low_test_id = 0;
224
225static void scsi_low_test_abort(struct scsi_low_softc *, struct targ_info *, struct lun_info *);
226static void scsi_low_test_cmdlnk(struct scsi_low_softc *, struct slccb *);
227static void scsi_low_test_atten(struct scsi_low_softc *, struct targ_info *, u_int);
228#define SCSI_LOW_DEBUG_TEST_GO(fl, id) \
229 ((scsi_low_test & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0)
230#define SCSI_LOW_DEBUG_GO(fl, id) \
231 ((scsi_low_debug & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0)
232#endif /* SCSI_LOW_DEBUG */
233
234/**************************************************************
235 * CCB
236 **************************************************************/
237GENERIC_CCB_STATIC_ALLOC(scsi_low, slccb)
238GENERIC_CCB(scsi_low, slccb, ccb_chain)
239
240/**************************************************************
241 * Inline functions
242 **************************************************************/
243#define SCSI_LOW_INLINE static __inline
244SCSI_LOW_INLINE void scsi_low_activate_qtag(struct slccb *);
245SCSI_LOW_INLINE void scsi_low_deactivate_qtag(struct slccb *);
246SCSI_LOW_INLINE void scsi_low_ccb_message_assert(struct slccb *, u_int);
247SCSI_LOW_INLINE void scsi_low_ccb_message_exec(struct scsi_low_softc *, struct slccb *);
248SCSI_LOW_INLINE void scsi_low_ccb_message_retry(struct slccb *);
249SCSI_LOW_INLINE void scsi_low_ccb_message_clear(struct slccb *);
250SCSI_LOW_INLINE void scsi_low_init_msgsys(struct scsi_low_softc *, struct targ_info *);
251
252SCSI_LOW_INLINE void
253scsi_low_activate_qtag(cb)
254 struct slccb *cb;
255{
256 struct lun_info *li = cb->li;
257
258 if (cb->ccb_tag != SCSI_LOW_UNKTAG)
259 return;
260
261 li->li_nqio ++;
262 cb->ccb_tag = cb->ccb_otag;
263}
264
265SCSI_LOW_INLINE void
266scsi_low_deactivate_qtag(cb)
267 struct slccb *cb;
268{
269 struct lun_info *li = cb->li;
270
271 if (cb->ccb_tag == SCSI_LOW_UNKTAG)
272 return;
273
274 li->li_nqio --;
275 cb->ccb_tag = SCSI_LOW_UNKTAG;
276}
277
278SCSI_LOW_INLINE void
279scsi_low_ccb_message_exec(slp, cb)
280 struct scsi_low_softc *slp;
281 struct slccb *cb;
282{
283
284 scsi_low_assert_msg(slp, cb->ti, cb->ccb_msgoutflag, 0);
285 cb->ccb_msgoutflag = 0;
286}
287
288SCSI_LOW_INLINE void
289scsi_low_ccb_message_assert(cb, msg)
290 struct slccb *cb;
291 u_int msg;
292{
293
294 cb->ccb_msgoutflag = cb->ccb_omsgoutflag = msg;
295}
296
297SCSI_LOW_INLINE void
298scsi_low_ccb_message_retry(cb)
299 struct slccb *cb;
300{
301 cb->ccb_msgoutflag = cb->ccb_omsgoutflag;
302}
303
304SCSI_LOW_INLINE void
305scsi_low_ccb_message_clear(cb)
306 struct slccb *cb;
307{
308 cb->ccb_msgoutflag = 0;
309}
310
311SCSI_LOW_INLINE void
312scsi_low_init_msgsys(slp, ti)
313 struct scsi_low_softc *slp;
314 struct targ_info *ti;
315{
316
317 ti->ti_msginptr = 0;
318 ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0;
319 SCSI_LOW_DEASSERT_ATN(slp);
320 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL);
321}
322
323/*=============================================================
324 * START OF OS switch (All OS depend fucntions should be here)
325 =============================================================*/
326/* common os depend utitlities */
327#define SCSI_LOW_CMD_RESIDUAL_CHK 0x0001
328#define SCSI_LOW_CMD_ORDERED_QTAG 0x0002
329#define SCSI_LOW_CMD_ABORT_WARNING 0x0004
330
331static u_int8_t scsi_low_cmd_flags[256] = {
332/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
333/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0,
334/*1*/ 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
335/*2*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 5, 5,
336/*3*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5,
337};
338
339struct scsi_low_error_code {
340 int error_bits;
341 int error_code;
342};
343
344static struct slccb *scsi_low_find_ccb(struct scsi_low_softc *, u_int, u_int, void *);
345static int scsi_low_translate_error_code(struct slccb *, struct scsi_low_error_code *);
346
347static struct slccb *
348scsi_low_find_ccb(slp, target, lun, osdep)
349 struct scsi_low_softc *slp;
350 u_int target, lun;
351 void *osdep;
352{
353 struct targ_info *ti;
354 struct lun_info *li;
355 struct slccb *cb;
356
357 ti = slp->sl_ti[target];
358 li = scsi_low_alloc_li(ti, lun, 0);
359 if (li == NULL)
360 return NULL;
361
362 if ((cb = slp->sl_Qnexus) != NULL && cb->osdep == osdep)
363 return cb;
364
365 for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL;
366 cb = TAILQ_NEXT(cb, ccb_chain))
367 {
368 if (cb->osdep == osdep)
369 return cb;
370 }
371
372 for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL;
373 cb = TAILQ_NEXT(cb, ccb_chain))
374 {
375 if (cb->osdep == osdep)
376 return cb;
377 }
378 return NULL;
379}
380
381static int
382scsi_low_translate_error_code(cb, tp)
383 struct slccb *cb;
384 struct scsi_low_error_code *tp;
385{
386
387 if (cb->ccb_error == 0)
388 return tp->error_code;
389
390 for (tp ++; (cb->ccb_error & tp->error_bits) == 0; tp ++)
391 ;
392 return tp->error_code;
393}
394
395#ifdef SCSI_LOW_INTERFACE_XS
396/**************************************************************
397 * SCSI INTERFACE (XS)
398 **************************************************************/
399#define SCSI_LOW_MINPHYS 0x10000
400#define SCSI_LOW_MALLOC(size) malloc((size), M_SCSILOW, M_NOWAIT)
401#define SCSI_LOW_FREE(pt) free((pt), M_SCSILOW)
402#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb((flags))
403#define SCSI_LOW_XS_POLL_HZ 1000
404
405static int scsi_low_poll_xs(struct scsi_low_softc *, struct slccb *);
406static void scsi_low_scsi_minphys_xs(struct buf *);
407#ifdef SCSI_LOW_TARGET_OPEN
408static int scsi_low_target_open(struct scsipi_link *, struct cfdata *);
409#endif /* SCSI_LOW_TARGET_OPEN */
410static int scsi_low_scsi_cmd_xs(struct scsipi_xfer *);
411static int scsi_low_enable_xs(void *, int);
412static int scsi_low_ioctl_xs(struct scsipi_link *, u_long, caddr_t, int, struct proc *);
413
414static int scsi_low_attach_xs(struct scsi_low_softc *);
415static int scsi_low_world_start_xs(struct scsi_low_softc *);
416static int scsi_low_dettach_xs(struct scsi_low_softc *);
417static int scsi_low_ccb_setup_xs(struct scsi_low_softc *, struct slccb *);
418static int scsi_low_done_xs(struct scsi_low_softc *, struct slccb *);
419static void scsi_low_timeout_xs(struct scsi_low_softc *, int, int);
420static u_int scsi_low_translate_quirks_xs(u_int);
421static void scsi_low_setup_quirks_xs(struct targ_info *, struct lun_info *, u_int);
422
423struct scsi_low_osdep_funcs scsi_low_osdep_funcs_xs = {
424 scsi_low_attach_xs,
425 scsi_low_world_start_xs,
426 scsi_low_dettach_xs,
427 scsi_low_ccb_setup_xs,
428 scsi_low_done_xs,
429 scsi_low_timeout_xs
430};
431
432struct scsipi_device scsi_low_dev = {
433 NULL, /* Use default error handler */
434 NULL, /* have a queue, served by this */
435 NULL, /* have no async handler */
436 NULL, /* Use default 'done' routine */
437};
438
439struct scsi_low_error_code scsi_low_error_code_xs[] = {
440 {0, XS_NOERROR},
441 {SENSEIO, XS_SENSE},
442 {BUSYERR, XS_BUSY },
443 {SELTIMEOUTIO, XS_SELTIMEOUT},
444 {TIMEOUTIO, XS_TIMEOUT},
445 {-1, XS_DRIVER_STUFFUP}
446};
447
448static int
449scsi_low_ioctl_xs(link, cmd, addr, flag, p)
450 struct scsipi_link *link;
451 u_long cmd;
452 caddr_t addr;
453 int flag;
454 struct proc *p;
455{
456 struct scsi_low_softc *slp;
457 int s, error = ENOTTY;
458
459 slp = (struct scsi_low_softc *) link->adapter_softc;
460 if ((slp->sl_flags & HW_INACTIVE) != 0)
461 return ENXIO;
462
463 if (cmd == SCBUSIORESET)
464 {
465 s = SCSI_LOW_SPLSCSI();
466 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL);
467 splx(s);
468 error = 0;
469 }
470 else if (slp->sl_funcs->scsi_low_ioctl != 0)
471 {
472 error = (*slp->sl_funcs->scsi_low_ioctl)
473 (slp, cmd, addr, flag, p);
474 }
475
476 return error;
477}
478
479static int
480scsi_low_enable_xs(arg, enable)
481 void *arg;
482 int enable;
483{
484 struct scsi_low_softc *slp = arg;
485
486 if (enable != 0)
487 {
488 if ((slp->sl_flags & HW_INACTIVE) != 0)
489 return ENXIO;
490 }
491 else
492 {
493 if ((slp->sl_flags & HW_INACTIVE) != 0 ||
494 (slp->sl_flags & HW_POWERCTRL) == 0)
495 return 0;
496
497 slp->sl_flags |= HW_POWDOWN;
498 if (slp->sl_funcs->scsi_low_power != NULL)
499 {
500 (*slp->sl_funcs->scsi_low_power)
501 (slp, SCSI_LOW_POWDOWN);
502 }
503 }
504 return 0;
505}
506
507static void
508scsi_low_scsi_minphys_xs(bp)
509 struct buf *bp;
510{
511
512 if (bp->b_bcount > SCSI_LOW_MINPHYS)
513 bp->b_bcount = SCSI_LOW_MINPHYS;
514 minphys(bp);
515}
516
517static int
518scsi_low_poll_xs(slp, cb)
519 struct scsi_low_softc *slp;
520 struct slccb *cb;
521{
522 struct scsipi_xfer *xs = cb->osdep;
523 int tcount;
524
525 cb->ccb_flags |= CCB_NOSDONE;
526 tcount = 0;
527
528 while (slp->sl_nio > 0)
529 {
530 SCSI_LOW_DELAY((1000 * 1000) / SCSI_LOW_XS_POLL_HZ);
531
532 (*slp->sl_funcs->scsi_low_poll) (slp);
533
534 if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0)
535 {
536 cb->ccb_flags |= CCB_NORETRY;
537 cb->ccb_error |= FATALIO;
538 (void) scsi_low_revoke_ccb(slp, cb, 1);
539 printf("%s: hardware inactive in poll mode\n",
540 slp->sl_xname);
541 }
542
543 if ((xs->flags & ITSDONE) != 0)
544 break;
545
546 if (tcount ++ < SCSI_LOW_XS_POLL_HZ / SCSI_LOW_TIMEOUT_HZ)
547 continue;
548
549 tcount = 0;
550 scsi_low_timeout_check(slp);
551 }
552
553 xs->flags |= ITSDONE;
554 scsipi_done(xs);
555 return COMPLETE;
556}
557
558static int
559scsi_low_scsi_cmd_xs(xs)
560 struct scsipi_xfer *xs;
561{
562 struct scsipi_link *splp = xs->sc_link;
563 struct scsi_low_softc *slp = splp->adapter_softc;
564 struct targ_info *ti;
565 struct lun_info *li;
566 struct slccb *cb;
567 int s, targ, lun, flags, rv;
568
569 if ((cb = SCSI_LOW_ALLOC_CCB(xs->flags & SCSI_NOSLEEP)) == NULL)
570 return TRY_AGAIN_LATER;
571
572 targ = splp->scsipi_scsi.target,
573 lun = splp->scsipi_scsi.lun;
574 ti = slp->sl_ti[targ];
575
576 cb->osdep = xs;
577 cb->bp = xs->bp;
578
579 if ((xs->flags & SCSI_POLL) == 0)
580 flags = CCB_AUTOSENSE;
581 else
582 flags = CCB_AUTOSENSE | CCB_POLLED;
583
584
585 s = SCSI_LOW_SPLSCSI();
586 li = scsi_low_alloc_li(ti, lun, 1);
587 if ((u_int) splp->quirks != li->li_sloi.sloi_quirks)
588 {
589 scsi_low_setup_quirks_xs(ti, li, (u_int) splp->quirks);
590 }
591
592 if ((xs->flags & SCSI_RESET) != 0)
593 {
594 flags |= CCB_NORETRY | CCB_URGENT;
595 scsi_low_enqueue(slp, ti, li, cb, flags, SCSI_LOW_MSG_RESET);
596 }
597 else
598 {
599 if (ti->ti_setup_msg != 0)
600 {
601 scsi_low_message_enqueue(slp, ti, li, flags);
602 }
603
604 flags |= CCB_SCSIIO;
605 scsi_low_enqueue(slp, ti, li, cb, flags, 0);
606 }
607
608#ifdef SCSI_LOW_DEBUG
609 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, ti->ti_id) != 0)
610 {
611 scsi_low_test_abort(slp, ti, li);
612 }
613#endif /* SCSI_LOW_DEBUG */
614
615 if ((cb->ccb_flags & CCB_POLLED) != 0)
616 {
617 rv = scsi_low_poll_xs(slp, cb);
618 }
619 else
620 {
621 rv = SUCCESSFULLY_QUEUED;
622 }
623 splx(s);
624 return rv;
625}
626
627static int
628scsi_low_attach_xs(slp)
629 struct scsi_low_softc *slp;
630{
631 struct scsipi_adapter *sap;
632 struct scsipi_link *splp;
633
634 strncpy(slp->sl_xname, slp->sl_dev.dv_xname, 16);
635
636 sap = SCSI_LOW_MALLOC(sizeof(*sap));
637 if (sap == NULL)
638 return ENOMEM;
639 splp = SCSI_LOW_MALLOC(sizeof(*splp));
640 if (splp == NULL)
641 return ENOMEM;
642
643 SCSI_LOW_BZERO(sap, sizeof(*sap));
644 SCSI_LOW_BZERO(splp, sizeof(*splp));
645
646 sap->scsipi_cmd = scsi_low_scsi_cmd_xs;
647 sap->scsipi_minphys = scsi_low_scsi_minphys_xs;
648 sap->scsipi_enable = scsi_low_enable_xs;
649 sap->scsipi_ioctl = scsi_low_ioctl_xs;
650#ifdef SCSI_LOW_TARGET_OPEN
651 sap->open_target_lu = scsi_low_target_open;
652#endif /* SCSI_LOW_TARGET_OPEN */
653
654 splp->adapter_softc = slp;
655 splp->scsipi_scsi.adapter_target = slp->sl_hostid;
656 splp->scsipi_scsi.max_target = slp->sl_ntargs - 1;
657 splp->scsipi_scsi.max_lun = slp->sl_nluns - 1;
658 splp->scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
659 splp->openings = slp->sl_openings;
660 splp->type = BUS_SCSI;
661 splp->adapter_softc = slp;
662 splp->adapter = sap;
663 splp->device = &scsi_low_dev;
664
665 slp->sl_si.si_splp = splp;
666 slp->sl_show_result = SHOW_ALL_NEG;
667 return 0;
668}
669
670static int
671scsi_low_world_start_xs(slp)
672 struct scsi_low_softc *slp;
673{
674
675 return 0;
676}
677
678static int
679scsi_low_dettach_xs(slp)
680 struct scsi_low_softc *slp;
681{
682
683 /*
684 * scsipi does not have dettach bus fucntion.
685 *
686 scsipi_dettach_scsibus(slp->sl_si.si_splp);
687 */
688 return 0;
689}
690
691static int
692scsi_low_ccb_setup_xs(slp, cb)
693 struct scsi_low_softc *slp;
694 struct slccb *cb;
695{
696 struct scsipi_xfer *xs = (struct scsipi_xfer *) cb->osdep;
697
698 if ((cb->ccb_flags & CCB_SCSIIO) != 0)
699 {
700 cb->ccb_scp.scp_cmd = (u_int8_t *) xs->cmd;
701 cb->ccb_scp.scp_cmdlen = xs->cmdlen;
702 cb->ccb_scp.scp_data = xs->data;
703 cb->ccb_scp.scp_datalen = xs->datalen;
704 cb->ccb_scp.scp_direction = (xs->flags & SCSI_DATA_OUT) ?
705 SCSI_LOW_WRITE : SCSI_LOW_READ;
706 cb->ccb_tcmax = xs->timeout / 1000;
707 }
708 else
709 {
710 scsi_low_unit_ready_cmd(cb);
711 }
712 return SCSI_LOW_START_QTAG;
713}
714
715static int
716scsi_low_done_xs(slp, cb)
717 struct scsi_low_softc *slp;
718 struct slccb *cb;
719{
720 struct scsipi_xfer *xs;
721
722 xs = (struct scsipi_xfer *) cb->osdep;
723 if (cb->ccb_error == 0)
724 {
725 xs->error = XS_NOERROR;
726 xs->resid = 0;
727 }
728 else
729 {
730 if (cb->ccb_rcnt >= slp->sl_max_retry)
731 cb->ccb_error |= ABORTIO;
732
733 if ((cb->ccb_flags & CCB_NORETRY) == 0 &&
734 (cb->ccb_error & ABORTIO) == 0)
735 return EJUSTRETURN;
736
737 if ((cb->ccb_error & SENSEIO) != 0)
738 {
739 xs->sense.scsi_sense = cb->ccb_sense;
740 }
741
742 xs->error = scsi_low_translate_error_code(cb,
743 &scsi_low_error_code_xs[0]);
744
745#ifdef SCSI_LOW_DIAGNOSTIC
746 if ((cb->ccb_flags & CCB_SILENT) == 0 &&
747 cb->ccb_scp.scp_cmdlen > 0 &&
748 (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] &
749 SCSI_LOW_CMD_ABORT_WARNING) != 0)
750 {
751 printf("%s: WARNING: scsi_low IO abort\n",
752 slp->sl_xname);
753 scsi_low_print(slp, NULL);
754 }
755#endif /* SCSI_LOW_DIAGNOSTIC */
756 }
757
758 if (cb->ccb_scp.scp_status == ST_UNKNOWN)
759 xs->status = 0; /* XXX */
760 else
761 xs->status = cb->ccb_scp.scp_status;
762
763 xs->flags |= ITSDONE;
764 if ((cb->ccb_flags & CCB_NOSDONE) == 0)
765 scsipi_done(xs);
766
767 return 0;
768}
769
770static void
771scsi_low_timeout_xs(slp, ch, action)
772 struct scsi_low_softc *slp;
773 int ch;
774 int action;
775{
776
777 switch (ch)
778 {
779 case SCSI_LOW_TIMEOUT_CH_IO:
780 switch (action)
781 {
782 case SCSI_LOW_TIMEOUT_START:
783 timeout(scsi_low_timeout, slp,
784 hz / SCSI_LOW_TIMEOUT_HZ);
785 break;
786 case SCSI_LOW_TIMEOUT_STOP:
787 untimeout(scsi_low_timeout, slp);
788 break;
789 }
790 break;
791
792 case SCSI_LOW_TIMEOUT_CH_ENGAGE:
793 switch (action)
794 {
795 case SCSI_LOW_TIMEOUT_START:
796 timeout(scsi_low_engage, slp, 1);
797 break;
798 case SCSI_LOW_TIMEOUT_STOP:
799 untimeout(scsi_low_engage, slp);
800 break;
801 }
802 break;
803
804 case SCSI_LOW_TIMEOUT_CH_RECOVER:
805 break;
806 }
807}
808
809u_int
810scsi_low_translate_quirks_xs(quirks)
811 u_int quirks;
812{
813 u_int flags;
814
815 flags = SCSI_LOW_DISK_LFLAGS | SCSI_LOW_DISK_TFLAGS;
816
817#ifdef SDEV_NODISC
818 if (quirks & SDEV_NODISC)
819 flags &= ~SCSI_LOW_DISK_DISC;
820#endif /* SDEV_NODISC */
821#ifdef SDEV_NOPARITY
822 if (quirks & SDEV_NOPARITY)
823 flags &= ~SCSI_LOW_DISK_PARITY;
824#endif /* SDEV_NOPARITY */
825#ifdef SDEV_NOCMDLNK
826 if (quirks & SDEV_NOCMDLNK)
827 flags &= ~SCSI_LOW_DISK_LINK;
828#endif /* SDEV_NOCMDLNK */
829#ifdef SDEV_NOTAG
830 if (quirks & SDEV_NOTAG)
831 flags &= ~SCSI_LOW_DISK_QTAG;
832#endif /* SDEV_NOTAG */
833#ifdef SDEV_NOSYNC
834 if (quirks & SDEV_NOSYNC)
835 flags &= ~SCSI_LOW_DISK_SYNC;
836#endif /* SDEV_NOSYNC */
837
838 return flags;
839}
840
841static void
842scsi_low_setup_quirks_xs(ti, li, flags)
843 struct targ_info *ti;
844 struct lun_info *li;
845 u_int flags;
846{
847 u_int quirks;
848
849 li->li_sloi.sloi_quirks = flags;
850 quirks = scsi_low_translate_quirks_xs(flags);
851 ti->ti_quirks = quirks & SCSI_LOW_DISK_TFLAGS;
852 li->li_quirks = quirks & SCSI_LOW_DISK_LFLAGS;
853 ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID;
854 li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID;
855 scsi_low_calcf_target(ti);
856 scsi_low_calcf_lun(li);
857 scsi_low_calcf_show(li);
858}
859
860#ifdef SCSI_LOW_TARGET_OPEN
861static int
862scsi_low_target_open(link, cf)
863 struct scsipi_link *link;
864 struct cfdata *cf;
865{
866 u_int target = link->scsipi_scsi.target;
867 u_int lun = link->scsipi_scsi.lun;
868 struct scsi_low_softc *slp;
869 struct targ_info *ti;
870 struct lun_info *li;
871
872 slp = (struct scsi_low_softc *) link->adapter_softc;
873 ti = slp->sl_ti[target];
874 li = scsi_low_alloc_li(ti, lun, 0);
875 if (li == NULL)
876 return 0;
877
878 li->li_cfgflags = cf->cf_flags;
879 scsi_low_setup_quirks_xs(ti, li, (u_int) link->quirks);
880 return 0;
881}
882#endif /* SCSI_LOW_TARGET_OPEN */
883
884#endif /* SCSI_LOW_INTERFACE_XS */
885
886#ifdef SCSI_LOW_INTERFACE_CAM
887/**************************************************************
888 * SCSI INTERFACE (CAM)
889 **************************************************************/
890#define SCSI_LOW_MALLOC(size) malloc((size), M_SCSILOW, M_NOWAIT)
891#define SCSI_LOW_FREE(pt) free((pt), M_SCSILOW)
892#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb()
893
894static void scsi_low_poll_cam(struct cam_sim *);
895static void scsi_low_cam_rescan_callback(struct cam_periph *, union ccb *);
896static void scsi_low_rescan_bus_cam(struct scsi_low_softc *);
897void scsi_low_scsi_action_cam(struct cam_sim *, union ccb *);
898
899static int scsi_low_attach_cam(struct scsi_low_softc *);
900static int scsi_low_world_start_cam(struct scsi_low_softc *);
901static int scsi_low_dettach_cam(struct scsi_low_softc *);
902static int scsi_low_ccb_setup_cam(struct scsi_low_softc *, struct slccb *);
903static int scsi_low_done_cam(struct scsi_low_softc *, struct slccb *);
904static void scsi_low_timeout_cam(struct scsi_low_softc *, int, int);
905
906struct scsi_low_osdep_funcs scsi_low_osdep_funcs_cam = {
907 scsi_low_attach_cam,
908 scsi_low_world_start_cam,
909 scsi_low_dettach_cam,
910 scsi_low_ccb_setup_cam,
911 scsi_low_done_cam,
912 scsi_low_timeout_cam
913};
914
915struct scsi_low_error_code scsi_low_error_code_cam[] = {
916 {0, CAM_REQ_CMP},
917 {SENSEIO, CAM_AUTOSNS_VALID | CAM_REQ_CMP_ERR},
918 {SENSEERR, CAM_AUTOSENSE_FAIL},
919 {UACAERR, CAM_SCSI_STATUS_ERROR},
920 {BUSYERR | STATERR, CAM_SCSI_STATUS_ERROR},
921 {SELTIMEOUTIO, CAM_SEL_TIMEOUT},
922 {TIMEOUTIO, CAM_CMD_TIMEOUT},
923 {PDMAERR, CAM_DATA_RUN_ERR},
924 {PARITYERR, CAM_UNCOR_PARITY},
925 {UBFERR, CAM_UNEXP_BUSFREE},
926 {ABORTIO, CAM_REQ_ABORTED},
927 {-1, CAM_UNREC_HBA_ERROR}
928};
929
930#define SIM2SLP(sim) ((struct scsi_low_softc *) cam_sim_softc((sim)))
931
932/* XXX:
933 * Please check a polling hz, currently we assume scsi_low_poll() is
934 * called each 1 ms.
935 */
936#define SCSI_LOW_CAM_POLL_HZ 1000 /* OK ? */
937
938static void
939scsi_low_poll_cam(sim)
940 struct cam_sim *sim;
941{
942 struct scsi_low_softc *slp = SIM2SLP(sim);
943
944 (*slp->sl_funcs->scsi_low_poll) (slp);
945
946 if (slp->sl_si.si_poll_count ++ >=
947 SCSI_LOW_CAM_POLL_HZ / SCSI_LOW_TIMEOUT_HZ)
948 {
949 slp->sl_si.si_poll_count = 0;
950 scsi_low_timeout_check(slp);
951 }
952}
953
954static void
955scsi_low_cam_rescan_callback(periph, ccb)
956 struct cam_periph *periph;
957 union ccb *ccb;
958{
959
960 xpt_free_path(ccb->ccb_h.path);
961 xpt_free_ccb(ccb);
962}
963
964static void
965scsi_low_rescan_bus_cam(slp)
966 struct scsi_low_softc *slp;
967{
968 struct cam_path *path;
969 union ccb *ccb = xpt_alloc_ccb(NULL);
970 cam_status status;
971
972 bzero(ccb, sizeof(union ccb));
973
974 status = xpt_create_path(&path, xpt_periph,
975 cam_sim_path(slp->sl_si.sim), -1, 0);
976 if (status != CAM_REQ_CMP)
977 return;
978
979 xpt_setup_ccb(&ccb->ccb_h, path, 5);
980 ccb->ccb_h.func_code = XPT_SCAN_BUS;
981 ccb->ccb_h.cbfcnp = scsi_low_cam_rescan_callback;
982 ccb->crcn.flags = CAM_FLAG_NONE;
983 xpt_action(ccb);
984}
985
986void
987scsi_low_scsi_action_cam(sim, ccb)
988 struct cam_sim *sim;
989 union ccb *ccb;
990{
991 struct scsi_low_softc *slp = SIM2SLP(sim);
992 struct targ_info *ti;
993 struct lun_info *li;
994 struct slccb *cb;
995 u_int lun, flags, msg, target;
996 int s, rv;
997
998 target = (u_int) (ccb->ccb_h.target_id);
999 lun = (u_int) ccb->ccb_h.target_lun;
1000
1001#ifdef SCSI_LOW_DEBUG
1002 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_ACTION, target) != 0)
1003 {
1004 printf("%s: cam_action: func code 0x%x target: %d, lun: %d\n",
1005 slp->sl_xname, ccb->ccb_h.func_code, target, lun);
1006 }
1007#endif /* SCSI_LOW_DEBUG */
1008
1009 switch (ccb->ccb_h.func_code) {
1010 case XPT_SCSI_IO: /* Execute the requested I/O operation */
1011#ifdef SCSI_LOW_DIAGNOSTIC
1012 if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD)
1013 {
1014 printf("%s: invalid target/lun\n", slp->sl_xname);
1015 ccb->ccb_h.status = CAM_REQ_INVALID;
1016 xpt_done(ccb);
1017 return;
1018 }
1019#endif /* SCSI_LOW_DIAGNOSTIC */
1020
1021 if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) {
1022 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1023 xpt_done(ccb);
1024 return;
1025 }
1026
1027 ti = slp->sl_ti[target];
1028 cb->osdep = ccb;
1029 cb->bp = NULL;
1030 if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
1031 flags = CCB_AUTOSENSE | CCB_SCSIIO;
1032 else
1033 flags = CCB_SCSIIO;
1034
1035 s = SCSI_LOW_SPLSCSI();
1036 li = scsi_low_alloc_li(ti, lun, 1);
1037
1038 if (ti->ti_setup_msg != 0)
1039 {
1040 scsi_low_message_enqueue(slp, ti, li, CCB_AUTOSENSE);
1041 }
1042
1043 scsi_low_enqueue(slp, ti, li, cb, flags, 0);
1044
1045#ifdef SCSI_LOW_DEBUG
1046 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, target) != 0)
1047 {
1048 scsi_low_test_abort(slp, ti, li);
1049 }
1050#endif /* SCSI_LOW_DEBUG */
1051 splx(s);
1052 break;
1053
1054 case XPT_EN_LUN: /* Enable LUN as a target */
1055 case XPT_TARGET_IO: /* Execute target I/O request */
1056 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
1057 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/
1058 /* XXX Implement */
1059 ccb->ccb_h.status = CAM_REQ_INVALID;
1060 xpt_done(ccb);
1061 break;
1062
1063 case XPT_ABORT: /* Abort the specified CCB */
1064#ifdef SCSI_LOW_DIAGNOSTIC
1065 if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD)
1066 {
1067 printf("%s: invalid target/lun\n", slp->sl_xname);
1068 ccb->ccb_h.status = CAM_REQ_INVALID;
1069 xpt_done(ccb);
1070 return;
1071 }
1072#endif /* SCSI_LOW_DIAGNOSTIC */
1073
1074 s = SCSI_LOW_SPLSCSI();
1075 cb = scsi_low_find_ccb(slp, target, lun, ccb->cab.abort_ccb);
1076 rv = scsi_low_abort_ccb(slp, cb);
1077 splx(s);
1078
1079 if (rv == 0)
1080 ccb->ccb_h.status = CAM_REQ_CMP;
1081 else
1082 ccb->ccb_h.status = CAM_REQ_INVALID;
1083 xpt_done(ccb);
1084 break;
1085
1086 case XPT_SET_TRAN_SETTINGS: {
1087 struct ccb_trans_settings_scsi *scsi;
1088 struct ccb_trans_settings_spi *spi;
1089 struct ccb_trans_settings *cts;
1090 u_int val;
1091
1092#ifdef SCSI_LOW_DIAGNOSTIC
1093 if (target == CAM_TARGET_WILDCARD)
1094 {
1095 printf("%s: invalid target\n", slp->sl_xname);
1096 ccb->ccb_h.status = CAM_REQ_INVALID;
1097 xpt_done(ccb);
1098 return;
1099 }
1100#endif /* SCSI_LOW_DIAGNOSTIC */
1101 cts = &ccb->cts;
1102 ti = slp->sl_ti[target];
1103 if (lun == CAM_LUN_WILDCARD)
1104 lun = 0;
1105
1106 s = SCSI_LOW_SPLSCSI();
1107 scsi = &cts->proto_specific.scsi;
1108 spi = &cts->xport_specific.spi;
1109 if ((spi->valid & (CTS_SPI_VALID_BUS_WIDTH |
1110 CTS_SPI_VALID_SYNC_RATE |
1111 CTS_SPI_VALID_SYNC_OFFSET)) != 0)
1112 {
1113 if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) {
1114 val = spi->bus_width;
1115 if (val < ti->ti_width)
1116 ti->ti_width = val;
1117 }
1118 if (spi->valid & CTS_SPI_VALID_SYNC_RATE) {
1119 val = spi->sync_period;
1120 if (val == 0 || val > ti->ti_maxsynch.period)
1121 ti->ti_maxsynch.period = val;
1122 }
1123 if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) {
1124 val = spi->sync_offset;
1125 if (val < ti->ti_maxsynch.offset)
1126 ti->ti_maxsynch.offset = val;
1127 }
1128 ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID;
1129 scsi_low_calcf_target(ti);
1130 }
1131
1132 if ((spi->valid & CTS_SPI_FLAGS_DISC_ENB) != 0 ||
1133 (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) {
1134
1135 li = scsi_low_alloc_li(ti, lun, 1);
1136 if (spi->valid & CTS_SPI_FLAGS_DISC_ENB) {
1137 li->li_quirks |= SCSI_LOW_DISK_DISC;
1138 } else {
1139 li->li_quirks &= ~SCSI_LOW_DISK_DISC;
1140 }
1141
1142 if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) {
1143 li->li_quirks |= SCSI_LOW_DISK_QTAG;
1144 } else {
1145 li->li_quirks &= ~SCSI_LOW_DISK_QTAG;
1146 }
1147 li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID;
1148 scsi_low_calcf_target(ti);
1149 scsi_low_calcf_lun(li);
1150 if ((slp->sl_show_result & SHOW_CALCF_RES) != 0)
1151 scsi_low_calcf_show(li);
1152 }
1153 splx(s);
1154
1155 ccb->ccb_h.status = CAM_REQ_CMP;
1156 xpt_done(ccb);
1157 break;
1158 }
1159
1160 case XPT_GET_TRAN_SETTINGS: {
1161 struct ccb_trans_settings *cts;
1162 u_int diskflags;
1163
1164 cts = &ccb->cts;
1165#ifdef SCSI_LOW_DIAGNOSTIC
1166 if (target == CAM_TARGET_WILDCARD)
1167 {
1168 printf("%s: invalid target\n", slp->sl_xname);
1169 ccb->ccb_h.status = CAM_REQ_INVALID;
1170 xpt_done(ccb);
1171 return;
1172 }
1173#endif /* SCSI_LOW_DIAGNOSTIC */
1174 ti = slp->sl_ti[target];
1175 if (lun == CAM_LUN_WILDCARD)
1176 lun = 0;
1177
1178 s = SCSI_LOW_SPLSCSI();
1179 li = scsi_low_alloc_li(ti, lun, 1);
1180 if (li != NULL && cts->type == CTS_TYPE_CURRENT_SETTINGS) {
1181 struct ccb_trans_settings_scsi *scsi =
1182 &cts->proto_specific.scsi;
1183 struct ccb_trans_settings_spi *spi =
1184 &cts->xport_specific.spi;
1185#ifdef SCSI_LOW_DIAGNOSTIC
1186 if (li->li_flags_valid != SCSI_LOW_LUN_FLAGS_ALL_VALID)
1187 {
1188 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1189 printf("%s: invalid GET_TRANS_CURRENT_SETTINGS call\n",
1190 slp->sl_xname);
1191 goto settings_out;
1192 }
1193#endif /* SCSI_LOW_DIAGNOSTIC */
1194 cts->protocol = PROTO_SCSI;
1195 cts->protocol_version = SCSI_REV_2;
1196 cts->transport = XPORT_SPI;
1197 cts->transport_version = 2;
1198
1199 scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
1200 spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
1201
1202 diskflags = li->li_diskflags & li->li_cfgflags;
1203 if (diskflags & SCSI_LOW_DISK_DISC)
1204 spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
1205 if (diskflags & SCSI_LOW_DISK_QTAG)
1206 scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
1207
1208 spi->sync_period = ti->ti_maxsynch.period;
1209 spi->valid |= CTS_SPI_VALID_SYNC_RATE;
1210 spi->sync_offset = ti->ti_maxsynch.offset;
1211 spi->valid |= CTS_SPI_VALID_SYNC_OFFSET;
1212
1213 spi->valid |= CTS_SPI_VALID_BUS_WIDTH;
1214 spi->bus_width = ti->ti_width;
1215
1216 if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
1217 scsi->valid = CTS_SCSI_VALID_TQ;
1218 spi->valid |= CTS_SPI_VALID_DISC;
1219 } else
1220 scsi->valid = 0;
1221 } else
1222 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL;
1223settings_out:
1224 splx(s);
1225 xpt_done(ccb);
1226 break;
1227 }
1228
1229 case XPT_CALC_GEOMETRY: { /* not yet HN2 */
1230 cam_calc_geometry(&ccb->ccg, /*extended*/1);
1231 xpt_done(ccb);
1232 break;
1233 }
1234
1235 case XPT_RESET_BUS: /* Reset the specified SCSI bus */
1236 s = SCSI_LOW_SPLSCSI();
1237 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL);
1238 splx(s);
1239 ccb->ccb_h.status = CAM_REQ_CMP;
1240 xpt_done(ccb);
1241 break;
1242
1243 case XPT_TERM_IO: /* Terminate the I/O process */
1244 ccb->ccb_h.status = CAM_REQ_INVALID;
1245 xpt_done(ccb);
1246 break;
1247
1248 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
1249#ifdef SCSI_LOW_DIAGNOSTIC
1250 if (target == CAM_TARGET_WILDCARD)
1251 {
1252 printf("%s: invalid target\n", slp->sl_xname);
1253 ccb->ccb_h.status = CAM_REQ_INVALID;
1254 xpt_done(ccb);
1255 return;
1256 }
1257#endif /* SCSI_LOW_DIAGNOSTIC */
1258
1259 msg = SCSI_LOW_MSG_RESET;
1260 if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL))
1261 {
1262 ccb->ccb_h.status = CAM_RESRC_UNAVAIL;
1263 xpt_done(ccb);
1264 return;
1265 }
1266
1267 ti = slp->sl_ti[target];
1268 if (lun == CAM_LUN_WILDCARD)
1269 lun = 0;
1270 cb->osdep = ccb;
1271 cb->bp = NULL;
1272 if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0)
1273 flags = CCB_AUTOSENSE | CCB_NORETRY | CCB_URGENT;
1274 else
1275 flags = CCB_NORETRY | CCB_URGENT;
1276
1277 s = SCSI_LOW_SPLSCSI();
1278 li = scsi_low_alloc_li(ti, lun, 1);
1279 scsi_low_enqueue(slp, ti, li, cb, flags, msg);
1280 splx(s);
1281 break;
1282
1283 case XPT_PATH_INQ: { /* Path routing inquiry */
1284 struct ccb_pathinq *cpi = &ccb->cpi;
1285
1286 cpi->version_num = scsi_low_version_major;
1287 cpi->hba_inquiry = PI_TAG_ABLE | PI_LINKED_CDB;
1288 ti = slp->sl_ti[slp->sl_hostid]; /* host id */
1289 if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8)
1290 cpi->hba_inquiry |= PI_WIDE_16;
1291 if (ti->ti_width > SCSI_LOW_BUS_WIDTH_16)
1292 cpi->hba_inquiry |= PI_WIDE_32;
1293 if (ti->ti_maxsynch.offset > 0)
1294 cpi->hba_inquiry |= PI_SDTR_ABLE;
1295 cpi->target_sprt = 0;
1296 cpi->hba_misc = 0;
1297 cpi->hba_eng_cnt = 0;
1298 cpi->max_target = slp->sl_ntargs - 1;
1299 cpi->max_lun = slp->sl_nluns - 1;
1300 cpi->initiator_id = slp->sl_hostid;
1301 cpi->bus_id = cam_sim_bus(sim);
1302 cpi->base_transfer_speed = 3300;
1303 cpi->transport = XPORT_SPI;
1304 cpi->transport_version = 2;
1305 cpi->protocol = PROTO_SCSI;
1306 cpi->protocol_version = SCSI_REV_2;
1307 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
1308 strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN);
1309 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
1310 cpi->unit_number = cam_sim_unit(sim);
1311 cpi->ccb_h.status = CAM_REQ_CMP;
1312 xpt_done(ccb);
1313 break;
1314 }
1315
1316 default:
1317 printf("scsi_low: non support func_code = %d ",
1318 ccb->ccb_h.func_code);
1319 ccb->ccb_h.status = CAM_REQ_INVALID;
1320 xpt_done(ccb);
1321 break;
1322 }
1323}
1324
1325static int
1326scsi_low_attach_cam(slp)
1327 struct scsi_low_softc *slp;
1328{
1329 struct cam_devq *devq;
1330 int tagged_openings;
1331
1332 sprintf(slp->sl_xname, "%s%d",
1333 DEVPORT_DEVNAME(slp->sl_dev), DEVPORT_DEVUNIT(slp->sl_dev));
1334
1335 devq = cam_simq_alloc(SCSI_LOW_NCCB);
1336 if (devq == NULL)
1337 return (ENOMEM);
1338
1339 /*
1340 * ask the adapter what subunits are present
1341 */
1342 tagged_openings = min(slp->sl_openings, SCSI_LOW_MAXNEXUS);
1343 slp->sl_si.sim = cam_sim_alloc(scsi_low_scsi_action_cam,
1344 scsi_low_poll_cam,
1345 DEVPORT_DEVNAME(slp->sl_dev), slp,
1346 DEVPORT_DEVUNIT(slp->sl_dev), &Giant,
1347 slp->sl_openings, tagged_openings, devq);
1348
1349 if (slp->sl_si.sim == NULL) {
1350 cam_simq_free(devq);
1351 return ENODEV;
1352 }
1353
1354 if (xpt_bus_register(slp->sl_si.sim, 0) != CAM_SUCCESS) {
1355 free(slp->sl_si.sim, M_SCSILOW);
1356 return ENODEV;
1357 }
1358
1359 if (xpt_create_path(&slp->sl_si.path, /*periph*/NULL,
1360 cam_sim_path(slp->sl_si.sim), CAM_TARGET_WILDCARD,
1361 CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
1362 xpt_bus_deregister(cam_sim_path(slp->sl_si.sim));
1363 cam_sim_free(slp->sl_si.sim, /*free_simq*/TRUE);
1364 return ENODEV;
1365 }
1366
1367 slp->sl_show_result = SHOW_CALCF_RES; /* OK ? */
1368 return 0;
1369}
1370
1371static int
1372scsi_low_world_start_cam(slp)
1373 struct scsi_low_softc *slp;
1374{
1375
1376 if (!cold)
1377 scsi_low_rescan_bus_cam(slp);
1378 return 0;
1379}
1380
1381static int
1382scsi_low_dettach_cam(slp)
1383 struct scsi_low_softc *slp;
1384{
1385
1386 xpt_async(AC_LOST_DEVICE, slp->sl_si.path, NULL);
1387 xpt_free_path(slp->sl_si.path);
1388 xpt_bus_deregister(cam_sim_path(slp->sl_si.sim));
1389 cam_sim_free(slp->sl_si.sim, /* free_devq */ TRUE);
1390 return 0;
1391}
1392
1393static int
1394scsi_low_ccb_setup_cam(slp, cb)
1395 struct scsi_low_softc *slp;
1396 struct slccb *cb;
1397{
1398 union ccb *ccb = (union ccb *) cb->osdep;
1399
1400 if ((cb->ccb_flags & CCB_SCSIIO) != 0)
1401 {
1402 cb->ccb_scp.scp_cmd = ccb->csio.cdb_io.cdb_bytes;
1403 cb->ccb_scp.scp_cmdlen = (int) ccb->csio.cdb_len;
1404 cb->ccb_scp.scp_data = ccb->csio.data_ptr;
1405 cb->ccb_scp.scp_datalen = (int) ccb->csio.dxfer_len;
1406 if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
1407 cb->ccb_scp.scp_direction = SCSI_LOW_WRITE;
1408 else /* if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) */
1409 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
1410 cb->ccb_tcmax = ccb->ccb_h.timeout / 1000;
1411 }
1412 else
1413 {
1414 scsi_low_unit_ready_cmd(cb);
1415 }
1416 return SCSI_LOW_START_QTAG;
1417}
1418
1419static int
1420scsi_low_done_cam(slp, cb)
1421 struct scsi_low_softc *slp;
1422 struct slccb *cb;
1423{
1424 union ccb *ccb;
1425
1426 ccb = (union ccb *) cb->osdep;
1427 if (cb->ccb_error == 0)
1428 {
1429 ccb->ccb_h.status = CAM_REQ_CMP;
1430 ccb->csio.resid = 0;
1431 }
1432 else
1433 {
1434 if (cb->ccb_rcnt >= slp->sl_max_retry)
1435 cb->ccb_error |= ABORTIO;
1436
1437 if ((cb->ccb_flags & CCB_NORETRY) == 0 &&
1438 (cb->ccb_error & ABORTIO) == 0)
1439 return EJUSTRETURN;
1440
1441 if ((cb->ccb_error & SENSEIO) != 0)
1442 {
1443 memcpy(&ccb->csio.sense_data,
1444 &cb->ccb_sense,
1445 sizeof(ccb->csio.sense_data));
1446 }
1447
1448 ccb->ccb_h.status = scsi_low_translate_error_code(cb,
1449 &scsi_low_error_code_cam[0]);
1450
1451#ifdef SCSI_LOW_DIAGNOSTIC
1452 if ((cb->ccb_flags & CCB_SILENT) == 0 &&
1453 cb->ccb_scp.scp_cmdlen > 0 &&
1454 (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] &
1455 SCSI_LOW_CMD_ABORT_WARNING) != 0)
1456 {
1457 printf("%s: WARNING: scsi_low IO abort\n",
1458 slp->sl_xname);
1459 scsi_low_print(slp, NULL);
1460 }
1461#endif /* SCSI_LOW_DIAGNOSTIC */
1462 }
1463
1464 if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 0)
1465 ccb->ccb_h.status |= CAM_REQ_CMP_ERR;
1466
1467 if (cb->ccb_scp.scp_status == ST_UNKNOWN)
1468 ccb->csio.scsi_status = 0; /* XXX */
1469 else
1470 ccb->csio.scsi_status = cb->ccb_scp.scp_status;
1471
1472 if ((cb->ccb_flags & CCB_NOSDONE) == 0)
1473 xpt_done(ccb);
1474 return 0;
1475}
1476
1477static void
1478scsi_low_timeout_cam(slp, ch, action)
1479 struct scsi_low_softc *slp;
1480 int ch;
1481 int action;
1482{
1483
1484 switch (ch)
1485 {
1486 case SCSI_LOW_TIMEOUT_CH_IO:
1487 switch (action)
1488 {
1489 case SCSI_LOW_TIMEOUT_START:
1490 slp->sl_si.timeout_ch = timeout(scsi_low_timeout, slp,
1491 hz / SCSI_LOW_TIMEOUT_HZ);
1492 break;
1493 case SCSI_LOW_TIMEOUT_STOP:
1494 untimeout(scsi_low_timeout, slp, slp->sl_si.timeout_ch);
1495 break;
1496 }
1497 break;
1498
1499 case SCSI_LOW_TIMEOUT_CH_ENGAGE:
1500 switch (action)
1501 {
1502 case SCSI_LOW_TIMEOUT_START:
1503 slp->sl_si.engage_ch = timeout(scsi_low_engage, slp, 1);
1504 break;
1505 case SCSI_LOW_TIMEOUT_STOP:
1506 untimeout(scsi_low_engage, slp, slp->sl_si.engage_ch);
1507 break;
1508 }
1509 break;
1510 case SCSI_LOW_TIMEOUT_CH_RECOVER:
1511 break;
1512 }
1513}
1514
1515#endif /* SCSI_LOW_INTERFACE_CAM */
1516
1517/*=============================================================
1518 * END OF OS switch (All OS depend fucntions should be above)
1519 =============================================================*/
1520
1521/**************************************************************
1522 * scsi low deactivate and activate
1523 **************************************************************/
1524int
1525scsi_low_is_busy(slp)
1526 struct scsi_low_softc *slp;
1527{
1528
1529 if (slp->sl_nio > 0)
1530 return EBUSY;
1531 return 0;
1532}
1533
1534int
1535scsi_low_deactivate(slp)
1536 struct scsi_low_softc *slp;
1537{
1538 int s;
1539
1540 s = SCSI_LOW_SPLSCSI();
1541 slp->sl_flags |= HW_INACTIVE;
1542 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
1543 (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_STOP);
1544 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
1545 (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP);
1546 splx(s);
1547 return 0;
1548}
1549
1550int
1551scsi_low_activate(slp)
1552 struct scsi_low_softc *slp;
1553{
1554 int error, s;
1555
1556 s = SCSI_LOW_SPLSCSI();
1557 slp->sl_flags &= ~HW_INACTIVE;
1558 if ((error = scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL)) != 0)
1559 {
1560 slp->sl_flags |= HW_INACTIVE;
1561 splx(s);
1562 return error;
1563 }
1564
1565 slp->sl_timeout_count = 0;
1566 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
1567 (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START);
1568 splx(s);
1569 return 0;
1570}
1571
1572/**************************************************************
1573 * scsi low log
1574 **************************************************************/
1575#ifdef SCSI_LOW_DIAGNOSTIC
1576static void scsi_low_msg_log_init(struct scsi_low_msg_log *);
1577static void scsi_low_msg_log_write(struct scsi_low_msg_log *, u_int8_t *, int);
1578static void scsi_low_msg_log_show(struct scsi_low_msg_log *, char *, int);
1579
1580static void
1581scsi_low_msg_log_init(slmlp)
1582 struct scsi_low_msg_log *slmlp;
1583{
1584
1585 slmlp->slml_ptr = 0;
1586}
1587
1588static void
1589scsi_low_msg_log_write(slmlp, datap, len)
1590 struct scsi_low_msg_log *slmlp;
1591 u_int8_t *datap;
1592 int len;
1593{
1594 int ptr, ind;
1595
1596 if (slmlp->slml_ptr >= SCSI_LOW_MSG_LOG_DATALEN)
1597 return;
1598
1599 ptr = slmlp->slml_ptr ++;
1600 for (ind = 0; ind < sizeof(slmlp->slml_msg[0]) && ind < len; ind ++)
1601 slmlp->slml_msg[ptr].msg[ind] = datap[ind];
1602 for ( ; ind < sizeof(slmlp->slml_msg[0]); ind ++)
1603 slmlp->slml_msg[ptr].msg[ind] = 0;
1604}
1605
1606static void
1607scsi_low_msg_log_show(slmlp, s, len)
1608 struct scsi_low_msg_log *slmlp;
1609 char *s;
1610 int len;
1611{
1612 int ptr, ind;
1613
1614 printf("%s: (%d) ", s, slmlp->slml_ptr);
1615 for (ptr = 0; ptr < slmlp->slml_ptr; ptr ++)
1616 {
1617 for (ind = 0; ind < len && ind < sizeof(slmlp->slml_msg[0]);
1618 ind ++)
1619 {
1620 printf("[%x]", (u_int) slmlp->slml_msg[ptr].msg[ind]);
1621 }
1622 printf(">");
1623 }
1624 printf("\n");
1625}
1626#endif /* SCSI_LOW_DIAGNOSTIC */
1627
1628/**************************************************************
1629 * power control
1630 **************************************************************/
1631static void
1632scsi_low_engage(arg)
1633 void *arg;
1634{
1635 struct scsi_low_softc *slp = arg;
1636 int s = SCSI_LOW_SPLSCSI();
1637
1638 switch (slp->sl_rstep)
1639 {
1640 case 0:
1641 slp->sl_rstep ++;
1642 (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE);
1643 (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp,
1644 SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_START);
1645 break;
1646
1647 case 1:
1648 slp->sl_rstep ++;
1649 slp->sl_flags &= ~HW_RESUME;
1650 scsi_low_start(slp);
1651 break;
1652
1653 case 2:
1654 break;
1655 }
1656 splx(s);
1657}
1658
1659static int
1660scsi_low_init(slp, flags)
1661 struct scsi_low_softc *slp;
1662 u_int flags;
1663{
1664 int rv = 0;
1665
1666 slp->sl_flags |= HW_INITIALIZING;
1667
1668 /* clear power control timeout */
1669 if ((slp->sl_flags & HW_POWERCTRL) != 0)
1670 {
1671 (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp,
1672 SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP);
1673 slp->sl_flags &= ~(HW_POWDOWN | HW_RESUME);
1674 slp->sl_active = 1;
1675 slp->sl_powc = SCSI_LOW_POWDOWN_TC;
1676 }
1677
1678 /* reset current nexus */
1679 scsi_low_reset_nexus(slp, flags);
1680 if ((slp->sl_flags & HW_INACTIVE) != 0)
1681 {
1682 rv = EBUSY;
1683 goto out;
1684 }
1685
1686 if (flags != SCSI_LOW_RESTART_SOFT)
1687 {
1688 rv = ((*slp->sl_funcs->scsi_low_init) (slp, flags));
1689 }
1690
1691out:
1692 slp->sl_flags &= ~HW_INITIALIZING;
1693 return rv;
1694}
1695
1696/**************************************************************
1697 * allocate lun_info
1698 **************************************************************/
1699static struct lun_info *
1700scsi_low_alloc_li(ti, lun, alloc)
1701 struct targ_info *ti;
1702 int lun;
1703 int alloc;
1704{
1705 struct scsi_low_softc *slp = ti->ti_sc;
1706 struct lun_info *li;
1707
1708 li = LIST_FIRST(&ti->ti_litab);
1709 if (li != NULL)
1710 {
1711 if (li->li_lun == lun)
1712 return li;
1713
1714 while ((li = LIST_NEXT(li, lun_chain)) != NULL)
1715 {
1716 if (li->li_lun == lun)
1717 {
1718 LIST_REMOVE(li, lun_chain);
1719 LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain);
1720 return li;
1721 }
1722 }
1723 }
1724
1725 if (alloc == 0)
1726 return li;
1727
1728 li = SCSI_LOW_MALLOC(ti->ti_lunsize);
1729 if (li == NULL)
1730 panic("no lun info mem");
1731
1732 SCSI_LOW_BZERO(li, ti->ti_lunsize);
1733 li->li_lun = lun;
1734 li->li_ti = ti;
1735
1736 li->li_cfgflags = SCSI_LOW_SYNC | SCSI_LOW_LINK | SCSI_LOW_DISC |
1737 SCSI_LOW_QTAG;
1738 li->li_quirks = li->li_diskflags = SCSI_LOW_DISK_LFLAGS;
1739 li->li_flags_valid = SCSI_LOW_LUN_FLAGS_USER_VALID;
1740#ifdef SCSI_LOW_FLAGS_QUIRKS_OK
1741 li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID;
1742#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */
1743
1744 li->li_qtagbits = (u_int) -1;
1745
1746 TAILQ_INIT(&li->li_discq);
1747 LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain);
1748
1749 /* host specific structure initialization per lun */
1750 if (slp->sl_funcs->scsi_low_lun_init != NULL)
1751 (*slp->sl_funcs->scsi_low_lun_init)
1752 (slp, ti, li, SCSI_LOW_INFO_ALLOC);
1753 scsi_low_calcf_lun(li);
1754 return li;
1755}
1756
1757/**************************************************************
1758 * allocate targ_info
1759 **************************************************************/
1760static struct targ_info *
1761scsi_low_alloc_ti(slp, targ)
1762 struct scsi_low_softc *slp;
1763 int targ;
1764{
1765 struct targ_info *ti;
1766
1767 if (TAILQ_FIRST(&slp->sl_titab) == NULL)
1768 TAILQ_INIT(&slp->sl_titab);
1769
1770 ti = SCSI_LOW_MALLOC(slp->sl_targsize);
1771 if (ti == NULL)
1772 panic("%s short of memory", slp->sl_xname);
1773
1774 SCSI_LOW_BZERO(ti, slp->sl_targsize);
1775 ti->ti_id = targ;
1776 ti->ti_sc = slp;
1777
1778 slp->sl_ti[targ] = ti;
1779 TAILQ_INSERT_TAIL(&slp->sl_titab, ti, ti_chain);
1780 LIST_INIT(&ti->ti_litab);
1781
1782 ti->ti_quirks = ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS;
1783 ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8;
1784 ti->ti_flags_valid = SCSI_LOW_TARG_FLAGS_USER_VALID;
1785#ifdef SCSI_LOW_FLAGS_QUIRKS_OK
1786 ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID;
1787#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */
1788
1789 if (slp->sl_funcs->scsi_low_targ_init != NULL)
1790 {
1791 (*slp->sl_funcs->scsi_low_targ_init)
1792 (slp, ti, SCSI_LOW_INFO_ALLOC);
1793 }
1794 scsi_low_calcf_target(ti);
1795 return ti;
1796}
1797
1798static void
1799scsi_low_free_ti(slp)
1800 struct scsi_low_softc *slp;
1801{
1802 struct targ_info *ti, *tib;
1803 struct lun_info *li, *nli;
1804
1805 for (ti = TAILQ_FIRST(&slp->sl_titab); ti; ti = tib)
1806 {
1807 for (li = LIST_FIRST(&ti->ti_litab); li != NULL; li = nli)
1808 {
1809 if (slp->sl_funcs->scsi_low_lun_init != NULL)
1810 {
1811 (*slp->sl_funcs->scsi_low_lun_init)
1812 (slp, ti, li, SCSI_LOW_INFO_DEALLOC);
1813 }
1814 nli = LIST_NEXT(li, lun_chain);
1815 SCSI_LOW_FREE(li);
1816 }
1817
1818 if (slp->sl_funcs->scsi_low_targ_init != NULL)
1819 {
1820 (*slp->sl_funcs->scsi_low_targ_init)
1821 (slp, ti, SCSI_LOW_INFO_DEALLOC);
1822 }
1823 tib = TAILQ_NEXT(ti, ti_chain);
1824 SCSI_LOW_FREE(ti);
1825 }
1826}
1827
1828/**************************************************************
1829 * timeout
1830 **************************************************************/
1831void
1832scsi_low_bus_idle(slp)
1833 struct scsi_low_softc *slp;
1834{
1835
1836 slp->sl_retry_sel = 0;
1837 if (slp->sl_Tnexus == NULL)
1838 scsi_low_start(slp);
1839}
1840
1841static void
1842scsi_low_timeout(arg)
1843 void *arg;
1844{
1845 struct scsi_low_softc *slp = arg;
1846 int s;
1847
1848 s = SCSI_LOW_SPLSCSI();
1849 (void) scsi_low_timeout_check(slp);
1850 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
1851 (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START);
1852 splx(s);
1853}
1854
1855static int
1856scsi_low_timeout_check(slp)
1857 struct scsi_low_softc *slp;
1858{
1859 struct targ_info *ti;
1860 struct lun_info *li;
1861 struct slccb *cb = NULL; /* XXX */
1862
1863 /* selection restart */
1864 if (slp->sl_retry_sel != 0)
1865 {
1866 slp->sl_retry_sel = 0;
1867 if (slp->sl_Tnexus != NULL)
1868 goto step1;
1869
1870 cb = TAILQ_FIRST(&slp->sl_start);
1871 if (cb == NULL)
1872 goto step1;
1873
1874 if (cb->ccb_selrcnt >= SCSI_LOW_MAX_SELECTION_RETRY)
1875 {
1876 cb->ccb_flags |= CCB_NORETRY;
1877 cb->ccb_error |= SELTIMEOUTIO;
1878 if (scsi_low_revoke_ccb(slp, cb, 1) != NULL)
1879 panic("%s: ccb not finished", slp->sl_xname);
1880 }
1881
1882 if (slp->sl_Tnexus == NULL)
1883 scsi_low_start(slp);
1884 }
1885
1886 /* call hardware timeout */
1887step1:
1888 if (slp->sl_funcs->scsi_low_timeout != NULL)
1889 {
1890 (*slp->sl_funcs->scsi_low_timeout) (slp);
1891 }
1892
1893 if (slp->sl_timeout_count ++ <
1894 SCSI_LOW_TIMEOUT_CHECK_INTERVAL * SCSI_LOW_TIMEOUT_HZ)
1895 return 0;
1896
1897 slp->sl_timeout_count = 0;
1898 if (slp->sl_nio > 0)
1899 {
1900 if ((cb = slp->sl_Qnexus) != NULL)
1901 {
1902 cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
1903 if (cb->ccb_tc < 0)
1904 goto bus_reset;
1905 }
1906 else if (slp->sl_disc == 0)
1907 {
1908 if ((cb = TAILQ_FIRST(&slp->sl_start)) == NULL)
1909 return 0;
1910
1911 cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
1912 if (cb->ccb_tc < 0)
1913 goto bus_reset;
1914 }
1915 else for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
1916 ti = TAILQ_NEXT(ti, ti_chain))
1917 {
1918 if (ti->ti_disc == 0)
1919 continue;
1920
1921 for (li = LIST_FIRST(&ti->ti_litab); li != NULL;
1922 li = LIST_NEXT(li, lun_chain))
1923 {
1924 for (cb = TAILQ_FIRST(&li->li_discq);
1925 cb != NULL;
1926 cb = TAILQ_NEXT(cb, ccb_chain))
1927 {
1928 cb->ccb_tc -=
1929 SCSI_LOW_TIMEOUT_CHECK_INTERVAL;
1930 if (cb->ccb_tc < 0)
1931 goto bus_reset;
1932 }
1933 }
1934 }
1935
1936 }
1937 else if ((slp->sl_flags & HW_POWERCTRL) != 0)
1938 {
1939 if ((slp->sl_flags & (HW_POWDOWN | HW_RESUME)) != 0)
1940 return 0;
1941
1942 if (slp->sl_active != 0)
1943 {
1944 slp->sl_powc = SCSI_LOW_POWDOWN_TC;
1945 slp->sl_active = 0;
1946 return 0;
1947 }
1948
1949 slp->sl_powc --;
1950 if (slp->sl_powc < 0)
1951 {
1952 slp->sl_powc = SCSI_LOW_POWDOWN_TC;
1953 slp->sl_flags |= HW_POWDOWN;
1954 (*slp->sl_funcs->scsi_low_power)
1955 (slp, SCSI_LOW_POWDOWN);
1956 }
1957 }
1958 return 0;
1959
1960bus_reset:
1961 cb->ccb_error |= TIMEOUTIO;
1962 printf("%s: slccb (0x%lx) timeout!\n", slp->sl_xname, (u_long) cb);
1963 scsi_low_info(slp, NULL, "scsi bus hangup. try to recover.");
1964 scsi_low_init(slp, SCSI_LOW_RESTART_HARD);
1965 scsi_low_start(slp);
1966 return ERESTART;
1967}
1968
1969
1970static int
1971scsi_low_abort_ccb(slp, cb)
1972 struct scsi_low_softc *slp;
1973 struct slccb *cb;
1974{
1975 struct targ_info *ti;
1976 struct lun_info *li;
1977 u_int msg;
1978
1979 if (cb == NULL)
1980 return EINVAL;
1981 if ((cb->ccb_omsgoutflag &
1982 (SCSI_LOW_MSG_ABORT | SCSI_LOW_MSG_ABORT_QTAG)) != 0)
1983 return EBUSY;
1984
1985 ti = cb->ti;
1986 li = cb->li;
1987 if (cb->ccb_tag == SCSI_LOW_UNKTAG)
1988 msg = SCSI_LOW_MSG_ABORT;
1989 else
1990 msg = SCSI_LOW_MSG_ABORT_QTAG;
1991
1992 cb->ccb_error |= ABORTIO;
1993 cb->ccb_flags |= CCB_NORETRY;
1994 scsi_low_ccb_message_assert(cb, msg);
1995
1996 if (cb == slp->sl_Qnexus)
1997 {
1998 scsi_low_assert_msg(slp, ti, msg, 1);
1999 }
2000 else if ((cb->ccb_flags & CCB_DISCQ) != 0)
2001 {
2002 if (scsi_low_revoke_ccb(slp, cb, 0) == NULL)
2003 panic("%s: revoked ccb done", slp->sl_xname);
2004
2005 cb->ccb_flags |= CCB_STARTQ;
2006 TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
2007
2008 if (slp->sl_Tnexus == NULL)
2009 scsi_low_start(slp);
2010 }
2011 else
2012 {
2013 if (scsi_low_revoke_ccb(slp, cb, 1) != NULL)
2014 panic("%s: revoked ccb retried", slp->sl_xname);
2015 }
2016 return 0;
2017}
2018
2019/**************************************************************
2020 * Generic SCSI INTERFACE
2021 **************************************************************/
2022int
2023scsi_low_attach(slp, openings, ntargs, nluns, targsize, lunsize)
2024 struct scsi_low_softc *slp;
2025 int openings, ntargs, nluns, targsize, lunsize;
2026{
2027 struct targ_info *ti;
2028 struct lun_info *li;
2029 int s, i, nccb, rv;
2030
2031#ifdef SCSI_LOW_INTERFACE_XS
2032 slp->sl_osdep_fp = &scsi_low_osdep_funcs_xs;
2033#endif /* SCSI_LOW_INTERFACE_XS */
2034#ifdef SCSI_LOW_INTERFACE_CAM
2035 slp->sl_osdep_fp = &scsi_low_osdep_funcs_cam;
2036#endif /* SCSI_LOW_INTERFACE_CAM */
2037
2038 if (slp->sl_osdep_fp == NULL)
2039 panic("scsi_low: interface not spcified");
2040
2041 if (ntargs > SCSI_LOW_NTARGETS)
2042 {
2043 printf("scsi_low: %d targets are too large\n", ntargs);
2044 printf("change kernel options SCSI_LOW_NTARGETS");
2045 return EINVAL;
2046 }
2047
2048 if (openings <= 0)
2049 slp->sl_openings = (SCSI_LOW_NCCB / ntargs);
2050 else
2051 slp->sl_openings = openings;
2052 slp->sl_ntargs = ntargs;
2053 slp->sl_nluns = nluns;
2054 slp->sl_max_retry = SCSI_LOW_MAX_RETRY;
2055
2056 if (lunsize < sizeof(struct lun_info))
2057 lunsize = sizeof(struct lun_info);
2058
2059 if (targsize < sizeof(struct targ_info))
2060 targsize = sizeof(struct targ_info);
2061
2062 slp->sl_targsize = targsize;
2063 for (i = 0; i < ntargs; i ++)
2064 {
2065 ti = scsi_low_alloc_ti(slp, i);
2066 ti->ti_lunsize = lunsize;
2067 li = scsi_low_alloc_li(ti, 0, 1);
2068 }
2069
2070 /* initialize queue */
2071 nccb = openings * ntargs;
2072 if (nccb >= SCSI_LOW_NCCB || nccb <= 0)
2073 nccb = SCSI_LOW_NCCB;
2074 scsi_low_init_ccbque(nccb);
2075 TAILQ_INIT(&slp->sl_start);
2076
2077 /* call os depend attach */
2078 s = SCSI_LOW_SPLSCSI();
2079 rv = (*slp->sl_osdep_fp->scsi_low_osdep_attach) (slp);
2080 if (rv != 0)
2081 {
2082 splx(s);
2083 printf("%s: scsi_low_attach: osdep attach failed\n",
2084 slp->sl_xname);
2085 return EINVAL;
2086 }
2087
2088 /* check hardware */
2089 SCSI_LOW_DELAY(1000); /* wait for 1ms */
2090 if (scsi_low_init(slp, SCSI_LOW_RESTART_HARD) != 0)
2091 {
2092 splx(s);
2093 printf("%s: scsi_low_attach: initialization failed\n",
2094 slp->sl_xname);
2095 return EINVAL;
2096 }
2097
2098 /* start watch dog */
2099 slp->sl_timeout_count = 0;
2100 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
2101 (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START);
2102 LIST_INSERT_HEAD(&sl_tab, slp, sl_chain);
2103
2104 /* fake call */
2105 scsi_low_abort_ccb(slp, scsi_low_find_ccb(slp, 0, 0, NULL));
2106
2107#ifdef SCSI_LOW_START_UP_CHECK
2108 /* probing devices */
2109 scsi_low_start_up(slp);
2110#endif /* SCSI_LOW_START_UP_CHECK */
2111
2112 /* call os depend attach done*/
2113 (*slp->sl_osdep_fp->scsi_low_osdep_world_start) (slp);
2114 splx(s);
2115 return 0;
2116}
2117
2118int
2119scsi_low_dettach(slp)
2120 struct scsi_low_softc *slp;
2121{
2122 int s, rv;
2123
2124 s = SCSI_LOW_SPLSCSI();
2125 if (scsi_low_is_busy(slp) != 0)
2126 {
2127 splx(s);
2128 return EBUSY;
2129 }
2130
2131 scsi_low_deactivate(slp);
2132
2133 rv = (*slp->sl_osdep_fp->scsi_low_osdep_dettach) (slp);
2134 if (rv != 0)
2135 {
2136 splx(s);
2137 return EBUSY;
2138 }
2139
2140 scsi_low_free_ti(slp);
2141 LIST_REMOVE(slp, sl_chain);
2142 splx(s);
2143 return 0;
2144}
2145
2146/**************************************************************
2147 * Generic enqueue
2148 **************************************************************/
2149static int
2150scsi_low_enqueue(slp, ti, li, cb, flags, msg)
2151 struct scsi_low_softc *slp;
2152 struct targ_info *ti;
2153 struct lun_info *li;
2154 struct slccb *cb;
2155 u_int flags, msg;
2156{
2157
2158 cb->ti = ti;
2159 cb->li = li;
2160
2161 scsi_low_ccb_message_assert(cb, msg);
2162
2163 cb->ccb_otag = cb->ccb_tag = SCSI_LOW_UNKTAG;
2164 scsi_low_alloc_qtag(cb);
2165
2166 cb->ccb_flags = flags | CCB_STARTQ;
2167 cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT;
2168 cb->ccb_error |= PENDINGIO;
2169
2170 if ((flags & CCB_URGENT) != 0)
2171 {
2172 TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
2173 }
2174 else
2175 {
2176 TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain);
2177 }
2178
2179 slp->sl_nio ++;
2180
2181 if (slp->sl_Tnexus == NULL)
2182 scsi_low_start(slp);
2183 return 0;
2184}
2185
2186static int
2187scsi_low_message_enqueue(slp, ti, li, flags)
2188 struct scsi_low_softc *slp;
2189 struct targ_info *ti;
2190 struct lun_info *li;
2191 u_int flags;
2192{
2193 struct slccb *cb;
2194 u_int tmsgflags;
2195
2196 tmsgflags = ti->ti_setup_msg;
2197 ti->ti_setup_msg = 0;
2198
2199 flags |= CCB_NORETRY;
2200 if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)
2201 return ENOMEM;
2202
2203 cb->osdep = NULL;
2204 cb->bp = NULL;
2205 scsi_low_enqueue(slp, ti, li, cb, flags, tmsgflags);
2206 return 0;
2207}
2208
2209/**************************************************************
2210 * Generic Start & Done
2211 **************************************************************/
2212#define SLSC_MODE_SENSE_SHORT 0x1a
2213static u_int8_t ss_cmd[6] = {START_STOP, 0, 0, 0, SSS_START, 0};
2214static u_int8_t sms_cmd[6] = {SLSC_MODE_SENSE_SHORT, 0x08, 0x0a, 0,
2215 sizeof(struct scsi_low_mode_sense_data), 0};
2216static u_int8_t inq_cmd[6] = {INQUIRY, 0, 0, 0,
2217 sizeof(struct scsi_low_inq_data), 0};
2218static u_int8_t unit_ready_cmd[6];
2219static int scsi_low_setup_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *);
2220static int scsi_low_sense_abort_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *);
2221static int scsi_low_resume(struct scsi_low_softc *);
2222
2223static void
2224scsi_low_unit_ready_cmd(cb)
2225 struct slccb *cb;
2226{
2227
2228 cb->ccb_scp.scp_cmd = unit_ready_cmd;
2229 cb->ccb_scp.scp_cmdlen = sizeof(unit_ready_cmd);
2230 cb->ccb_scp.scp_datalen = 0;
2231 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
2232 cb->ccb_tcmax = 15;
2233}
2234
2235static int
2236scsi_low_sense_abort_start(slp, ti, li, cb)
2237 struct scsi_low_softc *slp;
2238 struct targ_info *ti;
2239 struct lun_info *li;
2240 struct slccb *cb;
2241{
2242
2243 cb->ccb_scp.scp_cmdlen = 6;
2244 SCSI_LOW_BZERO(cb->ccb_scsi_cmd, cb->ccb_scp.scp_cmdlen);
2245 cb->ccb_scsi_cmd[0] = REQUEST_SENSE;
2246 cb->ccb_scsi_cmd[4] = sizeof(cb->ccb_sense);
2247 cb->ccb_scp.scp_cmd = cb->ccb_scsi_cmd;
2248 cb->ccb_scp.scp_data = (u_int8_t *) &cb->ccb_sense;
2249 cb->ccb_scp.scp_datalen = sizeof(cb->ccb_sense);
2250 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
2251 cb->ccb_tcmax = 15;
2252 scsi_low_ccb_message_clear(cb);
2253 if ((cb->ccb_flags & CCB_CLEARQ) != 0)
2254 {
2255 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
2256 }
2257 else
2258 {
2259 SCSI_LOW_BZERO(&cb->ccb_sense, sizeof(cb->ccb_sense));
2260#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE
2261 scsi_low_assert_msg(slp, ti, ti->ti_setup_msg_done, 0);
2262#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */
2263 }
2264
2265 return SCSI_LOW_START_NO_QTAG;
2266}
2267
2268static int
2269scsi_low_setup_start(slp, ti, li, cb)
2270 struct scsi_low_softc *slp;
2271 struct targ_info *ti;
2272 struct lun_info *li;
2273 struct slccb *cb;
2274{
2275
2276 switch(li->li_state)
2277 {
2278 case SCSI_LOW_LUN_SLEEP:
2279 scsi_low_unit_ready_cmd(cb);
2280 break;
2281
2282 case SCSI_LOW_LUN_START:
2283 cb->ccb_scp.scp_cmd = ss_cmd;
2284 cb->ccb_scp.scp_cmdlen = sizeof(ss_cmd);
2285 cb->ccb_scp.scp_datalen = 0;
2286 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
2287 cb->ccb_tcmax = 30;
2288 break;
2289
2290 case SCSI_LOW_LUN_INQ:
2291 cb->ccb_scp.scp_cmd = inq_cmd;
2292 cb->ccb_scp.scp_cmdlen = sizeof(inq_cmd);
2293 cb->ccb_scp.scp_data = (u_int8_t *)&li->li_inq;
2294 cb->ccb_scp.scp_datalen = sizeof(li->li_inq);
2295 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
2296 cb->ccb_tcmax = 15;
2297 break;
2298
2299 case SCSI_LOW_LUN_MODEQ:
2300 cb->ccb_scp.scp_cmd = sms_cmd;
2301 cb->ccb_scp.scp_cmdlen = sizeof(sms_cmd);
2302 cb->ccb_scp.scp_data = (u_int8_t *)&li->li_sms;
2303 cb->ccb_scp.scp_datalen = sizeof(li->li_sms);
2304 cb->ccb_scp.scp_direction = SCSI_LOW_READ;
2305 cb->ccb_tcmax = 15;
2306 return SCSI_LOW_START_QTAG;
2307
2308 default:
2309 panic("%s: no setup phase", slp->sl_xname);
2310 }
2311
2312 return SCSI_LOW_START_NO_QTAG;
2313}
2314
2315static int
2316scsi_low_resume(slp)
2317 struct scsi_low_softc *slp;
2318{
2319
2320 if (slp->sl_flags & HW_RESUME)
2321 return EJUSTRETURN;
2322 slp->sl_flags &= ~HW_POWDOWN;
2323 if (slp->sl_funcs->scsi_low_power != NULL)
2324 {
2325 slp->sl_flags |= HW_RESUME;
2326 slp->sl_rstep = 0;
2327 (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE);
2328 (*slp->sl_osdep_fp->scsi_low_osdep_timeout)
2329 (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE,
2330 SCSI_LOW_TIMEOUT_START);
2331 return EJUSTRETURN;
2332 }
2333 return 0;
2334}
2335
2336static void
2337scsi_low_start(slp)
2338 struct scsi_low_softc *slp;
2339{
2340 struct targ_info *ti;
2341 struct lun_info *li;
2342 struct slccb *cb;
2343 int rv;
2344
2345 /* check hardware exists or under initializations ? */
2346 if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0)
2347 return;
2348
2349 /* check hardware power up ? */
2350 if ((slp->sl_flags & HW_POWERCTRL) != 0)
2351 {
2352 slp->sl_active ++;
2353 if (slp->sl_flags & (HW_POWDOWN | HW_RESUME))
2354 {
2355 if (scsi_low_resume(slp) == EJUSTRETURN)
2356 return;
2357 }
2358 }
2359
2360 /* setup nexus */
2361#ifdef SCSI_LOW_DIAGNOSTIC
2362 if (slp->sl_Tnexus || slp->sl_Lnexus || slp->sl_Qnexus)
2363 {
2364 scsi_low_info(slp, NULL, "NEXUS INCOSISTENT");
2365 panic("%s: inconsistent", slp->sl_xname);
2366 }
2367#endif /* SCSI_LOW_DIAGNOSTIC */
2368
2369 for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL;
2370 cb = TAILQ_NEXT(cb, ccb_chain))
2371 {
2372 li = cb->li;
2373
2374 if (li->li_disc == 0)
2375 {
2376 goto scsi_low_cmd_start;
2377 }
2378 else if (li->li_nqio > 0)
2379 {
2380 if (li->li_nqio < li->li_maxnqio ||
2381 (cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0)
2382 goto scsi_low_cmd_start;
2383 }
2384 }
2385 return;
2386
2387scsi_low_cmd_start:
2388 cb->ccb_flags &= ~CCB_STARTQ;
2389 TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain);
2390 ti = cb->ti;
2391
2392 /* clear all error flag bits (for restart) */
2393 cb->ccb_error = 0;
2394 cb->ccb_datalen = -1;
2395 cb->ccb_scp.scp_status = ST_UNKNOWN;
2396
2397 /* setup nexus pointer */
2398 slp->sl_Qnexus = cb;
2399 slp->sl_Lnexus = li;
2400 slp->sl_Tnexus = ti;
2401
2402 /* initialize msgsys */
2403 scsi_low_init_msgsys(slp, ti);
2404
2405 /* exec cmd */
2406 if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0)
2407 {
2408 /* CA state or forced abort */
2409 rv = scsi_low_sense_abort_start(slp, ti, li, cb);
2410 }
2411 else if (li->li_state >= SCSI_LOW_LUN_OK)
2412 {
2413 cb->ccb_flags &= ~CCB_INTERNAL;
2414 rv = (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, cb);
2415 if (cb->ccb_msgoutflag != 0)
2416 {
2417 scsi_low_ccb_message_exec(slp, cb);
2418 }
2419 }
2420 else
2421 {
2422 cb->ccb_flags |= CCB_INTERNAL;
2423 rv = scsi_low_setup_start(slp, ti, li, cb);
2424 }
2425
2426 /* allocate qtag */
2427#define SCSI_LOW_QTAG_OK (SCSI_LOW_QTAG | SCSI_LOW_DISC)
2428
2429 if (rv == SCSI_LOW_START_QTAG &&
2430 (li->li_flags & SCSI_LOW_QTAG_OK) == SCSI_LOW_QTAG_OK &&
2431 li->li_maxnqio > 0)
2432 {
2433 u_int qmsg;
2434
2435 scsi_low_activate_qtag(cb);
2436 if ((scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] &
2437 SCSI_LOW_CMD_ORDERED_QTAG) != 0)
2438 qmsg = SCSI_LOW_MSG_ORDERED_QTAG;
2439 else if ((cb->ccb_flags & CCB_URGENT) != 0)
2440 qmsg = SCSI_LOW_MSG_HEAD_QTAG;
2441 else
2442 qmsg = SCSI_LOW_MSG_SIMPLE_QTAG;
2443 scsi_low_assert_msg(slp, ti, qmsg, 0);
2444 }
2445
2446 /* timeout */
2447 if (cb->ccb_tcmax < SCSI_LOW_MIN_TOUT)
2448 cb->ccb_tcmax = SCSI_LOW_MIN_TOUT;
2449 cb->ccb_tc = cb->ccb_tcmax;
2450
2451 /* setup saved scsi data pointer */
2452 cb->ccb_sscp = cb->ccb_scp;
2453
2454 /* setup current scsi pointer */
2455 slp->sl_scp = cb->ccb_sscp;
2456 slp->sl_error = cb->ccb_error;
2457
2458 /* assert always an identify msg */
2459 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0);
2460
2461 /* debug section */
2462#ifdef SCSI_LOW_DIAGNOSTIC
2463 scsi_low_msg_log_init(&ti->ti_log_msgin);
2464 scsi_low_msg_log_init(&ti->ti_log_msgout);
2465#endif /* SCSI_LOW_DIAGNOSTIC */
2466
2467 /* selection start */
2468 slp->sl_selid = cb;
2469 rv = ((*slp->sl_funcs->scsi_low_start_bus) (slp, cb));
2470 if (rv == SCSI_LOW_START_OK)
2471 {
2472#ifdef SCSI_LOW_STATICS
2473 scsi_low_statics.nexus_win ++;
2474#endif /* SCSI_LOW_STATICS */
2475 return;
2476 }
2477
2478 scsi_low_arbit_fail(slp, cb);
2479#ifdef SCSI_LOW_STATICS
2480 scsi_low_statics.nexus_fail ++;
2481#endif /* SCSI_LOW_STATICS */
2482}
2483
2484void
2485scsi_low_arbit_fail(slp, cb)
2486 struct scsi_low_softc *slp;
2487 struct slccb *cb;
2488{
2489 struct targ_info *ti = cb->ti;
2490
2491 scsi_low_deactivate_qtag(cb);
2492 scsi_low_ccb_message_retry(cb);
2493 cb->ccb_flags |= CCB_STARTQ;
2494 TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
2495
2496 scsi_low_bus_release(slp, ti);
2497
2498 cb->ccb_selrcnt ++;
2499 if (slp->sl_disc == 0)
2500 {
2501#ifdef SCSI_LOW_DIAGNOSTIC
2502 printf("%s: try selection again\n", slp->sl_xname);
2503#endif /* SCSI_LOW_DIAGNOSTIC */
2504 slp->sl_retry_sel = 1;
2505 }
2506}
2507
2508static void
2509scsi_low_bus_release(slp, ti)
2510 struct scsi_low_softc *slp;
2511 struct targ_info *ti;
2512{
2513
2514 if (ti->ti_disc > 0)
2515 {
2516 SCSI_LOW_SETUP_PHASE(ti, PH_DISC);
2517 }
2518 else
2519 {
2520 SCSI_LOW_SETUP_PHASE(ti, PH_NULL);
2521 }
2522
2523 /* clear all nexus pointer */
2524 slp->sl_Qnexus = NULL;
2525 slp->sl_Lnexus = NULL;
2526 slp->sl_Tnexus = NULL;
2527
2528 /* clear selection assert */
2529 slp->sl_selid = NULL;
2530
2531 /* clear nexus data */
2532 slp->sl_scp.scp_direction = SCSI_LOW_RWUNK;
2533
2534 /* clear phase change counter */
2535 slp->sl_ph_count = 0;
2536}
2537
2538static int
2539scsi_low_setup_done(slp, cb)
2540 struct scsi_low_softc *slp;
2541 struct slccb *cb;
2542{
2543 struct targ_info *ti;
2544 struct lun_info *li;
2545
2546 ti = cb->ti;
2547 li = cb->li;
2548
2549 if (cb->ccb_rcnt >= slp->sl_max_retry)
2550 {
2551 cb->ccb_error |= ABORTIO;
2552 return SCSI_LOW_DONE_COMPLETE;
2553 }
2554
2555 /* XXX: special huck for selection timeout */
2556 if (li->li_state == SCSI_LOW_LUN_SLEEP &&
2557 (cb->ccb_error & SELTIMEOUTIO) != 0)
2558 {
2559 cb->ccb_error |= ABORTIO;
2560 return SCSI_LOW_DONE_COMPLETE;
2561 }
2562
2563 switch(li->li_state)
2564 {
2565 case SCSI_LOW_LUN_INQ:
2566 if (cb->ccb_error != 0)
2567 {
2568 li->li_diskflags &=
2569 ~(SCSI_LOW_DISK_LINK | SCSI_LOW_DISK_QTAG);
2570 if (li->li_lun > 0)
2571 goto resume;
2572 ti->ti_diskflags &=
2573 ~(SCSI_LOW_DISK_SYNC | SCSI_LOW_DISK_WIDE);
2574 }
2575 else if ((li->li_inq.sd_version & 7) >= 2 ||
2576 (li->li_inq.sd_len >= 4))
2577 {
2578 if ((li->li_inq.sd_support & 0x2) == 0)
2579 li->li_diskflags &= ~SCSI_LOW_DISK_QTAG;
2580 if ((li->li_inq.sd_support & 0x8) == 0)
2581 li->li_diskflags &= ~SCSI_LOW_DISK_LINK;
2582 if (li->li_lun > 0)
2583 goto resume;
2584 if ((li->li_inq.sd_support & 0x10) == 0)
2585 ti->ti_diskflags &= ~SCSI_LOW_DISK_SYNC;
2586 if ((li->li_inq.sd_support & 0x20) == 0)
2587 ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_16;
2588 if ((li->li_inq.sd_support & 0x40) == 0)
2589 ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_32;
2590 }
2591 else
2592 {
2593 li->li_diskflags &=
2594 ~(SCSI_LOW_DISK_QTAG | SCSI_LOW_DISK_LINK);
2595 if (li->li_lun > 0)
2596 goto resume;
2597 ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE;
2598 }
2599 ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_DISK_VALID;
2600resume:
2601 scsi_low_calcf_target(ti);
2602 scsi_low_calcf_lun(li);
2603 break;
2604
2605 case SCSI_LOW_LUN_MODEQ:
2606 if (cb->ccb_error != 0)
2607 {
2608 if (cb->ccb_error & SENSEIO)
2609 {
2610#ifdef SCSI_LOW_DEBUG
2611 if (scsi_low_debug & SCSI_LOW_DEBUG_SENSE)
2612 {
2613 printf("SENSE: [%x][%x][%x][%x][%x]\n",
2614 (u_int) cb->ccb_sense.error_code,
2615 (u_int) cb->ccb_sense.segment,
2616 (u_int) cb->ccb_sense.flags,
2617 (u_int) cb->ccb_sense.add_sense_code,
2618 (u_int) cb->ccb_sense.add_sense_code_qual);
2619 }
2620#endif /* SCSI_LOW_DEBUG */
2621 }
2622 else
2623 {
2624 li->li_diskflags &= ~SCSI_LOW_DISK_QTAG;
2625 }
2626 }
2627 else if ((li->li_sms.sms_cmp.cmp_page & 0x3f) == 0x0a)
2628 {
2629 if (li->li_sms.sms_cmp.cmp_qc & 0x02)
2630 li->li_qflags |= SCSI_LOW_QFLAG_CA_QCLEAR;
2631 else
2632 li->li_qflags &= ~SCSI_LOW_QFLAG_CA_QCLEAR;
2633 if ((li->li_sms.sms_cmp.cmp_qc & 0x01) != 0)
2634 li->li_diskflags &= ~SCSI_LOW_DISK_QTAG;
2635 }
2636 li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_DISK_VALID;
2637 scsi_low_calcf_lun(li);
2638 break;
2639
2640 default:
2641 break;
2642 }
2643
2644 li->li_state ++;
2645 if (li->li_state == SCSI_LOW_LUN_OK)
2646 {
2647 scsi_low_calcf_target(ti);
2648 scsi_low_calcf_lun(li);
2649 if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID &&
2650 (slp->sl_show_result & SHOW_CALCF_RES) != 0)
2651 {
2652 scsi_low_calcf_show(li);
2653 }
2654 }
2655
2656 cb->ccb_rcnt --;
2657 return SCSI_LOW_DONE_RETRY;
2658}
2659
2660static int
2661scsi_low_done(slp, cb)
2662 struct scsi_low_softc *slp;
2663 struct slccb *cb;
2664{
2665 int rv;
2666
2667 if (cb->ccb_error == 0)
2668 {
2669 if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0)
2670 {
2671#ifdef SCSI_LOW_QCLEAR_AFTER_CA
2672 /* XXX:
2673 * SCSI-2 draft suggests
2674 * page 0x0a QErr bit determins if
2675 * the target aborts or continues
2676 * the queueing io's after CA state resolved.
2677 * However many targets seem not to support
2678 * the page 0x0a. Thus we should manually clear the
2679 * queuing io's after CA state.
2680 */
2681 if ((cb->ccb_flags & CCB_CLEARQ) == 0)
2682 {
2683 cb->ccb_rcnt --;
2684 cb->ccb_flags |= CCB_CLEARQ;
2685 goto retry;
2686 }
2687#endif /* SCSI_LOW_QCLEAR_AFTER_CA */
2688
2689 if ((cb->ccb_flags & CCB_SENSE) != 0)
2690 cb->ccb_error |= (SENSEIO | ABORTIO);
2691 cb->ccb_flags &= ~(CCB_SENSE | CCB_CLEARQ);
2692 }
2693 else switch (cb->ccb_sscp.scp_status)
2694 {
2695 case ST_GOOD:
2696 case ST_MET:
2697 case ST_INTERGOOD:
2698 case ST_INTERMET:
2699 if (cb->ccb_datalen == 0 ||
2700 cb->ccb_scp.scp_datalen == 0)
2701 break;
2702
2703 if (cb->ccb_scp.scp_cmdlen > 0 &&
2704 (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] &
2705 SCSI_LOW_CMD_RESIDUAL_CHK) == 0)
2706 break;
2707
2708 cb->ccb_error |= PDMAERR;
2709 break;
2710
2711 case ST_BUSY:
2712 case ST_QUEFULL:
2713 cb->ccb_error |= (BUSYERR | STATERR);
2714 break;
2715
2716 case ST_CONFLICT:
2717 cb->ccb_error |= (STATERR | ABORTIO);
2718 break;
2719
2720 case ST_CHKCOND:
2721 case ST_CMDTERM:
2722 if (cb->ccb_flags & (CCB_AUTOSENSE | CCB_INTERNAL))
2723 {
2724 cb->ccb_rcnt --;
2725 cb->ccb_flags |= CCB_SENSE;
2726 goto retry;
2727 }
2728 cb->ccb_error |= (UACAERR | STATERR | ABORTIO);
2729 break;
2730
2731 case ST_UNKNOWN:
2732 default:
2733 cb->ccb_error |= FATALIO;
2734 break;
2735 }
2736 }
2737 else
2738 {
2739 if (cb->ccb_flags & CCB_SENSE)
2740 {
2741 cb->ccb_error |= (SENSEERR | ABORTIO);
2742 }
2743 cb->ccb_flags &= ~(CCB_CLEARQ | CCB_SENSE);
2744 }
2745
2746 /* internal ccb */
2747 if ((cb->ccb_flags & CCB_INTERNAL) != 0)
2748 {
2749 if (scsi_low_setup_done(slp, cb) == SCSI_LOW_DONE_RETRY)
2750 goto retry;
2751 }
2752
2753 /* check a ccb msgout flag */
2754 if (cb->ccb_omsgoutflag != 0)
2755 {
2756#define SCSI_LOW_MSG_ABORT_OK (SCSI_LOW_MSG_ABORT | \
2757 SCSI_LOW_MSG_ABORT_QTAG | \
2758 SCSI_LOW_MSG_CLEAR_QTAG | \
2759 SCSI_LOW_MSG_TERMIO)
2760
2761 if ((cb->ccb_omsgoutflag & SCSI_LOW_MSG_ABORT_OK) != 0)
2762 {
2763 cb->ccb_error |= ABORTIO;
2764 }
2765 }
2766
2767 /* call OS depend done */
2768 if (cb->osdep != NULL)
2769 {
2770 rv = (*slp->sl_osdep_fp->scsi_low_osdep_done) (slp, cb);
2771 if (rv == EJUSTRETURN)
2772 goto retry;
2773 }
2774 else if (cb->ccb_error != 0)
2775 {
2776 if (cb->ccb_rcnt >= slp->sl_max_retry)
2777 cb->ccb_error |= ABORTIO;
2778
2779 if ((cb->ccb_flags & CCB_NORETRY) == 0 &&
2780 (cb->ccb_error & ABORTIO) == 0)
2781 goto retry;
2782 }
2783
2784 /* free our target */
2785#ifdef SCSI_LOW_DEBUG
2786 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0)
2787 {
2788 printf(">> SCSI_LOW_DONE_COMPLETE ===============\n");
2789 scsi_low_print(slp, NULL);
2790 }
2791#endif /* SCSI_LOW_DEBUG */
2792
2793 scsi_low_deactivate_qtag(cb);
2794 scsi_low_dealloc_qtag(cb);
2795 scsi_low_free_ccb(cb);
2796 slp->sl_nio --;
2797 return SCSI_LOW_DONE_COMPLETE;
2798
2799retry:
2800#ifdef SCSI_LOW_DEBUG
2801 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0)
2802 {
2803 printf("** SCSI_LOW_DONE_RETRY ===============\n");
2804 scsi_low_print(slp, NULL);
2805 }
2806#endif /* SCSI_LOW_DEBUG */
2807
2808 cb->ccb_rcnt ++;
2809 scsi_low_deactivate_qtag(cb);
2810 scsi_low_ccb_message_retry(cb);
2811 return SCSI_LOW_DONE_RETRY;
2812}
2813
2814/**************************************************************
2815 * Reset
2816 **************************************************************/
2817static void
2818scsi_low_reset_nexus_target(slp, ti, fdone)
2819 struct scsi_low_softc *slp;
2820 struct targ_info *ti;
2821 int fdone;
2822{
2823 struct lun_info *li;
2824
2825 for (li = LIST_FIRST(&ti->ti_litab); li != NULL;
2826 li = LIST_NEXT(li, lun_chain))
2827 {
2828 scsi_low_reset_nexus_lun(slp, li, fdone);
2829 li->li_state = SCSI_LOW_LUN_SLEEP;
2830 li->li_maxnqio = 0;
2831 }
2832
2833 ti->ti_disc = 0;
2834 ti->ti_setup_msg = 0;
2835 ti->ti_setup_msg_done = 0;
2836
2837 ti->ti_osynch.offset = ti->ti_osynch.period = 0;
2838 ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8;
2839
2840 ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS;
2841 ti->ti_flags_valid &= ~SCSI_LOW_TARG_FLAGS_DISK_VALID;
2842
2843 if (slp->sl_funcs->scsi_low_targ_init != NULL)
2844 {
2845 ((*slp->sl_funcs->scsi_low_targ_init)
2846 (slp, ti, SCSI_LOW_INFO_REVOKE));
2847 }
2848 scsi_low_calcf_target(ti);
2849
2850 for (li = LIST_FIRST(&ti->ti_litab); li != NULL;
2851 li = LIST_NEXT(li, lun_chain))
2852 {
2853 li->li_flags = 0;
2854
2855 li->li_diskflags = SCSI_LOW_DISK_LFLAGS;
2856 li->li_flags_valid &= ~SCSI_LOW_LUN_FLAGS_DISK_VALID;
2857
2858 if (slp->sl_funcs->scsi_low_lun_init != NULL)
2859 {
2860 ((*slp->sl_funcs->scsi_low_lun_init)
2861 (slp, ti, li, SCSI_LOW_INFO_REVOKE));
2862 }
2863 scsi_low_calcf_lun(li);
2864 }
2865}
2866
2867static void
2868scsi_low_reset_nexus(slp, fdone)
2869 struct scsi_low_softc *slp;
2870 int fdone;
2871{
2872 struct targ_info *ti;
2873 struct slccb *cb, *topcb;
2874
2875 if ((cb = slp->sl_Qnexus) != NULL)
2876 {
2877 topcb = scsi_low_revoke_ccb(slp, cb, fdone);
2878 }
2879 else
2880 {
2881 topcb = NULL;
2882 }
2883
2884 for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
2885 ti = TAILQ_NEXT(ti, ti_chain))
2886 {
2887 scsi_low_reset_nexus_target(slp, ti, fdone);
2888 scsi_low_bus_release(slp, ti);
2889 scsi_low_init_msgsys(slp, ti);
2890 }
2891
2892 if (topcb != NULL)
2893 {
2894 topcb->ccb_flags |= CCB_STARTQ;
2895 TAILQ_INSERT_HEAD(&slp->sl_start, topcb, ccb_chain);
2896 }
2897
2898 slp->sl_disc = 0;
2899 slp->sl_retry_sel = 0;
2900 slp->sl_flags &= ~HW_PDMASTART;
2901}
2902
2903/* misc */
2904static int tw_pos;
2905static char tw_chars[] = "|/-\\";
2906#define TWIDDLEWAIT 10000
2907
2908static void
2909scsi_low_twiddle_wait(void)
2910{
2911
2912 cnputc('\b');
2913 cnputc(tw_chars[tw_pos++]);
2914 tw_pos %= (sizeof(tw_chars) - 1);
2915 SCSI_LOW_DELAY(TWIDDLEWAIT);
2916}
2917
2918void
2919scsi_low_bus_reset(slp)
2920 struct scsi_low_softc *slp;
2921{
2922 int i;
2923
2924 (*slp->sl_funcs->scsi_low_bus_reset) (slp);
2925
2926 printf("%s: try to reset scsi bus ", slp->sl_xname);
2927 for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++)
2928 scsi_low_twiddle_wait();
2929 cnputc('\b');
2930 printf("\n");
2931}
2932
2933int
2934scsi_low_restart(slp, flags, s)
2935 struct scsi_low_softc *slp;
2936 int flags;
2937 u_char *s;
2938{
2939 int error;
2940
2941 if (s != NULL)
2942 printf("%s: scsi bus restart. reason: %s\n", slp->sl_xname, s);
2943
2944 if ((error = scsi_low_init(slp, flags)) != 0)
2945 return error;
2946
2947 scsi_low_start(slp);
2948 return 0;
2949}
2950
2951/**************************************************************
2952 * disconnect and reselect
2953 **************************************************************/
2954#define MSGCMD_LUN(msg) (msg & 0x07)
2955
2956static struct slccb *
2957scsi_low_establish_ccb(ti, li, tag)
2958 struct targ_info *ti;
2959 struct lun_info *li;
2960 scsi_low_tag_t tag;
2961{
2962 struct scsi_low_softc *slp = ti->ti_sc;
2963 struct slccb *cb;
2964
2965 if (li == NULL)
2966 return NULL;
2967
2968 cb = TAILQ_FIRST(&li->li_discq);
2969 for ( ; cb != NULL; cb = TAILQ_NEXT(cb, ccb_chain))
2970 if (cb->ccb_tag == tag)
2971 goto found;
2972 return cb;
2973
2974 /*
2975 * establish our ccb nexus
2976 */
2977found:
2978#ifdef SCSI_LOW_DEBUG
2979 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0)
2980 {
2981 printf("%s: nexus(0x%lx) abort check start\n",
2982 slp->sl_xname, (u_long) cb);
2983 cb->ccb_flags |= (CCB_NORETRY | CCB_SILENT);
2984 scsi_low_revoke_ccb(slp, cb, 1);
2985 return NULL;
2986 }
2987
2988 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id) != 0)
2989 {
2990 if (cb->ccb_omsgoutflag == 0)
2991 scsi_low_ccb_message_assert(cb, SCSI_LOW_MSG_NOOP);
2992 }
2993#endif /* SCSI_LOW_DEBUG */
2994
2995 TAILQ_REMOVE(&li->li_discq, cb, ccb_chain);
2996 cb->ccb_flags &= ~CCB_DISCQ;
2997 slp->sl_Qnexus = cb;
2998
2999 slp->sl_scp = cb->ccb_sscp;
3000 slp->sl_error |= cb->ccb_error;
3001
3002 slp->sl_disc --;
3003 ti->ti_disc --;
3004 li->li_disc --;
3005
3006 /* inform "ccb nexus established" to the host driver */
3007 (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp);
3008
3009 /* check msg */
3010 if (cb->ccb_msgoutflag != 0)
3011 {
3012 scsi_low_ccb_message_exec(slp, cb);
3013 }
3014
3015 return cb;
3016}
3017
3018struct targ_info *
3019scsi_low_reselected(slp, targ)
3020 struct scsi_low_softc *slp;
3021 u_int targ;
3022{
3023 struct targ_info *ti;
3024 struct slccb *cb;
3025 u_char *s;
3026
3027 /*
3028 * Check select vs reselected collision.
3029 */
3030
3031 if ((cb = slp->sl_selid) != NULL)
3032 {
3033 scsi_low_arbit_fail(slp, cb);
3034#ifdef SCSI_LOW_STATICS
3035 scsi_low_statics.nexus_conflict ++;
3036#endif /* SCSI_LOW_STATICS */
3037 }
3038
3039 /*
3040 * Check if no current active nexus.
3041 */
3042 if (slp->sl_Tnexus != NULL)
3043 {
3044 s = "host busy";
3045 goto world_restart;
3046 }
3047
3048 /*
3049 * Check a valid target id asserted ?
3050 */
3051 if (targ >= slp->sl_ntargs || targ == slp->sl_hostid)
3052 {
3053 s = "scsi id illegal";
3054 goto world_restart;
3055 }
3056
3057 /*
3058 * Check the target scsi status.
3059 */
3060 ti = slp->sl_ti[targ];
3061 if (ti->ti_phase != PH_DISC && ti->ti_phase != PH_NULL)
3062 {
3063 s = "phase mismatch";
3064 goto world_restart;
3065 }
3066
3067 /*
3068 * Setup init msgsys
3069 */
3070 slp->sl_error = 0;
3071 scsi_low_init_msgsys(slp, ti);
3072
3073 /*
3074 * Establish our target nexus
3075 */
3076 SCSI_LOW_SETUP_PHASE(ti, PH_RESEL);
3077 slp->sl_Tnexus = ti;
3078#ifdef SCSI_LOW_STATICS
3079 scsi_low_statics.nexus_reselected ++;
3080#endif /* SCSI_LOW_STATICS */
3081 return ti;
3082
3083world_restart:
3084 printf("%s: reselect(%x:unknown) %s\n", slp->sl_xname, targ, s);
3085 scsi_low_restart(slp, SCSI_LOW_RESTART_HARD,
3086 "reselect: scsi world confused");
3087 return NULL;
3088}
3089
3090/**************************************************************
3091 * cmd out pointer setup
3092 **************************************************************/
3093int
3094scsi_low_cmd(slp, ti)
3095 struct scsi_low_softc *slp;
3096 struct targ_info *ti;
3097{
3098 struct slccb *cb = slp->sl_Qnexus;
3099
3100 slp->sl_ph_count ++;
3101 if (cb == NULL)
3102 {
3103 /*
3104 * no ccb, abort!
3105 */
3106 slp->sl_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd;
3107 slp->sl_scp.scp_cmdlen = sizeof(unit_ready_cmd);
3108 slp->sl_scp.scp_datalen = 0;
3109 slp->sl_scp.scp_direction = SCSI_LOW_READ;
3110 slp->sl_error |= FATALIO;
3111 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
3112 SCSI_LOW_INFO(slp, ti, "CMDOUT: ccb nexus not found");
3113 return EINVAL;
3114 }
3115 else
3116 {
3117#ifdef SCSI_LOW_DEBUG
3118 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_CMDLNK_CHECK, ti->ti_id))
3119 {
3120 scsi_low_test_cmdlnk(slp, cb);
3121 }
3122#endif /* SCSI_LOW_DEBUG */
3123 }
3124 return 0;
3125}
3126
3127/**************************************************************
3128 * data out pointer setup
3129 **************************************************************/
3130int
3131scsi_low_data(slp, ti, bp, direction)
3132 struct scsi_low_softc *slp;
3133 struct targ_info *ti;
3134 struct buf **bp;
3135 int direction;
3136{
3137 struct slccb *cb = slp->sl_Qnexus;
3138
3139 if (cb != NULL && direction == cb->ccb_sscp.scp_direction)
3140 {
3141 *bp = cb->bp;
3142 return 0;
3143 }
3144
3145 slp->sl_error |= (FATALIO | PDMAERR);
3146 slp->sl_scp.scp_datalen = 0;
3147 slp->sl_scp.scp_direction = direction;
3148 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
3149 if (ti->ti_ophase != ti->ti_phase)
3150 {
3151 char *s;
3152
3153 if (cb == NULL)
3154 s = "DATA PHASE: ccb nexus not found";
3155 else
3156 s = "DATA PHASE: xfer direction mismatch";
3157 SCSI_LOW_INFO(slp, ti, s);
3158 }
3159
3160 *bp = NULL;
3161 return EINVAL;
3162}
3163
3164/**************************************************************
3165 * MSG_SYS
3166 **************************************************************/
3167#define MSGINPTR_CLR(ti) {(ti)->ti_msginptr = 0; (ti)->ti_msginlen = 0;}
3168#define MSGIN_PERIOD(ti) ((ti)->ti_msgin[3])
3169#define MSGIN_OFFSET(ti) ((ti)->ti_msgin[4])
3170#define MSGIN_WIDTHP(ti) ((ti)->ti_msgin[3])
3171#define MSGIN_DATA_LAST 0x30
3172
3173static int scsi_low_errfunc_synch(struct scsi_low_softc *, u_int);
3174static int scsi_low_errfunc_wide(struct scsi_low_softc *, u_int);
3175static int scsi_low_errfunc_identify(struct scsi_low_softc *, u_int);
3176static int scsi_low_errfunc_qtag(struct scsi_low_softc *, u_int);
3177
3178static int scsi_low_msgfunc_synch(struct scsi_low_softc *);
3179static int scsi_low_msgfunc_wide(struct scsi_low_softc *);
3180static int scsi_low_msgfunc_identify(struct scsi_low_softc *);
3181static int scsi_low_msgfunc_abort(struct scsi_low_softc *);
3182static int scsi_low_msgfunc_qabort(struct scsi_low_softc *);
3183static int scsi_low_msgfunc_qtag(struct scsi_low_softc *);
3184static int scsi_low_msgfunc_reset(struct scsi_low_softc *);
3185
3186struct scsi_low_msgout_data {
3187 u_int md_flags;
3188 u_int8_t md_msg;
3189 int (*md_msgfunc)(struct scsi_low_softc *);
3190 int (*md_errfunc)(struct scsi_low_softc *, u_int);
3191#define MSG_RELEASE_ATN 0x0001
3192 u_int md_condition;
3193};
3194
3195struct scsi_low_msgout_data scsi_low_msgout_data[] = {
3196/* 0 */ {SCSI_LOW_MSG_RESET, MSG_RESET, scsi_low_msgfunc_reset, NULL, MSG_RELEASE_ATN},
3197/* 1 */ {SCSI_LOW_MSG_REJECT, MSG_REJECT, NULL, NULL, MSG_RELEASE_ATN},
3198/* 2 */ {SCSI_LOW_MSG_PARITY, MSG_PARITY, NULL, NULL, MSG_RELEASE_ATN},
3199/* 3 */ {SCSI_LOW_MSG_ERROR, MSG_I_ERROR, NULL, NULL, MSG_RELEASE_ATN},
3200/* 4 */ {SCSI_LOW_MSG_IDENTIFY, MSG_IDENTIFY, scsi_low_msgfunc_identify, scsi_low_errfunc_identify, 0},
3201/* 5 */ {SCSI_LOW_MSG_ABORT, MSG_ABORT, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN},
3202/* 6 */ {SCSI_LOW_MSG_TERMIO, MSG_TERM_IO, NULL, NULL, MSG_RELEASE_ATN},
3203/* 7 */ {SCSI_LOW_MSG_SIMPLE_QTAG, MSG_SIMPLE_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0},
3204/* 8 */ {SCSI_LOW_MSG_ORDERED_QTAG, MSG_ORDERED_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0},
3205/* 9 */{SCSI_LOW_MSG_HEAD_QTAG, MSG_HEAD_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0},
3206/* 10 */ {SCSI_LOW_MSG_ABORT_QTAG, MSG_ABORT_QTAG, scsi_low_msgfunc_qabort, NULL, MSG_RELEASE_ATN},
3207/* 11 */ {SCSI_LOW_MSG_CLEAR_QTAG, MSG_CLEAR_QTAG, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN},
3208/* 12 */{SCSI_LOW_MSG_WIDE, MSG_EXTEND, scsi_low_msgfunc_wide, scsi_low_errfunc_wide, MSG_RELEASE_ATN},
3209/* 13 */{SCSI_LOW_MSG_SYNCH, MSG_EXTEND, scsi_low_msgfunc_synch, scsi_low_errfunc_synch, MSG_RELEASE_ATN},
3210/* 14 */{SCSI_LOW_MSG_NOOP, MSG_NOOP, NULL, NULL, MSG_RELEASE_ATN},
3211/* 15 */{SCSI_LOW_MSG_ALL, 0},
3212};
3213
3214static int scsi_low_msginfunc_ext(struct scsi_low_softc *);
3215static int scsi_low_synch(struct scsi_low_softc *);
3216static int scsi_low_wide(struct scsi_low_softc *);
3217static int scsi_low_msginfunc_msg_reject(struct scsi_low_softc *);
3218static int scsi_low_msginfunc_rejop(struct scsi_low_softc *);
3219static int scsi_low_msginfunc_rp(struct scsi_low_softc *);
3220static int scsi_low_msginfunc_sdp(struct scsi_low_softc *);
3221static int scsi_low_msginfunc_disc(struct scsi_low_softc *);
3222static int scsi_low_msginfunc_cc(struct scsi_low_softc *);
3223static int scsi_low_msginfunc_lcc(struct scsi_low_softc *);
3224static int scsi_low_msginfunc_parity(struct scsi_low_softc *);
3225static int scsi_low_msginfunc_noop(struct scsi_low_softc *);
3226static int scsi_low_msginfunc_simple_qtag(struct scsi_low_softc *);
3227static int scsi_low_msginfunc_i_wide_residue(struct scsi_low_softc *);
3228
3229struct scsi_low_msgin_data {
3230 u_int md_len;
3231 int (*md_msgfunc)(struct scsi_low_softc *);
3232};
3233
3234struct scsi_low_msgin_data scsi_low_msgin_data[] = {
3235/* 0 */ {1, scsi_low_msginfunc_cc},
3236/* 1 */ {2, scsi_low_msginfunc_ext},
3237/* 2 */ {1, scsi_low_msginfunc_sdp},
3238/* 3 */ {1, scsi_low_msginfunc_rp},
3239/* 4 */ {1, scsi_low_msginfunc_disc},
3240/* 5 */ {1, scsi_low_msginfunc_rejop},
3241/* 6 */ {1, scsi_low_msginfunc_rejop},
3242/* 7 */ {1, scsi_low_msginfunc_msg_reject},
3243/* 8 */ {1, scsi_low_msginfunc_noop},
3244/* 9 */ {1, scsi_low_msginfunc_parity},
3245/* a */ {1, scsi_low_msginfunc_lcc},
3246/* b */ {1, scsi_low_msginfunc_lcc},
3247/* c */ {1, scsi_low_msginfunc_rejop},
3248/* d */ {2, scsi_low_msginfunc_rejop},
3249/* e */ {1, scsi_low_msginfunc_rejop},
3250/* f */ {1, scsi_low_msginfunc_rejop},
3251/* 0x10 */ {1, scsi_low_msginfunc_rejop},
3252/* 0x11 */ {1, scsi_low_msginfunc_rejop},
3253/* 0x12 */ {1, scsi_low_msginfunc_rejop},
3254/* 0x13 */ {1, scsi_low_msginfunc_rejop},
3255/* 0x14 */ {1, scsi_low_msginfunc_rejop},
3256/* 0x15 */ {1, scsi_low_msginfunc_rejop},
3257/* 0x16 */ {1, scsi_low_msginfunc_rejop},
3258/* 0x17 */ {1, scsi_low_msginfunc_rejop},
3259/* 0x18 */ {1, scsi_low_msginfunc_rejop},
3260/* 0x19 */ {1, scsi_low_msginfunc_rejop},
3261/* 0x1a */ {1, scsi_low_msginfunc_rejop},
3262/* 0x1b */ {1, scsi_low_msginfunc_rejop},
3263/* 0x1c */ {1, scsi_low_msginfunc_rejop},
3264/* 0x1d */ {1, scsi_low_msginfunc_rejop},
3265/* 0x1e */ {1, scsi_low_msginfunc_rejop},
3266/* 0x1f */ {1, scsi_low_msginfunc_rejop},
3267/* 0x20 */ {2, scsi_low_msginfunc_simple_qtag},
3268/* 0x21 */ {2, scsi_low_msginfunc_rejop},
3269/* 0x22 */ {2, scsi_low_msginfunc_rejop},
3270/* 0x23 */ {2, scsi_low_msginfunc_i_wide_residue},
3271/* 0x24 */ {2, scsi_low_msginfunc_rejop},
3272/* 0x25 */ {2, scsi_low_msginfunc_rejop},
3273/* 0x26 */ {2, scsi_low_msginfunc_rejop},
3274/* 0x27 */ {2, scsi_low_msginfunc_rejop},
3275/* 0x28 */ {2, scsi_low_msginfunc_rejop},
3276/* 0x29 */ {2, scsi_low_msginfunc_rejop},
3277/* 0x2a */ {2, scsi_low_msginfunc_rejop},
3278/* 0x2b */ {2, scsi_low_msginfunc_rejop},
3279/* 0x2c */ {2, scsi_low_msginfunc_rejop},
3280/* 0x2d */ {2, scsi_low_msginfunc_rejop},
3281/* 0x2e */ {2, scsi_low_msginfunc_rejop},
3282/* 0x2f */ {2, scsi_low_msginfunc_rejop},
3283/* 0x30 */ {1, scsi_low_msginfunc_rejop} /* default rej op */
3284};
3285
3286/**************************************************************
3287 * msgout
3288 **************************************************************/
3289static int
3290scsi_low_msgfunc_synch(slp)
3291 struct scsi_low_softc *slp;
3292{
3293 struct targ_info *ti = slp->sl_Tnexus;
3294 int ptr = ti->ti_msgoutlen;
3295
3296 ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_SYNCHLEN;
3297 ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_SYNCHCODE;
3298 ti->ti_msgoutstr[ptr + 3] = ti->ti_maxsynch.period;
3299 ti->ti_msgoutstr[ptr + 4] = ti->ti_maxsynch.offset;
3300 return MSG_EXTEND_SYNCHLEN + 2;
3301}
3302
3303static int
3304scsi_low_msgfunc_wide(slp)
3305 struct scsi_low_softc *slp;
3306{
3307 struct targ_info *ti = slp->sl_Tnexus;
3308 int ptr = ti->ti_msgoutlen;
3309
3310 ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_WIDELEN;
3311 ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_WIDECODE;
3312 ti->ti_msgoutstr[ptr + 3] = ti->ti_width;
3313 return MSG_EXTEND_WIDELEN + 2;
3314}
3315
3316static int
3317scsi_low_msgfunc_identify(slp)
3318 struct scsi_low_softc *slp;
3319{
3320 struct targ_info *ti = slp->sl_Tnexus;
3321 struct lun_info *li = slp->sl_Lnexus;
3322 struct slccb *cb = slp->sl_Qnexus;
3323 int ptr = ti->ti_msgoutlen;
3324 u_int8_t msg;
3325
3326 msg = MSG_IDENTIFY;
3327 if (cb == NULL)
3328 {
3329 slp->sl_error |= FATALIO;
3330 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
3331 SCSI_LOW_INFO(slp, ti, "MSGOUT: nexus unknown");
3332 }
3333 else
3334 {
3335 if (scsi_low_is_disconnect_ok(cb) != 0)
3336 msg |= (MSG_IDENTIFY_DISCPRIV | li->li_lun);
3337 else
3338 msg |= li->li_lun;
3339
3340 if (ti->ti_phase == PH_MSGOUT)
3341 {
3342 (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp);
3343 if (cb->ccb_tag == SCSI_LOW_UNKTAG)
3344 {
3345 (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp);
3346 }
3347 }
3348 }
3349 ti->ti_msgoutstr[ptr + 0] = msg;
3350 return 1;
3351}
3352
3353static int
3354scsi_low_msgfunc_abort(slp)
3355 struct scsi_low_softc *slp;
3356{
3357
3358 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_ABORT);
3359 return 1;
3360}
3361
3362static int
3363scsi_low_msgfunc_qabort(slp)
3364 struct scsi_low_softc *slp;
3365{
3366
3367 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_TERM);
3368 return 1;
3369}
3370
3371static int
3372scsi_low_msgfunc_reset(slp)
3373 struct scsi_low_softc *slp;
3374{
3375
3376 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_RESET);
3377 return 1;
3378}
3379
3380static int
3381scsi_low_msgfunc_qtag(slp)
3382 struct scsi_low_softc *slp;
3383{
3384 struct targ_info *ti = slp->sl_Tnexus;
3385 struct slccb *cb = slp->sl_Qnexus;
3386 int ptr = ti->ti_msgoutlen;
3387
3388 if (cb == NULL || cb->ccb_tag == SCSI_LOW_UNKTAG)
3389 {
3390 ti->ti_msgoutstr[ptr + 0] = MSG_NOOP;
3391 return 1;
3392 }
3393 else
3394 {
3395 ti->ti_msgoutstr[ptr + 1] = (u_int8_t) cb->ccb_tag;
3396 if (ti->ti_phase == PH_MSGOUT)
3397 {
3398 (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp);
3399 }
3400 }
3401 return 2;
3402}
3403
3404/*
3405 * The following functions are called when targets give unexpected
3406 * responces in msgin (after msgout).
3407 */
3408static int
3409scsi_low_errfunc_identify(slp, msgflags)
3410 struct scsi_low_softc *slp;
3411 u_int msgflags;
3412{
3413
3414 if (slp->sl_Lnexus != NULL)
3415 {
3416 slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_DISC;
3417 scsi_low_calcf_lun(slp->sl_Lnexus);
3418 }
3419 return 0;
3420}
3421
3422static int
3423scsi_low_errfunc_synch(slp, msgflags)
3424 struct scsi_low_softc *slp;
3425 u_int msgflags;
3426{
3427 struct targ_info *ti = slp->sl_Tnexus;
3428
3429 MSGIN_PERIOD(ti) = 0;
3430 MSGIN_OFFSET(ti) = 0;
3431 scsi_low_synch(slp);
3432 return 0;
3433}
3434
3435static int
3436scsi_low_errfunc_wide(slp, msgflags)
3437 struct scsi_low_softc *slp;
3438 u_int msgflags;
3439{
3440 struct targ_info *ti = slp->sl_Tnexus;
3441
3442 MSGIN_WIDTHP(ti) = 0;
3443 scsi_low_wide(slp);
3444 return 0;
3445}
3446
3447static int
3448scsi_low_errfunc_qtag(slp, msgflags)
3449 struct scsi_low_softc *slp;
3450 u_int msgflags;
3451{
3452
3453 if ((msgflags & SCSI_LOW_MSG_REJECT) != 0)
3454 {
3455 if (slp->sl_Qnexus != NULL)
3456 {
3457 scsi_low_deactivate_qtag(slp->sl_Qnexus);
3458 }
3459 if (slp->sl_Lnexus != NULL)
3460 {
3461 slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_QTAG;
3462 scsi_low_calcf_lun(slp->sl_Lnexus);
3463 }
3464 printf("%s: scsi_low: qtag msg rejected\n", slp->sl_xname);
3465 }
3466 return 0;
3467}
3468
3469
3470int
3471scsi_low_msgout(slp, ti, fl)
3472 struct scsi_low_softc *slp;
3473 struct targ_info *ti;
3474 u_int fl;
3475{
3476 struct scsi_low_msgout_data *mdp;
3477 int len = 0;
3478
3479#ifdef SCSI_LOW_DIAGNOSTIC
3480 if (ti != slp->sl_Tnexus)
3481 {
3482 scsi_low_print(slp, NULL);
3483 panic("scsi_low_msgout: Target nexus inconsistent");
3484 }
3485#endif /* SCSI_LOW_DIAGNOSTIC */
3486
3487 slp->sl_ph_count ++;
3488 if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES)
3489 {
3490 printf("%s: too many phase changes\n", slp->sl_xname);
3491 slp->sl_error |= FATALIO;
3492 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
3493 }
3494
3495 /* STEP I.
3496 * Scsi phase changes.
3497 * Previously msgs asserted are accepted by our target or
3498 * processed by scsi_low_msgin.
3499 * Thus clear all saved informations.
3500 */
3501 if ((fl & SCSI_LOW_MSGOUT_INIT) != 0)
3502 {
3503 ti->ti_omsgflags = 0;
3504 ti->ti_emsgflags = 0;
3505 }
3506 else if (slp->sl_atten == 0)
3507 {
3508 /* STEP II.
3509 * We did not assert attention, however still our target required
3510 * msgs. Resend previous msgs.
3511 */
3512 ti->ti_msgflags |= ti->ti_omsgflags;
3513 ti->ti_omsgflags = 0;
3514#ifdef SCSI_LOW_DIAGNOSTIC
3515 printf("%s: scsi_low_msgout: retry msgout\n", slp->sl_xname);
3516#endif /* SCSI_LOW_DIAGNOSTIC */
3517 }
3518
3519 /* STEP III.
3520 * We have no msgs. send MSG_NOOP (OK?)
3521 */
3522 if (scsi_low_is_msgout_continue(ti, 0) == 0)
3523 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_NOOP, 0);
3524
3525 /* STEP IV.
3526 * Process all msgs
3527 */
3528 ti->ti_msgoutlen = 0;
3529 slp->sl_clear_atten = 0;
3530 mdp = &scsi_low_msgout_data[0];
3531 for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++)
3532 {
3533 if ((ti->ti_msgflags & mdp->md_flags) != 0)
3534 {
3535 ti->ti_omsgflags |= mdp->md_flags;
3536 ti->ti_msgflags &= ~mdp->md_flags;
3537 ti->ti_emsgflags = mdp->md_flags;
3538
3539 ti->ti_msgoutstr[ti->ti_msgoutlen] = mdp->md_msg;
3540 if (mdp->md_msgfunc != NULL)
3541 len = (*mdp->md_msgfunc) (slp);
3542 else
3543 len = 1;
3544
3545#ifdef SCSI_LOW_DIAGNOSTIC
3546 scsi_low_msg_log_write(&ti->ti_log_msgout,
3547 &ti->ti_msgoutstr[ti->ti_msgoutlen], len);
3548#endif /* SCSI_LOW_DIAGNOSTIC */
3549
3550 ti->ti_msgoutlen += len;
3551 if ((mdp->md_condition & MSG_RELEASE_ATN) != 0)
3552 {
3553 slp->sl_clear_atten = 1;
3554 break;
3555 }
3556
3557 if ((fl & SCSI_LOW_MSGOUT_UNIFY) == 0 ||
3558 ti->ti_msgflags == 0)
3559 break;
3560
3561 if (ti->ti_msgoutlen >= SCSI_LOW_MAX_MSGLEN - 5)
3562 break;
3563 }
3564 }
3565
3566 if (scsi_low_is_msgout_continue(ti, 0) == 0)
3567 slp->sl_clear_atten = 1;
3568
3569 return ti->ti_msgoutlen;
3570}
3571
3572/**************************************************************
3573 * msgin
3574 **************************************************************/
3575static int
3576scsi_low_msginfunc_noop(slp)
3577 struct scsi_low_softc *slp;
3578{
3579
3580 return 0;
3581}
3582
3583static int
3584scsi_low_msginfunc_rejop(slp)
3585 struct scsi_low_softc *slp;
3586{
3587 struct targ_info *ti = slp->sl_Tnexus;
3588 u_int8_t msg = ti->ti_msgin[0];
3589
3590 printf("%s: MSGIN: msg 0x%x rejected\n", slp->sl_xname, (u_int) msg);
3591 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
3592 return 0;
3593}
3594
3595static int
3596scsi_low_msginfunc_cc(slp)
3597 struct scsi_low_softc *slp;
3598{
3599 struct lun_info *li;
3600
3601 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC);
3602
3603 /* validate status */
3604 if (slp->sl_Qnexus == NULL)
3605 return ENOENT;
3606
3607 slp->sl_Qnexus->ccb_sscp.scp_status = slp->sl_scp.scp_status;
3608 li = slp->sl_Lnexus;
3609 switch (slp->sl_scp.scp_status)
3610 {
3611 case ST_GOOD:
3612 li->li_maxnqio = li->li_maxnexus;
3613 break;
3614
3615 case ST_CHKCOND:
3616 li->li_maxnqio = 0;
3617 if (li->li_qflags & SCSI_LOW_QFLAG_CA_QCLEAR)
3618 scsi_low_reset_nexus_lun(slp, li, 0);
3619 break;
3620
3621 case ST_BUSY:
3622 li->li_maxnqio = 0;
3623 break;
3624
3625 case ST_QUEFULL:
3626 if (li->li_maxnexus >= li->li_nqio)
3627 li->li_maxnexus = li->li_nqio - 1;
3628 li->li_maxnqio = li->li_maxnexus;
3629 break;
3630
3631 case ST_INTERGOOD:
3632 case ST_INTERMET:
3633 slp->sl_error |= MSGERR;
3634 break;
3635
3636 default:
3637 break;
3638 }
3639 return 0;
3640}
3641
3642static int
3643scsi_low_msginfunc_lcc(slp)
3644 struct scsi_low_softc *slp;
3645{
3646 struct targ_info *ti;
3647 struct lun_info *li;
3648 struct slccb *ncb, *cb;
3649
3650 ti = slp->sl_Tnexus;
3651 li = slp->sl_Lnexus;
3652 if ((cb = slp->sl_Qnexus) == NULL)
3653 goto bad;
3654
3655 cb->ccb_sscp.scp_status = slp->sl_scp.scp_status;
3656 switch (slp->sl_scp.scp_status)
3657 {
3658 case ST_INTERGOOD:
3659 case ST_INTERMET:
3660 li->li_maxnqio = li->li_maxnexus;
3661 break;
3662
3663 default:
3664 slp->sl_error |= MSGERR;
3665 break;
3666 }
3667
3668 if ((li->li_flags & SCSI_LOW_LINK) == 0)
3669 goto bad;
3670
3671 cb->ccb_error |= slp->sl_error;
3672 if (cb->ccb_error != 0)
3673 goto bad;
3674
3675 for (ncb = TAILQ_FIRST(&slp->sl_start); ncb != NULL;
3676 ncb = TAILQ_NEXT(ncb, ccb_chain))
3677 {
3678 if (ncb->li == li)
3679 goto cmd_link_start;
3680 }
3681
3682
3683bad:
3684 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_LCTERM);
3685 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
3686 return EIO;
3687
3688cmd_link_start:
3689 ncb->ccb_flags &= ~CCB_STARTQ;
3690 TAILQ_REMOVE(&slp->sl_start, ncb, ccb_chain);
3691
3692 scsi_low_dealloc_qtag(ncb);
3693 ncb->ccb_tag = cb->ccb_tag;
3694 ncb->ccb_otag = cb->ccb_otag;
3695 cb->ccb_tag = SCSI_LOW_UNKTAG;
3696 cb->ccb_otag = SCSI_LOW_UNKTAG;
3697 if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY)
3698 panic("%s: linked ccb retried", slp->sl_xname);
3699
3700 slp->sl_Qnexus = ncb;
3701 slp->sl_ph_count = 0;
3702
3703 ncb->ccb_error = 0;
3704 ncb->ccb_datalen = -1;
3705 ncb->ccb_scp.scp_status = ST_UNKNOWN;
3706 ncb->ccb_flags &= ~CCB_INTERNAL;
3707
3708 scsi_low_init_msgsys(slp, ti);
3709
3710 (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, ncb);
3711
3712 if (ncb->ccb_tcmax < SCSI_LOW_MIN_TOUT)
3713 ncb->ccb_tcmax = SCSI_LOW_MIN_TOUT;
3714 ncb->ccb_tc = ncb->ccb_tcmax;
3715
3716 /* setup saved scsi data pointer */
3717 ncb->ccb_sscp = ncb->ccb_scp;
3718 slp->sl_scp = ncb->ccb_sscp;
3719 slp->sl_error = ncb->ccb_error;
3720
3721#ifdef SCSI_LOW_DIAGNOSTIC
3722 scsi_low_msg_log_init(&ti->ti_log_msgin);
3723 scsi_low_msg_log_init(&ti->ti_log_msgout);
3724#endif /* SCSI_LOW_DIAGNOSTIC */
3725 return EJUSTRETURN;
3726}
3727
3728static int
3729scsi_low_msginfunc_disc(slp)
3730 struct scsi_low_softc *slp;
3731{
3732
3733 SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC);
3734 return 0;
3735}
3736
3737static int
3738scsi_low_msginfunc_sdp(slp)
3739 struct scsi_low_softc *slp;
3740{
3741 struct slccb *cb = slp->sl_Qnexus;
3742
3743 if (cb != NULL)
3744 {
3745 cb->ccb_sscp.scp_datalen = slp->sl_scp.scp_datalen;
3746 cb->ccb_sscp.scp_data = slp->sl_scp.scp_data;
3747 }
3748 else
3749 scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0);
3750 return 0;
3751}
3752
3753static int
3754scsi_low_msginfunc_rp(slp)
3755 struct scsi_low_softc *slp;
3756{
3757
3758 if (slp->sl_Qnexus != NULL)
3759 slp->sl_scp = slp->sl_Qnexus->ccb_sscp;
3760 else
3761 scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0);
3762 return 0;
3763}
3764
3765static int
3766scsi_low_synch(slp)
3767 struct scsi_low_softc *slp;
3768{
3769 struct targ_info *ti = slp->sl_Tnexus;
3770 u_int period = 0, offset = 0, speed;
3771 u_char *s;
3772 int error;
3773
3774 if ((MSGIN_PERIOD(ti) >= ti->ti_maxsynch.period &&
3775 MSGIN_OFFSET(ti) <= ti->ti_maxsynch.offset) ||
3776 MSGIN_OFFSET(ti) == 0)
3777 {
3778 if ((offset = MSGIN_OFFSET(ti)) != 0)
3779 period = MSGIN_PERIOD(ti);
3780 s = offset ? "synchronous" : "async";
3781 }
3782 else
3783 {
3784 /* XXX:
3785 * Target seems to be brain damaged.
3786 * Force async transfer.
3787 */
3788 ti->ti_maxsynch.period = 0;
3789 ti->ti_maxsynch.offset = 0;
3790 printf("%s: target brain damaged. async transfer\n",
3791 slp->sl_xname);
3792 return EINVAL;
3793 }
3794
3795 ti->ti_maxsynch.period = period;
3796 ti->ti_maxsynch.offset = offset;
3797
3798 error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_SYNCH);
3799 if (error != 0)
3800 {
3801 /* XXX:
3802 * Current period and offset are not acceptable
3803 * for our adapter.
3804 * The adapter changes max synch and max offset.
3805 */
3806 printf("%s: synch neg failed. retry synch msg neg ...\n",
3807 slp->sl_xname);
3808 return error;
3809 }
3810
3811 ti->ti_osynch = ti->ti_maxsynch;
3812 if (offset > 0)
3813 {
3814 ti->ti_setup_msg_done |= SCSI_LOW_MSG_SYNCH;
3815 }
3816
3817 /* inform data */
3818 if ((slp->sl_show_result & SHOW_SYNCH_NEG) != 0)
3819 {
3820#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE
3821 struct slccb *cb = slp->sl_Qnexus;
3822
3823 if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0)
3824 return 0;
3825#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */
3826
3827 printf("%s(%d:*): <%s> offset %d period %dns ",
3828 slp->sl_xname, ti->ti_id, s, offset, period * 4);
3829
3830 if (period != 0)
3831 {
3832 speed = 1000 * 10 / (period * 4);
3833 printf("%d.%d M/s", speed / 10, speed % 10);
3834 }
3835 printf("\n");
3836 }
3837 return 0;
3838}
3839
3840static int
3841scsi_low_wide(slp)
3842 struct scsi_low_softc *slp;
3843{
3844 struct targ_info *ti = slp->sl_Tnexus;
3845 int error;
3846
3847 ti->ti_width = MSGIN_WIDTHP(ti);
3848 error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_WIDE);
3849 if (error != 0)
3850 {
3851 /* XXX:
3852 * Current width is not acceptable for our adapter.
3853 * The adapter changes max width.
3854 */
3855 printf("%s: wide neg failed. retry wide msg neg ...\n",
3856 slp->sl_xname);
3857 return error;
3858 }
3859
3860 ti->ti_owidth = ti->ti_width;
3861 if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8)
3862 {
3863 ti->ti_setup_msg_done |=
3864 (SCSI_LOW_MSG_SYNCH | SCSI_LOW_MSG_WIDE);
3865 }
3866
3867 /* inform data */
3868 if ((slp->sl_show_result & SHOW_WIDE_NEG) != 0)
3869 {
3870#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE
3871 struct slccb *cb = slp->sl_Qnexus;
3872
3873 if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0)
3874 return 0;
3875#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */
3876
3877 printf("%s(%d:*): transfer width %d bits\n",
3878 slp->sl_xname, ti->ti_id, 1 << (3 + ti->ti_width));
3879 }
3880 return 0;
3881}
3882
3883static int
3884scsi_low_msginfunc_simple_qtag(slp)
3885 struct scsi_low_softc *slp;
3886{
3887 struct targ_info *ti = slp->sl_Tnexus;
3888 scsi_low_tag_t etag = (scsi_low_tag_t) ti->ti_msgin[1];
3889
3890 if (slp->sl_Qnexus != NULL)
3891 {
3892 if (slp->sl_Qnexus->ccb_tag != etag)
3893 {
3894 slp->sl_error |= FATALIO;
3895 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
3896 SCSI_LOW_INFO(slp, ti, "MSGIN: qtag mismatch");
3897 }
3898 }
3899 else if (scsi_low_establish_ccb(ti, slp->sl_Lnexus, etag) == NULL)
3900 {
3901#ifdef SCSI_LOW_DEBUG
3902 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id))
3903 return 0;
3904#endif /* SCSI_LOW_DEBUG */
3905
3906 slp->sl_error |= FATALIO;
3907 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT_QTAG, 0);
3908 SCSI_LOW_INFO(slp, ti, "MSGIN: taged ccb not found");
3909 }
3910 return 0;
3911}
3912
3913static int
3914scsi_low_msginfunc_i_wide_residue(slp)
3915 struct scsi_low_softc *slp;
3916{
3917 struct targ_info *ti = slp->sl_Tnexus;
3918 struct slccb *cb = slp->sl_Qnexus;
3919 int res = (int) ti->ti_msgin[1];
3920
3921 if (cb == NULL || res <= 0 ||
3922 (ti->ti_width == SCSI_LOW_BUS_WIDTH_16 && res > 1) ||
3923 (ti->ti_width == SCSI_LOW_BUS_WIDTH_32 && res > 3))
3924 return EINVAL;
3925
3926 if (slp->sl_scp.scp_datalen + res > cb->ccb_scp.scp_datalen)
3927 return EINVAL;
3928
3929 slp->sl_scp.scp_datalen += res;
3930 slp->sl_scp.scp_data -= res;
3931 scsi_low_data_finish(slp);
3932 return 0;
3933}
3934
3935static int
3936scsi_low_msginfunc_ext(slp)
3937 struct scsi_low_softc *slp;
3938{
3939 struct slccb *cb = slp->sl_Qnexus;
3940 struct lun_info *li = slp->sl_Lnexus;
3941 struct targ_info *ti = slp->sl_Tnexus;
3942 int count, retry;
3943 u_int32_t *ptr;
3944
3945 if (ti->ti_msginptr == 2)
3946 {
3947 ti->ti_msginlen = ti->ti_msgin[1] + 2;
3948 return 0;
3949 }
3950
3951 switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2]))
3952 {
3953 case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE):
3954 if (cb == NULL)
3955 break;
3956
3957 ptr = (u_int32_t *)(&ti->ti_msgin[3]);
3958 count = (int) htonl((long) (*ptr));
3959 if(slp->sl_scp.scp_datalen - count < 0 ||
3960 slp->sl_scp.scp_datalen - count > cb->ccb_scp.scp_datalen)
3961 break;
3962
3963 slp->sl_scp.scp_datalen -= count;
3964 slp->sl_scp.scp_data += count;
3965 return 0;
3966
3967 case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE):
3968 if (li == NULL)
3969 break;
3970
3971 retry = scsi_low_synch(slp);
3972 if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_SYNCH) == 0)
3973 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0);
3974
3975#ifdef SCSI_LOW_DEBUG
3976 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id))
3977 {
3978 scsi_low_test_atten(slp, ti, SCSI_LOW_MSG_SYNCH);
3979 }
3980#endif /* SCSI_LOW_DEBUG */
3981 return 0;
3982
3983 case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE):
3984 if (li == NULL)
3985 break;
3986
3987 retry = scsi_low_wide(slp);
3988 if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_WIDE) == 0)
3989 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0);
3990
3991 return 0;
3992
3993 default:
3994 break;
3995 }
3996
3997 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
3998 return EINVAL;
3999}
4000
4001static int
4002scsi_low_msginfunc_parity(slp)
4003 struct scsi_low_softc *slp;
4004{
4005 struct targ_info *ti = slp->sl_Tnexus;
4006
4007 /* only I -> T, invalid! */
4008 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
4009 return 0;
4010}
4011
4012static int
4013scsi_low_msginfunc_msg_reject(slp)
4014 struct scsi_low_softc *slp;
4015{
4016 struct targ_info *ti = slp->sl_Tnexus;
4017 struct scsi_low_msgout_data *mdp;
4018 u_int msgflags;
4019
4020 if (ti->ti_emsgflags != 0)
4021 {
4022 printf("%s: msg flags [0x%x] rejected\n",
4023 slp->sl_xname, ti->ti_emsgflags);
4024 msgflags = SCSI_LOW_MSG_REJECT;
4025 mdp = &scsi_low_msgout_data[0];
4026 for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++)
4027 {
4028 if ((ti->ti_emsgflags & mdp->md_flags) != 0)
4029 {
4030 ti->ti_emsgflags &= ~mdp->md_flags;
4031 if (mdp->md_errfunc != NULL)
4032 (*mdp->md_errfunc) (slp, msgflags);
4033 break;
4034 }
4035 }
4036 return 0;
4037 }
4038 else
4039 {
4040 SCSI_LOW_INFO(slp, ti, "MSGIN: rejected msg not found");
4041 slp->sl_error |= MSGERR;
4042 }
4043 return EINVAL;
4044}
4045
4046int
4047scsi_low_msgin(slp, ti, c)
4048 struct scsi_low_softc *slp;
4049 struct targ_info *ti;
4050 u_int c;
4051{
4052 struct scsi_low_msgin_data *sdp;
4053 struct lun_info *li;
4054 u_int8_t msg;
4055
4056#ifdef SCSI_LOW_DIAGNOSTIC
4057 if (ti != slp->sl_Tnexus)
4058 {
4059 scsi_low_print(slp, NULL);
4060 panic("scsi_low_msgin: Target nexus inconsistent");
4061 }
4062#endif /* SCSI_LOW_DIAGNOSTIC */
4063
4064 /*
4065 * Phase changes, clear the pointer.
4066 */
4067 if (ti->ti_ophase != ti->ti_phase)
4068 {
4069 MSGINPTR_CLR(ti);
4070 ti->ti_msgin_parity_error = 0;
4071
4072 slp->sl_ph_count ++;
4073 if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES)
4074 {
4075 printf("%s: too many phase changes\n", slp->sl_xname);
4076 slp->sl_error |= FATALIO;
4077 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
4078 }
4079 }
4080
4081 /*
4082 * Store a current messages byte into buffer and
4083 * wait for the completion of the current msg.
4084 */
4085 ti->ti_msgin[ti->ti_msginptr ++] = (u_int8_t) c;
4086 if (ti->ti_msginptr >= SCSI_LOW_MAX_MSGLEN)
4087 {
4088 ti->ti_msginptr = SCSI_LOW_MAX_MSGLEN - 1;
4089 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0);
4090 }
4091
4092 /*
4093 * Check parity errors.
4094 */
4095 if ((c & SCSI_LOW_DATA_PE) != 0)
4096 {
4097 ti->ti_msgin_parity_error ++;
4098 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0);
4099 goto out;
4100 }
4101
4102 if (ti->ti_msgin_parity_error != 0)
4103 goto out;
4104
4105 /*
4106 * Calculate messages length.
4107 */
4108 msg = ti->ti_msgin[0];
4109 if (msg < MSGIN_DATA_LAST)
4110 sdp = &scsi_low_msgin_data[msg];
4111 else
4112 sdp = &scsi_low_msgin_data[MSGIN_DATA_LAST];
4113
4114 if (ti->ti_msginlen == 0)
4115 {
4116 ti->ti_msginlen = sdp->md_len;
4117 }
4118
4119 /*
4120 * Check comletion.
4121 */
4122 if (ti->ti_msginptr < ti->ti_msginlen)
4123 return EJUSTRETURN;
4124
4125 /*
4126 * Do process.
4127 */
4128 if ((msg & MSG_IDENTIFY) == 0)
4129 {
4130 if (((*sdp->md_msgfunc) (slp)) == EJUSTRETURN)
4131 return EJUSTRETURN;
4132 }
4133 else
4134 {
4135 li = slp->sl_Lnexus;
4136 if (li == NULL)
4137 {
4138 li = scsi_low_alloc_li(ti, MSGCMD_LUN(msg), 0);
4139 if (li == NULL)
4140 goto badlun;
4141 slp->sl_Lnexus = li;
4142 (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp);
4143 }
4144 else
4145 {
4146 if (MSGCMD_LUN(msg) != li->li_lun)
4147 goto badlun;
4148 }
4149
4150 if (slp->sl_Qnexus == NULL && li->li_nqio == 0)
4151 {
4152 if (!scsi_low_establish_ccb(ti, li, SCSI_LOW_UNKTAG))
4153 {
4154#ifdef SCSI_LOW_DEBUG
4155 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0)
4156 {
4157 goto out;
4158 }
4159#endif /* SCSI_LOW_DEBUG */
4160 goto badlun;
4161 }
4162 }
4163 }
4164 goto out;
4165
4166 /*
4167 * Msg process completed, reset msgin pointer and assert ATN if desired.
4168 */
4169badlun:
4170 slp->sl_error |= FATALIO;
4171 scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0);
4172 SCSI_LOW_INFO(slp, ti, "MSGIN: identify wrong");
4173
4174out:
4175 if (ti->ti_msginptr < ti->ti_msginlen)
4176 return EJUSTRETURN;
4177
4178#ifdef SCSI_LOW_DIAGNOSTIC
4179 scsi_low_msg_log_write(&ti->ti_log_msgin,
4180 &ti->ti_msgin[0], ti->ti_msginlen);
4181#endif /* SCSI_LOW_DIAGNOSTIC */
4182
4183 MSGINPTR_CLR(ti);
4184 return 0;
4185}
4186
4187/**********************************************************
4188 * disconnect
4189 **********************************************************/
4190int
4191scsi_low_disconnected(slp, ti)
4192 struct scsi_low_softc *slp;
4193 struct targ_info *ti;
4194{
4195 struct slccb *cb = slp->sl_Qnexus;
4196
4197 /* check phase completion */
4198 switch (slp->sl_msgphase)
4199 {
4200 case MSGPH_RESET:
4201 scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD);
4202 scsi_low_msginfunc_cc(slp);
4203 scsi_low_reset_nexus_target(slp, slp->sl_Tnexus, 0);
4204 goto io_resume;
4205
4206 case MSGPH_ABORT:
4207 scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD);
4208 scsi_low_msginfunc_cc(slp);
4209 scsi_low_reset_nexus_lun(slp, slp->sl_Lnexus, 0);
4210 goto io_resume;
4211
4212 case MSGPH_TERM:
4213 scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD);
4214 scsi_low_msginfunc_cc(slp);
4215 goto io_resume;
4216
4217 case MSGPH_DISC:
4218 if (cb != NULL)
4219 {
4220 struct lun_info *li;
4221
4222 li = cb->li;
4223 TAILQ_INSERT_TAIL(&li->li_discq, cb, ccb_chain);
4224 cb->ccb_flags |= CCB_DISCQ;
4225 cb->ccb_error |= slp->sl_error;
4226 li->li_disc ++;
4227 ti->ti_disc ++;
4228 slp->sl_disc ++;
4229 }
4230
4231#ifdef SCSI_LOW_STATICS
4232 scsi_low_statics.nexus_disconnected ++;
4233#endif /* SCSI_LOW_STATICS */
4234
4235#ifdef SCSI_LOW_DEBUG
4236 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DISC, ti->ti_id) != 0)
4237 {
4238 printf("## SCSI_LOW_DISCONNECTED ===============\n");
4239 scsi_low_print(slp, NULL);
4240 }
4241#endif /* SCSI_LOW_DEBUG */
4242 break;
4243
4244 case MSGPH_NULL:
4245 slp->sl_error |= FATALIO;
4246 if (ti->ti_phase == PH_SELSTART)
4247 slp->sl_error |= SELTIMEOUTIO;
4248 else
4249 slp->sl_error |= UBFERR;
4250 /* fall through */
4251
4252 case MSGPH_LCTERM:
4253 case MSGPH_CMDC:
4254io_resume:
4255 if (cb == NULL)
4256 break;
4257
4258#ifdef SCSI_LOW_DEBUG
4259 if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id))
4260 {
4261 if (cb->ccb_omsgoutflag == SCSI_LOW_MSG_NOOP &&
4262 (cb->ccb_msgoutflag != 0 ||
4263 (ti->ti_msgflags & SCSI_LOW_MSG_NOOP)))
4264 {
4265 scsi_low_info(slp, ti, "ATTEN CHECK FAILED");
4266 }
4267 }
4268#endif /* SCSI_LOW_DEBUG */
4269
4270 cb->ccb_error |= slp->sl_error;
4271 if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY)
4272 {
4273 cb->ccb_flags |= CCB_STARTQ;
4274 TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain);
4275 }
4276 break;
4277 }
4278
4279 scsi_low_bus_release(slp, ti);
4280 scsi_low_start(slp);
4281 return 1;
4282}
4283
4284/**********************************************************
4285 * TAG operations
4286 **********************************************************/
4287static int
4288scsi_low_alloc_qtag(cb)
4289 struct slccb *cb;
4290{
4291 struct lun_info *li = cb->li;
4292 scsi_low_tag_t etag;
4293
4294 if (cb->ccb_otag != SCSI_LOW_UNKTAG)
4295 return 0;
4296
4297#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE
4298 etag = ffs(li->li_qtagbits);
4299 if (etag == 0)
4300 return ENOSPC;
4301
4302 li->li_qtagbits &= ~(1 << (etag - 1));
4303 cb->ccb_otag = etag;
4304 return 0;
4305
4306#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */
4307 for (etag = li->li_qd ; li->li_qd < SCSI_LOW_MAXNEXUS; li->li_qd ++)
4308 if (li->li_qtagarray[li->li_qd] == 0)
4309 goto found;
4310
4311 for (li->li_qd = 0; li->li_qd < etag; li->li_qd ++)
4312 if (li->li_qtagarray[li->li_qd] == 0)
4313 goto found;
4314
4315 return ENOSPC;
4316
4317found:
4318 li->li_qtagarray[li->li_qd] ++;
4319 cb->ccb_otag = (li->li_qd ++);
4320 return 0;
4321#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */
4322}
4323
4324static int
4325scsi_low_dealloc_qtag(cb)
4326 struct slccb *cb;
4327{
4328 struct lun_info *li = cb->li;
4329 scsi_low_tag_t etag;
4330
4331 if (cb->ccb_otag == SCSI_LOW_UNKTAG)
4332 return 0;
4333
4334#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE
4335 etag = cb->ccb_otag - 1;
4336#ifdef SCSI_LOW_DIAGNOSTIC
4337 if (etag >= sizeof(li->li_qtagbits) * NBBY)
4338 panic("scsi_low_dealloc_tag: illegal tag");
4339#endif /* SCSI_LOW_DIAGNOSTIC */
4340 li->li_qtagbits |= (1 << etag);
4341
4342#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */
4343 etag = cb->ccb_otag;
4344#ifdef SCSI_LOW_DIAGNOSTIC
4345 if (etag >= SCSI_LOW_MAXNEXUS)
4346 panic("scsi_low_dealloc_tag: illegal tag");
4347#endif /* SCSI_LOW_DIAGNOSTIC */
4348 li->li_qtagarray[etag] --;
4349#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */
4350
4351 cb->ccb_otag = SCSI_LOW_UNKTAG;
4352 return 0;
4353}
4354
4355static struct slccb *
4356scsi_low_revoke_ccb(slp, cb, fdone)
4357 struct scsi_low_softc *slp;
4358 struct slccb *cb;
4359 int fdone;
4360{
4361 struct targ_info *ti = cb->ti;
4362 struct lun_info *li = cb->li;
4363
4364#ifdef SCSI_LOW_DIAGNOSTIC
4365 if ((cb->ccb_flags & (CCB_STARTQ | CCB_DISCQ)) ==
4366 (CCB_STARTQ | CCB_DISCQ))
4367 {
4368 panic("%s: ccb in both queue", slp->sl_xname);
4369 }
4370#endif /* SCSI_LOW_DIAGNOSTIC */
4371
4372 if ((cb->ccb_flags & CCB_STARTQ) != 0)
4373 {
4374 TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain);
4375 }
4376
4377 if ((cb->ccb_flags & CCB_DISCQ) != 0)
4378 {
4379 TAILQ_REMOVE(&li->li_discq, cb, ccb_chain);
4380 li->li_disc --;
4381 ti->ti_disc --;
4382 slp->sl_disc --;
4383 }
4384
4385 cb->ccb_flags &= ~(CCB_STARTQ | CCB_DISCQ |
4386 CCB_SENSE | CCB_CLEARQ | CCB_INTERNAL);
4387
4388 if (fdone != 0 &&
4389 (cb->ccb_rcnt ++ >= slp->sl_max_retry ||
4390 (cb->ccb_flags & CCB_NORETRY) != 0))
4391 {
4392 cb->ccb_error |= FATALIO;
4393 cb->ccb_flags &= ~CCB_AUTOSENSE;
4394 if (scsi_low_done(slp, cb) != SCSI_LOW_DONE_COMPLETE)
4395 panic("%s: done ccb retried", slp->sl_xname);
4396 return NULL;
4397 }
4398 else
4399 {
4400 cb->ccb_error |= PENDINGIO;
4401 scsi_low_deactivate_qtag(cb);
4402 scsi_low_ccb_message_retry(cb);
4403 cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT;
4404 return cb;
4405 }
4406}
4407
4408static void
4409scsi_low_reset_nexus_lun(slp, li, fdone)
4410 struct scsi_low_softc *slp;
4411 struct lun_info *li;
4412 int fdone;
4413{
4414 struct slccb *cb, *ncb, *ecb;
4415
4416 if (li == NULL)
4417 return;
4418
4419 ecb = NULL;
4420 for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; cb = ncb)
4421 {
4422 ncb = TAILQ_NEXT(cb, ccb_chain);
4423 cb = scsi_low_revoke_ccb(slp, cb, fdone);
4424 if (cb != NULL)
4425 {
4426 /*
4427 * presumely keep ordering of io
4428 */
4429 cb->ccb_flags |= CCB_STARTQ;
4430 if (ecb == NULL)
4431 {
4432 TAILQ_INSERT_HEAD(&slp->sl_start,\
4433 cb, ccb_chain);
4434 }
4435 else
4436 {
4437 TAILQ_INSERT_AFTER(&slp->sl_start,\
4438 ecb, cb, ccb_chain);
4439 }
4440 ecb = cb;
4441 }
4442 }
4443}
4444
4445/**************************************************************
4446 * Qurik setup
4447 **************************************************************/
4448static void
4449scsi_low_calcf_lun(li)
4450 struct lun_info *li;
4451{
4452 struct targ_info *ti = li->li_ti;
4453 struct scsi_low_softc *slp = ti->ti_sc;
4454 u_int cfgflags, diskflags;
4455
4456 if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID)
4457 cfgflags = li->li_cfgflags;
4458 else
4459 cfgflags = 0;
4460
4461 diskflags = li->li_diskflags & li->li_quirks;
4462
4463 /* disconnect */
4464 li->li_flags &= ~SCSI_LOW_DISC;
4465 if ((slp->sl_cfgflags & CFG_NODISC) == 0 &&
4466 (diskflags & SCSI_LOW_DISK_DISC) != 0 &&
4467 (cfgflags & SCSI_LOW_DISC) != 0)
4468 li->li_flags |= SCSI_LOW_DISC;
4469
4470 /* parity */
4471 li->li_flags |= SCSI_LOW_NOPARITY;
4472 if ((slp->sl_cfgflags & CFG_NOPARITY) == 0 &&
4473 (diskflags & SCSI_LOW_DISK_PARITY) != 0 &&
4474 (cfgflags & SCSI_LOW_NOPARITY) == 0)
4475 li->li_flags &= ~SCSI_LOW_NOPARITY;
4476
4477 /* qtag */
4478 if ((slp->sl_cfgflags & CFG_NOQTAG) == 0 &&
4479 (cfgflags & SCSI_LOW_QTAG) != 0 &&
4480 (diskflags & SCSI_LOW_DISK_QTAG) != 0)
4481 {
4482 li->li_flags |= SCSI_LOW_QTAG;
4483 li->li_maxnexus = SCSI_LOW_MAXNEXUS;
4484 li->li_maxnqio = li->li_maxnexus;
4485 }
4486 else
4487 {
4488 li->li_flags &= ~SCSI_LOW_QTAG;
4489 li->li_maxnexus = 0;
4490 li->li_maxnqio = li->li_maxnexus;
4491 }
4492
4493 /* cmd link */
4494 li->li_flags &= ~SCSI_LOW_LINK;
4495 if ((cfgflags & SCSI_LOW_LINK) != 0 &&
4496 (diskflags & SCSI_LOW_DISK_LINK) != 0)
4497 li->li_flags |= SCSI_LOW_LINK;
4498
4499 /* compatible flags */
4500 li->li_flags &= ~SCSI_LOW_SYNC;
4501 if (ti->ti_maxsynch.offset > 0)
4502 li->li_flags |= SCSI_LOW_SYNC;
4503
4504#ifdef SCSI_LOW_DEBUG
4505 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0)
4506 {
4507 scsi_low_calcf_show(li);
4508 }
4509#endif /* SCSI_LOW_DEBUG */
4510}
4511
4512static void
4513scsi_low_calcf_target(ti)
4514 struct targ_info *ti;
4515{
4516 struct scsi_low_softc *slp = ti->ti_sc;
4517 u_int offset, period, diskflags;
4518
4519 diskflags = ti->ti_diskflags & ti->ti_quirks;
4520
4521 /* synch */
4522 if ((slp->sl_cfgflags & CFG_ASYNC) == 0 &&
4523 (diskflags & SCSI_LOW_DISK_SYNC) != 0)
4524 {
4525 offset = ti->ti_maxsynch.offset;
4526 period = ti->ti_maxsynch.period;
4527 if (offset == 0 || period == 0)
4528 offset = period = 0;
4529 }
4530 else
4531 {
4532 offset = period = 0;
4533 }
4534
4535 ti->ti_maxsynch.offset = offset;
4536 ti->ti_maxsynch.period = period;
4537
4538 /* wide */
4539 if ((diskflags & SCSI_LOW_DISK_WIDE_32) == 0 &&
4540 ti->ti_width > SCSI_LOW_BUS_WIDTH_16)
4541 ti->ti_width = SCSI_LOW_BUS_WIDTH_16;
4542
4543 if ((diskflags & SCSI_LOW_DISK_WIDE_16) == 0 &&
4544 ti->ti_width > SCSI_LOW_BUS_WIDTH_8)
4545 ti->ti_width = SCSI_LOW_BUS_WIDTH_8;
4546
4547 if (ti->ti_flags_valid == SCSI_LOW_TARG_FLAGS_ALL_VALID)
4548 {
4549 if (ti->ti_maxsynch.offset != ti->ti_osynch.offset ||
4550 ti->ti_maxsynch.period != ti->ti_osynch.period)
4551 ti->ti_setup_msg |= SCSI_LOW_MSG_SYNCH;
4552 if (ti->ti_width != ti->ti_owidth)
4553 ti->ti_setup_msg |= (SCSI_LOW_MSG_WIDE | SCSI_LOW_MSG_SYNCH);
4554
4555 ti->ti_osynch = ti->ti_maxsynch;
4556 ti->ti_owidth = ti->ti_width;
4557 }
4558
4559#ifdef SCSI_LOW_DEBUG
4560 if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0)
4561 {
4562 printf("%s(%d:*): max period(%dns) offset(%d) width(%d)\n",
4563 slp->sl_xname, ti->ti_id,
4564 ti->ti_maxsynch.period * 4,
4565 ti->ti_maxsynch.offset,
4566 ti->ti_width);
4567 }
4568#endif /* SCSI_LOW_DEBUG */
4569}
4570
4571static void
4572scsi_low_calcf_show(li)
4573 struct lun_info *li;
4574{
4575 struct targ_info *ti = li->li_ti;
4576 struct scsi_low_softc *slp = ti->ti_sc;
4577
4578 printf("%s(%d:%d): period(%d ns) offset(%d) width(%d) flags 0x%b\n",
4579 slp->sl_xname, ti->ti_id, li->li_lun,
4580 ti->ti_maxsynch.period * 4,
4581 ti->ti_maxsynch.offset,
4582 ti->ti_width,
4583 li->li_flags, SCSI_LOW_BITS);
4584}
4585
4586#ifdef SCSI_LOW_START_UP_CHECK
4587/**************************************************************
4588 * scsi world start up
4589 **************************************************************/
4590static int scsi_low_poll(struct scsi_low_softc *, struct slccb *);
4591
4592static int
4593scsi_low_start_up(slp)
4594 struct scsi_low_softc *slp;
4595{
4596 struct targ_info *ti;
4597 struct lun_info *li;
4598 struct slccb *cb;
4599 int target, lun;
4600
4601 printf("%s: scsi_low: probing all devices ....\n", slp->sl_xname);
4602
4603 for (target = 0; target < slp->sl_ntargs; target ++)
4604 {
4605 if (target == slp->sl_hostid)
4606 {
4607 if ((slp->sl_show_result & SHOW_PROBE_RES) != 0)
4608 {
4609 printf("%s: scsi_low: target %d (host card)\n",
4610 slp->sl_xname, target);
4611 }
4612 continue;
4613 }
4614
4615 if ((slp->sl_show_result & SHOW_PROBE_RES) != 0)
4616 {
4617 printf("%s: scsi_low: target %d lun ",
4618 slp->sl_xname, target);
4619 }
4620
4621 ti = slp->sl_ti[target];
4622 for (lun = 0; lun < slp->sl_nluns; lun ++)
4623 {
4624 if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)
4625 break;
4626
4627 cb->osdep = NULL;
4628 cb->bp = NULL;
4629
4630 li = scsi_low_alloc_li(ti, lun, 1);
4631
4632 scsi_low_enqueue(slp, ti, li, cb,
4633 CCB_AUTOSENSE | CCB_POLLED, 0);
4634
4635 scsi_low_poll(slp, cb);
4636
4637 if (li->li_state != SCSI_LOW_LUN_OK)
4638 break;
4639
4640 if ((slp->sl_show_result & SHOW_PROBE_RES) != 0)
4641 {
4642 printf("%d ", lun);
4643 }
4644 }
4645
4646 if ((slp->sl_show_result & SHOW_PROBE_RES) != 0)
4647 {
4648 printf("\n");
4649 }
4650 }
4651 return 0;
4652}
4653
4654static int
4655scsi_low_poll(slp, cb)
4656 struct scsi_low_softc *slp;
4657 struct slccb *cb;
4658{
4659 int tcount;
4660
4661 tcount = 0;
4662 while (slp->sl_nio > 0)
4663 {
4664 SCSI_LOW_DELAY((1000 * 1000) / SCSI_LOW_POLL_HZ);
4665
4666 (*slp->sl_funcs->scsi_low_poll) (slp);
4667 if (tcount ++ < SCSI_LOW_POLL_HZ / SCSI_LOW_TIMEOUT_HZ)
4668 continue;
4669
4670 tcount = 0;
4671 scsi_low_timeout_check(slp);
4672 }
4673
4674 return 0;
4675}
4676#endif /* SCSI_LOW_START_UP_CHECK */
4677
4678/**********************************************************
4679 * DEBUG SECTION
4680 **********************************************************/
4681#ifdef SCSI_LOW_DEBUG
4682static void
4683scsi_low_test_abort(slp, ti, li)
4684 struct scsi_low_softc *slp;
4685 struct targ_info *ti;
4686 struct lun_info *li;
4687{
4688 struct slccb *acb;
4689
4690 if (li->li_disc > 1)
4691 {
4692 acb = TAILQ_FIRST(&li->li_discq);
4693 if (scsi_low_abort_ccb(slp, acb) == 0)
4694 {
4695 printf("%s: aborting ccb(0x%lx) start\n",
4696 slp->sl_xname, (u_long) acb);
4697 }
4698 }
4699}
4700
4701static void
4702scsi_low_test_atten(slp, ti, msg)
4703 struct scsi_low_softc *slp;
4704 struct targ_info *ti;
4705 u_int msg;
4706{
4707
4708 if (slp->sl_ph_count < SCSI_LOW_MAX_ATTEN_CHECK)
4709 scsi_low_assert_msg(slp, ti, msg, 0);
4710 else
4711 printf("%s: atten check OK\n", slp->sl_xname);
4712}
4713
4714static void
4715scsi_low_test_cmdlnk(slp, cb)
4716 struct scsi_low_softc *slp;
4717 struct slccb *cb;
4718{
4719#define SCSI_LOW_CMDLNK_NOK (CCB_INTERNAL | CCB_SENSE | CCB_CLEARQ)
4720
4721 if ((cb->ccb_flags & SCSI_LOW_CMDLNK_NOK) != 0)
4722 return;
4723
4724 memcpy(cb->ccb_scsi_cmd, slp->sl_scp.scp_cmd,
4725 slp->sl_scp.scp_cmdlen);
4726 cb->ccb_scsi_cmd[slp->sl_scp.scp_cmdlen - 1] |= 1;
4727 slp->sl_scp.scp_cmd = cb->ccb_scsi_cmd;
4728}
4729#endif /* SCSI_LOW_DEBUG */
4730
4731/* static */ void
4732scsi_low_info(slp, ti, s)
4733 struct scsi_low_softc *slp;
4734 struct targ_info *ti;
4735 u_char *s;
4736{
4737
4738 if (slp == NULL)
4739 slp = LIST_FIRST(&sl_tab);
4740 if (s == NULL)
4741 s = "no message";
4742
4743 printf(">>>>> SCSI_LOW_INFO(0x%lx): %s\n", (u_long) slp->sl_Tnexus, s);
4744 if (ti == NULL)
4745 {
4746 for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL;
4747 ti = TAILQ_NEXT(ti, ti_chain))
4748 {
4749 scsi_low_print(slp, ti);
4750 }
4751 }
4752 else
4753 {
4754 scsi_low_print(slp, ti);
4755 }
4756}
4757
4758static u_char *phase[] =
4759{
4760 "FREE", "ARBSTART", "SELSTART", "SELECTED",
4761 "CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", "RESEL"
4762};
4763
4764void
4765scsi_low_print(slp, ti)
4766 struct scsi_low_softc *slp;
4767 struct targ_info *ti;
4768{
4769 struct lun_info *li;
4770 struct slccb *cb;
4771 struct sc_p *sp;
4772
4773 if (ti == NULL || ti == slp->sl_Tnexus)
4774 {
4775 ti = slp->sl_Tnexus;
4776 li = slp->sl_Lnexus;
4777 cb = slp->sl_Qnexus;
4778 }
4779 else
4780 {
4781 li = LIST_FIRST(&ti->ti_litab);
4782 cb = TAILQ_FIRST(&li->li_discq);
4783 }
4784 sp = &slp->sl_scp;
4785
4786 printf("%s: === NEXUS T(0x%lx) L(0x%lx) Q(0x%lx) NIO(%d) ===\n",
4787 slp->sl_xname, (u_long) ti, (u_long) li, (u_long) cb,
4788 slp->sl_nio);
4789
4790 /* target stat */
4791 if (ti != NULL)
4792 {
4793 u_int flags = 0, maxnqio = 0, nqio = 0;
4794 int lun = -1;
4795
4796 if (li != NULL)
4797 {
4798 lun = li->li_lun;
4799 flags = li->li_flags;
4800 maxnqio = li->li_maxnqio;
4801 nqio = li->li_nqio;
4802 }
4803
4804 printf("%s(%d:%d) ph<%s> => ph<%s> DISC(%d) QIO(%d:%d)\n",
4805 slp->sl_xname,
4806 ti->ti_id, lun, phase[(int) ti->ti_ophase],
4807 phase[(int) ti->ti_phase], ti->ti_disc,
4808 nqio, maxnqio);
4809
4810 if (cb != NULL)
4811 {
4812printf("CCB: cmd[0] 0x%x clen 0x%x dlen 0x%x<0x%x stat 0x%x err %b\n",
4813 (u_int) cb->ccb_scp.scp_cmd[0],
4814 cb->ccb_scp.scp_cmdlen,
4815 cb->ccb_datalen,
4816 cb->ccb_scp.scp_datalen,
4817 (u_int) cb->ccb_sscp.scp_status,
4818 cb->ccb_error, SCSI_LOW_ERRORBITS);
4819 }
4820
4821printf("MSGIN: ptr(%x) [%x][%x][%x][%x][%x] attention: %d\n",
4822 (u_int) (ti->ti_msginptr),
4823 (u_int) (ti->ti_msgin[0]),
4824 (u_int) (ti->ti_msgin[1]),
4825 (u_int) (ti->ti_msgin[2]),
4826 (u_int) (ti->ti_msgin[3]),
4827 (u_int) (ti->ti_msgin[4]),
4828 slp->sl_atten);
4829
4830printf("MSGOUT: msgflags 0x%x [%x][%x][%x][%x][%x] msgoutlen %d C_FLAGS: %b\n",
4831 (u_int) ti->ti_msgflags,
4832 (u_int) (ti->ti_msgoutstr[0]),
4833 (u_int) (ti->ti_msgoutstr[1]),
4834 (u_int) (ti->ti_msgoutstr[2]),
4835 (u_int) (ti->ti_msgoutstr[3]),
4836 (u_int) (ti->ti_msgoutstr[4]),
4837 ti->ti_msgoutlen,
4838 flags, SCSI_LOW_BITS);
4839
4840#ifdef SCSI_LOW_DIAGNOSTIC
4841 scsi_low_msg_log_show(&ti->ti_log_msgin, "MIN LOG ", 2);
4842 scsi_low_msg_log_show(&ti->ti_log_msgout, "MOUT LOG", 2);
4843#endif /* SCSI_LOW_DIAGNOSTIC */
4844
4845 }
4846
4847 printf("SCB: daddr 0x%lx dlen 0x%x stat 0x%x err %b\n",
4848 (u_long) sp->scp_data,
4849 sp->scp_datalen,
4850 (u_int) sp->scp_status,
4851 slp->sl_error, SCSI_LOW_ERRORBITS);
4852}