179697Snon/* $NecBSD: scsi_low.c,v 1.24.10.8 2001/06/26 07:39:44 honda Exp $ */ 267468Snon/* $NetBSD$ */ 367468Snon 4116162Sobrien#include <sys/cdefs.h> 5116162Sobrien__FBSDID("$FreeBSD$"); 6116162Sobrien 767468Snon#define SCSI_LOW_STATICS 879697Snon#define SCSI_LOW_DEBUG 979697Snon#define SCSI_LOW_NEGOTIATE_BEFORE_SENSE 1079697Snon#define SCSI_LOW_START_UP_CHECK 1179697Snon 1279697Snon/* #define SCSI_LOW_INFO_DETAIL */ 13116162Sobrien 1479697Snon/* #define SCSI_LOW_QCLEAR_AFTER_CA */ 1579697Snon/* #define SCSI_LOW_FLAGS_QUIRKS_OK */ 1679697Snon 1767468Snon#ifdef __NetBSD__ 1867468Snon#define SCSI_LOW_TARGET_OPEN 1979697Snon#endif /* __NetBSD__ */ 2067468Snon 2179697Snon#ifdef __FreeBSD__ 2279697Snon#define SCSI_LOW_FLAGS_QUIRKS_OK 2379697Snon#endif /* __FreeBSD__ */ 2479697Snon 25139743Simp/*- 2667468Snon * [NetBSD for NEC PC-98 series] 2779697Snon * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 2867468Snon * NetBSD/pc98 porting staff. All rights reserved. 2979697Snon * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 3067468Snon * Naofumi HONDA. All rights reserved. 3179697Snon * 3279697Snon * [Ported for FreeBSD CAM] 3379697Snon * Copyright (c) 2000, 2001 3479697Snon * MITSUNAGA Noriaki, NOKUBI Hirotaka and TAKAHASHI Yoshihiro. 3579697Snon * All rights reserved. 3667468Snon * 3767468Snon * Redistribution and use in source and binary forms, with or without 3867468Snon * modification, are permitted provided that the following conditions 3967468Snon * are met: 4067468Snon * 1. Redistributions of source code must retain the above copyright 4167468Snon * notice, this list of conditions and the following disclaimer. 4267468Snon * 2. Redistributions in binary form must reproduce the above copyright 4367468Snon * notice, this list of conditions and the following disclaimer in the 4467468Snon * documentation and/or other materials provided with the distribution. 4567468Snon * 3. The name of the author may not be used to endorse or promote products 4667468Snon * derived from this software without specific prior written permission. 4767468Snon * 4867468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4967468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 5067468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 5167468Snon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 5267468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 5367468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 5467468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5567468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 5667468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 5767468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5867468Snon * POSSIBILITY OF SUCH DAMAGE. 5967468Snon */ 6067468Snon 6167468Snon/* <On the nexus establishment> 6267468Snon * When our host is reselected, 6367468Snon * nexus establish processes are little complicated. 6467468Snon * Normal steps are followings: 6579697Snon * 1) Our host selected by target => target nexus (slp->sl_Tnexus) 6679697Snon * 2) Identify msgin => lun nexus (slp->sl_Lnexus) 6779697Snon * 3) Qtag msg => ccb nexus (slp->sl_Qnexus) 6867468Snon */ 6967468Snon#include "opt_ddb.h" 7067468Snon 7167468Snon#include <sys/param.h> 7267468Snon#include <sys/systm.h> 7367468Snon#include <sys/kernel.h> 7479697Snon 7573025Snon#ifdef __FreeBSD__ 7673025Snon#if __FreeBSD_version >= 500001 7767468Snon#include <sys/bio.h> 7879697Snon#else 7979697Snon#include <machine/clock.h> 8073025Snon#endif 8179697Snon#endif /* __FreeBSD__ */ 8279697Snon 8367468Snon#include <sys/buf.h> 8467468Snon#include <sys/queue.h> 8567468Snon#include <sys/malloc.h> 8667468Snon#include <sys/errno.h> 8767468Snon 8879697Snon#ifdef __NetBSD__ 8979697Snon#include <sys/device.h> 9067468Snon#include <vm/vm.h> 9167468Snon 9267468Snon#include <machine/bus.h> 9367468Snon#include <machine/intr.h> 9467468Snon#include <machine/dvcfg.h> 9567468Snon 9667468Snon#include <dev/cons.h> 9767468Snon 9867468Snon#include <dev/scsipi/scsipi_all.h> 9967468Snon#include <dev/scsipi/scsipiconf.h> 10067468Snon#include <dev/scsipi/scsipi_disk.h> 10167468Snon#include <dev/scsipi/scsi_all.h> 10267468Snon#include <dev/scsipi/scsiconf.h> 10379697Snon#include <sys/scsiio.h> 10467468Snon 10567468Snon#include <i386/Cbus/dev/scsi_low.h> 10679697Snon#endif /* __NetBSD__ */ 10779697Snon 10867468Snon#ifdef __FreeBSD__ 10967468Snon#include <cam/cam.h> 11067468Snon#include <cam/cam_ccb.h> 11167468Snon#include <cam/cam_sim.h> 11267468Snon#include <cam/cam_debug.h> 11367468Snon#include <cam/cam_periph.h> 114147723Savatar#include <cam/cam_xpt_periph.h> 11567468Snon 11667468Snon#include <cam/scsi/scsi_all.h> 11773025Snon#include <cam/scsi/scsi_message.h> 11867468Snon 11967468Snon#include <cam/scsi/scsi_low.h> 12067468Snon 12167468Snon#include <sys/cons.h> 12279697Snon#endif /* __FreeBSD__ */ 12367468Snon 12479697Snon/************************************************************** 12579697Snon * Constants 12679697Snon **************************************************************/ 12779697Snon#define SCSI_LOW_POLL_HZ 1000 12867468Snon 12979697Snon/* functions return values */ 13079697Snon#define SCSI_LOW_START_NO_QTAG 0 13179697Snon#define SCSI_LOW_START_QTAG 1 13279697Snon 13367468Snon#define SCSI_LOW_DONE_COMPLETE 0 13467468Snon#define SCSI_LOW_DONE_RETRY 1 13567468Snon 13679697Snon/* internal disk flags */ 13779697Snon#define SCSI_LOW_DISK_DISC 0x00000001 13879697Snon#define SCSI_LOW_DISK_QTAG 0x00000002 13979697Snon#define SCSI_LOW_DISK_LINK 0x00000004 14079697Snon#define SCSI_LOW_DISK_PARITY 0x00000008 14179697Snon#define SCSI_LOW_DISK_SYNC 0x00010000 14279697Snon#define SCSI_LOW_DISK_WIDE_16 0x00020000 14379697Snon#define SCSI_LOW_DISK_WIDE_32 0x00040000 14479697Snon#define SCSI_LOW_DISK_WIDE (SCSI_LOW_DISK_WIDE_16 | SCSI_LOW_DISK_WIDE_32) 14579697Snon#define SCSI_LOW_DISK_LFLAGS 0x0000ffff 14679697Snon#define SCSI_LOW_DISK_TFLAGS 0xffff0000 14779697Snon 148249132Smavstatic MALLOC_DEFINE(M_SCSILOW, "SCSI low", "SCSI low buffers"); 149147723Savatar 15079697Snon/************************************************************** 15179697Snon * Declarations 15279697Snon **************************************************************/ 15392770Salfred/* static */ void scsi_low_info(struct scsi_low_softc *, struct targ_info *, u_char *); 15492770Salfredstatic void scsi_low_engage(void *); 15592770Salfredstatic struct slccb *scsi_low_establish_ccb(struct targ_info *, struct lun_info *, scsi_low_tag_t); 15692770Salfredstatic int scsi_low_done(struct scsi_low_softc *, struct slccb *); 15792770Salfredstatic int scsi_low_setup_done(struct scsi_low_softc *, struct slccb *); 15892770Salfredstatic void scsi_low_bus_release(struct scsi_low_softc *, struct targ_info *); 15992770Salfredstatic void scsi_low_twiddle_wait(void); 16092770Salfredstatic struct lun_info *scsi_low_alloc_li(struct targ_info *, int, int); 16192770Salfredstatic struct targ_info *scsi_low_alloc_ti(struct scsi_low_softc *, int); 16292770Salfredstatic void scsi_low_calcf_lun(struct lun_info *); 16392770Salfredstatic void scsi_low_calcf_target(struct targ_info *); 16492770Salfredstatic void scsi_low_calcf_show(struct lun_info *); 16592770Salfredstatic void scsi_low_reset_nexus(struct scsi_low_softc *, int); 16692770Salfredstatic void scsi_low_reset_nexus_target(struct scsi_low_softc *, struct targ_info *, int); 16792770Salfredstatic void scsi_low_reset_nexus_lun(struct scsi_low_softc *, struct lun_info *, int); 16892770Salfredstatic int scsi_low_init(struct scsi_low_softc *, u_int); 16992770Salfredstatic void scsi_low_start(struct scsi_low_softc *); 17092770Salfredstatic void scsi_low_free_ti(struct scsi_low_softc *); 17167468Snon 17292770Salfredstatic int scsi_low_alloc_qtag(struct slccb *); 17392770Salfredstatic int scsi_low_dealloc_qtag(struct slccb *); 17492770Salfredstatic int scsi_low_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *, u_int, u_int); 17592770Salfredstatic int scsi_low_message_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, u_int); 17692770Salfredstatic void scsi_low_unit_ready_cmd(struct slccb *); 17792770Salfredstatic void scsi_low_timeout(void *); 17892770Salfredstatic int scsi_low_timeout_check(struct scsi_low_softc *); 17979697Snon#ifdef SCSI_LOW_START_UP_CHECK 18092770Salfredstatic int scsi_low_start_up(struct scsi_low_softc *); 18179697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 18292770Salfredstatic int scsi_low_abort_ccb(struct scsi_low_softc *, struct slccb *); 18392770Salfredstatic struct slccb *scsi_low_revoke_ccb(struct scsi_low_softc *, struct slccb *, int); 18479697Snon 18579697Snonint scsi_low_version_major = 2; 18679697Snonint scsi_low_version_minor = 17; 18779697Snon 18879697Snonstatic struct scsi_low_softc_tab sl_tab = LIST_HEAD_INITIALIZER(sl_tab); 18979697Snon 19079697Snon/************************************************************** 19179697Snon * Debug, Run test and Statics 19279697Snon **************************************************************/ 19379697Snon#ifdef SCSI_LOW_INFO_DETAIL 19479697Snon#define SCSI_LOW_INFO(slp, ti, s) scsi_low_info((slp), (ti), (s)) 19579697Snon#else /* !SCSI_LOW_INFO_DETAIL */ 19679697Snon#define SCSI_LOW_INFO(slp, ti, s) printf("%s: %s\n", (slp)->sl_xname, (s)) 19779697Snon#endif /* !SCSI_LOW_INFO_DETAIL */ 19879697Snon 19967468Snon#ifdef SCSI_LOW_STATICS 20089113Smsmithstatic struct scsi_low_statics { 20167468Snon int nexus_win; 20267468Snon int nexus_fail; 20367468Snon int nexus_disconnected; 20467468Snon int nexus_reselected; 20567468Snon int nexus_conflict; 20667468Snon} scsi_low_statics; 20767468Snon#endif /* SCSI_LOW_STATICS */ 20879697Snon 20979697Snon#ifdef SCSI_LOW_DEBUG 21079697Snon#define SCSI_LOW_DEBUG_DONE 0x00001 21179697Snon#define SCSI_LOW_DEBUG_DISC 0x00002 21279697Snon#define SCSI_LOW_DEBUG_SENSE 0x00004 21379697Snon#define SCSI_LOW_DEBUG_CALCF 0x00008 21479697Snon#define SCSI_LOW_DEBUG_ACTION 0x10000 21579697Snonint scsi_low_debug = 0; 21679697Snon 21779697Snon#define SCSI_LOW_MAX_ATTEN_CHECK 32 21879697Snon#define SCSI_LOW_ATTEN_CHECK 0x0001 21979697Snon#define SCSI_LOW_CMDLNK_CHECK 0x0002 22079697Snon#define SCSI_LOW_ABORT_CHECK 0x0004 22179697Snon#define SCSI_LOW_NEXUS_CHECK 0x0008 22279697Snonint scsi_low_test = 0; 22379697Snonint scsi_low_test_id = 0; 22479697Snon 22592770Salfredstatic void scsi_low_test_abort(struct scsi_low_softc *, struct targ_info *, struct lun_info *); 22692770Salfredstatic void scsi_low_test_cmdlnk(struct scsi_low_softc *, struct slccb *); 22792770Salfredstatic void scsi_low_test_atten(struct scsi_low_softc *, struct targ_info *, u_int); 22879697Snon#define SCSI_LOW_DEBUG_TEST_GO(fl, id) \ 22979697Snon ((scsi_low_test & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 23079697Snon#define SCSI_LOW_DEBUG_GO(fl, id) \ 23179697Snon ((scsi_low_debug & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 23279697Snon#endif /* SCSI_LOW_DEBUG */ 23379697Snon 23467468Snon/************************************************************** 23579697Snon * CCB 23679697Snon **************************************************************/ 23779697SnonGENERIC_CCB_STATIC_ALLOC(scsi_low, slccb) 23879697SnonGENERIC_CCB(scsi_low, slccb, ccb_chain) 23979697Snon 24079697Snon/************************************************************** 24179697Snon * Inline functions 24279697Snon **************************************************************/ 24379697Snon#define SCSI_LOW_INLINE static __inline 24492770SalfredSCSI_LOW_INLINE void scsi_low_activate_qtag(struct slccb *); 24592770SalfredSCSI_LOW_INLINE void scsi_low_deactivate_qtag(struct slccb *); 24692770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_assert(struct slccb *, u_int); 24792770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_exec(struct scsi_low_softc *, struct slccb *); 24892770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_retry(struct slccb *); 24992770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_clear(struct slccb *); 25092770SalfredSCSI_LOW_INLINE void scsi_low_init_msgsys(struct scsi_low_softc *, struct targ_info *); 25179697Snon 25279697SnonSCSI_LOW_INLINE void 25379697Snonscsi_low_activate_qtag(cb) 25479697Snon struct slccb *cb; 25579697Snon{ 25679697Snon struct lun_info *li = cb->li; 25779697Snon 25879697Snon if (cb->ccb_tag != SCSI_LOW_UNKTAG) 25979697Snon return; 26079697Snon 26179697Snon li->li_nqio ++; 26279697Snon cb->ccb_tag = cb->ccb_otag; 26379697Snon} 26479697Snon 26579697SnonSCSI_LOW_INLINE void 26679697Snonscsi_low_deactivate_qtag(cb) 26779697Snon struct slccb *cb; 26879697Snon{ 26979697Snon struct lun_info *li = cb->li; 27079697Snon 27179697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 27279697Snon return; 27379697Snon 27479697Snon li->li_nqio --; 27579697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 27679697Snon} 27779697Snon 27879697SnonSCSI_LOW_INLINE void 27979697Snonscsi_low_ccb_message_exec(slp, cb) 28079697Snon struct scsi_low_softc *slp; 28179697Snon struct slccb *cb; 28279697Snon{ 28379697Snon 28479697Snon scsi_low_assert_msg(slp, cb->ti, cb->ccb_msgoutflag, 0); 28579697Snon cb->ccb_msgoutflag = 0; 28679697Snon} 28779697Snon 28879697SnonSCSI_LOW_INLINE void 28979697Snonscsi_low_ccb_message_assert(cb, msg) 29079697Snon struct slccb *cb; 29179697Snon u_int msg; 29279697Snon{ 29379697Snon 29479697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag = msg; 29579697Snon} 29679697Snon 29779697SnonSCSI_LOW_INLINE void 29879697Snonscsi_low_ccb_message_retry(cb) 29979697Snon struct slccb *cb; 30079697Snon{ 30179697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag; 30279697Snon} 30379697Snon 30479697SnonSCSI_LOW_INLINE void 30579697Snonscsi_low_ccb_message_clear(cb) 30679697Snon struct slccb *cb; 30779697Snon{ 30879697Snon cb->ccb_msgoutflag = 0; 30979697Snon} 31079697Snon 31179697SnonSCSI_LOW_INLINE void 31279697Snonscsi_low_init_msgsys(slp, ti) 31379697Snon struct scsi_low_softc *slp; 31479697Snon struct targ_info *ti; 31579697Snon{ 31679697Snon 31779697Snon ti->ti_msginptr = 0; 31879697Snon ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0; 31979697Snon SCSI_LOW_DEASSERT_ATN(slp); 32079697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL); 32179697Snon} 32279697Snon 32379697Snon/*============================================================= 32479697Snon * START OF OS switch (All OS depend fucntions should be here) 32579697Snon =============================================================*/ 32679697Snon/* common os depend utitlities */ 32779697Snon#define SCSI_LOW_CMD_RESIDUAL_CHK 0x0001 32879697Snon#define SCSI_LOW_CMD_ORDERED_QTAG 0x0002 32979697Snon#define SCSI_LOW_CMD_ABORT_WARNING 0x0004 33079697Snon 33179697Snonstatic u_int8_t scsi_low_cmd_flags[256] = { 33279697Snon/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 33379697Snon/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 33479697Snon/*1*/ 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 33579697Snon/*2*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 5, 5, 33679697Snon/*3*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 33779697Snon}; 33879697Snon 33979697Snonstruct scsi_low_error_code { 34079697Snon int error_bits; 34179697Snon int error_code; 34279697Snon}; 34379697Snon 34492770Salfredstatic struct slccb *scsi_low_find_ccb(struct scsi_low_softc *, u_int, u_int, void *); 34592770Salfredstatic int scsi_low_translate_error_code(struct slccb *, struct scsi_low_error_code *); 34679697Snon 34779697Snonstatic struct slccb * 34879697Snonscsi_low_find_ccb(slp, target, lun, osdep) 34979697Snon struct scsi_low_softc *slp; 35079697Snon u_int target, lun; 35179697Snon void *osdep; 35279697Snon{ 35379697Snon struct targ_info *ti; 35479697Snon struct lun_info *li; 35579697Snon struct slccb *cb; 35679697Snon 35779697Snon ti = slp->sl_ti[target]; 35879697Snon li = scsi_low_alloc_li(ti, lun, 0); 35979697Snon if (li == NULL) 36079697Snon return NULL; 36179697Snon 36279697Snon if ((cb = slp->sl_Qnexus) != NULL && cb->osdep == osdep) 36379697Snon return cb; 36479697Snon 36579697Snon for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL; 36679697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 36779697Snon { 36879697Snon if (cb->osdep == osdep) 36979697Snon return cb; 37079697Snon } 37179697Snon 37279697Snon for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; 37379697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 37479697Snon { 37579697Snon if (cb->osdep == osdep) 37679697Snon return cb; 37779697Snon } 37879697Snon return NULL; 37979697Snon} 38079697Snon 38179697Snonstatic int 38279697Snonscsi_low_translate_error_code(cb, tp) 38379697Snon struct slccb *cb; 38479697Snon struct scsi_low_error_code *tp; 38579697Snon{ 38679697Snon 38779697Snon if (cb->ccb_error == 0) 38879697Snon return tp->error_code; 38979697Snon 39079697Snon for (tp ++; (cb->ccb_error & tp->error_bits) == 0; tp ++) 39179697Snon ; 39279697Snon return tp->error_code; 39379697Snon} 39479697Snon 39579697Snon#ifdef SCSI_LOW_INTERFACE_XS 39679697Snon/************************************************************** 39779697Snon * SCSI INTERFACE (XS) 39879697Snon **************************************************************/ 39979697Snon#define SCSI_LOW_MINPHYS 0x10000 400147723Savatar#define SCSI_LOW_MALLOC(size) malloc((size), M_SCSILOW, M_NOWAIT) 401147723Savatar#define SCSI_LOW_FREE(pt) free((pt), M_SCSILOW) 40279697Snon#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb((flags)) 40379697Snon#define SCSI_LOW_XS_POLL_HZ 1000 40479697Snon 40592770Salfredstatic int scsi_low_poll_xs(struct scsi_low_softc *, struct slccb *); 40692770Salfredstatic void scsi_low_scsi_minphys_xs(struct buf *); 40779697Snon#ifdef SCSI_LOW_TARGET_OPEN 40892770Salfredstatic int scsi_low_target_open(struct scsipi_link *, struct cfdata *); 40979697Snon#endif /* SCSI_LOW_TARGET_OPEN */ 41092770Salfredstatic int scsi_low_scsi_cmd_xs(struct scsipi_xfer *); 41192770Salfredstatic int scsi_low_enable_xs(void *, int); 41292770Salfredstatic int scsi_low_ioctl_xs(struct scsipi_link *, u_long, caddr_t, int, struct proc *); 41379697Snon 41492770Salfredstatic int scsi_low_attach_xs(struct scsi_low_softc *); 41592770Salfredstatic int scsi_low_world_start_xs(struct scsi_low_softc *); 41692770Salfredstatic int scsi_low_dettach_xs(struct scsi_low_softc *); 41792770Salfredstatic int scsi_low_ccb_setup_xs(struct scsi_low_softc *, struct slccb *); 41892770Salfredstatic int scsi_low_done_xs(struct scsi_low_softc *, struct slccb *); 41992770Salfredstatic void scsi_low_timeout_xs(struct scsi_low_softc *, int, int); 42092770Salfredstatic u_int scsi_low_translate_quirks_xs(u_int); 42192770Salfredstatic void scsi_low_setup_quirks_xs(struct targ_info *, struct lun_info *, u_int); 42279697Snon 42379697Snonstruct scsi_low_osdep_funcs scsi_low_osdep_funcs_xs = { 42479697Snon scsi_low_attach_xs, 42579697Snon scsi_low_world_start_xs, 42679697Snon scsi_low_dettach_xs, 42779697Snon scsi_low_ccb_setup_xs, 42879697Snon scsi_low_done_xs, 42979697Snon scsi_low_timeout_xs 43079697Snon}; 43179697Snon 43279697Snonstruct scsipi_device scsi_low_dev = { 43379697Snon NULL, /* Use default error handler */ 43479697Snon NULL, /* have a queue, served by this */ 43579697Snon NULL, /* have no async handler */ 43679697Snon NULL, /* Use default 'done' routine */ 43779697Snon}; 43879697Snon 43979697Snonstruct scsi_low_error_code scsi_low_error_code_xs[] = { 44079697Snon {0, XS_NOERROR}, 44179697Snon {SENSEIO, XS_SENSE}, 44279697Snon {BUSYERR, XS_BUSY }, 44379697Snon {SELTIMEOUTIO, XS_SELTIMEOUT}, 44479697Snon {TIMEOUTIO, XS_TIMEOUT}, 44579697Snon {-1, XS_DRIVER_STUFFUP} 44679697Snon}; 44779697Snon 44879697Snonstatic int 44979697Snonscsi_low_ioctl_xs(link, cmd, addr, flag, p) 45079697Snon struct scsipi_link *link; 45179697Snon u_long cmd; 45279697Snon caddr_t addr; 45379697Snon int flag; 45479697Snon struct proc *p; 45579697Snon{ 45679697Snon struct scsi_low_softc *slp; 45779697Snon int s, error = ENOTTY; 45879697Snon 45979697Snon slp = (struct scsi_low_softc *) link->adapter_softc; 46079697Snon if ((slp->sl_flags & HW_INACTIVE) != 0) 46179697Snon return ENXIO; 46279697Snon 46379697Snon if (cmd == SCBUSIORESET) 46479697Snon { 46579697Snon s = SCSI_LOW_SPLSCSI(); 46679697Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL); 46779697Snon splx(s); 46879697Snon error = 0; 46979697Snon } 47079697Snon else if (slp->sl_funcs->scsi_low_ioctl != 0) 47179697Snon { 47279697Snon error = (*slp->sl_funcs->scsi_low_ioctl) 47379697Snon (slp, cmd, addr, flag, p); 47479697Snon } 47579697Snon 47679697Snon return error; 47779697Snon} 47879697Snon 47979697Snonstatic int 48079697Snonscsi_low_enable_xs(arg, enable) 48179697Snon void *arg; 48279697Snon int enable; 48379697Snon{ 48479697Snon struct scsi_low_softc *slp = arg; 48579697Snon 48679697Snon if (enable != 0) 48779697Snon { 48879697Snon if ((slp->sl_flags & HW_INACTIVE) != 0) 48979697Snon return ENXIO; 49079697Snon } 49179697Snon else 49279697Snon { 49379697Snon if ((slp->sl_flags & HW_INACTIVE) != 0 || 49479697Snon (slp->sl_flags & HW_POWERCTRL) == 0) 49579697Snon return 0; 49679697Snon 49779697Snon slp->sl_flags |= HW_POWDOWN; 49879697Snon if (slp->sl_funcs->scsi_low_power != NULL) 49979697Snon { 50079697Snon (*slp->sl_funcs->scsi_low_power) 50179697Snon (slp, SCSI_LOW_POWDOWN); 50279697Snon } 50379697Snon } 50479697Snon return 0; 50579697Snon} 50679697Snon 50779697Snonstatic void 50879697Snonscsi_low_scsi_minphys_xs(bp) 50979697Snon struct buf *bp; 51079697Snon{ 51179697Snon 51279697Snon if (bp->b_bcount > SCSI_LOW_MINPHYS) 51379697Snon bp->b_bcount = SCSI_LOW_MINPHYS; 51479697Snon minphys(bp); 51579697Snon} 51679697Snon 51779697Snonstatic int 51879697Snonscsi_low_poll_xs(slp, cb) 51979697Snon struct scsi_low_softc *slp; 52079697Snon struct slccb *cb; 52179697Snon{ 52279697Snon struct scsipi_xfer *xs = cb->osdep; 52379697Snon int tcount; 52479697Snon 52579697Snon cb->ccb_flags |= CCB_NOSDONE; 52679697Snon tcount = 0; 52779697Snon 52879697Snon while (slp->sl_nio > 0) 52979697Snon { 53079697Snon SCSI_LOW_DELAY((1000 * 1000) / SCSI_LOW_XS_POLL_HZ); 53179697Snon 53279697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 53379697Snon 53479697Snon if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0) 53579697Snon { 53679697Snon cb->ccb_flags |= CCB_NORETRY; 53779697Snon cb->ccb_error |= FATALIO; 53879697Snon (void) scsi_low_revoke_ccb(slp, cb, 1); 53979697Snon printf("%s: hardware inactive in poll mode\n", 54079697Snon slp->sl_xname); 54179697Snon } 54279697Snon 54379697Snon if ((xs->flags & ITSDONE) != 0) 54479697Snon break; 54579697Snon 54679697Snon if (tcount ++ < SCSI_LOW_XS_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 54779697Snon continue; 54879697Snon 54979697Snon tcount = 0; 55079697Snon scsi_low_timeout_check(slp); 55179697Snon } 55279697Snon 55379697Snon xs->flags |= ITSDONE; 55479697Snon scsipi_done(xs); 55579697Snon return COMPLETE; 55679697Snon} 55779697Snon 55879697Snonstatic int 55979697Snonscsi_low_scsi_cmd_xs(xs) 56079697Snon struct scsipi_xfer *xs; 56179697Snon{ 56279697Snon struct scsipi_link *splp = xs->sc_link; 56379697Snon struct scsi_low_softc *slp = splp->adapter_softc; 56479697Snon struct targ_info *ti; 56579697Snon struct lun_info *li; 56679697Snon struct slccb *cb; 56779697Snon int s, targ, lun, flags, rv; 56879697Snon 56979697Snon if ((cb = SCSI_LOW_ALLOC_CCB(xs->flags & SCSI_NOSLEEP)) == NULL) 57079697Snon return TRY_AGAIN_LATER; 57179697Snon 57279697Snon targ = splp->scsipi_scsi.target, 57379697Snon lun = splp->scsipi_scsi.lun; 57479697Snon ti = slp->sl_ti[targ]; 57579697Snon 57679697Snon cb->osdep = xs; 57779697Snon cb->bp = xs->bp; 57879697Snon 57979697Snon if ((xs->flags & SCSI_POLL) == 0) 58079697Snon flags = CCB_AUTOSENSE; 58179697Snon else 58279697Snon flags = CCB_AUTOSENSE | CCB_POLLED; 58379697Snon 58479697Snon 58579697Snon s = SCSI_LOW_SPLSCSI(); 58679697Snon li = scsi_low_alloc_li(ti, lun, 1); 58779697Snon if ((u_int) splp->quirks != li->li_sloi.sloi_quirks) 58879697Snon { 58979697Snon scsi_low_setup_quirks_xs(ti, li, (u_int) splp->quirks); 59079697Snon } 59179697Snon 59279697Snon if ((xs->flags & SCSI_RESET) != 0) 59379697Snon { 59479697Snon flags |= CCB_NORETRY | CCB_URGENT; 59579697Snon scsi_low_enqueue(slp, ti, li, cb, flags, SCSI_LOW_MSG_RESET); 59679697Snon } 59779697Snon else 59879697Snon { 59979697Snon if (ti->ti_setup_msg != 0) 60079697Snon { 60179697Snon scsi_low_message_enqueue(slp, ti, li, flags); 60279697Snon } 60379697Snon 60479697Snon flags |= CCB_SCSIIO; 60579697Snon scsi_low_enqueue(slp, ti, li, cb, flags, 0); 60679697Snon } 60779697Snon 60879697Snon#ifdef SCSI_LOW_DEBUG 60979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, ti->ti_id) != 0) 61079697Snon { 61179697Snon scsi_low_test_abort(slp, ti, li); 61279697Snon } 61379697Snon#endif /* SCSI_LOW_DEBUG */ 61479697Snon 61579697Snon if ((cb->ccb_flags & CCB_POLLED) != 0) 61679697Snon { 61779697Snon rv = scsi_low_poll_xs(slp, cb); 61879697Snon } 61979697Snon else 62079697Snon { 62179697Snon rv = SUCCESSFULLY_QUEUED; 62279697Snon } 62379697Snon splx(s); 62479697Snon return rv; 62579697Snon} 62679697Snon 62779697Snonstatic int 62879697Snonscsi_low_attach_xs(slp) 62979697Snon struct scsi_low_softc *slp; 63079697Snon{ 63179697Snon struct scsipi_adapter *sap; 63279697Snon struct scsipi_link *splp; 63379697Snon 63479697Snon strncpy(slp->sl_xname, slp->sl_dev.dv_xname, 16); 63579697Snon 63679697Snon sap = SCSI_LOW_MALLOC(sizeof(*sap)); 63779697Snon if (sap == NULL) 63879697Snon return ENOMEM; 63979697Snon splp = SCSI_LOW_MALLOC(sizeof(*splp)); 64079697Snon if (splp == NULL) 641198356Sbrueffer { 642198356Sbrueffer SCSI_LOW_FREE(sap); 64379697Snon return ENOMEM; 644198356Sbrueffer } 64579697Snon 64679697Snon SCSI_LOW_BZERO(sap, sizeof(*sap)); 64779697Snon SCSI_LOW_BZERO(splp, sizeof(*splp)); 64879697Snon 64979697Snon sap->scsipi_cmd = scsi_low_scsi_cmd_xs; 65079697Snon sap->scsipi_minphys = scsi_low_scsi_minphys_xs; 65179697Snon sap->scsipi_enable = scsi_low_enable_xs; 65279697Snon sap->scsipi_ioctl = scsi_low_ioctl_xs; 65379697Snon#ifdef SCSI_LOW_TARGET_OPEN 65479697Snon sap->open_target_lu = scsi_low_target_open; 65579697Snon#endif /* SCSI_LOW_TARGET_OPEN */ 65679697Snon 65779697Snon splp->adapter_softc = slp; 65879697Snon splp->scsipi_scsi.adapter_target = slp->sl_hostid; 65979697Snon splp->scsipi_scsi.max_target = slp->sl_ntargs - 1; 66079697Snon splp->scsipi_scsi.max_lun = slp->sl_nluns - 1; 66179697Snon splp->scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE; 66279697Snon splp->openings = slp->sl_openings; 66379697Snon splp->type = BUS_SCSI; 66479697Snon splp->adapter_softc = slp; 66579697Snon splp->adapter = sap; 66679697Snon splp->device = &scsi_low_dev; 66779697Snon 66879697Snon slp->sl_si.si_splp = splp; 66979697Snon slp->sl_show_result = SHOW_ALL_NEG; 67079697Snon return 0; 67179697Snon} 67279697Snon 67379697Snonstatic int 67479697Snonscsi_low_world_start_xs(slp) 67579697Snon struct scsi_low_softc *slp; 67679697Snon{ 67779697Snon 67879697Snon return 0; 67979697Snon} 68079697Snon 68179697Snonstatic int 68279697Snonscsi_low_dettach_xs(slp) 68379697Snon struct scsi_low_softc *slp; 68479697Snon{ 68579697Snon 68679697Snon /* 68779697Snon * scsipi does not have dettach bus fucntion. 68879697Snon * 68979697Snon scsipi_dettach_scsibus(slp->sl_si.si_splp); 69079697Snon */ 69179697Snon return 0; 69279697Snon} 69379697Snon 69479697Snonstatic int 69579697Snonscsi_low_ccb_setup_xs(slp, cb) 69679697Snon struct scsi_low_softc *slp; 69779697Snon struct slccb *cb; 69879697Snon{ 69979697Snon struct scsipi_xfer *xs = (struct scsipi_xfer *) cb->osdep; 70079697Snon 70179697Snon if ((cb->ccb_flags & CCB_SCSIIO) != 0) 70279697Snon { 70379697Snon cb->ccb_scp.scp_cmd = (u_int8_t *) xs->cmd; 70479697Snon cb->ccb_scp.scp_cmdlen = xs->cmdlen; 70579697Snon cb->ccb_scp.scp_data = xs->data; 70679697Snon cb->ccb_scp.scp_datalen = xs->datalen; 70779697Snon cb->ccb_scp.scp_direction = (xs->flags & SCSI_DATA_OUT) ? 70879697Snon SCSI_LOW_WRITE : SCSI_LOW_READ; 70979697Snon cb->ccb_tcmax = xs->timeout / 1000; 71079697Snon } 71179697Snon else 71279697Snon { 71379697Snon scsi_low_unit_ready_cmd(cb); 71479697Snon } 71579697Snon return SCSI_LOW_START_QTAG; 71679697Snon} 71779697Snon 71879697Snonstatic int 71979697Snonscsi_low_done_xs(slp, cb) 72079697Snon struct scsi_low_softc *slp; 72179697Snon struct slccb *cb; 72279697Snon{ 72379697Snon struct scsipi_xfer *xs; 72479697Snon 72579697Snon xs = (struct scsipi_xfer *) cb->osdep; 72679697Snon if (cb->ccb_error == 0) 72779697Snon { 72879697Snon xs->error = XS_NOERROR; 72979697Snon xs->resid = 0; 73079697Snon } 73179697Snon else 73279697Snon { 73379697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 73479697Snon cb->ccb_error |= ABORTIO; 73579697Snon 73679697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 73779697Snon (cb->ccb_error & ABORTIO) == 0) 73879697Snon return EJUSTRETURN; 73979697Snon 74079697Snon if ((cb->ccb_error & SENSEIO) != 0) 74179697Snon { 74279697Snon xs->sense.scsi_sense = cb->ccb_sense; 74379697Snon } 74479697Snon 74579697Snon xs->error = scsi_low_translate_error_code(cb, 74679697Snon &scsi_low_error_code_xs[0]); 74779697Snon 74879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 74979697Snon if ((cb->ccb_flags & CCB_SILENT) == 0 && 75079697Snon cb->ccb_scp.scp_cmdlen > 0 && 75179697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 75279697Snon SCSI_LOW_CMD_ABORT_WARNING) != 0) 75379697Snon { 75479697Snon printf("%s: WARNING: scsi_low IO abort\n", 75579697Snon slp->sl_xname); 75679697Snon scsi_low_print(slp, NULL); 75779697Snon } 75879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 75979697Snon } 76079697Snon 76179697Snon if (cb->ccb_scp.scp_status == ST_UNKNOWN) 76279697Snon xs->status = 0; /* XXX */ 76379697Snon else 76479697Snon xs->status = cb->ccb_scp.scp_status; 76579697Snon 76679697Snon xs->flags |= ITSDONE; 76779697Snon if ((cb->ccb_flags & CCB_NOSDONE) == 0) 76879697Snon scsipi_done(xs); 76979697Snon 77079697Snon return 0; 77179697Snon} 77279697Snon 77379697Snonstatic void 77479697Snonscsi_low_timeout_xs(slp, ch, action) 77579697Snon struct scsi_low_softc *slp; 77679697Snon int ch; 77779697Snon int action; 77879697Snon{ 77979697Snon 78079697Snon switch (ch) 78179697Snon { 78279697Snon case SCSI_LOW_TIMEOUT_CH_IO: 78379697Snon switch (action) 78479697Snon { 78579697Snon case SCSI_LOW_TIMEOUT_START: 78679697Snon timeout(scsi_low_timeout, slp, 78779697Snon hz / SCSI_LOW_TIMEOUT_HZ); 78879697Snon break; 78979697Snon case SCSI_LOW_TIMEOUT_STOP: 79079697Snon untimeout(scsi_low_timeout, slp); 79179697Snon break; 79279697Snon } 79379697Snon break; 79479697Snon 79579697Snon case SCSI_LOW_TIMEOUT_CH_ENGAGE: 79679697Snon switch (action) 79779697Snon { 79879697Snon case SCSI_LOW_TIMEOUT_START: 79979697Snon timeout(scsi_low_engage, slp, 1); 80079697Snon break; 80179697Snon case SCSI_LOW_TIMEOUT_STOP: 80279697Snon untimeout(scsi_low_engage, slp); 80379697Snon break; 80479697Snon } 80579697Snon break; 80679697Snon 80779697Snon case SCSI_LOW_TIMEOUT_CH_RECOVER: 80879697Snon break; 80979697Snon } 81079697Snon} 81179697Snon 81279697Snonu_int 81379697Snonscsi_low_translate_quirks_xs(quirks) 81479697Snon u_int quirks; 81579697Snon{ 81679697Snon u_int flags; 81779697Snon 81879697Snon flags = SCSI_LOW_DISK_LFLAGS | SCSI_LOW_DISK_TFLAGS; 81979697Snon 82079697Snon#ifdef SDEV_NODISC 82179697Snon if (quirks & SDEV_NODISC) 82279697Snon flags &= ~SCSI_LOW_DISK_DISC; 82379697Snon#endif /* SDEV_NODISC */ 82479697Snon#ifdef SDEV_NOPARITY 82579697Snon if (quirks & SDEV_NOPARITY) 82679697Snon flags &= ~SCSI_LOW_DISK_PARITY; 82779697Snon#endif /* SDEV_NOPARITY */ 82879697Snon#ifdef SDEV_NOCMDLNK 82979697Snon if (quirks & SDEV_NOCMDLNK) 83079697Snon flags &= ~SCSI_LOW_DISK_LINK; 83179697Snon#endif /* SDEV_NOCMDLNK */ 83279697Snon#ifdef SDEV_NOTAG 83379697Snon if (quirks & SDEV_NOTAG) 83479697Snon flags &= ~SCSI_LOW_DISK_QTAG; 83579697Snon#endif /* SDEV_NOTAG */ 83679697Snon#ifdef SDEV_NOSYNC 83779697Snon if (quirks & SDEV_NOSYNC) 83879697Snon flags &= ~SCSI_LOW_DISK_SYNC; 83979697Snon#endif /* SDEV_NOSYNC */ 84079697Snon 84179697Snon return flags; 84279697Snon} 84379697Snon 84479697Snonstatic void 84579697Snonscsi_low_setup_quirks_xs(ti, li, flags) 84679697Snon struct targ_info *ti; 84779697Snon struct lun_info *li; 84879697Snon u_int flags; 84979697Snon{ 85079697Snon u_int quirks; 85179697Snon 85279697Snon li->li_sloi.sloi_quirks = flags; 85379697Snon quirks = scsi_low_translate_quirks_xs(flags); 85479697Snon ti->ti_quirks = quirks & SCSI_LOW_DISK_TFLAGS; 85579697Snon li->li_quirks = quirks & SCSI_LOW_DISK_LFLAGS; 85679697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 85779697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 85879697Snon scsi_low_calcf_target(ti); 85979697Snon scsi_low_calcf_lun(li); 86079697Snon scsi_low_calcf_show(li); 86179697Snon} 86279697Snon 86379697Snon#ifdef SCSI_LOW_TARGET_OPEN 86479697Snonstatic int 86579697Snonscsi_low_target_open(link, cf) 86679697Snon struct scsipi_link *link; 86779697Snon struct cfdata *cf; 86879697Snon{ 86979697Snon u_int target = link->scsipi_scsi.target; 87079697Snon u_int lun = link->scsipi_scsi.lun; 87179697Snon struct scsi_low_softc *slp; 87279697Snon struct targ_info *ti; 87379697Snon struct lun_info *li; 87479697Snon 87579697Snon slp = (struct scsi_low_softc *) link->adapter_softc; 87679697Snon ti = slp->sl_ti[target]; 87779697Snon li = scsi_low_alloc_li(ti, lun, 0); 87879697Snon if (li == NULL) 87979697Snon return 0; 88079697Snon 88179697Snon li->li_cfgflags = cf->cf_flags; 88279697Snon scsi_low_setup_quirks_xs(ti, li, (u_int) link->quirks); 88379697Snon return 0; 88479697Snon} 88579697Snon#endif /* SCSI_LOW_TARGET_OPEN */ 88679697Snon 88779697Snon#endif /* SCSI_LOW_INTERFACE_XS */ 88879697Snon 88979697Snon#ifdef SCSI_LOW_INTERFACE_CAM 89079697Snon/************************************************************** 89179697Snon * SCSI INTERFACE (CAM) 89279697Snon **************************************************************/ 893147723Savatar#define SCSI_LOW_MALLOC(size) malloc((size), M_SCSILOW, M_NOWAIT) 894147723Savatar#define SCSI_LOW_FREE(pt) free((pt), M_SCSILOW) 89579697Snon#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb() 89679697Snon 89792770Salfredstatic void scsi_low_poll_cam(struct cam_sim *); 89892770Salfredvoid scsi_low_scsi_action_cam(struct cam_sim *, union ccb *); 89979697Snon 90092770Salfredstatic int scsi_low_attach_cam(struct scsi_low_softc *); 90192770Salfredstatic int scsi_low_world_start_cam(struct scsi_low_softc *); 90292770Salfredstatic int scsi_low_dettach_cam(struct scsi_low_softc *); 90392770Salfredstatic int scsi_low_ccb_setup_cam(struct scsi_low_softc *, struct slccb *); 90492770Salfredstatic int scsi_low_done_cam(struct scsi_low_softc *, struct slccb *); 90592770Salfredstatic void scsi_low_timeout_cam(struct scsi_low_softc *, int, int); 90679697Snon 90779697Snonstruct scsi_low_osdep_funcs scsi_low_osdep_funcs_cam = { 90879697Snon scsi_low_attach_cam, 90979697Snon scsi_low_world_start_cam, 91079697Snon scsi_low_dettach_cam, 91179697Snon scsi_low_ccb_setup_cam, 91279697Snon scsi_low_done_cam, 91379697Snon scsi_low_timeout_cam 91479697Snon}; 91579697Snon 91679697Snonstruct scsi_low_error_code scsi_low_error_code_cam[] = { 91779697Snon {0, CAM_REQ_CMP}, 91879697Snon {SENSEIO, CAM_AUTOSNS_VALID | CAM_REQ_CMP_ERR}, 91979697Snon {SENSEERR, CAM_AUTOSENSE_FAIL}, 92079697Snon {UACAERR, CAM_SCSI_STATUS_ERROR}, 92179697Snon {BUSYERR | STATERR, CAM_SCSI_STATUS_ERROR}, 92279697Snon {SELTIMEOUTIO, CAM_SEL_TIMEOUT}, 92379697Snon {TIMEOUTIO, CAM_CMD_TIMEOUT}, 92479697Snon {PDMAERR, CAM_DATA_RUN_ERR}, 92579697Snon {PARITYERR, CAM_UNCOR_PARITY}, 92679697Snon {UBFERR, CAM_UNEXP_BUSFREE}, 92779697Snon {ABORTIO, CAM_REQ_ABORTED}, 92879697Snon {-1, CAM_UNREC_HBA_ERROR} 92979697Snon}; 93079697Snon 93179697Snon#define SIM2SLP(sim) ((struct scsi_low_softc *) cam_sim_softc((sim))) 93279697Snon 93379697Snon/* XXX: 93479697Snon * Please check a polling hz, currently we assume scsi_low_poll() is 93579697Snon * called each 1 ms. 93679697Snon */ 93779697Snon#define SCSI_LOW_CAM_POLL_HZ 1000 /* OK ? */ 93879697Snon 93979697Snonstatic void 94079697Snonscsi_low_poll_cam(sim) 94179697Snon struct cam_sim *sim; 94279697Snon{ 94379697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 94479697Snon 94579697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 94679697Snon 94779697Snon if (slp->sl_si.si_poll_count ++ >= 94879697Snon SCSI_LOW_CAM_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 94979697Snon { 95079697Snon slp->sl_si.si_poll_count = 0; 95179697Snon scsi_low_timeout_check(slp); 95279697Snon } 95379697Snon} 95479697Snon 95579697Snonvoid 95679697Snonscsi_low_scsi_action_cam(sim, ccb) 95779697Snon struct cam_sim *sim; 95879697Snon union ccb *ccb; 95979697Snon{ 96079697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 96179697Snon struct targ_info *ti; 96279697Snon struct lun_info *li; 96379697Snon struct slccb *cb; 96479697Snon u_int lun, flags, msg, target; 96579697Snon int s, rv; 96679697Snon 96779697Snon target = (u_int) (ccb->ccb_h.target_id); 96879697Snon lun = (u_int) ccb->ccb_h.target_lun; 96979697Snon 97079697Snon#ifdef SCSI_LOW_DEBUG 97179697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_ACTION, target) != 0) 97279697Snon { 97379697Snon printf("%s: cam_action: func code 0x%x target: %d, lun: %d\n", 97479697Snon slp->sl_xname, ccb->ccb_h.func_code, target, lun); 97579697Snon } 97679697Snon#endif /* SCSI_LOW_DEBUG */ 97779697Snon 97879697Snon switch (ccb->ccb_h.func_code) { 97979697Snon case XPT_SCSI_IO: /* Execute the requested I/O operation */ 98079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 98179697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 98279697Snon { 98379697Snon printf("%s: invalid target/lun\n", slp->sl_xname); 98479697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 98579697Snon xpt_done(ccb); 98679697Snon return; 98779697Snon } 98879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 98979697Snon 99079697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) { 99179697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 99279697Snon xpt_done(ccb); 99379697Snon return; 99479697Snon } 99579697Snon 99679697Snon ti = slp->sl_ti[target]; 99779697Snon cb->osdep = ccb; 99879697Snon cb->bp = NULL; 99979697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 100079697Snon flags = CCB_AUTOSENSE | CCB_SCSIIO; 100179697Snon else 100279697Snon flags = CCB_SCSIIO; 100379697Snon 100479697Snon s = SCSI_LOW_SPLSCSI(); 100579697Snon li = scsi_low_alloc_li(ti, lun, 1); 100679697Snon 100779697Snon if (ti->ti_setup_msg != 0) 100879697Snon { 100979697Snon scsi_low_message_enqueue(slp, ti, li, CCB_AUTOSENSE); 101079697Snon } 101179697Snon 101279697Snon scsi_low_enqueue(slp, ti, li, cb, flags, 0); 101379697Snon 101479697Snon#ifdef SCSI_LOW_DEBUG 101579697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, target) != 0) 101679697Snon { 101779697Snon scsi_low_test_abort(slp, ti, li); 101879697Snon } 101979697Snon#endif /* SCSI_LOW_DEBUG */ 102079697Snon splx(s); 102179697Snon break; 102279697Snon 102379697Snon case XPT_EN_LUN: /* Enable LUN as a target */ 102479697Snon case XPT_TARGET_IO: /* Execute target I/O request */ 102579697Snon case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 102679697Snon case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 102779697Snon /* XXX Implement */ 102879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 102979697Snon xpt_done(ccb); 103079697Snon break; 103179697Snon 103279697Snon case XPT_ABORT: /* Abort the specified CCB */ 103379697Snon#ifdef SCSI_LOW_DIAGNOSTIC 103479697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 103579697Snon { 103679697Snon printf("%s: invalid target/lun\n", slp->sl_xname); 103779697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 103879697Snon xpt_done(ccb); 103979697Snon return; 104079697Snon } 104179697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 104279697Snon 104379697Snon s = SCSI_LOW_SPLSCSI(); 104479697Snon cb = scsi_low_find_ccb(slp, target, lun, ccb->cab.abort_ccb); 104579697Snon rv = scsi_low_abort_ccb(slp, cb); 104679697Snon splx(s); 104779697Snon 104879697Snon if (rv == 0) 104979697Snon ccb->ccb_h.status = CAM_REQ_CMP; 105079697Snon else 105179697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 105279697Snon xpt_done(ccb); 105379697Snon break; 105479697Snon 105579697Snon case XPT_SET_TRAN_SETTINGS: { 1056163816Smjacob struct ccb_trans_settings_scsi *scsi; 1057163816Smjacob struct ccb_trans_settings_spi *spi; 105879697Snon struct ccb_trans_settings *cts; 105979697Snon u_int val; 106079697Snon 106179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 106279697Snon if (target == CAM_TARGET_WILDCARD) 106379697Snon { 106479697Snon printf("%s: invalid target\n", slp->sl_xname); 106579697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 106679697Snon xpt_done(ccb); 106779697Snon return; 106879697Snon } 106979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 107079697Snon cts = &ccb->cts; 107179697Snon ti = slp->sl_ti[target]; 107279697Snon if (lun == CAM_LUN_WILDCARD) 107379697Snon lun = 0; 107479697Snon 107579697Snon s = SCSI_LOW_SPLSCSI(); 1076163816Smjacob scsi = &cts->proto_specific.scsi; 1077163816Smjacob spi = &cts->xport_specific.spi; 1078163816Smjacob if ((spi->valid & (CTS_SPI_VALID_BUS_WIDTH | 1079163816Smjacob CTS_SPI_VALID_SYNC_RATE | 1080163816Smjacob CTS_SPI_VALID_SYNC_OFFSET)) != 0) 1081163816Smjacob { 1082163816Smjacob if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) { 1083163816Smjacob val = spi->bus_width; 1084163816Smjacob if (val < ti->ti_width) 1085163816Smjacob ti->ti_width = val; 1086163816Smjacob } 1087163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_RATE) { 1088163816Smjacob val = spi->sync_period; 1089163816Smjacob if (val == 0 || val > ti->ti_maxsynch.period) 1090163816Smjacob ti->ti_maxsynch.period = val; 1091163816Smjacob } 1092163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) { 1093163816Smjacob val = spi->sync_offset; 1094163816Smjacob if (val < ti->ti_maxsynch.offset) 1095163816Smjacob ti->ti_maxsynch.offset = val; 1096163816Smjacob } 1097163816Smjacob ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 1098163816Smjacob scsi_low_calcf_target(ti); 1099163816Smjacob } 1100163816Smjacob 1101163816Smjacob if ((spi->valid & CTS_SPI_FLAGS_DISC_ENB) != 0 || 1102163816Smjacob (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 1103163816Smjacob 1104163816Smjacob li = scsi_low_alloc_li(ti, lun, 1); 1105163816Smjacob if (spi->valid & CTS_SPI_FLAGS_DISC_ENB) { 1106163816Smjacob li->li_quirks |= SCSI_LOW_DISK_DISC; 1107163816Smjacob } else { 1108163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_DISC; 1109163816Smjacob } 1110163816Smjacob 1111163816Smjacob if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) { 1112163816Smjacob li->li_quirks |= SCSI_LOW_DISK_QTAG; 1113163816Smjacob } else { 1114163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_QTAG; 1115163816Smjacob } 1116163816Smjacob li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 1117163816Smjacob scsi_low_calcf_target(ti); 1118163816Smjacob scsi_low_calcf_lun(li); 1119163816Smjacob if ((slp->sl_show_result & SHOW_CALCF_RES) != 0) 1120163816Smjacob scsi_low_calcf_show(li); 1121163816Smjacob } 112279697Snon splx(s); 112379697Snon 112479697Snon ccb->ccb_h.status = CAM_REQ_CMP; 112579697Snon xpt_done(ccb); 112679697Snon break; 112779697Snon } 112879697Snon 112979697Snon case XPT_GET_TRAN_SETTINGS: { 113079697Snon struct ccb_trans_settings *cts; 113179697Snon u_int diskflags; 113279697Snon 113379697Snon cts = &ccb->cts; 113479697Snon#ifdef SCSI_LOW_DIAGNOSTIC 113579697Snon if (target == CAM_TARGET_WILDCARD) 113679697Snon { 113779697Snon printf("%s: invalid target\n", slp->sl_xname); 113879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 113979697Snon xpt_done(ccb); 114079697Snon return; 114179697Snon } 114279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 114379697Snon ti = slp->sl_ti[target]; 114479697Snon if (lun == CAM_LUN_WILDCARD) 114579697Snon lun = 0; 114679697Snon 114779697Snon s = SCSI_LOW_SPLSCSI(); 114879697Snon li = scsi_low_alloc_li(ti, lun, 1); 114979697Snon if (li != NULL && cts->type == CTS_TYPE_CURRENT_SETTINGS) { 115079697Snon struct ccb_trans_settings_scsi *scsi = 115179697Snon &cts->proto_specific.scsi; 115279697Snon struct ccb_trans_settings_spi *spi = 115379697Snon &cts->xport_specific.spi; 115479697Snon#ifdef SCSI_LOW_DIAGNOSTIC 115579697Snon if (li->li_flags_valid != SCSI_LOW_LUN_FLAGS_ALL_VALID) 115679697Snon { 115779697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 115879697Snon printf("%s: invalid GET_TRANS_CURRENT_SETTINGS call\n", 115979697Snon slp->sl_xname); 116079697Snon goto settings_out; 116179697Snon } 116279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 116379697Snon cts->protocol = PROTO_SCSI; 116479697Snon cts->protocol_version = SCSI_REV_2; 116579697Snon cts->transport = XPORT_SPI; 116679697Snon cts->transport_version = 2; 116779697Snon 116879697Snon scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 116979697Snon spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 117079697Snon 117179697Snon diskflags = li->li_diskflags & li->li_cfgflags; 117279697Snon if (diskflags & SCSI_LOW_DISK_DISC) 117379697Snon spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 117479697Snon if (diskflags & SCSI_LOW_DISK_QTAG) 117579697Snon scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 117679697Snon 117779697Snon spi->sync_period = ti->ti_maxsynch.period; 117879697Snon spi->valid |= CTS_SPI_VALID_SYNC_RATE; 117979697Snon spi->sync_offset = ti->ti_maxsynch.offset; 118079697Snon spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 118179697Snon 118279697Snon spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 118379697Snon spi->bus_width = ti->ti_width; 118479697Snon 118579697Snon if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 118679697Snon scsi->valid = CTS_SCSI_VALID_TQ; 118779697Snon spi->valid |= CTS_SPI_VALID_DISC; 118879697Snon } else 118979697Snon scsi->valid = 0; 119079697Snon } else 119179697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 119279697Snonsettings_out: 119379697Snon splx(s); 119479697Snon xpt_done(ccb); 119579697Snon break; 119679697Snon } 119779697Snon 119879697Snon case XPT_CALC_GEOMETRY: { /* not yet HN2 */ 1199116351Snjl cam_calc_geometry(&ccb->ccg, /*extended*/1); 120079697Snon xpt_done(ccb); 120179697Snon break; 120279697Snon } 120379697Snon 120479697Snon case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 120579697Snon s = SCSI_LOW_SPLSCSI(); 120679697Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL); 120779697Snon splx(s); 120879697Snon ccb->ccb_h.status = CAM_REQ_CMP; 120979697Snon xpt_done(ccb); 121079697Snon break; 121179697Snon 121279697Snon case XPT_TERM_IO: /* Terminate the I/O process */ 121379697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 121479697Snon xpt_done(ccb); 121579697Snon break; 121679697Snon 121779697Snon case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 121879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 121979697Snon if (target == CAM_TARGET_WILDCARD) 122079697Snon { 122179697Snon printf("%s: invalid target\n", slp->sl_xname); 122279697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 122379697Snon xpt_done(ccb); 122479697Snon return; 122579697Snon } 122679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 122779697Snon 122879697Snon msg = SCSI_LOW_MSG_RESET; 122979697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) 123079697Snon { 123179697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 123279697Snon xpt_done(ccb); 123379697Snon return; 123479697Snon } 123579697Snon 123679697Snon ti = slp->sl_ti[target]; 123779697Snon if (lun == CAM_LUN_WILDCARD) 123879697Snon lun = 0; 123979697Snon cb->osdep = ccb; 124079697Snon cb->bp = NULL; 124179697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 124279697Snon flags = CCB_AUTOSENSE | CCB_NORETRY | CCB_URGENT; 124379697Snon else 124479697Snon flags = CCB_NORETRY | CCB_URGENT; 124579697Snon 124679697Snon s = SCSI_LOW_SPLSCSI(); 124779697Snon li = scsi_low_alloc_li(ti, lun, 1); 124879697Snon scsi_low_enqueue(slp, ti, li, cb, flags, msg); 124979697Snon splx(s); 125079697Snon break; 125179697Snon 125279697Snon case XPT_PATH_INQ: { /* Path routing inquiry */ 125379697Snon struct ccb_pathinq *cpi = &ccb->cpi; 125479697Snon 125579697Snon cpi->version_num = scsi_low_version_major; 125679697Snon cpi->hba_inquiry = PI_TAG_ABLE | PI_LINKED_CDB; 125779697Snon ti = slp->sl_ti[slp->sl_hostid]; /* host id */ 125879697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 125979697Snon cpi->hba_inquiry |= PI_WIDE_16; 126079697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 126179697Snon cpi->hba_inquiry |= PI_WIDE_32; 126279697Snon if (ti->ti_maxsynch.offset > 0) 126379697Snon cpi->hba_inquiry |= PI_SDTR_ABLE; 126479697Snon cpi->target_sprt = 0; 126579697Snon cpi->hba_misc = 0; 126679697Snon cpi->hba_eng_cnt = 0; 126779697Snon cpi->max_target = slp->sl_ntargs - 1; 126879697Snon cpi->max_lun = slp->sl_nluns - 1; 126979697Snon cpi->initiator_id = slp->sl_hostid; 127079697Snon cpi->bus_id = cam_sim_bus(sim); 127179697Snon cpi->base_transfer_speed = 3300; 127279697Snon cpi->transport = XPORT_SPI; 127379697Snon cpi->transport_version = 2; 127479697Snon cpi->protocol = PROTO_SCSI; 127579697Snon cpi->protocol_version = SCSI_REV_2; 127679697Snon strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 127779697Snon strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN); 127879697Snon strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 127979697Snon cpi->unit_number = cam_sim_unit(sim); 128079697Snon cpi->ccb_h.status = CAM_REQ_CMP; 128179697Snon xpt_done(ccb); 128279697Snon break; 128379697Snon } 128479697Snon 128579697Snon default: 128679697Snon printf("scsi_low: non support func_code = %d ", 128779697Snon ccb->ccb_h.func_code); 128879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 128979697Snon xpt_done(ccb); 129079697Snon break; 129179697Snon } 129279697Snon} 129379697Snon 129479697Snonstatic int 129579697Snonscsi_low_attach_cam(slp) 129679697Snon struct scsi_low_softc *slp; 129779697Snon{ 129879697Snon struct cam_devq *devq; 129979697Snon int tagged_openings; 130079697Snon 130179697Snon sprintf(slp->sl_xname, "%s%d", 130279697Snon DEVPORT_DEVNAME(slp->sl_dev), DEVPORT_DEVUNIT(slp->sl_dev)); 130379697Snon 130479697Snon devq = cam_simq_alloc(SCSI_LOW_NCCB); 130579697Snon if (devq == NULL) 130679697Snon return (ENOMEM); 130779697Snon 130879697Snon /* 130979697Snon * ask the adapter what subunits are present 131079697Snon */ 131179697Snon tagged_openings = min(slp->sl_openings, SCSI_LOW_MAXNEXUS); 131279697Snon slp->sl_si.sim = cam_sim_alloc(scsi_low_scsi_action_cam, 131379697Snon scsi_low_poll_cam, 131479697Snon DEVPORT_DEVNAME(slp->sl_dev), slp, 1315168752Sscottl DEVPORT_DEVUNIT(slp->sl_dev), &Giant, 131679697Snon slp->sl_openings, tagged_openings, devq); 131779697Snon 131879697Snon if (slp->sl_si.sim == NULL) { 131979697Snon cam_simq_free(devq); 132079697Snon return ENODEV; 132179697Snon } 132279697Snon 1323170872Sscottl if (xpt_bus_register(slp->sl_si.sim, NULL, 0) != CAM_SUCCESS) { 1324147723Savatar free(slp->sl_si.sim, M_SCSILOW); 132579697Snon return ENODEV; 132679697Snon } 132779697Snon 132879697Snon if (xpt_create_path(&slp->sl_si.path, /*periph*/NULL, 132979697Snon cam_sim_path(slp->sl_si.sim), CAM_TARGET_WILDCARD, 133079697Snon CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 133179697Snon xpt_bus_deregister(cam_sim_path(slp->sl_si.sim)); 133279697Snon cam_sim_free(slp->sl_si.sim, /*free_simq*/TRUE); 133379697Snon return ENODEV; 133479697Snon } 133579697Snon 133679697Snon slp->sl_show_result = SHOW_CALCF_RES; /* OK ? */ 133779697Snon return 0; 133879697Snon} 133979697Snon 134079697Snonstatic int 134179697Snonscsi_low_world_start_cam(slp) 134279697Snon struct scsi_low_softc *slp; 134379697Snon{ 134479697Snon 134579697Snon return 0; 134679697Snon} 134779697Snon 134879697Snonstatic int 134979697Snonscsi_low_dettach_cam(slp) 135079697Snon struct scsi_low_softc *slp; 135179697Snon{ 135279697Snon 135379697Snon xpt_async(AC_LOST_DEVICE, slp->sl_si.path, NULL); 135479697Snon xpt_free_path(slp->sl_si.path); 135579697Snon xpt_bus_deregister(cam_sim_path(slp->sl_si.sim)); 135679697Snon cam_sim_free(slp->sl_si.sim, /* free_devq */ TRUE); 135779697Snon return 0; 135879697Snon} 135979697Snon 136079697Snonstatic int 136179697Snonscsi_low_ccb_setup_cam(slp, cb) 136279697Snon struct scsi_low_softc *slp; 136379697Snon struct slccb *cb; 136479697Snon{ 136579697Snon union ccb *ccb = (union ccb *) cb->osdep; 136679697Snon 136779697Snon if ((cb->ccb_flags & CCB_SCSIIO) != 0) 136879697Snon { 136979697Snon cb->ccb_scp.scp_cmd = ccb->csio.cdb_io.cdb_bytes; 137079697Snon cb->ccb_scp.scp_cmdlen = (int) ccb->csio.cdb_len; 137179697Snon cb->ccb_scp.scp_data = ccb->csio.data_ptr; 137279697Snon cb->ccb_scp.scp_datalen = (int) ccb->csio.dxfer_len; 137379697Snon if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 137479697Snon cb->ccb_scp.scp_direction = SCSI_LOW_WRITE; 137579697Snon else /* if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) */ 137679697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 137779697Snon cb->ccb_tcmax = ccb->ccb_h.timeout / 1000; 137879697Snon } 137979697Snon else 138079697Snon { 138179697Snon scsi_low_unit_ready_cmd(cb); 138279697Snon } 138379697Snon return SCSI_LOW_START_QTAG; 138479697Snon} 138579697Snon 138679697Snonstatic int 138779697Snonscsi_low_done_cam(slp, cb) 138879697Snon struct scsi_low_softc *slp; 138979697Snon struct slccb *cb; 139079697Snon{ 139179697Snon union ccb *ccb; 139279697Snon 139379697Snon ccb = (union ccb *) cb->osdep; 139479697Snon if (cb->ccb_error == 0) 139579697Snon { 139679697Snon ccb->ccb_h.status = CAM_REQ_CMP; 139779697Snon ccb->csio.resid = 0; 139879697Snon } 139979697Snon else 140079697Snon { 140179697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 140279697Snon cb->ccb_error |= ABORTIO; 140379697Snon 140479697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 140579697Snon (cb->ccb_error & ABORTIO) == 0) 140679697Snon return EJUSTRETURN; 140779697Snon 140879697Snon if ((cb->ccb_error & SENSEIO) != 0) 140979697Snon { 141079697Snon memcpy(&ccb->csio.sense_data, 141179697Snon &cb->ccb_sense, 141279697Snon sizeof(ccb->csio.sense_data)); 141379697Snon } 141479697Snon 141579697Snon ccb->ccb_h.status = scsi_low_translate_error_code(cb, 141679697Snon &scsi_low_error_code_cam[0]); 141779697Snon 141879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 141979697Snon if ((cb->ccb_flags & CCB_SILENT) == 0 && 142079697Snon cb->ccb_scp.scp_cmdlen > 0 && 142179697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 142279697Snon SCSI_LOW_CMD_ABORT_WARNING) != 0) 142379697Snon { 142479697Snon printf("%s: WARNING: scsi_low IO abort\n", 142579697Snon slp->sl_xname); 142679697Snon scsi_low_print(slp, NULL); 142779697Snon } 142879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 142979697Snon } 143079697Snon 143179697Snon if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 0) 143279697Snon ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 143379697Snon 143479697Snon if (cb->ccb_scp.scp_status == ST_UNKNOWN) 143579697Snon ccb->csio.scsi_status = 0; /* XXX */ 143679697Snon else 143779697Snon ccb->csio.scsi_status = cb->ccb_scp.scp_status; 143879697Snon 143979697Snon if ((cb->ccb_flags & CCB_NOSDONE) == 0) 144079697Snon xpt_done(ccb); 144179697Snon return 0; 144279697Snon} 144379697Snon 144479697Snonstatic void 144579697Snonscsi_low_timeout_cam(slp, ch, action) 144679697Snon struct scsi_low_softc *slp; 144779697Snon int ch; 144879697Snon int action; 144979697Snon{ 145079697Snon 145179697Snon switch (ch) 145279697Snon { 145379697Snon case SCSI_LOW_TIMEOUT_CH_IO: 145479697Snon switch (action) 145579697Snon { 145679697Snon case SCSI_LOW_TIMEOUT_START: 145779697Snon slp->sl_si.timeout_ch = timeout(scsi_low_timeout, slp, 145879697Snon hz / SCSI_LOW_TIMEOUT_HZ); 145979697Snon break; 146079697Snon case SCSI_LOW_TIMEOUT_STOP: 146179697Snon untimeout(scsi_low_timeout, slp, slp->sl_si.timeout_ch); 146279697Snon break; 146379697Snon } 146479697Snon break; 146579697Snon 146679697Snon case SCSI_LOW_TIMEOUT_CH_ENGAGE: 146779697Snon switch (action) 146879697Snon { 146979697Snon case SCSI_LOW_TIMEOUT_START: 147079697Snon slp->sl_si.engage_ch = timeout(scsi_low_engage, slp, 1); 147179697Snon break; 147279697Snon case SCSI_LOW_TIMEOUT_STOP: 147379697Snon untimeout(scsi_low_engage, slp, slp->sl_si.engage_ch); 147479697Snon break; 147579697Snon } 147679697Snon break; 147779697Snon case SCSI_LOW_TIMEOUT_CH_RECOVER: 147879697Snon break; 147979697Snon } 148079697Snon} 148179697Snon 148279697Snon#endif /* SCSI_LOW_INTERFACE_CAM */ 148379697Snon 148479697Snon/*============================================================= 148579697Snon * END OF OS switch (All OS depend fucntions should be above) 148679697Snon =============================================================*/ 148779697Snon 148879697Snon/************************************************************** 148979697Snon * scsi low deactivate and activate 149079697Snon **************************************************************/ 149179697Snonint 149279697Snonscsi_low_is_busy(slp) 149379697Snon struct scsi_low_softc *slp; 149479697Snon{ 149579697Snon 149679697Snon if (slp->sl_nio > 0) 149779697Snon return EBUSY; 149879697Snon return 0; 149979697Snon} 150079697Snon 150179697Snonint 150279697Snonscsi_low_deactivate(slp) 150379697Snon struct scsi_low_softc *slp; 150479697Snon{ 150579697Snon int s; 150679697Snon 150779697Snon s = SCSI_LOW_SPLSCSI(); 150879697Snon slp->sl_flags |= HW_INACTIVE; 150979697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 151079697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_STOP); 151179697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 151279697Snon (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP); 151379697Snon splx(s); 151479697Snon return 0; 151579697Snon} 151679697Snon 151779697Snonint 151879697Snonscsi_low_activate(slp) 151979697Snon struct scsi_low_softc *slp; 152079697Snon{ 152179697Snon int error, s; 152279697Snon 152379697Snon s = SCSI_LOW_SPLSCSI(); 152479697Snon slp->sl_flags &= ~HW_INACTIVE; 152579697Snon if ((error = scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL)) != 0) 152679697Snon { 152779697Snon slp->sl_flags |= HW_INACTIVE; 152879697Snon splx(s); 152979697Snon return error; 153079697Snon } 153179697Snon 153279697Snon slp->sl_timeout_count = 0; 153379697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 153479697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 153579697Snon splx(s); 153679697Snon return 0; 153779697Snon} 153879697Snon 153979697Snon/************************************************************** 154079697Snon * scsi low log 154179697Snon **************************************************************/ 154279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 154392770Salfredstatic void scsi_low_msg_log_init(struct scsi_low_msg_log *); 154492770Salfredstatic void scsi_low_msg_log_write(struct scsi_low_msg_log *, u_int8_t *, int); 154592770Salfredstatic void scsi_low_msg_log_show(struct scsi_low_msg_log *, char *, int); 154679697Snon 154779697Snonstatic void 154879697Snonscsi_low_msg_log_init(slmlp) 154979697Snon struct scsi_low_msg_log *slmlp; 155079697Snon{ 155179697Snon 155279697Snon slmlp->slml_ptr = 0; 155379697Snon} 155479697Snon 155579697Snonstatic void 155679697Snonscsi_low_msg_log_write(slmlp, datap, len) 155779697Snon struct scsi_low_msg_log *slmlp; 155879697Snon u_int8_t *datap; 155979697Snon int len; 156079697Snon{ 156179697Snon int ptr, ind; 156279697Snon 156379697Snon if (slmlp->slml_ptr >= SCSI_LOW_MSG_LOG_DATALEN) 156479697Snon return; 156579697Snon 156679697Snon ptr = slmlp->slml_ptr ++; 156779697Snon for (ind = 0; ind < sizeof(slmlp->slml_msg[0]) && ind < len; ind ++) 156879697Snon slmlp->slml_msg[ptr].msg[ind] = datap[ind]; 156979697Snon for ( ; ind < sizeof(slmlp->slml_msg[0]); ind ++) 157079697Snon slmlp->slml_msg[ptr].msg[ind] = 0; 157179697Snon} 157279697Snon 157379697Snonstatic void 157479697Snonscsi_low_msg_log_show(slmlp, s, len) 157579697Snon struct scsi_low_msg_log *slmlp; 157679697Snon char *s; 157779697Snon int len; 157879697Snon{ 157979697Snon int ptr, ind; 158079697Snon 158179697Snon printf("%s: (%d) ", s, slmlp->slml_ptr); 158279697Snon for (ptr = 0; ptr < slmlp->slml_ptr; ptr ++) 158379697Snon { 158479697Snon for (ind = 0; ind < len && ind < sizeof(slmlp->slml_msg[0]); 158579697Snon ind ++) 158679697Snon { 158779697Snon printf("[%x]", (u_int) slmlp->slml_msg[ptr].msg[ind]); 158879697Snon } 158979697Snon printf(">"); 159079697Snon } 159179697Snon printf("\n"); 159279697Snon} 159379697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 159479697Snon 159579697Snon/************************************************************** 159667468Snon * power control 159767468Snon **************************************************************/ 159867468Snonstatic void 159967468Snonscsi_low_engage(arg) 160067468Snon void *arg; 160167468Snon{ 160267468Snon struct scsi_low_softc *slp = arg; 160379697Snon int s = SCSI_LOW_SPLSCSI(); 160467468Snon 160567468Snon switch (slp->sl_rstep) 160667468Snon { 160767468Snon case 0: 160867468Snon slp->sl_rstep ++; 160967468Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 161079697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp, 161179697Snon SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_START); 161267468Snon break; 161367468Snon 161467468Snon case 1: 161567468Snon slp->sl_rstep ++; 161667468Snon slp->sl_flags &= ~HW_RESUME; 161767468Snon scsi_low_start(slp); 161867468Snon break; 161967468Snon 162067468Snon case 2: 162167468Snon break; 162267468Snon } 162367468Snon splx(s); 162467468Snon} 162567468Snon 162667468Snonstatic int 162767468Snonscsi_low_init(slp, flags) 162867468Snon struct scsi_low_softc *slp; 162967468Snon u_int flags; 163067468Snon{ 163179697Snon int rv = 0; 163267468Snon 163379697Snon slp->sl_flags |= HW_INITIALIZING; 163479697Snon 163579697Snon /* clear power control timeout */ 163667468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 163767468Snon { 163879697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp, 163979697Snon SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP); 164067468Snon slp->sl_flags &= ~(HW_POWDOWN | HW_RESUME); 164167468Snon slp->sl_active = 1; 164267468Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 164367468Snon } 164467468Snon 164567468Snon /* reset current nexus */ 164667468Snon scsi_low_reset_nexus(slp, flags); 164767468Snon if ((slp->sl_flags & HW_INACTIVE) != 0) 164879697Snon { 164979697Snon rv = EBUSY; 165079697Snon goto out; 165179697Snon } 165267468Snon 165379697Snon if (flags != SCSI_LOW_RESTART_SOFT) 165479697Snon { 165579697Snon rv = ((*slp->sl_funcs->scsi_low_init) (slp, flags)); 165679697Snon } 165767468Snon 165879697Snonout: 165979697Snon slp->sl_flags &= ~HW_INITIALIZING; 166079697Snon return rv; 166167468Snon} 166267468Snon 166367468Snon/************************************************************** 166467468Snon * allocate lun_info 166567468Snon **************************************************************/ 166667468Snonstatic struct lun_info * 166767468Snonscsi_low_alloc_li(ti, lun, alloc) 166867468Snon struct targ_info *ti; 166967468Snon int lun; 167067468Snon int alloc; 167167468Snon{ 167279697Snon struct scsi_low_softc *slp = ti->ti_sc; 167367468Snon struct lun_info *li; 167467468Snon 167567468Snon li = LIST_FIRST(&ti->ti_litab); 167667468Snon if (li != NULL) 167767468Snon { 167867468Snon if (li->li_lun == lun) 167967468Snon return li; 168067468Snon 168167468Snon while ((li = LIST_NEXT(li, lun_chain)) != NULL) 168267468Snon { 168367468Snon if (li->li_lun == lun) 168467468Snon { 168567468Snon LIST_REMOVE(li, lun_chain); 168667468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 168767468Snon return li; 168867468Snon } 168967468Snon } 169067468Snon } 169167468Snon 169267468Snon if (alloc == 0) 169367468Snon return li; 169467468Snon 169579697Snon li = SCSI_LOW_MALLOC(ti->ti_lunsize); 169667468Snon if (li == NULL) 1697106890Simp panic("no lun info mem"); 169867468Snon 169979697Snon SCSI_LOW_BZERO(li, ti->ti_lunsize); 170067468Snon li->li_lun = lun; 170167468Snon li->li_ti = ti; 170267468Snon 170379697Snon li->li_cfgflags = SCSI_LOW_SYNC | SCSI_LOW_LINK | SCSI_LOW_DISC | 170479697Snon SCSI_LOW_QTAG; 170579697Snon li->li_quirks = li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 170679697Snon li->li_flags_valid = SCSI_LOW_LUN_FLAGS_USER_VALID; 170779697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 170879697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 170979697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 171079697Snon 171179697Snon li->li_qtagbits = (u_int) -1; 171279697Snon 171379697Snon TAILQ_INIT(&li->li_discq); 171467468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 171567468Snon 171679697Snon /* host specific structure initialization per lun */ 171779697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 171879697Snon (*slp->sl_funcs->scsi_low_lun_init) 171979697Snon (slp, ti, li, SCSI_LOW_INFO_ALLOC); 172079697Snon scsi_low_calcf_lun(li); 172167468Snon return li; 172267468Snon} 172367468Snon 172467468Snon/************************************************************** 172567468Snon * allocate targ_info 172667468Snon **************************************************************/ 172767468Snonstatic struct targ_info * 172879697Snonscsi_low_alloc_ti(slp, targ) 172967468Snon struct scsi_low_softc *slp; 173079697Snon int targ; 173167468Snon{ 173267468Snon struct targ_info *ti; 173367468Snon 173471999Sphk if (TAILQ_FIRST(&slp->sl_titab) == NULL) 173567468Snon TAILQ_INIT(&slp->sl_titab); 173667468Snon 173779697Snon ti = SCSI_LOW_MALLOC(slp->sl_targsize); 173867468Snon if (ti == NULL) 1739106890Simp panic("%s short of memory", slp->sl_xname); 174067468Snon 174179697Snon SCSI_LOW_BZERO(ti, slp->sl_targsize); 174267468Snon ti->ti_id = targ; 174367468Snon ti->ti_sc = slp; 174467468Snon 174567468Snon slp->sl_ti[targ] = ti; 174667468Snon TAILQ_INSERT_TAIL(&slp->sl_titab, ti, ti_chain); 174767468Snon LIST_INIT(&ti->ti_litab); 174867468Snon 174979697Snon ti->ti_quirks = ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 175079697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 175179697Snon ti->ti_flags_valid = SCSI_LOW_TARG_FLAGS_USER_VALID; 175279697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 175379697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 175479697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 175573025Snon 175679697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 175779697Snon { 175879697Snon (*slp->sl_funcs->scsi_low_targ_init) 175979697Snon (slp, ti, SCSI_LOW_INFO_ALLOC); 176079697Snon } 176179697Snon scsi_low_calcf_target(ti); 176267468Snon return ti; 176367468Snon} 176467468Snon 176567468Snonstatic void 176667468Snonscsi_low_free_ti(slp) 176767468Snon struct scsi_low_softc *slp; 176867468Snon{ 176967468Snon struct targ_info *ti, *tib; 177067468Snon struct lun_info *li, *nli; 177167468Snon 177271999Sphk for (ti = TAILQ_FIRST(&slp->sl_titab); ti; ti = tib) 177367468Snon { 177467468Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; li = nli) 177567468Snon { 177679697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 177779697Snon { 177879697Snon (*slp->sl_funcs->scsi_low_lun_init) 177979697Snon (slp, ti, li, SCSI_LOW_INFO_DEALLOC); 178079697Snon } 178167468Snon nli = LIST_NEXT(li, lun_chain); 178279697Snon SCSI_LOW_FREE(li); 178367468Snon } 178479697Snon 178579697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 178679697Snon { 178779697Snon (*slp->sl_funcs->scsi_low_targ_init) 178879697Snon (slp, ti, SCSI_LOW_INFO_DEALLOC); 178979697Snon } 179079697Snon tib = TAILQ_NEXT(ti, ti_chain); 179179697Snon SCSI_LOW_FREE(ti); 179267468Snon } 179367468Snon} 179467468Snon 179567468Snon/************************************************************** 179667468Snon * timeout 179767468Snon **************************************************************/ 179867468Snonvoid 179979697Snonscsi_low_bus_idle(slp) 180079697Snon struct scsi_low_softc *slp; 180179697Snon{ 180279697Snon 180379697Snon slp->sl_retry_sel = 0; 180479697Snon if (slp->sl_Tnexus == NULL) 180579697Snon scsi_low_start(slp); 180679697Snon} 180779697Snon 180879697Snonstatic void 180967468Snonscsi_low_timeout(arg) 181067468Snon void *arg; 181167468Snon{ 181267468Snon struct scsi_low_softc *slp = arg; 181379697Snon int s; 181479697Snon 181579697Snon s = SCSI_LOW_SPLSCSI(); 181679697Snon (void) scsi_low_timeout_check(slp); 181779697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 181879697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 181979697Snon splx(s); 182079697Snon} 182179697Snon 182279697Snonstatic int 182379697Snonscsi_low_timeout_check(slp) 182479697Snon struct scsi_low_softc *slp; 182579697Snon{ 182667468Snon struct targ_info *ti; 182779697Snon struct lun_info *li; 182867468Snon struct slccb *cb = NULL; /* XXX */ 182967468Snon 183079697Snon /* selection restart */ 183179697Snon if (slp->sl_retry_sel != 0) 183267468Snon { 183379697Snon slp->sl_retry_sel = 0; 183479697Snon if (slp->sl_Tnexus != NULL) 183579697Snon goto step1; 183667468Snon 183779697Snon cb = TAILQ_FIRST(&slp->sl_start); 183879697Snon if (cb == NULL) 183979697Snon goto step1; 184079697Snon 184179697Snon if (cb->ccb_selrcnt >= SCSI_LOW_MAX_SELECTION_RETRY) 184267468Snon { 184379697Snon cb->ccb_flags |= CCB_NORETRY; 184479697Snon cb->ccb_error |= SELTIMEOUTIO; 184579697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1846106890Simp panic("%s: ccb not finished", slp->sl_xname); 184767468Snon } 184879697Snon 184979697Snon if (slp->sl_Tnexus == NULL) 185079697Snon scsi_low_start(slp); 185167468Snon } 185279697Snon 185379697Snon /* call hardware timeout */ 185479697Snonstep1: 185579697Snon if (slp->sl_funcs->scsi_low_timeout != NULL) 185667468Snon { 185779697Snon (*slp->sl_funcs->scsi_low_timeout) (slp); 185879697Snon } 185979697Snon 186079697Snon if (slp->sl_timeout_count ++ < 186179697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL * SCSI_LOW_TIMEOUT_HZ) 186279697Snon return 0; 186379697Snon 186479697Snon slp->sl_timeout_count = 0; 186579697Snon if (slp->sl_nio > 0) 186679697Snon { 186779697Snon if ((cb = slp->sl_Qnexus) != NULL) 186867468Snon { 186967468Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 187067468Snon if (cb->ccb_tc < 0) 187167468Snon goto bus_reset; 187267468Snon } 187379697Snon else if (slp->sl_disc == 0) 187467468Snon { 187579697Snon if ((cb = TAILQ_FIRST(&slp->sl_start)) == NULL) 187679697Snon return 0; 187767468Snon 187879697Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 187979697Snon if (cb->ccb_tc < 0) 188079697Snon goto bus_reset; 188179697Snon } 188279697Snon else for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 188379697Snon ti = TAILQ_NEXT(ti, ti_chain)) 188479697Snon { 188579697Snon if (ti->ti_disc == 0) 188679697Snon continue; 188767468Snon 188879697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 188979697Snon li = LIST_NEXT(li, lun_chain)) 189067468Snon { 189179697Snon for (cb = TAILQ_FIRST(&li->li_discq); 189279697Snon cb != NULL; 189379697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 189479697Snon { 189579697Snon cb->ccb_tc -= 189679697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 189779697Snon if (cb->ccb_tc < 0) 189879697Snon goto bus_reset; 189979697Snon } 190067468Snon } 190167468Snon } 190279697Snon 190367468Snon } 190479697Snon else if ((slp->sl_flags & HW_POWERCTRL) != 0) 190579697Snon { 190679697Snon if ((slp->sl_flags & (HW_POWDOWN | HW_RESUME)) != 0) 190779697Snon return 0; 190867468Snon 190979697Snon if (slp->sl_active != 0) 191079697Snon { 191179697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 191279697Snon slp->sl_active = 0; 191379697Snon return 0; 191479697Snon } 191567468Snon 191679697Snon slp->sl_powc --; 191779697Snon if (slp->sl_powc < 0) 191879697Snon { 191979697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 192079697Snon slp->sl_flags |= HW_POWDOWN; 192179697Snon (*slp->sl_funcs->scsi_low_power) 192279697Snon (slp, SCSI_LOW_POWDOWN); 192379697Snon } 192479697Snon } 192579697Snon return 0; 192667468Snon 192767468Snonbus_reset: 192867468Snon cb->ccb_error |= TIMEOUTIO; 192979697Snon printf("%s: slccb (0x%lx) timeout!\n", slp->sl_xname, (u_long) cb); 193067468Snon scsi_low_info(slp, NULL, "scsi bus hangup. try to recover."); 193167468Snon scsi_low_init(slp, SCSI_LOW_RESTART_HARD); 193267468Snon scsi_low_start(slp); 193379697Snon return ERESTART; 193467468Snon} 193567468Snon 193667468Snon 193779697Snonstatic int 193879697Snonscsi_low_abort_ccb(slp, cb) 193979697Snon struct scsi_low_softc *slp; 194079697Snon struct slccb *cb; 194179697Snon{ 194279697Snon struct targ_info *ti; 194379697Snon struct lun_info *li; 194479697Snon u_int msg; 194567468Snon 194679697Snon if (cb == NULL) 194779697Snon return EINVAL; 194879697Snon if ((cb->ccb_omsgoutflag & 194979697Snon (SCSI_LOW_MSG_ABORT | SCSI_LOW_MSG_ABORT_QTAG)) != 0) 195079697Snon return EBUSY; 195167468Snon 195279697Snon ti = cb->ti; 195379697Snon li = cb->li; 195479697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 195579697Snon msg = SCSI_LOW_MSG_ABORT; 195679697Snon else 195779697Snon msg = SCSI_LOW_MSG_ABORT_QTAG; 195867468Snon 195979697Snon cb->ccb_error |= ABORTIO; 196079697Snon cb->ccb_flags |= CCB_NORETRY; 196179697Snon scsi_low_ccb_message_assert(cb, msg); 196267468Snon 196379697Snon if (cb == slp->sl_Qnexus) 196479697Snon { 196579697Snon scsi_low_assert_msg(slp, ti, msg, 1); 196679697Snon } 196779697Snon else if ((cb->ccb_flags & CCB_DISCQ) != 0) 196879697Snon { 196979697Snon if (scsi_low_revoke_ccb(slp, cb, 0) == NULL) 1970106890Simp panic("%s: revoked ccb done", slp->sl_xname); 197167468Snon 197279697Snon cb->ccb_flags |= CCB_STARTQ; 197379697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 197467468Snon 197579697Snon if (slp->sl_Tnexus == NULL) 197679697Snon scsi_low_start(slp); 197779697Snon } 197879697Snon else 197979697Snon { 198079697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1981106890Simp panic("%s: revoked ccb retried", slp->sl_xname); 198279697Snon } 198379697Snon return 0; 198467468Snon} 198567468Snon 198679697Snon/************************************************************** 198779697Snon * Generic SCSI INTERFACE 198879697Snon **************************************************************/ 198967468Snonint 199079697Snonscsi_low_attach(slp, openings, ntargs, nluns, targsize, lunsize) 199167468Snon struct scsi_low_softc *slp; 199279697Snon int openings, ntargs, nluns, targsize, lunsize; 199367468Snon{ 199467468Snon struct targ_info *ti; 199567468Snon struct lun_info *li; 199679697Snon int s, i, nccb, rv; 199767468Snon 199879697Snon#ifdef SCSI_LOW_INTERFACE_XS 199979697Snon slp->sl_osdep_fp = &scsi_low_osdep_funcs_xs; 200079697Snon#endif /* SCSI_LOW_INTERFACE_XS */ 200179697Snon#ifdef SCSI_LOW_INTERFACE_CAM 200279697Snon slp->sl_osdep_fp = &scsi_low_osdep_funcs_cam; 200379697Snon#endif /* SCSI_LOW_INTERFACE_CAM */ 200479697Snon 200579697Snon if (slp->sl_osdep_fp == NULL) 2006106890Simp panic("scsi_low: interface not spcified"); 200779697Snon 200867468Snon if (ntargs > SCSI_LOW_NTARGETS) 200967468Snon { 201067468Snon printf("scsi_low: %d targets are too large\n", ntargs); 201167468Snon printf("change kernel options SCSI_LOW_NTARGETS"); 201279697Snon return EINVAL; 201367468Snon } 201467468Snon 201579697Snon if (openings <= 0) 201679697Snon slp->sl_openings = (SCSI_LOW_NCCB / ntargs); 201779697Snon else 201879697Snon slp->sl_openings = openings; 201979697Snon slp->sl_ntargs = ntargs; 202079697Snon slp->sl_nluns = nluns; 202179697Snon slp->sl_max_retry = SCSI_LOW_MAX_RETRY; 202267468Snon 202379697Snon if (lunsize < sizeof(struct lun_info)) 202479697Snon lunsize = sizeof(struct lun_info); 202579697Snon 202679697Snon if (targsize < sizeof(struct targ_info)) 202779697Snon targsize = sizeof(struct targ_info); 202879697Snon 202979697Snon slp->sl_targsize = targsize; 203067468Snon for (i = 0; i < ntargs; i ++) 203167468Snon { 203279697Snon ti = scsi_low_alloc_ti(slp, i); 203379697Snon ti->ti_lunsize = lunsize; 203467468Snon li = scsi_low_alloc_li(ti, 0, 1); 203567468Snon } 203667468Snon 203767468Snon /* initialize queue */ 203879697Snon nccb = openings * ntargs; 203967468Snon if (nccb >= SCSI_LOW_NCCB || nccb <= 0) 204067468Snon nccb = SCSI_LOW_NCCB; 204167468Snon scsi_low_init_ccbque(nccb); 204267468Snon TAILQ_INIT(&slp->sl_start); 204367468Snon 204479697Snon /* call os depend attach */ 204579697Snon s = SCSI_LOW_SPLSCSI(); 204679697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_attach) (slp); 204779697Snon if (rv != 0) 204879697Snon { 204979697Snon splx(s); 205079697Snon printf("%s: scsi_low_attach: osdep attach failed\n", 205179697Snon slp->sl_xname); 205279697Snon return EINVAL; 205379697Snon } 205467468Snon 205579697Snon /* check hardware */ 205679697Snon SCSI_LOW_DELAY(1000); /* wait for 1ms */ 205779697Snon if (scsi_low_init(slp, SCSI_LOW_RESTART_HARD) != 0) 205879697Snon { 205979697Snon splx(s); 206079697Snon printf("%s: scsi_low_attach: initialization failed\n", 206179697Snon slp->sl_xname); 206279697Snon return EINVAL; 206379697Snon } 206467468Snon 206567468Snon /* start watch dog */ 206679697Snon slp->sl_timeout_count = 0; 206779697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 206879697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 206979697Snon LIST_INSERT_HEAD(&sl_tab, slp, sl_chain); 207067468Snon 207179697Snon /* fake call */ 207279697Snon scsi_low_abort_ccb(slp, scsi_low_find_ccb(slp, 0, 0, NULL)); 207367468Snon 207479697Snon#ifdef SCSI_LOW_START_UP_CHECK 207579697Snon /* probing devices */ 207679697Snon scsi_low_start_up(slp); 207779697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 207867468Snon 207979697Snon /* call os depend attach done*/ 208079697Snon (*slp->sl_osdep_fp->scsi_low_osdep_world_start) (slp); 208179697Snon splx(s); 208279697Snon return 0; 208367468Snon} 208467468Snon 208567468Snonint 208667468Snonscsi_low_dettach(slp) 208767468Snon struct scsi_low_softc *slp; 208867468Snon{ 208979697Snon int s, rv; 209067468Snon 209179697Snon s = SCSI_LOW_SPLSCSI(); 209279697Snon if (scsi_low_is_busy(slp) != 0) 209379697Snon { 209479697Snon splx(s); 209567468Snon return EBUSY; 209679697Snon } 209767468Snon 209879697Snon scsi_low_deactivate(slp); 209967468Snon 210079697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_dettach) (slp); 210179697Snon if (rv != 0) 210279697Snon { 210379697Snon splx(s); 210479697Snon return EBUSY; 210579697Snon } 210667468Snon 210767468Snon scsi_low_free_ti(slp); 210879697Snon LIST_REMOVE(slp, sl_chain); 210979697Snon splx(s); 211067468Snon return 0; 211167468Snon} 211267468Snon 211379697Snon/************************************************************** 211479697Snon * Generic enqueue 211579697Snon **************************************************************/ 211679697Snonstatic int 211779697Snonscsi_low_enqueue(slp, ti, li, cb, flags, msg) 211879697Snon struct scsi_low_softc *slp; 211967468Snon struct targ_info *ti; 212067468Snon struct lun_info *li; 212167468Snon struct slccb *cb; 212279697Snon u_int flags, msg; 212379697Snon{ 212467468Snon 212579697Snon cb->ti = ti; 212679697Snon cb->li = li; 212767468Snon 212879697Snon scsi_low_ccb_message_assert(cb, msg); 212967468Snon 213079697Snon cb->ccb_otag = cb->ccb_tag = SCSI_LOW_UNKTAG; 213179697Snon scsi_low_alloc_qtag(cb); 213267468Snon 213379697Snon cb->ccb_flags = flags | CCB_STARTQ; 213479697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 213579697Snon cb->ccb_error |= PENDINGIO; 213679697Snon 213779697Snon if ((flags & CCB_URGENT) != 0) 213879697Snon { 213979697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 214079697Snon } 214179697Snon else 214279697Snon { 214367468Snon TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain); 214479697Snon } 214567468Snon 214679697Snon slp->sl_nio ++; 214767468Snon 214879697Snon if (slp->sl_Tnexus == NULL) 214979697Snon scsi_low_start(slp); 215079697Snon return 0; 215179697Snon} 215267468Snon 215379697Snonstatic int 215479697Snonscsi_low_message_enqueue(slp, ti, li, flags) 215579697Snon struct scsi_low_softc *slp; 215679697Snon struct targ_info *ti; 215779697Snon struct lun_info *li; 215879697Snon u_int flags; 215979697Snon{ 216079697Snon struct slccb *cb; 216179697Snon u_int tmsgflags; 216267468Snon 216379697Snon tmsgflags = ti->ti_setup_msg; 216479697Snon ti->ti_setup_msg = 0; 216567468Snon 216679697Snon flags |= CCB_NORETRY; 216779697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 216879697Snon return ENOMEM; 216967468Snon 217079697Snon cb->osdep = NULL; 217179697Snon cb->bp = NULL; 217279697Snon scsi_low_enqueue(slp, ti, li, cb, flags, tmsgflags); 217379697Snon return 0; 217479697Snon} 217567468Snon 217679697Snon/************************************************************** 217779697Snon * Generic Start & Done 217879697Snon **************************************************************/ 217979697Snon#define SLSC_MODE_SENSE_SHORT 0x1a 218079697Snonstatic u_int8_t ss_cmd[6] = {START_STOP, 0, 0, 0, SSS_START, 0}; 218179697Snonstatic u_int8_t sms_cmd[6] = {SLSC_MODE_SENSE_SHORT, 0x08, 0x0a, 0, 218279697Snon sizeof(struct scsi_low_mode_sense_data), 0}; 218379697Snonstatic u_int8_t inq_cmd[6] = {INQUIRY, 0, 0, 0, 218479697Snon sizeof(struct scsi_low_inq_data), 0}; 218579697Snonstatic u_int8_t unit_ready_cmd[6]; 218692770Salfredstatic int scsi_low_setup_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 218792770Salfredstatic int scsi_low_sense_abort_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 218892770Salfredstatic int scsi_low_resume(struct scsi_low_softc *); 218979697Snon 219079697Snonstatic void 219179697Snonscsi_low_unit_ready_cmd(cb) 219279697Snon struct slccb *cb; 219379697Snon{ 219479697Snon 219579697Snon cb->ccb_scp.scp_cmd = unit_ready_cmd; 219679697Snon cb->ccb_scp.scp_cmdlen = sizeof(unit_ready_cmd); 219779697Snon cb->ccb_scp.scp_datalen = 0; 219879697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 219979697Snon cb->ccb_tcmax = 15; 220067468Snon} 220179697Snon 220267468Snonstatic int 220379697Snonscsi_low_sense_abort_start(slp, ti, li, cb) 220479697Snon struct scsi_low_softc *slp; 220567468Snon struct targ_info *ti; 220679697Snon struct lun_info *li; 220767468Snon struct slccb *cb; 220879697Snon{ 220967468Snon 221079697Snon cb->ccb_scp.scp_cmdlen = 6; 221179697Snon SCSI_LOW_BZERO(cb->ccb_scsi_cmd, cb->ccb_scp.scp_cmdlen); 221279697Snon cb->ccb_scsi_cmd[0] = REQUEST_SENSE; 221379697Snon cb->ccb_scsi_cmd[4] = sizeof(cb->ccb_sense); 221479697Snon cb->ccb_scp.scp_cmd = cb->ccb_scsi_cmd; 221579697Snon cb->ccb_scp.scp_data = (u_int8_t *) &cb->ccb_sense; 221679697Snon cb->ccb_scp.scp_datalen = sizeof(cb->ccb_sense); 221779697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 221879697Snon cb->ccb_tcmax = 15; 221979697Snon scsi_low_ccb_message_clear(cb); 222079697Snon if ((cb->ccb_flags & CCB_CLEARQ) != 0) 222167468Snon { 222279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 222367468Snon } 222479697Snon else 222579697Snon { 222679697Snon SCSI_LOW_BZERO(&cb->ccb_sense, sizeof(cb->ccb_sense)); 222779697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 222879697Snon scsi_low_assert_msg(slp, ti, ti->ti_setup_msg_done, 0); 222979697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 223079697Snon } 223167468Snon 223279697Snon return SCSI_LOW_START_NO_QTAG; 223379697Snon} 223467468Snon 223579697Snonstatic int 223679697Snonscsi_low_setup_start(slp, ti, li, cb) 223779697Snon struct scsi_low_softc *slp; 223879697Snon struct targ_info *ti; 223979697Snon struct lun_info *li; 224079697Snon struct slccb *cb; 224179697Snon{ 224267468Snon 224379697Snon switch(li->li_state) 224479697Snon { 224579697Snon case SCSI_LOW_LUN_SLEEP: 224679697Snon scsi_low_unit_ready_cmd(cb); 224779697Snon break; 224867468Snon 224979697Snon case SCSI_LOW_LUN_START: 225079697Snon cb->ccb_scp.scp_cmd = ss_cmd; 225179697Snon cb->ccb_scp.scp_cmdlen = sizeof(ss_cmd); 225279697Snon cb->ccb_scp.scp_datalen = 0; 225379697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 225479697Snon cb->ccb_tcmax = 30; 225579697Snon break; 225667468Snon 225779697Snon case SCSI_LOW_LUN_INQ: 225879697Snon cb->ccb_scp.scp_cmd = inq_cmd; 225979697Snon cb->ccb_scp.scp_cmdlen = sizeof(inq_cmd); 226079697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_inq; 226179697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_inq); 226279697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 226379697Snon cb->ccb_tcmax = 15; 226479697Snon break; 226567468Snon 226679697Snon case SCSI_LOW_LUN_MODEQ: 226779697Snon cb->ccb_scp.scp_cmd = sms_cmd; 226879697Snon cb->ccb_scp.scp_cmdlen = sizeof(sms_cmd); 226979697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_sms; 227079697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_sms); 227179697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 227279697Snon cb->ccb_tcmax = 15; 227379697Snon return SCSI_LOW_START_QTAG; 227467468Snon 227579697Snon default: 2276106890Simp panic("%s: no setup phase", slp->sl_xname); 227767468Snon } 227867468Snon 227979697Snon return SCSI_LOW_START_NO_QTAG; 228067468Snon} 228167468Snon 228279697Snonstatic int 228379697Snonscsi_low_resume(slp) 228479697Snon struct scsi_low_softc *slp; 228567468Snon{ 228667468Snon 228779697Snon if (slp->sl_flags & HW_RESUME) 228879697Snon return EJUSTRETURN; 228979697Snon slp->sl_flags &= ~HW_POWDOWN; 229079697Snon if (slp->sl_funcs->scsi_low_power != NULL) 229179697Snon { 229279697Snon slp->sl_flags |= HW_RESUME; 229379697Snon slp->sl_rstep = 0; 229479697Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 229579697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 229679697Snon (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE, 229779697Snon SCSI_LOW_TIMEOUT_START); 229879697Snon return EJUSTRETURN; 229979697Snon } 230079697Snon return 0; 230167468Snon} 230267468Snon 230367468Snonstatic void 230467468Snonscsi_low_start(slp) 230567468Snon struct scsi_low_softc *slp; 230667468Snon{ 230767468Snon struct targ_info *ti; 230867468Snon struct lun_info *li; 230967468Snon struct slccb *cb; 231067468Snon int rv; 231167468Snon 231279697Snon /* check hardware exists or under initializations ? */ 231379697Snon if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0) 231467468Snon return; 231567468Snon 231667468Snon /* check hardware power up ? */ 231767468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 231867468Snon { 231967468Snon slp->sl_active ++; 232067468Snon if (slp->sl_flags & (HW_POWDOWN | HW_RESUME)) 232167468Snon { 232279697Snon if (scsi_low_resume(slp) == EJUSTRETURN) 232367468Snon return; 232467468Snon } 232567468Snon } 232667468Snon 232767468Snon /* setup nexus */ 232867468Snon#ifdef SCSI_LOW_DIAGNOSTIC 232979697Snon if (slp->sl_Tnexus || slp->sl_Lnexus || slp->sl_Qnexus) 233067468Snon { 233167468Snon scsi_low_info(slp, NULL, "NEXUS INCOSISTENT"); 2332106890Simp panic("%s: inconsistent", slp->sl_xname); 233367468Snon } 233467468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 233567468Snon 233679697Snon for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL; 233779697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 233867468Snon { 233967468Snon li = cb->li; 234079697Snon 234179697Snon if (li->li_disc == 0) 234279697Snon { 234367468Snon goto scsi_low_cmd_start; 234479697Snon } 234579697Snon else if (li->li_nqio > 0) 234679697Snon { 234779697Snon if (li->li_nqio < li->li_maxnqio || 234879697Snon (cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 234979697Snon goto scsi_low_cmd_start; 235079697Snon } 235167468Snon } 235267468Snon return; 235367468Snon 235467468Snonscsi_low_cmd_start: 235579697Snon cb->ccb_flags &= ~CCB_STARTQ; 235679697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 235779697Snon ti = cb->ti; 235867468Snon 235967468Snon /* clear all error flag bits (for restart) */ 236067468Snon cb->ccb_error = 0; 236179697Snon cb->ccb_datalen = -1; 236279697Snon cb->ccb_scp.scp_status = ST_UNKNOWN; 236367468Snon 236467468Snon /* setup nexus pointer */ 236579697Snon slp->sl_Qnexus = cb; 236679697Snon slp->sl_Lnexus = li; 236779697Snon slp->sl_Tnexus = ti; 236867468Snon 236967468Snon /* initialize msgsys */ 237067468Snon scsi_low_init_msgsys(slp, ti); 237167468Snon 237279697Snon /* exec cmd */ 237379697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 237467468Snon { 237579697Snon /* CA state or forced abort */ 237679697Snon rv = scsi_low_sense_abort_start(slp, ti, li, cb); 237767468Snon } 237879697Snon else if (li->li_state >= SCSI_LOW_LUN_OK) 237967468Snon { 238079697Snon cb->ccb_flags &= ~CCB_INTERNAL; 238179697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, cb); 238279697Snon if (cb->ccb_msgoutflag != 0) 238379697Snon { 238479697Snon scsi_low_ccb_message_exec(slp, cb); 238579697Snon } 238667468Snon } 238779697Snon else 238867468Snon { 238979697Snon cb->ccb_flags |= CCB_INTERNAL; 239079697Snon rv = scsi_low_setup_start(slp, ti, li, cb); 239179697Snon } 239267468Snon 239379697Snon /* allocate qtag */ 239479697Snon#define SCSI_LOW_QTAG_OK (SCSI_LOW_QTAG | SCSI_LOW_DISC) 239567468Snon 239679697Snon if (rv == SCSI_LOW_START_QTAG && 239779697Snon (li->li_flags & SCSI_LOW_QTAG_OK) == SCSI_LOW_QTAG_OK && 239879697Snon li->li_maxnqio > 0) 239979697Snon { 240079697Snon u_int qmsg; 240167468Snon 240279697Snon scsi_low_activate_qtag(cb); 240379697Snon if ((scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 240479697Snon SCSI_LOW_CMD_ORDERED_QTAG) != 0) 240579697Snon qmsg = SCSI_LOW_MSG_ORDERED_QTAG; 240679697Snon else if ((cb->ccb_flags & CCB_URGENT) != 0) 240779697Snon qmsg = SCSI_LOW_MSG_HEAD_QTAG; 240879697Snon else 240979697Snon qmsg = SCSI_LOW_MSG_SIMPLE_QTAG; 241079697Snon scsi_low_assert_msg(slp, ti, qmsg, 0); 241167468Snon } 241267468Snon 241367468Snon /* timeout */ 241467468Snon if (cb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 241567468Snon cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 241667468Snon cb->ccb_tc = cb->ccb_tcmax; 241767468Snon 241867468Snon /* setup saved scsi data pointer */ 241967468Snon cb->ccb_sscp = cb->ccb_scp; 242067468Snon 242167468Snon /* setup current scsi pointer */ 242267468Snon slp->sl_scp = cb->ccb_sscp; 242367468Snon slp->sl_error = cb->ccb_error; 242467468Snon 242579697Snon /* assert always an identify msg */ 242679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); 242779697Snon 242879697Snon /* debug section */ 242979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 243079697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 243179697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 243279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 243379697Snon 243467468Snon /* selection start */ 243579697Snon slp->sl_selid = cb; 243667468Snon rv = ((*slp->sl_funcs->scsi_low_start_bus) (slp, cb)); 243767468Snon if (rv == SCSI_LOW_START_OK) 243867468Snon { 243967468Snon#ifdef SCSI_LOW_STATICS 244067468Snon scsi_low_statics.nexus_win ++; 244167468Snon#endif /* SCSI_LOW_STATICS */ 244267468Snon return; 244367468Snon } 244467468Snon 244579697Snon scsi_low_arbit_fail(slp, cb); 244667468Snon#ifdef SCSI_LOW_STATICS 244767468Snon scsi_low_statics.nexus_fail ++; 244867468Snon#endif /* SCSI_LOW_STATICS */ 244967468Snon} 245067468Snon 245167468Snonvoid 245279697Snonscsi_low_arbit_fail(slp, cb) 245367468Snon struct scsi_low_softc *slp; 245479697Snon struct slccb *cb; 245579697Snon{ 245679697Snon struct targ_info *ti = cb->ti; 245779697Snon 245879697Snon scsi_low_deactivate_qtag(cb); 245979697Snon scsi_low_ccb_message_retry(cb); 246079697Snon cb->ccb_flags |= CCB_STARTQ; 246179697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 246279697Snon 246379697Snon scsi_low_bus_release(slp, ti); 246479697Snon 246579697Snon cb->ccb_selrcnt ++; 246679697Snon if (slp->sl_disc == 0) 246779697Snon { 246879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 246979697Snon printf("%s: try selection again\n", slp->sl_xname); 247079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 247179697Snon slp->sl_retry_sel = 1; 247279697Snon } 247379697Snon} 247479697Snon 247579697Snonstatic void 247679697Snonscsi_low_bus_release(slp, ti) 247779697Snon struct scsi_low_softc *slp; 247867468Snon struct targ_info *ti; 247967468Snon{ 248067468Snon 248179697Snon if (ti->ti_disc > 0) 248279697Snon { 248379697Snon SCSI_LOW_SETUP_PHASE(ti, PH_DISC); 248479697Snon } 248579697Snon else 248679697Snon { 248779697Snon SCSI_LOW_SETUP_PHASE(ti, PH_NULL); 248879697Snon } 248979697Snon 249067468Snon /* clear all nexus pointer */ 249179697Snon slp->sl_Qnexus = NULL; 249279697Snon slp->sl_Lnexus = NULL; 249379697Snon slp->sl_Tnexus = NULL; 249467468Snon 249567468Snon /* clear selection assert */ 249667468Snon slp->sl_selid = NULL; 249767468Snon 249867468Snon /* clear nexus data */ 249967468Snon slp->sl_scp.scp_direction = SCSI_LOW_RWUNK; 250079697Snon 250179697Snon /* clear phase change counter */ 250279697Snon slp->sl_ph_count = 0; 250367468Snon} 250467468Snon 250567468Snonstatic int 250679697Snonscsi_low_setup_done(slp, cb) 250767468Snon struct scsi_low_softc *slp; 250867468Snon struct slccb *cb; 250967468Snon{ 251067468Snon struct targ_info *ti; 251167468Snon struct lun_info *li; 251267468Snon 251367468Snon ti = cb->ti; 251467468Snon li = cb->li; 251579697Snon 251679697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 251767468Snon { 251879697Snon cb->ccb_error |= ABORTIO; 251979697Snon return SCSI_LOW_DONE_COMPLETE; 252079697Snon } 252179697Snon 252279697Snon /* XXX: special huck for selection timeout */ 252379697Snon if (li->li_state == SCSI_LOW_LUN_SLEEP && 252479697Snon (cb->ccb_error & SELTIMEOUTIO) != 0) 252579697Snon { 252679697Snon cb->ccb_error |= ABORTIO; 252779697Snon return SCSI_LOW_DONE_COMPLETE; 252879697Snon } 252979697Snon 253079697Snon switch(li->li_state) 253179697Snon { 253279697Snon case SCSI_LOW_LUN_INQ: 253379697Snon if (cb->ccb_error != 0) 253467468Snon { 253579697Snon li->li_diskflags &= 253679697Snon ~(SCSI_LOW_DISK_LINK | SCSI_LOW_DISK_QTAG); 253779697Snon if (li->li_lun > 0) 253879697Snon goto resume; 253979697Snon ti->ti_diskflags &= 254079697Snon ~(SCSI_LOW_DISK_SYNC | SCSI_LOW_DISK_WIDE); 254167468Snon } 254279697Snon else if ((li->li_inq.sd_version & 7) >= 2 || 254379697Snon (li->li_inq.sd_len >= 4)) 254467468Snon { 254579697Snon if ((li->li_inq.sd_support & 0x2) == 0) 254679697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 254779697Snon if ((li->li_inq.sd_support & 0x8) == 0) 254879697Snon li->li_diskflags &= ~SCSI_LOW_DISK_LINK; 254979697Snon if (li->li_lun > 0) 255079697Snon goto resume; 255179697Snon if ((li->li_inq.sd_support & 0x10) == 0) 255279697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_SYNC; 255379697Snon if ((li->li_inq.sd_support & 0x20) == 0) 255479697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_16; 255579697Snon if ((li->li_inq.sd_support & 0x40) == 0) 255679697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_32; 255779697Snon } 255879697Snon else 255979697Snon { 256079697Snon li->li_diskflags &= 256179697Snon ~(SCSI_LOW_DISK_QTAG | SCSI_LOW_DISK_LINK); 256279697Snon if (li->li_lun > 0) 256379697Snon goto resume; 256479697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE; 256579697Snon } 256679697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_DISK_VALID; 256779697Snonresume: 256879697Snon scsi_low_calcf_target(ti); 256979697Snon scsi_low_calcf_lun(li); 257079697Snon break; 257179697Snon 257279697Snon case SCSI_LOW_LUN_MODEQ: 257379697Snon if (cb->ccb_error != 0) 257479697Snon { 257579697Snon if (cb->ccb_error & SENSEIO) 257667468Snon { 257779697Snon#ifdef SCSI_LOW_DEBUG 257879697Snon if (scsi_low_debug & SCSI_LOW_DEBUG_SENSE) 257979697Snon { 2580226067Sken int error_code, sense_key, asc, ascq; 2581226067Sken 2582226067Sken scsi_extract_sense(&cb->ccb_sense, 2583226067Sken &error_code, 2584226067Sken &sense_key, 2585226067Sken &asc, 2586226067Sken &ascq); 2587226067Sken printf("SENSE: [%x][%x][%x][%x]\n", 2588226067Sken error_code, sense_key, asc, 2589226067Sken ascq); 259079697Snon } 259179697Snon#endif /* SCSI_LOW_DEBUG */ 259267468Snon } 259379697Snon else 259479697Snon { 259579697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 259679697Snon } 259779697Snon } 259879697Snon else if ((li->li_sms.sms_cmp.cmp_page & 0x3f) == 0x0a) 259979697Snon { 260079697Snon if (li->li_sms.sms_cmp.cmp_qc & 0x02) 260179697Snon li->li_qflags |= SCSI_LOW_QFLAG_CA_QCLEAR; 260279697Snon else 260379697Snon li->li_qflags &= ~SCSI_LOW_QFLAG_CA_QCLEAR; 260479697Snon if ((li->li_sms.sms_cmp.cmp_qc & 0x01) != 0) 260579697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 260679697Snon } 260779697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_DISK_VALID; 260879697Snon scsi_low_calcf_lun(li); 260979697Snon break; 261067468Snon 261179697Snon default: 261279697Snon break; 261379697Snon } 261479697Snon 261579697Snon li->li_state ++; 261679697Snon if (li->li_state == SCSI_LOW_LUN_OK) 261779697Snon { 261879697Snon scsi_low_calcf_target(ti); 261979697Snon scsi_low_calcf_lun(li); 262079697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID && 262179697Snon (slp->sl_show_result & SHOW_CALCF_RES) != 0) 262279697Snon { 262379697Snon scsi_low_calcf_show(li); 262479697Snon } 262579697Snon } 262679697Snon 262779697Snon cb->ccb_rcnt --; 262879697Snon return SCSI_LOW_DONE_RETRY; 262979697Snon} 263079697Snon 263179697Snonstatic int 263279697Snonscsi_low_done(slp, cb) 263379697Snon struct scsi_low_softc *slp; 263479697Snon struct slccb *cb; 263579697Snon{ 263679697Snon int rv; 263779697Snon 263879697Snon if (cb->ccb_error == 0) 263979697Snon { 264079697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 264179697Snon { 264279697Snon#ifdef SCSI_LOW_QCLEAR_AFTER_CA 264379697Snon /* XXX: 264479697Snon * SCSI-2 draft suggests 264579697Snon * page 0x0a QErr bit determins if 264679697Snon * the target aborts or continues 264779697Snon * the queueing io's after CA state resolved. 264879697Snon * However many targets seem not to support 264979697Snon * the page 0x0a. Thus we should manually clear the 265079697Snon * queuing io's after CA state. 265179697Snon */ 265279697Snon if ((cb->ccb_flags & CCB_CLEARQ) == 0) 265367468Snon { 265479697Snon cb->ccb_rcnt --; 265579697Snon cb->ccb_flags |= CCB_CLEARQ; 265679697Snon goto retry; 265779697Snon } 265879697Snon#endif /* SCSI_LOW_QCLEAR_AFTER_CA */ 265979697Snon 266079697Snon if ((cb->ccb_flags & CCB_SENSE) != 0) 266179697Snon cb->ccb_error |= (SENSEIO | ABORTIO); 266279697Snon cb->ccb_flags &= ~(CCB_SENSE | CCB_CLEARQ); 266379697Snon } 266479697Snon else switch (cb->ccb_sscp.scp_status) 266579697Snon { 266679697Snon case ST_GOOD: 266779697Snon case ST_MET: 266879697Snon case ST_INTERGOOD: 266979697Snon case ST_INTERMET: 267079697Snon if (cb->ccb_datalen == 0 || 267179697Snon cb->ccb_scp.scp_datalen == 0) 267267468Snon break; 267367468Snon 267479697Snon if (cb->ccb_scp.scp_cmdlen > 0 && 267579697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 267679697Snon SCSI_LOW_CMD_RESIDUAL_CHK) == 0) 267779697Snon break; 267879697Snon 267967468Snon cb->ccb_error |= PDMAERR; 268067468Snon break; 268167468Snon 268279697Snon case ST_BUSY: 268379697Snon case ST_QUEFULL: 268479697Snon cb->ccb_error |= (BUSYERR | STATERR); 268579697Snon break; 268679697Snon 268779697Snon case ST_CONFLICT: 268879697Snon cb->ccb_error |= (STATERR | ABORTIO); 268979697Snon break; 269079697Snon 269167468Snon case ST_CHKCOND: 269279697Snon case ST_CMDTERM: 269379697Snon if (cb->ccb_flags & (CCB_AUTOSENSE | CCB_INTERNAL)) 269479697Snon { 269579697Snon cb->ccb_rcnt --; 269673025Snon cb->ccb_flags |= CCB_SENSE; 269773025Snon goto retry; 269873025Snon } 269979697Snon cb->ccb_error |= (UACAERR | STATERR | ABORTIO); 270073025Snon break; 270167468Snon 270279697Snon case ST_UNKNOWN: 270367468Snon default: 270467468Snon cb->ccb_error |= FATALIO; 270567468Snon break; 270667468Snon } 270767468Snon } 270867468Snon else 270967468Snon { 271079697Snon if (cb->ccb_flags & CCB_SENSE) 271167468Snon { 271279697Snon cb->ccb_error |= (SENSEERR | ABORTIO); 271367468Snon } 271479697Snon cb->ccb_flags &= ~(CCB_CLEARQ | CCB_SENSE); 271579697Snon } 271667468Snon 271779697Snon /* internal ccb */ 271879697Snon if ((cb->ccb_flags & CCB_INTERNAL) != 0) 271979697Snon { 272079697Snon if (scsi_low_setup_done(slp, cb) == SCSI_LOW_DONE_RETRY) 272179697Snon goto retry; 272267468Snon } 272367468Snon 272479697Snon /* check a ccb msgout flag */ 272579697Snon if (cb->ccb_omsgoutflag != 0) 272667468Snon { 272779697Snon#define SCSI_LOW_MSG_ABORT_OK (SCSI_LOW_MSG_ABORT | \ 272879697Snon SCSI_LOW_MSG_ABORT_QTAG | \ 272979697Snon SCSI_LOW_MSG_CLEAR_QTAG | \ 273079697Snon SCSI_LOW_MSG_TERMIO) 273179697Snon 273279697Snon if ((cb->ccb_omsgoutflag & SCSI_LOW_MSG_ABORT_OK) != 0) 273367468Snon { 273479697Snon cb->ccb_error |= ABORTIO; 273567468Snon } 273667468Snon } 273767468Snon 273879697Snon /* call OS depend done */ 273979697Snon if (cb->osdep != NULL) 274067468Snon { 274179697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_done) (slp, cb); 274279697Snon if (rv == EJUSTRETURN) 274379697Snon goto retry; 274467468Snon } 274579697Snon else if (cb->ccb_error != 0) 274667468Snon { 274779697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 274879697Snon cb->ccb_error |= ABORTIO; 274979697Snon 275079697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 275179697Snon (cb->ccb_error & ABORTIO) == 0) 275267468Snon goto retry; 275367468Snon } 275479697Snon 275579697Snon /* free our target */ 275679697Snon#ifdef SCSI_LOW_DEBUG 275779697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 275867468Snon { 275979697Snon printf(">> SCSI_LOW_DONE_COMPLETE ===============\n"); 276079697Snon scsi_low_print(slp, NULL); 276167468Snon } 276279697Snon#endif /* SCSI_LOW_DEBUG */ 276367468Snon 276479697Snon scsi_low_deactivate_qtag(cb); 276579697Snon scsi_low_dealloc_qtag(cb); 276667468Snon scsi_low_free_ccb(cb); 276779697Snon slp->sl_nio --; 276867468Snon return SCSI_LOW_DONE_COMPLETE; 276967468Snon 277067468Snonretry: 277179697Snon#ifdef SCSI_LOW_DEBUG 277279697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 277367468Snon { 277479697Snon printf("** SCSI_LOW_DONE_RETRY ===============\n"); 277579697Snon scsi_low_print(slp, NULL); 277667468Snon } 277779697Snon#endif /* SCSI_LOW_DEBUG */ 277879697Snon 277979697Snon cb->ccb_rcnt ++; 278079697Snon scsi_low_deactivate_qtag(cb); 278179697Snon scsi_low_ccb_message_retry(cb); 278267468Snon return SCSI_LOW_DONE_RETRY; 278367468Snon} 278467468Snon 278567468Snon/************************************************************** 278667468Snon * Reset 278767468Snon **************************************************************/ 278867468Snonstatic void 278979697Snonscsi_low_reset_nexus_target(slp, ti, fdone) 279079697Snon struct scsi_low_softc *slp; 279179697Snon struct targ_info *ti; 279279697Snon int fdone; 279367468Snon{ 279479697Snon struct lun_info *li; 279567468Snon 279679697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 279779697Snon li = LIST_NEXT(li, lun_chain)) 279879697Snon { 279979697Snon scsi_low_reset_nexus_lun(slp, li, fdone); 280079697Snon li->li_state = SCSI_LOW_LUN_SLEEP; 280179697Snon li->li_maxnqio = 0; 280279697Snon } 280379697Snon 280479697Snon ti->ti_disc = 0; 280579697Snon ti->ti_setup_msg = 0; 280679697Snon ti->ti_setup_msg_done = 0; 280779697Snon 280879697Snon ti->ti_osynch.offset = ti->ti_osynch.period = 0; 280979697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 281079697Snon 281179697Snon ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 281279697Snon ti->ti_flags_valid &= ~SCSI_LOW_TARG_FLAGS_DISK_VALID; 281379697Snon 281479697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 281579697Snon { 281679697Snon ((*slp->sl_funcs->scsi_low_targ_init) 281779697Snon (slp, ti, SCSI_LOW_INFO_REVOKE)); 281879697Snon } 281979697Snon scsi_low_calcf_target(ti); 282079697Snon 282179697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 282279697Snon li = LIST_NEXT(li, lun_chain)) 282379697Snon { 282479697Snon li->li_flags = 0; 282579697Snon 282679697Snon li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 282779697Snon li->li_flags_valid &= ~SCSI_LOW_LUN_FLAGS_DISK_VALID; 282879697Snon 282979697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 283079697Snon { 283179697Snon ((*slp->sl_funcs->scsi_low_lun_init) 283279697Snon (slp, ti, li, SCSI_LOW_INFO_REVOKE)); 283379697Snon } 283479697Snon scsi_low_calcf_lun(li); 283579697Snon } 283667468Snon} 283767468Snon 283867468Snonstatic void 283967468Snonscsi_low_reset_nexus(slp, fdone) 284067468Snon struct scsi_low_softc *slp; 284167468Snon int fdone; 284267468Snon{ 284367468Snon struct targ_info *ti; 284479697Snon struct slccb *cb, *topcb; 284567468Snon 284679697Snon if ((cb = slp->sl_Qnexus) != NULL) 284767468Snon { 284879697Snon topcb = scsi_low_revoke_ccb(slp, cb, fdone); 284967468Snon } 285079697Snon else 285179697Snon { 285279697Snon topcb = NULL; 285379697Snon } 285467468Snon 285579697Snon for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 285679697Snon ti = TAILQ_NEXT(ti, ti_chain)) 285767468Snon { 285879697Snon scsi_low_reset_nexus_target(slp, ti, fdone); 285979697Snon scsi_low_bus_release(slp, ti); 286067468Snon scsi_low_init_msgsys(slp, ti); 286167468Snon } 286267468Snon 286379697Snon if (topcb != NULL) 286479697Snon { 286579697Snon topcb->ccb_flags |= CCB_STARTQ; 286679697Snon TAILQ_INSERT_HEAD(&slp->sl_start, topcb, ccb_chain); 286779697Snon } 286879697Snon 286979697Snon slp->sl_disc = 0; 287079697Snon slp->sl_retry_sel = 0; 287167468Snon slp->sl_flags &= ~HW_PDMASTART; 287267468Snon} 287367468Snon 287467468Snon/* misc */ 287567468Snonstatic int tw_pos; 287667468Snonstatic char tw_chars[] = "|/-\\"; 287779697Snon#define TWIDDLEWAIT 10000 287867468Snon 287967468Snonstatic void 288067468Snonscsi_low_twiddle_wait(void) 288167468Snon{ 288267468Snon 288367468Snon cnputc('\b'); 288467468Snon cnputc(tw_chars[tw_pos++]); 288567468Snon tw_pos %= (sizeof(tw_chars) - 1); 288679697Snon SCSI_LOW_DELAY(TWIDDLEWAIT); 288767468Snon} 288867468Snon 288967468Snonvoid 289067468Snonscsi_low_bus_reset(slp) 289167468Snon struct scsi_low_softc *slp; 289267468Snon{ 289367468Snon int i; 289467468Snon 289567468Snon (*slp->sl_funcs->scsi_low_bus_reset) (slp); 289667468Snon 289767468Snon printf("%s: try to reset scsi bus ", slp->sl_xname); 289867468Snon for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++) 289967468Snon scsi_low_twiddle_wait(); 290067468Snon cnputc('\b'); 290167468Snon printf("\n"); 290267468Snon} 290367468Snon 290467468Snonint 290567468Snonscsi_low_restart(slp, flags, s) 290667468Snon struct scsi_low_softc *slp; 290767468Snon int flags; 290867468Snon u_char *s; 290967468Snon{ 291067468Snon int error; 291167468Snon 291267468Snon if (s != NULL) 291367468Snon printf("%s: scsi bus restart. reason: %s\n", slp->sl_xname, s); 291467468Snon 291567468Snon if ((error = scsi_low_init(slp, flags)) != 0) 291667468Snon return error; 291767468Snon 291867468Snon scsi_low_start(slp); 291967468Snon return 0; 292067468Snon} 292167468Snon 292267468Snon/************************************************************** 292367468Snon * disconnect and reselect 292467468Snon **************************************************************/ 292567468Snon#define MSGCMD_LUN(msg) (msg & 0x07) 292667468Snon 292767468Snonstatic struct slccb * 292867468Snonscsi_low_establish_ccb(ti, li, tag) 292967468Snon struct targ_info *ti; 293067468Snon struct lun_info *li; 293167468Snon scsi_low_tag_t tag; 293267468Snon{ 293367468Snon struct scsi_low_softc *slp = ti->ti_sc; 293467468Snon struct slccb *cb; 293567468Snon 293679697Snon if (li == NULL) 293779697Snon return NULL; 293879697Snon 293979697Snon cb = TAILQ_FIRST(&li->li_discq); 294071999Sphk for ( ; cb != NULL; cb = TAILQ_NEXT(cb, ccb_chain)) 294179697Snon if (cb->ccb_tag == tag) 294267468Snon goto found; 294367468Snon return cb; 294467468Snon 294567468Snon /* 294667468Snon * establish our ccb nexus 294767468Snon */ 294867468Snonfound: 294979697Snon#ifdef SCSI_LOW_DEBUG 295079697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 295179697Snon { 295279697Snon printf("%s: nexus(0x%lx) abort check start\n", 295379697Snon slp->sl_xname, (u_long) cb); 295479697Snon cb->ccb_flags |= (CCB_NORETRY | CCB_SILENT); 295579697Snon scsi_low_revoke_ccb(slp, cb, 1); 295679697Snon return NULL; 295779697Snon } 295867468Snon 295979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id) != 0) 296079697Snon { 296179697Snon if (cb->ccb_omsgoutflag == 0) 296279697Snon scsi_low_ccb_message_assert(cb, SCSI_LOW_MSG_NOOP); 296379697Snon } 296479697Snon#endif /* SCSI_LOW_DEBUG */ 296579697Snon 296679697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 296779697Snon cb->ccb_flags &= ~CCB_DISCQ; 296879697Snon slp->sl_Qnexus = cb; 296979697Snon 297067468Snon slp->sl_scp = cb->ccb_sscp; 297167468Snon slp->sl_error |= cb->ccb_error; 297267468Snon 297367468Snon slp->sl_disc --; 297479697Snon ti->ti_disc --; 297567468Snon li->li_disc --; 297667468Snon 297767468Snon /* inform "ccb nexus established" to the host driver */ 297879697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 297979697Snon 298079697Snon /* check msg */ 298179697Snon if (cb->ccb_msgoutflag != 0) 298279697Snon { 298379697Snon scsi_low_ccb_message_exec(slp, cb); 298479697Snon } 298579697Snon 298667468Snon return cb; 298767468Snon} 298867468Snon 298967468Snonstruct targ_info * 299067468Snonscsi_low_reselected(slp, targ) 299167468Snon struct scsi_low_softc *slp; 299267468Snon u_int targ; 299367468Snon{ 299467468Snon struct targ_info *ti; 299579697Snon struct slccb *cb; 299667468Snon u_char *s; 299767468Snon 299867468Snon /* 299967468Snon * Check select vs reselected collision. 300067468Snon */ 300167468Snon 300279697Snon if ((cb = slp->sl_selid) != NULL) 300367468Snon { 300479697Snon scsi_low_arbit_fail(slp, cb); 300567468Snon#ifdef SCSI_LOW_STATICS 300667468Snon scsi_low_statics.nexus_conflict ++; 300767468Snon#endif /* SCSI_LOW_STATICS */ 300867468Snon } 300979697Snon 301079697Snon /* 301179697Snon * Check if no current active nexus. 301279697Snon */ 301379697Snon if (slp->sl_Tnexus != NULL) 301467468Snon { 301567468Snon s = "host busy"; 301667468Snon goto world_restart; 301767468Snon } 301867468Snon 301967468Snon /* 302067468Snon * Check a valid target id asserted ? 302167468Snon */ 302267468Snon if (targ >= slp->sl_ntargs || targ == slp->sl_hostid) 302367468Snon { 302467468Snon s = "scsi id illegal"; 302567468Snon goto world_restart; 302667468Snon } 302767468Snon 302867468Snon /* 302967468Snon * Check the target scsi status. 303067468Snon */ 303167468Snon ti = slp->sl_ti[targ]; 303279697Snon if (ti->ti_phase != PH_DISC && ti->ti_phase != PH_NULL) 303367468Snon { 303467468Snon s = "phase mismatch"; 303567468Snon goto world_restart; 303667468Snon } 303767468Snon 303867468Snon /* 303979697Snon * Setup init msgsys 304067468Snon */ 304167468Snon slp->sl_error = 0; 304267468Snon scsi_low_init_msgsys(slp, ti); 304367468Snon 304467468Snon /* 304567468Snon * Establish our target nexus 304667468Snon */ 304767468Snon SCSI_LOW_SETUP_PHASE(ti, PH_RESEL); 304879697Snon slp->sl_Tnexus = ti; 304967468Snon#ifdef SCSI_LOW_STATICS 305067468Snon scsi_low_statics.nexus_reselected ++; 305167468Snon#endif /* SCSI_LOW_STATICS */ 305267468Snon return ti; 305367468Snon 305467468Snonworld_restart: 305567468Snon printf("%s: reselect(%x:unknown) %s\n", slp->sl_xname, targ, s); 305667468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, 305767468Snon "reselect: scsi world confused"); 305867468Snon return NULL; 305967468Snon} 306067468Snon 306167468Snon/************************************************************** 306267468Snon * cmd out pointer setup 306367468Snon **************************************************************/ 306467468Snonint 306567468Snonscsi_low_cmd(slp, ti) 306667468Snon struct scsi_low_softc *slp; 306767468Snon struct targ_info *ti; 306867468Snon{ 306979697Snon struct slccb *cb = slp->sl_Qnexus; 307067468Snon 307179697Snon slp->sl_ph_count ++; 307267468Snon if (cb == NULL) 307367468Snon { 307467468Snon /* 307579697Snon * no ccb, abort! 307667468Snon */ 307767468Snon slp->sl_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd; 307867468Snon slp->sl_scp.scp_cmdlen = sizeof(unit_ready_cmd); 307967468Snon slp->sl_scp.scp_datalen = 0; 308067468Snon slp->sl_scp.scp_direction = SCSI_LOW_READ; 308179697Snon slp->sl_error |= FATALIO; 308279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 308379697Snon SCSI_LOW_INFO(slp, ti, "CMDOUT: ccb nexus not found"); 308479697Snon return EINVAL; 308567468Snon } 308679697Snon else 308767468Snon { 308879697Snon#ifdef SCSI_LOW_DEBUG 308979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_CMDLNK_CHECK, ti->ti_id)) 309079697Snon { 309179697Snon scsi_low_test_cmdlnk(slp, cb); 309279697Snon } 309379697Snon#endif /* SCSI_LOW_DEBUG */ 309467468Snon } 309567468Snon return 0; 309667468Snon} 309767468Snon 309867468Snon/************************************************************** 309967468Snon * data out pointer setup 310067468Snon **************************************************************/ 310167468Snonint 310267468Snonscsi_low_data(slp, ti, bp, direction) 310367468Snon struct scsi_low_softc *slp; 310467468Snon struct targ_info *ti; 310567468Snon struct buf **bp; 310667468Snon int direction; 310767468Snon{ 310879697Snon struct slccb *cb = slp->sl_Qnexus; 310967468Snon 311079697Snon if (cb != NULL && direction == cb->ccb_sscp.scp_direction) 311167468Snon { 311279697Snon *bp = cb->bp; 311379697Snon return 0; 311467468Snon } 311567468Snon 311679697Snon slp->sl_error |= (FATALIO | PDMAERR); 311779697Snon slp->sl_scp.scp_datalen = 0; 311879697Snon slp->sl_scp.scp_direction = direction; 311979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 312079697Snon if (ti->ti_ophase != ti->ti_phase) 312167468Snon { 312279697Snon char *s; 312379697Snon 312479697Snon if (cb == NULL) 312579697Snon s = "DATA PHASE: ccb nexus not found"; 312679697Snon else 312779697Snon s = "DATA PHASE: xfer direction mismatch"; 312879697Snon SCSI_LOW_INFO(slp, ti, s); 312967468Snon } 313067468Snon 313179697Snon *bp = NULL; 313279697Snon return EINVAL; 313367468Snon} 313467468Snon 313567468Snon/************************************************************** 313667468Snon * MSG_SYS 313767468Snon **************************************************************/ 313867468Snon#define MSGINPTR_CLR(ti) {(ti)->ti_msginptr = 0; (ti)->ti_msginlen = 0;} 313967468Snon#define MSGIN_PERIOD(ti) ((ti)->ti_msgin[3]) 314067468Snon#define MSGIN_OFFSET(ti) ((ti)->ti_msgin[4]) 314179697Snon#define MSGIN_WIDTHP(ti) ((ti)->ti_msgin[3]) 314267468Snon#define MSGIN_DATA_LAST 0x30 314367468Snon 314492770Salfredstatic int scsi_low_errfunc_synch(struct scsi_low_softc *, u_int); 314592770Salfredstatic int scsi_low_errfunc_wide(struct scsi_low_softc *, u_int); 314692770Salfredstatic int scsi_low_errfunc_identify(struct scsi_low_softc *, u_int); 314792770Salfredstatic int scsi_low_errfunc_qtag(struct scsi_low_softc *, u_int); 314867468Snon 314992770Salfredstatic int scsi_low_msgfunc_synch(struct scsi_low_softc *); 315092770Salfredstatic int scsi_low_msgfunc_wide(struct scsi_low_softc *); 315192770Salfredstatic int scsi_low_msgfunc_identify(struct scsi_low_softc *); 315292770Salfredstatic int scsi_low_msgfunc_abort(struct scsi_low_softc *); 315392770Salfredstatic int scsi_low_msgfunc_qabort(struct scsi_low_softc *); 315492770Salfredstatic int scsi_low_msgfunc_qtag(struct scsi_low_softc *); 315592770Salfredstatic int scsi_low_msgfunc_reset(struct scsi_low_softc *); 315667468Snon 315767468Snonstruct scsi_low_msgout_data { 315867468Snon u_int md_flags; 315967468Snon u_int8_t md_msg; 316092770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 316192770Salfred int (*md_errfunc)(struct scsi_low_softc *, u_int); 316279697Snon#define MSG_RELEASE_ATN 0x0001 316379697Snon u_int md_condition; 316467468Snon}; 316567468Snon 316667468Snonstruct scsi_low_msgout_data scsi_low_msgout_data[] = { 316779697Snon/* 0 */ {SCSI_LOW_MSG_RESET, MSG_RESET, scsi_low_msgfunc_reset, NULL, MSG_RELEASE_ATN}, 316879697Snon/* 1 */ {SCSI_LOW_MSG_REJECT, MSG_REJECT, NULL, NULL, MSG_RELEASE_ATN}, 316979697Snon/* 2 */ {SCSI_LOW_MSG_PARITY, MSG_PARITY, NULL, NULL, MSG_RELEASE_ATN}, 317079697Snon/* 3 */ {SCSI_LOW_MSG_ERROR, MSG_I_ERROR, NULL, NULL, MSG_RELEASE_ATN}, 317179697Snon/* 4 */ {SCSI_LOW_MSG_IDENTIFY, MSG_IDENTIFY, scsi_low_msgfunc_identify, scsi_low_errfunc_identify, 0}, 317279697Snon/* 5 */ {SCSI_LOW_MSG_ABORT, MSG_ABORT, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 317379697Snon/* 6 */ {SCSI_LOW_MSG_TERMIO, MSG_TERM_IO, NULL, NULL, MSG_RELEASE_ATN}, 317479697Snon/* 7 */ {SCSI_LOW_MSG_SIMPLE_QTAG, MSG_SIMPLE_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 317579697Snon/* 8 */ {SCSI_LOW_MSG_ORDERED_QTAG, MSG_ORDERED_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 317679697Snon/* 9 */{SCSI_LOW_MSG_HEAD_QTAG, MSG_HEAD_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 317779697Snon/* 10 */ {SCSI_LOW_MSG_ABORT_QTAG, MSG_ABORT_QTAG, scsi_low_msgfunc_qabort, NULL, MSG_RELEASE_ATN}, 317879697Snon/* 11 */ {SCSI_LOW_MSG_CLEAR_QTAG, MSG_CLEAR_QTAG, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 317979697Snon/* 12 */{SCSI_LOW_MSG_WIDE, MSG_EXTEND, scsi_low_msgfunc_wide, scsi_low_errfunc_wide, MSG_RELEASE_ATN}, 318079697Snon/* 13 */{SCSI_LOW_MSG_SYNCH, MSG_EXTEND, scsi_low_msgfunc_synch, scsi_low_errfunc_synch, MSG_RELEASE_ATN}, 318179697Snon/* 14 */{SCSI_LOW_MSG_NOOP, MSG_NOOP, NULL, NULL, MSG_RELEASE_ATN}, 318279697Snon/* 15 */{SCSI_LOW_MSG_ALL, 0}, 318367468Snon}; 318467468Snon 318592770Salfredstatic int scsi_low_msginfunc_ext(struct scsi_low_softc *); 318692770Salfredstatic int scsi_low_synch(struct scsi_low_softc *); 318792770Salfredstatic int scsi_low_wide(struct scsi_low_softc *); 318892770Salfredstatic int scsi_low_msginfunc_msg_reject(struct scsi_low_softc *); 318992770Salfredstatic int scsi_low_msginfunc_rejop(struct scsi_low_softc *); 319092770Salfredstatic int scsi_low_msginfunc_rp(struct scsi_low_softc *); 319192770Salfredstatic int scsi_low_msginfunc_sdp(struct scsi_low_softc *); 319292770Salfredstatic int scsi_low_msginfunc_disc(struct scsi_low_softc *); 319392770Salfredstatic int scsi_low_msginfunc_cc(struct scsi_low_softc *); 319492770Salfredstatic int scsi_low_msginfunc_lcc(struct scsi_low_softc *); 319592770Salfredstatic int scsi_low_msginfunc_parity(struct scsi_low_softc *); 319692770Salfredstatic int scsi_low_msginfunc_noop(struct scsi_low_softc *); 319792770Salfredstatic int scsi_low_msginfunc_simple_qtag(struct scsi_low_softc *); 319892770Salfredstatic int scsi_low_msginfunc_i_wide_residue(struct scsi_low_softc *); 319967468Snon 320067468Snonstruct scsi_low_msgin_data { 320167468Snon u_int md_len; 320292770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 320367468Snon}; 320467468Snon 320567468Snonstruct scsi_low_msgin_data scsi_low_msgin_data[] = { 320667468Snon/* 0 */ {1, scsi_low_msginfunc_cc}, 320767468Snon/* 1 */ {2, scsi_low_msginfunc_ext}, 320867468Snon/* 2 */ {1, scsi_low_msginfunc_sdp}, 320979697Snon/* 3 */ {1, scsi_low_msginfunc_rp}, 321067468Snon/* 4 */ {1, scsi_low_msginfunc_disc}, 321167468Snon/* 5 */ {1, scsi_low_msginfunc_rejop}, 321267468Snon/* 6 */ {1, scsi_low_msginfunc_rejop}, 321367468Snon/* 7 */ {1, scsi_low_msginfunc_msg_reject}, 321467468Snon/* 8 */ {1, scsi_low_msginfunc_noop}, 321567468Snon/* 9 */ {1, scsi_low_msginfunc_parity}, 321679697Snon/* a */ {1, scsi_low_msginfunc_lcc}, 321779697Snon/* b */ {1, scsi_low_msginfunc_lcc}, 321867468Snon/* c */ {1, scsi_low_msginfunc_rejop}, 321967468Snon/* d */ {2, scsi_low_msginfunc_rejop}, 322067468Snon/* e */ {1, scsi_low_msginfunc_rejop}, 322167468Snon/* f */ {1, scsi_low_msginfunc_rejop}, 322267468Snon/* 0x10 */ {1, scsi_low_msginfunc_rejop}, 322367468Snon/* 0x11 */ {1, scsi_low_msginfunc_rejop}, 322467468Snon/* 0x12 */ {1, scsi_low_msginfunc_rejop}, 322567468Snon/* 0x13 */ {1, scsi_low_msginfunc_rejop}, 322667468Snon/* 0x14 */ {1, scsi_low_msginfunc_rejop}, 322767468Snon/* 0x15 */ {1, scsi_low_msginfunc_rejop}, 322867468Snon/* 0x16 */ {1, scsi_low_msginfunc_rejop}, 322967468Snon/* 0x17 */ {1, scsi_low_msginfunc_rejop}, 323067468Snon/* 0x18 */ {1, scsi_low_msginfunc_rejop}, 323167468Snon/* 0x19 */ {1, scsi_low_msginfunc_rejop}, 323267468Snon/* 0x1a */ {1, scsi_low_msginfunc_rejop}, 323367468Snon/* 0x1b */ {1, scsi_low_msginfunc_rejop}, 323467468Snon/* 0x1c */ {1, scsi_low_msginfunc_rejop}, 323567468Snon/* 0x1d */ {1, scsi_low_msginfunc_rejop}, 323667468Snon/* 0x1e */ {1, scsi_low_msginfunc_rejop}, 323767468Snon/* 0x1f */ {1, scsi_low_msginfunc_rejop}, 323879697Snon/* 0x20 */ {2, scsi_low_msginfunc_simple_qtag}, 323967468Snon/* 0x21 */ {2, scsi_low_msginfunc_rejop}, 324067468Snon/* 0x22 */ {2, scsi_low_msginfunc_rejop}, 324179697Snon/* 0x23 */ {2, scsi_low_msginfunc_i_wide_residue}, 324267468Snon/* 0x24 */ {2, scsi_low_msginfunc_rejop}, 324367468Snon/* 0x25 */ {2, scsi_low_msginfunc_rejop}, 324467468Snon/* 0x26 */ {2, scsi_low_msginfunc_rejop}, 324567468Snon/* 0x27 */ {2, scsi_low_msginfunc_rejop}, 324667468Snon/* 0x28 */ {2, scsi_low_msginfunc_rejop}, 324767468Snon/* 0x29 */ {2, scsi_low_msginfunc_rejop}, 324867468Snon/* 0x2a */ {2, scsi_low_msginfunc_rejop}, 324967468Snon/* 0x2b */ {2, scsi_low_msginfunc_rejop}, 325067468Snon/* 0x2c */ {2, scsi_low_msginfunc_rejop}, 325167468Snon/* 0x2d */ {2, scsi_low_msginfunc_rejop}, 325267468Snon/* 0x2e */ {2, scsi_low_msginfunc_rejop}, 325367468Snon/* 0x2f */ {2, scsi_low_msginfunc_rejop}, 325467468Snon/* 0x30 */ {1, scsi_low_msginfunc_rejop} /* default rej op */ 325567468Snon}; 325667468Snon 325767468Snon/************************************************************** 325867468Snon * msgout 325967468Snon **************************************************************/ 326067468Snonstatic int 326179697Snonscsi_low_msgfunc_synch(slp) 326279697Snon struct scsi_low_softc *slp; 326367468Snon{ 326479697Snon struct targ_info *ti = slp->sl_Tnexus; 326567468Snon int ptr = ti->ti_msgoutlen; 326667468Snon 326767468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_SYNCHLEN; 326867468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_SYNCHCODE; 326973025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_maxsynch.period; 327073025Snon ti->ti_msgoutstr[ptr + 4] = ti->ti_maxsynch.offset; 327167468Snon return MSG_EXTEND_SYNCHLEN + 2; 327267468Snon} 327367468Snon 327467468Snonstatic int 327579697Snonscsi_low_msgfunc_wide(slp) 327679697Snon struct scsi_low_softc *slp; 327767468Snon{ 327879697Snon struct targ_info *ti = slp->sl_Tnexus; 327967468Snon int ptr = ti->ti_msgoutlen; 328067468Snon 328167468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_WIDELEN; 328267468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_WIDECODE; 328373025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_width; 328467468Snon return MSG_EXTEND_WIDELEN + 2; 328567468Snon} 328667468Snon 328767468Snonstatic int 328879697Snonscsi_low_msgfunc_identify(slp) 328979697Snon struct scsi_low_softc *slp; 329067468Snon{ 329179697Snon struct targ_info *ti = slp->sl_Tnexus; 329279697Snon struct lun_info *li = slp->sl_Lnexus; 329379697Snon struct slccb *cb = slp->sl_Qnexus; 329479697Snon int ptr = ti->ti_msgoutlen; 329579697Snon u_int8_t msg; 329667468Snon 329779697Snon msg = MSG_IDENTIFY; 329879697Snon if (cb == NULL) 329967468Snon { 330079697Snon slp->sl_error |= FATALIO; 330179697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 330279697Snon SCSI_LOW_INFO(slp, ti, "MSGOUT: nexus unknown"); 330367468Snon } 330467468Snon else 330567468Snon { 330679697Snon if (scsi_low_is_disconnect_ok(cb) != 0) 330779697Snon msg |= (MSG_IDENTIFY_DISCPRIV | li->li_lun); 330879697Snon else 330979697Snon msg |= li->li_lun; 331079697Snon 331179697Snon if (ti->ti_phase == PH_MSGOUT) 331279697Snon { 331379697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 331479697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 331579697Snon { 331679697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 331779697Snon } 331879697Snon } 331967468Snon } 332079697Snon ti->ti_msgoutstr[ptr + 0] = msg; 332167468Snon return 1; 332267468Snon} 332367468Snon 332467468Snonstatic int 332579697Snonscsi_low_msgfunc_abort(slp) 332679697Snon struct scsi_low_softc *slp; 332767468Snon{ 332867468Snon 332979697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_ABORT); 333079697Snon return 1; 333179697Snon} 333279697Snon 333379697Snonstatic int 333479697Snonscsi_low_msgfunc_qabort(slp) 333579697Snon struct scsi_low_softc *slp; 333679697Snon{ 333779697Snon 333879697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_TERM); 333979697Snon return 1; 334079697Snon} 334179697Snon 334279697Snonstatic int 334379697Snonscsi_low_msgfunc_reset(slp) 334479697Snon struct scsi_low_softc *slp; 334579697Snon{ 334679697Snon 334779697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_RESET); 334879697Snon return 1; 334979697Snon} 335079697Snon 335179697Snonstatic int 335279697Snonscsi_low_msgfunc_qtag(slp) 335379697Snon struct scsi_low_softc *slp; 335479697Snon{ 335579697Snon struct targ_info *ti = slp->sl_Tnexus; 335679697Snon struct slccb *cb = slp->sl_Qnexus; 335779697Snon int ptr = ti->ti_msgoutlen; 335879697Snon 335979697Snon if (cb == NULL || cb->ccb_tag == SCSI_LOW_UNKTAG) 336067468Snon { 336167468Snon ti->ti_msgoutstr[ptr + 0] = MSG_NOOP; 336267468Snon return 1; 336367468Snon } 336467468Snon else 336567468Snon { 336679697Snon ti->ti_msgoutstr[ptr + 1] = (u_int8_t) cb->ccb_tag; 336779697Snon if (ti->ti_phase == PH_MSGOUT) 336879697Snon { 336979697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 337079697Snon } 337167468Snon } 337279697Snon return 2; 337367468Snon} 337467468Snon 337567468Snon/* 337667468Snon * The following functions are called when targets give unexpected 337767468Snon * responces in msgin (after msgout). 337867468Snon */ 337967468Snonstatic int 338079697Snonscsi_low_errfunc_identify(slp, msgflags) 338179697Snon struct scsi_low_softc *slp; 338267468Snon u_int msgflags; 338367468Snon{ 338467468Snon 338579697Snon if (slp->sl_Lnexus != NULL) 338679697Snon { 338779697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_DISC; 338879697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 338979697Snon } 339067468Snon return 0; 339167468Snon} 339267468Snon 339367468Snonstatic int 339479697Snonscsi_low_errfunc_synch(slp, msgflags) 339579697Snon struct scsi_low_softc *slp; 339667468Snon u_int msgflags; 339767468Snon{ 339879697Snon struct targ_info *ti = slp->sl_Tnexus; 339967468Snon 340067468Snon MSGIN_PERIOD(ti) = 0; 340167468Snon MSGIN_OFFSET(ti) = 0; 340279697Snon scsi_low_synch(slp); 340367468Snon return 0; 340467468Snon} 340567468Snon 340667468Snonstatic int 340779697Snonscsi_low_errfunc_wide(slp, msgflags) 340879697Snon struct scsi_low_softc *slp; 340967468Snon u_int msgflags; 341067468Snon{ 341179697Snon struct targ_info *ti = slp->sl_Tnexus; 341279697Snon 341379697Snon MSGIN_WIDTHP(ti) = 0; 341479697Snon scsi_low_wide(slp); 341567468Snon return 0; 341667468Snon} 341767468Snon 341879697Snonstatic int 341979697Snonscsi_low_errfunc_qtag(slp, msgflags) 342079697Snon struct scsi_low_softc *slp; 342179697Snon u_int msgflags; 342279697Snon{ 342379697Snon 342479697Snon if ((msgflags & SCSI_LOW_MSG_REJECT) != 0) 342579697Snon { 342679697Snon if (slp->sl_Qnexus != NULL) 342779697Snon { 342879697Snon scsi_low_deactivate_qtag(slp->sl_Qnexus); 342979697Snon } 343079697Snon if (slp->sl_Lnexus != NULL) 343179697Snon { 343279697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_QTAG; 343379697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 343479697Snon } 343579697Snon printf("%s: scsi_low: qtag msg rejected\n", slp->sl_xname); 343679697Snon } 343779697Snon return 0; 343879697Snon} 343979697Snon 344079697Snon 344167468Snonint 344279697Snonscsi_low_msgout(slp, ti, fl) 344367468Snon struct scsi_low_softc *slp; 344467468Snon struct targ_info *ti; 344579697Snon u_int fl; 344667468Snon{ 344767468Snon struct scsi_low_msgout_data *mdp; 344867468Snon int len = 0; 344967468Snon 345079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 345179697Snon if (ti != slp->sl_Tnexus) 345279697Snon { 345379697Snon scsi_low_print(slp, NULL); 345479697Snon panic("scsi_low_msgout: Target nexus inconsistent"); 345579697Snon } 345679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 345779697Snon 345879697Snon slp->sl_ph_count ++; 345979697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 346079697Snon { 346179697Snon printf("%s: too many phase changes\n", slp->sl_xname); 346279697Snon slp->sl_error |= FATALIO; 346379697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 346479697Snon } 346579697Snon 346667468Snon /* STEP I. 346767468Snon * Scsi phase changes. 346867468Snon * Previously msgs asserted are accepted by our target or 346967468Snon * processed by scsi_low_msgin. 347067468Snon * Thus clear all saved informations. 347167468Snon */ 347279697Snon if ((fl & SCSI_LOW_MSGOUT_INIT) != 0) 347367468Snon { 347467468Snon ti->ti_omsgflags = 0; 347567468Snon ti->ti_emsgflags = 0; 347667468Snon } 347779697Snon else if (slp->sl_atten == 0) 347879697Snon { 347967468Snon /* STEP II. 348067468Snon * We did not assert attention, however still our target required 348167468Snon * msgs. Resend previous msgs. 348267468Snon */ 348367468Snon ti->ti_msgflags |= ti->ti_omsgflags; 348479697Snon ti->ti_omsgflags = 0; 348567468Snon#ifdef SCSI_LOW_DIAGNOSTIC 348667468Snon printf("%s: scsi_low_msgout: retry msgout\n", slp->sl_xname); 348767468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 348867468Snon } 348967468Snon 349067468Snon /* STEP III. 349179697Snon * We have no msgs. send MSG_NOOP (OK?) 349267468Snon */ 349379697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 349467468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_NOOP, 0); 349567468Snon 349667468Snon /* STEP IV. 349767468Snon * Process all msgs 349867468Snon */ 349967468Snon ti->ti_msgoutlen = 0; 350079697Snon slp->sl_clear_atten = 0; 350167468Snon mdp = &scsi_low_msgout_data[0]; 350267468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 350367468Snon { 350467468Snon if ((ti->ti_msgflags & mdp->md_flags) != 0) 350567468Snon { 350667468Snon ti->ti_omsgflags |= mdp->md_flags; 350767468Snon ti->ti_msgflags &= ~mdp->md_flags; 350867468Snon ti->ti_emsgflags = mdp->md_flags; 350967468Snon 351067468Snon ti->ti_msgoutstr[ti->ti_msgoutlen] = mdp->md_msg; 351167468Snon if (mdp->md_msgfunc != NULL) 351279697Snon len = (*mdp->md_msgfunc) (slp); 351367468Snon else 351467468Snon len = 1; 351567468Snon 351679697Snon#ifdef SCSI_LOW_DIAGNOSTIC 351779697Snon scsi_low_msg_log_write(&ti->ti_log_msgout, 351879697Snon &ti->ti_msgoutstr[ti->ti_msgoutlen], len); 351979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 352079697Snon 352167468Snon ti->ti_msgoutlen += len; 352279697Snon if ((mdp->md_condition & MSG_RELEASE_ATN) != 0) 352379697Snon { 352479697Snon slp->sl_clear_atten = 1; 352579697Snon break; 352679697Snon } 352779697Snon 352879697Snon if ((fl & SCSI_LOW_MSGOUT_UNIFY) == 0 || 352967468Snon ti->ti_msgflags == 0) 353067468Snon break; 353179697Snon 353267468Snon if (ti->ti_msgoutlen >= SCSI_LOW_MAX_MSGLEN - 5) 353367468Snon break; 353467468Snon } 353567468Snon } 353667468Snon 353779697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 353879697Snon slp->sl_clear_atten = 1; 353967468Snon 354067468Snon return ti->ti_msgoutlen; 354167468Snon} 354267468Snon 354367468Snon/************************************************************** 354467468Snon * msgin 354567468Snon **************************************************************/ 354667468Snonstatic int 354779697Snonscsi_low_msginfunc_noop(slp) 354879697Snon struct scsi_low_softc *slp; 354967468Snon{ 355067468Snon 355167468Snon return 0; 355267468Snon} 355367468Snon 355467468Snonstatic int 355579697Snonscsi_low_msginfunc_rejop(slp) 355679697Snon struct scsi_low_softc *slp; 355767468Snon{ 355879697Snon struct targ_info *ti = slp->sl_Tnexus; 355967468Snon u_int8_t msg = ti->ti_msgin[0]; 356067468Snon 356179697Snon printf("%s: MSGIN: msg 0x%x rejected\n", slp->sl_xname, (u_int) msg); 356267468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 356367468Snon return 0; 356467468Snon} 356567468Snon 356667468Snonstatic int 356779697Snonscsi_low_msginfunc_cc(slp) 356879697Snon struct scsi_low_softc *slp; 356967468Snon{ 357079697Snon struct lun_info *li; 357167468Snon 357267468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC); 357379697Snon 357479697Snon /* validate status */ 357579697Snon if (slp->sl_Qnexus == NULL) 357679697Snon return ENOENT; 357779697Snon 357879697Snon slp->sl_Qnexus->ccb_sscp.scp_status = slp->sl_scp.scp_status; 357979697Snon li = slp->sl_Lnexus; 358079697Snon switch (slp->sl_scp.scp_status) 358179697Snon { 358279697Snon case ST_GOOD: 358379697Snon li->li_maxnqio = li->li_maxnexus; 358479697Snon break; 358579697Snon 358679697Snon case ST_CHKCOND: 358779697Snon li->li_maxnqio = 0; 358879697Snon if (li->li_qflags & SCSI_LOW_QFLAG_CA_QCLEAR) 358979697Snon scsi_low_reset_nexus_lun(slp, li, 0); 359079697Snon break; 359179697Snon 359279697Snon case ST_BUSY: 359379697Snon li->li_maxnqio = 0; 359479697Snon break; 359579697Snon 359679697Snon case ST_QUEFULL: 359779697Snon if (li->li_maxnexus >= li->li_nqio) 359879697Snon li->li_maxnexus = li->li_nqio - 1; 359979697Snon li->li_maxnqio = li->li_maxnexus; 360079697Snon break; 360179697Snon 360279697Snon case ST_INTERGOOD: 360379697Snon case ST_INTERMET: 360479697Snon slp->sl_error |= MSGERR; 360579697Snon break; 360679697Snon 360779697Snon default: 360879697Snon break; 360979697Snon } 361067468Snon return 0; 361167468Snon} 361267468Snon 361367468Snonstatic int 361479697Snonscsi_low_msginfunc_lcc(slp) 361579697Snon struct scsi_low_softc *slp; 361679697Snon{ 361767468Snon struct targ_info *ti; 361879697Snon struct lun_info *li; 361979697Snon struct slccb *ncb, *cb; 362079697Snon 362179697Snon ti = slp->sl_Tnexus; 362279697Snon li = slp->sl_Lnexus; 362379697Snon if ((cb = slp->sl_Qnexus) == NULL) 362479697Snon goto bad; 362579697Snon 362679697Snon cb->ccb_sscp.scp_status = slp->sl_scp.scp_status; 362779697Snon switch (slp->sl_scp.scp_status) 362879697Snon { 362979697Snon case ST_INTERGOOD: 363079697Snon case ST_INTERMET: 363179697Snon li->li_maxnqio = li->li_maxnexus; 363279697Snon break; 363379697Snon 363479697Snon default: 363579697Snon slp->sl_error |= MSGERR; 363679697Snon break; 363779697Snon } 363879697Snon 363979697Snon if ((li->li_flags & SCSI_LOW_LINK) == 0) 364079697Snon goto bad; 364179697Snon 364279697Snon cb->ccb_error |= slp->sl_error; 364379697Snon if (cb->ccb_error != 0) 364479697Snon goto bad; 364579697Snon 364679697Snon for (ncb = TAILQ_FIRST(&slp->sl_start); ncb != NULL; 364779697Snon ncb = TAILQ_NEXT(ncb, ccb_chain)) 364879697Snon { 364979697Snon if (ncb->li == li) 365079697Snon goto cmd_link_start; 365179697Snon } 365279697Snon 365379697Snon 365479697Snonbad: 365579697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_LCTERM); 365679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 365779697Snon return EIO; 365879697Snon 365979697Snoncmd_link_start: 366079697Snon ncb->ccb_flags &= ~CCB_STARTQ; 366179697Snon TAILQ_REMOVE(&slp->sl_start, ncb, ccb_chain); 366279697Snon 366379697Snon scsi_low_dealloc_qtag(ncb); 366479697Snon ncb->ccb_tag = cb->ccb_tag; 366579697Snon ncb->ccb_otag = cb->ccb_otag; 366679697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 366779697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 366879697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 3669106890Simp panic("%s: linked ccb retried", slp->sl_xname); 367079697Snon 367179697Snon slp->sl_Qnexus = ncb; 367279697Snon slp->sl_ph_count = 0; 367379697Snon 367479697Snon ncb->ccb_error = 0; 367579697Snon ncb->ccb_datalen = -1; 367679697Snon ncb->ccb_scp.scp_status = ST_UNKNOWN; 367779697Snon ncb->ccb_flags &= ~CCB_INTERNAL; 367879697Snon 367979697Snon scsi_low_init_msgsys(slp, ti); 368079697Snon 368179697Snon (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, ncb); 368279697Snon 368379697Snon if (ncb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 368479697Snon ncb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 368579697Snon ncb->ccb_tc = ncb->ccb_tcmax; 368679697Snon 368779697Snon /* setup saved scsi data pointer */ 368879697Snon ncb->ccb_sscp = ncb->ccb_scp; 368979697Snon slp->sl_scp = ncb->ccb_sscp; 369079697Snon slp->sl_error = ncb->ccb_error; 369179697Snon 369279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 369379697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 369479697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 369579697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 369679697Snon return EJUSTRETURN; 369779697Snon} 369879697Snon 369979697Snonstatic int 370079697Snonscsi_low_msginfunc_disc(slp) 370179697Snon struct scsi_low_softc *slp; 370267468Snon{ 370367468Snon 370467468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC); 370567468Snon return 0; 370667468Snon} 370767468Snon 370867468Snonstatic int 370979697Snonscsi_low_msginfunc_sdp(slp) 371079697Snon struct scsi_low_softc *slp; 371167468Snon{ 371279697Snon struct slccb *cb = slp->sl_Qnexus; 371367468Snon 371479697Snon if (cb != NULL) 371579697Snon { 371679697Snon cb->ccb_sscp.scp_datalen = slp->sl_scp.scp_datalen; 371779697Snon cb->ccb_sscp.scp_data = slp->sl_scp.scp_data; 371879697Snon } 371967468Snon else 372079697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 372167468Snon return 0; 372267468Snon} 372367468Snon 372467468Snonstatic int 372579697Snonscsi_low_msginfunc_rp(slp) 372679697Snon struct scsi_low_softc *slp; 372767468Snon{ 372867468Snon 372979697Snon if (slp->sl_Qnexus != NULL) 373079697Snon slp->sl_scp = slp->sl_Qnexus->ccb_sscp; 373167468Snon else 373279697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 373367468Snon return 0; 373467468Snon} 373567468Snon 373667468Snonstatic int 373779697Snonscsi_low_synch(slp) 373879697Snon struct scsi_low_softc *slp; 373967468Snon{ 374079697Snon struct targ_info *ti = slp->sl_Tnexus; 374179697Snon u_int period = 0, offset = 0, speed; 374267468Snon u_char *s; 374367468Snon int error; 374467468Snon 374579697Snon if ((MSGIN_PERIOD(ti) >= ti->ti_maxsynch.period && 374679697Snon MSGIN_OFFSET(ti) <= ti->ti_maxsynch.offset) || 374779697Snon MSGIN_OFFSET(ti) == 0) 374867468Snon { 374967468Snon if ((offset = MSGIN_OFFSET(ti)) != 0) 375067468Snon period = MSGIN_PERIOD(ti); 375167468Snon s = offset ? "synchronous" : "async"; 375267468Snon } 375367468Snon else 375467468Snon { 375567468Snon /* XXX: 375667468Snon * Target seems to be brain damaged. 375767468Snon * Force async transfer. 375867468Snon */ 375973025Snon ti->ti_maxsynch.period = 0; 376073025Snon ti->ti_maxsynch.offset = 0; 376167468Snon printf("%s: target brain damaged. async transfer\n", 376267468Snon slp->sl_xname); 376367468Snon return EINVAL; 376467468Snon } 376567468Snon 376673025Snon ti->ti_maxsynch.period = period; 376773025Snon ti->ti_maxsynch.offset = offset; 376867468Snon 376967468Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_SYNCH); 377067468Snon if (error != 0) 377167468Snon { 377267468Snon /* XXX: 377367468Snon * Current period and offset are not acceptable 377467468Snon * for our adapter. 377567468Snon * The adapter changes max synch and max offset. 377667468Snon */ 377767468Snon printf("%s: synch neg failed. retry synch msg neg ...\n", 377867468Snon slp->sl_xname); 377967468Snon return error; 378067468Snon } 378167468Snon 378279697Snon ti->ti_osynch = ti->ti_maxsynch; 378379697Snon if (offset > 0) 378479697Snon { 378579697Snon ti->ti_setup_msg_done |= SCSI_LOW_MSG_SYNCH; 378679697Snon } 378779697Snon 378867468Snon /* inform data */ 378979697Snon if ((slp->sl_show_result & SHOW_SYNCH_NEG) != 0) 379067468Snon { 379179697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 379279697Snon struct slccb *cb = slp->sl_Qnexus; 379379697Snon 379479697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 379579697Snon return 0; 379679697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 379779697Snon 379879697Snon printf("%s(%d:*): <%s> offset %d period %dns ", 379979697Snon slp->sl_xname, ti->ti_id, s, offset, period * 4); 380079697Snon 380179697Snon if (period != 0) 380279697Snon { 380379697Snon speed = 1000 * 10 / (period * 4); 380479697Snon printf("%d.%d M/s", speed / 10, speed % 10); 380579697Snon } 380679697Snon printf("\n"); 380767468Snon } 380879697Snon return 0; 380979697Snon} 381067468Snon 381179697Snonstatic int 381279697Snonscsi_low_wide(slp) 381379697Snon struct scsi_low_softc *slp; 381479697Snon{ 381579697Snon struct targ_info *ti = slp->sl_Tnexus; 381679697Snon int error; 381779697Snon 381879697Snon ti->ti_width = MSGIN_WIDTHP(ti); 381979697Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_WIDE); 382079697Snon if (error != 0) 382179697Snon { 382279697Snon /* XXX: 382379697Snon * Current width is not acceptable for our adapter. 382479697Snon * The adapter changes max width. 382579697Snon */ 382679697Snon printf("%s: wide neg failed. retry wide msg neg ...\n", 382779697Snon slp->sl_xname); 382879697Snon return error; 382979697Snon } 383079697Snon 383179697Snon ti->ti_owidth = ti->ti_width; 383279697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 383379697Snon { 383479697Snon ti->ti_setup_msg_done |= 383579697Snon (SCSI_LOW_MSG_SYNCH | SCSI_LOW_MSG_WIDE); 383679697Snon } 383779697Snon 383879697Snon /* inform data */ 383979697Snon if ((slp->sl_show_result & SHOW_WIDE_NEG) != 0) 384079697Snon { 384179697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 384279697Snon struct slccb *cb = slp->sl_Qnexus; 384379697Snon 384479697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 384579697Snon return 0; 384679697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 384779697Snon 384879697Snon printf("%s(%d:*): transfer width %d bits\n", 384979697Snon slp->sl_xname, ti->ti_id, 1 << (3 + ti->ti_width)); 385079697Snon } 385167468Snon return 0; 385267468Snon} 385367468Snon 385467468Snonstatic int 385579697Snonscsi_low_msginfunc_simple_qtag(slp) 385679697Snon struct scsi_low_softc *slp; 385767468Snon{ 385879697Snon struct targ_info *ti = slp->sl_Tnexus; 385979697Snon scsi_low_tag_t etag = (scsi_low_tag_t) ti->ti_msgin[1]; 386079697Snon 386179697Snon if (slp->sl_Qnexus != NULL) 386279697Snon { 386379697Snon if (slp->sl_Qnexus->ccb_tag != etag) 386479697Snon { 386579697Snon slp->sl_error |= FATALIO; 386679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 386779697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: qtag mismatch"); 386879697Snon } 386979697Snon } 387079697Snon else if (scsi_low_establish_ccb(ti, slp->sl_Lnexus, etag) == NULL) 387179697Snon { 387279697Snon#ifdef SCSI_LOW_DEBUG 387379697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id)) 387479697Snon return 0; 387579697Snon#endif /* SCSI_LOW_DEBUG */ 387679697Snon 387779697Snon slp->sl_error |= FATALIO; 387879697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT_QTAG, 0); 387979697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: taged ccb not found"); 388079697Snon } 388179697Snon return 0; 388279697Snon} 388379697Snon 388479697Snonstatic int 388579697Snonscsi_low_msginfunc_i_wide_residue(slp) 388679697Snon struct scsi_low_softc *slp; 388779697Snon{ 388879697Snon struct targ_info *ti = slp->sl_Tnexus; 388979697Snon struct slccb *cb = slp->sl_Qnexus; 389079697Snon int res = (int) ti->ti_msgin[1]; 389179697Snon 389279697Snon if (cb == NULL || res <= 0 || 389379697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_16 && res > 1) || 389479697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_32 && res > 3)) 389579697Snon return EINVAL; 389679697Snon 389779697Snon if (slp->sl_scp.scp_datalen + res > cb->ccb_scp.scp_datalen) 389879697Snon return EINVAL; 389979697Snon 390079697Snon slp->sl_scp.scp_datalen += res; 390179697Snon slp->sl_scp.scp_data -= res; 390279697Snon scsi_low_data_finish(slp); 390379697Snon return 0; 390479697Snon} 390579697Snon 390679697Snonstatic int 390779697Snonscsi_low_msginfunc_ext(slp) 390879697Snon struct scsi_low_softc *slp; 390979697Snon{ 391079697Snon struct slccb *cb = slp->sl_Qnexus; 391179697Snon struct lun_info *li = slp->sl_Lnexus; 391279697Snon struct targ_info *ti = slp->sl_Tnexus; 391367468Snon int count, retry; 391467468Snon u_int32_t *ptr; 391567468Snon 391667468Snon if (ti->ti_msginptr == 2) 391767468Snon { 391867468Snon ti->ti_msginlen = ti->ti_msgin[1] + 2; 391967468Snon return 0; 392067468Snon } 392167468Snon 392267468Snon switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2])) 392367468Snon { 392467468Snon case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE): 392567468Snon if (cb == NULL) 392667468Snon break; 392767468Snon 392867468Snon ptr = (u_int32_t *)(&ti->ti_msgin[3]); 392967468Snon count = (int) htonl((long) (*ptr)); 393067468Snon if(slp->sl_scp.scp_datalen - count < 0 || 393167468Snon slp->sl_scp.scp_datalen - count > cb->ccb_scp.scp_datalen) 393267468Snon break; 393367468Snon 393467468Snon slp->sl_scp.scp_datalen -= count; 393567468Snon slp->sl_scp.scp_data += count; 393667468Snon return 0; 393767468Snon 393867468Snon case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE): 393967468Snon if (li == NULL) 394067468Snon break; 394167468Snon 394279697Snon retry = scsi_low_synch(slp); 394367468Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_SYNCH) == 0) 394467468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0); 394579697Snon 394679697Snon#ifdef SCSI_LOW_DEBUG 394779697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 394879697Snon { 394979697Snon scsi_low_test_atten(slp, ti, SCSI_LOW_MSG_SYNCH); 395079697Snon } 395179697Snon#endif /* SCSI_LOW_DEBUG */ 395267468Snon return 0; 395367468Snon 395467468Snon case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE): 395567468Snon if (li == NULL) 395667468Snon break; 395767468Snon 395879697Snon retry = scsi_low_wide(slp); 395979697Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_WIDE) == 0) 396079697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0); 396179697Snon 396267468Snon return 0; 396367468Snon 396467468Snon default: 396567468Snon break; 396667468Snon } 396767468Snon 396867468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 396967468Snon return EINVAL; 397067468Snon} 397167468Snon 397267468Snonstatic int 397379697Snonscsi_low_msginfunc_parity(slp) 397479697Snon struct scsi_low_softc *slp; 397567468Snon{ 397679697Snon struct targ_info *ti = slp->sl_Tnexus; 397767468Snon 397879697Snon /* only I -> T, invalid! */ 397979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 398067468Snon return 0; 398167468Snon} 398267468Snon 398367468Snonstatic int 398479697Snonscsi_low_msginfunc_msg_reject(slp) 398579697Snon struct scsi_low_softc *slp; 398667468Snon{ 398779697Snon struct targ_info *ti = slp->sl_Tnexus; 398867468Snon struct scsi_low_msgout_data *mdp; 398967468Snon u_int msgflags; 399067468Snon 399179697Snon if (ti->ti_emsgflags != 0) 399267468Snon { 399379697Snon printf("%s: msg flags [0x%x] rejected\n", 399479697Snon slp->sl_xname, ti->ti_emsgflags); 399567468Snon msgflags = SCSI_LOW_MSG_REJECT; 399667468Snon mdp = &scsi_low_msgout_data[0]; 399767468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 399867468Snon { 399967468Snon if ((ti->ti_emsgflags & mdp->md_flags) != 0) 400067468Snon { 400167468Snon ti->ti_emsgflags &= ~mdp->md_flags; 400267468Snon if (mdp->md_errfunc != NULL) 400379697Snon (*mdp->md_errfunc) (slp, msgflags); 400467468Snon break; 400567468Snon } 400667468Snon } 400779697Snon return 0; 400867468Snon } 400979697Snon else 401079697Snon { 401179697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: rejected msg not found"); 401279697Snon slp->sl_error |= MSGERR; 401379697Snon } 401479697Snon return EINVAL; 401567468Snon} 401667468Snon 401779697Snonint 401867468Snonscsi_low_msgin(slp, ti, c) 401967468Snon struct scsi_low_softc *slp; 402067468Snon struct targ_info *ti; 402179697Snon u_int c; 402267468Snon{ 402367468Snon struct scsi_low_msgin_data *sdp; 402467468Snon struct lun_info *li; 402567468Snon u_int8_t msg; 402667468Snon 402779697Snon#ifdef SCSI_LOW_DIAGNOSTIC 402879697Snon if (ti != slp->sl_Tnexus) 402979697Snon { 403079697Snon scsi_low_print(slp, NULL); 403179697Snon panic("scsi_low_msgin: Target nexus inconsistent"); 403279697Snon } 403379697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 403479697Snon 403567468Snon /* 403667468Snon * Phase changes, clear the pointer. 403767468Snon */ 403867468Snon if (ti->ti_ophase != ti->ti_phase) 403967468Snon { 404067468Snon MSGINPTR_CLR(ti); 404179697Snon ti->ti_msgin_parity_error = 0; 404279697Snon 404379697Snon slp->sl_ph_count ++; 404479697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 404579697Snon { 404679697Snon printf("%s: too many phase changes\n", slp->sl_xname); 404779697Snon slp->sl_error |= FATALIO; 404879697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 404979697Snon } 405067468Snon } 405167468Snon 405267468Snon /* 405367468Snon * Store a current messages byte into buffer and 405467468Snon * wait for the completion of the current msg. 405567468Snon */ 405679697Snon ti->ti_msgin[ti->ti_msginptr ++] = (u_int8_t) c; 405767468Snon if (ti->ti_msginptr >= SCSI_LOW_MAX_MSGLEN) 405867468Snon { 405967468Snon ti->ti_msginptr = SCSI_LOW_MAX_MSGLEN - 1; 406067468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 406167468Snon } 406267468Snon 406367468Snon /* 406479697Snon * Check parity errors. 406579697Snon */ 406679697Snon if ((c & SCSI_LOW_DATA_PE) != 0) 406779697Snon { 406879697Snon ti->ti_msgin_parity_error ++; 406979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0); 407079697Snon goto out; 407179697Snon } 407279697Snon 407379697Snon if (ti->ti_msgin_parity_error != 0) 407479697Snon goto out; 407579697Snon 407679697Snon /* 407767468Snon * Calculate messages length. 407867468Snon */ 407967468Snon msg = ti->ti_msgin[0]; 408067468Snon if (msg < MSGIN_DATA_LAST) 408167468Snon sdp = &scsi_low_msgin_data[msg]; 408267468Snon else 408367468Snon sdp = &scsi_low_msgin_data[MSGIN_DATA_LAST]; 408467468Snon 408567468Snon if (ti->ti_msginlen == 0) 408667468Snon { 408767468Snon ti->ti_msginlen = sdp->md_len; 408867468Snon } 408967468Snon 409067468Snon /* 409167468Snon * Check comletion. 409267468Snon */ 409367468Snon if (ti->ti_msginptr < ti->ti_msginlen) 409479697Snon return EJUSTRETURN; 409567468Snon 409667468Snon /* 409767468Snon * Do process. 409867468Snon */ 409967468Snon if ((msg & MSG_IDENTIFY) == 0) 410067468Snon { 410179697Snon if (((*sdp->md_msgfunc) (slp)) == EJUSTRETURN) 410279697Snon return EJUSTRETURN; 410367468Snon } 410467468Snon else 410567468Snon { 410679697Snon li = slp->sl_Lnexus; 410767468Snon if (li == NULL) 410867468Snon { 410979697Snon li = scsi_low_alloc_li(ti, MSGCMD_LUN(msg), 0); 411067468Snon if (li == NULL) 411167468Snon goto badlun; 411279697Snon slp->sl_Lnexus = li; 411379697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 411467468Snon } 411579697Snon else 411679697Snon { 411779697Snon if (MSGCMD_LUN(msg) != li->li_lun) 411879697Snon goto badlun; 411979697Snon } 412067468Snon 412179697Snon if (slp->sl_Qnexus == NULL && li->li_nqio == 0) 412267468Snon { 412367468Snon if (!scsi_low_establish_ccb(ti, li, SCSI_LOW_UNKTAG)) 412479697Snon { 412579697Snon#ifdef SCSI_LOW_DEBUG 412679697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 412779697Snon { 412879697Snon goto out; 412979697Snon } 413079697Snon#endif /* SCSI_LOW_DEBUG */ 413167468Snon goto badlun; 413279697Snon } 413367468Snon } 413467468Snon } 413579697Snon goto out; 413667468Snon 413767468Snon /* 413879697Snon * Msg process completed, reset msgin pointer and assert ATN if desired. 413967468Snon */ 414079697Snonbadlun: 414179697Snon slp->sl_error |= FATALIO; 414279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 414379697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: identify wrong"); 414479697Snon 414579697Snonout: 414679697Snon if (ti->ti_msginptr < ti->ti_msginlen) 414779697Snon return EJUSTRETURN; 414879697Snon 414979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 415079697Snon scsi_low_msg_log_write(&ti->ti_log_msgin, 415179697Snon &ti->ti_msgin[0], ti->ti_msginlen); 415279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 415379697Snon 415479697Snon MSGINPTR_CLR(ti); 415579697Snon return 0; 415679697Snon} 415779697Snon 415879697Snon/********************************************************** 415979697Snon * disconnect 416079697Snon **********************************************************/ 416179697Snonint 416279697Snonscsi_low_disconnected(slp, ti) 416379697Snon struct scsi_low_softc *slp; 416479697Snon struct targ_info *ti; 416579697Snon{ 416679697Snon struct slccb *cb = slp->sl_Qnexus; 416779697Snon 416879697Snon /* check phase completion */ 416979697Snon switch (slp->sl_msgphase) 417067468Snon { 417179697Snon case MSGPH_RESET: 417279697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 417379697Snon scsi_low_msginfunc_cc(slp); 417479697Snon scsi_low_reset_nexus_target(slp, slp->sl_Tnexus, 0); 417579697Snon goto io_resume; 417667468Snon 417779697Snon case MSGPH_ABORT: 417879697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 417979697Snon scsi_low_msginfunc_cc(slp); 418079697Snon scsi_low_reset_nexus_lun(slp, slp->sl_Lnexus, 0); 418179697Snon goto io_resume; 418279697Snon 418379697Snon case MSGPH_TERM: 418479697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 418579697Snon scsi_low_msginfunc_cc(slp); 418679697Snon goto io_resume; 418779697Snon 418879697Snon case MSGPH_DISC: 418979697Snon if (cb != NULL) 419067468Snon { 419179697Snon struct lun_info *li; 419279697Snon 419379697Snon li = cb->li; 419479697Snon TAILQ_INSERT_TAIL(&li->li_discq, cb, ccb_chain); 419579697Snon cb->ccb_flags |= CCB_DISCQ; 419679697Snon cb->ccb_error |= slp->sl_error; 419779697Snon li->li_disc ++; 419879697Snon ti->ti_disc ++; 419979697Snon slp->sl_disc ++; 420079697Snon } 420179697Snon 420279697Snon#ifdef SCSI_LOW_STATICS 420379697Snon scsi_low_statics.nexus_disconnected ++; 420479697Snon#endif /* SCSI_LOW_STATICS */ 420579697Snon 420679697Snon#ifdef SCSI_LOW_DEBUG 420779697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DISC, ti->ti_id) != 0) 420879697Snon { 420979697Snon printf("## SCSI_LOW_DISCONNECTED ===============\n"); 421079697Snon scsi_low_print(slp, NULL); 421179697Snon } 421279697Snon#endif /* SCSI_LOW_DEBUG */ 421379697Snon break; 421479697Snon 421579697Snon case MSGPH_NULL: 421679697Snon slp->sl_error |= FATALIO; 421779697Snon if (ti->ti_phase == PH_SELSTART) 421879697Snon slp->sl_error |= SELTIMEOUTIO; 421979697Snon else 422079697Snon slp->sl_error |= UBFERR; 422179697Snon /* fall through */ 422279697Snon 422379697Snon case MSGPH_LCTERM: 422479697Snon case MSGPH_CMDC: 422579697Snonio_resume: 422679697Snon if (cb == NULL) 422779697Snon break; 422879697Snon 422979697Snon#ifdef SCSI_LOW_DEBUG 423079697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 423179697Snon { 423279697Snon if (cb->ccb_omsgoutflag == SCSI_LOW_MSG_NOOP && 423379697Snon (cb->ccb_msgoutflag != 0 || 423479697Snon (ti->ti_msgflags & SCSI_LOW_MSG_NOOP))) 423579697Snon { 423679697Snon scsi_low_info(slp, ti, "ATTEN CHECK FAILED"); 423779697Snon } 423879697Snon } 423979697Snon#endif /* SCSI_LOW_DEBUG */ 424079697Snon 424179697Snon cb->ccb_error |= slp->sl_error; 424279697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 424379697Snon { 424479697Snon cb->ccb_flags |= CCB_STARTQ; 424579697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 424679697Snon } 424779697Snon break; 424879697Snon } 424979697Snon 425079697Snon scsi_low_bus_release(slp, ti); 425179697Snon scsi_low_start(slp); 425279697Snon return 1; 425379697Snon} 425479697Snon 425579697Snon/********************************************************** 425679697Snon * TAG operations 425779697Snon **********************************************************/ 4258104094Sphkstatic int 425979697Snonscsi_low_alloc_qtag(cb) 426079697Snon struct slccb *cb; 426179697Snon{ 426279697Snon struct lun_info *li = cb->li; 426379697Snon scsi_low_tag_t etag; 426479697Snon 426579697Snon if (cb->ccb_otag != SCSI_LOW_UNKTAG) 426679697Snon return 0; 426779697Snon 426879697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 426979697Snon etag = ffs(li->li_qtagbits); 427079697Snon if (etag == 0) 427179697Snon return ENOSPC; 427279697Snon 427379697Snon li->li_qtagbits &= ~(1 << (etag - 1)); 427479697Snon cb->ccb_otag = etag; 427579697Snon return 0; 427679697Snon 427779697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 427879697Snon for (etag = li->li_qd ; li->li_qd < SCSI_LOW_MAXNEXUS; li->li_qd ++) 427979697Snon if (li->li_qtagarray[li->li_qd] == 0) 428079697Snon goto found; 428179697Snon 428279697Snon for (li->li_qd = 0; li->li_qd < etag; li->li_qd ++) 428379697Snon if (li->li_qtagarray[li->li_qd] == 0) 428479697Snon goto found; 428579697Snon 428679697Snon return ENOSPC; 428779697Snon 428879697Snonfound: 428979697Snon li->li_qtagarray[li->li_qd] ++; 429079697Snon cb->ccb_otag = (li->li_qd ++); 429179697Snon return 0; 429279697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 429379697Snon} 429479697Snon 4295104094Sphkstatic int 429679697Snonscsi_low_dealloc_qtag(cb) 429779697Snon struct slccb *cb; 429879697Snon{ 429979697Snon struct lun_info *li = cb->li; 430079697Snon scsi_low_tag_t etag; 430179697Snon 430279697Snon if (cb->ccb_otag == SCSI_LOW_UNKTAG) 430379697Snon return 0; 430479697Snon 430579697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 430679697Snon etag = cb->ccb_otag - 1; 430767468Snon#ifdef SCSI_LOW_DIAGNOSTIC 430879697Snon if (etag >= sizeof(li->li_qtagbits) * NBBY) 430979697Snon panic("scsi_low_dealloc_tag: illegal tag"); 431067468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 431179697Snon li->li_qtagbits |= (1 << etag); 431279697Snon 431379697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 431479697Snon etag = cb->ccb_otag; 431579697Snon#ifdef SCSI_LOW_DIAGNOSTIC 431679697Snon if (etag >= SCSI_LOW_MAXNEXUS) 431779697Snon panic("scsi_low_dealloc_tag: illegal tag"); 431879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 431979697Snon li->li_qtagarray[etag] --; 432079697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 432179697Snon 432279697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 432379697Snon return 0; 432479697Snon} 432579697Snon 4326104094Sphkstatic struct slccb * 432779697Snonscsi_low_revoke_ccb(slp, cb, fdone) 432879697Snon struct scsi_low_softc *slp; 432979697Snon struct slccb *cb; 433079697Snon int fdone; 433179697Snon{ 433279697Snon struct targ_info *ti = cb->ti; 433379697Snon struct lun_info *li = cb->li; 433479697Snon 433579697Snon#ifdef SCSI_LOW_DIAGNOSTIC 433679697Snon if ((cb->ccb_flags & (CCB_STARTQ | CCB_DISCQ)) == 433779697Snon (CCB_STARTQ | CCB_DISCQ)) 433879697Snon { 4339106890Simp panic("%s: ccb in both queue", slp->sl_xname); 434067468Snon } 434179697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 434267468Snon 434379697Snon if ((cb->ccb_flags & CCB_STARTQ) != 0) 434479697Snon { 434579697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 434679697Snon } 434779697Snon 434879697Snon if ((cb->ccb_flags & CCB_DISCQ) != 0) 434979697Snon { 435079697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 435179697Snon li->li_disc --; 435279697Snon ti->ti_disc --; 435379697Snon slp->sl_disc --; 435479697Snon } 435579697Snon 435679697Snon cb->ccb_flags &= ~(CCB_STARTQ | CCB_DISCQ | 435779697Snon CCB_SENSE | CCB_CLEARQ | CCB_INTERNAL); 435879697Snon 435979697Snon if (fdone != 0 && 436079697Snon (cb->ccb_rcnt ++ >= slp->sl_max_retry || 436179697Snon (cb->ccb_flags & CCB_NORETRY) != 0)) 436279697Snon { 436379697Snon cb->ccb_error |= FATALIO; 436479697Snon cb->ccb_flags &= ~CCB_AUTOSENSE; 436579697Snon if (scsi_low_done(slp, cb) != SCSI_LOW_DONE_COMPLETE) 4366106890Simp panic("%s: done ccb retried", slp->sl_xname); 436779697Snon return NULL; 436879697Snon } 436979697Snon else 437079697Snon { 437179697Snon cb->ccb_error |= PENDINGIO; 437279697Snon scsi_low_deactivate_qtag(cb); 437379697Snon scsi_low_ccb_message_retry(cb); 437479697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 437579697Snon return cb; 437679697Snon } 437767468Snon} 437867468Snon 4379104094Sphkstatic void 438079697Snonscsi_low_reset_nexus_lun(slp, li, fdone) 438179697Snon struct scsi_low_softc *slp; 438279697Snon struct lun_info *li; 438379697Snon int fdone; 438479697Snon{ 438579697Snon struct slccb *cb, *ncb, *ecb; 438679697Snon 438779697Snon if (li == NULL) 438879697Snon return; 438979697Snon 439079697Snon ecb = NULL; 439179697Snon for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; cb = ncb) 439279697Snon { 439379697Snon ncb = TAILQ_NEXT(cb, ccb_chain); 439479697Snon cb = scsi_low_revoke_ccb(slp, cb, fdone); 439579697Snon if (cb != NULL) 439679697Snon { 439779697Snon /* 439879697Snon * presumely keep ordering of io 439979697Snon */ 440079697Snon cb->ccb_flags |= CCB_STARTQ; 440179697Snon if (ecb == NULL) 440279697Snon { 440379697Snon TAILQ_INSERT_HEAD(&slp->sl_start,\ 440479697Snon cb, ccb_chain); 440579697Snon } 440679697Snon else 440779697Snon { 440879697Snon TAILQ_INSERT_AFTER(&slp->sl_start,\ 440979697Snon ecb, cb, ccb_chain); 441079697Snon } 441179697Snon ecb = cb; 441279697Snon } 441379697Snon } 441479697Snon} 441579697Snon 441667468Snon/************************************************************** 441767468Snon * Qurik setup 441867468Snon **************************************************************/ 441967468Snonstatic void 442079697Snonscsi_low_calcf_lun(li) 442167468Snon struct lun_info *li; 442267468Snon{ 442379697Snon struct targ_info *ti = li->li_ti; 442467468Snon struct scsi_low_softc *slp = ti->ti_sc; 442579697Snon u_int cfgflags, diskflags; 442667468Snon 442779697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID) 442879697Snon cfgflags = li->li_cfgflags; 442979697Snon else 443079697Snon cfgflags = 0; 443179697Snon 443279697Snon diskflags = li->li_diskflags & li->li_quirks; 443379697Snon 443479697Snon /* disconnect */ 443567468Snon li->li_flags &= ~SCSI_LOW_DISC; 443667468Snon if ((slp->sl_cfgflags & CFG_NODISC) == 0 && 443779697Snon (diskflags & SCSI_LOW_DISK_DISC) != 0 && 443879697Snon (cfgflags & SCSI_LOW_DISC) != 0) 443967468Snon li->li_flags |= SCSI_LOW_DISC; 444067468Snon 444179697Snon /* parity */ 444267468Snon li->li_flags |= SCSI_LOW_NOPARITY; 444367468Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0 && 444479697Snon (diskflags & SCSI_LOW_DISK_PARITY) != 0 && 444579697Snon (cfgflags & SCSI_LOW_NOPARITY) == 0) 444667468Snon li->li_flags &= ~SCSI_LOW_NOPARITY; 444767468Snon 444879697Snon /* qtag */ 444979697Snon if ((slp->sl_cfgflags & CFG_NOQTAG) == 0 && 445079697Snon (cfgflags & SCSI_LOW_QTAG) != 0 && 445179697Snon (diskflags & SCSI_LOW_DISK_QTAG) != 0) 445279697Snon { 445379697Snon li->li_flags |= SCSI_LOW_QTAG; 445479697Snon li->li_maxnexus = SCSI_LOW_MAXNEXUS; 445579697Snon li->li_maxnqio = li->li_maxnexus; 445679697Snon } 445779697Snon else 445879697Snon { 445979697Snon li->li_flags &= ~SCSI_LOW_QTAG; 446079697Snon li->li_maxnexus = 0; 446179697Snon li->li_maxnqio = li->li_maxnexus; 446279697Snon } 446379697Snon 446479697Snon /* cmd link */ 446579697Snon li->li_flags &= ~SCSI_LOW_LINK; 446679697Snon if ((cfgflags & SCSI_LOW_LINK) != 0 && 446779697Snon (diskflags & SCSI_LOW_DISK_LINK) != 0) 446879697Snon li->li_flags |= SCSI_LOW_LINK; 446979697Snon 447079697Snon /* compatible flags */ 447167468Snon li->li_flags &= ~SCSI_LOW_SYNC; 447279697Snon if (ti->ti_maxsynch.offset > 0) 447379697Snon li->li_flags |= SCSI_LOW_SYNC; 447479697Snon 447579697Snon#ifdef SCSI_LOW_DEBUG 447679697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 447767468Snon { 447879697Snon scsi_low_calcf_show(li); 447967468Snon } 448079697Snon#endif /* SCSI_LOW_DEBUG */ 448179697Snon} 448279697Snon 448379697Snonstatic void 448479697Snonscsi_low_calcf_target(ti) 448579697Snon struct targ_info *ti; 448679697Snon{ 448779697Snon struct scsi_low_softc *slp = ti->ti_sc; 448879697Snon u_int offset, period, diskflags; 448979697Snon 449079697Snon diskflags = ti->ti_diskflags & ti->ti_quirks; 449179697Snon 449279697Snon /* synch */ 449379697Snon if ((slp->sl_cfgflags & CFG_ASYNC) == 0 && 449479697Snon (diskflags & SCSI_LOW_DISK_SYNC) != 0) 449579697Snon { 449679697Snon offset = ti->ti_maxsynch.offset; 449779697Snon period = ti->ti_maxsynch.period; 449879697Snon if (offset == 0 || period == 0) 449979697Snon offset = period = 0; 450079697Snon } 450167468Snon else 450279697Snon { 450379697Snon offset = period = 0; 450479697Snon } 450567468Snon 450679697Snon ti->ti_maxsynch.offset = offset; 450779697Snon ti->ti_maxsynch.period = period; 450879697Snon 450979697Snon /* wide */ 451079697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_32) == 0 && 451179697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 451279697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_16; 451379697Snon 451479697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_16) == 0 && 451579697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 451679697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 451779697Snon 451879697Snon if (ti->ti_flags_valid == SCSI_LOW_TARG_FLAGS_ALL_VALID) 451967468Snon { 452079697Snon if (ti->ti_maxsynch.offset != ti->ti_osynch.offset || 452179697Snon ti->ti_maxsynch.period != ti->ti_osynch.period) 452279697Snon ti->ti_setup_msg |= SCSI_LOW_MSG_SYNCH; 452379697Snon if (ti->ti_width != ti->ti_owidth) 452479697Snon ti->ti_setup_msg |= (SCSI_LOW_MSG_WIDE | SCSI_LOW_MSG_SYNCH); 452579697Snon 452679697Snon ti->ti_osynch = ti->ti_maxsynch; 452779697Snon ti->ti_owidth = ti->ti_width; 452867468Snon } 452967468Snon 453079697Snon#ifdef SCSI_LOW_DEBUG 453179697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 453279697Snon { 453379697Snon printf("%s(%d:*): max period(%dns) offset(%d) width(%d)\n", 453479697Snon slp->sl_xname, ti->ti_id, 453579697Snon ti->ti_maxsynch.period * 4, 453679697Snon ti->ti_maxsynch.offset, 453779697Snon ti->ti_width); 453879697Snon } 453979697Snon#endif /* SCSI_LOW_DEBUG */ 454067468Snon} 454167468Snon 454279697Snonstatic void 454379697Snonscsi_low_calcf_show(li) 454479697Snon struct lun_info *li; 454579697Snon{ 454679697Snon struct targ_info *ti = li->li_ti; 454779697Snon struct scsi_low_softc *slp = ti->ti_sc; 454879697Snon 454979697Snon printf("%s(%d:%d): period(%d ns) offset(%d) width(%d) flags 0x%b\n", 455079697Snon slp->sl_xname, ti->ti_id, li->li_lun, 455179697Snon ti->ti_maxsynch.period * 4, 455279697Snon ti->ti_maxsynch.offset, 455379697Snon ti->ti_width, 455479697Snon li->li_flags, SCSI_LOW_BITS); 455579697Snon} 455679697Snon 455779697Snon#ifdef SCSI_LOW_START_UP_CHECK 455879697Snon/************************************************************** 455979697Snon * scsi world start up 456079697Snon **************************************************************/ 456192770Salfredstatic int scsi_low_poll(struct scsi_low_softc *, struct slccb *); 456279697Snon 456367468Snonstatic int 456479697Snonscsi_low_start_up(slp) 456579697Snon struct scsi_low_softc *slp; 456667468Snon{ 456767468Snon struct targ_info *ti; 456867468Snon struct lun_info *li; 456979697Snon struct slccb *cb; 457079697Snon int target, lun; 457167468Snon 457279697Snon printf("%s: scsi_low: probing all devices ....\n", slp->sl_xname); 457367468Snon 457479697Snon for (target = 0; target < slp->sl_ntargs; target ++) 457579697Snon { 457679697Snon if (target == slp->sl_hostid) 457779697Snon { 457879697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 457979697Snon { 458079697Snon printf("%s: scsi_low: target %d (host card)\n", 458179697Snon slp->sl_xname, target); 458279697Snon } 458379697Snon continue; 458479697Snon } 458567468Snon 458679697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 458779697Snon { 458879697Snon printf("%s: scsi_low: target %d lun ", 458979697Snon slp->sl_xname, target); 459079697Snon } 459167468Snon 459279697Snon ti = slp->sl_ti[target]; 459379697Snon for (lun = 0; lun < slp->sl_nluns; lun ++) 459479697Snon { 459579697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 459679697Snon break; 459779697Snon 459879697Snon cb->osdep = NULL; 459979697Snon cb->bp = NULL; 460079697Snon 460179697Snon li = scsi_low_alloc_li(ti, lun, 1); 460279697Snon 460379697Snon scsi_low_enqueue(slp, ti, li, cb, 460479697Snon CCB_AUTOSENSE | CCB_POLLED, 0); 460579697Snon 460679697Snon scsi_low_poll(slp, cb); 460779697Snon 460879697Snon if (li->li_state != SCSI_LOW_LUN_OK) 460979697Snon break; 461079697Snon 461179697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 461279697Snon { 461379697Snon printf("%d ", lun); 461479697Snon } 461579697Snon } 461679697Snon 461779697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 461879697Snon { 461979697Snon printf("\n"); 462079697Snon } 462179697Snon } 462267468Snon return 0; 462367468Snon} 462467468Snon 462579697Snonstatic int 462679697Snonscsi_low_poll(slp, cb) 462779697Snon struct scsi_low_softc *slp; 462879697Snon struct slccb *cb; 462979697Snon{ 463079697Snon int tcount; 463179697Snon 463279697Snon tcount = 0; 463379697Snon while (slp->sl_nio > 0) 463479697Snon { 463579697Snon SCSI_LOW_DELAY((1000 * 1000) / SCSI_LOW_POLL_HZ); 463679697Snon 463779697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 463879697Snon if (tcount ++ < SCSI_LOW_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 463979697Snon continue; 464079697Snon 464179697Snon tcount = 0; 464279697Snon scsi_low_timeout_check(slp); 464379697Snon } 464479697Snon 464579697Snon return 0; 464679697Snon} 464779697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 464879697Snon 464967468Snon/********************************************************** 465067468Snon * DEBUG SECTION 465167468Snon **********************************************************/ 465279697Snon#ifdef SCSI_LOW_DEBUG 465367468Snonstatic void 465479697Snonscsi_low_test_abort(slp, ti, li) 465579697Snon struct scsi_low_softc *slp; 465679697Snon struct targ_info *ti; 465779697Snon struct lun_info *li; 465879697Snon{ 465979697Snon struct slccb *acb; 466079697Snon 466179697Snon if (li->li_disc > 1) 466279697Snon { 466379697Snon acb = TAILQ_FIRST(&li->li_discq); 466479697Snon if (scsi_low_abort_ccb(slp, acb) == 0) 466579697Snon { 466679697Snon printf("%s: aborting ccb(0x%lx) start\n", 466779697Snon slp->sl_xname, (u_long) acb); 466879697Snon } 466979697Snon } 467079697Snon} 467179697Snon 467279697Snonstatic void 467379697Snonscsi_low_test_atten(slp, ti, msg) 467479697Snon struct scsi_low_softc *slp; 467579697Snon struct targ_info *ti; 467679697Snon u_int msg; 467779697Snon{ 467879697Snon 467979697Snon if (slp->sl_ph_count < SCSI_LOW_MAX_ATTEN_CHECK) 468079697Snon scsi_low_assert_msg(slp, ti, msg, 0); 468179697Snon else 468279697Snon printf("%s: atten check OK\n", slp->sl_xname); 468379697Snon} 468479697Snon 468579697Snonstatic void 468679697Snonscsi_low_test_cmdlnk(slp, cb) 468779697Snon struct scsi_low_softc *slp; 468879697Snon struct slccb *cb; 468979697Snon{ 469079697Snon#define SCSI_LOW_CMDLNK_NOK (CCB_INTERNAL | CCB_SENSE | CCB_CLEARQ) 469179697Snon 469279697Snon if ((cb->ccb_flags & SCSI_LOW_CMDLNK_NOK) != 0) 469379697Snon return; 469479697Snon 469579697Snon memcpy(cb->ccb_scsi_cmd, slp->sl_scp.scp_cmd, 469679697Snon slp->sl_scp.scp_cmdlen); 469779697Snon cb->ccb_scsi_cmd[slp->sl_scp.scp_cmdlen - 1] |= 1; 469879697Snon slp->sl_scp.scp_cmd = cb->ccb_scsi_cmd; 469979697Snon} 470079697Snon#endif /* SCSI_LOW_DEBUG */ 470179697Snon 470279697Snon/* static */ void 470367468Snonscsi_low_info(slp, ti, s) 470467468Snon struct scsi_low_softc *slp; 470567468Snon struct targ_info *ti; 470667468Snon u_char *s; 470767468Snon{ 470867468Snon 470979697Snon if (slp == NULL) 471079697Snon slp = LIST_FIRST(&sl_tab); 471179697Snon if (s == NULL) 471279697Snon s = "no message"; 471379697Snon 471479697Snon printf(">>>>> SCSI_LOW_INFO(0x%lx): %s\n", (u_long) slp->sl_Tnexus, s); 471567468Snon if (ti == NULL) 471667468Snon { 471779697Snon for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 471879697Snon ti = TAILQ_NEXT(ti, ti_chain)) 471979697Snon { 472067468Snon scsi_low_print(slp, ti); 472179697Snon } 472267468Snon } 472367468Snon else 472479697Snon { 472567468Snon scsi_low_print(slp, ti); 472679697Snon } 472767468Snon} 472867468Snon 472967468Snonstatic u_char *phase[] = 473067468Snon{ 473167468Snon "FREE", "ARBSTART", "SELSTART", "SELECTED", 473267468Snon "CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", "RESEL" 473367468Snon}; 473467468Snon 473567468Snonvoid 473667468Snonscsi_low_print(slp, ti) 473767468Snon struct scsi_low_softc *slp; 473867468Snon struct targ_info *ti; 473967468Snon{ 474079697Snon struct lun_info *li; 474179697Snon struct slccb *cb; 474279697Snon struct sc_p *sp; 474367468Snon 474479697Snon if (ti == NULL || ti == slp->sl_Tnexus) 474579697Snon { 474679697Snon ti = slp->sl_Tnexus; 474779697Snon li = slp->sl_Lnexus; 474879697Snon cb = slp->sl_Qnexus; 474979697Snon } 475079697Snon else 475179697Snon { 475279697Snon li = LIST_FIRST(&ti->ti_litab); 475379697Snon cb = TAILQ_FIRST(&li->li_discq); 475479697Snon } 475579697Snon sp = &slp->sl_scp; 475667468Snon 475779697Snon printf("%s: === NEXUS T(0x%lx) L(0x%lx) Q(0x%lx) NIO(%d) ===\n", 475879697Snon slp->sl_xname, (u_long) ti, (u_long) li, (u_long) cb, 475979697Snon slp->sl_nio); 476067468Snon 476167468Snon /* target stat */ 476267468Snon if (ti != NULL) 476367468Snon { 476479697Snon u_int flags = 0, maxnqio = 0, nqio = 0; 4765265633Smav int lun = CAM_LUN_WILDCARD; 476667468Snon 476767468Snon if (li != NULL) 476867468Snon { 476967468Snon lun = li->li_lun; 477067468Snon flags = li->li_flags; 477179697Snon maxnqio = li->li_maxnqio; 477279697Snon nqio = li->li_nqio; 477367468Snon } 477467468Snon 477579697Snon printf("%s(%d:%d) ph<%s> => ph<%s> DISC(%d) QIO(%d:%d)\n", 477679697Snon slp->sl_xname, 477767468Snon ti->ti_id, lun, phase[(int) ti->ti_ophase], 477879697Snon phase[(int) ti->ti_phase], ti->ti_disc, 477979697Snon nqio, maxnqio); 478067468Snon 478179697Snon if (cb != NULL) 478279697Snon { 478379697Snonprintf("CCB: cmd[0] 0x%x clen 0x%x dlen 0x%x<0x%x stat 0x%x err %b\n", 478479697Snon (u_int) cb->ccb_scp.scp_cmd[0], 478579697Snon cb->ccb_scp.scp_cmdlen, 478679697Snon cb->ccb_datalen, 478779697Snon cb->ccb_scp.scp_datalen, 478879697Snon (u_int) cb->ccb_sscp.scp_status, 478979697Snon cb->ccb_error, SCSI_LOW_ERRORBITS); 479079697Snon } 479167468Snon 479279697Snonprintf("MSGIN: ptr(%x) [%x][%x][%x][%x][%x] attention: %d\n", 479379697Snon (u_int) (ti->ti_msginptr), 479479697Snon (u_int) (ti->ti_msgin[0]), 479579697Snon (u_int) (ti->ti_msgin[1]), 479679697Snon (u_int) (ti->ti_msgin[2]), 479779697Snon (u_int) (ti->ti_msgin[3]), 479879697Snon (u_int) (ti->ti_msgin[4]), 479979697Snon slp->sl_atten); 480079697Snon 480167468Snonprintf("MSGOUT: msgflags 0x%x [%x][%x][%x][%x][%x] msgoutlen %d C_FLAGS: %b\n", 480279697Snon (u_int) ti->ti_msgflags, 480379697Snon (u_int) (ti->ti_msgoutstr[0]), 480479697Snon (u_int) (ti->ti_msgoutstr[1]), 480579697Snon (u_int) (ti->ti_msgoutstr[2]), 480679697Snon (u_int) (ti->ti_msgoutstr[3]), 480779697Snon (u_int) (ti->ti_msgoutstr[4]), 480879697Snon ti->ti_msgoutlen, 480979697Snon flags, SCSI_LOW_BITS); 481067468Snon 481179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 481279697Snon scsi_low_msg_log_show(&ti->ti_log_msgin, "MIN LOG ", 2); 481379697Snon scsi_low_msg_log_show(&ti->ti_log_msgout, "MOUT LOG", 2); 481479697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 481567468Snon 481667468Snon } 481779697Snon 481879697Snon printf("SCB: daddr 0x%lx dlen 0x%x stat 0x%x err %b\n", 481979697Snon (u_long) sp->scp_data, 482079697Snon sp->scp_datalen, 482179697Snon (u_int) sp->scp_status, 482279697Snon slp->sl_error, SCSI_LOW_ERRORBITS); 482367468Snon} 4824