scsi_low.c revision 274760
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: head/sys/cam/scsi/scsi_low.c 274760 2014-11-20 20:50:05Z jhb $"); 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 1779697Snon#define SCSI_LOW_FLAGS_QUIRKS_OK 1879697Snon 19139743Simp/*- 2067468Snon * [NetBSD for NEC PC-98 series] 2179697Snon * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 2267468Snon * NetBSD/pc98 porting staff. All rights reserved. 2379697Snon * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 2467468Snon * Naofumi HONDA. All rights reserved. 2579697Snon * 2679697Snon * [Ported for FreeBSD CAM] 2779697Snon * Copyright (c) 2000, 2001 2879697Snon * MITSUNAGA Noriaki, NOKUBI Hirotaka and TAKAHASHI Yoshihiro. 2979697Snon * All rights reserved. 3067468Snon * 3167468Snon * Redistribution and use in source and binary forms, with or without 3267468Snon * modification, are permitted provided that the following conditions 3367468Snon * are met: 3467468Snon * 1. Redistributions of source code must retain the above copyright 3567468Snon * notice, this list of conditions and the following disclaimer. 3667468Snon * 2. Redistributions in binary form must reproduce the above copyright 3767468Snon * notice, this list of conditions and the following disclaimer in the 3867468Snon * documentation and/or other materials provided with the distribution. 3967468Snon * 3. The name of the author may not be used to endorse or promote products 4067468Snon * derived from this software without specific prior written permission. 4167468Snon * 4267468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 4367468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 4467468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 4567468Snon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 4667468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 4767468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 4867468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4967468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 5067468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 5167468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 5267468Snon * POSSIBILITY OF SUCH DAMAGE. 5367468Snon */ 5467468Snon 5567468Snon/* <On the nexus establishment> 5667468Snon * When our host is reselected, 5767468Snon * nexus establish processes are little complicated. 5867468Snon * Normal steps are followings: 5979697Snon * 1) Our host selected by target => target nexus (slp->sl_Tnexus) 6079697Snon * 2) Identify msgin => lun nexus (slp->sl_Lnexus) 6179697Snon * 3) Qtag msg => ccb nexus (slp->sl_Qnexus) 6267468Snon */ 6367468Snon#include "opt_ddb.h" 6467468Snon 6567468Snon#include <sys/param.h> 6667468Snon#include <sys/systm.h> 6767468Snon#include <sys/kernel.h> 6867468Snon#include <sys/bio.h> 6967468Snon#include <sys/buf.h> 7067468Snon#include <sys/queue.h> 7167468Snon#include <sys/malloc.h> 7267468Snon#include <sys/errno.h> 7367468Snon 7467468Snon#include <cam/cam.h> 7567468Snon#include <cam/cam_ccb.h> 7667468Snon#include <cam/cam_sim.h> 7767468Snon#include <cam/cam_debug.h> 7867468Snon#include <cam/cam_periph.h> 79147723Savatar#include <cam/cam_xpt_periph.h> 8067468Snon 8167468Snon#include <cam/scsi/scsi_all.h> 8273025Snon#include <cam/scsi/scsi_message.h> 8367468Snon 8467468Snon#include <cam/scsi/scsi_low.h> 8567468Snon 8667468Snon#include <sys/cons.h> 8767468Snon 8879697Snon/************************************************************** 8979697Snon * Constants 9079697Snon **************************************************************/ 9179697Snon#define SCSI_LOW_POLL_HZ 1000 9267468Snon 9379697Snon/* functions return values */ 9479697Snon#define SCSI_LOW_START_NO_QTAG 0 9579697Snon#define SCSI_LOW_START_QTAG 1 9679697Snon 9767468Snon#define SCSI_LOW_DONE_COMPLETE 0 9867468Snon#define SCSI_LOW_DONE_RETRY 1 9967468Snon 10079697Snon/* internal disk flags */ 10179697Snon#define SCSI_LOW_DISK_DISC 0x00000001 10279697Snon#define SCSI_LOW_DISK_QTAG 0x00000002 10379697Snon#define SCSI_LOW_DISK_LINK 0x00000004 10479697Snon#define SCSI_LOW_DISK_PARITY 0x00000008 10579697Snon#define SCSI_LOW_DISK_SYNC 0x00010000 10679697Snon#define SCSI_LOW_DISK_WIDE_16 0x00020000 10779697Snon#define SCSI_LOW_DISK_WIDE_32 0x00040000 10879697Snon#define SCSI_LOW_DISK_WIDE (SCSI_LOW_DISK_WIDE_16 | SCSI_LOW_DISK_WIDE_32) 10979697Snon#define SCSI_LOW_DISK_LFLAGS 0x0000ffff 11079697Snon#define SCSI_LOW_DISK_TFLAGS 0xffff0000 11179697Snon 112227293Sedstatic MALLOC_DEFINE(M_SCSILOW, "SCSI low", "SCSI low buffers"); 113147723Savatar 11479697Snon/************************************************************** 11579697Snon * Declarations 11679697Snon **************************************************************/ 11792770Salfred/* static */ void scsi_low_info(struct scsi_low_softc *, struct targ_info *, u_char *); 11892770Salfredstatic void scsi_low_engage(void *); 11992770Salfredstatic struct slccb *scsi_low_establish_ccb(struct targ_info *, struct lun_info *, scsi_low_tag_t); 12092770Salfredstatic int scsi_low_done(struct scsi_low_softc *, struct slccb *); 12192770Salfredstatic int scsi_low_setup_done(struct scsi_low_softc *, struct slccb *); 12292770Salfredstatic void scsi_low_bus_release(struct scsi_low_softc *, struct targ_info *); 12392770Salfredstatic void scsi_low_twiddle_wait(void); 12492770Salfredstatic struct lun_info *scsi_low_alloc_li(struct targ_info *, int, int); 12592770Salfredstatic struct targ_info *scsi_low_alloc_ti(struct scsi_low_softc *, int); 12692770Salfredstatic void scsi_low_calcf_lun(struct lun_info *); 12792770Salfredstatic void scsi_low_calcf_target(struct targ_info *); 12892770Salfredstatic void scsi_low_calcf_show(struct lun_info *); 12992770Salfredstatic void scsi_low_reset_nexus(struct scsi_low_softc *, int); 13092770Salfredstatic void scsi_low_reset_nexus_target(struct scsi_low_softc *, struct targ_info *, int); 13192770Salfredstatic void scsi_low_reset_nexus_lun(struct scsi_low_softc *, struct lun_info *, int); 13292770Salfredstatic int scsi_low_init(struct scsi_low_softc *, u_int); 13392770Salfredstatic void scsi_low_start(struct scsi_low_softc *); 13492770Salfredstatic void scsi_low_free_ti(struct scsi_low_softc *); 13567468Snon 13692770Salfredstatic int scsi_low_alloc_qtag(struct slccb *); 13792770Salfredstatic int scsi_low_dealloc_qtag(struct slccb *); 13892770Salfredstatic int scsi_low_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *, u_int, u_int); 13992770Salfredstatic int scsi_low_message_enqueue(struct scsi_low_softc *, struct targ_info *, struct lun_info *, u_int); 14092770Salfredstatic void scsi_low_unit_ready_cmd(struct slccb *); 14192770Salfredstatic void scsi_low_timeout(void *); 14292770Salfredstatic int scsi_low_timeout_check(struct scsi_low_softc *); 14379697Snon#ifdef SCSI_LOW_START_UP_CHECK 14492770Salfredstatic int scsi_low_start_up(struct scsi_low_softc *); 14579697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 14692770Salfredstatic int scsi_low_abort_ccb(struct scsi_low_softc *, struct slccb *); 14792770Salfredstatic struct slccb *scsi_low_revoke_ccb(struct scsi_low_softc *, struct slccb *, int); 14879697Snon 14979697Snonint scsi_low_version_major = 2; 15079697Snonint scsi_low_version_minor = 17; 15179697Snon 15279697Snonstatic struct scsi_low_softc_tab sl_tab = LIST_HEAD_INITIALIZER(sl_tab); 153274760Sjhbstatic struct mtx sl_tab_lock; 154274760SjhbMTX_SYSINIT(sl_tab_lock, &sl_tab_lock, "scsi low table", MTX_DEF); 15579697Snon 15679697Snon/************************************************************** 15779697Snon * Debug, Run test and Statics 15879697Snon **************************************************************/ 15979697Snon#ifdef SCSI_LOW_INFO_DETAIL 16079697Snon#define SCSI_LOW_INFO(slp, ti, s) scsi_low_info((slp), (ti), (s)) 16179697Snon#else /* !SCSI_LOW_INFO_DETAIL */ 162240325Sjhb#define SCSI_LOW_INFO(slp, ti, s) device_printf((slp)->sl_dev, "%s\n", (s)) 16379697Snon#endif /* !SCSI_LOW_INFO_DETAIL */ 16479697Snon 16567468Snon#ifdef SCSI_LOW_STATICS 16689113Smsmithstatic struct scsi_low_statics { 16767468Snon int nexus_win; 16867468Snon int nexus_fail; 16967468Snon int nexus_disconnected; 17067468Snon int nexus_reselected; 17167468Snon int nexus_conflict; 17267468Snon} scsi_low_statics; 17367468Snon#endif /* SCSI_LOW_STATICS */ 17479697Snon 17579697Snon#ifdef SCSI_LOW_DEBUG 17679697Snon#define SCSI_LOW_DEBUG_DONE 0x00001 17779697Snon#define SCSI_LOW_DEBUG_DISC 0x00002 17879697Snon#define SCSI_LOW_DEBUG_SENSE 0x00004 17979697Snon#define SCSI_LOW_DEBUG_CALCF 0x00008 18079697Snon#define SCSI_LOW_DEBUG_ACTION 0x10000 18179697Snonint scsi_low_debug = 0; 18279697Snon 18379697Snon#define SCSI_LOW_MAX_ATTEN_CHECK 32 18479697Snon#define SCSI_LOW_ATTEN_CHECK 0x0001 18579697Snon#define SCSI_LOW_CMDLNK_CHECK 0x0002 18679697Snon#define SCSI_LOW_ABORT_CHECK 0x0004 18779697Snon#define SCSI_LOW_NEXUS_CHECK 0x0008 18879697Snonint scsi_low_test = 0; 18979697Snonint scsi_low_test_id = 0; 19079697Snon 19192770Salfredstatic void scsi_low_test_abort(struct scsi_low_softc *, struct targ_info *, struct lun_info *); 19292770Salfredstatic void scsi_low_test_cmdlnk(struct scsi_low_softc *, struct slccb *); 19392770Salfredstatic void scsi_low_test_atten(struct scsi_low_softc *, struct targ_info *, u_int); 19479697Snon#define SCSI_LOW_DEBUG_TEST_GO(fl, id) \ 19579697Snon ((scsi_low_test & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 19679697Snon#define SCSI_LOW_DEBUG_GO(fl, id) \ 19779697Snon ((scsi_low_debug & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 19879697Snon#endif /* SCSI_LOW_DEBUG */ 19979697Snon 20067468Snon/************************************************************** 20179697Snon * CCB 20279697Snon **************************************************************/ 20379697SnonGENERIC_CCB_STATIC_ALLOC(scsi_low, slccb) 20479697SnonGENERIC_CCB(scsi_low, slccb, ccb_chain) 20579697Snon 20679697Snon/************************************************************** 20779697Snon * Inline functions 20879697Snon **************************************************************/ 20979697Snon#define SCSI_LOW_INLINE static __inline 21092770SalfredSCSI_LOW_INLINE void scsi_low_activate_qtag(struct slccb *); 21192770SalfredSCSI_LOW_INLINE void scsi_low_deactivate_qtag(struct slccb *); 21292770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_assert(struct slccb *, u_int); 21392770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_exec(struct scsi_low_softc *, struct slccb *); 21492770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_retry(struct slccb *); 21592770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_clear(struct slccb *); 21692770SalfredSCSI_LOW_INLINE void scsi_low_init_msgsys(struct scsi_low_softc *, struct targ_info *); 21779697Snon 21879697SnonSCSI_LOW_INLINE void 21979697Snonscsi_low_activate_qtag(cb) 22079697Snon struct slccb *cb; 22179697Snon{ 22279697Snon struct lun_info *li = cb->li; 22379697Snon 22479697Snon if (cb->ccb_tag != SCSI_LOW_UNKTAG) 22579697Snon return; 22679697Snon 22779697Snon li->li_nqio ++; 22879697Snon cb->ccb_tag = cb->ccb_otag; 22979697Snon} 23079697Snon 23179697SnonSCSI_LOW_INLINE void 23279697Snonscsi_low_deactivate_qtag(cb) 23379697Snon struct slccb *cb; 23479697Snon{ 23579697Snon struct lun_info *li = cb->li; 23679697Snon 23779697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 23879697Snon return; 23979697Snon 24079697Snon li->li_nqio --; 24179697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 24279697Snon} 24379697Snon 24479697SnonSCSI_LOW_INLINE void 24579697Snonscsi_low_ccb_message_exec(slp, cb) 24679697Snon struct scsi_low_softc *slp; 24779697Snon struct slccb *cb; 24879697Snon{ 24979697Snon 25079697Snon scsi_low_assert_msg(slp, cb->ti, cb->ccb_msgoutflag, 0); 25179697Snon cb->ccb_msgoutflag = 0; 25279697Snon} 25379697Snon 25479697SnonSCSI_LOW_INLINE void 25579697Snonscsi_low_ccb_message_assert(cb, msg) 25679697Snon struct slccb *cb; 25779697Snon u_int msg; 25879697Snon{ 25979697Snon 26079697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag = msg; 26179697Snon} 26279697Snon 26379697SnonSCSI_LOW_INLINE void 26479697Snonscsi_low_ccb_message_retry(cb) 26579697Snon struct slccb *cb; 26679697Snon{ 26779697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag; 26879697Snon} 26979697Snon 27079697SnonSCSI_LOW_INLINE void 27179697Snonscsi_low_ccb_message_clear(cb) 27279697Snon struct slccb *cb; 27379697Snon{ 27479697Snon cb->ccb_msgoutflag = 0; 27579697Snon} 27679697Snon 27779697SnonSCSI_LOW_INLINE void 27879697Snonscsi_low_init_msgsys(slp, ti) 27979697Snon struct scsi_low_softc *slp; 28079697Snon struct targ_info *ti; 28179697Snon{ 28279697Snon 28379697Snon ti->ti_msginptr = 0; 28479697Snon ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0; 28579697Snon SCSI_LOW_DEASSERT_ATN(slp); 28679697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL); 28779697Snon} 28879697Snon 28979697Snon/*============================================================= 29079697Snon * START OF OS switch (All OS depend fucntions should be here) 29179697Snon =============================================================*/ 29279697Snon/* common os depend utitlities */ 29379697Snon#define SCSI_LOW_CMD_RESIDUAL_CHK 0x0001 29479697Snon#define SCSI_LOW_CMD_ORDERED_QTAG 0x0002 29579697Snon#define SCSI_LOW_CMD_ABORT_WARNING 0x0004 29679697Snon 29779697Snonstatic u_int8_t scsi_low_cmd_flags[256] = { 29879697Snon/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 29979697Snon/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 30079697Snon/*1*/ 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 30179697Snon/*2*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 5, 5, 30279697Snon/*3*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 30379697Snon}; 30479697Snon 30579697Snonstruct scsi_low_error_code { 30679697Snon int error_bits; 30779697Snon int error_code; 30879697Snon}; 30979697Snon 31092770Salfredstatic struct slccb *scsi_low_find_ccb(struct scsi_low_softc *, u_int, u_int, void *); 31192770Salfredstatic int scsi_low_translate_error_code(struct slccb *, struct scsi_low_error_code *); 31279697Snon 31379697Snonstatic struct slccb * 31479697Snonscsi_low_find_ccb(slp, target, lun, osdep) 31579697Snon struct scsi_low_softc *slp; 31679697Snon u_int target, lun; 31779697Snon void *osdep; 31879697Snon{ 31979697Snon struct targ_info *ti; 32079697Snon struct lun_info *li; 32179697Snon struct slccb *cb; 32279697Snon 32379697Snon ti = slp->sl_ti[target]; 32479697Snon li = scsi_low_alloc_li(ti, lun, 0); 32579697Snon if (li == NULL) 32679697Snon return NULL; 32779697Snon 32879697Snon if ((cb = slp->sl_Qnexus) != NULL && cb->osdep == osdep) 32979697Snon return cb; 33079697Snon 331270225Sjhb TAILQ_FOREACH(cb, &slp->sl_start, ccb_chain) 33279697Snon { 33379697Snon if (cb->osdep == osdep) 33479697Snon return cb; 33579697Snon } 33679697Snon 337270225Sjhb TAILQ_FOREACH(cb, &li->li_discq, ccb_chain) 33879697Snon { 33979697Snon if (cb->osdep == osdep) 34079697Snon return cb; 34179697Snon } 34279697Snon return NULL; 34379697Snon} 34479697Snon 34579697Snonstatic int 34679697Snonscsi_low_translate_error_code(cb, tp) 34779697Snon struct slccb *cb; 34879697Snon struct scsi_low_error_code *tp; 34979697Snon{ 35079697Snon 35179697Snon if (cb->ccb_error == 0) 35279697Snon return tp->error_code; 35379697Snon 35479697Snon for (tp ++; (cb->ccb_error & tp->error_bits) == 0; tp ++) 35579697Snon ; 35679697Snon return tp->error_code; 35779697Snon} 35879697Snon 35979697Snon/************************************************************** 36079697Snon * SCSI INTERFACE (CAM) 36179697Snon **************************************************************/ 362147723Savatar#define SCSI_LOW_MALLOC(size) malloc((size), M_SCSILOW, M_NOWAIT) 363147723Savatar#define SCSI_LOW_FREE(pt) free((pt), M_SCSILOW) 36479697Snon#define SCSI_LOW_ALLOC_CCB(flags) scsi_low_get_ccb() 36579697Snon 36692770Salfredstatic void scsi_low_poll_cam(struct cam_sim *); 36792770Salfredvoid scsi_low_scsi_action_cam(struct cam_sim *, union ccb *); 36879697Snon 36992770Salfredstatic int scsi_low_attach_cam(struct scsi_low_softc *); 370274760Sjhbstatic int scsi_low_detach_cam(struct scsi_low_softc *); 37192770Salfredstatic int scsi_low_ccb_setup_cam(struct scsi_low_softc *, struct slccb *); 37292770Salfredstatic int scsi_low_done_cam(struct scsi_low_softc *, struct slccb *); 37379697Snon 37479697Snonstruct scsi_low_error_code scsi_low_error_code_cam[] = { 37579697Snon {0, CAM_REQ_CMP}, 37679697Snon {SENSEIO, CAM_AUTOSNS_VALID | CAM_REQ_CMP_ERR}, 37779697Snon {SENSEERR, CAM_AUTOSENSE_FAIL}, 37879697Snon {UACAERR, CAM_SCSI_STATUS_ERROR}, 37979697Snon {BUSYERR | STATERR, CAM_SCSI_STATUS_ERROR}, 38079697Snon {SELTIMEOUTIO, CAM_SEL_TIMEOUT}, 38179697Snon {TIMEOUTIO, CAM_CMD_TIMEOUT}, 38279697Snon {PDMAERR, CAM_DATA_RUN_ERR}, 38379697Snon {PARITYERR, CAM_UNCOR_PARITY}, 38479697Snon {UBFERR, CAM_UNEXP_BUSFREE}, 38579697Snon {ABORTIO, CAM_REQ_ABORTED}, 38679697Snon {-1, CAM_UNREC_HBA_ERROR} 38779697Snon}; 38879697Snon 38979697Snon#define SIM2SLP(sim) ((struct scsi_low_softc *) cam_sim_softc((sim))) 39079697Snon 39179697Snon/* XXX: 39279697Snon * Please check a polling hz, currently we assume scsi_low_poll() is 39379697Snon * called each 1 ms. 39479697Snon */ 39579697Snon#define SCSI_LOW_CAM_POLL_HZ 1000 /* OK ? */ 39679697Snon 39779697Snonstatic void 39879697Snonscsi_low_poll_cam(sim) 39979697Snon struct cam_sim *sim; 40079697Snon{ 40179697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 40279697Snon 403274760Sjhb SCSI_LOW_ASSERT_LOCKED(slp); 40479697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 40579697Snon 406274760Sjhb if (slp->sl_poll_count ++ >= 40779697Snon SCSI_LOW_CAM_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 40879697Snon { 409274760Sjhb slp->sl_poll_count = 0; 41079697Snon scsi_low_timeout_check(slp); 41179697Snon } 41279697Snon} 41379697Snon 41479697Snonvoid 41579697Snonscsi_low_scsi_action_cam(sim, ccb) 41679697Snon struct cam_sim *sim; 41779697Snon union ccb *ccb; 41879697Snon{ 41979697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 42079697Snon struct targ_info *ti; 42179697Snon struct lun_info *li; 42279697Snon struct slccb *cb; 42379697Snon u_int lun, flags, msg, target; 424274760Sjhb int rv; 42579697Snon 426274760Sjhb SCSI_LOW_ASSERT_LOCKED(slp); 42779697Snon target = (u_int) (ccb->ccb_h.target_id); 42879697Snon lun = (u_int) ccb->ccb_h.target_lun; 42979697Snon 43079697Snon#ifdef SCSI_LOW_DEBUG 43179697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_ACTION, target) != 0) 43279697Snon { 433240325Sjhb device_printf(slp->sl_dev, 434240325Sjhb "cam_action: func code 0x%x target: %d, lun: %d\n", 435240325Sjhb ccb->ccb_h.func_code, target, lun); 43679697Snon } 43779697Snon#endif /* SCSI_LOW_DEBUG */ 43879697Snon 43979697Snon switch (ccb->ccb_h.func_code) { 44079697Snon case XPT_SCSI_IO: /* Execute the requested I/O operation */ 44179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 44279697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 44379697Snon { 444240325Sjhb device_printf(slp->sl_dev, "invalid target/lun\n"); 44579697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 44679697Snon xpt_done(ccb); 44779697Snon return; 44879697Snon } 44979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 45079697Snon 45179697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) { 45279697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 45379697Snon xpt_done(ccb); 45479697Snon return; 45579697Snon } 45679697Snon 45779697Snon ti = slp->sl_ti[target]; 45879697Snon cb->osdep = ccb; 45979697Snon cb->bp = NULL; 46079697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 46179697Snon flags = CCB_AUTOSENSE | CCB_SCSIIO; 46279697Snon else 46379697Snon flags = CCB_SCSIIO; 46479697Snon 46579697Snon li = scsi_low_alloc_li(ti, lun, 1); 46679697Snon 46779697Snon if (ti->ti_setup_msg != 0) 46879697Snon { 46979697Snon scsi_low_message_enqueue(slp, ti, li, CCB_AUTOSENSE); 47079697Snon } 47179697Snon 47279697Snon scsi_low_enqueue(slp, ti, li, cb, flags, 0); 47379697Snon 47479697Snon#ifdef SCSI_LOW_DEBUG 47579697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, target) != 0) 47679697Snon { 47779697Snon scsi_low_test_abort(slp, ti, li); 47879697Snon } 47979697Snon#endif /* SCSI_LOW_DEBUG */ 48079697Snon break; 48179697Snon 48279697Snon case XPT_EN_LUN: /* Enable LUN as a target */ 48379697Snon case XPT_TARGET_IO: /* Execute target I/O request */ 48479697Snon case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 48579697Snon case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 48679697Snon /* XXX Implement */ 48779697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 48879697Snon xpt_done(ccb); 48979697Snon break; 49079697Snon 49179697Snon case XPT_ABORT: /* Abort the specified CCB */ 49279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 49379697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 49479697Snon { 495240325Sjhb device_printf(slp->sl_dev, "invalid target/lun\n"); 49679697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 49779697Snon xpt_done(ccb); 49879697Snon return; 49979697Snon } 50079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 50179697Snon 50279697Snon cb = scsi_low_find_ccb(slp, target, lun, ccb->cab.abort_ccb); 50379697Snon rv = scsi_low_abort_ccb(slp, cb); 50479697Snon 50579697Snon if (rv == 0) 50679697Snon ccb->ccb_h.status = CAM_REQ_CMP; 50779697Snon else 50879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 50979697Snon xpt_done(ccb); 51079697Snon break; 51179697Snon 51279697Snon case XPT_SET_TRAN_SETTINGS: { 513163816Smjacob struct ccb_trans_settings_scsi *scsi; 514163816Smjacob struct ccb_trans_settings_spi *spi; 51579697Snon struct ccb_trans_settings *cts; 51679697Snon u_int val; 51779697Snon 51879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 51979697Snon if (target == CAM_TARGET_WILDCARD) 52079697Snon { 521240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 52279697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 52379697Snon xpt_done(ccb); 52479697Snon return; 52579697Snon } 52679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 52779697Snon cts = &ccb->cts; 52879697Snon ti = slp->sl_ti[target]; 52979697Snon if (lun == CAM_LUN_WILDCARD) 53079697Snon lun = 0; 53179697Snon 532163816Smjacob scsi = &cts->proto_specific.scsi; 533163816Smjacob spi = &cts->xport_specific.spi; 534163816Smjacob if ((spi->valid & (CTS_SPI_VALID_BUS_WIDTH | 535163816Smjacob CTS_SPI_VALID_SYNC_RATE | 536163816Smjacob CTS_SPI_VALID_SYNC_OFFSET)) != 0) 537163816Smjacob { 538163816Smjacob if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) { 539163816Smjacob val = spi->bus_width; 540163816Smjacob if (val < ti->ti_width) 541163816Smjacob ti->ti_width = val; 542163816Smjacob } 543163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_RATE) { 544163816Smjacob val = spi->sync_period; 545163816Smjacob if (val == 0 || val > ti->ti_maxsynch.period) 546163816Smjacob ti->ti_maxsynch.period = val; 547163816Smjacob } 548163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) { 549163816Smjacob val = spi->sync_offset; 550163816Smjacob if (val < ti->ti_maxsynch.offset) 551163816Smjacob ti->ti_maxsynch.offset = val; 552163816Smjacob } 553163816Smjacob ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 554163816Smjacob scsi_low_calcf_target(ti); 555163816Smjacob } 556163816Smjacob 557163816Smjacob if ((spi->valid & CTS_SPI_FLAGS_DISC_ENB) != 0 || 558163816Smjacob (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 559163816Smjacob 560163816Smjacob li = scsi_low_alloc_li(ti, lun, 1); 561163816Smjacob if (spi->valid & CTS_SPI_FLAGS_DISC_ENB) { 562163816Smjacob li->li_quirks |= SCSI_LOW_DISK_DISC; 563163816Smjacob } else { 564163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_DISC; 565163816Smjacob } 566163816Smjacob 567163816Smjacob if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) { 568163816Smjacob li->li_quirks |= SCSI_LOW_DISK_QTAG; 569163816Smjacob } else { 570163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_QTAG; 571163816Smjacob } 572163816Smjacob li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 573163816Smjacob scsi_low_calcf_target(ti); 574163816Smjacob scsi_low_calcf_lun(li); 575163816Smjacob if ((slp->sl_show_result & SHOW_CALCF_RES) != 0) 576163816Smjacob scsi_low_calcf_show(li); 577163816Smjacob } 57879697Snon 57979697Snon ccb->ccb_h.status = CAM_REQ_CMP; 58079697Snon xpt_done(ccb); 58179697Snon break; 58279697Snon } 58379697Snon 58479697Snon case XPT_GET_TRAN_SETTINGS: { 58579697Snon struct ccb_trans_settings *cts; 58679697Snon u_int diskflags; 58779697Snon 58879697Snon cts = &ccb->cts; 58979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 59079697Snon if (target == CAM_TARGET_WILDCARD) 59179697Snon { 592240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 59379697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 59479697Snon xpt_done(ccb); 59579697Snon return; 59679697Snon } 59779697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 59879697Snon ti = slp->sl_ti[target]; 59979697Snon if (lun == CAM_LUN_WILDCARD) 60079697Snon lun = 0; 60179697Snon 60279697Snon li = scsi_low_alloc_li(ti, lun, 1); 60379697Snon if (li != NULL && cts->type == CTS_TYPE_CURRENT_SETTINGS) { 60479697Snon struct ccb_trans_settings_scsi *scsi = 60579697Snon &cts->proto_specific.scsi; 60679697Snon struct ccb_trans_settings_spi *spi = 60779697Snon &cts->xport_specific.spi; 60879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 60979697Snon if (li->li_flags_valid != SCSI_LOW_LUN_FLAGS_ALL_VALID) 61079697Snon { 61179697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 612240325Sjhb device_printf(slp->sl_dev, 613240325Sjhb "invalid GET_TRANS_CURRENT_SETTINGS call\n"); 61479697Snon goto settings_out; 61579697Snon } 61679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 61779697Snon cts->protocol = PROTO_SCSI; 61879697Snon cts->protocol_version = SCSI_REV_2; 61979697Snon cts->transport = XPORT_SPI; 62079697Snon cts->transport_version = 2; 62179697Snon 62279697Snon scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 62379697Snon spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 62479697Snon 62579697Snon diskflags = li->li_diskflags & li->li_cfgflags; 62679697Snon if (diskflags & SCSI_LOW_DISK_DISC) 62779697Snon spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 62879697Snon if (diskflags & SCSI_LOW_DISK_QTAG) 62979697Snon scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 63079697Snon 63179697Snon spi->sync_period = ti->ti_maxsynch.period; 63279697Snon spi->valid |= CTS_SPI_VALID_SYNC_RATE; 63379697Snon spi->sync_offset = ti->ti_maxsynch.offset; 63479697Snon spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 63579697Snon 63679697Snon spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 63779697Snon spi->bus_width = ti->ti_width; 63879697Snon 63979697Snon if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 64079697Snon scsi->valid = CTS_SCSI_VALID_TQ; 64179697Snon spi->valid |= CTS_SPI_VALID_DISC; 64279697Snon } else 64379697Snon scsi->valid = 0; 64479697Snon } else 64579697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 64679697Snonsettings_out: 64779697Snon xpt_done(ccb); 64879697Snon break; 64979697Snon } 65079697Snon 65179697Snon case XPT_CALC_GEOMETRY: { /* not yet HN2 */ 652116351Snjl cam_calc_geometry(&ccb->ccg, /*extended*/1); 65379697Snon xpt_done(ccb); 65479697Snon break; 65579697Snon } 65679697Snon 65779697Snon case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 65879697Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL); 65979697Snon ccb->ccb_h.status = CAM_REQ_CMP; 66079697Snon xpt_done(ccb); 66179697Snon break; 66279697Snon 66379697Snon case XPT_TERM_IO: /* Terminate the I/O process */ 66479697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 66579697Snon xpt_done(ccb); 66679697Snon break; 66779697Snon 66879697Snon case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 66979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 67079697Snon if (target == CAM_TARGET_WILDCARD) 67179697Snon { 672240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 67379697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 67479697Snon xpt_done(ccb); 67579697Snon return; 67679697Snon } 67779697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 67879697Snon 67979697Snon msg = SCSI_LOW_MSG_RESET; 68079697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) 68179697Snon { 68279697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 68379697Snon xpt_done(ccb); 68479697Snon return; 68579697Snon } 68679697Snon 68779697Snon ti = slp->sl_ti[target]; 68879697Snon if (lun == CAM_LUN_WILDCARD) 68979697Snon lun = 0; 69079697Snon cb->osdep = ccb; 69179697Snon cb->bp = NULL; 69279697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 69379697Snon flags = CCB_AUTOSENSE | CCB_NORETRY | CCB_URGENT; 69479697Snon else 69579697Snon flags = CCB_NORETRY | CCB_URGENT; 69679697Snon 69779697Snon li = scsi_low_alloc_li(ti, lun, 1); 69879697Snon scsi_low_enqueue(slp, ti, li, cb, flags, msg); 69979697Snon break; 70079697Snon 70179697Snon case XPT_PATH_INQ: { /* Path routing inquiry */ 70279697Snon struct ccb_pathinq *cpi = &ccb->cpi; 70379697Snon 70479697Snon cpi->version_num = scsi_low_version_major; 70579697Snon cpi->hba_inquiry = PI_TAG_ABLE | PI_LINKED_CDB; 70679697Snon ti = slp->sl_ti[slp->sl_hostid]; /* host id */ 70779697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 70879697Snon cpi->hba_inquiry |= PI_WIDE_16; 70979697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 71079697Snon cpi->hba_inquiry |= PI_WIDE_32; 71179697Snon if (ti->ti_maxsynch.offset > 0) 71279697Snon cpi->hba_inquiry |= PI_SDTR_ABLE; 71379697Snon cpi->target_sprt = 0; 71479697Snon cpi->hba_misc = 0; 71579697Snon cpi->hba_eng_cnt = 0; 71679697Snon cpi->max_target = slp->sl_ntargs - 1; 71779697Snon cpi->max_lun = slp->sl_nluns - 1; 71879697Snon cpi->initiator_id = slp->sl_hostid; 71979697Snon cpi->bus_id = cam_sim_bus(sim); 72079697Snon cpi->base_transfer_speed = 3300; 72179697Snon cpi->transport = XPORT_SPI; 72279697Snon cpi->transport_version = 2; 72379697Snon cpi->protocol = PROTO_SCSI; 72479697Snon cpi->protocol_version = SCSI_REV_2; 72579697Snon strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 72679697Snon strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN); 72779697Snon strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 72879697Snon cpi->unit_number = cam_sim_unit(sim); 72979697Snon cpi->ccb_h.status = CAM_REQ_CMP; 73079697Snon xpt_done(ccb); 73179697Snon break; 73279697Snon } 73379697Snon 73479697Snon default: 73579697Snon printf("scsi_low: non support func_code = %d ", 73679697Snon ccb->ccb_h.func_code); 73779697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 73879697Snon xpt_done(ccb); 73979697Snon break; 74079697Snon } 74179697Snon} 74279697Snon 74379697Snonstatic int 74479697Snonscsi_low_attach_cam(slp) 74579697Snon struct scsi_low_softc *slp; 74679697Snon{ 74779697Snon struct cam_devq *devq; 74879697Snon int tagged_openings; 74979697Snon 75079697Snon devq = cam_simq_alloc(SCSI_LOW_NCCB); 75179697Snon if (devq == NULL) 75279697Snon return (ENOMEM); 75379697Snon 75479697Snon /* 75579697Snon * ask the adapter what subunits are present 75679697Snon */ 75779697Snon tagged_openings = min(slp->sl_openings, SCSI_LOW_MAXNEXUS); 758274760Sjhb slp->sl_sim = cam_sim_alloc(scsi_low_scsi_action_cam, 75979697Snon scsi_low_poll_cam, 760240172Sjhb device_get_name(slp->sl_dev), slp, 761274760Sjhb device_get_unit(slp->sl_dev), &slp->sl_lock, 76279697Snon slp->sl_openings, tagged_openings, devq); 76379697Snon 764274760Sjhb if (slp->sl_sim == NULL) { 76579697Snon cam_simq_free(devq); 76679697Snon return ENODEV; 76779697Snon } 76879697Snon 769274760Sjhb SCSI_LOW_LOCK(slp); 770274760Sjhb if (xpt_bus_register(slp->sl_sim, slp->sl_dev, 0) != CAM_SUCCESS) { 771274760Sjhb cam_sim_free(slp->sl_sim, TRUE); 772274760Sjhb SCSI_LOW_UNLOCK(slp); 77379697Snon return ENODEV; 77479697Snon } 77579697Snon 776274760Sjhb if (xpt_create_path(&slp->sl_path, /*periph*/NULL, 777274760Sjhb cam_sim_path(slp->sl_sim), CAM_TARGET_WILDCARD, 77879697Snon CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 779274760Sjhb xpt_bus_deregister(cam_sim_path(slp->sl_sim)); 780274760Sjhb cam_sim_free(slp->sl_sim, /*free_simq*/TRUE); 781274760Sjhb SCSI_LOW_UNLOCK(slp); 78279697Snon return ENODEV; 78379697Snon } 78479697Snon 78579697Snon slp->sl_show_result = SHOW_CALCF_RES; /* OK ? */ 786274760Sjhb SCSI_LOW_UNLOCK(slp); 78779697Snon return 0; 78879697Snon} 78979697Snon 79079697Snonstatic int 791274760Sjhbscsi_low_detach_cam(slp) 79279697Snon struct scsi_low_softc *slp; 79379697Snon{ 79479697Snon 795274760Sjhb xpt_async(AC_LOST_DEVICE, slp->sl_path, NULL); 796274760Sjhb xpt_free_path(slp->sl_path); 797274760Sjhb xpt_bus_deregister(cam_sim_path(slp->sl_sim)); 798274760Sjhb cam_sim_free(slp->sl_sim, /* free_devq */ TRUE); 79979697Snon return 0; 80079697Snon} 80179697Snon 80279697Snonstatic int 80379697Snonscsi_low_ccb_setup_cam(slp, cb) 80479697Snon struct scsi_low_softc *slp; 80579697Snon struct slccb *cb; 80679697Snon{ 80779697Snon union ccb *ccb = (union ccb *) cb->osdep; 80879697Snon 80979697Snon if ((cb->ccb_flags & CCB_SCSIIO) != 0) 81079697Snon { 81179697Snon cb->ccb_scp.scp_cmd = ccb->csio.cdb_io.cdb_bytes; 81279697Snon cb->ccb_scp.scp_cmdlen = (int) ccb->csio.cdb_len; 81379697Snon cb->ccb_scp.scp_data = ccb->csio.data_ptr; 81479697Snon cb->ccb_scp.scp_datalen = (int) ccb->csio.dxfer_len; 81579697Snon if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 81679697Snon cb->ccb_scp.scp_direction = SCSI_LOW_WRITE; 81779697Snon else /* if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) */ 81879697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 81979697Snon cb->ccb_tcmax = ccb->ccb_h.timeout / 1000; 82079697Snon } 82179697Snon else 82279697Snon { 82379697Snon scsi_low_unit_ready_cmd(cb); 82479697Snon } 82579697Snon return SCSI_LOW_START_QTAG; 82679697Snon} 82779697Snon 82879697Snonstatic int 82979697Snonscsi_low_done_cam(slp, cb) 83079697Snon struct scsi_low_softc *slp; 83179697Snon struct slccb *cb; 83279697Snon{ 83379697Snon union ccb *ccb; 83479697Snon 83579697Snon ccb = (union ccb *) cb->osdep; 83679697Snon if (cb->ccb_error == 0) 83779697Snon { 83879697Snon ccb->ccb_h.status = CAM_REQ_CMP; 83979697Snon ccb->csio.resid = 0; 84079697Snon } 84179697Snon else 84279697Snon { 84379697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 84479697Snon cb->ccb_error |= ABORTIO; 84579697Snon 84679697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 84779697Snon (cb->ccb_error & ABORTIO) == 0) 84879697Snon return EJUSTRETURN; 84979697Snon 85079697Snon if ((cb->ccb_error & SENSEIO) != 0) 85179697Snon { 85279697Snon memcpy(&ccb->csio.sense_data, 85379697Snon &cb->ccb_sense, 85479697Snon sizeof(ccb->csio.sense_data)); 85579697Snon } 85679697Snon 85779697Snon ccb->ccb_h.status = scsi_low_translate_error_code(cb, 85879697Snon &scsi_low_error_code_cam[0]); 85979697Snon 86079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 86179697Snon if ((cb->ccb_flags & CCB_SILENT) == 0 && 86279697Snon cb->ccb_scp.scp_cmdlen > 0 && 86379697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 86479697Snon SCSI_LOW_CMD_ABORT_WARNING) != 0) 86579697Snon { 866240325Sjhb device_printf(slp->sl_dev, 867240325Sjhb "WARNING: scsi_low IO abort\n"); 86879697Snon scsi_low_print(slp, NULL); 86979697Snon } 87079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 87179697Snon } 87279697Snon 87379697Snon if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 0) 87479697Snon ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 87579697Snon 87679697Snon if (cb->ccb_scp.scp_status == ST_UNKNOWN) 87779697Snon ccb->csio.scsi_status = 0; /* XXX */ 87879697Snon else 87979697Snon ccb->csio.scsi_status = cb->ccb_scp.scp_status; 88079697Snon 88179697Snon if ((cb->ccb_flags & CCB_NOSDONE) == 0) 88279697Snon xpt_done(ccb); 88379697Snon return 0; 88479697Snon} 88579697Snon 88679697Snon/************************************************************** 88779697Snon * scsi low deactivate and activate 88879697Snon **************************************************************/ 88979697Snonint 89079697Snonscsi_low_is_busy(slp) 89179697Snon struct scsi_low_softc *slp; 89279697Snon{ 89379697Snon 89479697Snon if (slp->sl_nio > 0) 89579697Snon return EBUSY; 89679697Snon return 0; 89779697Snon} 89879697Snon 89979697Snonint 90079697Snonscsi_low_deactivate(slp) 90179697Snon struct scsi_low_softc *slp; 90279697Snon{ 90379697Snon 90479697Snon slp->sl_flags |= HW_INACTIVE; 905274760Sjhb callout_stop(&slp->sl_timeout_timer); 906274760Sjhb callout_stop(&slp->sl_engage_timer); 90779697Snon return 0; 90879697Snon} 90979697Snon 91079697Snonint 91179697Snonscsi_low_activate(slp) 91279697Snon struct scsi_low_softc *slp; 91379697Snon{ 914274760Sjhb int error; 91579697Snon 91679697Snon slp->sl_flags &= ~HW_INACTIVE; 91779697Snon if ((error = scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL)) != 0) 91879697Snon { 91979697Snon slp->sl_flags |= HW_INACTIVE; 92079697Snon return error; 92179697Snon } 92279697Snon 92379697Snon slp->sl_timeout_count = 0; 924274760Sjhb callout_reset(&slp->sl_timeout_timer, hz / SCSI_LOW_TIMEOUT_HZ, 925274760Sjhb scsi_low_timeout, slp); 92679697Snon return 0; 92779697Snon} 92879697Snon 92979697Snon/************************************************************** 93079697Snon * scsi low log 93179697Snon **************************************************************/ 93279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 93392770Salfredstatic void scsi_low_msg_log_init(struct scsi_low_msg_log *); 93492770Salfredstatic void scsi_low_msg_log_write(struct scsi_low_msg_log *, u_int8_t *, int); 93592770Salfredstatic void scsi_low_msg_log_show(struct scsi_low_msg_log *, char *, int); 93679697Snon 93779697Snonstatic void 93879697Snonscsi_low_msg_log_init(slmlp) 93979697Snon struct scsi_low_msg_log *slmlp; 94079697Snon{ 94179697Snon 94279697Snon slmlp->slml_ptr = 0; 94379697Snon} 94479697Snon 94579697Snonstatic void 94679697Snonscsi_low_msg_log_write(slmlp, datap, len) 94779697Snon struct scsi_low_msg_log *slmlp; 94879697Snon u_int8_t *datap; 94979697Snon int len; 95079697Snon{ 95179697Snon int ptr, ind; 95279697Snon 95379697Snon if (slmlp->slml_ptr >= SCSI_LOW_MSG_LOG_DATALEN) 95479697Snon return; 95579697Snon 95679697Snon ptr = slmlp->slml_ptr ++; 95779697Snon for (ind = 0; ind < sizeof(slmlp->slml_msg[0]) && ind < len; ind ++) 95879697Snon slmlp->slml_msg[ptr].msg[ind] = datap[ind]; 95979697Snon for ( ; ind < sizeof(slmlp->slml_msg[0]); ind ++) 96079697Snon slmlp->slml_msg[ptr].msg[ind] = 0; 96179697Snon} 96279697Snon 96379697Snonstatic void 96479697Snonscsi_low_msg_log_show(slmlp, s, len) 96579697Snon struct scsi_low_msg_log *slmlp; 96679697Snon char *s; 96779697Snon int len; 96879697Snon{ 96979697Snon int ptr, ind; 97079697Snon 97179697Snon printf("%s: (%d) ", s, slmlp->slml_ptr); 97279697Snon for (ptr = 0; ptr < slmlp->slml_ptr; ptr ++) 97379697Snon { 97479697Snon for (ind = 0; ind < len && ind < sizeof(slmlp->slml_msg[0]); 97579697Snon ind ++) 97679697Snon { 97779697Snon printf("[%x]", (u_int) slmlp->slml_msg[ptr].msg[ind]); 97879697Snon } 97979697Snon printf(">"); 98079697Snon } 98179697Snon printf("\n"); 98279697Snon} 98379697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 98479697Snon 98579697Snon/************************************************************** 98667468Snon * power control 98767468Snon **************************************************************/ 98867468Snonstatic void 98967468Snonscsi_low_engage(arg) 99067468Snon void *arg; 99167468Snon{ 99267468Snon struct scsi_low_softc *slp = arg; 99367468Snon 994274760Sjhb SCSI_LOW_ASSERT_LOCKED(slp); 99567468Snon switch (slp->sl_rstep) 99667468Snon { 99767468Snon case 0: 99867468Snon slp->sl_rstep ++; 99967468Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 1000274760Sjhb callout_reset(&slp->sl_engage_timer, hz / 1000, 1001274760Sjhb scsi_low_engage, slp); 100267468Snon break; 100367468Snon 100467468Snon case 1: 100567468Snon slp->sl_rstep ++; 100667468Snon slp->sl_flags &= ~HW_RESUME; 100767468Snon scsi_low_start(slp); 100867468Snon break; 100967468Snon 101067468Snon case 2: 101167468Snon break; 101267468Snon } 101367468Snon} 101467468Snon 101567468Snonstatic int 101667468Snonscsi_low_init(slp, flags) 101767468Snon struct scsi_low_softc *slp; 101867468Snon u_int flags; 101967468Snon{ 102079697Snon int rv = 0; 102167468Snon 102279697Snon slp->sl_flags |= HW_INITIALIZING; 102379697Snon 102479697Snon /* clear power control timeout */ 102567468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 102667468Snon { 1027274760Sjhb callout_stop(&slp->sl_engage_timer); 102867468Snon slp->sl_flags &= ~(HW_POWDOWN | HW_RESUME); 102967468Snon slp->sl_active = 1; 103067468Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 103167468Snon } 103267468Snon 103367468Snon /* reset current nexus */ 103467468Snon scsi_low_reset_nexus(slp, flags); 103567468Snon if ((slp->sl_flags & HW_INACTIVE) != 0) 103679697Snon { 103779697Snon rv = EBUSY; 103879697Snon goto out; 103979697Snon } 104067468Snon 104179697Snon if (flags != SCSI_LOW_RESTART_SOFT) 104279697Snon { 104379697Snon rv = ((*slp->sl_funcs->scsi_low_init) (slp, flags)); 104479697Snon } 104567468Snon 104679697Snonout: 104779697Snon slp->sl_flags &= ~HW_INITIALIZING; 104879697Snon return rv; 104967468Snon} 105067468Snon 105167468Snon/************************************************************** 105267468Snon * allocate lun_info 105367468Snon **************************************************************/ 105467468Snonstatic struct lun_info * 105567468Snonscsi_low_alloc_li(ti, lun, alloc) 105667468Snon struct targ_info *ti; 105767468Snon int lun; 105867468Snon int alloc; 105967468Snon{ 106079697Snon struct scsi_low_softc *slp = ti->ti_sc; 106167468Snon struct lun_info *li; 106267468Snon 106367468Snon li = LIST_FIRST(&ti->ti_litab); 106467468Snon if (li != NULL) 106567468Snon { 106667468Snon if (li->li_lun == lun) 106767468Snon return li; 106867468Snon 106967468Snon while ((li = LIST_NEXT(li, lun_chain)) != NULL) 107067468Snon { 107167468Snon if (li->li_lun == lun) 107267468Snon { 107367468Snon LIST_REMOVE(li, lun_chain); 107467468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 107567468Snon return li; 107667468Snon } 107767468Snon } 107867468Snon } 107967468Snon 108067468Snon if (alloc == 0) 108167468Snon return li; 108267468Snon 108379697Snon li = SCSI_LOW_MALLOC(ti->ti_lunsize); 108467468Snon if (li == NULL) 1085106890Simp panic("no lun info mem"); 108667468Snon 1087240172Sjhb bzero(li, ti->ti_lunsize); 108867468Snon li->li_lun = lun; 108967468Snon li->li_ti = ti; 109067468Snon 109179697Snon li->li_cfgflags = SCSI_LOW_SYNC | SCSI_LOW_LINK | SCSI_LOW_DISC | 109279697Snon SCSI_LOW_QTAG; 109379697Snon li->li_quirks = li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 109479697Snon li->li_flags_valid = SCSI_LOW_LUN_FLAGS_USER_VALID; 109579697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 109679697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 109779697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 109879697Snon 109979697Snon li->li_qtagbits = (u_int) -1; 110079697Snon 110179697Snon TAILQ_INIT(&li->li_discq); 110267468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 110367468Snon 110479697Snon /* host specific structure initialization per lun */ 110579697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 110679697Snon (*slp->sl_funcs->scsi_low_lun_init) 110779697Snon (slp, ti, li, SCSI_LOW_INFO_ALLOC); 110879697Snon scsi_low_calcf_lun(li); 110967468Snon return li; 111067468Snon} 111167468Snon 111267468Snon/************************************************************** 111367468Snon * allocate targ_info 111467468Snon **************************************************************/ 111567468Snonstatic struct targ_info * 111679697Snonscsi_low_alloc_ti(slp, targ) 111767468Snon struct scsi_low_softc *slp; 111879697Snon int targ; 111967468Snon{ 112067468Snon struct targ_info *ti; 112167468Snon 112271999Sphk if (TAILQ_FIRST(&slp->sl_titab) == NULL) 112367468Snon TAILQ_INIT(&slp->sl_titab); 112467468Snon 112579697Snon ti = SCSI_LOW_MALLOC(slp->sl_targsize); 112667468Snon if (ti == NULL) 1127240325Sjhb panic("%s short of memory", device_get_nameunit(slp->sl_dev)); 112867468Snon 1129240172Sjhb bzero(ti, slp->sl_targsize); 113067468Snon ti->ti_id = targ; 113167468Snon ti->ti_sc = slp; 113267468Snon 113367468Snon slp->sl_ti[targ] = ti; 113467468Snon TAILQ_INSERT_TAIL(&slp->sl_titab, ti, ti_chain); 113567468Snon LIST_INIT(&ti->ti_litab); 113667468Snon 113779697Snon ti->ti_quirks = ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 113879697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 113979697Snon ti->ti_flags_valid = SCSI_LOW_TARG_FLAGS_USER_VALID; 114079697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 114179697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 114279697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 114373025Snon 114479697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 114579697Snon { 114679697Snon (*slp->sl_funcs->scsi_low_targ_init) 114779697Snon (slp, ti, SCSI_LOW_INFO_ALLOC); 114879697Snon } 114979697Snon scsi_low_calcf_target(ti); 115067468Snon return ti; 115167468Snon} 115267468Snon 115367468Snonstatic void 115467468Snonscsi_low_free_ti(slp) 115567468Snon struct scsi_low_softc *slp; 115667468Snon{ 115767468Snon struct targ_info *ti, *tib; 115867468Snon struct lun_info *li, *nli; 115967468Snon 116071999Sphk for (ti = TAILQ_FIRST(&slp->sl_titab); ti; ti = tib) 116167468Snon { 116267468Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; li = nli) 116367468Snon { 116479697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 116579697Snon { 116679697Snon (*slp->sl_funcs->scsi_low_lun_init) 116779697Snon (slp, ti, li, SCSI_LOW_INFO_DEALLOC); 116879697Snon } 116967468Snon nli = LIST_NEXT(li, lun_chain); 117079697Snon SCSI_LOW_FREE(li); 117167468Snon } 117279697Snon 117379697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 117479697Snon { 117579697Snon (*slp->sl_funcs->scsi_low_targ_init) 117679697Snon (slp, ti, SCSI_LOW_INFO_DEALLOC); 117779697Snon } 117879697Snon tib = TAILQ_NEXT(ti, ti_chain); 117979697Snon SCSI_LOW_FREE(ti); 118067468Snon } 118167468Snon} 118267468Snon 118367468Snon/************************************************************** 118467468Snon * timeout 118567468Snon **************************************************************/ 118667468Snonvoid 118779697Snonscsi_low_bus_idle(slp) 118879697Snon struct scsi_low_softc *slp; 118979697Snon{ 119079697Snon 119179697Snon slp->sl_retry_sel = 0; 119279697Snon if (slp->sl_Tnexus == NULL) 119379697Snon scsi_low_start(slp); 119479697Snon} 119579697Snon 119679697Snonstatic void 119767468Snonscsi_low_timeout(arg) 119867468Snon void *arg; 119967468Snon{ 120067468Snon struct scsi_low_softc *slp = arg; 120179697Snon 1202274760Sjhb SCSI_LOW_ASSERT_LOCKED(slp); 120379697Snon (void) scsi_low_timeout_check(slp); 1204274760Sjhb callout_schedule(&slp->sl_timeout_timer, hz / SCSI_LOW_TIMEOUT_HZ); 120579697Snon} 120679697Snon 120779697Snonstatic int 120879697Snonscsi_low_timeout_check(slp) 120979697Snon struct scsi_low_softc *slp; 121079697Snon{ 121167468Snon struct targ_info *ti; 121279697Snon struct lun_info *li; 121367468Snon struct slccb *cb = NULL; /* XXX */ 121467468Snon 121579697Snon /* selection restart */ 121679697Snon if (slp->sl_retry_sel != 0) 121767468Snon { 121879697Snon slp->sl_retry_sel = 0; 121979697Snon if (slp->sl_Tnexus != NULL) 122079697Snon goto step1; 122167468Snon 122279697Snon cb = TAILQ_FIRST(&slp->sl_start); 122379697Snon if (cb == NULL) 122479697Snon goto step1; 122579697Snon 122679697Snon if (cb->ccb_selrcnt >= SCSI_LOW_MAX_SELECTION_RETRY) 122767468Snon { 122879697Snon cb->ccb_flags |= CCB_NORETRY; 122979697Snon cb->ccb_error |= SELTIMEOUTIO; 123079697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1231240325Sjhb panic("%s: ccb not finished", 1232240325Sjhb device_get_nameunit(slp->sl_dev)); 123367468Snon } 123479697Snon 123579697Snon if (slp->sl_Tnexus == NULL) 123679697Snon scsi_low_start(slp); 123767468Snon } 123879697Snon 123979697Snon /* call hardware timeout */ 124079697Snonstep1: 124179697Snon if (slp->sl_funcs->scsi_low_timeout != NULL) 124267468Snon { 124379697Snon (*slp->sl_funcs->scsi_low_timeout) (slp); 124479697Snon } 124579697Snon 124679697Snon if (slp->sl_timeout_count ++ < 124779697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL * SCSI_LOW_TIMEOUT_HZ) 124879697Snon return 0; 124979697Snon 125079697Snon slp->sl_timeout_count = 0; 125179697Snon if (slp->sl_nio > 0) 125279697Snon { 125379697Snon if ((cb = slp->sl_Qnexus) != NULL) 125467468Snon { 125567468Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 125667468Snon if (cb->ccb_tc < 0) 125767468Snon goto bus_reset; 125867468Snon } 125979697Snon else if (slp->sl_disc == 0) 126067468Snon { 126179697Snon if ((cb = TAILQ_FIRST(&slp->sl_start)) == NULL) 126279697Snon return 0; 126367468Snon 126479697Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 126579697Snon if (cb->ccb_tc < 0) 126679697Snon goto bus_reset; 126779697Snon } 126879697Snon else for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 126979697Snon ti = TAILQ_NEXT(ti, ti_chain)) 127079697Snon { 127179697Snon if (ti->ti_disc == 0) 127279697Snon continue; 127367468Snon 127479697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 127579697Snon li = LIST_NEXT(li, lun_chain)) 127667468Snon { 127779697Snon for (cb = TAILQ_FIRST(&li->li_discq); 127879697Snon cb != NULL; 127979697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 128079697Snon { 128179697Snon cb->ccb_tc -= 128279697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 128379697Snon if (cb->ccb_tc < 0) 128479697Snon goto bus_reset; 128579697Snon } 128667468Snon } 128767468Snon } 128879697Snon 128967468Snon } 129079697Snon else if ((slp->sl_flags & HW_POWERCTRL) != 0) 129179697Snon { 129279697Snon if ((slp->sl_flags & (HW_POWDOWN | HW_RESUME)) != 0) 129379697Snon return 0; 129467468Snon 129579697Snon if (slp->sl_active != 0) 129679697Snon { 129779697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 129879697Snon slp->sl_active = 0; 129979697Snon return 0; 130079697Snon } 130167468Snon 130279697Snon slp->sl_powc --; 130379697Snon if (slp->sl_powc < 0) 130479697Snon { 130579697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 130679697Snon slp->sl_flags |= HW_POWDOWN; 130779697Snon (*slp->sl_funcs->scsi_low_power) 130879697Snon (slp, SCSI_LOW_POWDOWN); 130979697Snon } 131079697Snon } 131179697Snon return 0; 131267468Snon 131367468Snonbus_reset: 131467468Snon cb->ccb_error |= TIMEOUTIO; 1315240325Sjhb device_printf(slp->sl_dev, "slccb (0x%lx) timeout!\n", (u_long) cb); 131667468Snon scsi_low_info(slp, NULL, "scsi bus hangup. try to recover."); 131767468Snon scsi_low_init(slp, SCSI_LOW_RESTART_HARD); 131867468Snon scsi_low_start(slp); 131979697Snon return ERESTART; 132067468Snon} 132167468Snon 132267468Snon 132379697Snonstatic int 132479697Snonscsi_low_abort_ccb(slp, cb) 132579697Snon struct scsi_low_softc *slp; 132679697Snon struct slccb *cb; 132779697Snon{ 132879697Snon struct targ_info *ti; 132979697Snon struct lun_info *li; 133079697Snon u_int msg; 133167468Snon 133279697Snon if (cb == NULL) 133379697Snon return EINVAL; 133479697Snon if ((cb->ccb_omsgoutflag & 133579697Snon (SCSI_LOW_MSG_ABORT | SCSI_LOW_MSG_ABORT_QTAG)) != 0) 133679697Snon return EBUSY; 133767468Snon 133879697Snon ti = cb->ti; 133979697Snon li = cb->li; 134079697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 134179697Snon msg = SCSI_LOW_MSG_ABORT; 134279697Snon else 134379697Snon msg = SCSI_LOW_MSG_ABORT_QTAG; 134467468Snon 134579697Snon cb->ccb_error |= ABORTIO; 134679697Snon cb->ccb_flags |= CCB_NORETRY; 134779697Snon scsi_low_ccb_message_assert(cb, msg); 134867468Snon 134979697Snon if (cb == slp->sl_Qnexus) 135079697Snon { 135179697Snon scsi_low_assert_msg(slp, ti, msg, 1); 135279697Snon } 135379697Snon else if ((cb->ccb_flags & CCB_DISCQ) != 0) 135479697Snon { 135579697Snon if (scsi_low_revoke_ccb(slp, cb, 0) == NULL) 1356240325Sjhb panic("%s: revoked ccb done", 1357240325Sjhb device_get_nameunit(slp->sl_dev)); 135867468Snon 135979697Snon cb->ccb_flags |= CCB_STARTQ; 136079697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 136167468Snon 136279697Snon if (slp->sl_Tnexus == NULL) 136379697Snon scsi_low_start(slp); 136479697Snon } 136579697Snon else 136679697Snon { 136779697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1368240325Sjhb panic("%s: revoked ccb retried", 1369240325Sjhb device_get_nameunit(slp->sl_dev)); 137079697Snon } 137179697Snon return 0; 137267468Snon} 137367468Snon 137479697Snon/************************************************************** 137579697Snon * Generic SCSI INTERFACE 137679697Snon **************************************************************/ 137767468Snonint 137879697Snonscsi_low_attach(slp, openings, ntargs, nluns, targsize, lunsize) 137967468Snon struct scsi_low_softc *slp; 138079697Snon int openings, ntargs, nluns, targsize, lunsize; 138167468Snon{ 138267468Snon struct targ_info *ti; 138367468Snon struct lun_info *li; 1384274760Sjhb int i, nccb, rv; 138567468Snon 138667468Snon if (ntargs > SCSI_LOW_NTARGETS) 138767468Snon { 138867468Snon printf("scsi_low: %d targets are too large\n", ntargs); 138967468Snon printf("change kernel options SCSI_LOW_NTARGETS"); 139079697Snon return EINVAL; 139167468Snon } 139267468Snon 139379697Snon if (openings <= 0) 139479697Snon slp->sl_openings = (SCSI_LOW_NCCB / ntargs); 139579697Snon else 139679697Snon slp->sl_openings = openings; 139779697Snon slp->sl_ntargs = ntargs; 139879697Snon slp->sl_nluns = nluns; 139979697Snon slp->sl_max_retry = SCSI_LOW_MAX_RETRY; 140067468Snon 140179697Snon if (lunsize < sizeof(struct lun_info)) 140279697Snon lunsize = sizeof(struct lun_info); 140379697Snon 140479697Snon if (targsize < sizeof(struct targ_info)) 140579697Snon targsize = sizeof(struct targ_info); 140679697Snon 140779697Snon slp->sl_targsize = targsize; 140867468Snon for (i = 0; i < ntargs; i ++) 140967468Snon { 141079697Snon ti = scsi_low_alloc_ti(slp, i); 141179697Snon ti->ti_lunsize = lunsize; 141267468Snon li = scsi_low_alloc_li(ti, 0, 1); 141367468Snon } 141467468Snon 141567468Snon /* initialize queue */ 141679697Snon nccb = openings * ntargs; 141767468Snon if (nccb >= SCSI_LOW_NCCB || nccb <= 0) 141867468Snon nccb = SCSI_LOW_NCCB; 141967468Snon scsi_low_init_ccbque(nccb); 142067468Snon TAILQ_INIT(&slp->sl_start); 142167468Snon 142279697Snon /* call os depend attach */ 1423274760Sjhb rv = scsi_low_attach_cam(slp); 142479697Snon if (rv != 0) 142579697Snon { 1426240325Sjhb device_printf(slp->sl_dev, 1427240325Sjhb "scsi_low_attach: osdep attach failed\n"); 1428274760Sjhb return (rv); 142979697Snon } 143067468Snon 143179697Snon /* check hardware */ 1432240172Sjhb DELAY(1000); /* wait for 1ms */ 1433274760Sjhb SCSI_LOW_LOCK(slp); 143479697Snon if (scsi_low_init(slp, SCSI_LOW_RESTART_HARD) != 0) 143579697Snon { 1436240325Sjhb device_printf(slp->sl_dev, 1437240325Sjhb "scsi_low_attach: initialization failed\n"); 1438274760Sjhb SCSI_LOW_UNLOCK(slp); 143979697Snon return EINVAL; 144079697Snon } 144167468Snon 144267468Snon /* start watch dog */ 144379697Snon slp->sl_timeout_count = 0; 1444274760Sjhb callout_reset(&slp->sl_timeout_timer, hz / SCSI_LOW_TIMEOUT_HZ, 1445274760Sjhb scsi_low_timeout, slp); 1446274760Sjhb mtx_lock(&sl_tab_lock); 144779697Snon LIST_INSERT_HEAD(&sl_tab, slp, sl_chain); 1448274760Sjhb mtx_unlock(&sl_tab_lock); 144967468Snon 145079697Snon /* fake call */ 145179697Snon scsi_low_abort_ccb(slp, scsi_low_find_ccb(slp, 0, 0, NULL)); 145267468Snon 145379697Snon#ifdef SCSI_LOW_START_UP_CHECK 145479697Snon /* probing devices */ 145579697Snon scsi_low_start_up(slp); 145679697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 1457274760Sjhb SCSI_LOW_UNLOCK(slp); 145867468Snon 145979697Snon return 0; 146067468Snon} 146167468Snon 146267468Snonint 1463274760Sjhbscsi_low_detach(slp) 146467468Snon struct scsi_low_softc *slp; 146567468Snon{ 1466274760Sjhb int rv; 146767468Snon 1468274760Sjhb SCSI_LOW_LOCK(slp); 146979697Snon if (scsi_low_is_busy(slp) != 0) 147079697Snon { 1471274760Sjhb SCSI_LOW_UNLOCK(slp); 147267468Snon return EBUSY; 147379697Snon } 147467468Snon 147579697Snon scsi_low_deactivate(slp); 147667468Snon 1477274760Sjhb rv = scsi_low_detach_cam(slp); 147879697Snon if (rv != 0) 147979697Snon { 1480274760Sjhb SCSI_LOW_UNLOCK(slp); 148179697Snon return EBUSY; 148279697Snon } 148367468Snon 148467468Snon scsi_low_free_ti(slp); 1485274760Sjhb SCSI_LOW_UNLOCK(slp); 1486274760Sjhb callout_drain(&slp->sl_timeout_timer); 1487274760Sjhb callout_drain(&slp->sl_engage_timer); 1488274760Sjhb mtx_lock(&sl_tab_lock); 148979697Snon LIST_REMOVE(slp, sl_chain); 1490274760Sjhb mtx_unlock(&sl_tab_lock); 149167468Snon return 0; 149267468Snon} 149367468Snon 149479697Snon/************************************************************** 149579697Snon * Generic enqueue 149679697Snon **************************************************************/ 149779697Snonstatic int 149879697Snonscsi_low_enqueue(slp, ti, li, cb, flags, msg) 149979697Snon struct scsi_low_softc *slp; 150067468Snon struct targ_info *ti; 150167468Snon struct lun_info *li; 150267468Snon struct slccb *cb; 150379697Snon u_int flags, msg; 150479697Snon{ 150567468Snon 150679697Snon cb->ti = ti; 150779697Snon cb->li = li; 150867468Snon 150979697Snon scsi_low_ccb_message_assert(cb, msg); 151067468Snon 151179697Snon cb->ccb_otag = cb->ccb_tag = SCSI_LOW_UNKTAG; 151279697Snon scsi_low_alloc_qtag(cb); 151367468Snon 151479697Snon cb->ccb_flags = flags | CCB_STARTQ; 151579697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 151679697Snon cb->ccb_error |= PENDINGIO; 151779697Snon 151879697Snon if ((flags & CCB_URGENT) != 0) 151979697Snon { 152079697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 152179697Snon } 152279697Snon else 152379697Snon { 152467468Snon TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain); 152579697Snon } 152667468Snon 152779697Snon slp->sl_nio ++; 152867468Snon 152979697Snon if (slp->sl_Tnexus == NULL) 153079697Snon scsi_low_start(slp); 153179697Snon return 0; 153279697Snon} 153367468Snon 153479697Snonstatic int 153579697Snonscsi_low_message_enqueue(slp, ti, li, flags) 153679697Snon struct scsi_low_softc *slp; 153779697Snon struct targ_info *ti; 153879697Snon struct lun_info *li; 153979697Snon u_int flags; 154079697Snon{ 154179697Snon struct slccb *cb; 154279697Snon u_int tmsgflags; 154367468Snon 154479697Snon tmsgflags = ti->ti_setup_msg; 154579697Snon ti->ti_setup_msg = 0; 154667468Snon 154779697Snon flags |= CCB_NORETRY; 154879697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 154979697Snon return ENOMEM; 155067468Snon 155179697Snon cb->osdep = NULL; 155279697Snon cb->bp = NULL; 155379697Snon scsi_low_enqueue(slp, ti, li, cb, flags, tmsgflags); 155479697Snon return 0; 155579697Snon} 155667468Snon 155779697Snon/************************************************************** 155879697Snon * Generic Start & Done 155979697Snon **************************************************************/ 156079697Snon#define SLSC_MODE_SENSE_SHORT 0x1a 156179697Snonstatic u_int8_t ss_cmd[6] = {START_STOP, 0, 0, 0, SSS_START, 0}; 156279697Snonstatic u_int8_t sms_cmd[6] = {SLSC_MODE_SENSE_SHORT, 0x08, 0x0a, 0, 156379697Snon sizeof(struct scsi_low_mode_sense_data), 0}; 156479697Snonstatic u_int8_t inq_cmd[6] = {INQUIRY, 0, 0, 0, 156579697Snon sizeof(struct scsi_low_inq_data), 0}; 156679697Snonstatic u_int8_t unit_ready_cmd[6]; 156792770Salfredstatic int scsi_low_setup_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 156892770Salfredstatic int scsi_low_sense_abort_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 156992770Salfredstatic int scsi_low_resume(struct scsi_low_softc *); 157079697Snon 157179697Snonstatic void 157279697Snonscsi_low_unit_ready_cmd(cb) 157379697Snon struct slccb *cb; 157479697Snon{ 157579697Snon 157679697Snon cb->ccb_scp.scp_cmd = unit_ready_cmd; 157779697Snon cb->ccb_scp.scp_cmdlen = sizeof(unit_ready_cmd); 157879697Snon cb->ccb_scp.scp_datalen = 0; 157979697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 158079697Snon cb->ccb_tcmax = 15; 158167468Snon} 158279697Snon 158367468Snonstatic int 158479697Snonscsi_low_sense_abort_start(slp, ti, li, cb) 158579697Snon struct scsi_low_softc *slp; 158667468Snon struct targ_info *ti; 158779697Snon struct lun_info *li; 158867468Snon struct slccb *cb; 158979697Snon{ 159067468Snon 159179697Snon cb->ccb_scp.scp_cmdlen = 6; 1592240172Sjhb bzero(cb->ccb_scsi_cmd, cb->ccb_scp.scp_cmdlen); 159379697Snon cb->ccb_scsi_cmd[0] = REQUEST_SENSE; 159479697Snon cb->ccb_scsi_cmd[4] = sizeof(cb->ccb_sense); 159579697Snon cb->ccb_scp.scp_cmd = cb->ccb_scsi_cmd; 159679697Snon cb->ccb_scp.scp_data = (u_int8_t *) &cb->ccb_sense; 159779697Snon cb->ccb_scp.scp_datalen = sizeof(cb->ccb_sense); 159879697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 159979697Snon cb->ccb_tcmax = 15; 160079697Snon scsi_low_ccb_message_clear(cb); 160179697Snon if ((cb->ccb_flags & CCB_CLEARQ) != 0) 160267468Snon { 160379697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 160467468Snon } 160579697Snon else 160679697Snon { 1607240172Sjhb bzero(&cb->ccb_sense, sizeof(cb->ccb_sense)); 160879697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 160979697Snon scsi_low_assert_msg(slp, ti, ti->ti_setup_msg_done, 0); 161079697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 161179697Snon } 161267468Snon 161379697Snon return SCSI_LOW_START_NO_QTAG; 161479697Snon} 161567468Snon 161679697Snonstatic int 161779697Snonscsi_low_setup_start(slp, ti, li, cb) 161879697Snon struct scsi_low_softc *slp; 161979697Snon struct targ_info *ti; 162079697Snon struct lun_info *li; 162179697Snon struct slccb *cb; 162279697Snon{ 162367468Snon 162479697Snon switch(li->li_state) 162579697Snon { 162679697Snon case SCSI_LOW_LUN_SLEEP: 162779697Snon scsi_low_unit_ready_cmd(cb); 162879697Snon break; 162967468Snon 163079697Snon case SCSI_LOW_LUN_START: 163179697Snon cb->ccb_scp.scp_cmd = ss_cmd; 163279697Snon cb->ccb_scp.scp_cmdlen = sizeof(ss_cmd); 163379697Snon cb->ccb_scp.scp_datalen = 0; 163479697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 163579697Snon cb->ccb_tcmax = 30; 163679697Snon break; 163767468Snon 163879697Snon case SCSI_LOW_LUN_INQ: 163979697Snon cb->ccb_scp.scp_cmd = inq_cmd; 164079697Snon cb->ccb_scp.scp_cmdlen = sizeof(inq_cmd); 164179697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_inq; 164279697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_inq); 164379697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 164479697Snon cb->ccb_tcmax = 15; 164579697Snon break; 164667468Snon 164779697Snon case SCSI_LOW_LUN_MODEQ: 164879697Snon cb->ccb_scp.scp_cmd = sms_cmd; 164979697Snon cb->ccb_scp.scp_cmdlen = sizeof(sms_cmd); 165079697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_sms; 165179697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_sms); 165279697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 165379697Snon cb->ccb_tcmax = 15; 165479697Snon return SCSI_LOW_START_QTAG; 165567468Snon 165679697Snon default: 1657240325Sjhb panic("%s: no setup phase", device_get_nameunit(slp->sl_dev)); 165867468Snon } 165967468Snon 166079697Snon return SCSI_LOW_START_NO_QTAG; 166167468Snon} 166267468Snon 166379697Snonstatic int 166479697Snonscsi_low_resume(slp) 166579697Snon struct scsi_low_softc *slp; 166667468Snon{ 166767468Snon 166879697Snon if (slp->sl_flags & HW_RESUME) 166979697Snon return EJUSTRETURN; 167079697Snon slp->sl_flags &= ~HW_POWDOWN; 167179697Snon if (slp->sl_funcs->scsi_low_power != NULL) 167279697Snon { 167379697Snon slp->sl_flags |= HW_RESUME; 167479697Snon slp->sl_rstep = 0; 167579697Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 1676274760Sjhb callout_reset(&slp->sl_engage_timer, hz / 1000, 1677274760Sjhb scsi_low_engage, slp); 167879697Snon return EJUSTRETURN; 167979697Snon } 168079697Snon return 0; 168167468Snon} 168267468Snon 168367468Snonstatic void 168467468Snonscsi_low_start(slp) 168567468Snon struct scsi_low_softc *slp; 168667468Snon{ 168767468Snon struct targ_info *ti; 168867468Snon struct lun_info *li; 168967468Snon struct slccb *cb; 169067468Snon int rv; 169167468Snon 169279697Snon /* check hardware exists or under initializations ? */ 169379697Snon if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0) 169467468Snon return; 169567468Snon 169667468Snon /* check hardware power up ? */ 169767468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 169867468Snon { 169967468Snon slp->sl_active ++; 170067468Snon if (slp->sl_flags & (HW_POWDOWN | HW_RESUME)) 170167468Snon { 170279697Snon if (scsi_low_resume(slp) == EJUSTRETURN) 170367468Snon return; 170467468Snon } 170567468Snon } 170667468Snon 170767468Snon /* setup nexus */ 170867468Snon#ifdef SCSI_LOW_DIAGNOSTIC 170979697Snon if (slp->sl_Tnexus || slp->sl_Lnexus || slp->sl_Qnexus) 171067468Snon { 171167468Snon scsi_low_info(slp, NULL, "NEXUS INCOSISTENT"); 1712240325Sjhb panic("%s: inconsistent", device_get_nameunit(slp->sl_dev)); 171367468Snon } 171467468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 171567468Snon 171679697Snon for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL; 171779697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 171867468Snon { 171967468Snon li = cb->li; 172079697Snon 172179697Snon if (li->li_disc == 0) 172279697Snon { 172367468Snon goto scsi_low_cmd_start; 172479697Snon } 172579697Snon else if (li->li_nqio > 0) 172679697Snon { 172779697Snon if (li->li_nqio < li->li_maxnqio || 172879697Snon (cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 172979697Snon goto scsi_low_cmd_start; 173079697Snon } 173167468Snon } 173267468Snon return; 173367468Snon 173467468Snonscsi_low_cmd_start: 173579697Snon cb->ccb_flags &= ~CCB_STARTQ; 173679697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 173779697Snon ti = cb->ti; 173867468Snon 173967468Snon /* clear all error flag bits (for restart) */ 174067468Snon cb->ccb_error = 0; 174179697Snon cb->ccb_datalen = -1; 174279697Snon cb->ccb_scp.scp_status = ST_UNKNOWN; 174367468Snon 174467468Snon /* setup nexus pointer */ 174579697Snon slp->sl_Qnexus = cb; 174679697Snon slp->sl_Lnexus = li; 174779697Snon slp->sl_Tnexus = ti; 174867468Snon 174967468Snon /* initialize msgsys */ 175067468Snon scsi_low_init_msgsys(slp, ti); 175167468Snon 175279697Snon /* exec cmd */ 175379697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 175467468Snon { 175579697Snon /* CA state or forced abort */ 175679697Snon rv = scsi_low_sense_abort_start(slp, ti, li, cb); 175767468Snon } 175879697Snon else if (li->li_state >= SCSI_LOW_LUN_OK) 175967468Snon { 176079697Snon cb->ccb_flags &= ~CCB_INTERNAL; 1761274760Sjhb rv = scsi_low_ccb_setup_cam(slp, cb); 176279697Snon if (cb->ccb_msgoutflag != 0) 176379697Snon { 176479697Snon scsi_low_ccb_message_exec(slp, cb); 176579697Snon } 176667468Snon } 176779697Snon else 176867468Snon { 176979697Snon cb->ccb_flags |= CCB_INTERNAL; 177079697Snon rv = scsi_low_setup_start(slp, ti, li, cb); 177179697Snon } 177267468Snon 177379697Snon /* allocate qtag */ 177479697Snon#define SCSI_LOW_QTAG_OK (SCSI_LOW_QTAG | SCSI_LOW_DISC) 177567468Snon 177679697Snon if (rv == SCSI_LOW_START_QTAG && 177779697Snon (li->li_flags & SCSI_LOW_QTAG_OK) == SCSI_LOW_QTAG_OK && 177879697Snon li->li_maxnqio > 0) 177979697Snon { 178079697Snon u_int qmsg; 178167468Snon 178279697Snon scsi_low_activate_qtag(cb); 178379697Snon if ((scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 178479697Snon SCSI_LOW_CMD_ORDERED_QTAG) != 0) 178579697Snon qmsg = SCSI_LOW_MSG_ORDERED_QTAG; 178679697Snon else if ((cb->ccb_flags & CCB_URGENT) != 0) 178779697Snon qmsg = SCSI_LOW_MSG_HEAD_QTAG; 178879697Snon else 178979697Snon qmsg = SCSI_LOW_MSG_SIMPLE_QTAG; 179079697Snon scsi_low_assert_msg(slp, ti, qmsg, 0); 179167468Snon } 179267468Snon 179367468Snon /* timeout */ 179467468Snon if (cb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 179567468Snon cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 179667468Snon cb->ccb_tc = cb->ccb_tcmax; 179767468Snon 179867468Snon /* setup saved scsi data pointer */ 179967468Snon cb->ccb_sscp = cb->ccb_scp; 180067468Snon 180167468Snon /* setup current scsi pointer */ 180267468Snon slp->sl_scp = cb->ccb_sscp; 180367468Snon slp->sl_error = cb->ccb_error; 180467468Snon 180579697Snon /* assert always an identify msg */ 180679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); 180779697Snon 180879697Snon /* debug section */ 180979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 181079697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 181179697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 181279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 181379697Snon 181467468Snon /* selection start */ 181579697Snon slp->sl_selid = cb; 181667468Snon rv = ((*slp->sl_funcs->scsi_low_start_bus) (slp, cb)); 181767468Snon if (rv == SCSI_LOW_START_OK) 181867468Snon { 181967468Snon#ifdef SCSI_LOW_STATICS 182067468Snon scsi_low_statics.nexus_win ++; 182167468Snon#endif /* SCSI_LOW_STATICS */ 182267468Snon return; 182367468Snon } 182467468Snon 182579697Snon scsi_low_arbit_fail(slp, cb); 182667468Snon#ifdef SCSI_LOW_STATICS 182767468Snon scsi_low_statics.nexus_fail ++; 182867468Snon#endif /* SCSI_LOW_STATICS */ 182967468Snon} 183067468Snon 183167468Snonvoid 183279697Snonscsi_low_arbit_fail(slp, cb) 183367468Snon struct scsi_low_softc *slp; 183479697Snon struct slccb *cb; 183579697Snon{ 183679697Snon struct targ_info *ti = cb->ti; 183779697Snon 183879697Snon scsi_low_deactivate_qtag(cb); 183979697Snon scsi_low_ccb_message_retry(cb); 184079697Snon cb->ccb_flags |= CCB_STARTQ; 184179697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 184279697Snon 184379697Snon scsi_low_bus_release(slp, ti); 184479697Snon 184579697Snon cb->ccb_selrcnt ++; 184679697Snon if (slp->sl_disc == 0) 184779697Snon { 184879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 1849240325Sjhb device_printf(slp->sl_dev, "try selection again\n"); 185079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 185179697Snon slp->sl_retry_sel = 1; 185279697Snon } 185379697Snon} 185479697Snon 185579697Snonstatic void 185679697Snonscsi_low_bus_release(slp, ti) 185779697Snon struct scsi_low_softc *slp; 185867468Snon struct targ_info *ti; 185967468Snon{ 186067468Snon 186179697Snon if (ti->ti_disc > 0) 186279697Snon { 186379697Snon SCSI_LOW_SETUP_PHASE(ti, PH_DISC); 186479697Snon } 186579697Snon else 186679697Snon { 186779697Snon SCSI_LOW_SETUP_PHASE(ti, PH_NULL); 186879697Snon } 186979697Snon 187067468Snon /* clear all nexus pointer */ 187179697Snon slp->sl_Qnexus = NULL; 187279697Snon slp->sl_Lnexus = NULL; 187379697Snon slp->sl_Tnexus = NULL; 187467468Snon 187567468Snon /* clear selection assert */ 187667468Snon slp->sl_selid = NULL; 187767468Snon 187867468Snon /* clear nexus data */ 187967468Snon slp->sl_scp.scp_direction = SCSI_LOW_RWUNK; 188079697Snon 188179697Snon /* clear phase change counter */ 188279697Snon slp->sl_ph_count = 0; 188367468Snon} 188467468Snon 188567468Snonstatic int 188679697Snonscsi_low_setup_done(slp, cb) 188767468Snon struct scsi_low_softc *slp; 188867468Snon struct slccb *cb; 188967468Snon{ 189067468Snon struct targ_info *ti; 189167468Snon struct lun_info *li; 189267468Snon 189367468Snon ti = cb->ti; 189467468Snon li = cb->li; 189579697Snon 189679697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 189767468Snon { 189879697Snon cb->ccb_error |= ABORTIO; 189979697Snon return SCSI_LOW_DONE_COMPLETE; 190079697Snon } 190179697Snon 190279697Snon /* XXX: special huck for selection timeout */ 190379697Snon if (li->li_state == SCSI_LOW_LUN_SLEEP && 190479697Snon (cb->ccb_error & SELTIMEOUTIO) != 0) 190579697Snon { 190679697Snon cb->ccb_error |= ABORTIO; 190779697Snon return SCSI_LOW_DONE_COMPLETE; 190879697Snon } 190979697Snon 191079697Snon switch(li->li_state) 191179697Snon { 191279697Snon case SCSI_LOW_LUN_INQ: 191379697Snon if (cb->ccb_error != 0) 191467468Snon { 191579697Snon li->li_diskflags &= 191679697Snon ~(SCSI_LOW_DISK_LINK | SCSI_LOW_DISK_QTAG); 191779697Snon if (li->li_lun > 0) 191879697Snon goto resume; 191979697Snon ti->ti_diskflags &= 192079697Snon ~(SCSI_LOW_DISK_SYNC | SCSI_LOW_DISK_WIDE); 192167468Snon } 192279697Snon else if ((li->li_inq.sd_version & 7) >= 2 || 192379697Snon (li->li_inq.sd_len >= 4)) 192467468Snon { 192579697Snon if ((li->li_inq.sd_support & 0x2) == 0) 192679697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 192779697Snon if ((li->li_inq.sd_support & 0x8) == 0) 192879697Snon li->li_diskflags &= ~SCSI_LOW_DISK_LINK; 192979697Snon if (li->li_lun > 0) 193079697Snon goto resume; 193179697Snon if ((li->li_inq.sd_support & 0x10) == 0) 193279697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_SYNC; 193379697Snon if ((li->li_inq.sd_support & 0x20) == 0) 193479697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_16; 193579697Snon if ((li->li_inq.sd_support & 0x40) == 0) 193679697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_32; 193779697Snon } 193879697Snon else 193979697Snon { 194079697Snon li->li_diskflags &= 194179697Snon ~(SCSI_LOW_DISK_QTAG | SCSI_LOW_DISK_LINK); 194279697Snon if (li->li_lun > 0) 194379697Snon goto resume; 194479697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE; 194579697Snon } 194679697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_DISK_VALID; 194779697Snonresume: 194879697Snon scsi_low_calcf_target(ti); 194979697Snon scsi_low_calcf_lun(li); 195079697Snon break; 195179697Snon 195279697Snon case SCSI_LOW_LUN_MODEQ: 195379697Snon if (cb->ccb_error != 0) 195479697Snon { 195579697Snon if (cb->ccb_error & SENSEIO) 195667468Snon { 195779697Snon#ifdef SCSI_LOW_DEBUG 195879697Snon if (scsi_low_debug & SCSI_LOW_DEBUG_SENSE) 195979697Snon { 1960225950Sken int error_code, sense_key, asc, ascq; 1961225950Sken 1962225950Sken scsi_extract_sense(&cb->ccb_sense, 1963225950Sken &error_code, 1964225950Sken &sense_key, 1965225950Sken &asc, 1966225950Sken &ascq); 1967225950Sken printf("SENSE: [%x][%x][%x][%x]\n", 1968225950Sken error_code, sense_key, asc, 1969225950Sken ascq); 197079697Snon } 197179697Snon#endif /* SCSI_LOW_DEBUG */ 197267468Snon } 197379697Snon else 197479697Snon { 197579697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 197679697Snon } 197779697Snon } 197879697Snon else if ((li->li_sms.sms_cmp.cmp_page & 0x3f) == 0x0a) 197979697Snon { 198079697Snon if (li->li_sms.sms_cmp.cmp_qc & 0x02) 198179697Snon li->li_qflags |= SCSI_LOW_QFLAG_CA_QCLEAR; 198279697Snon else 198379697Snon li->li_qflags &= ~SCSI_LOW_QFLAG_CA_QCLEAR; 198479697Snon if ((li->li_sms.sms_cmp.cmp_qc & 0x01) != 0) 198579697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 198679697Snon } 198779697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_DISK_VALID; 198879697Snon scsi_low_calcf_lun(li); 198979697Snon break; 199067468Snon 199179697Snon default: 199279697Snon break; 199379697Snon } 199479697Snon 199579697Snon li->li_state ++; 199679697Snon if (li->li_state == SCSI_LOW_LUN_OK) 199779697Snon { 199879697Snon scsi_low_calcf_target(ti); 199979697Snon scsi_low_calcf_lun(li); 200079697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID && 200179697Snon (slp->sl_show_result & SHOW_CALCF_RES) != 0) 200279697Snon { 200379697Snon scsi_low_calcf_show(li); 200479697Snon } 200579697Snon } 200679697Snon 200779697Snon cb->ccb_rcnt --; 200879697Snon return SCSI_LOW_DONE_RETRY; 200979697Snon} 201079697Snon 201179697Snonstatic int 201279697Snonscsi_low_done(slp, cb) 201379697Snon struct scsi_low_softc *slp; 201479697Snon struct slccb *cb; 201579697Snon{ 201679697Snon int rv; 201779697Snon 201879697Snon if (cb->ccb_error == 0) 201979697Snon { 202079697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 202179697Snon { 202279697Snon#ifdef SCSI_LOW_QCLEAR_AFTER_CA 202379697Snon /* XXX: 202479697Snon * SCSI-2 draft suggests 202579697Snon * page 0x0a QErr bit determins if 202679697Snon * the target aborts or continues 202779697Snon * the queueing io's after CA state resolved. 202879697Snon * However many targets seem not to support 202979697Snon * the page 0x0a. Thus we should manually clear the 203079697Snon * queuing io's after CA state. 203179697Snon */ 203279697Snon if ((cb->ccb_flags & CCB_CLEARQ) == 0) 203367468Snon { 203479697Snon cb->ccb_rcnt --; 203579697Snon cb->ccb_flags |= CCB_CLEARQ; 203679697Snon goto retry; 203779697Snon } 203879697Snon#endif /* SCSI_LOW_QCLEAR_AFTER_CA */ 203979697Snon 204079697Snon if ((cb->ccb_flags & CCB_SENSE) != 0) 204179697Snon cb->ccb_error |= (SENSEIO | ABORTIO); 204279697Snon cb->ccb_flags &= ~(CCB_SENSE | CCB_CLEARQ); 204379697Snon } 204479697Snon else switch (cb->ccb_sscp.scp_status) 204579697Snon { 204679697Snon case ST_GOOD: 204779697Snon case ST_MET: 204879697Snon case ST_INTERGOOD: 204979697Snon case ST_INTERMET: 205079697Snon if (cb->ccb_datalen == 0 || 205179697Snon cb->ccb_scp.scp_datalen == 0) 205267468Snon break; 205367468Snon 205479697Snon if (cb->ccb_scp.scp_cmdlen > 0 && 205579697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 205679697Snon SCSI_LOW_CMD_RESIDUAL_CHK) == 0) 205779697Snon break; 205879697Snon 205967468Snon cb->ccb_error |= PDMAERR; 206067468Snon break; 206167468Snon 206279697Snon case ST_BUSY: 206379697Snon case ST_QUEFULL: 206479697Snon cb->ccb_error |= (BUSYERR | STATERR); 206579697Snon break; 206679697Snon 206779697Snon case ST_CONFLICT: 206879697Snon cb->ccb_error |= (STATERR | ABORTIO); 206979697Snon break; 207079697Snon 207167468Snon case ST_CHKCOND: 207279697Snon case ST_CMDTERM: 207379697Snon if (cb->ccb_flags & (CCB_AUTOSENSE | CCB_INTERNAL)) 207479697Snon { 207579697Snon cb->ccb_rcnt --; 207673025Snon cb->ccb_flags |= CCB_SENSE; 207773025Snon goto retry; 207873025Snon } 207979697Snon cb->ccb_error |= (UACAERR | STATERR | ABORTIO); 208073025Snon break; 208167468Snon 208279697Snon case ST_UNKNOWN: 208367468Snon default: 208467468Snon cb->ccb_error |= FATALIO; 208567468Snon break; 208667468Snon } 208767468Snon } 208867468Snon else 208967468Snon { 209079697Snon if (cb->ccb_flags & CCB_SENSE) 209167468Snon { 209279697Snon cb->ccb_error |= (SENSEERR | ABORTIO); 209367468Snon } 209479697Snon cb->ccb_flags &= ~(CCB_CLEARQ | CCB_SENSE); 209579697Snon } 209667468Snon 209779697Snon /* internal ccb */ 209879697Snon if ((cb->ccb_flags & CCB_INTERNAL) != 0) 209979697Snon { 210079697Snon if (scsi_low_setup_done(slp, cb) == SCSI_LOW_DONE_RETRY) 210179697Snon goto retry; 210267468Snon } 210367468Snon 210479697Snon /* check a ccb msgout flag */ 210579697Snon if (cb->ccb_omsgoutflag != 0) 210667468Snon { 210779697Snon#define SCSI_LOW_MSG_ABORT_OK (SCSI_LOW_MSG_ABORT | \ 210879697Snon SCSI_LOW_MSG_ABORT_QTAG | \ 210979697Snon SCSI_LOW_MSG_CLEAR_QTAG | \ 211079697Snon SCSI_LOW_MSG_TERMIO) 211179697Snon 211279697Snon if ((cb->ccb_omsgoutflag & SCSI_LOW_MSG_ABORT_OK) != 0) 211367468Snon { 211479697Snon cb->ccb_error |= ABORTIO; 211567468Snon } 211667468Snon } 211767468Snon 211879697Snon /* call OS depend done */ 211979697Snon if (cb->osdep != NULL) 212067468Snon { 2121274760Sjhb rv = scsi_low_done_cam(slp, cb); 212279697Snon if (rv == EJUSTRETURN) 212379697Snon goto retry; 212467468Snon } 212579697Snon else if (cb->ccb_error != 0) 212667468Snon { 212779697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 212879697Snon cb->ccb_error |= ABORTIO; 212979697Snon 213079697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 213179697Snon (cb->ccb_error & ABORTIO) == 0) 213267468Snon goto retry; 213367468Snon } 213479697Snon 213579697Snon /* free our target */ 213679697Snon#ifdef SCSI_LOW_DEBUG 213779697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 213867468Snon { 213979697Snon printf(">> SCSI_LOW_DONE_COMPLETE ===============\n"); 214079697Snon scsi_low_print(slp, NULL); 214167468Snon } 214279697Snon#endif /* SCSI_LOW_DEBUG */ 214367468Snon 214479697Snon scsi_low_deactivate_qtag(cb); 214579697Snon scsi_low_dealloc_qtag(cb); 214667468Snon scsi_low_free_ccb(cb); 214779697Snon slp->sl_nio --; 214867468Snon return SCSI_LOW_DONE_COMPLETE; 214967468Snon 215067468Snonretry: 215179697Snon#ifdef SCSI_LOW_DEBUG 215279697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 215367468Snon { 215479697Snon printf("** SCSI_LOW_DONE_RETRY ===============\n"); 215579697Snon scsi_low_print(slp, NULL); 215667468Snon } 215779697Snon#endif /* SCSI_LOW_DEBUG */ 215879697Snon 215979697Snon cb->ccb_rcnt ++; 216079697Snon scsi_low_deactivate_qtag(cb); 216179697Snon scsi_low_ccb_message_retry(cb); 216267468Snon return SCSI_LOW_DONE_RETRY; 216367468Snon} 216467468Snon 216567468Snon/************************************************************** 216667468Snon * Reset 216767468Snon **************************************************************/ 216867468Snonstatic void 216979697Snonscsi_low_reset_nexus_target(slp, ti, fdone) 217079697Snon struct scsi_low_softc *slp; 217179697Snon struct targ_info *ti; 217279697Snon int fdone; 217367468Snon{ 217479697Snon struct lun_info *li; 217567468Snon 217679697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 217779697Snon li = LIST_NEXT(li, lun_chain)) 217879697Snon { 217979697Snon scsi_low_reset_nexus_lun(slp, li, fdone); 218079697Snon li->li_state = SCSI_LOW_LUN_SLEEP; 218179697Snon li->li_maxnqio = 0; 218279697Snon } 218379697Snon 218479697Snon ti->ti_disc = 0; 218579697Snon ti->ti_setup_msg = 0; 218679697Snon ti->ti_setup_msg_done = 0; 218779697Snon 218879697Snon ti->ti_osynch.offset = ti->ti_osynch.period = 0; 218979697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 219079697Snon 219179697Snon ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 219279697Snon ti->ti_flags_valid &= ~SCSI_LOW_TARG_FLAGS_DISK_VALID; 219379697Snon 219479697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 219579697Snon { 219679697Snon ((*slp->sl_funcs->scsi_low_targ_init) 219779697Snon (slp, ti, SCSI_LOW_INFO_REVOKE)); 219879697Snon } 219979697Snon scsi_low_calcf_target(ti); 220079697Snon 220179697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 220279697Snon li = LIST_NEXT(li, lun_chain)) 220379697Snon { 220479697Snon li->li_flags = 0; 220579697Snon 220679697Snon li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 220779697Snon li->li_flags_valid &= ~SCSI_LOW_LUN_FLAGS_DISK_VALID; 220879697Snon 220979697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 221079697Snon { 221179697Snon ((*slp->sl_funcs->scsi_low_lun_init) 221279697Snon (slp, ti, li, SCSI_LOW_INFO_REVOKE)); 221379697Snon } 221479697Snon scsi_low_calcf_lun(li); 221579697Snon } 221667468Snon} 221767468Snon 221867468Snonstatic void 221967468Snonscsi_low_reset_nexus(slp, fdone) 222067468Snon struct scsi_low_softc *slp; 222167468Snon int fdone; 222267468Snon{ 222367468Snon struct targ_info *ti; 222479697Snon struct slccb *cb, *topcb; 222567468Snon 222679697Snon if ((cb = slp->sl_Qnexus) != NULL) 222767468Snon { 222879697Snon topcb = scsi_low_revoke_ccb(slp, cb, fdone); 222967468Snon } 223079697Snon else 223179697Snon { 223279697Snon topcb = NULL; 223379697Snon } 223467468Snon 223579697Snon for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 223679697Snon ti = TAILQ_NEXT(ti, ti_chain)) 223767468Snon { 223879697Snon scsi_low_reset_nexus_target(slp, ti, fdone); 223979697Snon scsi_low_bus_release(slp, ti); 224067468Snon scsi_low_init_msgsys(slp, ti); 224167468Snon } 224267468Snon 224379697Snon if (topcb != NULL) 224479697Snon { 224579697Snon topcb->ccb_flags |= CCB_STARTQ; 224679697Snon TAILQ_INSERT_HEAD(&slp->sl_start, topcb, ccb_chain); 224779697Snon } 224879697Snon 224979697Snon slp->sl_disc = 0; 225079697Snon slp->sl_retry_sel = 0; 225167468Snon slp->sl_flags &= ~HW_PDMASTART; 225267468Snon} 225367468Snon 225467468Snon/* misc */ 225567468Snonstatic int tw_pos; 225667468Snonstatic char tw_chars[] = "|/-\\"; 225779697Snon#define TWIDDLEWAIT 10000 225867468Snon 225967468Snonstatic void 226067468Snonscsi_low_twiddle_wait(void) 226167468Snon{ 226267468Snon 226367468Snon cnputc('\b'); 226467468Snon cnputc(tw_chars[tw_pos++]); 226567468Snon tw_pos %= (sizeof(tw_chars) - 1); 2266240172Sjhb DELAY(TWIDDLEWAIT); 226767468Snon} 226867468Snon 226967468Snonvoid 227067468Snonscsi_low_bus_reset(slp) 227167468Snon struct scsi_low_softc *slp; 227267468Snon{ 227367468Snon int i; 227467468Snon 227567468Snon (*slp->sl_funcs->scsi_low_bus_reset) (slp); 227667468Snon 2277240325Sjhb device_printf(slp->sl_dev, "try to reset scsi bus "); 227867468Snon for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++) 227967468Snon scsi_low_twiddle_wait(); 228067468Snon cnputc('\b'); 228167468Snon printf("\n"); 228267468Snon} 228367468Snon 228467468Snonint 228567468Snonscsi_low_restart(slp, flags, s) 228667468Snon struct scsi_low_softc *slp; 228767468Snon int flags; 228867468Snon u_char *s; 228967468Snon{ 229067468Snon int error; 229167468Snon 229267468Snon if (s != NULL) 2293240325Sjhb device_printf(slp->sl_dev, "scsi bus restart. reason: %s\n", s); 229467468Snon 229567468Snon if ((error = scsi_low_init(slp, flags)) != 0) 229667468Snon return error; 229767468Snon 229867468Snon scsi_low_start(slp); 229967468Snon return 0; 230067468Snon} 230167468Snon 230267468Snon/************************************************************** 230367468Snon * disconnect and reselect 230467468Snon **************************************************************/ 230567468Snon#define MSGCMD_LUN(msg) (msg & 0x07) 230667468Snon 230767468Snonstatic struct slccb * 230867468Snonscsi_low_establish_ccb(ti, li, tag) 230967468Snon struct targ_info *ti; 231067468Snon struct lun_info *li; 231167468Snon scsi_low_tag_t tag; 231267468Snon{ 231367468Snon struct scsi_low_softc *slp = ti->ti_sc; 231467468Snon struct slccb *cb; 231567468Snon 231679697Snon if (li == NULL) 231779697Snon return NULL; 231879697Snon 231979697Snon cb = TAILQ_FIRST(&li->li_discq); 232071999Sphk for ( ; cb != NULL; cb = TAILQ_NEXT(cb, ccb_chain)) 232179697Snon if (cb->ccb_tag == tag) 232267468Snon goto found; 232367468Snon return cb; 232467468Snon 232567468Snon /* 232667468Snon * establish our ccb nexus 232767468Snon */ 232867468Snonfound: 232979697Snon#ifdef SCSI_LOW_DEBUG 233079697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 233179697Snon { 2332240325Sjhb device_printf(slp->sl_dev, "nexus(0x%lx) abort check start\n", 2333240325Sjhb (u_long) cb); 233479697Snon cb->ccb_flags |= (CCB_NORETRY | CCB_SILENT); 233579697Snon scsi_low_revoke_ccb(slp, cb, 1); 233679697Snon return NULL; 233779697Snon } 233867468Snon 233979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id) != 0) 234079697Snon { 234179697Snon if (cb->ccb_omsgoutflag == 0) 234279697Snon scsi_low_ccb_message_assert(cb, SCSI_LOW_MSG_NOOP); 234379697Snon } 234479697Snon#endif /* SCSI_LOW_DEBUG */ 234579697Snon 234679697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 234779697Snon cb->ccb_flags &= ~CCB_DISCQ; 234879697Snon slp->sl_Qnexus = cb; 234979697Snon 235067468Snon slp->sl_scp = cb->ccb_sscp; 235167468Snon slp->sl_error |= cb->ccb_error; 235267468Snon 235367468Snon slp->sl_disc --; 235479697Snon ti->ti_disc --; 235567468Snon li->li_disc --; 235667468Snon 235767468Snon /* inform "ccb nexus established" to the host driver */ 235879697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 235979697Snon 236079697Snon /* check msg */ 236179697Snon if (cb->ccb_msgoutflag != 0) 236279697Snon { 236379697Snon scsi_low_ccb_message_exec(slp, cb); 236479697Snon } 236579697Snon 236667468Snon return cb; 236767468Snon} 236867468Snon 236967468Snonstruct targ_info * 237067468Snonscsi_low_reselected(slp, targ) 237167468Snon struct scsi_low_softc *slp; 237267468Snon u_int targ; 237367468Snon{ 237467468Snon struct targ_info *ti; 237579697Snon struct slccb *cb; 237667468Snon u_char *s; 237767468Snon 237867468Snon /* 237967468Snon * Check select vs reselected collision. 238067468Snon */ 238167468Snon 238279697Snon if ((cb = slp->sl_selid) != NULL) 238367468Snon { 238479697Snon scsi_low_arbit_fail(slp, cb); 238567468Snon#ifdef SCSI_LOW_STATICS 238667468Snon scsi_low_statics.nexus_conflict ++; 238767468Snon#endif /* SCSI_LOW_STATICS */ 238867468Snon } 238979697Snon 239079697Snon /* 239179697Snon * Check if no current active nexus. 239279697Snon */ 239379697Snon if (slp->sl_Tnexus != NULL) 239467468Snon { 239567468Snon s = "host busy"; 239667468Snon goto world_restart; 239767468Snon } 239867468Snon 239967468Snon /* 240067468Snon * Check a valid target id asserted ? 240167468Snon */ 240267468Snon if (targ >= slp->sl_ntargs || targ == slp->sl_hostid) 240367468Snon { 240467468Snon s = "scsi id illegal"; 240567468Snon goto world_restart; 240667468Snon } 240767468Snon 240867468Snon /* 240967468Snon * Check the target scsi status. 241067468Snon */ 241167468Snon ti = slp->sl_ti[targ]; 241279697Snon if (ti->ti_phase != PH_DISC && ti->ti_phase != PH_NULL) 241367468Snon { 241467468Snon s = "phase mismatch"; 241567468Snon goto world_restart; 241667468Snon } 241767468Snon 241867468Snon /* 241979697Snon * Setup init msgsys 242067468Snon */ 242167468Snon slp->sl_error = 0; 242267468Snon scsi_low_init_msgsys(slp, ti); 242367468Snon 242467468Snon /* 242567468Snon * Establish our target nexus 242667468Snon */ 242767468Snon SCSI_LOW_SETUP_PHASE(ti, PH_RESEL); 242879697Snon slp->sl_Tnexus = ti; 242967468Snon#ifdef SCSI_LOW_STATICS 243067468Snon scsi_low_statics.nexus_reselected ++; 243167468Snon#endif /* SCSI_LOW_STATICS */ 243267468Snon return ti; 243367468Snon 243467468Snonworld_restart: 2435240325Sjhb device_printf(slp->sl_dev, "reselect(%x:unknown) %s\n", targ, s); 243667468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, 243767468Snon "reselect: scsi world confused"); 243867468Snon return NULL; 243967468Snon} 244067468Snon 244167468Snon/************************************************************** 244267468Snon * cmd out pointer setup 244367468Snon **************************************************************/ 244467468Snonint 244567468Snonscsi_low_cmd(slp, ti) 244667468Snon struct scsi_low_softc *slp; 244767468Snon struct targ_info *ti; 244867468Snon{ 244979697Snon struct slccb *cb = slp->sl_Qnexus; 245067468Snon 245179697Snon slp->sl_ph_count ++; 245267468Snon if (cb == NULL) 245367468Snon { 245467468Snon /* 245579697Snon * no ccb, abort! 245667468Snon */ 245767468Snon slp->sl_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd; 245867468Snon slp->sl_scp.scp_cmdlen = sizeof(unit_ready_cmd); 245967468Snon slp->sl_scp.scp_datalen = 0; 246067468Snon slp->sl_scp.scp_direction = SCSI_LOW_READ; 246179697Snon slp->sl_error |= FATALIO; 246279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 246379697Snon SCSI_LOW_INFO(slp, ti, "CMDOUT: ccb nexus not found"); 246479697Snon return EINVAL; 246567468Snon } 246679697Snon else 246767468Snon { 246879697Snon#ifdef SCSI_LOW_DEBUG 246979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_CMDLNK_CHECK, ti->ti_id)) 247079697Snon { 247179697Snon scsi_low_test_cmdlnk(slp, cb); 247279697Snon } 247379697Snon#endif /* SCSI_LOW_DEBUG */ 247467468Snon } 247567468Snon return 0; 247667468Snon} 247767468Snon 247867468Snon/************************************************************** 247967468Snon * data out pointer setup 248067468Snon **************************************************************/ 248167468Snonint 248267468Snonscsi_low_data(slp, ti, bp, direction) 248367468Snon struct scsi_low_softc *slp; 248467468Snon struct targ_info *ti; 248567468Snon struct buf **bp; 248667468Snon int direction; 248767468Snon{ 248879697Snon struct slccb *cb = slp->sl_Qnexus; 248967468Snon 249079697Snon if (cb != NULL && direction == cb->ccb_sscp.scp_direction) 249167468Snon { 249279697Snon *bp = cb->bp; 249379697Snon return 0; 249467468Snon } 249567468Snon 249679697Snon slp->sl_error |= (FATALIO | PDMAERR); 249779697Snon slp->sl_scp.scp_datalen = 0; 249879697Snon slp->sl_scp.scp_direction = direction; 249979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 250079697Snon if (ti->ti_ophase != ti->ti_phase) 250167468Snon { 250279697Snon char *s; 250379697Snon 250479697Snon if (cb == NULL) 250579697Snon s = "DATA PHASE: ccb nexus not found"; 250679697Snon else 250779697Snon s = "DATA PHASE: xfer direction mismatch"; 250879697Snon SCSI_LOW_INFO(slp, ti, s); 250967468Snon } 251067468Snon 251179697Snon *bp = NULL; 251279697Snon return EINVAL; 251367468Snon} 251467468Snon 251567468Snon/************************************************************** 251667468Snon * MSG_SYS 251767468Snon **************************************************************/ 251867468Snon#define MSGINPTR_CLR(ti) {(ti)->ti_msginptr = 0; (ti)->ti_msginlen = 0;} 251967468Snon#define MSGIN_PERIOD(ti) ((ti)->ti_msgin[3]) 252067468Snon#define MSGIN_OFFSET(ti) ((ti)->ti_msgin[4]) 252179697Snon#define MSGIN_WIDTHP(ti) ((ti)->ti_msgin[3]) 252267468Snon#define MSGIN_DATA_LAST 0x30 252367468Snon 252492770Salfredstatic int scsi_low_errfunc_synch(struct scsi_low_softc *, u_int); 252592770Salfredstatic int scsi_low_errfunc_wide(struct scsi_low_softc *, u_int); 252692770Salfredstatic int scsi_low_errfunc_identify(struct scsi_low_softc *, u_int); 252792770Salfredstatic int scsi_low_errfunc_qtag(struct scsi_low_softc *, u_int); 252867468Snon 252992770Salfredstatic int scsi_low_msgfunc_synch(struct scsi_low_softc *); 253092770Salfredstatic int scsi_low_msgfunc_wide(struct scsi_low_softc *); 253192770Salfredstatic int scsi_low_msgfunc_identify(struct scsi_low_softc *); 253292770Salfredstatic int scsi_low_msgfunc_abort(struct scsi_low_softc *); 253392770Salfredstatic int scsi_low_msgfunc_qabort(struct scsi_low_softc *); 253492770Salfredstatic int scsi_low_msgfunc_qtag(struct scsi_low_softc *); 253592770Salfredstatic int scsi_low_msgfunc_reset(struct scsi_low_softc *); 253667468Snon 253767468Snonstruct scsi_low_msgout_data { 253867468Snon u_int md_flags; 253967468Snon u_int8_t md_msg; 254092770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 254192770Salfred int (*md_errfunc)(struct scsi_low_softc *, u_int); 254279697Snon#define MSG_RELEASE_ATN 0x0001 254379697Snon u_int md_condition; 254467468Snon}; 254567468Snon 254667468Snonstruct scsi_low_msgout_data scsi_low_msgout_data[] = { 254779697Snon/* 0 */ {SCSI_LOW_MSG_RESET, MSG_RESET, scsi_low_msgfunc_reset, NULL, MSG_RELEASE_ATN}, 254879697Snon/* 1 */ {SCSI_LOW_MSG_REJECT, MSG_REJECT, NULL, NULL, MSG_RELEASE_ATN}, 254979697Snon/* 2 */ {SCSI_LOW_MSG_PARITY, MSG_PARITY, NULL, NULL, MSG_RELEASE_ATN}, 255079697Snon/* 3 */ {SCSI_LOW_MSG_ERROR, MSG_I_ERROR, NULL, NULL, MSG_RELEASE_ATN}, 255179697Snon/* 4 */ {SCSI_LOW_MSG_IDENTIFY, MSG_IDENTIFY, scsi_low_msgfunc_identify, scsi_low_errfunc_identify, 0}, 255279697Snon/* 5 */ {SCSI_LOW_MSG_ABORT, MSG_ABORT, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 255379697Snon/* 6 */ {SCSI_LOW_MSG_TERMIO, MSG_TERM_IO, NULL, NULL, MSG_RELEASE_ATN}, 255479697Snon/* 7 */ {SCSI_LOW_MSG_SIMPLE_QTAG, MSG_SIMPLE_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 255579697Snon/* 8 */ {SCSI_LOW_MSG_ORDERED_QTAG, MSG_ORDERED_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 255679697Snon/* 9 */{SCSI_LOW_MSG_HEAD_QTAG, MSG_HEAD_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 255779697Snon/* 10 */ {SCSI_LOW_MSG_ABORT_QTAG, MSG_ABORT_QTAG, scsi_low_msgfunc_qabort, NULL, MSG_RELEASE_ATN}, 255879697Snon/* 11 */ {SCSI_LOW_MSG_CLEAR_QTAG, MSG_CLEAR_QTAG, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 255979697Snon/* 12 */{SCSI_LOW_MSG_WIDE, MSG_EXTEND, scsi_low_msgfunc_wide, scsi_low_errfunc_wide, MSG_RELEASE_ATN}, 256079697Snon/* 13 */{SCSI_LOW_MSG_SYNCH, MSG_EXTEND, scsi_low_msgfunc_synch, scsi_low_errfunc_synch, MSG_RELEASE_ATN}, 256179697Snon/* 14 */{SCSI_LOW_MSG_NOOP, MSG_NOOP, NULL, NULL, MSG_RELEASE_ATN}, 256279697Snon/* 15 */{SCSI_LOW_MSG_ALL, 0}, 256367468Snon}; 256467468Snon 256592770Salfredstatic int scsi_low_msginfunc_ext(struct scsi_low_softc *); 256692770Salfredstatic int scsi_low_synch(struct scsi_low_softc *); 256792770Salfredstatic int scsi_low_wide(struct scsi_low_softc *); 256892770Salfredstatic int scsi_low_msginfunc_msg_reject(struct scsi_low_softc *); 256992770Salfredstatic int scsi_low_msginfunc_rejop(struct scsi_low_softc *); 257092770Salfredstatic int scsi_low_msginfunc_rp(struct scsi_low_softc *); 257192770Salfredstatic int scsi_low_msginfunc_sdp(struct scsi_low_softc *); 257292770Salfredstatic int scsi_low_msginfunc_disc(struct scsi_low_softc *); 257392770Salfredstatic int scsi_low_msginfunc_cc(struct scsi_low_softc *); 257492770Salfredstatic int scsi_low_msginfunc_lcc(struct scsi_low_softc *); 257592770Salfredstatic int scsi_low_msginfunc_parity(struct scsi_low_softc *); 257692770Salfredstatic int scsi_low_msginfunc_noop(struct scsi_low_softc *); 257792770Salfredstatic int scsi_low_msginfunc_simple_qtag(struct scsi_low_softc *); 257892770Salfredstatic int scsi_low_msginfunc_i_wide_residue(struct scsi_low_softc *); 257967468Snon 258067468Snonstruct scsi_low_msgin_data { 258167468Snon u_int md_len; 258292770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 258367468Snon}; 258467468Snon 258567468Snonstruct scsi_low_msgin_data scsi_low_msgin_data[] = { 258667468Snon/* 0 */ {1, scsi_low_msginfunc_cc}, 258767468Snon/* 1 */ {2, scsi_low_msginfunc_ext}, 258867468Snon/* 2 */ {1, scsi_low_msginfunc_sdp}, 258979697Snon/* 3 */ {1, scsi_low_msginfunc_rp}, 259067468Snon/* 4 */ {1, scsi_low_msginfunc_disc}, 259167468Snon/* 5 */ {1, scsi_low_msginfunc_rejop}, 259267468Snon/* 6 */ {1, scsi_low_msginfunc_rejop}, 259367468Snon/* 7 */ {1, scsi_low_msginfunc_msg_reject}, 259467468Snon/* 8 */ {1, scsi_low_msginfunc_noop}, 259567468Snon/* 9 */ {1, scsi_low_msginfunc_parity}, 259679697Snon/* a */ {1, scsi_low_msginfunc_lcc}, 259779697Snon/* b */ {1, scsi_low_msginfunc_lcc}, 259867468Snon/* c */ {1, scsi_low_msginfunc_rejop}, 259967468Snon/* d */ {2, scsi_low_msginfunc_rejop}, 260067468Snon/* e */ {1, scsi_low_msginfunc_rejop}, 260167468Snon/* f */ {1, scsi_low_msginfunc_rejop}, 260267468Snon/* 0x10 */ {1, scsi_low_msginfunc_rejop}, 260367468Snon/* 0x11 */ {1, scsi_low_msginfunc_rejop}, 260467468Snon/* 0x12 */ {1, scsi_low_msginfunc_rejop}, 260567468Snon/* 0x13 */ {1, scsi_low_msginfunc_rejop}, 260667468Snon/* 0x14 */ {1, scsi_low_msginfunc_rejop}, 260767468Snon/* 0x15 */ {1, scsi_low_msginfunc_rejop}, 260867468Snon/* 0x16 */ {1, scsi_low_msginfunc_rejop}, 260967468Snon/* 0x17 */ {1, scsi_low_msginfunc_rejop}, 261067468Snon/* 0x18 */ {1, scsi_low_msginfunc_rejop}, 261167468Snon/* 0x19 */ {1, scsi_low_msginfunc_rejop}, 261267468Snon/* 0x1a */ {1, scsi_low_msginfunc_rejop}, 261367468Snon/* 0x1b */ {1, scsi_low_msginfunc_rejop}, 261467468Snon/* 0x1c */ {1, scsi_low_msginfunc_rejop}, 261567468Snon/* 0x1d */ {1, scsi_low_msginfunc_rejop}, 261667468Snon/* 0x1e */ {1, scsi_low_msginfunc_rejop}, 261767468Snon/* 0x1f */ {1, scsi_low_msginfunc_rejop}, 261879697Snon/* 0x20 */ {2, scsi_low_msginfunc_simple_qtag}, 261967468Snon/* 0x21 */ {2, scsi_low_msginfunc_rejop}, 262067468Snon/* 0x22 */ {2, scsi_low_msginfunc_rejop}, 262179697Snon/* 0x23 */ {2, scsi_low_msginfunc_i_wide_residue}, 262267468Snon/* 0x24 */ {2, scsi_low_msginfunc_rejop}, 262367468Snon/* 0x25 */ {2, scsi_low_msginfunc_rejop}, 262467468Snon/* 0x26 */ {2, scsi_low_msginfunc_rejop}, 262567468Snon/* 0x27 */ {2, scsi_low_msginfunc_rejop}, 262667468Snon/* 0x28 */ {2, scsi_low_msginfunc_rejop}, 262767468Snon/* 0x29 */ {2, scsi_low_msginfunc_rejop}, 262867468Snon/* 0x2a */ {2, scsi_low_msginfunc_rejop}, 262967468Snon/* 0x2b */ {2, scsi_low_msginfunc_rejop}, 263067468Snon/* 0x2c */ {2, scsi_low_msginfunc_rejop}, 263167468Snon/* 0x2d */ {2, scsi_low_msginfunc_rejop}, 263267468Snon/* 0x2e */ {2, scsi_low_msginfunc_rejop}, 263367468Snon/* 0x2f */ {2, scsi_low_msginfunc_rejop}, 263467468Snon/* 0x30 */ {1, scsi_low_msginfunc_rejop} /* default rej op */ 263567468Snon}; 263667468Snon 263767468Snon/************************************************************** 263867468Snon * msgout 263967468Snon **************************************************************/ 264067468Snonstatic int 264179697Snonscsi_low_msgfunc_synch(slp) 264279697Snon struct scsi_low_softc *slp; 264367468Snon{ 264479697Snon struct targ_info *ti = slp->sl_Tnexus; 264567468Snon int ptr = ti->ti_msgoutlen; 264667468Snon 264767468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_SYNCHLEN; 264867468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_SYNCHCODE; 264973025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_maxsynch.period; 265073025Snon ti->ti_msgoutstr[ptr + 4] = ti->ti_maxsynch.offset; 265167468Snon return MSG_EXTEND_SYNCHLEN + 2; 265267468Snon} 265367468Snon 265467468Snonstatic int 265579697Snonscsi_low_msgfunc_wide(slp) 265679697Snon struct scsi_low_softc *slp; 265767468Snon{ 265879697Snon struct targ_info *ti = slp->sl_Tnexus; 265967468Snon int ptr = ti->ti_msgoutlen; 266067468Snon 266167468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_WIDELEN; 266267468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_WIDECODE; 266373025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_width; 266467468Snon return MSG_EXTEND_WIDELEN + 2; 266567468Snon} 266667468Snon 266767468Snonstatic int 266879697Snonscsi_low_msgfunc_identify(slp) 266979697Snon struct scsi_low_softc *slp; 267067468Snon{ 267179697Snon struct targ_info *ti = slp->sl_Tnexus; 267279697Snon struct lun_info *li = slp->sl_Lnexus; 267379697Snon struct slccb *cb = slp->sl_Qnexus; 267479697Snon int ptr = ti->ti_msgoutlen; 267579697Snon u_int8_t msg; 267667468Snon 267779697Snon msg = MSG_IDENTIFY; 267879697Snon if (cb == NULL) 267967468Snon { 268079697Snon slp->sl_error |= FATALIO; 268179697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 268279697Snon SCSI_LOW_INFO(slp, ti, "MSGOUT: nexus unknown"); 268367468Snon } 268467468Snon else 268567468Snon { 268679697Snon if (scsi_low_is_disconnect_ok(cb) != 0) 268779697Snon msg |= (MSG_IDENTIFY_DISCPRIV | li->li_lun); 268879697Snon else 268979697Snon msg |= li->li_lun; 269079697Snon 269179697Snon if (ti->ti_phase == PH_MSGOUT) 269279697Snon { 269379697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 269479697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 269579697Snon { 269679697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 269779697Snon } 269879697Snon } 269967468Snon } 270079697Snon ti->ti_msgoutstr[ptr + 0] = msg; 270167468Snon return 1; 270267468Snon} 270367468Snon 270467468Snonstatic int 270579697Snonscsi_low_msgfunc_abort(slp) 270679697Snon struct scsi_low_softc *slp; 270767468Snon{ 270867468Snon 270979697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_ABORT); 271079697Snon return 1; 271179697Snon} 271279697Snon 271379697Snonstatic int 271479697Snonscsi_low_msgfunc_qabort(slp) 271579697Snon struct scsi_low_softc *slp; 271679697Snon{ 271779697Snon 271879697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_TERM); 271979697Snon return 1; 272079697Snon} 272179697Snon 272279697Snonstatic int 272379697Snonscsi_low_msgfunc_reset(slp) 272479697Snon struct scsi_low_softc *slp; 272579697Snon{ 272679697Snon 272779697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_RESET); 272879697Snon return 1; 272979697Snon} 273079697Snon 273179697Snonstatic int 273279697Snonscsi_low_msgfunc_qtag(slp) 273379697Snon struct scsi_low_softc *slp; 273479697Snon{ 273579697Snon struct targ_info *ti = slp->sl_Tnexus; 273679697Snon struct slccb *cb = slp->sl_Qnexus; 273779697Snon int ptr = ti->ti_msgoutlen; 273879697Snon 273979697Snon if (cb == NULL || cb->ccb_tag == SCSI_LOW_UNKTAG) 274067468Snon { 274167468Snon ti->ti_msgoutstr[ptr + 0] = MSG_NOOP; 274267468Snon return 1; 274367468Snon } 274467468Snon else 274567468Snon { 274679697Snon ti->ti_msgoutstr[ptr + 1] = (u_int8_t) cb->ccb_tag; 274779697Snon if (ti->ti_phase == PH_MSGOUT) 274879697Snon { 274979697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 275079697Snon } 275167468Snon } 275279697Snon return 2; 275367468Snon} 275467468Snon 275567468Snon/* 275667468Snon * The following functions are called when targets give unexpected 275767468Snon * responces in msgin (after msgout). 275867468Snon */ 275967468Snonstatic int 276079697Snonscsi_low_errfunc_identify(slp, msgflags) 276179697Snon struct scsi_low_softc *slp; 276267468Snon u_int msgflags; 276367468Snon{ 276467468Snon 276579697Snon if (slp->sl_Lnexus != NULL) 276679697Snon { 276779697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_DISC; 276879697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 276979697Snon } 277067468Snon return 0; 277167468Snon} 277267468Snon 277367468Snonstatic int 277479697Snonscsi_low_errfunc_synch(slp, msgflags) 277579697Snon struct scsi_low_softc *slp; 277667468Snon u_int msgflags; 277767468Snon{ 277879697Snon struct targ_info *ti = slp->sl_Tnexus; 277967468Snon 278067468Snon MSGIN_PERIOD(ti) = 0; 278167468Snon MSGIN_OFFSET(ti) = 0; 278279697Snon scsi_low_synch(slp); 278367468Snon return 0; 278467468Snon} 278567468Snon 278667468Snonstatic int 278779697Snonscsi_low_errfunc_wide(slp, msgflags) 278879697Snon struct scsi_low_softc *slp; 278967468Snon u_int msgflags; 279067468Snon{ 279179697Snon struct targ_info *ti = slp->sl_Tnexus; 279279697Snon 279379697Snon MSGIN_WIDTHP(ti) = 0; 279479697Snon scsi_low_wide(slp); 279567468Snon return 0; 279667468Snon} 279767468Snon 279879697Snonstatic int 279979697Snonscsi_low_errfunc_qtag(slp, msgflags) 280079697Snon struct scsi_low_softc *slp; 280179697Snon u_int msgflags; 280279697Snon{ 280379697Snon 280479697Snon if ((msgflags & SCSI_LOW_MSG_REJECT) != 0) 280579697Snon { 280679697Snon if (slp->sl_Qnexus != NULL) 280779697Snon { 280879697Snon scsi_low_deactivate_qtag(slp->sl_Qnexus); 280979697Snon } 281079697Snon if (slp->sl_Lnexus != NULL) 281179697Snon { 281279697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_QTAG; 281379697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 281479697Snon } 2815240325Sjhb device_printf(slp->sl_dev, "scsi_low: qtag msg rejected\n"); 281679697Snon } 281779697Snon return 0; 281879697Snon} 281979697Snon 282079697Snon 282167468Snonint 282279697Snonscsi_low_msgout(slp, ti, fl) 282367468Snon struct scsi_low_softc *slp; 282467468Snon struct targ_info *ti; 282579697Snon u_int fl; 282667468Snon{ 282767468Snon struct scsi_low_msgout_data *mdp; 282867468Snon int len = 0; 282967468Snon 283079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 283179697Snon if (ti != slp->sl_Tnexus) 283279697Snon { 283379697Snon scsi_low_print(slp, NULL); 283479697Snon panic("scsi_low_msgout: Target nexus inconsistent"); 283579697Snon } 283679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 283779697Snon 283879697Snon slp->sl_ph_count ++; 283979697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 284079697Snon { 2841240325Sjhb device_printf(slp->sl_dev, "too many phase changes\n"); 284279697Snon slp->sl_error |= FATALIO; 284379697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 284479697Snon } 284579697Snon 284667468Snon /* STEP I. 284767468Snon * Scsi phase changes. 284867468Snon * Previously msgs asserted are accepted by our target or 284967468Snon * processed by scsi_low_msgin. 285067468Snon * Thus clear all saved informations. 285167468Snon */ 285279697Snon if ((fl & SCSI_LOW_MSGOUT_INIT) != 0) 285367468Snon { 285467468Snon ti->ti_omsgflags = 0; 285567468Snon ti->ti_emsgflags = 0; 285667468Snon } 285779697Snon else if (slp->sl_atten == 0) 285879697Snon { 285967468Snon /* STEP II. 286067468Snon * We did not assert attention, however still our target required 286167468Snon * msgs. Resend previous msgs. 286267468Snon */ 286367468Snon ti->ti_msgflags |= ti->ti_omsgflags; 286479697Snon ti->ti_omsgflags = 0; 286567468Snon#ifdef SCSI_LOW_DIAGNOSTIC 2866240325Sjhb device_printf(slp->sl_dev, "scsi_low_msgout: retry msgout\n"); 286767468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 286867468Snon } 286967468Snon 287067468Snon /* STEP III. 287179697Snon * We have no msgs. send MSG_NOOP (OK?) 287267468Snon */ 287379697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 287467468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_NOOP, 0); 287567468Snon 287667468Snon /* STEP IV. 287767468Snon * Process all msgs 287867468Snon */ 287967468Snon ti->ti_msgoutlen = 0; 288079697Snon slp->sl_clear_atten = 0; 288167468Snon mdp = &scsi_low_msgout_data[0]; 288267468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 288367468Snon { 288467468Snon if ((ti->ti_msgflags & mdp->md_flags) != 0) 288567468Snon { 288667468Snon ti->ti_omsgflags |= mdp->md_flags; 288767468Snon ti->ti_msgflags &= ~mdp->md_flags; 288867468Snon ti->ti_emsgflags = mdp->md_flags; 288967468Snon 289067468Snon ti->ti_msgoutstr[ti->ti_msgoutlen] = mdp->md_msg; 289167468Snon if (mdp->md_msgfunc != NULL) 289279697Snon len = (*mdp->md_msgfunc) (slp); 289367468Snon else 289467468Snon len = 1; 289567468Snon 289679697Snon#ifdef SCSI_LOW_DIAGNOSTIC 289779697Snon scsi_low_msg_log_write(&ti->ti_log_msgout, 289879697Snon &ti->ti_msgoutstr[ti->ti_msgoutlen], len); 289979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 290079697Snon 290167468Snon ti->ti_msgoutlen += len; 290279697Snon if ((mdp->md_condition & MSG_RELEASE_ATN) != 0) 290379697Snon { 290479697Snon slp->sl_clear_atten = 1; 290579697Snon break; 290679697Snon } 290779697Snon 290879697Snon if ((fl & SCSI_LOW_MSGOUT_UNIFY) == 0 || 290967468Snon ti->ti_msgflags == 0) 291067468Snon break; 291179697Snon 291267468Snon if (ti->ti_msgoutlen >= SCSI_LOW_MAX_MSGLEN - 5) 291367468Snon break; 291467468Snon } 291567468Snon } 291667468Snon 291779697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 291879697Snon slp->sl_clear_atten = 1; 291967468Snon 292067468Snon return ti->ti_msgoutlen; 292167468Snon} 292267468Snon 292367468Snon/************************************************************** 292467468Snon * msgin 292567468Snon **************************************************************/ 292667468Snonstatic int 292779697Snonscsi_low_msginfunc_noop(slp) 292879697Snon struct scsi_low_softc *slp; 292967468Snon{ 293067468Snon 293167468Snon return 0; 293267468Snon} 293367468Snon 293467468Snonstatic int 293579697Snonscsi_low_msginfunc_rejop(slp) 293679697Snon struct scsi_low_softc *slp; 293767468Snon{ 293879697Snon struct targ_info *ti = slp->sl_Tnexus; 293967468Snon u_int8_t msg = ti->ti_msgin[0]; 294067468Snon 2941240325Sjhb device_printf(slp->sl_dev, "MSGIN: msg 0x%x rejected\n", (u_int) msg); 294267468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 294367468Snon return 0; 294467468Snon} 294567468Snon 294667468Snonstatic int 294779697Snonscsi_low_msginfunc_cc(slp) 294879697Snon struct scsi_low_softc *slp; 294967468Snon{ 295079697Snon struct lun_info *li; 295167468Snon 295267468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC); 295379697Snon 295479697Snon /* validate status */ 295579697Snon if (slp->sl_Qnexus == NULL) 295679697Snon return ENOENT; 295779697Snon 295879697Snon slp->sl_Qnexus->ccb_sscp.scp_status = slp->sl_scp.scp_status; 295979697Snon li = slp->sl_Lnexus; 296079697Snon switch (slp->sl_scp.scp_status) 296179697Snon { 296279697Snon case ST_GOOD: 296379697Snon li->li_maxnqio = li->li_maxnexus; 296479697Snon break; 296579697Snon 296679697Snon case ST_CHKCOND: 296779697Snon li->li_maxnqio = 0; 296879697Snon if (li->li_qflags & SCSI_LOW_QFLAG_CA_QCLEAR) 296979697Snon scsi_low_reset_nexus_lun(slp, li, 0); 297079697Snon break; 297179697Snon 297279697Snon case ST_BUSY: 297379697Snon li->li_maxnqio = 0; 297479697Snon break; 297579697Snon 297679697Snon case ST_QUEFULL: 297779697Snon if (li->li_maxnexus >= li->li_nqio) 297879697Snon li->li_maxnexus = li->li_nqio - 1; 297979697Snon li->li_maxnqio = li->li_maxnexus; 298079697Snon break; 298179697Snon 298279697Snon case ST_INTERGOOD: 298379697Snon case ST_INTERMET: 298479697Snon slp->sl_error |= MSGERR; 298579697Snon break; 298679697Snon 298779697Snon default: 298879697Snon break; 298979697Snon } 299067468Snon return 0; 299167468Snon} 299267468Snon 299367468Snonstatic int 299479697Snonscsi_low_msginfunc_lcc(slp) 299579697Snon struct scsi_low_softc *slp; 299679697Snon{ 299767468Snon struct targ_info *ti; 299879697Snon struct lun_info *li; 299979697Snon struct slccb *ncb, *cb; 300079697Snon 300179697Snon ti = slp->sl_Tnexus; 300279697Snon li = slp->sl_Lnexus; 300379697Snon if ((cb = slp->sl_Qnexus) == NULL) 300479697Snon goto bad; 300579697Snon 300679697Snon cb->ccb_sscp.scp_status = slp->sl_scp.scp_status; 300779697Snon switch (slp->sl_scp.scp_status) 300879697Snon { 300979697Snon case ST_INTERGOOD: 301079697Snon case ST_INTERMET: 301179697Snon li->li_maxnqio = li->li_maxnexus; 301279697Snon break; 301379697Snon 301479697Snon default: 301579697Snon slp->sl_error |= MSGERR; 301679697Snon break; 301779697Snon } 301879697Snon 301979697Snon if ((li->li_flags & SCSI_LOW_LINK) == 0) 302079697Snon goto bad; 302179697Snon 302279697Snon cb->ccb_error |= slp->sl_error; 302379697Snon if (cb->ccb_error != 0) 302479697Snon goto bad; 302579697Snon 302679697Snon for (ncb = TAILQ_FIRST(&slp->sl_start); ncb != NULL; 302779697Snon ncb = TAILQ_NEXT(ncb, ccb_chain)) 302879697Snon { 302979697Snon if (ncb->li == li) 303079697Snon goto cmd_link_start; 303179697Snon } 303279697Snon 303379697Snon 303479697Snonbad: 303579697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_LCTERM); 303679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 303779697Snon return EIO; 303879697Snon 303979697Snoncmd_link_start: 304079697Snon ncb->ccb_flags &= ~CCB_STARTQ; 304179697Snon TAILQ_REMOVE(&slp->sl_start, ncb, ccb_chain); 304279697Snon 304379697Snon scsi_low_dealloc_qtag(ncb); 304479697Snon ncb->ccb_tag = cb->ccb_tag; 304579697Snon ncb->ccb_otag = cb->ccb_otag; 304679697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 304779697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 304879697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 3049240325Sjhb panic("%s: linked ccb retried", 3050240325Sjhb device_get_nameunit(slp->sl_dev)); 305179697Snon 305279697Snon slp->sl_Qnexus = ncb; 305379697Snon slp->sl_ph_count = 0; 305479697Snon 305579697Snon ncb->ccb_error = 0; 305679697Snon ncb->ccb_datalen = -1; 305779697Snon ncb->ccb_scp.scp_status = ST_UNKNOWN; 305879697Snon ncb->ccb_flags &= ~CCB_INTERNAL; 305979697Snon 306079697Snon scsi_low_init_msgsys(slp, ti); 306179697Snon 3062274760Sjhb scsi_low_ccb_setup_cam(slp, ncb); 306379697Snon 306479697Snon if (ncb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 306579697Snon ncb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 306679697Snon ncb->ccb_tc = ncb->ccb_tcmax; 306779697Snon 306879697Snon /* setup saved scsi data pointer */ 306979697Snon ncb->ccb_sscp = ncb->ccb_scp; 307079697Snon slp->sl_scp = ncb->ccb_sscp; 307179697Snon slp->sl_error = ncb->ccb_error; 307279697Snon 307379697Snon#ifdef SCSI_LOW_DIAGNOSTIC 307479697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 307579697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 307679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 307779697Snon return EJUSTRETURN; 307879697Snon} 307979697Snon 308079697Snonstatic int 308179697Snonscsi_low_msginfunc_disc(slp) 308279697Snon struct scsi_low_softc *slp; 308367468Snon{ 308467468Snon 308567468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC); 308667468Snon return 0; 308767468Snon} 308867468Snon 308967468Snonstatic int 309079697Snonscsi_low_msginfunc_sdp(slp) 309179697Snon struct scsi_low_softc *slp; 309267468Snon{ 309379697Snon struct slccb *cb = slp->sl_Qnexus; 309467468Snon 309579697Snon if (cb != NULL) 309679697Snon { 309779697Snon cb->ccb_sscp.scp_datalen = slp->sl_scp.scp_datalen; 309879697Snon cb->ccb_sscp.scp_data = slp->sl_scp.scp_data; 309979697Snon } 310067468Snon else 310179697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 310267468Snon return 0; 310367468Snon} 310467468Snon 310567468Snonstatic int 310679697Snonscsi_low_msginfunc_rp(slp) 310779697Snon struct scsi_low_softc *slp; 310867468Snon{ 310967468Snon 311079697Snon if (slp->sl_Qnexus != NULL) 311179697Snon slp->sl_scp = slp->sl_Qnexus->ccb_sscp; 311267468Snon else 311379697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 311467468Snon return 0; 311567468Snon} 311667468Snon 311767468Snonstatic int 311879697Snonscsi_low_synch(slp) 311979697Snon struct scsi_low_softc *slp; 312067468Snon{ 312179697Snon struct targ_info *ti = slp->sl_Tnexus; 312279697Snon u_int period = 0, offset = 0, speed; 312367468Snon u_char *s; 312467468Snon int error; 312567468Snon 312679697Snon if ((MSGIN_PERIOD(ti) >= ti->ti_maxsynch.period && 312779697Snon MSGIN_OFFSET(ti) <= ti->ti_maxsynch.offset) || 312879697Snon MSGIN_OFFSET(ti) == 0) 312967468Snon { 313067468Snon if ((offset = MSGIN_OFFSET(ti)) != 0) 313167468Snon period = MSGIN_PERIOD(ti); 313267468Snon s = offset ? "synchronous" : "async"; 313367468Snon } 313467468Snon else 313567468Snon { 313667468Snon /* XXX: 313767468Snon * Target seems to be brain damaged. 313867468Snon * Force async transfer. 313967468Snon */ 314073025Snon ti->ti_maxsynch.period = 0; 314173025Snon ti->ti_maxsynch.offset = 0; 3142240325Sjhb device_printf(slp->sl_dev, 3143240325Sjhb "target brain damaged. async transfer\n"); 314467468Snon return EINVAL; 314567468Snon } 314667468Snon 314773025Snon ti->ti_maxsynch.period = period; 314873025Snon ti->ti_maxsynch.offset = offset; 314967468Snon 315067468Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_SYNCH); 315167468Snon if (error != 0) 315267468Snon { 315367468Snon /* XXX: 315467468Snon * Current period and offset are not acceptable 315567468Snon * for our adapter. 315667468Snon * The adapter changes max synch and max offset. 315767468Snon */ 3158240325Sjhb device_printf(slp->sl_dev, 3159240325Sjhb "synch neg failed. retry synch msg neg ...\n"); 316067468Snon return error; 316167468Snon } 316267468Snon 316379697Snon ti->ti_osynch = ti->ti_maxsynch; 316479697Snon if (offset > 0) 316579697Snon { 316679697Snon ti->ti_setup_msg_done |= SCSI_LOW_MSG_SYNCH; 316779697Snon } 316879697Snon 316967468Snon /* inform data */ 317079697Snon if ((slp->sl_show_result & SHOW_SYNCH_NEG) != 0) 317167468Snon { 317279697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 317379697Snon struct slccb *cb = slp->sl_Qnexus; 317479697Snon 317579697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 317679697Snon return 0; 317779697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 317879697Snon 3179240325Sjhb device_printf(slp->sl_dev, 3180240325Sjhb "(%d:*): <%s> offset %d period %dns ", 3181240325Sjhb ti->ti_id, s, offset, period * 4); 318279697Snon 318379697Snon if (period != 0) 318479697Snon { 318579697Snon speed = 1000 * 10 / (period * 4); 318679697Snon printf("%d.%d M/s", speed / 10, speed % 10); 318779697Snon } 318879697Snon printf("\n"); 318967468Snon } 319079697Snon return 0; 319179697Snon} 319267468Snon 319379697Snonstatic int 319479697Snonscsi_low_wide(slp) 319579697Snon struct scsi_low_softc *slp; 319679697Snon{ 319779697Snon struct targ_info *ti = slp->sl_Tnexus; 319879697Snon int error; 319979697Snon 320079697Snon ti->ti_width = MSGIN_WIDTHP(ti); 320179697Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_WIDE); 320279697Snon if (error != 0) 320379697Snon { 320479697Snon /* XXX: 320579697Snon * Current width is not acceptable for our adapter. 320679697Snon * The adapter changes max width. 320779697Snon */ 3208240325Sjhb device_printf(slp->sl_dev, 3209240325Sjhb "wide neg failed. retry wide msg neg ...\n"); 321079697Snon return error; 321179697Snon } 321279697Snon 321379697Snon ti->ti_owidth = ti->ti_width; 321479697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 321579697Snon { 321679697Snon ti->ti_setup_msg_done |= 321779697Snon (SCSI_LOW_MSG_SYNCH | SCSI_LOW_MSG_WIDE); 321879697Snon } 321979697Snon 322079697Snon /* inform data */ 322179697Snon if ((slp->sl_show_result & SHOW_WIDE_NEG) != 0) 322279697Snon { 322379697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 322479697Snon struct slccb *cb = slp->sl_Qnexus; 322579697Snon 322679697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 322779697Snon return 0; 322879697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 322979697Snon 3230240325Sjhb device_printf(slp->sl_dev, "(%d:*): transfer width %d bits\n", 3231240325Sjhb ti->ti_id, 1 << (3 + ti->ti_width)); 323279697Snon } 323367468Snon return 0; 323467468Snon} 323567468Snon 323667468Snonstatic int 323779697Snonscsi_low_msginfunc_simple_qtag(slp) 323879697Snon struct scsi_low_softc *slp; 323967468Snon{ 324079697Snon struct targ_info *ti = slp->sl_Tnexus; 324179697Snon scsi_low_tag_t etag = (scsi_low_tag_t) ti->ti_msgin[1]; 324279697Snon 324379697Snon if (slp->sl_Qnexus != NULL) 324479697Snon { 324579697Snon if (slp->sl_Qnexus->ccb_tag != etag) 324679697Snon { 324779697Snon slp->sl_error |= FATALIO; 324879697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 324979697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: qtag mismatch"); 325079697Snon } 325179697Snon } 325279697Snon else if (scsi_low_establish_ccb(ti, slp->sl_Lnexus, etag) == NULL) 325379697Snon { 325479697Snon#ifdef SCSI_LOW_DEBUG 325579697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id)) 325679697Snon return 0; 325779697Snon#endif /* SCSI_LOW_DEBUG */ 325879697Snon 325979697Snon slp->sl_error |= FATALIO; 326079697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT_QTAG, 0); 326179697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: taged ccb not found"); 326279697Snon } 326379697Snon return 0; 326479697Snon} 326579697Snon 326679697Snonstatic int 326779697Snonscsi_low_msginfunc_i_wide_residue(slp) 326879697Snon struct scsi_low_softc *slp; 326979697Snon{ 327079697Snon struct targ_info *ti = slp->sl_Tnexus; 327179697Snon struct slccb *cb = slp->sl_Qnexus; 327279697Snon int res = (int) ti->ti_msgin[1]; 327379697Snon 327479697Snon if (cb == NULL || res <= 0 || 327579697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_16 && res > 1) || 327679697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_32 && res > 3)) 327779697Snon return EINVAL; 327879697Snon 327979697Snon if (slp->sl_scp.scp_datalen + res > cb->ccb_scp.scp_datalen) 328079697Snon return EINVAL; 328179697Snon 328279697Snon slp->sl_scp.scp_datalen += res; 328379697Snon slp->sl_scp.scp_data -= res; 328479697Snon scsi_low_data_finish(slp); 328579697Snon return 0; 328679697Snon} 328779697Snon 328879697Snonstatic int 328979697Snonscsi_low_msginfunc_ext(slp) 329079697Snon struct scsi_low_softc *slp; 329179697Snon{ 329279697Snon struct slccb *cb = slp->sl_Qnexus; 329379697Snon struct lun_info *li = slp->sl_Lnexus; 329479697Snon struct targ_info *ti = slp->sl_Tnexus; 329567468Snon int count, retry; 329667468Snon u_int32_t *ptr; 329767468Snon 329867468Snon if (ti->ti_msginptr == 2) 329967468Snon { 330067468Snon ti->ti_msginlen = ti->ti_msgin[1] + 2; 330167468Snon return 0; 330267468Snon } 330367468Snon 330467468Snon switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2])) 330567468Snon { 330667468Snon case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE): 330767468Snon if (cb == NULL) 330867468Snon break; 330967468Snon 331067468Snon ptr = (u_int32_t *)(&ti->ti_msgin[3]); 331167468Snon count = (int) htonl((long) (*ptr)); 331267468Snon if(slp->sl_scp.scp_datalen - count < 0 || 331367468Snon slp->sl_scp.scp_datalen - count > cb->ccb_scp.scp_datalen) 331467468Snon break; 331567468Snon 331667468Snon slp->sl_scp.scp_datalen -= count; 331767468Snon slp->sl_scp.scp_data += count; 331867468Snon return 0; 331967468Snon 332067468Snon case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE): 332167468Snon if (li == NULL) 332267468Snon break; 332367468Snon 332479697Snon retry = scsi_low_synch(slp); 332567468Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_SYNCH) == 0) 332667468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0); 332779697Snon 332879697Snon#ifdef SCSI_LOW_DEBUG 332979697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 333079697Snon { 333179697Snon scsi_low_test_atten(slp, ti, SCSI_LOW_MSG_SYNCH); 333279697Snon } 333379697Snon#endif /* SCSI_LOW_DEBUG */ 333467468Snon return 0; 333567468Snon 333667468Snon case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE): 333767468Snon if (li == NULL) 333867468Snon break; 333967468Snon 334079697Snon retry = scsi_low_wide(slp); 334179697Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_WIDE) == 0) 334279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0); 334379697Snon 334467468Snon return 0; 334567468Snon 334667468Snon default: 334767468Snon break; 334867468Snon } 334967468Snon 335067468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 335167468Snon return EINVAL; 335267468Snon} 335367468Snon 335467468Snonstatic int 335579697Snonscsi_low_msginfunc_parity(slp) 335679697Snon struct scsi_low_softc *slp; 335767468Snon{ 335879697Snon struct targ_info *ti = slp->sl_Tnexus; 335967468Snon 336079697Snon /* only I -> T, invalid! */ 336179697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 336267468Snon return 0; 336367468Snon} 336467468Snon 336567468Snonstatic int 336679697Snonscsi_low_msginfunc_msg_reject(slp) 336779697Snon struct scsi_low_softc *slp; 336867468Snon{ 336979697Snon struct targ_info *ti = slp->sl_Tnexus; 337067468Snon struct scsi_low_msgout_data *mdp; 337167468Snon u_int msgflags; 337267468Snon 337379697Snon if (ti->ti_emsgflags != 0) 337467468Snon { 3375240325Sjhb device_printf(slp->sl_dev, "msg flags [0x%x] rejected\n", 3376240325Sjhb ti->ti_emsgflags); 337767468Snon msgflags = SCSI_LOW_MSG_REJECT; 337867468Snon mdp = &scsi_low_msgout_data[0]; 337967468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 338067468Snon { 338167468Snon if ((ti->ti_emsgflags & mdp->md_flags) != 0) 338267468Snon { 338367468Snon ti->ti_emsgflags &= ~mdp->md_flags; 338467468Snon if (mdp->md_errfunc != NULL) 338579697Snon (*mdp->md_errfunc) (slp, msgflags); 338667468Snon break; 338767468Snon } 338867468Snon } 338979697Snon return 0; 339067468Snon } 339179697Snon else 339279697Snon { 339379697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: rejected msg not found"); 339479697Snon slp->sl_error |= MSGERR; 339579697Snon } 339679697Snon return EINVAL; 339767468Snon} 339867468Snon 339979697Snonint 340067468Snonscsi_low_msgin(slp, ti, c) 340167468Snon struct scsi_low_softc *slp; 340267468Snon struct targ_info *ti; 340379697Snon u_int c; 340467468Snon{ 340567468Snon struct scsi_low_msgin_data *sdp; 340667468Snon struct lun_info *li; 340767468Snon u_int8_t msg; 340867468Snon 340979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 341079697Snon if (ti != slp->sl_Tnexus) 341179697Snon { 341279697Snon scsi_low_print(slp, NULL); 341379697Snon panic("scsi_low_msgin: Target nexus inconsistent"); 341479697Snon } 341579697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 341679697Snon 341767468Snon /* 341867468Snon * Phase changes, clear the pointer. 341967468Snon */ 342067468Snon if (ti->ti_ophase != ti->ti_phase) 342167468Snon { 342267468Snon MSGINPTR_CLR(ti); 342379697Snon ti->ti_msgin_parity_error = 0; 342479697Snon 342579697Snon slp->sl_ph_count ++; 342679697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 342779697Snon { 3428240325Sjhb device_printf(slp->sl_dev, "too many phase changes\n"); 342979697Snon slp->sl_error |= FATALIO; 343079697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 343179697Snon } 343267468Snon } 343367468Snon 343467468Snon /* 343567468Snon * Store a current messages byte into buffer and 343667468Snon * wait for the completion of the current msg. 343767468Snon */ 343879697Snon ti->ti_msgin[ti->ti_msginptr ++] = (u_int8_t) c; 343967468Snon if (ti->ti_msginptr >= SCSI_LOW_MAX_MSGLEN) 344067468Snon { 344167468Snon ti->ti_msginptr = SCSI_LOW_MAX_MSGLEN - 1; 344267468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 344367468Snon } 344467468Snon 344567468Snon /* 344679697Snon * Check parity errors. 344779697Snon */ 344879697Snon if ((c & SCSI_LOW_DATA_PE) != 0) 344979697Snon { 345079697Snon ti->ti_msgin_parity_error ++; 345179697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0); 345279697Snon goto out; 345379697Snon } 345479697Snon 345579697Snon if (ti->ti_msgin_parity_error != 0) 345679697Snon goto out; 345779697Snon 345879697Snon /* 345967468Snon * Calculate messages length. 346067468Snon */ 346167468Snon msg = ti->ti_msgin[0]; 346267468Snon if (msg < MSGIN_DATA_LAST) 346367468Snon sdp = &scsi_low_msgin_data[msg]; 346467468Snon else 346567468Snon sdp = &scsi_low_msgin_data[MSGIN_DATA_LAST]; 346667468Snon 346767468Snon if (ti->ti_msginlen == 0) 346867468Snon { 346967468Snon ti->ti_msginlen = sdp->md_len; 347067468Snon } 347167468Snon 347267468Snon /* 347367468Snon * Check comletion. 347467468Snon */ 347567468Snon if (ti->ti_msginptr < ti->ti_msginlen) 347679697Snon return EJUSTRETURN; 347767468Snon 347867468Snon /* 347967468Snon * Do process. 348067468Snon */ 348167468Snon if ((msg & MSG_IDENTIFY) == 0) 348267468Snon { 348379697Snon if (((*sdp->md_msgfunc) (slp)) == EJUSTRETURN) 348479697Snon return EJUSTRETURN; 348567468Snon } 348667468Snon else 348767468Snon { 348879697Snon li = slp->sl_Lnexus; 348967468Snon if (li == NULL) 349067468Snon { 349179697Snon li = scsi_low_alloc_li(ti, MSGCMD_LUN(msg), 0); 349267468Snon if (li == NULL) 349367468Snon goto badlun; 349479697Snon slp->sl_Lnexus = li; 349579697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 349667468Snon } 349779697Snon else 349879697Snon { 349979697Snon if (MSGCMD_LUN(msg) != li->li_lun) 350079697Snon goto badlun; 350179697Snon } 350267468Snon 350379697Snon if (slp->sl_Qnexus == NULL && li->li_nqio == 0) 350467468Snon { 350567468Snon if (!scsi_low_establish_ccb(ti, li, SCSI_LOW_UNKTAG)) 350679697Snon { 350779697Snon#ifdef SCSI_LOW_DEBUG 350879697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 350979697Snon { 351079697Snon goto out; 351179697Snon } 351279697Snon#endif /* SCSI_LOW_DEBUG */ 351367468Snon goto badlun; 351479697Snon } 351567468Snon } 351667468Snon } 351779697Snon goto out; 351867468Snon 351967468Snon /* 352079697Snon * Msg process completed, reset msgin pointer and assert ATN if desired. 352167468Snon */ 352279697Snonbadlun: 352379697Snon slp->sl_error |= FATALIO; 352479697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 352579697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: identify wrong"); 352679697Snon 352779697Snonout: 352879697Snon if (ti->ti_msginptr < ti->ti_msginlen) 352979697Snon return EJUSTRETURN; 353079697Snon 353179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 353279697Snon scsi_low_msg_log_write(&ti->ti_log_msgin, 353379697Snon &ti->ti_msgin[0], ti->ti_msginlen); 353479697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 353579697Snon 353679697Snon MSGINPTR_CLR(ti); 353779697Snon return 0; 353879697Snon} 353979697Snon 354079697Snon/********************************************************** 354179697Snon * disconnect 354279697Snon **********************************************************/ 354379697Snonint 354479697Snonscsi_low_disconnected(slp, ti) 354579697Snon struct scsi_low_softc *slp; 354679697Snon struct targ_info *ti; 354779697Snon{ 354879697Snon struct slccb *cb = slp->sl_Qnexus; 354979697Snon 355079697Snon /* check phase completion */ 355179697Snon switch (slp->sl_msgphase) 355267468Snon { 355379697Snon case MSGPH_RESET: 355479697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 355579697Snon scsi_low_msginfunc_cc(slp); 355679697Snon scsi_low_reset_nexus_target(slp, slp->sl_Tnexus, 0); 355779697Snon goto io_resume; 355867468Snon 355979697Snon case MSGPH_ABORT: 356079697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 356179697Snon scsi_low_msginfunc_cc(slp); 356279697Snon scsi_low_reset_nexus_lun(slp, slp->sl_Lnexus, 0); 356379697Snon goto io_resume; 356479697Snon 356579697Snon case MSGPH_TERM: 356679697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 356779697Snon scsi_low_msginfunc_cc(slp); 356879697Snon goto io_resume; 356979697Snon 357079697Snon case MSGPH_DISC: 357179697Snon if (cb != NULL) 357267468Snon { 357379697Snon struct lun_info *li; 357479697Snon 357579697Snon li = cb->li; 357679697Snon TAILQ_INSERT_TAIL(&li->li_discq, cb, ccb_chain); 357779697Snon cb->ccb_flags |= CCB_DISCQ; 357879697Snon cb->ccb_error |= slp->sl_error; 357979697Snon li->li_disc ++; 358079697Snon ti->ti_disc ++; 358179697Snon slp->sl_disc ++; 358279697Snon } 358379697Snon 358479697Snon#ifdef SCSI_LOW_STATICS 358579697Snon scsi_low_statics.nexus_disconnected ++; 358679697Snon#endif /* SCSI_LOW_STATICS */ 358779697Snon 358879697Snon#ifdef SCSI_LOW_DEBUG 358979697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DISC, ti->ti_id) != 0) 359079697Snon { 359179697Snon printf("## SCSI_LOW_DISCONNECTED ===============\n"); 359279697Snon scsi_low_print(slp, NULL); 359379697Snon } 359479697Snon#endif /* SCSI_LOW_DEBUG */ 359579697Snon break; 359679697Snon 359779697Snon case MSGPH_NULL: 359879697Snon slp->sl_error |= FATALIO; 359979697Snon if (ti->ti_phase == PH_SELSTART) 360079697Snon slp->sl_error |= SELTIMEOUTIO; 360179697Snon else 360279697Snon slp->sl_error |= UBFERR; 360379697Snon /* fall through */ 360479697Snon 360579697Snon case MSGPH_LCTERM: 360679697Snon case MSGPH_CMDC: 360779697Snonio_resume: 360879697Snon if (cb == NULL) 360979697Snon break; 361079697Snon 361179697Snon#ifdef SCSI_LOW_DEBUG 361279697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 361379697Snon { 361479697Snon if (cb->ccb_omsgoutflag == SCSI_LOW_MSG_NOOP && 361579697Snon (cb->ccb_msgoutflag != 0 || 361679697Snon (ti->ti_msgflags & SCSI_LOW_MSG_NOOP))) 361779697Snon { 361879697Snon scsi_low_info(slp, ti, "ATTEN CHECK FAILED"); 361979697Snon } 362079697Snon } 362179697Snon#endif /* SCSI_LOW_DEBUG */ 362279697Snon 362379697Snon cb->ccb_error |= slp->sl_error; 362479697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 362579697Snon { 362679697Snon cb->ccb_flags |= CCB_STARTQ; 362779697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 362879697Snon } 362979697Snon break; 363079697Snon } 363179697Snon 363279697Snon scsi_low_bus_release(slp, ti); 363379697Snon scsi_low_start(slp); 363479697Snon return 1; 363579697Snon} 363679697Snon 363779697Snon/********************************************************** 363879697Snon * TAG operations 363979697Snon **********************************************************/ 3640104094Sphkstatic int 364179697Snonscsi_low_alloc_qtag(cb) 364279697Snon struct slccb *cb; 364379697Snon{ 364479697Snon struct lun_info *li = cb->li; 364579697Snon scsi_low_tag_t etag; 364679697Snon 364779697Snon if (cb->ccb_otag != SCSI_LOW_UNKTAG) 364879697Snon return 0; 364979697Snon 365079697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 365179697Snon etag = ffs(li->li_qtagbits); 365279697Snon if (etag == 0) 365379697Snon return ENOSPC; 365479697Snon 365579697Snon li->li_qtagbits &= ~(1 << (etag - 1)); 365679697Snon cb->ccb_otag = etag; 365779697Snon return 0; 365879697Snon 365979697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 366079697Snon for (etag = li->li_qd ; li->li_qd < SCSI_LOW_MAXNEXUS; li->li_qd ++) 366179697Snon if (li->li_qtagarray[li->li_qd] == 0) 366279697Snon goto found; 366379697Snon 366479697Snon for (li->li_qd = 0; li->li_qd < etag; li->li_qd ++) 366579697Snon if (li->li_qtagarray[li->li_qd] == 0) 366679697Snon goto found; 366779697Snon 366879697Snon return ENOSPC; 366979697Snon 367079697Snonfound: 367179697Snon li->li_qtagarray[li->li_qd] ++; 367279697Snon cb->ccb_otag = (li->li_qd ++); 367379697Snon return 0; 367479697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 367579697Snon} 367679697Snon 3677104094Sphkstatic int 367879697Snonscsi_low_dealloc_qtag(cb) 367979697Snon struct slccb *cb; 368079697Snon{ 368179697Snon struct lun_info *li = cb->li; 368279697Snon scsi_low_tag_t etag; 368379697Snon 368479697Snon if (cb->ccb_otag == SCSI_LOW_UNKTAG) 368579697Snon return 0; 368679697Snon 368779697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 368879697Snon etag = cb->ccb_otag - 1; 368967468Snon#ifdef SCSI_LOW_DIAGNOSTIC 369079697Snon if (etag >= sizeof(li->li_qtagbits) * NBBY) 369179697Snon panic("scsi_low_dealloc_tag: illegal tag"); 369267468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 369379697Snon li->li_qtagbits |= (1 << etag); 369479697Snon 369579697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 369679697Snon etag = cb->ccb_otag; 369779697Snon#ifdef SCSI_LOW_DIAGNOSTIC 369879697Snon if (etag >= SCSI_LOW_MAXNEXUS) 369979697Snon panic("scsi_low_dealloc_tag: illegal tag"); 370079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 370179697Snon li->li_qtagarray[etag] --; 370279697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 370379697Snon 370479697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 370579697Snon return 0; 370679697Snon} 370779697Snon 3708104094Sphkstatic struct slccb * 370979697Snonscsi_low_revoke_ccb(slp, cb, fdone) 371079697Snon struct scsi_low_softc *slp; 371179697Snon struct slccb *cb; 371279697Snon int fdone; 371379697Snon{ 371479697Snon struct targ_info *ti = cb->ti; 371579697Snon struct lun_info *li = cb->li; 371679697Snon 371779697Snon#ifdef SCSI_LOW_DIAGNOSTIC 371879697Snon if ((cb->ccb_flags & (CCB_STARTQ | CCB_DISCQ)) == 371979697Snon (CCB_STARTQ | CCB_DISCQ)) 372079697Snon { 3721240325Sjhb panic("%s: ccb in both queue", 3722240325Sjhb device_get_nameunit(slp->sl_dev)); 372367468Snon } 372479697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 372567468Snon 372679697Snon if ((cb->ccb_flags & CCB_STARTQ) != 0) 372779697Snon { 372879697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 372979697Snon } 373079697Snon 373179697Snon if ((cb->ccb_flags & CCB_DISCQ) != 0) 373279697Snon { 373379697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 373479697Snon li->li_disc --; 373579697Snon ti->ti_disc --; 373679697Snon slp->sl_disc --; 373779697Snon } 373879697Snon 373979697Snon cb->ccb_flags &= ~(CCB_STARTQ | CCB_DISCQ | 374079697Snon CCB_SENSE | CCB_CLEARQ | CCB_INTERNAL); 374179697Snon 374279697Snon if (fdone != 0 && 374379697Snon (cb->ccb_rcnt ++ >= slp->sl_max_retry || 374479697Snon (cb->ccb_flags & CCB_NORETRY) != 0)) 374579697Snon { 374679697Snon cb->ccb_error |= FATALIO; 374779697Snon cb->ccb_flags &= ~CCB_AUTOSENSE; 374879697Snon if (scsi_low_done(slp, cb) != SCSI_LOW_DONE_COMPLETE) 3749240325Sjhb panic("%s: done ccb retried", 3750240325Sjhb device_get_nameunit(slp->sl_dev)); 375179697Snon return NULL; 375279697Snon } 375379697Snon else 375479697Snon { 375579697Snon cb->ccb_error |= PENDINGIO; 375679697Snon scsi_low_deactivate_qtag(cb); 375779697Snon scsi_low_ccb_message_retry(cb); 375879697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 375979697Snon return cb; 376079697Snon } 376167468Snon} 376267468Snon 3763104094Sphkstatic void 376479697Snonscsi_low_reset_nexus_lun(slp, li, fdone) 376579697Snon struct scsi_low_softc *slp; 376679697Snon struct lun_info *li; 376779697Snon int fdone; 376879697Snon{ 376979697Snon struct slccb *cb, *ncb, *ecb; 377079697Snon 377179697Snon if (li == NULL) 377279697Snon return; 377379697Snon 377479697Snon ecb = NULL; 377579697Snon for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; cb = ncb) 377679697Snon { 377779697Snon ncb = TAILQ_NEXT(cb, ccb_chain); 377879697Snon cb = scsi_low_revoke_ccb(slp, cb, fdone); 377979697Snon if (cb != NULL) 378079697Snon { 378179697Snon /* 378279697Snon * presumely keep ordering of io 378379697Snon */ 378479697Snon cb->ccb_flags |= CCB_STARTQ; 378579697Snon if (ecb == NULL) 378679697Snon { 378779697Snon TAILQ_INSERT_HEAD(&slp->sl_start,\ 378879697Snon cb, ccb_chain); 378979697Snon } 379079697Snon else 379179697Snon { 379279697Snon TAILQ_INSERT_AFTER(&slp->sl_start,\ 379379697Snon ecb, cb, ccb_chain); 379479697Snon } 379579697Snon ecb = cb; 379679697Snon } 379779697Snon } 379879697Snon} 379979697Snon 380067468Snon/************************************************************** 380167468Snon * Qurik setup 380267468Snon **************************************************************/ 380367468Snonstatic void 380479697Snonscsi_low_calcf_lun(li) 380567468Snon struct lun_info *li; 380667468Snon{ 380779697Snon struct targ_info *ti = li->li_ti; 380867468Snon struct scsi_low_softc *slp = ti->ti_sc; 380979697Snon u_int cfgflags, diskflags; 381067468Snon 381179697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID) 381279697Snon cfgflags = li->li_cfgflags; 381379697Snon else 381479697Snon cfgflags = 0; 381579697Snon 381679697Snon diskflags = li->li_diskflags & li->li_quirks; 381779697Snon 381879697Snon /* disconnect */ 381967468Snon li->li_flags &= ~SCSI_LOW_DISC; 382067468Snon if ((slp->sl_cfgflags & CFG_NODISC) == 0 && 382179697Snon (diskflags & SCSI_LOW_DISK_DISC) != 0 && 382279697Snon (cfgflags & SCSI_LOW_DISC) != 0) 382367468Snon li->li_flags |= SCSI_LOW_DISC; 382467468Snon 382579697Snon /* parity */ 382667468Snon li->li_flags |= SCSI_LOW_NOPARITY; 382767468Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0 && 382879697Snon (diskflags & SCSI_LOW_DISK_PARITY) != 0 && 382979697Snon (cfgflags & SCSI_LOW_NOPARITY) == 0) 383067468Snon li->li_flags &= ~SCSI_LOW_NOPARITY; 383167468Snon 383279697Snon /* qtag */ 383379697Snon if ((slp->sl_cfgflags & CFG_NOQTAG) == 0 && 383479697Snon (cfgflags & SCSI_LOW_QTAG) != 0 && 383579697Snon (diskflags & SCSI_LOW_DISK_QTAG) != 0) 383679697Snon { 383779697Snon li->li_flags |= SCSI_LOW_QTAG; 383879697Snon li->li_maxnexus = SCSI_LOW_MAXNEXUS; 383979697Snon li->li_maxnqio = li->li_maxnexus; 384079697Snon } 384179697Snon else 384279697Snon { 384379697Snon li->li_flags &= ~SCSI_LOW_QTAG; 384479697Snon li->li_maxnexus = 0; 384579697Snon li->li_maxnqio = li->li_maxnexus; 384679697Snon } 384779697Snon 384879697Snon /* cmd link */ 384979697Snon li->li_flags &= ~SCSI_LOW_LINK; 385079697Snon if ((cfgflags & SCSI_LOW_LINK) != 0 && 385179697Snon (diskflags & SCSI_LOW_DISK_LINK) != 0) 385279697Snon li->li_flags |= SCSI_LOW_LINK; 385379697Snon 385479697Snon /* compatible flags */ 385567468Snon li->li_flags &= ~SCSI_LOW_SYNC; 385679697Snon if (ti->ti_maxsynch.offset > 0) 385779697Snon li->li_flags |= SCSI_LOW_SYNC; 385879697Snon 385979697Snon#ifdef SCSI_LOW_DEBUG 386079697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 386167468Snon { 386279697Snon scsi_low_calcf_show(li); 386367468Snon } 386479697Snon#endif /* SCSI_LOW_DEBUG */ 386579697Snon} 386679697Snon 386779697Snonstatic void 386879697Snonscsi_low_calcf_target(ti) 386979697Snon struct targ_info *ti; 387079697Snon{ 387179697Snon struct scsi_low_softc *slp = ti->ti_sc; 387279697Snon u_int offset, period, diskflags; 387379697Snon 387479697Snon diskflags = ti->ti_diskflags & ti->ti_quirks; 387579697Snon 387679697Snon /* synch */ 387779697Snon if ((slp->sl_cfgflags & CFG_ASYNC) == 0 && 387879697Snon (diskflags & SCSI_LOW_DISK_SYNC) != 0) 387979697Snon { 388079697Snon offset = ti->ti_maxsynch.offset; 388179697Snon period = ti->ti_maxsynch.period; 388279697Snon if (offset == 0 || period == 0) 388379697Snon offset = period = 0; 388479697Snon } 388567468Snon else 388679697Snon { 388779697Snon offset = period = 0; 388879697Snon } 388967468Snon 389079697Snon ti->ti_maxsynch.offset = offset; 389179697Snon ti->ti_maxsynch.period = period; 389279697Snon 389379697Snon /* wide */ 389479697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_32) == 0 && 389579697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 389679697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_16; 389779697Snon 389879697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_16) == 0 && 389979697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 390079697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 390179697Snon 390279697Snon if (ti->ti_flags_valid == SCSI_LOW_TARG_FLAGS_ALL_VALID) 390367468Snon { 390479697Snon if (ti->ti_maxsynch.offset != ti->ti_osynch.offset || 390579697Snon ti->ti_maxsynch.period != ti->ti_osynch.period) 390679697Snon ti->ti_setup_msg |= SCSI_LOW_MSG_SYNCH; 390779697Snon if (ti->ti_width != ti->ti_owidth) 390879697Snon ti->ti_setup_msg |= (SCSI_LOW_MSG_WIDE | SCSI_LOW_MSG_SYNCH); 390979697Snon 391079697Snon ti->ti_osynch = ti->ti_maxsynch; 391179697Snon ti->ti_owidth = ti->ti_width; 391267468Snon } 391367468Snon 391479697Snon#ifdef SCSI_LOW_DEBUG 391579697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 391679697Snon { 3917240325Sjhb device_printf(slp->sl_dev, 3918240325Sjhb "(%d:*): max period(%dns) offset(%d) width(%d)\n", 3919240325Sjhb ti->ti_id, 392079697Snon ti->ti_maxsynch.period * 4, 392179697Snon ti->ti_maxsynch.offset, 392279697Snon ti->ti_width); 392379697Snon } 392479697Snon#endif /* SCSI_LOW_DEBUG */ 392567468Snon} 392667468Snon 392779697Snonstatic void 392879697Snonscsi_low_calcf_show(li) 392979697Snon struct lun_info *li; 393079697Snon{ 393179697Snon struct targ_info *ti = li->li_ti; 393279697Snon struct scsi_low_softc *slp = ti->ti_sc; 393379697Snon 3934240325Sjhb device_printf(slp->sl_dev, 3935240325Sjhb "(%d:%d): period(%d ns) offset(%d) width(%d) flags 0x%b\n", 3936240325Sjhb ti->ti_id, li->li_lun, 393779697Snon ti->ti_maxsynch.period * 4, 393879697Snon ti->ti_maxsynch.offset, 393979697Snon ti->ti_width, 394079697Snon li->li_flags, SCSI_LOW_BITS); 394179697Snon} 394279697Snon 394379697Snon#ifdef SCSI_LOW_START_UP_CHECK 394479697Snon/************************************************************** 394579697Snon * scsi world start up 394679697Snon **************************************************************/ 394792770Salfredstatic int scsi_low_poll(struct scsi_low_softc *, struct slccb *); 394879697Snon 394967468Snonstatic int 395079697Snonscsi_low_start_up(slp) 395179697Snon struct scsi_low_softc *slp; 395267468Snon{ 395367468Snon struct targ_info *ti; 395467468Snon struct lun_info *li; 395579697Snon struct slccb *cb; 395679697Snon int target, lun; 395767468Snon 3958240325Sjhb device_printf(slp->sl_dev, "scsi_low: probing all devices ....\n"); 395967468Snon 396079697Snon for (target = 0; target < slp->sl_ntargs; target ++) 396179697Snon { 396279697Snon if (target == slp->sl_hostid) 396379697Snon { 396479697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 396579697Snon { 3966240325Sjhb device_printf(slp->sl_dev, 3967240325Sjhb "scsi_low: target %d (host card)\n", 3968240325Sjhb target); 396979697Snon } 397079697Snon continue; 397179697Snon } 397267468Snon 397379697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 397479697Snon { 3975240325Sjhb device_printf(slp->sl_dev, "scsi_low: target %d lun ", 3976240325Sjhb target); 397779697Snon } 397867468Snon 397979697Snon ti = slp->sl_ti[target]; 398079697Snon for (lun = 0; lun < slp->sl_nluns; lun ++) 398179697Snon { 398279697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 398379697Snon break; 398479697Snon 398579697Snon cb->osdep = NULL; 398679697Snon cb->bp = NULL; 398779697Snon 398879697Snon li = scsi_low_alloc_li(ti, lun, 1); 398979697Snon 399079697Snon scsi_low_enqueue(slp, ti, li, cb, 399179697Snon CCB_AUTOSENSE | CCB_POLLED, 0); 399279697Snon 399379697Snon scsi_low_poll(slp, cb); 399479697Snon 399579697Snon if (li->li_state != SCSI_LOW_LUN_OK) 399679697Snon break; 399779697Snon 399879697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 399979697Snon { 400079697Snon printf("%d ", lun); 400179697Snon } 400279697Snon } 400379697Snon 400479697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 400579697Snon { 400679697Snon printf("\n"); 400779697Snon } 400879697Snon } 400967468Snon return 0; 401067468Snon} 401167468Snon 401279697Snonstatic int 401379697Snonscsi_low_poll(slp, cb) 401479697Snon struct scsi_low_softc *slp; 401579697Snon struct slccb *cb; 401679697Snon{ 401779697Snon int tcount; 401879697Snon 401979697Snon tcount = 0; 402079697Snon while (slp->sl_nio > 0) 402179697Snon { 4022240172Sjhb DELAY((1000 * 1000) / SCSI_LOW_POLL_HZ); 402379697Snon 402479697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 402579697Snon if (tcount ++ < SCSI_LOW_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 402679697Snon continue; 402779697Snon 402879697Snon tcount = 0; 402979697Snon scsi_low_timeout_check(slp); 403079697Snon } 403179697Snon 403279697Snon return 0; 403379697Snon} 403479697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 403579697Snon 403667468Snon/********************************************************** 403767468Snon * DEBUG SECTION 403867468Snon **********************************************************/ 403979697Snon#ifdef SCSI_LOW_DEBUG 404067468Snonstatic void 404179697Snonscsi_low_test_abort(slp, ti, li) 404279697Snon struct scsi_low_softc *slp; 404379697Snon struct targ_info *ti; 404479697Snon struct lun_info *li; 404579697Snon{ 404679697Snon struct slccb *acb; 404779697Snon 404879697Snon if (li->li_disc > 1) 404979697Snon { 405079697Snon acb = TAILQ_FIRST(&li->li_discq); 405179697Snon if (scsi_low_abort_ccb(slp, acb) == 0) 405279697Snon { 4053240325Sjhb device_printf(slp->sl_dev, 4054240325Sjhb "aborting ccb(0x%lx) start\n", (u_long) acb); 405579697Snon } 405679697Snon } 405779697Snon} 405879697Snon 405979697Snonstatic void 406079697Snonscsi_low_test_atten(slp, ti, msg) 406179697Snon struct scsi_low_softc *slp; 406279697Snon struct targ_info *ti; 406379697Snon u_int msg; 406479697Snon{ 406579697Snon 406679697Snon if (slp->sl_ph_count < SCSI_LOW_MAX_ATTEN_CHECK) 406779697Snon scsi_low_assert_msg(slp, ti, msg, 0); 406879697Snon else 4069240325Sjhb device_printf(slp->sl_dev, "atten check OK\n"); 407079697Snon} 407179697Snon 407279697Snonstatic void 407379697Snonscsi_low_test_cmdlnk(slp, cb) 407479697Snon struct scsi_low_softc *slp; 407579697Snon struct slccb *cb; 407679697Snon{ 407779697Snon#define SCSI_LOW_CMDLNK_NOK (CCB_INTERNAL | CCB_SENSE | CCB_CLEARQ) 407879697Snon 407979697Snon if ((cb->ccb_flags & SCSI_LOW_CMDLNK_NOK) != 0) 408079697Snon return; 408179697Snon 408279697Snon memcpy(cb->ccb_scsi_cmd, slp->sl_scp.scp_cmd, 408379697Snon slp->sl_scp.scp_cmdlen); 408479697Snon cb->ccb_scsi_cmd[slp->sl_scp.scp_cmdlen - 1] |= 1; 408579697Snon slp->sl_scp.scp_cmd = cb->ccb_scsi_cmd; 408679697Snon} 408779697Snon#endif /* SCSI_LOW_DEBUG */ 408879697Snon 408979697Snon/* static */ void 409067468Snonscsi_low_info(slp, ti, s) 409167468Snon struct scsi_low_softc *slp; 409267468Snon struct targ_info *ti; 409367468Snon u_char *s; 409467468Snon{ 409567468Snon 409679697Snon if (slp == NULL) 409779697Snon slp = LIST_FIRST(&sl_tab); 409879697Snon if (s == NULL) 409979697Snon s = "no message"; 410079697Snon 410179697Snon printf(">>>>> SCSI_LOW_INFO(0x%lx): %s\n", (u_long) slp->sl_Tnexus, s); 410267468Snon if (ti == NULL) 410367468Snon { 4104270225Sjhb TAILQ_FOREACH(ti, &slp->sl_titab, ti_chain) 410579697Snon { 410667468Snon scsi_low_print(slp, ti); 410779697Snon } 410867468Snon } 410967468Snon else 411079697Snon { 411167468Snon scsi_low_print(slp, ti); 411279697Snon } 411367468Snon} 411467468Snon 411567468Snonstatic u_char *phase[] = 411667468Snon{ 411767468Snon "FREE", "ARBSTART", "SELSTART", "SELECTED", 411867468Snon "CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", "RESEL" 411967468Snon}; 412067468Snon 412167468Snonvoid 412267468Snonscsi_low_print(slp, ti) 412367468Snon struct scsi_low_softc *slp; 412467468Snon struct targ_info *ti; 412567468Snon{ 412679697Snon struct lun_info *li; 412779697Snon struct slccb *cb; 412879697Snon struct sc_p *sp; 412967468Snon 413079697Snon if (ti == NULL || ti == slp->sl_Tnexus) 413179697Snon { 413279697Snon ti = slp->sl_Tnexus; 413379697Snon li = slp->sl_Lnexus; 413479697Snon cb = slp->sl_Qnexus; 413579697Snon } 413679697Snon else 413779697Snon { 413879697Snon li = LIST_FIRST(&ti->ti_litab); 413979697Snon cb = TAILQ_FIRST(&li->li_discq); 414079697Snon } 414179697Snon sp = &slp->sl_scp; 414267468Snon 4143240325Sjhb device_printf(slp->sl_dev, 4144240325Sjhb "=== NEXUS T(0x%lx) L(0x%lx) Q(0x%lx) NIO(%d) ===\n", 4145240325Sjhb (u_long) ti, (u_long) li, (u_long) cb, slp->sl_nio); 414667468Snon 414767468Snon /* target stat */ 414867468Snon if (ti != NULL) 414967468Snon { 415079697Snon u_int flags = 0, maxnqio = 0, nqio = 0; 4151260509Smav int lun = CAM_LUN_WILDCARD; 415267468Snon 415367468Snon if (li != NULL) 415467468Snon { 415567468Snon lun = li->li_lun; 415667468Snon flags = li->li_flags; 415779697Snon maxnqio = li->li_maxnqio; 415879697Snon nqio = li->li_nqio; 415967468Snon } 416067468Snon 4161240325Sjhb device_printf(slp->sl_dev, 4162240325Sjhb "(%d:%d) ph<%s> => ph<%s> DISC(%d) QIO(%d:%d)\n", 416367468Snon ti->ti_id, lun, phase[(int) ti->ti_ophase], 416479697Snon phase[(int) ti->ti_phase], ti->ti_disc, 416579697Snon nqio, maxnqio); 416667468Snon 416779697Snon if (cb != NULL) 416879697Snon { 416979697Snonprintf("CCB: cmd[0] 0x%x clen 0x%x dlen 0x%x<0x%x stat 0x%x err %b\n", 417079697Snon (u_int) cb->ccb_scp.scp_cmd[0], 417179697Snon cb->ccb_scp.scp_cmdlen, 417279697Snon cb->ccb_datalen, 417379697Snon cb->ccb_scp.scp_datalen, 417479697Snon (u_int) cb->ccb_sscp.scp_status, 417579697Snon cb->ccb_error, SCSI_LOW_ERRORBITS); 417679697Snon } 417767468Snon 417879697Snonprintf("MSGIN: ptr(%x) [%x][%x][%x][%x][%x] attention: %d\n", 417979697Snon (u_int) (ti->ti_msginptr), 418079697Snon (u_int) (ti->ti_msgin[0]), 418179697Snon (u_int) (ti->ti_msgin[1]), 418279697Snon (u_int) (ti->ti_msgin[2]), 418379697Snon (u_int) (ti->ti_msgin[3]), 418479697Snon (u_int) (ti->ti_msgin[4]), 418579697Snon slp->sl_atten); 418679697Snon 418767468Snonprintf("MSGOUT: msgflags 0x%x [%x][%x][%x][%x][%x] msgoutlen %d C_FLAGS: %b\n", 418879697Snon (u_int) ti->ti_msgflags, 418979697Snon (u_int) (ti->ti_msgoutstr[0]), 419079697Snon (u_int) (ti->ti_msgoutstr[1]), 419179697Snon (u_int) (ti->ti_msgoutstr[2]), 419279697Snon (u_int) (ti->ti_msgoutstr[3]), 419379697Snon (u_int) (ti->ti_msgoutstr[4]), 419479697Snon ti->ti_msgoutlen, 419579697Snon flags, SCSI_LOW_BITS); 419667468Snon 419779697Snon#ifdef SCSI_LOW_DIAGNOSTIC 419879697Snon scsi_low_msg_log_show(&ti->ti_log_msgin, "MIN LOG ", 2); 419979697Snon scsi_low_msg_log_show(&ti->ti_log_msgout, "MOUT LOG", 2); 420079697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 420167468Snon 420267468Snon } 420379697Snon 420479697Snon printf("SCB: daddr 0x%lx dlen 0x%x stat 0x%x err %b\n", 420579697Snon (u_long) sp->scp_data, 420679697Snon sp->scp_datalen, 420779697Snon (u_int) sp->scp_status, 420879697Snon slp->sl_error, SCSI_LOW_ERRORBITS); 420967468Snon} 4210