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: releng/10.2/sys/cam/scsi/scsi_low.c 265632 2014-05-08 06:55:48Z mav $"); 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); 15379697Snon 15479697Snon/************************************************************** 15579697Snon * Debug, Run test and Statics 15679697Snon **************************************************************/ 15779697Snon#ifdef SCSI_LOW_INFO_DETAIL 15879697Snon#define SCSI_LOW_INFO(slp, ti, s) scsi_low_info((slp), (ti), (s)) 15979697Snon#else /* !SCSI_LOW_INFO_DETAIL */ 160240325Sjhb#define SCSI_LOW_INFO(slp, ti, s) device_printf((slp)->sl_dev, "%s\n", (s)) 16179697Snon#endif /* !SCSI_LOW_INFO_DETAIL */ 16279697Snon 16367468Snon#ifdef SCSI_LOW_STATICS 16489113Smsmithstatic struct scsi_low_statics { 16567468Snon int nexus_win; 16667468Snon int nexus_fail; 16767468Snon int nexus_disconnected; 16867468Snon int nexus_reselected; 16967468Snon int nexus_conflict; 17067468Snon} scsi_low_statics; 17167468Snon#endif /* SCSI_LOW_STATICS */ 17279697Snon 17379697Snon#ifdef SCSI_LOW_DEBUG 17479697Snon#define SCSI_LOW_DEBUG_DONE 0x00001 17579697Snon#define SCSI_LOW_DEBUG_DISC 0x00002 17679697Snon#define SCSI_LOW_DEBUG_SENSE 0x00004 17779697Snon#define SCSI_LOW_DEBUG_CALCF 0x00008 17879697Snon#define SCSI_LOW_DEBUG_ACTION 0x10000 17979697Snonint scsi_low_debug = 0; 18079697Snon 18179697Snon#define SCSI_LOW_MAX_ATTEN_CHECK 32 18279697Snon#define SCSI_LOW_ATTEN_CHECK 0x0001 18379697Snon#define SCSI_LOW_CMDLNK_CHECK 0x0002 18479697Snon#define SCSI_LOW_ABORT_CHECK 0x0004 18579697Snon#define SCSI_LOW_NEXUS_CHECK 0x0008 18679697Snonint scsi_low_test = 0; 18779697Snonint scsi_low_test_id = 0; 18879697Snon 18992770Salfredstatic void scsi_low_test_abort(struct scsi_low_softc *, struct targ_info *, struct lun_info *); 19092770Salfredstatic void scsi_low_test_cmdlnk(struct scsi_low_softc *, struct slccb *); 19192770Salfredstatic void scsi_low_test_atten(struct scsi_low_softc *, struct targ_info *, u_int); 19279697Snon#define SCSI_LOW_DEBUG_TEST_GO(fl, id) \ 19379697Snon ((scsi_low_test & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 19479697Snon#define SCSI_LOW_DEBUG_GO(fl, id) \ 19579697Snon ((scsi_low_debug & (fl)) != 0 && (scsi_low_test_id & (1 << (id))) == 0) 19679697Snon#endif /* SCSI_LOW_DEBUG */ 19779697Snon 19867468Snon/************************************************************** 19979697Snon * CCB 20079697Snon **************************************************************/ 20179697SnonGENERIC_CCB_STATIC_ALLOC(scsi_low, slccb) 20279697SnonGENERIC_CCB(scsi_low, slccb, ccb_chain) 20379697Snon 20479697Snon/************************************************************** 20579697Snon * Inline functions 20679697Snon **************************************************************/ 20779697Snon#define SCSI_LOW_INLINE static __inline 20892770SalfredSCSI_LOW_INLINE void scsi_low_activate_qtag(struct slccb *); 20992770SalfredSCSI_LOW_INLINE void scsi_low_deactivate_qtag(struct slccb *); 21092770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_assert(struct slccb *, u_int); 21192770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_exec(struct scsi_low_softc *, struct slccb *); 21292770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_retry(struct slccb *); 21392770SalfredSCSI_LOW_INLINE void scsi_low_ccb_message_clear(struct slccb *); 21492770SalfredSCSI_LOW_INLINE void scsi_low_init_msgsys(struct scsi_low_softc *, struct targ_info *); 21579697Snon 21679697SnonSCSI_LOW_INLINE void 21779697Snonscsi_low_activate_qtag(cb) 21879697Snon struct slccb *cb; 21979697Snon{ 22079697Snon struct lun_info *li = cb->li; 22179697Snon 22279697Snon if (cb->ccb_tag != SCSI_LOW_UNKTAG) 22379697Snon return; 22479697Snon 22579697Snon li->li_nqio ++; 22679697Snon cb->ccb_tag = cb->ccb_otag; 22779697Snon} 22879697Snon 22979697SnonSCSI_LOW_INLINE void 23079697Snonscsi_low_deactivate_qtag(cb) 23179697Snon struct slccb *cb; 23279697Snon{ 23379697Snon struct lun_info *li = cb->li; 23479697Snon 23579697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 23679697Snon return; 23779697Snon 23879697Snon li->li_nqio --; 23979697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 24079697Snon} 24179697Snon 24279697SnonSCSI_LOW_INLINE void 24379697Snonscsi_low_ccb_message_exec(slp, cb) 24479697Snon struct scsi_low_softc *slp; 24579697Snon struct slccb *cb; 24679697Snon{ 24779697Snon 24879697Snon scsi_low_assert_msg(slp, cb->ti, cb->ccb_msgoutflag, 0); 24979697Snon cb->ccb_msgoutflag = 0; 25079697Snon} 25179697Snon 25279697SnonSCSI_LOW_INLINE void 25379697Snonscsi_low_ccb_message_assert(cb, msg) 25479697Snon struct slccb *cb; 25579697Snon u_int msg; 25679697Snon{ 25779697Snon 25879697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag = msg; 25979697Snon} 26079697Snon 26179697SnonSCSI_LOW_INLINE void 26279697Snonscsi_low_ccb_message_retry(cb) 26379697Snon struct slccb *cb; 26479697Snon{ 26579697Snon cb->ccb_msgoutflag = cb->ccb_omsgoutflag; 26679697Snon} 26779697Snon 26879697SnonSCSI_LOW_INLINE void 26979697Snonscsi_low_ccb_message_clear(cb) 27079697Snon struct slccb *cb; 27179697Snon{ 27279697Snon cb->ccb_msgoutflag = 0; 27379697Snon} 27479697Snon 27579697SnonSCSI_LOW_INLINE void 27679697Snonscsi_low_init_msgsys(slp, ti) 27779697Snon struct scsi_low_softc *slp; 27879697Snon struct targ_info *ti; 27979697Snon{ 28079697Snon 28179697Snon ti->ti_msginptr = 0; 28279697Snon ti->ti_emsgflags = ti->ti_msgflags = ti->ti_omsgflags = 0; 28379697Snon SCSI_LOW_DEASSERT_ATN(slp); 28479697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_NULL); 28579697Snon} 28679697Snon 28779697Snon/*============================================================= 28879697Snon * START OF OS switch (All OS depend fucntions should be here) 28979697Snon =============================================================*/ 29079697Snon/* common os depend utitlities */ 29179697Snon#define SCSI_LOW_CMD_RESIDUAL_CHK 0x0001 29279697Snon#define SCSI_LOW_CMD_ORDERED_QTAG 0x0002 29379697Snon#define SCSI_LOW_CMD_ABORT_WARNING 0x0004 29479697Snon 29579697Snonstatic u_int8_t scsi_low_cmd_flags[256] = { 29679697Snon/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */ 29779697Snon/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 0, 0, 29879697Snon/*1*/ 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 29979697Snon/*2*/ 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 5, 0, 0, 0, 5, 5, 30079697Snon/*3*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 5, 30179697Snon}; 30279697Snon 30379697Snonstruct scsi_low_error_code { 30479697Snon int error_bits; 30579697Snon int error_code; 30679697Snon}; 30779697Snon 30892770Salfredstatic struct slccb *scsi_low_find_ccb(struct scsi_low_softc *, u_int, u_int, void *); 30992770Salfredstatic int scsi_low_translate_error_code(struct slccb *, struct scsi_low_error_code *); 31079697Snon 31179697Snonstatic struct slccb * 31279697Snonscsi_low_find_ccb(slp, target, lun, osdep) 31379697Snon struct scsi_low_softc *slp; 31479697Snon u_int target, lun; 31579697Snon void *osdep; 31679697Snon{ 31779697Snon struct targ_info *ti; 31879697Snon struct lun_info *li; 31979697Snon struct slccb *cb; 32079697Snon 32179697Snon ti = slp->sl_ti[target]; 32279697Snon li = scsi_low_alloc_li(ti, lun, 0); 32379697Snon if (li == NULL) 32479697Snon return NULL; 32579697Snon 32679697Snon if ((cb = slp->sl_Qnexus) != NULL && cb->osdep == osdep) 32779697Snon return cb; 32879697Snon 32979697Snon for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL; 33079697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 33179697Snon { 33279697Snon if (cb->osdep == osdep) 33379697Snon return cb; 33479697Snon } 33579697Snon 33679697Snon for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; 33779697Snon cb = TAILQ_NEXT(cb, 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 *); 37092770Salfredstatic int scsi_low_world_start_cam(struct scsi_low_softc *); 37192770Salfredstatic int scsi_low_dettach_cam(struct scsi_low_softc *); 37292770Salfredstatic int scsi_low_ccb_setup_cam(struct scsi_low_softc *, struct slccb *); 37392770Salfredstatic int scsi_low_done_cam(struct scsi_low_softc *, struct slccb *); 37492770Salfredstatic void scsi_low_timeout_cam(struct scsi_low_softc *, int, int); 37579697Snon 37679697Snonstruct scsi_low_osdep_funcs scsi_low_osdep_funcs_cam = { 37779697Snon scsi_low_attach_cam, 37879697Snon scsi_low_world_start_cam, 37979697Snon scsi_low_dettach_cam, 38079697Snon scsi_low_ccb_setup_cam, 38179697Snon scsi_low_done_cam, 38279697Snon scsi_low_timeout_cam 38379697Snon}; 38479697Snon 38579697Snonstruct scsi_low_error_code scsi_low_error_code_cam[] = { 38679697Snon {0, CAM_REQ_CMP}, 38779697Snon {SENSEIO, CAM_AUTOSNS_VALID | CAM_REQ_CMP_ERR}, 38879697Snon {SENSEERR, CAM_AUTOSENSE_FAIL}, 38979697Snon {UACAERR, CAM_SCSI_STATUS_ERROR}, 39079697Snon {BUSYERR | STATERR, CAM_SCSI_STATUS_ERROR}, 39179697Snon {SELTIMEOUTIO, CAM_SEL_TIMEOUT}, 39279697Snon {TIMEOUTIO, CAM_CMD_TIMEOUT}, 39379697Snon {PDMAERR, CAM_DATA_RUN_ERR}, 39479697Snon {PARITYERR, CAM_UNCOR_PARITY}, 39579697Snon {UBFERR, CAM_UNEXP_BUSFREE}, 39679697Snon {ABORTIO, CAM_REQ_ABORTED}, 39779697Snon {-1, CAM_UNREC_HBA_ERROR} 39879697Snon}; 39979697Snon 40079697Snon#define SIM2SLP(sim) ((struct scsi_low_softc *) cam_sim_softc((sim))) 40179697Snon 40279697Snon/* XXX: 40379697Snon * Please check a polling hz, currently we assume scsi_low_poll() is 40479697Snon * called each 1 ms. 40579697Snon */ 40679697Snon#define SCSI_LOW_CAM_POLL_HZ 1000 /* OK ? */ 40779697Snon 40879697Snonstatic void 40979697Snonscsi_low_poll_cam(sim) 41079697Snon struct cam_sim *sim; 41179697Snon{ 41279697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 41379697Snon 41479697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 41579697Snon 41679697Snon if (slp->sl_si.si_poll_count ++ >= 41779697Snon SCSI_LOW_CAM_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 41879697Snon { 41979697Snon slp->sl_si.si_poll_count = 0; 42079697Snon scsi_low_timeout_check(slp); 42179697Snon } 42279697Snon} 42379697Snon 42479697Snonvoid 42579697Snonscsi_low_scsi_action_cam(sim, ccb) 42679697Snon struct cam_sim *sim; 42779697Snon union ccb *ccb; 42879697Snon{ 42979697Snon struct scsi_low_softc *slp = SIM2SLP(sim); 43079697Snon struct targ_info *ti; 43179697Snon struct lun_info *li; 43279697Snon struct slccb *cb; 43379697Snon u_int lun, flags, msg, target; 43479697Snon int s, rv; 43579697Snon 43679697Snon target = (u_int) (ccb->ccb_h.target_id); 43779697Snon lun = (u_int) ccb->ccb_h.target_lun; 43879697Snon 43979697Snon#ifdef SCSI_LOW_DEBUG 44079697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_ACTION, target) != 0) 44179697Snon { 442240325Sjhb device_printf(slp->sl_dev, 443240325Sjhb "cam_action: func code 0x%x target: %d, lun: %d\n", 444240325Sjhb ccb->ccb_h.func_code, target, lun); 44579697Snon } 44679697Snon#endif /* SCSI_LOW_DEBUG */ 44779697Snon 44879697Snon switch (ccb->ccb_h.func_code) { 44979697Snon case XPT_SCSI_IO: /* Execute the requested I/O operation */ 45079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 45179697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 45279697Snon { 453240325Sjhb device_printf(slp->sl_dev, "invalid target/lun\n"); 45479697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 45579697Snon xpt_done(ccb); 45679697Snon return; 45779697Snon } 45879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 45979697Snon 46079697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) { 46179697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 46279697Snon xpt_done(ccb); 46379697Snon return; 46479697Snon } 46579697Snon 46679697Snon ti = slp->sl_ti[target]; 46779697Snon cb->osdep = ccb; 46879697Snon cb->bp = NULL; 46979697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 47079697Snon flags = CCB_AUTOSENSE | CCB_SCSIIO; 47179697Snon else 47279697Snon flags = CCB_SCSIIO; 47379697Snon 474240172Sjhb s = splcam(); 47579697Snon li = scsi_low_alloc_li(ti, lun, 1); 47679697Snon 47779697Snon if (ti->ti_setup_msg != 0) 47879697Snon { 47979697Snon scsi_low_message_enqueue(slp, ti, li, CCB_AUTOSENSE); 48079697Snon } 48179697Snon 48279697Snon scsi_low_enqueue(slp, ti, li, cb, flags, 0); 48379697Snon 48479697Snon#ifdef SCSI_LOW_DEBUG 48579697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ABORT_CHECK, target) != 0) 48679697Snon { 48779697Snon scsi_low_test_abort(slp, ti, li); 48879697Snon } 48979697Snon#endif /* SCSI_LOW_DEBUG */ 49079697Snon splx(s); 49179697Snon break; 49279697Snon 49379697Snon case XPT_EN_LUN: /* Enable LUN as a target */ 49479697Snon case XPT_TARGET_IO: /* Execute target I/O request */ 49579697Snon case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 49679697Snon case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 49779697Snon /* XXX Implement */ 49879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 49979697Snon xpt_done(ccb); 50079697Snon break; 50179697Snon 50279697Snon case XPT_ABORT: /* Abort the specified CCB */ 50379697Snon#ifdef SCSI_LOW_DIAGNOSTIC 50479697Snon if (target == CAM_TARGET_WILDCARD || lun == CAM_LUN_WILDCARD) 50579697Snon { 506240325Sjhb device_printf(slp->sl_dev, "invalid target/lun\n"); 50779697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 50879697Snon xpt_done(ccb); 50979697Snon return; 51079697Snon } 51179697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 51279697Snon 513240172Sjhb s = splcam(); 51479697Snon cb = scsi_low_find_ccb(slp, target, lun, ccb->cab.abort_ccb); 51579697Snon rv = scsi_low_abort_ccb(slp, cb); 51679697Snon splx(s); 51779697Snon 51879697Snon if (rv == 0) 51979697Snon ccb->ccb_h.status = CAM_REQ_CMP; 52079697Snon else 52179697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 52279697Snon xpt_done(ccb); 52379697Snon break; 52479697Snon 52579697Snon case XPT_SET_TRAN_SETTINGS: { 526163816Smjacob struct ccb_trans_settings_scsi *scsi; 527163816Smjacob struct ccb_trans_settings_spi *spi; 52879697Snon struct ccb_trans_settings *cts; 52979697Snon u_int val; 53079697Snon 53179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 53279697Snon if (target == CAM_TARGET_WILDCARD) 53379697Snon { 534240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 53579697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 53679697Snon xpt_done(ccb); 53779697Snon return; 53879697Snon } 53979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 54079697Snon cts = &ccb->cts; 54179697Snon ti = slp->sl_ti[target]; 54279697Snon if (lun == CAM_LUN_WILDCARD) 54379697Snon lun = 0; 54479697Snon 545240172Sjhb s = splcam(); 546163816Smjacob scsi = &cts->proto_specific.scsi; 547163816Smjacob spi = &cts->xport_specific.spi; 548163816Smjacob if ((spi->valid & (CTS_SPI_VALID_BUS_WIDTH | 549163816Smjacob CTS_SPI_VALID_SYNC_RATE | 550163816Smjacob CTS_SPI_VALID_SYNC_OFFSET)) != 0) 551163816Smjacob { 552163816Smjacob if (spi->valid & CTS_SPI_VALID_BUS_WIDTH) { 553163816Smjacob val = spi->bus_width; 554163816Smjacob if (val < ti->ti_width) 555163816Smjacob ti->ti_width = val; 556163816Smjacob } 557163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_RATE) { 558163816Smjacob val = spi->sync_period; 559163816Smjacob if (val == 0 || val > ti->ti_maxsynch.period) 560163816Smjacob ti->ti_maxsynch.period = val; 561163816Smjacob } 562163816Smjacob if (spi->valid & CTS_SPI_VALID_SYNC_OFFSET) { 563163816Smjacob val = spi->sync_offset; 564163816Smjacob if (val < ti->ti_maxsynch.offset) 565163816Smjacob ti->ti_maxsynch.offset = val; 566163816Smjacob } 567163816Smjacob ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 568163816Smjacob scsi_low_calcf_target(ti); 569163816Smjacob } 570163816Smjacob 571163816Smjacob if ((spi->valid & CTS_SPI_FLAGS_DISC_ENB) != 0 || 572163816Smjacob (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0) { 573163816Smjacob 574163816Smjacob li = scsi_low_alloc_li(ti, lun, 1); 575163816Smjacob if (spi->valid & CTS_SPI_FLAGS_DISC_ENB) { 576163816Smjacob li->li_quirks |= SCSI_LOW_DISK_DISC; 577163816Smjacob } else { 578163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_DISC; 579163816Smjacob } 580163816Smjacob 581163816Smjacob if (scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) { 582163816Smjacob li->li_quirks |= SCSI_LOW_DISK_QTAG; 583163816Smjacob } else { 584163816Smjacob li->li_quirks &= ~SCSI_LOW_DISK_QTAG; 585163816Smjacob } 586163816Smjacob li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 587163816Smjacob scsi_low_calcf_target(ti); 588163816Smjacob scsi_low_calcf_lun(li); 589163816Smjacob if ((slp->sl_show_result & SHOW_CALCF_RES) != 0) 590163816Smjacob scsi_low_calcf_show(li); 591163816Smjacob } 59279697Snon splx(s); 59379697Snon 59479697Snon ccb->ccb_h.status = CAM_REQ_CMP; 59579697Snon xpt_done(ccb); 59679697Snon break; 59779697Snon } 59879697Snon 59979697Snon case XPT_GET_TRAN_SETTINGS: { 60079697Snon struct ccb_trans_settings *cts; 60179697Snon u_int diskflags; 60279697Snon 60379697Snon cts = &ccb->cts; 60479697Snon#ifdef SCSI_LOW_DIAGNOSTIC 60579697Snon if (target == CAM_TARGET_WILDCARD) 60679697Snon { 607240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 60879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 60979697Snon xpt_done(ccb); 61079697Snon return; 61179697Snon } 61279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 61379697Snon ti = slp->sl_ti[target]; 61479697Snon if (lun == CAM_LUN_WILDCARD) 61579697Snon lun = 0; 61679697Snon 617240172Sjhb s = splcam(); 61879697Snon li = scsi_low_alloc_li(ti, lun, 1); 61979697Snon if (li != NULL && cts->type == CTS_TYPE_CURRENT_SETTINGS) { 62079697Snon struct ccb_trans_settings_scsi *scsi = 62179697Snon &cts->proto_specific.scsi; 62279697Snon struct ccb_trans_settings_spi *spi = 62379697Snon &cts->xport_specific.spi; 62479697Snon#ifdef SCSI_LOW_DIAGNOSTIC 62579697Snon if (li->li_flags_valid != SCSI_LOW_LUN_FLAGS_ALL_VALID) 62679697Snon { 62779697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 628240325Sjhb device_printf(slp->sl_dev, 629240325Sjhb "invalid GET_TRANS_CURRENT_SETTINGS call\n"); 63079697Snon goto settings_out; 63179697Snon } 63279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 63379697Snon cts->protocol = PROTO_SCSI; 63479697Snon cts->protocol_version = SCSI_REV_2; 63579697Snon cts->transport = XPORT_SPI; 63679697Snon cts->transport_version = 2; 63779697Snon 63879697Snon scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; 63979697Snon spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; 64079697Snon 64179697Snon diskflags = li->li_diskflags & li->li_cfgflags; 64279697Snon if (diskflags & SCSI_LOW_DISK_DISC) 64379697Snon spi->flags |= CTS_SPI_FLAGS_DISC_ENB; 64479697Snon if (diskflags & SCSI_LOW_DISK_QTAG) 64579697Snon scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; 64679697Snon 64779697Snon spi->sync_period = ti->ti_maxsynch.period; 64879697Snon spi->valid |= CTS_SPI_VALID_SYNC_RATE; 64979697Snon spi->sync_offset = ti->ti_maxsynch.offset; 65079697Snon spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; 65179697Snon 65279697Snon spi->valid |= CTS_SPI_VALID_BUS_WIDTH; 65379697Snon spi->bus_width = ti->ti_width; 65479697Snon 65579697Snon if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { 65679697Snon scsi->valid = CTS_SCSI_VALID_TQ; 65779697Snon spi->valid |= CTS_SPI_VALID_DISC; 65879697Snon } else 65979697Snon scsi->valid = 0; 66079697Snon } else 66179697Snon ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 66279697Snonsettings_out: 66379697Snon splx(s); 66479697Snon xpt_done(ccb); 66579697Snon break; 66679697Snon } 66779697Snon 66879697Snon case XPT_CALC_GEOMETRY: { /* not yet HN2 */ 669116351Snjl cam_calc_geometry(&ccb->ccg, /*extended*/1); 67079697Snon xpt_done(ccb); 67179697Snon break; 67279697Snon } 67379697Snon 67479697Snon case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 675240172Sjhb s = splcam(); 67679697Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL); 67779697Snon splx(s); 67879697Snon ccb->ccb_h.status = CAM_REQ_CMP; 67979697Snon xpt_done(ccb); 68079697Snon break; 68179697Snon 68279697Snon case XPT_TERM_IO: /* Terminate the I/O process */ 68379697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 68479697Snon xpt_done(ccb); 68579697Snon break; 68679697Snon 68779697Snon case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 68879697Snon#ifdef SCSI_LOW_DIAGNOSTIC 68979697Snon if (target == CAM_TARGET_WILDCARD) 69079697Snon { 691240325Sjhb device_printf(slp->sl_dev, "invalid target\n"); 69279697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 69379697Snon xpt_done(ccb); 69479697Snon return; 69579697Snon } 69679697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 69779697Snon 69879697Snon msg = SCSI_LOW_MSG_RESET; 69979697Snon if (((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL)) 70079697Snon { 70179697Snon ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 70279697Snon xpt_done(ccb); 70379697Snon return; 70479697Snon } 70579697Snon 70679697Snon ti = slp->sl_ti[target]; 70779697Snon if (lun == CAM_LUN_WILDCARD) 70879697Snon lun = 0; 70979697Snon cb->osdep = ccb; 71079697Snon cb->bp = NULL; 71179697Snon if ((ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) 71279697Snon flags = CCB_AUTOSENSE | CCB_NORETRY | CCB_URGENT; 71379697Snon else 71479697Snon flags = CCB_NORETRY | CCB_URGENT; 71579697Snon 716240172Sjhb s = splcam(); 71779697Snon li = scsi_low_alloc_li(ti, lun, 1); 71879697Snon scsi_low_enqueue(slp, ti, li, cb, flags, msg); 71979697Snon splx(s); 72079697Snon break; 72179697Snon 72279697Snon case XPT_PATH_INQ: { /* Path routing inquiry */ 72379697Snon struct ccb_pathinq *cpi = &ccb->cpi; 72479697Snon 72579697Snon cpi->version_num = scsi_low_version_major; 72679697Snon cpi->hba_inquiry = PI_TAG_ABLE | PI_LINKED_CDB; 72779697Snon ti = slp->sl_ti[slp->sl_hostid]; /* host id */ 72879697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 72979697Snon cpi->hba_inquiry |= PI_WIDE_16; 73079697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 73179697Snon cpi->hba_inquiry |= PI_WIDE_32; 73279697Snon if (ti->ti_maxsynch.offset > 0) 73379697Snon cpi->hba_inquiry |= PI_SDTR_ABLE; 73479697Snon cpi->target_sprt = 0; 73579697Snon cpi->hba_misc = 0; 73679697Snon cpi->hba_eng_cnt = 0; 73779697Snon cpi->max_target = slp->sl_ntargs - 1; 73879697Snon cpi->max_lun = slp->sl_nluns - 1; 73979697Snon cpi->initiator_id = slp->sl_hostid; 74079697Snon cpi->bus_id = cam_sim_bus(sim); 74179697Snon cpi->base_transfer_speed = 3300; 74279697Snon cpi->transport = XPORT_SPI; 74379697Snon cpi->transport_version = 2; 74479697Snon cpi->protocol = PROTO_SCSI; 74579697Snon cpi->protocol_version = SCSI_REV_2; 74679697Snon strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 74779697Snon strncpy(cpi->hba_vid, "SCSI_LOW", HBA_IDLEN); 74879697Snon strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 74979697Snon cpi->unit_number = cam_sim_unit(sim); 75079697Snon cpi->ccb_h.status = CAM_REQ_CMP; 75179697Snon xpt_done(ccb); 75279697Snon break; 75379697Snon } 75479697Snon 75579697Snon default: 75679697Snon printf("scsi_low: non support func_code = %d ", 75779697Snon ccb->ccb_h.func_code); 75879697Snon ccb->ccb_h.status = CAM_REQ_INVALID; 75979697Snon xpt_done(ccb); 76079697Snon break; 76179697Snon } 76279697Snon} 76379697Snon 76479697Snonstatic int 76579697Snonscsi_low_attach_cam(slp) 76679697Snon struct scsi_low_softc *slp; 76779697Snon{ 76879697Snon struct cam_devq *devq; 76979697Snon int tagged_openings; 77079697Snon 77179697Snon devq = cam_simq_alloc(SCSI_LOW_NCCB); 77279697Snon if (devq == NULL) 77379697Snon return (ENOMEM); 77479697Snon 77579697Snon /* 77679697Snon * ask the adapter what subunits are present 77779697Snon */ 77879697Snon tagged_openings = min(slp->sl_openings, SCSI_LOW_MAXNEXUS); 77979697Snon slp->sl_si.sim = cam_sim_alloc(scsi_low_scsi_action_cam, 78079697Snon scsi_low_poll_cam, 781240172Sjhb device_get_name(slp->sl_dev), slp, 782240172Sjhb device_get_unit(slp->sl_dev), &Giant, 78379697Snon slp->sl_openings, tagged_openings, devq); 78479697Snon 78579697Snon if (slp->sl_si.sim == NULL) { 78679697Snon cam_simq_free(devq); 78779697Snon return ENODEV; 78879697Snon } 78979697Snon 790170872Sscottl if (xpt_bus_register(slp->sl_si.sim, NULL, 0) != CAM_SUCCESS) { 791147723Savatar free(slp->sl_si.sim, M_SCSILOW); 79279697Snon return ENODEV; 79379697Snon } 79479697Snon 79579697Snon if (xpt_create_path(&slp->sl_si.path, /*periph*/NULL, 79679697Snon cam_sim_path(slp->sl_si.sim), CAM_TARGET_WILDCARD, 79779697Snon CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 79879697Snon xpt_bus_deregister(cam_sim_path(slp->sl_si.sim)); 79979697Snon cam_sim_free(slp->sl_si.sim, /*free_simq*/TRUE); 80079697Snon return ENODEV; 80179697Snon } 80279697Snon 80379697Snon slp->sl_show_result = SHOW_CALCF_RES; /* OK ? */ 80479697Snon return 0; 80579697Snon} 80679697Snon 80779697Snonstatic int 80879697Snonscsi_low_world_start_cam(slp) 80979697Snon struct scsi_low_softc *slp; 81079697Snon{ 81179697Snon 81279697Snon return 0; 81379697Snon} 81479697Snon 81579697Snonstatic int 81679697Snonscsi_low_dettach_cam(slp) 81779697Snon struct scsi_low_softc *slp; 81879697Snon{ 81979697Snon 82079697Snon xpt_async(AC_LOST_DEVICE, slp->sl_si.path, NULL); 82179697Snon xpt_free_path(slp->sl_si.path); 82279697Snon xpt_bus_deregister(cam_sim_path(slp->sl_si.sim)); 82379697Snon cam_sim_free(slp->sl_si.sim, /* free_devq */ TRUE); 82479697Snon return 0; 82579697Snon} 82679697Snon 82779697Snonstatic int 82879697Snonscsi_low_ccb_setup_cam(slp, cb) 82979697Snon struct scsi_low_softc *slp; 83079697Snon struct slccb *cb; 83179697Snon{ 83279697Snon union ccb *ccb = (union ccb *) cb->osdep; 83379697Snon 83479697Snon if ((cb->ccb_flags & CCB_SCSIIO) != 0) 83579697Snon { 83679697Snon cb->ccb_scp.scp_cmd = ccb->csio.cdb_io.cdb_bytes; 83779697Snon cb->ccb_scp.scp_cmdlen = (int) ccb->csio.cdb_len; 83879697Snon cb->ccb_scp.scp_data = ccb->csio.data_ptr; 83979697Snon cb->ccb_scp.scp_datalen = (int) ccb->csio.dxfer_len; 84079697Snon if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) 84179697Snon cb->ccb_scp.scp_direction = SCSI_LOW_WRITE; 84279697Snon else /* if((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) */ 84379697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 84479697Snon cb->ccb_tcmax = ccb->ccb_h.timeout / 1000; 84579697Snon } 84679697Snon else 84779697Snon { 84879697Snon scsi_low_unit_ready_cmd(cb); 84979697Snon } 85079697Snon return SCSI_LOW_START_QTAG; 85179697Snon} 85279697Snon 85379697Snonstatic int 85479697Snonscsi_low_done_cam(slp, cb) 85579697Snon struct scsi_low_softc *slp; 85679697Snon struct slccb *cb; 85779697Snon{ 85879697Snon union ccb *ccb; 85979697Snon 86079697Snon ccb = (union ccb *) cb->osdep; 86179697Snon if (cb->ccb_error == 0) 86279697Snon { 86379697Snon ccb->ccb_h.status = CAM_REQ_CMP; 86479697Snon ccb->csio.resid = 0; 86579697Snon } 86679697Snon else 86779697Snon { 86879697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 86979697Snon cb->ccb_error |= ABORTIO; 87079697Snon 87179697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 87279697Snon (cb->ccb_error & ABORTIO) == 0) 87379697Snon return EJUSTRETURN; 87479697Snon 87579697Snon if ((cb->ccb_error & SENSEIO) != 0) 87679697Snon { 87779697Snon memcpy(&ccb->csio.sense_data, 87879697Snon &cb->ccb_sense, 87979697Snon sizeof(ccb->csio.sense_data)); 88079697Snon } 88179697Snon 88279697Snon ccb->ccb_h.status = scsi_low_translate_error_code(cb, 88379697Snon &scsi_low_error_code_cam[0]); 88479697Snon 88579697Snon#ifdef SCSI_LOW_DIAGNOSTIC 88679697Snon if ((cb->ccb_flags & CCB_SILENT) == 0 && 88779697Snon cb->ccb_scp.scp_cmdlen > 0 && 88879697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 88979697Snon SCSI_LOW_CMD_ABORT_WARNING) != 0) 89079697Snon { 891240325Sjhb device_printf(slp->sl_dev, 892240325Sjhb "WARNING: scsi_low IO abort\n"); 89379697Snon scsi_low_print(slp, NULL); 89479697Snon } 89579697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 89679697Snon } 89779697Snon 89879697Snon if ((ccb->ccb_h.status & CAM_STATUS_MASK) == 0) 89979697Snon ccb->ccb_h.status |= CAM_REQ_CMP_ERR; 90079697Snon 90179697Snon if (cb->ccb_scp.scp_status == ST_UNKNOWN) 90279697Snon ccb->csio.scsi_status = 0; /* XXX */ 90379697Snon else 90479697Snon ccb->csio.scsi_status = cb->ccb_scp.scp_status; 90579697Snon 90679697Snon if ((cb->ccb_flags & CCB_NOSDONE) == 0) 90779697Snon xpt_done(ccb); 90879697Snon return 0; 90979697Snon} 91079697Snon 91179697Snonstatic void 91279697Snonscsi_low_timeout_cam(slp, ch, action) 91379697Snon struct scsi_low_softc *slp; 91479697Snon int ch; 91579697Snon int action; 91679697Snon{ 91779697Snon 91879697Snon switch (ch) 91979697Snon { 92079697Snon case SCSI_LOW_TIMEOUT_CH_IO: 92179697Snon switch (action) 92279697Snon { 92379697Snon case SCSI_LOW_TIMEOUT_START: 92479697Snon slp->sl_si.timeout_ch = timeout(scsi_low_timeout, slp, 92579697Snon hz / SCSI_LOW_TIMEOUT_HZ); 92679697Snon break; 92779697Snon case SCSI_LOW_TIMEOUT_STOP: 92879697Snon untimeout(scsi_low_timeout, slp, slp->sl_si.timeout_ch); 92979697Snon break; 93079697Snon } 93179697Snon break; 93279697Snon 93379697Snon case SCSI_LOW_TIMEOUT_CH_ENGAGE: 93479697Snon switch (action) 93579697Snon { 93679697Snon case SCSI_LOW_TIMEOUT_START: 93779697Snon slp->sl_si.engage_ch = timeout(scsi_low_engage, slp, 1); 93879697Snon break; 93979697Snon case SCSI_LOW_TIMEOUT_STOP: 94079697Snon untimeout(scsi_low_engage, slp, slp->sl_si.engage_ch); 94179697Snon break; 94279697Snon } 94379697Snon break; 94479697Snon case SCSI_LOW_TIMEOUT_CH_RECOVER: 94579697Snon break; 94679697Snon } 94779697Snon} 94879697Snon 94979697Snon/*============================================================= 95079697Snon * END OF OS switch (All OS depend fucntions should be above) 95179697Snon =============================================================*/ 95279697Snon 95379697Snon/************************************************************** 95479697Snon * scsi low deactivate and activate 95579697Snon **************************************************************/ 95679697Snonint 95779697Snonscsi_low_is_busy(slp) 95879697Snon struct scsi_low_softc *slp; 95979697Snon{ 96079697Snon 96179697Snon if (slp->sl_nio > 0) 96279697Snon return EBUSY; 96379697Snon return 0; 96479697Snon} 96579697Snon 96679697Snonint 96779697Snonscsi_low_deactivate(slp) 96879697Snon struct scsi_low_softc *slp; 96979697Snon{ 97079697Snon int s; 97179697Snon 972240172Sjhb s = splcam(); 97379697Snon slp->sl_flags |= HW_INACTIVE; 97479697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 97579697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_STOP); 97679697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 97779697Snon (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP); 97879697Snon splx(s); 97979697Snon return 0; 98079697Snon} 98179697Snon 98279697Snonint 98379697Snonscsi_low_activate(slp) 98479697Snon struct scsi_low_softc *slp; 98579697Snon{ 98679697Snon int error, s; 98779697Snon 988240172Sjhb s = splcam(); 98979697Snon slp->sl_flags &= ~HW_INACTIVE; 99079697Snon if ((error = scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, NULL)) != 0) 99179697Snon { 99279697Snon slp->sl_flags |= HW_INACTIVE; 99379697Snon splx(s); 99479697Snon return error; 99579697Snon } 99679697Snon 99779697Snon slp->sl_timeout_count = 0; 99879697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 99979697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 100079697Snon splx(s); 100179697Snon return 0; 100279697Snon} 100379697Snon 100479697Snon/************************************************************** 100579697Snon * scsi low log 100679697Snon **************************************************************/ 100779697Snon#ifdef SCSI_LOW_DIAGNOSTIC 100892770Salfredstatic void scsi_low_msg_log_init(struct scsi_low_msg_log *); 100992770Salfredstatic void scsi_low_msg_log_write(struct scsi_low_msg_log *, u_int8_t *, int); 101092770Salfredstatic void scsi_low_msg_log_show(struct scsi_low_msg_log *, char *, int); 101179697Snon 101279697Snonstatic void 101379697Snonscsi_low_msg_log_init(slmlp) 101479697Snon struct scsi_low_msg_log *slmlp; 101579697Snon{ 101679697Snon 101779697Snon slmlp->slml_ptr = 0; 101879697Snon} 101979697Snon 102079697Snonstatic void 102179697Snonscsi_low_msg_log_write(slmlp, datap, len) 102279697Snon struct scsi_low_msg_log *slmlp; 102379697Snon u_int8_t *datap; 102479697Snon int len; 102579697Snon{ 102679697Snon int ptr, ind; 102779697Snon 102879697Snon if (slmlp->slml_ptr >= SCSI_LOW_MSG_LOG_DATALEN) 102979697Snon return; 103079697Snon 103179697Snon ptr = slmlp->slml_ptr ++; 103279697Snon for (ind = 0; ind < sizeof(slmlp->slml_msg[0]) && ind < len; ind ++) 103379697Snon slmlp->slml_msg[ptr].msg[ind] = datap[ind]; 103479697Snon for ( ; ind < sizeof(slmlp->slml_msg[0]); ind ++) 103579697Snon slmlp->slml_msg[ptr].msg[ind] = 0; 103679697Snon} 103779697Snon 103879697Snonstatic void 103979697Snonscsi_low_msg_log_show(slmlp, s, len) 104079697Snon struct scsi_low_msg_log *slmlp; 104179697Snon char *s; 104279697Snon int len; 104379697Snon{ 104479697Snon int ptr, ind; 104579697Snon 104679697Snon printf("%s: (%d) ", s, slmlp->slml_ptr); 104779697Snon for (ptr = 0; ptr < slmlp->slml_ptr; ptr ++) 104879697Snon { 104979697Snon for (ind = 0; ind < len && ind < sizeof(slmlp->slml_msg[0]); 105079697Snon ind ++) 105179697Snon { 105279697Snon printf("[%x]", (u_int) slmlp->slml_msg[ptr].msg[ind]); 105379697Snon } 105479697Snon printf(">"); 105579697Snon } 105679697Snon printf("\n"); 105779697Snon} 105879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 105979697Snon 106079697Snon/************************************************************** 106167468Snon * power control 106267468Snon **************************************************************/ 106367468Snonstatic void 106467468Snonscsi_low_engage(arg) 106567468Snon void *arg; 106667468Snon{ 106767468Snon struct scsi_low_softc *slp = arg; 1068240172Sjhb int s = splcam(); 106967468Snon 107067468Snon switch (slp->sl_rstep) 107167468Snon { 107267468Snon case 0: 107367468Snon slp->sl_rstep ++; 107467468Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 107579697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp, 107679697Snon SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_START); 107767468Snon break; 107867468Snon 107967468Snon case 1: 108067468Snon slp->sl_rstep ++; 108167468Snon slp->sl_flags &= ~HW_RESUME; 108267468Snon scsi_low_start(slp); 108367468Snon break; 108467468Snon 108567468Snon case 2: 108667468Snon break; 108767468Snon } 108867468Snon splx(s); 108967468Snon} 109067468Snon 109167468Snonstatic int 109267468Snonscsi_low_init(slp, flags) 109367468Snon struct scsi_low_softc *slp; 109467468Snon u_int flags; 109567468Snon{ 109679697Snon int rv = 0; 109767468Snon 109879697Snon slp->sl_flags |= HW_INITIALIZING; 109979697Snon 110079697Snon /* clear power control timeout */ 110167468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 110267468Snon { 110379697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) (slp, 110479697Snon SCSI_LOW_TIMEOUT_CH_ENGAGE, SCSI_LOW_TIMEOUT_STOP); 110567468Snon slp->sl_flags &= ~(HW_POWDOWN | HW_RESUME); 110667468Snon slp->sl_active = 1; 110767468Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 110867468Snon } 110967468Snon 111067468Snon /* reset current nexus */ 111167468Snon scsi_low_reset_nexus(slp, flags); 111267468Snon if ((slp->sl_flags & HW_INACTIVE) != 0) 111379697Snon { 111479697Snon rv = EBUSY; 111579697Snon goto out; 111679697Snon } 111767468Snon 111879697Snon if (flags != SCSI_LOW_RESTART_SOFT) 111979697Snon { 112079697Snon rv = ((*slp->sl_funcs->scsi_low_init) (slp, flags)); 112179697Snon } 112267468Snon 112379697Snonout: 112479697Snon slp->sl_flags &= ~HW_INITIALIZING; 112579697Snon return rv; 112667468Snon} 112767468Snon 112867468Snon/************************************************************** 112967468Snon * allocate lun_info 113067468Snon **************************************************************/ 113167468Snonstatic struct lun_info * 113267468Snonscsi_low_alloc_li(ti, lun, alloc) 113367468Snon struct targ_info *ti; 113467468Snon int lun; 113567468Snon int alloc; 113667468Snon{ 113779697Snon struct scsi_low_softc *slp = ti->ti_sc; 113867468Snon struct lun_info *li; 113967468Snon 114067468Snon li = LIST_FIRST(&ti->ti_litab); 114167468Snon if (li != NULL) 114267468Snon { 114367468Snon if (li->li_lun == lun) 114467468Snon return li; 114567468Snon 114667468Snon while ((li = LIST_NEXT(li, lun_chain)) != NULL) 114767468Snon { 114867468Snon if (li->li_lun == lun) 114967468Snon { 115067468Snon LIST_REMOVE(li, lun_chain); 115167468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 115267468Snon return li; 115367468Snon } 115467468Snon } 115567468Snon } 115667468Snon 115767468Snon if (alloc == 0) 115867468Snon return li; 115967468Snon 116079697Snon li = SCSI_LOW_MALLOC(ti->ti_lunsize); 116167468Snon if (li == NULL) 1162106890Simp panic("no lun info mem"); 116367468Snon 1164240172Sjhb bzero(li, ti->ti_lunsize); 116567468Snon li->li_lun = lun; 116667468Snon li->li_ti = ti; 116767468Snon 116879697Snon li->li_cfgflags = SCSI_LOW_SYNC | SCSI_LOW_LINK | SCSI_LOW_DISC | 116979697Snon SCSI_LOW_QTAG; 117079697Snon li->li_quirks = li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 117179697Snon li->li_flags_valid = SCSI_LOW_LUN_FLAGS_USER_VALID; 117279697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 117379697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_QUIRKS_VALID; 117479697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 117579697Snon 117679697Snon li->li_qtagbits = (u_int) -1; 117779697Snon 117879697Snon TAILQ_INIT(&li->li_discq); 117967468Snon LIST_INSERT_HEAD(&ti->ti_litab, li, lun_chain); 118067468Snon 118179697Snon /* host specific structure initialization per lun */ 118279697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 118379697Snon (*slp->sl_funcs->scsi_low_lun_init) 118479697Snon (slp, ti, li, SCSI_LOW_INFO_ALLOC); 118579697Snon scsi_low_calcf_lun(li); 118667468Snon return li; 118767468Snon} 118867468Snon 118967468Snon/************************************************************** 119067468Snon * allocate targ_info 119167468Snon **************************************************************/ 119267468Snonstatic struct targ_info * 119379697Snonscsi_low_alloc_ti(slp, targ) 119467468Snon struct scsi_low_softc *slp; 119579697Snon int targ; 119667468Snon{ 119767468Snon struct targ_info *ti; 119867468Snon 119971999Sphk if (TAILQ_FIRST(&slp->sl_titab) == NULL) 120067468Snon TAILQ_INIT(&slp->sl_titab); 120167468Snon 120279697Snon ti = SCSI_LOW_MALLOC(slp->sl_targsize); 120367468Snon if (ti == NULL) 1204240325Sjhb panic("%s short of memory", device_get_nameunit(slp->sl_dev)); 120567468Snon 1206240172Sjhb bzero(ti, slp->sl_targsize); 120767468Snon ti->ti_id = targ; 120867468Snon ti->ti_sc = slp; 120967468Snon 121067468Snon slp->sl_ti[targ] = ti; 121167468Snon TAILQ_INSERT_TAIL(&slp->sl_titab, ti, ti_chain); 121267468Snon LIST_INIT(&ti->ti_litab); 121367468Snon 121479697Snon ti->ti_quirks = ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 121579697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 121679697Snon ti->ti_flags_valid = SCSI_LOW_TARG_FLAGS_USER_VALID; 121779697Snon#ifdef SCSI_LOW_FLAGS_QUIRKS_OK 121879697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_QUIRKS_VALID; 121979697Snon#endif /* SCSI_LOW_FLAGS_QUIRKS_OK */ 122073025Snon 122179697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 122279697Snon { 122379697Snon (*slp->sl_funcs->scsi_low_targ_init) 122479697Snon (slp, ti, SCSI_LOW_INFO_ALLOC); 122579697Snon } 122679697Snon scsi_low_calcf_target(ti); 122767468Snon return ti; 122867468Snon} 122967468Snon 123067468Snonstatic void 123167468Snonscsi_low_free_ti(slp) 123267468Snon struct scsi_low_softc *slp; 123367468Snon{ 123467468Snon struct targ_info *ti, *tib; 123567468Snon struct lun_info *li, *nli; 123667468Snon 123771999Sphk for (ti = TAILQ_FIRST(&slp->sl_titab); ti; ti = tib) 123867468Snon { 123967468Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; li = nli) 124067468Snon { 124179697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 124279697Snon { 124379697Snon (*slp->sl_funcs->scsi_low_lun_init) 124479697Snon (slp, ti, li, SCSI_LOW_INFO_DEALLOC); 124579697Snon } 124667468Snon nli = LIST_NEXT(li, lun_chain); 124779697Snon SCSI_LOW_FREE(li); 124867468Snon } 124979697Snon 125079697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 125179697Snon { 125279697Snon (*slp->sl_funcs->scsi_low_targ_init) 125379697Snon (slp, ti, SCSI_LOW_INFO_DEALLOC); 125479697Snon } 125579697Snon tib = TAILQ_NEXT(ti, ti_chain); 125679697Snon SCSI_LOW_FREE(ti); 125767468Snon } 125867468Snon} 125967468Snon 126067468Snon/************************************************************** 126167468Snon * timeout 126267468Snon **************************************************************/ 126367468Snonvoid 126479697Snonscsi_low_bus_idle(slp) 126579697Snon struct scsi_low_softc *slp; 126679697Snon{ 126779697Snon 126879697Snon slp->sl_retry_sel = 0; 126979697Snon if (slp->sl_Tnexus == NULL) 127079697Snon scsi_low_start(slp); 127179697Snon} 127279697Snon 127379697Snonstatic void 127467468Snonscsi_low_timeout(arg) 127567468Snon void *arg; 127667468Snon{ 127767468Snon struct scsi_low_softc *slp = arg; 127879697Snon int s; 127979697Snon 1280240172Sjhb s = splcam(); 128179697Snon (void) scsi_low_timeout_check(slp); 128279697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 128379697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 128479697Snon splx(s); 128579697Snon} 128679697Snon 128779697Snonstatic int 128879697Snonscsi_low_timeout_check(slp) 128979697Snon struct scsi_low_softc *slp; 129079697Snon{ 129167468Snon struct targ_info *ti; 129279697Snon struct lun_info *li; 129367468Snon struct slccb *cb = NULL; /* XXX */ 129467468Snon 129579697Snon /* selection restart */ 129679697Snon if (slp->sl_retry_sel != 0) 129767468Snon { 129879697Snon slp->sl_retry_sel = 0; 129979697Snon if (slp->sl_Tnexus != NULL) 130079697Snon goto step1; 130167468Snon 130279697Snon cb = TAILQ_FIRST(&slp->sl_start); 130379697Snon if (cb == NULL) 130479697Snon goto step1; 130579697Snon 130679697Snon if (cb->ccb_selrcnt >= SCSI_LOW_MAX_SELECTION_RETRY) 130767468Snon { 130879697Snon cb->ccb_flags |= CCB_NORETRY; 130979697Snon cb->ccb_error |= SELTIMEOUTIO; 131079697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1311240325Sjhb panic("%s: ccb not finished", 1312240325Sjhb device_get_nameunit(slp->sl_dev)); 131367468Snon } 131479697Snon 131579697Snon if (slp->sl_Tnexus == NULL) 131679697Snon scsi_low_start(slp); 131767468Snon } 131879697Snon 131979697Snon /* call hardware timeout */ 132079697Snonstep1: 132179697Snon if (slp->sl_funcs->scsi_low_timeout != NULL) 132267468Snon { 132379697Snon (*slp->sl_funcs->scsi_low_timeout) (slp); 132479697Snon } 132579697Snon 132679697Snon if (slp->sl_timeout_count ++ < 132779697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL * SCSI_LOW_TIMEOUT_HZ) 132879697Snon return 0; 132979697Snon 133079697Snon slp->sl_timeout_count = 0; 133179697Snon if (slp->sl_nio > 0) 133279697Snon { 133379697Snon if ((cb = slp->sl_Qnexus) != NULL) 133467468Snon { 133567468Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 133667468Snon if (cb->ccb_tc < 0) 133767468Snon goto bus_reset; 133867468Snon } 133979697Snon else if (slp->sl_disc == 0) 134067468Snon { 134179697Snon if ((cb = TAILQ_FIRST(&slp->sl_start)) == NULL) 134279697Snon return 0; 134367468Snon 134479697Snon cb->ccb_tc -= SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 134579697Snon if (cb->ccb_tc < 0) 134679697Snon goto bus_reset; 134779697Snon } 134879697Snon else for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 134979697Snon ti = TAILQ_NEXT(ti, ti_chain)) 135079697Snon { 135179697Snon if (ti->ti_disc == 0) 135279697Snon continue; 135367468Snon 135479697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 135579697Snon li = LIST_NEXT(li, lun_chain)) 135667468Snon { 135779697Snon for (cb = TAILQ_FIRST(&li->li_discq); 135879697Snon cb != NULL; 135979697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 136079697Snon { 136179697Snon cb->ccb_tc -= 136279697Snon SCSI_LOW_TIMEOUT_CHECK_INTERVAL; 136379697Snon if (cb->ccb_tc < 0) 136479697Snon goto bus_reset; 136579697Snon } 136667468Snon } 136767468Snon } 136879697Snon 136967468Snon } 137079697Snon else if ((slp->sl_flags & HW_POWERCTRL) != 0) 137179697Snon { 137279697Snon if ((slp->sl_flags & (HW_POWDOWN | HW_RESUME)) != 0) 137379697Snon return 0; 137467468Snon 137579697Snon if (slp->sl_active != 0) 137679697Snon { 137779697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 137879697Snon slp->sl_active = 0; 137979697Snon return 0; 138079697Snon } 138167468Snon 138279697Snon slp->sl_powc --; 138379697Snon if (slp->sl_powc < 0) 138479697Snon { 138579697Snon slp->sl_powc = SCSI_LOW_POWDOWN_TC; 138679697Snon slp->sl_flags |= HW_POWDOWN; 138779697Snon (*slp->sl_funcs->scsi_low_power) 138879697Snon (slp, SCSI_LOW_POWDOWN); 138979697Snon } 139079697Snon } 139179697Snon return 0; 139267468Snon 139367468Snonbus_reset: 139467468Snon cb->ccb_error |= TIMEOUTIO; 1395240325Sjhb device_printf(slp->sl_dev, "slccb (0x%lx) timeout!\n", (u_long) cb); 139667468Snon scsi_low_info(slp, NULL, "scsi bus hangup. try to recover."); 139767468Snon scsi_low_init(slp, SCSI_LOW_RESTART_HARD); 139867468Snon scsi_low_start(slp); 139979697Snon return ERESTART; 140067468Snon} 140167468Snon 140267468Snon 140379697Snonstatic int 140479697Snonscsi_low_abort_ccb(slp, cb) 140579697Snon struct scsi_low_softc *slp; 140679697Snon struct slccb *cb; 140779697Snon{ 140879697Snon struct targ_info *ti; 140979697Snon struct lun_info *li; 141079697Snon u_int msg; 141167468Snon 141279697Snon if (cb == NULL) 141379697Snon return EINVAL; 141479697Snon if ((cb->ccb_omsgoutflag & 141579697Snon (SCSI_LOW_MSG_ABORT | SCSI_LOW_MSG_ABORT_QTAG)) != 0) 141679697Snon return EBUSY; 141767468Snon 141879697Snon ti = cb->ti; 141979697Snon li = cb->li; 142079697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 142179697Snon msg = SCSI_LOW_MSG_ABORT; 142279697Snon else 142379697Snon msg = SCSI_LOW_MSG_ABORT_QTAG; 142467468Snon 142579697Snon cb->ccb_error |= ABORTIO; 142679697Snon cb->ccb_flags |= CCB_NORETRY; 142779697Snon scsi_low_ccb_message_assert(cb, msg); 142867468Snon 142979697Snon if (cb == slp->sl_Qnexus) 143079697Snon { 143179697Snon scsi_low_assert_msg(slp, ti, msg, 1); 143279697Snon } 143379697Snon else if ((cb->ccb_flags & CCB_DISCQ) != 0) 143479697Snon { 143579697Snon if (scsi_low_revoke_ccb(slp, cb, 0) == NULL) 1436240325Sjhb panic("%s: revoked ccb done", 1437240325Sjhb device_get_nameunit(slp->sl_dev)); 143867468Snon 143979697Snon cb->ccb_flags |= CCB_STARTQ; 144079697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 144167468Snon 144279697Snon if (slp->sl_Tnexus == NULL) 144379697Snon scsi_low_start(slp); 144479697Snon } 144579697Snon else 144679697Snon { 144779697Snon if (scsi_low_revoke_ccb(slp, cb, 1) != NULL) 1448240325Sjhb panic("%s: revoked ccb retried", 1449240325Sjhb device_get_nameunit(slp->sl_dev)); 145079697Snon } 145179697Snon return 0; 145267468Snon} 145367468Snon 145479697Snon/************************************************************** 145579697Snon * Generic SCSI INTERFACE 145679697Snon **************************************************************/ 145767468Snonint 145879697Snonscsi_low_attach(slp, openings, ntargs, nluns, targsize, lunsize) 145967468Snon struct scsi_low_softc *slp; 146079697Snon int openings, ntargs, nluns, targsize, lunsize; 146167468Snon{ 146267468Snon struct targ_info *ti; 146367468Snon struct lun_info *li; 146479697Snon int s, i, nccb, rv; 146567468Snon 146679697Snon slp->sl_osdep_fp = &scsi_low_osdep_funcs_cam; 146779697Snon 146879697Snon if (slp->sl_osdep_fp == NULL) 1469106890Simp panic("scsi_low: interface not spcified"); 147079697Snon 147167468Snon if (ntargs > SCSI_LOW_NTARGETS) 147267468Snon { 147367468Snon printf("scsi_low: %d targets are too large\n", ntargs); 147467468Snon printf("change kernel options SCSI_LOW_NTARGETS"); 147579697Snon return EINVAL; 147667468Snon } 147767468Snon 147879697Snon if (openings <= 0) 147979697Snon slp->sl_openings = (SCSI_LOW_NCCB / ntargs); 148079697Snon else 148179697Snon slp->sl_openings = openings; 148279697Snon slp->sl_ntargs = ntargs; 148379697Snon slp->sl_nluns = nluns; 148479697Snon slp->sl_max_retry = SCSI_LOW_MAX_RETRY; 148567468Snon 148679697Snon if (lunsize < sizeof(struct lun_info)) 148779697Snon lunsize = sizeof(struct lun_info); 148879697Snon 148979697Snon if (targsize < sizeof(struct targ_info)) 149079697Snon targsize = sizeof(struct targ_info); 149179697Snon 149279697Snon slp->sl_targsize = targsize; 149367468Snon for (i = 0; i < ntargs; i ++) 149467468Snon { 149579697Snon ti = scsi_low_alloc_ti(slp, i); 149679697Snon ti->ti_lunsize = lunsize; 149767468Snon li = scsi_low_alloc_li(ti, 0, 1); 149867468Snon } 149967468Snon 150067468Snon /* initialize queue */ 150179697Snon nccb = openings * ntargs; 150267468Snon if (nccb >= SCSI_LOW_NCCB || nccb <= 0) 150367468Snon nccb = SCSI_LOW_NCCB; 150467468Snon scsi_low_init_ccbque(nccb); 150567468Snon TAILQ_INIT(&slp->sl_start); 150667468Snon 150779697Snon /* call os depend attach */ 1508240172Sjhb s = splcam(); 150979697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_attach) (slp); 151079697Snon if (rv != 0) 151179697Snon { 151279697Snon splx(s); 1513240325Sjhb device_printf(slp->sl_dev, 1514240325Sjhb "scsi_low_attach: osdep attach failed\n"); 151579697Snon return EINVAL; 151679697Snon } 151767468Snon 151879697Snon /* check hardware */ 1519240172Sjhb DELAY(1000); /* wait for 1ms */ 152079697Snon if (scsi_low_init(slp, SCSI_LOW_RESTART_HARD) != 0) 152179697Snon { 152279697Snon splx(s); 1523240325Sjhb device_printf(slp->sl_dev, 1524240325Sjhb "scsi_low_attach: initialization failed\n"); 152579697Snon return EINVAL; 152679697Snon } 152767468Snon 152867468Snon /* start watch dog */ 152979697Snon slp->sl_timeout_count = 0; 153079697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 153179697Snon (slp, SCSI_LOW_TIMEOUT_CH_IO, SCSI_LOW_TIMEOUT_START); 153279697Snon LIST_INSERT_HEAD(&sl_tab, slp, sl_chain); 153367468Snon 153479697Snon /* fake call */ 153579697Snon scsi_low_abort_ccb(slp, scsi_low_find_ccb(slp, 0, 0, NULL)); 153667468Snon 153779697Snon#ifdef SCSI_LOW_START_UP_CHECK 153879697Snon /* probing devices */ 153979697Snon scsi_low_start_up(slp); 154079697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 154167468Snon 154279697Snon /* call os depend attach done*/ 154379697Snon (*slp->sl_osdep_fp->scsi_low_osdep_world_start) (slp); 154479697Snon splx(s); 154579697Snon return 0; 154667468Snon} 154767468Snon 154867468Snonint 154967468Snonscsi_low_dettach(slp) 155067468Snon struct scsi_low_softc *slp; 155167468Snon{ 155279697Snon int s, rv; 155367468Snon 1554240172Sjhb s = splcam(); 155579697Snon if (scsi_low_is_busy(slp) != 0) 155679697Snon { 155779697Snon splx(s); 155867468Snon return EBUSY; 155979697Snon } 156067468Snon 156179697Snon scsi_low_deactivate(slp); 156267468Snon 156379697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_dettach) (slp); 156479697Snon if (rv != 0) 156579697Snon { 156679697Snon splx(s); 156779697Snon return EBUSY; 156879697Snon } 156967468Snon 157067468Snon scsi_low_free_ti(slp); 157179697Snon LIST_REMOVE(slp, sl_chain); 157279697Snon splx(s); 157367468Snon return 0; 157467468Snon} 157567468Snon 157679697Snon/************************************************************** 157779697Snon * Generic enqueue 157879697Snon **************************************************************/ 157979697Snonstatic int 158079697Snonscsi_low_enqueue(slp, ti, li, cb, flags, msg) 158179697Snon struct scsi_low_softc *slp; 158267468Snon struct targ_info *ti; 158367468Snon struct lun_info *li; 158467468Snon struct slccb *cb; 158579697Snon u_int flags, msg; 158679697Snon{ 158767468Snon 158879697Snon cb->ti = ti; 158979697Snon cb->li = li; 159067468Snon 159179697Snon scsi_low_ccb_message_assert(cb, msg); 159267468Snon 159379697Snon cb->ccb_otag = cb->ccb_tag = SCSI_LOW_UNKTAG; 159479697Snon scsi_low_alloc_qtag(cb); 159567468Snon 159679697Snon cb->ccb_flags = flags | CCB_STARTQ; 159779697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 159879697Snon cb->ccb_error |= PENDINGIO; 159979697Snon 160079697Snon if ((flags & CCB_URGENT) != 0) 160179697Snon { 160279697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 160379697Snon } 160479697Snon else 160579697Snon { 160667468Snon TAILQ_INSERT_TAIL(&slp->sl_start, cb, ccb_chain); 160779697Snon } 160867468Snon 160979697Snon slp->sl_nio ++; 161067468Snon 161179697Snon if (slp->sl_Tnexus == NULL) 161279697Snon scsi_low_start(slp); 161379697Snon return 0; 161479697Snon} 161567468Snon 161679697Snonstatic int 161779697Snonscsi_low_message_enqueue(slp, ti, li, flags) 161879697Snon struct scsi_low_softc *slp; 161979697Snon struct targ_info *ti; 162079697Snon struct lun_info *li; 162179697Snon u_int flags; 162279697Snon{ 162379697Snon struct slccb *cb; 162479697Snon u_int tmsgflags; 162567468Snon 162679697Snon tmsgflags = ti->ti_setup_msg; 162779697Snon ti->ti_setup_msg = 0; 162867468Snon 162979697Snon flags |= CCB_NORETRY; 163079697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 163179697Snon return ENOMEM; 163267468Snon 163379697Snon cb->osdep = NULL; 163479697Snon cb->bp = NULL; 163579697Snon scsi_low_enqueue(slp, ti, li, cb, flags, tmsgflags); 163679697Snon return 0; 163779697Snon} 163867468Snon 163979697Snon/************************************************************** 164079697Snon * Generic Start & Done 164179697Snon **************************************************************/ 164279697Snon#define SLSC_MODE_SENSE_SHORT 0x1a 164379697Snonstatic u_int8_t ss_cmd[6] = {START_STOP, 0, 0, 0, SSS_START, 0}; 164479697Snonstatic u_int8_t sms_cmd[6] = {SLSC_MODE_SENSE_SHORT, 0x08, 0x0a, 0, 164579697Snon sizeof(struct scsi_low_mode_sense_data), 0}; 164679697Snonstatic u_int8_t inq_cmd[6] = {INQUIRY, 0, 0, 0, 164779697Snon sizeof(struct scsi_low_inq_data), 0}; 164879697Snonstatic u_int8_t unit_ready_cmd[6]; 164992770Salfredstatic int scsi_low_setup_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 165092770Salfredstatic int scsi_low_sense_abort_start(struct scsi_low_softc *, struct targ_info *, struct lun_info *, struct slccb *); 165192770Salfredstatic int scsi_low_resume(struct scsi_low_softc *); 165279697Snon 165379697Snonstatic void 165479697Snonscsi_low_unit_ready_cmd(cb) 165579697Snon struct slccb *cb; 165679697Snon{ 165779697Snon 165879697Snon cb->ccb_scp.scp_cmd = unit_ready_cmd; 165979697Snon cb->ccb_scp.scp_cmdlen = sizeof(unit_ready_cmd); 166079697Snon cb->ccb_scp.scp_datalen = 0; 166179697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 166279697Snon cb->ccb_tcmax = 15; 166367468Snon} 166479697Snon 166567468Snonstatic int 166679697Snonscsi_low_sense_abort_start(slp, ti, li, cb) 166779697Snon struct scsi_low_softc *slp; 166867468Snon struct targ_info *ti; 166979697Snon struct lun_info *li; 167067468Snon struct slccb *cb; 167179697Snon{ 167267468Snon 167379697Snon cb->ccb_scp.scp_cmdlen = 6; 1674240172Sjhb bzero(cb->ccb_scsi_cmd, cb->ccb_scp.scp_cmdlen); 167579697Snon cb->ccb_scsi_cmd[0] = REQUEST_SENSE; 167679697Snon cb->ccb_scsi_cmd[4] = sizeof(cb->ccb_sense); 167779697Snon cb->ccb_scp.scp_cmd = cb->ccb_scsi_cmd; 167879697Snon cb->ccb_scp.scp_data = (u_int8_t *) &cb->ccb_sense; 167979697Snon cb->ccb_scp.scp_datalen = sizeof(cb->ccb_sense); 168079697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 168179697Snon cb->ccb_tcmax = 15; 168279697Snon scsi_low_ccb_message_clear(cb); 168379697Snon if ((cb->ccb_flags & CCB_CLEARQ) != 0) 168467468Snon { 168579697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 168667468Snon } 168779697Snon else 168879697Snon { 1689240172Sjhb bzero(&cb->ccb_sense, sizeof(cb->ccb_sense)); 169079697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 169179697Snon scsi_low_assert_msg(slp, ti, ti->ti_setup_msg_done, 0); 169279697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 169379697Snon } 169467468Snon 169579697Snon return SCSI_LOW_START_NO_QTAG; 169679697Snon} 169767468Snon 169879697Snonstatic int 169979697Snonscsi_low_setup_start(slp, ti, li, cb) 170079697Snon struct scsi_low_softc *slp; 170179697Snon struct targ_info *ti; 170279697Snon struct lun_info *li; 170379697Snon struct slccb *cb; 170479697Snon{ 170567468Snon 170679697Snon switch(li->li_state) 170779697Snon { 170879697Snon case SCSI_LOW_LUN_SLEEP: 170979697Snon scsi_low_unit_ready_cmd(cb); 171079697Snon break; 171167468Snon 171279697Snon case SCSI_LOW_LUN_START: 171379697Snon cb->ccb_scp.scp_cmd = ss_cmd; 171479697Snon cb->ccb_scp.scp_cmdlen = sizeof(ss_cmd); 171579697Snon cb->ccb_scp.scp_datalen = 0; 171679697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 171779697Snon cb->ccb_tcmax = 30; 171879697Snon break; 171967468Snon 172079697Snon case SCSI_LOW_LUN_INQ: 172179697Snon cb->ccb_scp.scp_cmd = inq_cmd; 172279697Snon cb->ccb_scp.scp_cmdlen = sizeof(inq_cmd); 172379697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_inq; 172479697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_inq); 172579697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 172679697Snon cb->ccb_tcmax = 15; 172779697Snon break; 172867468Snon 172979697Snon case SCSI_LOW_LUN_MODEQ: 173079697Snon cb->ccb_scp.scp_cmd = sms_cmd; 173179697Snon cb->ccb_scp.scp_cmdlen = sizeof(sms_cmd); 173279697Snon cb->ccb_scp.scp_data = (u_int8_t *)&li->li_sms; 173379697Snon cb->ccb_scp.scp_datalen = sizeof(li->li_sms); 173479697Snon cb->ccb_scp.scp_direction = SCSI_LOW_READ; 173579697Snon cb->ccb_tcmax = 15; 173679697Snon return SCSI_LOW_START_QTAG; 173767468Snon 173879697Snon default: 1739240325Sjhb panic("%s: no setup phase", device_get_nameunit(slp->sl_dev)); 174067468Snon } 174167468Snon 174279697Snon return SCSI_LOW_START_NO_QTAG; 174367468Snon} 174467468Snon 174579697Snonstatic int 174679697Snonscsi_low_resume(slp) 174779697Snon struct scsi_low_softc *slp; 174867468Snon{ 174967468Snon 175079697Snon if (slp->sl_flags & HW_RESUME) 175179697Snon return EJUSTRETURN; 175279697Snon slp->sl_flags &= ~HW_POWDOWN; 175379697Snon if (slp->sl_funcs->scsi_low_power != NULL) 175479697Snon { 175579697Snon slp->sl_flags |= HW_RESUME; 175679697Snon slp->sl_rstep = 0; 175779697Snon (*slp->sl_funcs->scsi_low_power) (slp, SCSI_LOW_ENGAGE); 175879697Snon (*slp->sl_osdep_fp->scsi_low_osdep_timeout) 175979697Snon (slp, SCSI_LOW_TIMEOUT_CH_ENGAGE, 176079697Snon SCSI_LOW_TIMEOUT_START); 176179697Snon return EJUSTRETURN; 176279697Snon } 176379697Snon return 0; 176467468Snon} 176567468Snon 176667468Snonstatic void 176767468Snonscsi_low_start(slp) 176867468Snon struct scsi_low_softc *slp; 176967468Snon{ 177067468Snon struct targ_info *ti; 177167468Snon struct lun_info *li; 177267468Snon struct slccb *cb; 177367468Snon int rv; 177467468Snon 177579697Snon /* check hardware exists or under initializations ? */ 177679697Snon if ((slp->sl_flags & (HW_INACTIVE | HW_INITIALIZING)) != 0) 177767468Snon return; 177867468Snon 177967468Snon /* check hardware power up ? */ 178067468Snon if ((slp->sl_flags & HW_POWERCTRL) != 0) 178167468Snon { 178267468Snon slp->sl_active ++; 178367468Snon if (slp->sl_flags & (HW_POWDOWN | HW_RESUME)) 178467468Snon { 178579697Snon if (scsi_low_resume(slp) == EJUSTRETURN) 178667468Snon return; 178767468Snon } 178867468Snon } 178967468Snon 179067468Snon /* setup nexus */ 179167468Snon#ifdef SCSI_LOW_DIAGNOSTIC 179279697Snon if (slp->sl_Tnexus || slp->sl_Lnexus || slp->sl_Qnexus) 179367468Snon { 179467468Snon scsi_low_info(slp, NULL, "NEXUS INCOSISTENT"); 1795240325Sjhb panic("%s: inconsistent", device_get_nameunit(slp->sl_dev)); 179667468Snon } 179767468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 179867468Snon 179979697Snon for (cb = TAILQ_FIRST(&slp->sl_start); cb != NULL; 180079697Snon cb = TAILQ_NEXT(cb, ccb_chain)) 180167468Snon { 180267468Snon li = cb->li; 180379697Snon 180479697Snon if (li->li_disc == 0) 180579697Snon { 180667468Snon goto scsi_low_cmd_start; 180779697Snon } 180879697Snon else if (li->li_nqio > 0) 180979697Snon { 181079697Snon if (li->li_nqio < li->li_maxnqio || 181179697Snon (cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 181279697Snon goto scsi_low_cmd_start; 181379697Snon } 181467468Snon } 181567468Snon return; 181667468Snon 181767468Snonscsi_low_cmd_start: 181879697Snon cb->ccb_flags &= ~CCB_STARTQ; 181979697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 182079697Snon ti = cb->ti; 182167468Snon 182267468Snon /* clear all error flag bits (for restart) */ 182367468Snon cb->ccb_error = 0; 182479697Snon cb->ccb_datalen = -1; 182579697Snon cb->ccb_scp.scp_status = ST_UNKNOWN; 182667468Snon 182767468Snon /* setup nexus pointer */ 182879697Snon slp->sl_Qnexus = cb; 182979697Snon slp->sl_Lnexus = li; 183079697Snon slp->sl_Tnexus = ti; 183167468Snon 183267468Snon /* initialize msgsys */ 183367468Snon scsi_low_init_msgsys(slp, ti); 183467468Snon 183579697Snon /* exec cmd */ 183679697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 183767468Snon { 183879697Snon /* CA state or forced abort */ 183979697Snon rv = scsi_low_sense_abort_start(slp, ti, li, cb); 184067468Snon } 184179697Snon else if (li->li_state >= SCSI_LOW_LUN_OK) 184267468Snon { 184379697Snon cb->ccb_flags &= ~CCB_INTERNAL; 184479697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, cb); 184579697Snon if (cb->ccb_msgoutflag != 0) 184679697Snon { 184779697Snon scsi_low_ccb_message_exec(slp, cb); 184879697Snon } 184967468Snon } 185079697Snon else 185167468Snon { 185279697Snon cb->ccb_flags |= CCB_INTERNAL; 185379697Snon rv = scsi_low_setup_start(slp, ti, li, cb); 185479697Snon } 185567468Snon 185679697Snon /* allocate qtag */ 185779697Snon#define SCSI_LOW_QTAG_OK (SCSI_LOW_QTAG | SCSI_LOW_DISC) 185867468Snon 185979697Snon if (rv == SCSI_LOW_START_QTAG && 186079697Snon (li->li_flags & SCSI_LOW_QTAG_OK) == SCSI_LOW_QTAG_OK && 186179697Snon li->li_maxnqio > 0) 186279697Snon { 186379697Snon u_int qmsg; 186467468Snon 186579697Snon scsi_low_activate_qtag(cb); 186679697Snon if ((scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 186779697Snon SCSI_LOW_CMD_ORDERED_QTAG) != 0) 186879697Snon qmsg = SCSI_LOW_MSG_ORDERED_QTAG; 186979697Snon else if ((cb->ccb_flags & CCB_URGENT) != 0) 187079697Snon qmsg = SCSI_LOW_MSG_HEAD_QTAG; 187179697Snon else 187279697Snon qmsg = SCSI_LOW_MSG_SIMPLE_QTAG; 187379697Snon scsi_low_assert_msg(slp, ti, qmsg, 0); 187467468Snon } 187567468Snon 187667468Snon /* timeout */ 187767468Snon if (cb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 187867468Snon cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 187967468Snon cb->ccb_tc = cb->ccb_tcmax; 188067468Snon 188167468Snon /* setup saved scsi data pointer */ 188267468Snon cb->ccb_sscp = cb->ccb_scp; 188367468Snon 188467468Snon /* setup current scsi pointer */ 188567468Snon slp->sl_scp = cb->ccb_sscp; 188667468Snon slp->sl_error = cb->ccb_error; 188767468Snon 188879697Snon /* assert always an identify msg */ 188979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); 189079697Snon 189179697Snon /* debug section */ 189279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 189379697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 189479697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 189579697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 189679697Snon 189767468Snon /* selection start */ 189879697Snon slp->sl_selid = cb; 189967468Snon rv = ((*slp->sl_funcs->scsi_low_start_bus) (slp, cb)); 190067468Snon if (rv == SCSI_LOW_START_OK) 190167468Snon { 190267468Snon#ifdef SCSI_LOW_STATICS 190367468Snon scsi_low_statics.nexus_win ++; 190467468Snon#endif /* SCSI_LOW_STATICS */ 190567468Snon return; 190667468Snon } 190767468Snon 190879697Snon scsi_low_arbit_fail(slp, cb); 190967468Snon#ifdef SCSI_LOW_STATICS 191067468Snon scsi_low_statics.nexus_fail ++; 191167468Snon#endif /* SCSI_LOW_STATICS */ 191267468Snon} 191367468Snon 191467468Snonvoid 191579697Snonscsi_low_arbit_fail(slp, cb) 191667468Snon struct scsi_low_softc *slp; 191779697Snon struct slccb *cb; 191879697Snon{ 191979697Snon struct targ_info *ti = cb->ti; 192079697Snon 192179697Snon scsi_low_deactivate_qtag(cb); 192279697Snon scsi_low_ccb_message_retry(cb); 192379697Snon cb->ccb_flags |= CCB_STARTQ; 192479697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 192579697Snon 192679697Snon scsi_low_bus_release(slp, ti); 192779697Snon 192879697Snon cb->ccb_selrcnt ++; 192979697Snon if (slp->sl_disc == 0) 193079697Snon { 193179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 1932240325Sjhb device_printf(slp->sl_dev, "try selection again\n"); 193379697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 193479697Snon slp->sl_retry_sel = 1; 193579697Snon } 193679697Snon} 193779697Snon 193879697Snonstatic void 193979697Snonscsi_low_bus_release(slp, ti) 194079697Snon struct scsi_low_softc *slp; 194167468Snon struct targ_info *ti; 194267468Snon{ 194367468Snon 194479697Snon if (ti->ti_disc > 0) 194579697Snon { 194679697Snon SCSI_LOW_SETUP_PHASE(ti, PH_DISC); 194779697Snon } 194879697Snon else 194979697Snon { 195079697Snon SCSI_LOW_SETUP_PHASE(ti, PH_NULL); 195179697Snon } 195279697Snon 195367468Snon /* clear all nexus pointer */ 195479697Snon slp->sl_Qnexus = NULL; 195579697Snon slp->sl_Lnexus = NULL; 195679697Snon slp->sl_Tnexus = NULL; 195767468Snon 195867468Snon /* clear selection assert */ 195967468Snon slp->sl_selid = NULL; 196067468Snon 196167468Snon /* clear nexus data */ 196267468Snon slp->sl_scp.scp_direction = SCSI_LOW_RWUNK; 196379697Snon 196479697Snon /* clear phase change counter */ 196579697Snon slp->sl_ph_count = 0; 196667468Snon} 196767468Snon 196867468Snonstatic int 196979697Snonscsi_low_setup_done(slp, cb) 197067468Snon struct scsi_low_softc *slp; 197167468Snon struct slccb *cb; 197267468Snon{ 197367468Snon struct targ_info *ti; 197467468Snon struct lun_info *li; 197567468Snon 197667468Snon ti = cb->ti; 197767468Snon li = cb->li; 197879697Snon 197979697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 198067468Snon { 198179697Snon cb->ccb_error |= ABORTIO; 198279697Snon return SCSI_LOW_DONE_COMPLETE; 198379697Snon } 198479697Snon 198579697Snon /* XXX: special huck for selection timeout */ 198679697Snon if (li->li_state == SCSI_LOW_LUN_SLEEP && 198779697Snon (cb->ccb_error & SELTIMEOUTIO) != 0) 198879697Snon { 198979697Snon cb->ccb_error |= ABORTIO; 199079697Snon return SCSI_LOW_DONE_COMPLETE; 199179697Snon } 199279697Snon 199379697Snon switch(li->li_state) 199479697Snon { 199579697Snon case SCSI_LOW_LUN_INQ: 199679697Snon if (cb->ccb_error != 0) 199767468Snon { 199879697Snon li->li_diskflags &= 199979697Snon ~(SCSI_LOW_DISK_LINK | SCSI_LOW_DISK_QTAG); 200079697Snon if (li->li_lun > 0) 200179697Snon goto resume; 200279697Snon ti->ti_diskflags &= 200379697Snon ~(SCSI_LOW_DISK_SYNC | SCSI_LOW_DISK_WIDE); 200467468Snon } 200579697Snon else if ((li->li_inq.sd_version & 7) >= 2 || 200679697Snon (li->li_inq.sd_len >= 4)) 200767468Snon { 200879697Snon if ((li->li_inq.sd_support & 0x2) == 0) 200979697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 201079697Snon if ((li->li_inq.sd_support & 0x8) == 0) 201179697Snon li->li_diskflags &= ~SCSI_LOW_DISK_LINK; 201279697Snon if (li->li_lun > 0) 201379697Snon goto resume; 201479697Snon if ((li->li_inq.sd_support & 0x10) == 0) 201579697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_SYNC; 201679697Snon if ((li->li_inq.sd_support & 0x20) == 0) 201779697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_16; 201879697Snon if ((li->li_inq.sd_support & 0x40) == 0) 201979697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE_32; 202079697Snon } 202179697Snon else 202279697Snon { 202379697Snon li->li_diskflags &= 202479697Snon ~(SCSI_LOW_DISK_QTAG | SCSI_LOW_DISK_LINK); 202579697Snon if (li->li_lun > 0) 202679697Snon goto resume; 202779697Snon ti->ti_diskflags &= ~SCSI_LOW_DISK_WIDE; 202879697Snon } 202979697Snon ti->ti_flags_valid |= SCSI_LOW_TARG_FLAGS_DISK_VALID; 203079697Snonresume: 203179697Snon scsi_low_calcf_target(ti); 203279697Snon scsi_low_calcf_lun(li); 203379697Snon break; 203479697Snon 203579697Snon case SCSI_LOW_LUN_MODEQ: 203679697Snon if (cb->ccb_error != 0) 203779697Snon { 203879697Snon if (cb->ccb_error & SENSEIO) 203967468Snon { 204079697Snon#ifdef SCSI_LOW_DEBUG 204179697Snon if (scsi_low_debug & SCSI_LOW_DEBUG_SENSE) 204279697Snon { 2043225950Sken int error_code, sense_key, asc, ascq; 2044225950Sken 2045225950Sken scsi_extract_sense(&cb->ccb_sense, 2046225950Sken &error_code, 2047225950Sken &sense_key, 2048225950Sken &asc, 2049225950Sken &ascq); 2050225950Sken printf("SENSE: [%x][%x][%x][%x]\n", 2051225950Sken error_code, sense_key, asc, 2052225950Sken ascq); 205379697Snon } 205479697Snon#endif /* SCSI_LOW_DEBUG */ 205567468Snon } 205679697Snon else 205779697Snon { 205879697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 205979697Snon } 206079697Snon } 206179697Snon else if ((li->li_sms.sms_cmp.cmp_page & 0x3f) == 0x0a) 206279697Snon { 206379697Snon if (li->li_sms.sms_cmp.cmp_qc & 0x02) 206479697Snon li->li_qflags |= SCSI_LOW_QFLAG_CA_QCLEAR; 206579697Snon else 206679697Snon li->li_qflags &= ~SCSI_LOW_QFLAG_CA_QCLEAR; 206779697Snon if ((li->li_sms.sms_cmp.cmp_qc & 0x01) != 0) 206879697Snon li->li_diskflags &= ~SCSI_LOW_DISK_QTAG; 206979697Snon } 207079697Snon li->li_flags_valid |= SCSI_LOW_LUN_FLAGS_DISK_VALID; 207179697Snon scsi_low_calcf_lun(li); 207279697Snon break; 207367468Snon 207479697Snon default: 207579697Snon break; 207679697Snon } 207779697Snon 207879697Snon li->li_state ++; 207979697Snon if (li->li_state == SCSI_LOW_LUN_OK) 208079697Snon { 208179697Snon scsi_low_calcf_target(ti); 208279697Snon scsi_low_calcf_lun(li); 208379697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID && 208479697Snon (slp->sl_show_result & SHOW_CALCF_RES) != 0) 208579697Snon { 208679697Snon scsi_low_calcf_show(li); 208779697Snon } 208879697Snon } 208979697Snon 209079697Snon cb->ccb_rcnt --; 209179697Snon return SCSI_LOW_DONE_RETRY; 209279697Snon} 209379697Snon 209479697Snonstatic int 209579697Snonscsi_low_done(slp, cb) 209679697Snon struct scsi_low_softc *slp; 209779697Snon struct slccb *cb; 209879697Snon{ 209979697Snon int rv; 210079697Snon 210179697Snon if (cb->ccb_error == 0) 210279697Snon { 210379697Snon if ((cb->ccb_flags & (CCB_SENSE | CCB_CLEARQ)) != 0) 210479697Snon { 210579697Snon#ifdef SCSI_LOW_QCLEAR_AFTER_CA 210679697Snon /* XXX: 210779697Snon * SCSI-2 draft suggests 210879697Snon * page 0x0a QErr bit determins if 210979697Snon * the target aborts or continues 211079697Snon * the queueing io's after CA state resolved. 211179697Snon * However many targets seem not to support 211279697Snon * the page 0x0a. Thus we should manually clear the 211379697Snon * queuing io's after CA state. 211479697Snon */ 211579697Snon if ((cb->ccb_flags & CCB_CLEARQ) == 0) 211667468Snon { 211779697Snon cb->ccb_rcnt --; 211879697Snon cb->ccb_flags |= CCB_CLEARQ; 211979697Snon goto retry; 212079697Snon } 212179697Snon#endif /* SCSI_LOW_QCLEAR_AFTER_CA */ 212279697Snon 212379697Snon if ((cb->ccb_flags & CCB_SENSE) != 0) 212479697Snon cb->ccb_error |= (SENSEIO | ABORTIO); 212579697Snon cb->ccb_flags &= ~(CCB_SENSE | CCB_CLEARQ); 212679697Snon } 212779697Snon else switch (cb->ccb_sscp.scp_status) 212879697Snon { 212979697Snon case ST_GOOD: 213079697Snon case ST_MET: 213179697Snon case ST_INTERGOOD: 213279697Snon case ST_INTERMET: 213379697Snon if (cb->ccb_datalen == 0 || 213479697Snon cb->ccb_scp.scp_datalen == 0) 213567468Snon break; 213667468Snon 213779697Snon if (cb->ccb_scp.scp_cmdlen > 0 && 213879697Snon (scsi_low_cmd_flags[cb->ccb_scp.scp_cmd[0]] & 213979697Snon SCSI_LOW_CMD_RESIDUAL_CHK) == 0) 214079697Snon break; 214179697Snon 214267468Snon cb->ccb_error |= PDMAERR; 214367468Snon break; 214467468Snon 214579697Snon case ST_BUSY: 214679697Snon case ST_QUEFULL: 214779697Snon cb->ccb_error |= (BUSYERR | STATERR); 214879697Snon break; 214979697Snon 215079697Snon case ST_CONFLICT: 215179697Snon cb->ccb_error |= (STATERR | ABORTIO); 215279697Snon break; 215379697Snon 215467468Snon case ST_CHKCOND: 215579697Snon case ST_CMDTERM: 215679697Snon if (cb->ccb_flags & (CCB_AUTOSENSE | CCB_INTERNAL)) 215779697Snon { 215879697Snon cb->ccb_rcnt --; 215973025Snon cb->ccb_flags |= CCB_SENSE; 216073025Snon goto retry; 216173025Snon } 216279697Snon cb->ccb_error |= (UACAERR | STATERR | ABORTIO); 216373025Snon break; 216467468Snon 216579697Snon case ST_UNKNOWN: 216667468Snon default: 216767468Snon cb->ccb_error |= FATALIO; 216867468Snon break; 216967468Snon } 217067468Snon } 217167468Snon else 217267468Snon { 217379697Snon if (cb->ccb_flags & CCB_SENSE) 217467468Snon { 217579697Snon cb->ccb_error |= (SENSEERR | ABORTIO); 217667468Snon } 217779697Snon cb->ccb_flags &= ~(CCB_CLEARQ | CCB_SENSE); 217879697Snon } 217967468Snon 218079697Snon /* internal ccb */ 218179697Snon if ((cb->ccb_flags & CCB_INTERNAL) != 0) 218279697Snon { 218379697Snon if (scsi_low_setup_done(slp, cb) == SCSI_LOW_DONE_RETRY) 218479697Snon goto retry; 218567468Snon } 218667468Snon 218779697Snon /* check a ccb msgout flag */ 218879697Snon if (cb->ccb_omsgoutflag != 0) 218967468Snon { 219079697Snon#define SCSI_LOW_MSG_ABORT_OK (SCSI_LOW_MSG_ABORT | \ 219179697Snon SCSI_LOW_MSG_ABORT_QTAG | \ 219279697Snon SCSI_LOW_MSG_CLEAR_QTAG | \ 219379697Snon SCSI_LOW_MSG_TERMIO) 219479697Snon 219579697Snon if ((cb->ccb_omsgoutflag & SCSI_LOW_MSG_ABORT_OK) != 0) 219667468Snon { 219779697Snon cb->ccb_error |= ABORTIO; 219867468Snon } 219967468Snon } 220067468Snon 220179697Snon /* call OS depend done */ 220279697Snon if (cb->osdep != NULL) 220367468Snon { 220479697Snon rv = (*slp->sl_osdep_fp->scsi_low_osdep_done) (slp, cb); 220579697Snon if (rv == EJUSTRETURN) 220679697Snon goto retry; 220767468Snon } 220879697Snon else if (cb->ccb_error != 0) 220967468Snon { 221079697Snon if (cb->ccb_rcnt >= slp->sl_max_retry) 221179697Snon cb->ccb_error |= ABORTIO; 221279697Snon 221379697Snon if ((cb->ccb_flags & CCB_NORETRY) == 0 && 221479697Snon (cb->ccb_error & ABORTIO) == 0) 221567468Snon goto retry; 221667468Snon } 221779697Snon 221879697Snon /* free our target */ 221979697Snon#ifdef SCSI_LOW_DEBUG 222079697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 222167468Snon { 222279697Snon printf(">> SCSI_LOW_DONE_COMPLETE ===============\n"); 222379697Snon scsi_low_print(slp, NULL); 222467468Snon } 222579697Snon#endif /* SCSI_LOW_DEBUG */ 222667468Snon 222779697Snon scsi_low_deactivate_qtag(cb); 222879697Snon scsi_low_dealloc_qtag(cb); 222967468Snon scsi_low_free_ccb(cb); 223079697Snon slp->sl_nio --; 223167468Snon return SCSI_LOW_DONE_COMPLETE; 223267468Snon 223367468Snonretry: 223479697Snon#ifdef SCSI_LOW_DEBUG 223579697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DONE, cb->ti->ti_id) != 0) 223667468Snon { 223779697Snon printf("** SCSI_LOW_DONE_RETRY ===============\n"); 223879697Snon scsi_low_print(slp, NULL); 223967468Snon } 224079697Snon#endif /* SCSI_LOW_DEBUG */ 224179697Snon 224279697Snon cb->ccb_rcnt ++; 224379697Snon scsi_low_deactivate_qtag(cb); 224479697Snon scsi_low_ccb_message_retry(cb); 224567468Snon return SCSI_LOW_DONE_RETRY; 224667468Snon} 224767468Snon 224867468Snon/************************************************************** 224967468Snon * Reset 225067468Snon **************************************************************/ 225167468Snonstatic void 225279697Snonscsi_low_reset_nexus_target(slp, ti, fdone) 225379697Snon struct scsi_low_softc *slp; 225479697Snon struct targ_info *ti; 225579697Snon int fdone; 225667468Snon{ 225779697Snon struct lun_info *li; 225867468Snon 225979697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 226079697Snon li = LIST_NEXT(li, lun_chain)) 226179697Snon { 226279697Snon scsi_low_reset_nexus_lun(slp, li, fdone); 226379697Snon li->li_state = SCSI_LOW_LUN_SLEEP; 226479697Snon li->li_maxnqio = 0; 226579697Snon } 226679697Snon 226779697Snon ti->ti_disc = 0; 226879697Snon ti->ti_setup_msg = 0; 226979697Snon ti->ti_setup_msg_done = 0; 227079697Snon 227179697Snon ti->ti_osynch.offset = ti->ti_osynch.period = 0; 227279697Snon ti->ti_owidth = SCSI_LOW_BUS_WIDTH_8; 227379697Snon 227479697Snon ti->ti_diskflags = SCSI_LOW_DISK_TFLAGS; 227579697Snon ti->ti_flags_valid &= ~SCSI_LOW_TARG_FLAGS_DISK_VALID; 227679697Snon 227779697Snon if (slp->sl_funcs->scsi_low_targ_init != NULL) 227879697Snon { 227979697Snon ((*slp->sl_funcs->scsi_low_targ_init) 228079697Snon (slp, ti, SCSI_LOW_INFO_REVOKE)); 228179697Snon } 228279697Snon scsi_low_calcf_target(ti); 228379697Snon 228479697Snon for (li = LIST_FIRST(&ti->ti_litab); li != NULL; 228579697Snon li = LIST_NEXT(li, lun_chain)) 228679697Snon { 228779697Snon li->li_flags = 0; 228879697Snon 228979697Snon li->li_diskflags = SCSI_LOW_DISK_LFLAGS; 229079697Snon li->li_flags_valid &= ~SCSI_LOW_LUN_FLAGS_DISK_VALID; 229179697Snon 229279697Snon if (slp->sl_funcs->scsi_low_lun_init != NULL) 229379697Snon { 229479697Snon ((*slp->sl_funcs->scsi_low_lun_init) 229579697Snon (slp, ti, li, SCSI_LOW_INFO_REVOKE)); 229679697Snon } 229779697Snon scsi_low_calcf_lun(li); 229879697Snon } 229967468Snon} 230067468Snon 230167468Snonstatic void 230267468Snonscsi_low_reset_nexus(slp, fdone) 230367468Snon struct scsi_low_softc *slp; 230467468Snon int fdone; 230567468Snon{ 230667468Snon struct targ_info *ti; 230779697Snon struct slccb *cb, *topcb; 230867468Snon 230979697Snon if ((cb = slp->sl_Qnexus) != NULL) 231067468Snon { 231179697Snon topcb = scsi_low_revoke_ccb(slp, cb, fdone); 231267468Snon } 231379697Snon else 231479697Snon { 231579697Snon topcb = NULL; 231679697Snon } 231767468Snon 231879697Snon for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 231979697Snon ti = TAILQ_NEXT(ti, ti_chain)) 232067468Snon { 232179697Snon scsi_low_reset_nexus_target(slp, ti, fdone); 232279697Snon scsi_low_bus_release(slp, ti); 232367468Snon scsi_low_init_msgsys(slp, ti); 232467468Snon } 232567468Snon 232679697Snon if (topcb != NULL) 232779697Snon { 232879697Snon topcb->ccb_flags |= CCB_STARTQ; 232979697Snon TAILQ_INSERT_HEAD(&slp->sl_start, topcb, ccb_chain); 233079697Snon } 233179697Snon 233279697Snon slp->sl_disc = 0; 233379697Snon slp->sl_retry_sel = 0; 233467468Snon slp->sl_flags &= ~HW_PDMASTART; 233567468Snon} 233667468Snon 233767468Snon/* misc */ 233867468Snonstatic int tw_pos; 233967468Snonstatic char tw_chars[] = "|/-\\"; 234079697Snon#define TWIDDLEWAIT 10000 234167468Snon 234267468Snonstatic void 234367468Snonscsi_low_twiddle_wait(void) 234467468Snon{ 234567468Snon 234667468Snon cnputc('\b'); 234767468Snon cnputc(tw_chars[tw_pos++]); 234867468Snon tw_pos %= (sizeof(tw_chars) - 1); 2349240172Sjhb DELAY(TWIDDLEWAIT); 235067468Snon} 235167468Snon 235267468Snonvoid 235367468Snonscsi_low_bus_reset(slp) 235467468Snon struct scsi_low_softc *slp; 235567468Snon{ 235667468Snon int i; 235767468Snon 235867468Snon (*slp->sl_funcs->scsi_low_bus_reset) (slp); 235967468Snon 2360240325Sjhb device_printf(slp->sl_dev, "try to reset scsi bus "); 236167468Snon for (i = 0; i <= SCSI2_RESET_DELAY / TWIDDLEWAIT ; i++) 236267468Snon scsi_low_twiddle_wait(); 236367468Snon cnputc('\b'); 236467468Snon printf("\n"); 236567468Snon} 236667468Snon 236767468Snonint 236867468Snonscsi_low_restart(slp, flags, s) 236967468Snon struct scsi_low_softc *slp; 237067468Snon int flags; 237167468Snon u_char *s; 237267468Snon{ 237367468Snon int error; 237467468Snon 237567468Snon if (s != NULL) 2376240325Sjhb device_printf(slp->sl_dev, "scsi bus restart. reason: %s\n", s); 237767468Snon 237867468Snon if ((error = scsi_low_init(slp, flags)) != 0) 237967468Snon return error; 238067468Snon 238167468Snon scsi_low_start(slp); 238267468Snon return 0; 238367468Snon} 238467468Snon 238567468Snon/************************************************************** 238667468Snon * disconnect and reselect 238767468Snon **************************************************************/ 238867468Snon#define MSGCMD_LUN(msg) (msg & 0x07) 238967468Snon 239067468Snonstatic struct slccb * 239167468Snonscsi_low_establish_ccb(ti, li, tag) 239267468Snon struct targ_info *ti; 239367468Snon struct lun_info *li; 239467468Snon scsi_low_tag_t tag; 239567468Snon{ 239667468Snon struct scsi_low_softc *slp = ti->ti_sc; 239767468Snon struct slccb *cb; 239867468Snon 239979697Snon if (li == NULL) 240079697Snon return NULL; 240179697Snon 240279697Snon cb = TAILQ_FIRST(&li->li_discq); 240371999Sphk for ( ; cb != NULL; cb = TAILQ_NEXT(cb, ccb_chain)) 240479697Snon if (cb->ccb_tag == tag) 240567468Snon goto found; 240667468Snon return cb; 240767468Snon 240867468Snon /* 240967468Snon * establish our ccb nexus 241067468Snon */ 241167468Snonfound: 241279697Snon#ifdef SCSI_LOW_DEBUG 241379697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 241479697Snon { 2415240325Sjhb device_printf(slp->sl_dev, "nexus(0x%lx) abort check start\n", 2416240325Sjhb (u_long) cb); 241779697Snon cb->ccb_flags |= (CCB_NORETRY | CCB_SILENT); 241879697Snon scsi_low_revoke_ccb(slp, cb, 1); 241979697Snon return NULL; 242079697Snon } 242167468Snon 242279697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id) != 0) 242379697Snon { 242479697Snon if (cb->ccb_omsgoutflag == 0) 242579697Snon scsi_low_ccb_message_assert(cb, SCSI_LOW_MSG_NOOP); 242679697Snon } 242779697Snon#endif /* SCSI_LOW_DEBUG */ 242879697Snon 242979697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 243079697Snon cb->ccb_flags &= ~CCB_DISCQ; 243179697Snon slp->sl_Qnexus = cb; 243279697Snon 243367468Snon slp->sl_scp = cb->ccb_sscp; 243467468Snon slp->sl_error |= cb->ccb_error; 243567468Snon 243667468Snon slp->sl_disc --; 243779697Snon ti->ti_disc --; 243867468Snon li->li_disc --; 243967468Snon 244067468Snon /* inform "ccb nexus established" to the host driver */ 244179697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 244279697Snon 244379697Snon /* check msg */ 244479697Snon if (cb->ccb_msgoutflag != 0) 244579697Snon { 244679697Snon scsi_low_ccb_message_exec(slp, cb); 244779697Snon } 244879697Snon 244967468Snon return cb; 245067468Snon} 245167468Snon 245267468Snonstruct targ_info * 245367468Snonscsi_low_reselected(slp, targ) 245467468Snon struct scsi_low_softc *slp; 245567468Snon u_int targ; 245667468Snon{ 245767468Snon struct targ_info *ti; 245879697Snon struct slccb *cb; 245967468Snon u_char *s; 246067468Snon 246167468Snon /* 246267468Snon * Check select vs reselected collision. 246367468Snon */ 246467468Snon 246579697Snon if ((cb = slp->sl_selid) != NULL) 246667468Snon { 246779697Snon scsi_low_arbit_fail(slp, cb); 246867468Snon#ifdef SCSI_LOW_STATICS 246967468Snon scsi_low_statics.nexus_conflict ++; 247067468Snon#endif /* SCSI_LOW_STATICS */ 247167468Snon } 247279697Snon 247379697Snon /* 247479697Snon * Check if no current active nexus. 247579697Snon */ 247679697Snon if (slp->sl_Tnexus != NULL) 247767468Snon { 247867468Snon s = "host busy"; 247967468Snon goto world_restart; 248067468Snon } 248167468Snon 248267468Snon /* 248367468Snon * Check a valid target id asserted ? 248467468Snon */ 248567468Snon if (targ >= slp->sl_ntargs || targ == slp->sl_hostid) 248667468Snon { 248767468Snon s = "scsi id illegal"; 248867468Snon goto world_restart; 248967468Snon } 249067468Snon 249167468Snon /* 249267468Snon * Check the target scsi status. 249367468Snon */ 249467468Snon ti = slp->sl_ti[targ]; 249579697Snon if (ti->ti_phase != PH_DISC && ti->ti_phase != PH_NULL) 249667468Snon { 249767468Snon s = "phase mismatch"; 249867468Snon goto world_restart; 249967468Snon } 250067468Snon 250167468Snon /* 250279697Snon * Setup init msgsys 250367468Snon */ 250467468Snon slp->sl_error = 0; 250567468Snon scsi_low_init_msgsys(slp, ti); 250667468Snon 250767468Snon /* 250867468Snon * Establish our target nexus 250967468Snon */ 251067468Snon SCSI_LOW_SETUP_PHASE(ti, PH_RESEL); 251179697Snon slp->sl_Tnexus = ti; 251267468Snon#ifdef SCSI_LOW_STATICS 251367468Snon scsi_low_statics.nexus_reselected ++; 251467468Snon#endif /* SCSI_LOW_STATICS */ 251567468Snon return ti; 251667468Snon 251767468Snonworld_restart: 2518240325Sjhb device_printf(slp->sl_dev, "reselect(%x:unknown) %s\n", targ, s); 251967468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, 252067468Snon "reselect: scsi world confused"); 252167468Snon return NULL; 252267468Snon} 252367468Snon 252467468Snon/************************************************************** 252567468Snon * cmd out pointer setup 252667468Snon **************************************************************/ 252767468Snonint 252867468Snonscsi_low_cmd(slp, ti) 252967468Snon struct scsi_low_softc *slp; 253067468Snon struct targ_info *ti; 253167468Snon{ 253279697Snon struct slccb *cb = slp->sl_Qnexus; 253367468Snon 253479697Snon slp->sl_ph_count ++; 253567468Snon if (cb == NULL) 253667468Snon { 253767468Snon /* 253879697Snon * no ccb, abort! 253967468Snon */ 254067468Snon slp->sl_scp.scp_cmd = (u_int8_t *) &unit_ready_cmd; 254167468Snon slp->sl_scp.scp_cmdlen = sizeof(unit_ready_cmd); 254267468Snon slp->sl_scp.scp_datalen = 0; 254367468Snon slp->sl_scp.scp_direction = SCSI_LOW_READ; 254479697Snon slp->sl_error |= FATALIO; 254579697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 254679697Snon SCSI_LOW_INFO(slp, ti, "CMDOUT: ccb nexus not found"); 254779697Snon return EINVAL; 254867468Snon } 254979697Snon else 255067468Snon { 255179697Snon#ifdef SCSI_LOW_DEBUG 255279697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_CMDLNK_CHECK, ti->ti_id)) 255379697Snon { 255479697Snon scsi_low_test_cmdlnk(slp, cb); 255579697Snon } 255679697Snon#endif /* SCSI_LOW_DEBUG */ 255767468Snon } 255867468Snon return 0; 255967468Snon} 256067468Snon 256167468Snon/************************************************************** 256267468Snon * data out pointer setup 256367468Snon **************************************************************/ 256467468Snonint 256567468Snonscsi_low_data(slp, ti, bp, direction) 256667468Snon struct scsi_low_softc *slp; 256767468Snon struct targ_info *ti; 256867468Snon struct buf **bp; 256967468Snon int direction; 257067468Snon{ 257179697Snon struct slccb *cb = slp->sl_Qnexus; 257267468Snon 257379697Snon if (cb != NULL && direction == cb->ccb_sscp.scp_direction) 257467468Snon { 257579697Snon *bp = cb->bp; 257679697Snon return 0; 257767468Snon } 257867468Snon 257979697Snon slp->sl_error |= (FATALIO | PDMAERR); 258079697Snon slp->sl_scp.scp_datalen = 0; 258179697Snon slp->sl_scp.scp_direction = direction; 258279697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 258379697Snon if (ti->ti_ophase != ti->ti_phase) 258467468Snon { 258579697Snon char *s; 258679697Snon 258779697Snon if (cb == NULL) 258879697Snon s = "DATA PHASE: ccb nexus not found"; 258979697Snon else 259079697Snon s = "DATA PHASE: xfer direction mismatch"; 259179697Snon SCSI_LOW_INFO(slp, ti, s); 259267468Snon } 259367468Snon 259479697Snon *bp = NULL; 259579697Snon return EINVAL; 259667468Snon} 259767468Snon 259867468Snon/************************************************************** 259967468Snon * MSG_SYS 260067468Snon **************************************************************/ 260167468Snon#define MSGINPTR_CLR(ti) {(ti)->ti_msginptr = 0; (ti)->ti_msginlen = 0;} 260267468Snon#define MSGIN_PERIOD(ti) ((ti)->ti_msgin[3]) 260367468Snon#define MSGIN_OFFSET(ti) ((ti)->ti_msgin[4]) 260479697Snon#define MSGIN_WIDTHP(ti) ((ti)->ti_msgin[3]) 260567468Snon#define MSGIN_DATA_LAST 0x30 260667468Snon 260792770Salfredstatic int scsi_low_errfunc_synch(struct scsi_low_softc *, u_int); 260892770Salfredstatic int scsi_low_errfunc_wide(struct scsi_low_softc *, u_int); 260992770Salfredstatic int scsi_low_errfunc_identify(struct scsi_low_softc *, u_int); 261092770Salfredstatic int scsi_low_errfunc_qtag(struct scsi_low_softc *, u_int); 261167468Snon 261292770Salfredstatic int scsi_low_msgfunc_synch(struct scsi_low_softc *); 261392770Salfredstatic int scsi_low_msgfunc_wide(struct scsi_low_softc *); 261492770Salfredstatic int scsi_low_msgfunc_identify(struct scsi_low_softc *); 261592770Salfredstatic int scsi_low_msgfunc_abort(struct scsi_low_softc *); 261692770Salfredstatic int scsi_low_msgfunc_qabort(struct scsi_low_softc *); 261792770Salfredstatic int scsi_low_msgfunc_qtag(struct scsi_low_softc *); 261892770Salfredstatic int scsi_low_msgfunc_reset(struct scsi_low_softc *); 261967468Snon 262067468Snonstruct scsi_low_msgout_data { 262167468Snon u_int md_flags; 262267468Snon u_int8_t md_msg; 262392770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 262492770Salfred int (*md_errfunc)(struct scsi_low_softc *, u_int); 262579697Snon#define MSG_RELEASE_ATN 0x0001 262679697Snon u_int md_condition; 262767468Snon}; 262867468Snon 262967468Snonstruct scsi_low_msgout_data scsi_low_msgout_data[] = { 263079697Snon/* 0 */ {SCSI_LOW_MSG_RESET, MSG_RESET, scsi_low_msgfunc_reset, NULL, MSG_RELEASE_ATN}, 263179697Snon/* 1 */ {SCSI_LOW_MSG_REJECT, MSG_REJECT, NULL, NULL, MSG_RELEASE_ATN}, 263279697Snon/* 2 */ {SCSI_LOW_MSG_PARITY, MSG_PARITY, NULL, NULL, MSG_RELEASE_ATN}, 263379697Snon/* 3 */ {SCSI_LOW_MSG_ERROR, MSG_I_ERROR, NULL, NULL, MSG_RELEASE_ATN}, 263479697Snon/* 4 */ {SCSI_LOW_MSG_IDENTIFY, MSG_IDENTIFY, scsi_low_msgfunc_identify, scsi_low_errfunc_identify, 0}, 263579697Snon/* 5 */ {SCSI_LOW_MSG_ABORT, MSG_ABORT, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 263679697Snon/* 6 */ {SCSI_LOW_MSG_TERMIO, MSG_TERM_IO, NULL, NULL, MSG_RELEASE_ATN}, 263779697Snon/* 7 */ {SCSI_LOW_MSG_SIMPLE_QTAG, MSG_SIMPLE_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 263879697Snon/* 8 */ {SCSI_LOW_MSG_ORDERED_QTAG, MSG_ORDERED_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 263979697Snon/* 9 */{SCSI_LOW_MSG_HEAD_QTAG, MSG_HEAD_QTAG, scsi_low_msgfunc_qtag, scsi_low_errfunc_qtag, 0}, 264079697Snon/* 10 */ {SCSI_LOW_MSG_ABORT_QTAG, MSG_ABORT_QTAG, scsi_low_msgfunc_qabort, NULL, MSG_RELEASE_ATN}, 264179697Snon/* 11 */ {SCSI_LOW_MSG_CLEAR_QTAG, MSG_CLEAR_QTAG, scsi_low_msgfunc_abort, NULL, MSG_RELEASE_ATN}, 264279697Snon/* 12 */{SCSI_LOW_MSG_WIDE, MSG_EXTEND, scsi_low_msgfunc_wide, scsi_low_errfunc_wide, MSG_RELEASE_ATN}, 264379697Snon/* 13 */{SCSI_LOW_MSG_SYNCH, MSG_EXTEND, scsi_low_msgfunc_synch, scsi_low_errfunc_synch, MSG_RELEASE_ATN}, 264479697Snon/* 14 */{SCSI_LOW_MSG_NOOP, MSG_NOOP, NULL, NULL, MSG_RELEASE_ATN}, 264579697Snon/* 15 */{SCSI_LOW_MSG_ALL, 0}, 264667468Snon}; 264767468Snon 264892770Salfredstatic int scsi_low_msginfunc_ext(struct scsi_low_softc *); 264992770Salfredstatic int scsi_low_synch(struct scsi_low_softc *); 265092770Salfredstatic int scsi_low_wide(struct scsi_low_softc *); 265192770Salfredstatic int scsi_low_msginfunc_msg_reject(struct scsi_low_softc *); 265292770Salfredstatic int scsi_low_msginfunc_rejop(struct scsi_low_softc *); 265392770Salfredstatic int scsi_low_msginfunc_rp(struct scsi_low_softc *); 265492770Salfredstatic int scsi_low_msginfunc_sdp(struct scsi_low_softc *); 265592770Salfredstatic int scsi_low_msginfunc_disc(struct scsi_low_softc *); 265692770Salfredstatic int scsi_low_msginfunc_cc(struct scsi_low_softc *); 265792770Salfredstatic int scsi_low_msginfunc_lcc(struct scsi_low_softc *); 265892770Salfredstatic int scsi_low_msginfunc_parity(struct scsi_low_softc *); 265992770Salfredstatic int scsi_low_msginfunc_noop(struct scsi_low_softc *); 266092770Salfredstatic int scsi_low_msginfunc_simple_qtag(struct scsi_low_softc *); 266192770Salfredstatic int scsi_low_msginfunc_i_wide_residue(struct scsi_low_softc *); 266267468Snon 266367468Snonstruct scsi_low_msgin_data { 266467468Snon u_int md_len; 266592770Salfred int (*md_msgfunc)(struct scsi_low_softc *); 266667468Snon}; 266767468Snon 266867468Snonstruct scsi_low_msgin_data scsi_low_msgin_data[] = { 266967468Snon/* 0 */ {1, scsi_low_msginfunc_cc}, 267067468Snon/* 1 */ {2, scsi_low_msginfunc_ext}, 267167468Snon/* 2 */ {1, scsi_low_msginfunc_sdp}, 267279697Snon/* 3 */ {1, scsi_low_msginfunc_rp}, 267367468Snon/* 4 */ {1, scsi_low_msginfunc_disc}, 267467468Snon/* 5 */ {1, scsi_low_msginfunc_rejop}, 267567468Snon/* 6 */ {1, scsi_low_msginfunc_rejop}, 267667468Snon/* 7 */ {1, scsi_low_msginfunc_msg_reject}, 267767468Snon/* 8 */ {1, scsi_low_msginfunc_noop}, 267867468Snon/* 9 */ {1, scsi_low_msginfunc_parity}, 267979697Snon/* a */ {1, scsi_low_msginfunc_lcc}, 268079697Snon/* b */ {1, scsi_low_msginfunc_lcc}, 268167468Snon/* c */ {1, scsi_low_msginfunc_rejop}, 268267468Snon/* d */ {2, scsi_low_msginfunc_rejop}, 268367468Snon/* e */ {1, scsi_low_msginfunc_rejop}, 268467468Snon/* f */ {1, scsi_low_msginfunc_rejop}, 268567468Snon/* 0x10 */ {1, scsi_low_msginfunc_rejop}, 268667468Snon/* 0x11 */ {1, scsi_low_msginfunc_rejop}, 268767468Snon/* 0x12 */ {1, scsi_low_msginfunc_rejop}, 268867468Snon/* 0x13 */ {1, scsi_low_msginfunc_rejop}, 268967468Snon/* 0x14 */ {1, scsi_low_msginfunc_rejop}, 269067468Snon/* 0x15 */ {1, scsi_low_msginfunc_rejop}, 269167468Snon/* 0x16 */ {1, scsi_low_msginfunc_rejop}, 269267468Snon/* 0x17 */ {1, scsi_low_msginfunc_rejop}, 269367468Snon/* 0x18 */ {1, scsi_low_msginfunc_rejop}, 269467468Snon/* 0x19 */ {1, scsi_low_msginfunc_rejop}, 269567468Snon/* 0x1a */ {1, scsi_low_msginfunc_rejop}, 269667468Snon/* 0x1b */ {1, scsi_low_msginfunc_rejop}, 269767468Snon/* 0x1c */ {1, scsi_low_msginfunc_rejop}, 269867468Snon/* 0x1d */ {1, scsi_low_msginfunc_rejop}, 269967468Snon/* 0x1e */ {1, scsi_low_msginfunc_rejop}, 270067468Snon/* 0x1f */ {1, scsi_low_msginfunc_rejop}, 270179697Snon/* 0x20 */ {2, scsi_low_msginfunc_simple_qtag}, 270267468Snon/* 0x21 */ {2, scsi_low_msginfunc_rejop}, 270367468Snon/* 0x22 */ {2, scsi_low_msginfunc_rejop}, 270479697Snon/* 0x23 */ {2, scsi_low_msginfunc_i_wide_residue}, 270567468Snon/* 0x24 */ {2, scsi_low_msginfunc_rejop}, 270667468Snon/* 0x25 */ {2, scsi_low_msginfunc_rejop}, 270767468Snon/* 0x26 */ {2, scsi_low_msginfunc_rejop}, 270867468Snon/* 0x27 */ {2, scsi_low_msginfunc_rejop}, 270967468Snon/* 0x28 */ {2, scsi_low_msginfunc_rejop}, 271067468Snon/* 0x29 */ {2, scsi_low_msginfunc_rejop}, 271167468Snon/* 0x2a */ {2, scsi_low_msginfunc_rejop}, 271267468Snon/* 0x2b */ {2, scsi_low_msginfunc_rejop}, 271367468Snon/* 0x2c */ {2, scsi_low_msginfunc_rejop}, 271467468Snon/* 0x2d */ {2, scsi_low_msginfunc_rejop}, 271567468Snon/* 0x2e */ {2, scsi_low_msginfunc_rejop}, 271667468Snon/* 0x2f */ {2, scsi_low_msginfunc_rejop}, 271767468Snon/* 0x30 */ {1, scsi_low_msginfunc_rejop} /* default rej op */ 271867468Snon}; 271967468Snon 272067468Snon/************************************************************** 272167468Snon * msgout 272267468Snon **************************************************************/ 272367468Snonstatic int 272479697Snonscsi_low_msgfunc_synch(slp) 272579697Snon struct scsi_low_softc *slp; 272667468Snon{ 272779697Snon struct targ_info *ti = slp->sl_Tnexus; 272867468Snon int ptr = ti->ti_msgoutlen; 272967468Snon 273067468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_SYNCHLEN; 273167468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_SYNCHCODE; 273273025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_maxsynch.period; 273373025Snon ti->ti_msgoutstr[ptr + 4] = ti->ti_maxsynch.offset; 273467468Snon return MSG_EXTEND_SYNCHLEN + 2; 273567468Snon} 273667468Snon 273767468Snonstatic int 273879697Snonscsi_low_msgfunc_wide(slp) 273979697Snon struct scsi_low_softc *slp; 274067468Snon{ 274179697Snon struct targ_info *ti = slp->sl_Tnexus; 274267468Snon int ptr = ti->ti_msgoutlen; 274367468Snon 274467468Snon ti->ti_msgoutstr[ptr + 1] = MSG_EXTEND_WIDELEN; 274567468Snon ti->ti_msgoutstr[ptr + 2] = MSG_EXTEND_WIDECODE; 274673025Snon ti->ti_msgoutstr[ptr + 3] = ti->ti_width; 274767468Snon return MSG_EXTEND_WIDELEN + 2; 274867468Snon} 274967468Snon 275067468Snonstatic int 275179697Snonscsi_low_msgfunc_identify(slp) 275279697Snon struct scsi_low_softc *slp; 275367468Snon{ 275479697Snon struct targ_info *ti = slp->sl_Tnexus; 275579697Snon struct lun_info *li = slp->sl_Lnexus; 275679697Snon struct slccb *cb = slp->sl_Qnexus; 275779697Snon int ptr = ti->ti_msgoutlen; 275879697Snon u_int8_t msg; 275967468Snon 276079697Snon msg = MSG_IDENTIFY; 276179697Snon if (cb == NULL) 276267468Snon { 276379697Snon slp->sl_error |= FATALIO; 276479697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 276579697Snon SCSI_LOW_INFO(slp, ti, "MSGOUT: nexus unknown"); 276667468Snon } 276767468Snon else 276867468Snon { 276979697Snon if (scsi_low_is_disconnect_ok(cb) != 0) 277079697Snon msg |= (MSG_IDENTIFY_DISCPRIV | li->li_lun); 277179697Snon else 277279697Snon msg |= li->li_lun; 277379697Snon 277479697Snon if (ti->ti_phase == PH_MSGOUT) 277579697Snon { 277679697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 277779697Snon if (cb->ccb_tag == SCSI_LOW_UNKTAG) 277879697Snon { 277979697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 278079697Snon } 278179697Snon } 278267468Snon } 278379697Snon ti->ti_msgoutstr[ptr + 0] = msg; 278467468Snon return 1; 278567468Snon} 278667468Snon 278767468Snonstatic int 278879697Snonscsi_low_msgfunc_abort(slp) 278979697Snon struct scsi_low_softc *slp; 279067468Snon{ 279167468Snon 279279697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_ABORT); 279379697Snon return 1; 279479697Snon} 279579697Snon 279679697Snonstatic int 279779697Snonscsi_low_msgfunc_qabort(slp) 279879697Snon struct scsi_low_softc *slp; 279979697Snon{ 280079697Snon 280179697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_TERM); 280279697Snon return 1; 280379697Snon} 280479697Snon 280579697Snonstatic int 280679697Snonscsi_low_msgfunc_reset(slp) 280779697Snon struct scsi_low_softc *slp; 280879697Snon{ 280979697Snon 281079697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_RESET); 281179697Snon return 1; 281279697Snon} 281379697Snon 281479697Snonstatic int 281579697Snonscsi_low_msgfunc_qtag(slp) 281679697Snon struct scsi_low_softc *slp; 281779697Snon{ 281879697Snon struct targ_info *ti = slp->sl_Tnexus; 281979697Snon struct slccb *cb = slp->sl_Qnexus; 282079697Snon int ptr = ti->ti_msgoutlen; 282179697Snon 282279697Snon if (cb == NULL || cb->ccb_tag == SCSI_LOW_UNKTAG) 282367468Snon { 282467468Snon ti->ti_msgoutstr[ptr + 0] = MSG_NOOP; 282567468Snon return 1; 282667468Snon } 282767468Snon else 282867468Snon { 282979697Snon ti->ti_msgoutstr[ptr + 1] = (u_int8_t) cb->ccb_tag; 283079697Snon if (ti->ti_phase == PH_MSGOUT) 283179697Snon { 283279697Snon (*slp->sl_funcs->scsi_low_establish_ccb_nexus) (slp); 283379697Snon } 283467468Snon } 283579697Snon return 2; 283667468Snon} 283767468Snon 283867468Snon/* 283967468Snon * The following functions are called when targets give unexpected 284067468Snon * responces in msgin (after msgout). 284167468Snon */ 284267468Snonstatic int 284379697Snonscsi_low_errfunc_identify(slp, msgflags) 284479697Snon struct scsi_low_softc *slp; 284567468Snon u_int msgflags; 284667468Snon{ 284767468Snon 284879697Snon if (slp->sl_Lnexus != NULL) 284979697Snon { 285079697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_DISC; 285179697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 285279697Snon } 285367468Snon return 0; 285467468Snon} 285567468Snon 285667468Snonstatic int 285779697Snonscsi_low_errfunc_synch(slp, msgflags) 285879697Snon struct scsi_low_softc *slp; 285967468Snon u_int msgflags; 286067468Snon{ 286179697Snon struct targ_info *ti = slp->sl_Tnexus; 286267468Snon 286367468Snon MSGIN_PERIOD(ti) = 0; 286467468Snon MSGIN_OFFSET(ti) = 0; 286579697Snon scsi_low_synch(slp); 286667468Snon return 0; 286767468Snon} 286867468Snon 286967468Snonstatic int 287079697Snonscsi_low_errfunc_wide(slp, msgflags) 287179697Snon struct scsi_low_softc *slp; 287267468Snon u_int msgflags; 287367468Snon{ 287479697Snon struct targ_info *ti = slp->sl_Tnexus; 287579697Snon 287679697Snon MSGIN_WIDTHP(ti) = 0; 287779697Snon scsi_low_wide(slp); 287867468Snon return 0; 287967468Snon} 288067468Snon 288179697Snonstatic int 288279697Snonscsi_low_errfunc_qtag(slp, msgflags) 288379697Snon struct scsi_low_softc *slp; 288479697Snon u_int msgflags; 288579697Snon{ 288679697Snon 288779697Snon if ((msgflags & SCSI_LOW_MSG_REJECT) != 0) 288879697Snon { 288979697Snon if (slp->sl_Qnexus != NULL) 289079697Snon { 289179697Snon scsi_low_deactivate_qtag(slp->sl_Qnexus); 289279697Snon } 289379697Snon if (slp->sl_Lnexus != NULL) 289479697Snon { 289579697Snon slp->sl_Lnexus->li_cfgflags &= ~SCSI_LOW_QTAG; 289679697Snon scsi_low_calcf_lun(slp->sl_Lnexus); 289779697Snon } 2898240325Sjhb device_printf(slp->sl_dev, "scsi_low: qtag msg rejected\n"); 289979697Snon } 290079697Snon return 0; 290179697Snon} 290279697Snon 290379697Snon 290467468Snonint 290579697Snonscsi_low_msgout(slp, ti, fl) 290667468Snon struct scsi_low_softc *slp; 290767468Snon struct targ_info *ti; 290879697Snon u_int fl; 290967468Snon{ 291067468Snon struct scsi_low_msgout_data *mdp; 291167468Snon int len = 0; 291267468Snon 291379697Snon#ifdef SCSI_LOW_DIAGNOSTIC 291479697Snon if (ti != slp->sl_Tnexus) 291579697Snon { 291679697Snon scsi_low_print(slp, NULL); 291779697Snon panic("scsi_low_msgout: Target nexus inconsistent"); 291879697Snon } 291979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 292079697Snon 292179697Snon slp->sl_ph_count ++; 292279697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 292379697Snon { 2924240325Sjhb device_printf(slp->sl_dev, "too many phase changes\n"); 292579697Snon slp->sl_error |= FATALIO; 292679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 292779697Snon } 292879697Snon 292967468Snon /* STEP I. 293067468Snon * Scsi phase changes. 293167468Snon * Previously msgs asserted are accepted by our target or 293267468Snon * processed by scsi_low_msgin. 293367468Snon * Thus clear all saved informations. 293467468Snon */ 293579697Snon if ((fl & SCSI_LOW_MSGOUT_INIT) != 0) 293667468Snon { 293767468Snon ti->ti_omsgflags = 0; 293867468Snon ti->ti_emsgflags = 0; 293967468Snon } 294079697Snon else if (slp->sl_atten == 0) 294179697Snon { 294267468Snon /* STEP II. 294367468Snon * We did not assert attention, however still our target required 294467468Snon * msgs. Resend previous msgs. 294567468Snon */ 294667468Snon ti->ti_msgflags |= ti->ti_omsgflags; 294779697Snon ti->ti_omsgflags = 0; 294867468Snon#ifdef SCSI_LOW_DIAGNOSTIC 2949240325Sjhb device_printf(slp->sl_dev, "scsi_low_msgout: retry msgout\n"); 295067468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 295167468Snon } 295267468Snon 295367468Snon /* STEP III. 295479697Snon * We have no msgs. send MSG_NOOP (OK?) 295567468Snon */ 295679697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 295767468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_NOOP, 0); 295867468Snon 295967468Snon /* STEP IV. 296067468Snon * Process all msgs 296167468Snon */ 296267468Snon ti->ti_msgoutlen = 0; 296379697Snon slp->sl_clear_atten = 0; 296467468Snon mdp = &scsi_low_msgout_data[0]; 296567468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 296667468Snon { 296767468Snon if ((ti->ti_msgflags & mdp->md_flags) != 0) 296867468Snon { 296967468Snon ti->ti_omsgflags |= mdp->md_flags; 297067468Snon ti->ti_msgflags &= ~mdp->md_flags; 297167468Snon ti->ti_emsgflags = mdp->md_flags; 297267468Snon 297367468Snon ti->ti_msgoutstr[ti->ti_msgoutlen] = mdp->md_msg; 297467468Snon if (mdp->md_msgfunc != NULL) 297579697Snon len = (*mdp->md_msgfunc) (slp); 297667468Snon else 297767468Snon len = 1; 297867468Snon 297979697Snon#ifdef SCSI_LOW_DIAGNOSTIC 298079697Snon scsi_low_msg_log_write(&ti->ti_log_msgout, 298179697Snon &ti->ti_msgoutstr[ti->ti_msgoutlen], len); 298279697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 298379697Snon 298467468Snon ti->ti_msgoutlen += len; 298579697Snon if ((mdp->md_condition & MSG_RELEASE_ATN) != 0) 298679697Snon { 298779697Snon slp->sl_clear_atten = 1; 298879697Snon break; 298979697Snon } 299079697Snon 299179697Snon if ((fl & SCSI_LOW_MSGOUT_UNIFY) == 0 || 299267468Snon ti->ti_msgflags == 0) 299367468Snon break; 299479697Snon 299567468Snon if (ti->ti_msgoutlen >= SCSI_LOW_MAX_MSGLEN - 5) 299667468Snon break; 299767468Snon } 299867468Snon } 299967468Snon 300079697Snon if (scsi_low_is_msgout_continue(ti, 0) == 0) 300179697Snon slp->sl_clear_atten = 1; 300267468Snon 300367468Snon return ti->ti_msgoutlen; 300467468Snon} 300567468Snon 300667468Snon/************************************************************** 300767468Snon * msgin 300867468Snon **************************************************************/ 300967468Snonstatic int 301079697Snonscsi_low_msginfunc_noop(slp) 301179697Snon struct scsi_low_softc *slp; 301267468Snon{ 301367468Snon 301467468Snon return 0; 301567468Snon} 301667468Snon 301767468Snonstatic int 301879697Snonscsi_low_msginfunc_rejop(slp) 301979697Snon struct scsi_low_softc *slp; 302067468Snon{ 302179697Snon struct targ_info *ti = slp->sl_Tnexus; 302267468Snon u_int8_t msg = ti->ti_msgin[0]; 302367468Snon 3024240325Sjhb device_printf(slp->sl_dev, "MSGIN: msg 0x%x rejected\n", (u_int) msg); 302567468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 302667468Snon return 0; 302767468Snon} 302867468Snon 302967468Snonstatic int 303079697Snonscsi_low_msginfunc_cc(slp) 303179697Snon struct scsi_low_softc *slp; 303267468Snon{ 303379697Snon struct lun_info *li; 303467468Snon 303567468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC); 303679697Snon 303779697Snon /* validate status */ 303879697Snon if (slp->sl_Qnexus == NULL) 303979697Snon return ENOENT; 304079697Snon 304179697Snon slp->sl_Qnexus->ccb_sscp.scp_status = slp->sl_scp.scp_status; 304279697Snon li = slp->sl_Lnexus; 304379697Snon switch (slp->sl_scp.scp_status) 304479697Snon { 304579697Snon case ST_GOOD: 304679697Snon li->li_maxnqio = li->li_maxnexus; 304779697Snon break; 304879697Snon 304979697Snon case ST_CHKCOND: 305079697Snon li->li_maxnqio = 0; 305179697Snon if (li->li_qflags & SCSI_LOW_QFLAG_CA_QCLEAR) 305279697Snon scsi_low_reset_nexus_lun(slp, li, 0); 305379697Snon break; 305479697Snon 305579697Snon case ST_BUSY: 305679697Snon li->li_maxnqio = 0; 305779697Snon break; 305879697Snon 305979697Snon case ST_QUEFULL: 306079697Snon if (li->li_maxnexus >= li->li_nqio) 306179697Snon li->li_maxnexus = li->li_nqio - 1; 306279697Snon li->li_maxnqio = li->li_maxnexus; 306379697Snon break; 306479697Snon 306579697Snon case ST_INTERGOOD: 306679697Snon case ST_INTERMET: 306779697Snon slp->sl_error |= MSGERR; 306879697Snon break; 306979697Snon 307079697Snon default: 307179697Snon break; 307279697Snon } 307367468Snon return 0; 307467468Snon} 307567468Snon 307667468Snonstatic int 307779697Snonscsi_low_msginfunc_lcc(slp) 307879697Snon struct scsi_low_softc *slp; 307979697Snon{ 308067468Snon struct targ_info *ti; 308179697Snon struct lun_info *li; 308279697Snon struct slccb *ncb, *cb; 308379697Snon 308479697Snon ti = slp->sl_Tnexus; 308579697Snon li = slp->sl_Lnexus; 308679697Snon if ((cb = slp->sl_Qnexus) == NULL) 308779697Snon goto bad; 308879697Snon 308979697Snon cb->ccb_sscp.scp_status = slp->sl_scp.scp_status; 309079697Snon switch (slp->sl_scp.scp_status) 309179697Snon { 309279697Snon case ST_INTERGOOD: 309379697Snon case ST_INTERMET: 309479697Snon li->li_maxnqio = li->li_maxnexus; 309579697Snon break; 309679697Snon 309779697Snon default: 309879697Snon slp->sl_error |= MSGERR; 309979697Snon break; 310079697Snon } 310179697Snon 310279697Snon if ((li->li_flags & SCSI_LOW_LINK) == 0) 310379697Snon goto bad; 310479697Snon 310579697Snon cb->ccb_error |= slp->sl_error; 310679697Snon if (cb->ccb_error != 0) 310779697Snon goto bad; 310879697Snon 310979697Snon for (ncb = TAILQ_FIRST(&slp->sl_start); ncb != NULL; 311079697Snon ncb = TAILQ_NEXT(ncb, ccb_chain)) 311179697Snon { 311279697Snon if (ncb->li == li) 311379697Snon goto cmd_link_start; 311479697Snon } 311579697Snon 311679697Snon 311779697Snonbad: 311879697Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_LCTERM); 311979697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 312079697Snon return EIO; 312179697Snon 312279697Snoncmd_link_start: 312379697Snon ncb->ccb_flags &= ~CCB_STARTQ; 312479697Snon TAILQ_REMOVE(&slp->sl_start, ncb, ccb_chain); 312579697Snon 312679697Snon scsi_low_dealloc_qtag(ncb); 312779697Snon ncb->ccb_tag = cb->ccb_tag; 312879697Snon ncb->ccb_otag = cb->ccb_otag; 312979697Snon cb->ccb_tag = SCSI_LOW_UNKTAG; 313079697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 313179697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 3132240325Sjhb panic("%s: linked ccb retried", 3133240325Sjhb device_get_nameunit(slp->sl_dev)); 313479697Snon 313579697Snon slp->sl_Qnexus = ncb; 313679697Snon slp->sl_ph_count = 0; 313779697Snon 313879697Snon ncb->ccb_error = 0; 313979697Snon ncb->ccb_datalen = -1; 314079697Snon ncb->ccb_scp.scp_status = ST_UNKNOWN; 314179697Snon ncb->ccb_flags &= ~CCB_INTERNAL; 314279697Snon 314379697Snon scsi_low_init_msgsys(slp, ti); 314479697Snon 314579697Snon (*slp->sl_osdep_fp->scsi_low_osdep_ccb_setup) (slp, ncb); 314679697Snon 314779697Snon if (ncb->ccb_tcmax < SCSI_LOW_MIN_TOUT) 314879697Snon ncb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 314979697Snon ncb->ccb_tc = ncb->ccb_tcmax; 315079697Snon 315179697Snon /* setup saved scsi data pointer */ 315279697Snon ncb->ccb_sscp = ncb->ccb_scp; 315379697Snon slp->sl_scp = ncb->ccb_sscp; 315479697Snon slp->sl_error = ncb->ccb_error; 315579697Snon 315679697Snon#ifdef SCSI_LOW_DIAGNOSTIC 315779697Snon scsi_low_msg_log_init(&ti->ti_log_msgin); 315879697Snon scsi_low_msg_log_init(&ti->ti_log_msgout); 315979697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 316079697Snon return EJUSTRETURN; 316179697Snon} 316279697Snon 316379697Snonstatic int 316479697Snonscsi_low_msginfunc_disc(slp) 316579697Snon struct scsi_low_softc *slp; 316667468Snon{ 316767468Snon 316867468Snon SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC); 316967468Snon return 0; 317067468Snon} 317167468Snon 317267468Snonstatic int 317379697Snonscsi_low_msginfunc_sdp(slp) 317479697Snon struct scsi_low_softc *slp; 317567468Snon{ 317679697Snon struct slccb *cb = slp->sl_Qnexus; 317767468Snon 317879697Snon if (cb != NULL) 317979697Snon { 318079697Snon cb->ccb_sscp.scp_datalen = slp->sl_scp.scp_datalen; 318179697Snon cb->ccb_sscp.scp_data = slp->sl_scp.scp_data; 318279697Snon } 318367468Snon else 318479697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 318567468Snon return 0; 318667468Snon} 318767468Snon 318867468Snonstatic int 318979697Snonscsi_low_msginfunc_rp(slp) 319079697Snon struct scsi_low_softc *slp; 319167468Snon{ 319267468Snon 319379697Snon if (slp->sl_Qnexus != NULL) 319479697Snon slp->sl_scp = slp->sl_Qnexus->ccb_sscp; 319567468Snon else 319679697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_REJECT, 0); 319767468Snon return 0; 319867468Snon} 319967468Snon 320067468Snonstatic int 320179697Snonscsi_low_synch(slp) 320279697Snon struct scsi_low_softc *slp; 320367468Snon{ 320479697Snon struct targ_info *ti = slp->sl_Tnexus; 320579697Snon u_int period = 0, offset = 0, speed; 320667468Snon u_char *s; 320767468Snon int error; 320867468Snon 320979697Snon if ((MSGIN_PERIOD(ti) >= ti->ti_maxsynch.period && 321079697Snon MSGIN_OFFSET(ti) <= ti->ti_maxsynch.offset) || 321179697Snon MSGIN_OFFSET(ti) == 0) 321267468Snon { 321367468Snon if ((offset = MSGIN_OFFSET(ti)) != 0) 321467468Snon period = MSGIN_PERIOD(ti); 321567468Snon s = offset ? "synchronous" : "async"; 321667468Snon } 321767468Snon else 321867468Snon { 321967468Snon /* XXX: 322067468Snon * Target seems to be brain damaged. 322167468Snon * Force async transfer. 322267468Snon */ 322373025Snon ti->ti_maxsynch.period = 0; 322473025Snon ti->ti_maxsynch.offset = 0; 3225240325Sjhb device_printf(slp->sl_dev, 3226240325Sjhb "target brain damaged. async transfer\n"); 322767468Snon return EINVAL; 322867468Snon } 322967468Snon 323073025Snon ti->ti_maxsynch.period = period; 323173025Snon ti->ti_maxsynch.offset = offset; 323267468Snon 323367468Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_SYNCH); 323467468Snon if (error != 0) 323567468Snon { 323667468Snon /* XXX: 323767468Snon * Current period and offset are not acceptable 323867468Snon * for our adapter. 323967468Snon * The adapter changes max synch and max offset. 324067468Snon */ 3241240325Sjhb device_printf(slp->sl_dev, 3242240325Sjhb "synch neg failed. retry synch msg neg ...\n"); 324367468Snon return error; 324467468Snon } 324567468Snon 324679697Snon ti->ti_osynch = ti->ti_maxsynch; 324779697Snon if (offset > 0) 324879697Snon { 324979697Snon ti->ti_setup_msg_done |= SCSI_LOW_MSG_SYNCH; 325079697Snon } 325179697Snon 325267468Snon /* inform data */ 325379697Snon if ((slp->sl_show_result & SHOW_SYNCH_NEG) != 0) 325467468Snon { 325579697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 325679697Snon struct slccb *cb = slp->sl_Qnexus; 325779697Snon 325879697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 325979697Snon return 0; 326079697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 326179697Snon 3262240325Sjhb device_printf(slp->sl_dev, 3263240325Sjhb "(%d:*): <%s> offset %d period %dns ", 3264240325Sjhb ti->ti_id, s, offset, period * 4); 326579697Snon 326679697Snon if (period != 0) 326779697Snon { 326879697Snon speed = 1000 * 10 / (period * 4); 326979697Snon printf("%d.%d M/s", speed / 10, speed % 10); 327079697Snon } 327179697Snon printf("\n"); 327267468Snon } 327379697Snon return 0; 327479697Snon} 327567468Snon 327679697Snonstatic int 327779697Snonscsi_low_wide(slp) 327879697Snon struct scsi_low_softc *slp; 327979697Snon{ 328079697Snon struct targ_info *ti = slp->sl_Tnexus; 328179697Snon int error; 328279697Snon 328379697Snon ti->ti_width = MSGIN_WIDTHP(ti); 328479697Snon error = (*slp->sl_funcs->scsi_low_msg) (slp, ti, SCSI_LOW_MSG_WIDE); 328579697Snon if (error != 0) 328679697Snon { 328779697Snon /* XXX: 328879697Snon * Current width is not acceptable for our adapter. 328979697Snon * The adapter changes max width. 329079697Snon */ 3291240325Sjhb device_printf(slp->sl_dev, 3292240325Sjhb "wide neg failed. retry wide msg neg ...\n"); 329379697Snon return error; 329479697Snon } 329579697Snon 329679697Snon ti->ti_owidth = ti->ti_width; 329779697Snon if (ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 329879697Snon { 329979697Snon ti->ti_setup_msg_done |= 330079697Snon (SCSI_LOW_MSG_SYNCH | SCSI_LOW_MSG_WIDE); 330179697Snon } 330279697Snon 330379697Snon /* inform data */ 330479697Snon if ((slp->sl_show_result & SHOW_WIDE_NEG) != 0) 330579697Snon { 330679697Snon#ifdef SCSI_LOW_NEGOTIATE_BEFORE_SENSE 330779697Snon struct slccb *cb = slp->sl_Qnexus; 330879697Snon 330979697Snon if (cb != NULL && (cb->ccb_flags & CCB_SENSE) != 0) 331079697Snon return 0; 331179697Snon#endif /* SCSI_LOW_NEGOTIATE_BEFORE_SENSE */ 331279697Snon 3313240325Sjhb device_printf(slp->sl_dev, "(%d:*): transfer width %d bits\n", 3314240325Sjhb ti->ti_id, 1 << (3 + ti->ti_width)); 331579697Snon } 331667468Snon return 0; 331767468Snon} 331867468Snon 331967468Snonstatic int 332079697Snonscsi_low_msginfunc_simple_qtag(slp) 332179697Snon struct scsi_low_softc *slp; 332267468Snon{ 332379697Snon struct targ_info *ti = slp->sl_Tnexus; 332479697Snon scsi_low_tag_t etag = (scsi_low_tag_t) ti->ti_msgin[1]; 332579697Snon 332679697Snon if (slp->sl_Qnexus != NULL) 332779697Snon { 332879697Snon if (slp->sl_Qnexus->ccb_tag != etag) 332979697Snon { 333079697Snon slp->sl_error |= FATALIO; 333179697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 333279697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: qtag mismatch"); 333379697Snon } 333479697Snon } 333579697Snon else if (scsi_low_establish_ccb(ti, slp->sl_Lnexus, etag) == NULL) 333679697Snon { 333779697Snon#ifdef SCSI_LOW_DEBUG 333879697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id)) 333979697Snon return 0; 334079697Snon#endif /* SCSI_LOW_DEBUG */ 334179697Snon 334279697Snon slp->sl_error |= FATALIO; 334379697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT_QTAG, 0); 334479697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: taged ccb not found"); 334579697Snon } 334679697Snon return 0; 334779697Snon} 334879697Snon 334979697Snonstatic int 335079697Snonscsi_low_msginfunc_i_wide_residue(slp) 335179697Snon struct scsi_low_softc *slp; 335279697Snon{ 335379697Snon struct targ_info *ti = slp->sl_Tnexus; 335479697Snon struct slccb *cb = slp->sl_Qnexus; 335579697Snon int res = (int) ti->ti_msgin[1]; 335679697Snon 335779697Snon if (cb == NULL || res <= 0 || 335879697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_16 && res > 1) || 335979697Snon (ti->ti_width == SCSI_LOW_BUS_WIDTH_32 && res > 3)) 336079697Snon return EINVAL; 336179697Snon 336279697Snon if (slp->sl_scp.scp_datalen + res > cb->ccb_scp.scp_datalen) 336379697Snon return EINVAL; 336479697Snon 336579697Snon slp->sl_scp.scp_datalen += res; 336679697Snon slp->sl_scp.scp_data -= res; 336779697Snon scsi_low_data_finish(slp); 336879697Snon return 0; 336979697Snon} 337079697Snon 337179697Snonstatic int 337279697Snonscsi_low_msginfunc_ext(slp) 337379697Snon struct scsi_low_softc *slp; 337479697Snon{ 337579697Snon struct slccb *cb = slp->sl_Qnexus; 337679697Snon struct lun_info *li = slp->sl_Lnexus; 337779697Snon struct targ_info *ti = slp->sl_Tnexus; 337867468Snon int count, retry; 337967468Snon u_int32_t *ptr; 338067468Snon 338167468Snon if (ti->ti_msginptr == 2) 338267468Snon { 338367468Snon ti->ti_msginlen = ti->ti_msgin[1] + 2; 338467468Snon return 0; 338567468Snon } 338667468Snon 338767468Snon switch (MKMSG_EXTEND(ti->ti_msgin[1], ti->ti_msgin[2])) 338867468Snon { 338967468Snon case MKMSG_EXTEND(MSG_EXTEND_MDPLEN, MSG_EXTEND_MDPCODE): 339067468Snon if (cb == NULL) 339167468Snon break; 339267468Snon 339367468Snon ptr = (u_int32_t *)(&ti->ti_msgin[3]); 339467468Snon count = (int) htonl((long) (*ptr)); 339567468Snon if(slp->sl_scp.scp_datalen - count < 0 || 339667468Snon slp->sl_scp.scp_datalen - count > cb->ccb_scp.scp_datalen) 339767468Snon break; 339867468Snon 339967468Snon slp->sl_scp.scp_datalen -= count; 340067468Snon slp->sl_scp.scp_data += count; 340167468Snon return 0; 340267468Snon 340367468Snon case MKMSG_EXTEND(MSG_EXTEND_SYNCHLEN, MSG_EXTEND_SYNCHCODE): 340467468Snon if (li == NULL) 340567468Snon break; 340667468Snon 340779697Snon retry = scsi_low_synch(slp); 340867468Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_SYNCH) == 0) 340967468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_SYNCH, 0); 341079697Snon 341179697Snon#ifdef SCSI_LOW_DEBUG 341279697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 341379697Snon { 341479697Snon scsi_low_test_atten(slp, ti, SCSI_LOW_MSG_SYNCH); 341579697Snon } 341679697Snon#endif /* SCSI_LOW_DEBUG */ 341767468Snon return 0; 341867468Snon 341967468Snon case MKMSG_EXTEND(MSG_EXTEND_WIDELEN, MSG_EXTEND_WIDECODE): 342067468Snon if (li == NULL) 342167468Snon break; 342267468Snon 342379697Snon retry = scsi_low_wide(slp); 342479697Snon if (retry != 0 || (ti->ti_emsgflags & SCSI_LOW_MSG_WIDE) == 0) 342579697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_WIDE, 0); 342679697Snon 342767468Snon return 0; 342867468Snon 342967468Snon default: 343067468Snon break; 343167468Snon } 343267468Snon 343367468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 343467468Snon return EINVAL; 343567468Snon} 343667468Snon 343767468Snonstatic int 343879697Snonscsi_low_msginfunc_parity(slp) 343979697Snon struct scsi_low_softc *slp; 344067468Snon{ 344179697Snon struct targ_info *ti = slp->sl_Tnexus; 344267468Snon 344379697Snon /* only I -> T, invalid! */ 344479697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 344567468Snon return 0; 344667468Snon} 344767468Snon 344867468Snonstatic int 344979697Snonscsi_low_msginfunc_msg_reject(slp) 345079697Snon struct scsi_low_softc *slp; 345167468Snon{ 345279697Snon struct targ_info *ti = slp->sl_Tnexus; 345367468Snon struct scsi_low_msgout_data *mdp; 345467468Snon u_int msgflags; 345567468Snon 345679697Snon if (ti->ti_emsgflags != 0) 345767468Snon { 3458240325Sjhb device_printf(slp->sl_dev, "msg flags [0x%x] rejected\n", 3459240325Sjhb ti->ti_emsgflags); 346067468Snon msgflags = SCSI_LOW_MSG_REJECT; 346167468Snon mdp = &scsi_low_msgout_data[0]; 346267468Snon for ( ; mdp->md_flags != SCSI_LOW_MSG_ALL; mdp ++) 346367468Snon { 346467468Snon if ((ti->ti_emsgflags & mdp->md_flags) != 0) 346567468Snon { 346667468Snon ti->ti_emsgflags &= ~mdp->md_flags; 346767468Snon if (mdp->md_errfunc != NULL) 346879697Snon (*mdp->md_errfunc) (slp, msgflags); 346967468Snon break; 347067468Snon } 347167468Snon } 347279697Snon return 0; 347367468Snon } 347479697Snon else 347579697Snon { 347679697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: rejected msg not found"); 347779697Snon slp->sl_error |= MSGERR; 347879697Snon } 347979697Snon return EINVAL; 348067468Snon} 348167468Snon 348279697Snonint 348367468Snonscsi_low_msgin(slp, ti, c) 348467468Snon struct scsi_low_softc *slp; 348567468Snon struct targ_info *ti; 348679697Snon u_int c; 348767468Snon{ 348867468Snon struct scsi_low_msgin_data *sdp; 348967468Snon struct lun_info *li; 349067468Snon u_int8_t msg; 349167468Snon 349279697Snon#ifdef SCSI_LOW_DIAGNOSTIC 349379697Snon if (ti != slp->sl_Tnexus) 349479697Snon { 349579697Snon scsi_low_print(slp, NULL); 349679697Snon panic("scsi_low_msgin: Target nexus inconsistent"); 349779697Snon } 349879697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 349979697Snon 350067468Snon /* 350167468Snon * Phase changes, clear the pointer. 350267468Snon */ 350367468Snon if (ti->ti_ophase != ti->ti_phase) 350467468Snon { 350567468Snon MSGINPTR_CLR(ti); 350679697Snon ti->ti_msgin_parity_error = 0; 350779697Snon 350879697Snon slp->sl_ph_count ++; 350979697Snon if (slp->sl_ph_count > SCSI_LOW_MAX_PHCHANGES) 351079697Snon { 3511240325Sjhb device_printf(slp->sl_dev, "too many phase changes\n"); 351279697Snon slp->sl_error |= FATALIO; 351379697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 351479697Snon } 351567468Snon } 351667468Snon 351767468Snon /* 351867468Snon * Store a current messages byte into buffer and 351967468Snon * wait for the completion of the current msg. 352067468Snon */ 352179697Snon ti->ti_msgin[ti->ti_msginptr ++] = (u_int8_t) c; 352267468Snon if (ti->ti_msginptr >= SCSI_LOW_MAX_MSGLEN) 352367468Snon { 352467468Snon ti->ti_msginptr = SCSI_LOW_MAX_MSGLEN - 1; 352567468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_REJECT, 0); 352667468Snon } 352767468Snon 352867468Snon /* 352979697Snon * Check parity errors. 353079697Snon */ 353179697Snon if ((c & SCSI_LOW_DATA_PE) != 0) 353279697Snon { 353379697Snon ti->ti_msgin_parity_error ++; 353479697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0); 353579697Snon goto out; 353679697Snon } 353779697Snon 353879697Snon if (ti->ti_msgin_parity_error != 0) 353979697Snon goto out; 354079697Snon 354179697Snon /* 354267468Snon * Calculate messages length. 354367468Snon */ 354467468Snon msg = ti->ti_msgin[0]; 354567468Snon if (msg < MSGIN_DATA_LAST) 354667468Snon sdp = &scsi_low_msgin_data[msg]; 354767468Snon else 354867468Snon sdp = &scsi_low_msgin_data[MSGIN_DATA_LAST]; 354967468Snon 355067468Snon if (ti->ti_msginlen == 0) 355167468Snon { 355267468Snon ti->ti_msginlen = sdp->md_len; 355367468Snon } 355467468Snon 355567468Snon /* 355667468Snon * Check comletion. 355767468Snon */ 355867468Snon if (ti->ti_msginptr < ti->ti_msginlen) 355979697Snon return EJUSTRETURN; 356067468Snon 356167468Snon /* 356267468Snon * Do process. 356367468Snon */ 356467468Snon if ((msg & MSG_IDENTIFY) == 0) 356567468Snon { 356679697Snon if (((*sdp->md_msgfunc) (slp)) == EJUSTRETURN) 356779697Snon return EJUSTRETURN; 356867468Snon } 356967468Snon else 357067468Snon { 357179697Snon li = slp->sl_Lnexus; 357267468Snon if (li == NULL) 357367468Snon { 357479697Snon li = scsi_low_alloc_li(ti, MSGCMD_LUN(msg), 0); 357567468Snon if (li == NULL) 357667468Snon goto badlun; 357779697Snon slp->sl_Lnexus = li; 357879697Snon (*slp->sl_funcs->scsi_low_establish_lun_nexus) (slp); 357967468Snon } 358079697Snon else 358179697Snon { 358279697Snon if (MSGCMD_LUN(msg) != li->li_lun) 358379697Snon goto badlun; 358479697Snon } 358567468Snon 358679697Snon if (slp->sl_Qnexus == NULL && li->li_nqio == 0) 358767468Snon { 358867468Snon if (!scsi_low_establish_ccb(ti, li, SCSI_LOW_UNKTAG)) 358979697Snon { 359079697Snon#ifdef SCSI_LOW_DEBUG 359179697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_NEXUS_CHECK, ti->ti_id) != 0) 359279697Snon { 359379697Snon goto out; 359479697Snon } 359579697Snon#endif /* SCSI_LOW_DEBUG */ 359667468Snon goto badlun; 359779697Snon } 359867468Snon } 359967468Snon } 360079697Snon goto out; 360167468Snon 360267468Snon /* 360379697Snon * Msg process completed, reset msgin pointer and assert ATN if desired. 360467468Snon */ 360579697Snonbadlun: 360679697Snon slp->sl_error |= FATALIO; 360779697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 0); 360879697Snon SCSI_LOW_INFO(slp, ti, "MSGIN: identify wrong"); 360979697Snon 361079697Snonout: 361179697Snon if (ti->ti_msginptr < ti->ti_msginlen) 361279697Snon return EJUSTRETURN; 361379697Snon 361479697Snon#ifdef SCSI_LOW_DIAGNOSTIC 361579697Snon scsi_low_msg_log_write(&ti->ti_log_msgin, 361679697Snon &ti->ti_msgin[0], ti->ti_msginlen); 361779697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 361879697Snon 361979697Snon MSGINPTR_CLR(ti); 362079697Snon return 0; 362179697Snon} 362279697Snon 362379697Snon/********************************************************** 362479697Snon * disconnect 362579697Snon **********************************************************/ 362679697Snonint 362779697Snonscsi_low_disconnected(slp, ti) 362879697Snon struct scsi_low_softc *slp; 362979697Snon struct targ_info *ti; 363079697Snon{ 363179697Snon struct slccb *cb = slp->sl_Qnexus; 363279697Snon 363379697Snon /* check phase completion */ 363479697Snon switch (slp->sl_msgphase) 363567468Snon { 363679697Snon case MSGPH_RESET: 363779697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 363879697Snon scsi_low_msginfunc_cc(slp); 363979697Snon scsi_low_reset_nexus_target(slp, slp->sl_Tnexus, 0); 364079697Snon goto io_resume; 364167468Snon 364279697Snon case MSGPH_ABORT: 364379697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 364479697Snon scsi_low_msginfunc_cc(slp); 364579697Snon scsi_low_reset_nexus_lun(slp, slp->sl_Lnexus, 0); 364679697Snon goto io_resume; 364779697Snon 364879697Snon case MSGPH_TERM: 364979697Snon scsi_low_statusin(slp, slp->sl_Tnexus, ST_GOOD); 365079697Snon scsi_low_msginfunc_cc(slp); 365179697Snon goto io_resume; 365279697Snon 365379697Snon case MSGPH_DISC: 365479697Snon if (cb != NULL) 365567468Snon { 365679697Snon struct lun_info *li; 365779697Snon 365879697Snon li = cb->li; 365979697Snon TAILQ_INSERT_TAIL(&li->li_discq, cb, ccb_chain); 366079697Snon cb->ccb_flags |= CCB_DISCQ; 366179697Snon cb->ccb_error |= slp->sl_error; 366279697Snon li->li_disc ++; 366379697Snon ti->ti_disc ++; 366479697Snon slp->sl_disc ++; 366579697Snon } 366679697Snon 366779697Snon#ifdef SCSI_LOW_STATICS 366879697Snon scsi_low_statics.nexus_disconnected ++; 366979697Snon#endif /* SCSI_LOW_STATICS */ 367079697Snon 367179697Snon#ifdef SCSI_LOW_DEBUG 367279697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_DISC, ti->ti_id) != 0) 367379697Snon { 367479697Snon printf("## SCSI_LOW_DISCONNECTED ===============\n"); 367579697Snon scsi_low_print(slp, NULL); 367679697Snon } 367779697Snon#endif /* SCSI_LOW_DEBUG */ 367879697Snon break; 367979697Snon 368079697Snon case MSGPH_NULL: 368179697Snon slp->sl_error |= FATALIO; 368279697Snon if (ti->ti_phase == PH_SELSTART) 368379697Snon slp->sl_error |= SELTIMEOUTIO; 368479697Snon else 368579697Snon slp->sl_error |= UBFERR; 368679697Snon /* fall through */ 368779697Snon 368879697Snon case MSGPH_LCTERM: 368979697Snon case MSGPH_CMDC: 369079697Snonio_resume: 369179697Snon if (cb == NULL) 369279697Snon break; 369379697Snon 369479697Snon#ifdef SCSI_LOW_DEBUG 369579697Snon if (SCSI_LOW_DEBUG_TEST_GO(SCSI_LOW_ATTEN_CHECK, ti->ti_id)) 369679697Snon { 369779697Snon if (cb->ccb_omsgoutflag == SCSI_LOW_MSG_NOOP && 369879697Snon (cb->ccb_msgoutflag != 0 || 369979697Snon (ti->ti_msgflags & SCSI_LOW_MSG_NOOP))) 370079697Snon { 370179697Snon scsi_low_info(slp, ti, "ATTEN CHECK FAILED"); 370279697Snon } 370379697Snon } 370479697Snon#endif /* SCSI_LOW_DEBUG */ 370579697Snon 370679697Snon cb->ccb_error |= slp->sl_error; 370779697Snon if (scsi_low_done(slp, cb) == SCSI_LOW_DONE_RETRY) 370879697Snon { 370979697Snon cb->ccb_flags |= CCB_STARTQ; 371079697Snon TAILQ_INSERT_HEAD(&slp->sl_start, cb, ccb_chain); 371179697Snon } 371279697Snon break; 371379697Snon } 371479697Snon 371579697Snon scsi_low_bus_release(slp, ti); 371679697Snon scsi_low_start(slp); 371779697Snon return 1; 371879697Snon} 371979697Snon 372079697Snon/********************************************************** 372179697Snon * TAG operations 372279697Snon **********************************************************/ 3723104094Sphkstatic int 372479697Snonscsi_low_alloc_qtag(cb) 372579697Snon struct slccb *cb; 372679697Snon{ 372779697Snon struct lun_info *li = cb->li; 372879697Snon scsi_low_tag_t etag; 372979697Snon 373079697Snon if (cb->ccb_otag != SCSI_LOW_UNKTAG) 373179697Snon return 0; 373279697Snon 373379697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 373479697Snon etag = ffs(li->li_qtagbits); 373579697Snon if (etag == 0) 373679697Snon return ENOSPC; 373779697Snon 373879697Snon li->li_qtagbits &= ~(1 << (etag - 1)); 373979697Snon cb->ccb_otag = etag; 374079697Snon return 0; 374179697Snon 374279697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 374379697Snon for (etag = li->li_qd ; li->li_qd < SCSI_LOW_MAXNEXUS; li->li_qd ++) 374479697Snon if (li->li_qtagarray[li->li_qd] == 0) 374579697Snon goto found; 374679697Snon 374779697Snon for (li->li_qd = 0; li->li_qd < etag; li->li_qd ++) 374879697Snon if (li->li_qtagarray[li->li_qd] == 0) 374979697Snon goto found; 375079697Snon 375179697Snon return ENOSPC; 375279697Snon 375379697Snonfound: 375479697Snon li->li_qtagarray[li->li_qd] ++; 375579697Snon cb->ccb_otag = (li->li_qd ++); 375679697Snon return 0; 375779697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 375879697Snon} 375979697Snon 3760104094Sphkstatic int 376179697Snonscsi_low_dealloc_qtag(cb) 376279697Snon struct slccb *cb; 376379697Snon{ 376479697Snon struct lun_info *li = cb->li; 376579697Snon scsi_low_tag_t etag; 376679697Snon 376779697Snon if (cb->ccb_otag == SCSI_LOW_UNKTAG) 376879697Snon return 0; 376979697Snon 377079697Snon#ifndef SCSI_LOW_ALT_QTAG_ALLOCATE 377179697Snon etag = cb->ccb_otag - 1; 377267468Snon#ifdef SCSI_LOW_DIAGNOSTIC 377379697Snon if (etag >= sizeof(li->li_qtagbits) * NBBY) 377479697Snon panic("scsi_low_dealloc_tag: illegal tag"); 377567468Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 377679697Snon li->li_qtagbits |= (1 << etag); 377779697Snon 377879697Snon#else /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 377979697Snon etag = cb->ccb_otag; 378079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 378179697Snon if (etag >= SCSI_LOW_MAXNEXUS) 378279697Snon panic("scsi_low_dealloc_tag: illegal tag"); 378379697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 378479697Snon li->li_qtagarray[etag] --; 378579697Snon#endif /* SCSI_LOW_ALT_QTAG_ALLOCATE */ 378679697Snon 378779697Snon cb->ccb_otag = SCSI_LOW_UNKTAG; 378879697Snon return 0; 378979697Snon} 379079697Snon 3791104094Sphkstatic struct slccb * 379279697Snonscsi_low_revoke_ccb(slp, cb, fdone) 379379697Snon struct scsi_low_softc *slp; 379479697Snon struct slccb *cb; 379579697Snon int fdone; 379679697Snon{ 379779697Snon struct targ_info *ti = cb->ti; 379879697Snon struct lun_info *li = cb->li; 379979697Snon 380079697Snon#ifdef SCSI_LOW_DIAGNOSTIC 380179697Snon if ((cb->ccb_flags & (CCB_STARTQ | CCB_DISCQ)) == 380279697Snon (CCB_STARTQ | CCB_DISCQ)) 380379697Snon { 3804240325Sjhb panic("%s: ccb in both queue", 3805240325Sjhb device_get_nameunit(slp->sl_dev)); 380667468Snon } 380779697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 380867468Snon 380979697Snon if ((cb->ccb_flags & CCB_STARTQ) != 0) 381079697Snon { 381179697Snon TAILQ_REMOVE(&slp->sl_start, cb, ccb_chain); 381279697Snon } 381379697Snon 381479697Snon if ((cb->ccb_flags & CCB_DISCQ) != 0) 381579697Snon { 381679697Snon TAILQ_REMOVE(&li->li_discq, cb, ccb_chain); 381779697Snon li->li_disc --; 381879697Snon ti->ti_disc --; 381979697Snon slp->sl_disc --; 382079697Snon } 382179697Snon 382279697Snon cb->ccb_flags &= ~(CCB_STARTQ | CCB_DISCQ | 382379697Snon CCB_SENSE | CCB_CLEARQ | CCB_INTERNAL); 382479697Snon 382579697Snon if (fdone != 0 && 382679697Snon (cb->ccb_rcnt ++ >= slp->sl_max_retry || 382779697Snon (cb->ccb_flags & CCB_NORETRY) != 0)) 382879697Snon { 382979697Snon cb->ccb_error |= FATALIO; 383079697Snon cb->ccb_flags &= ~CCB_AUTOSENSE; 383179697Snon if (scsi_low_done(slp, cb) != SCSI_LOW_DONE_COMPLETE) 3832240325Sjhb panic("%s: done ccb retried", 3833240325Sjhb device_get_nameunit(slp->sl_dev)); 383479697Snon return NULL; 383579697Snon } 383679697Snon else 383779697Snon { 383879697Snon cb->ccb_error |= PENDINGIO; 383979697Snon scsi_low_deactivate_qtag(cb); 384079697Snon scsi_low_ccb_message_retry(cb); 384179697Snon cb->ccb_tc = cb->ccb_tcmax = SCSI_LOW_MIN_TOUT; 384279697Snon return cb; 384379697Snon } 384467468Snon} 384567468Snon 3846104094Sphkstatic void 384779697Snonscsi_low_reset_nexus_lun(slp, li, fdone) 384879697Snon struct scsi_low_softc *slp; 384979697Snon struct lun_info *li; 385079697Snon int fdone; 385179697Snon{ 385279697Snon struct slccb *cb, *ncb, *ecb; 385379697Snon 385479697Snon if (li == NULL) 385579697Snon return; 385679697Snon 385779697Snon ecb = NULL; 385879697Snon for (cb = TAILQ_FIRST(&li->li_discq); cb != NULL; cb = ncb) 385979697Snon { 386079697Snon ncb = TAILQ_NEXT(cb, ccb_chain); 386179697Snon cb = scsi_low_revoke_ccb(slp, cb, fdone); 386279697Snon if (cb != NULL) 386379697Snon { 386479697Snon /* 386579697Snon * presumely keep ordering of io 386679697Snon */ 386779697Snon cb->ccb_flags |= CCB_STARTQ; 386879697Snon if (ecb == NULL) 386979697Snon { 387079697Snon TAILQ_INSERT_HEAD(&slp->sl_start,\ 387179697Snon cb, ccb_chain); 387279697Snon } 387379697Snon else 387479697Snon { 387579697Snon TAILQ_INSERT_AFTER(&slp->sl_start,\ 387679697Snon ecb, cb, ccb_chain); 387779697Snon } 387879697Snon ecb = cb; 387979697Snon } 388079697Snon } 388179697Snon} 388279697Snon 388367468Snon/************************************************************** 388467468Snon * Qurik setup 388567468Snon **************************************************************/ 388667468Snonstatic void 388779697Snonscsi_low_calcf_lun(li) 388867468Snon struct lun_info *li; 388967468Snon{ 389079697Snon struct targ_info *ti = li->li_ti; 389167468Snon struct scsi_low_softc *slp = ti->ti_sc; 389279697Snon u_int cfgflags, diskflags; 389367468Snon 389479697Snon if (li->li_flags_valid == SCSI_LOW_LUN_FLAGS_ALL_VALID) 389579697Snon cfgflags = li->li_cfgflags; 389679697Snon else 389779697Snon cfgflags = 0; 389879697Snon 389979697Snon diskflags = li->li_diskflags & li->li_quirks; 390079697Snon 390179697Snon /* disconnect */ 390267468Snon li->li_flags &= ~SCSI_LOW_DISC; 390367468Snon if ((slp->sl_cfgflags & CFG_NODISC) == 0 && 390479697Snon (diskflags & SCSI_LOW_DISK_DISC) != 0 && 390579697Snon (cfgflags & SCSI_LOW_DISC) != 0) 390667468Snon li->li_flags |= SCSI_LOW_DISC; 390767468Snon 390879697Snon /* parity */ 390967468Snon li->li_flags |= SCSI_LOW_NOPARITY; 391067468Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0 && 391179697Snon (diskflags & SCSI_LOW_DISK_PARITY) != 0 && 391279697Snon (cfgflags & SCSI_LOW_NOPARITY) == 0) 391367468Snon li->li_flags &= ~SCSI_LOW_NOPARITY; 391467468Snon 391579697Snon /* qtag */ 391679697Snon if ((slp->sl_cfgflags & CFG_NOQTAG) == 0 && 391779697Snon (cfgflags & SCSI_LOW_QTAG) != 0 && 391879697Snon (diskflags & SCSI_LOW_DISK_QTAG) != 0) 391979697Snon { 392079697Snon li->li_flags |= SCSI_LOW_QTAG; 392179697Snon li->li_maxnexus = SCSI_LOW_MAXNEXUS; 392279697Snon li->li_maxnqio = li->li_maxnexus; 392379697Snon } 392479697Snon else 392579697Snon { 392679697Snon li->li_flags &= ~SCSI_LOW_QTAG; 392779697Snon li->li_maxnexus = 0; 392879697Snon li->li_maxnqio = li->li_maxnexus; 392979697Snon } 393079697Snon 393179697Snon /* cmd link */ 393279697Snon li->li_flags &= ~SCSI_LOW_LINK; 393379697Snon if ((cfgflags & SCSI_LOW_LINK) != 0 && 393479697Snon (diskflags & SCSI_LOW_DISK_LINK) != 0) 393579697Snon li->li_flags |= SCSI_LOW_LINK; 393679697Snon 393779697Snon /* compatible flags */ 393867468Snon li->li_flags &= ~SCSI_LOW_SYNC; 393979697Snon if (ti->ti_maxsynch.offset > 0) 394079697Snon li->li_flags |= SCSI_LOW_SYNC; 394179697Snon 394279697Snon#ifdef SCSI_LOW_DEBUG 394379697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 394467468Snon { 394579697Snon scsi_low_calcf_show(li); 394667468Snon } 394779697Snon#endif /* SCSI_LOW_DEBUG */ 394879697Snon} 394979697Snon 395079697Snonstatic void 395179697Snonscsi_low_calcf_target(ti) 395279697Snon struct targ_info *ti; 395379697Snon{ 395479697Snon struct scsi_low_softc *slp = ti->ti_sc; 395579697Snon u_int offset, period, diskflags; 395679697Snon 395779697Snon diskflags = ti->ti_diskflags & ti->ti_quirks; 395879697Snon 395979697Snon /* synch */ 396079697Snon if ((slp->sl_cfgflags & CFG_ASYNC) == 0 && 396179697Snon (diskflags & SCSI_LOW_DISK_SYNC) != 0) 396279697Snon { 396379697Snon offset = ti->ti_maxsynch.offset; 396479697Snon period = ti->ti_maxsynch.period; 396579697Snon if (offset == 0 || period == 0) 396679697Snon offset = period = 0; 396779697Snon } 396867468Snon else 396979697Snon { 397079697Snon offset = period = 0; 397179697Snon } 397267468Snon 397379697Snon ti->ti_maxsynch.offset = offset; 397479697Snon ti->ti_maxsynch.period = period; 397579697Snon 397679697Snon /* wide */ 397779697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_32) == 0 && 397879697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_16) 397979697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_16; 398079697Snon 398179697Snon if ((diskflags & SCSI_LOW_DISK_WIDE_16) == 0 && 398279697Snon ti->ti_width > SCSI_LOW_BUS_WIDTH_8) 398379697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 398479697Snon 398579697Snon if (ti->ti_flags_valid == SCSI_LOW_TARG_FLAGS_ALL_VALID) 398667468Snon { 398779697Snon if (ti->ti_maxsynch.offset != ti->ti_osynch.offset || 398879697Snon ti->ti_maxsynch.period != ti->ti_osynch.period) 398979697Snon ti->ti_setup_msg |= SCSI_LOW_MSG_SYNCH; 399079697Snon if (ti->ti_width != ti->ti_owidth) 399179697Snon ti->ti_setup_msg |= (SCSI_LOW_MSG_WIDE | SCSI_LOW_MSG_SYNCH); 399279697Snon 399379697Snon ti->ti_osynch = ti->ti_maxsynch; 399479697Snon ti->ti_owidth = ti->ti_width; 399567468Snon } 399667468Snon 399779697Snon#ifdef SCSI_LOW_DEBUG 399879697Snon if (SCSI_LOW_DEBUG_GO(SCSI_LOW_DEBUG_CALCF, ti->ti_id) != 0) 399979697Snon { 4000240325Sjhb device_printf(slp->sl_dev, 4001240325Sjhb "(%d:*): max period(%dns) offset(%d) width(%d)\n", 4002240325Sjhb ti->ti_id, 400379697Snon ti->ti_maxsynch.period * 4, 400479697Snon ti->ti_maxsynch.offset, 400579697Snon ti->ti_width); 400679697Snon } 400779697Snon#endif /* SCSI_LOW_DEBUG */ 400867468Snon} 400967468Snon 401079697Snonstatic void 401179697Snonscsi_low_calcf_show(li) 401279697Snon struct lun_info *li; 401379697Snon{ 401479697Snon struct targ_info *ti = li->li_ti; 401579697Snon struct scsi_low_softc *slp = ti->ti_sc; 401679697Snon 4017240325Sjhb device_printf(slp->sl_dev, 4018240325Sjhb "(%d:%d): period(%d ns) offset(%d) width(%d) flags 0x%b\n", 4019240325Sjhb ti->ti_id, li->li_lun, 402079697Snon ti->ti_maxsynch.period * 4, 402179697Snon ti->ti_maxsynch.offset, 402279697Snon ti->ti_width, 402379697Snon li->li_flags, SCSI_LOW_BITS); 402479697Snon} 402579697Snon 402679697Snon#ifdef SCSI_LOW_START_UP_CHECK 402779697Snon/************************************************************** 402879697Snon * scsi world start up 402979697Snon **************************************************************/ 403092770Salfredstatic int scsi_low_poll(struct scsi_low_softc *, struct slccb *); 403179697Snon 403267468Snonstatic int 403379697Snonscsi_low_start_up(slp) 403479697Snon struct scsi_low_softc *slp; 403567468Snon{ 403667468Snon struct targ_info *ti; 403767468Snon struct lun_info *li; 403879697Snon struct slccb *cb; 403979697Snon int target, lun; 404067468Snon 4041240325Sjhb device_printf(slp->sl_dev, "scsi_low: probing all devices ....\n"); 404267468Snon 404379697Snon for (target = 0; target < slp->sl_ntargs; target ++) 404479697Snon { 404579697Snon if (target == slp->sl_hostid) 404679697Snon { 404779697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 404879697Snon { 4049240325Sjhb device_printf(slp->sl_dev, 4050240325Sjhb "scsi_low: target %d (host card)\n", 4051240325Sjhb target); 405279697Snon } 405379697Snon continue; 405479697Snon } 405567468Snon 405679697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 405779697Snon { 4058240325Sjhb device_printf(slp->sl_dev, "scsi_low: target %d lun ", 4059240325Sjhb target); 406079697Snon } 406167468Snon 406279697Snon ti = slp->sl_ti[target]; 406379697Snon for (lun = 0; lun < slp->sl_nluns; lun ++) 406479697Snon { 406579697Snon if ((cb = SCSI_LOW_ALLOC_CCB(1)) == NULL) 406679697Snon break; 406779697Snon 406879697Snon cb->osdep = NULL; 406979697Snon cb->bp = NULL; 407079697Snon 407179697Snon li = scsi_low_alloc_li(ti, lun, 1); 407279697Snon 407379697Snon scsi_low_enqueue(slp, ti, li, cb, 407479697Snon CCB_AUTOSENSE | CCB_POLLED, 0); 407579697Snon 407679697Snon scsi_low_poll(slp, cb); 407779697Snon 407879697Snon if (li->li_state != SCSI_LOW_LUN_OK) 407979697Snon break; 408079697Snon 408179697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 408279697Snon { 408379697Snon printf("%d ", lun); 408479697Snon } 408579697Snon } 408679697Snon 408779697Snon if ((slp->sl_show_result & SHOW_PROBE_RES) != 0) 408879697Snon { 408979697Snon printf("\n"); 409079697Snon } 409179697Snon } 409267468Snon return 0; 409367468Snon} 409467468Snon 409579697Snonstatic int 409679697Snonscsi_low_poll(slp, cb) 409779697Snon struct scsi_low_softc *slp; 409879697Snon struct slccb *cb; 409979697Snon{ 410079697Snon int tcount; 410179697Snon 410279697Snon tcount = 0; 410379697Snon while (slp->sl_nio > 0) 410479697Snon { 4105240172Sjhb DELAY((1000 * 1000) / SCSI_LOW_POLL_HZ); 410679697Snon 410779697Snon (*slp->sl_funcs->scsi_low_poll) (slp); 410879697Snon if (tcount ++ < SCSI_LOW_POLL_HZ / SCSI_LOW_TIMEOUT_HZ) 410979697Snon continue; 411079697Snon 411179697Snon tcount = 0; 411279697Snon scsi_low_timeout_check(slp); 411379697Snon } 411479697Snon 411579697Snon return 0; 411679697Snon} 411779697Snon#endif /* SCSI_LOW_START_UP_CHECK */ 411879697Snon 411967468Snon/********************************************************** 412067468Snon * DEBUG SECTION 412167468Snon **********************************************************/ 412279697Snon#ifdef SCSI_LOW_DEBUG 412367468Snonstatic void 412479697Snonscsi_low_test_abort(slp, ti, li) 412579697Snon struct scsi_low_softc *slp; 412679697Snon struct targ_info *ti; 412779697Snon struct lun_info *li; 412879697Snon{ 412979697Snon struct slccb *acb; 413079697Snon 413179697Snon if (li->li_disc > 1) 413279697Snon { 413379697Snon acb = TAILQ_FIRST(&li->li_discq); 413479697Snon if (scsi_low_abort_ccb(slp, acb) == 0) 413579697Snon { 4136240325Sjhb device_printf(slp->sl_dev, 4137240325Sjhb "aborting ccb(0x%lx) start\n", (u_long) acb); 413879697Snon } 413979697Snon } 414079697Snon} 414179697Snon 414279697Snonstatic void 414379697Snonscsi_low_test_atten(slp, ti, msg) 414479697Snon struct scsi_low_softc *slp; 414579697Snon struct targ_info *ti; 414679697Snon u_int msg; 414779697Snon{ 414879697Snon 414979697Snon if (slp->sl_ph_count < SCSI_LOW_MAX_ATTEN_CHECK) 415079697Snon scsi_low_assert_msg(slp, ti, msg, 0); 415179697Snon else 4152240325Sjhb device_printf(slp->sl_dev, "atten check OK\n"); 415379697Snon} 415479697Snon 415579697Snonstatic void 415679697Snonscsi_low_test_cmdlnk(slp, cb) 415779697Snon struct scsi_low_softc *slp; 415879697Snon struct slccb *cb; 415979697Snon{ 416079697Snon#define SCSI_LOW_CMDLNK_NOK (CCB_INTERNAL | CCB_SENSE | CCB_CLEARQ) 416179697Snon 416279697Snon if ((cb->ccb_flags & SCSI_LOW_CMDLNK_NOK) != 0) 416379697Snon return; 416479697Snon 416579697Snon memcpy(cb->ccb_scsi_cmd, slp->sl_scp.scp_cmd, 416679697Snon slp->sl_scp.scp_cmdlen); 416779697Snon cb->ccb_scsi_cmd[slp->sl_scp.scp_cmdlen - 1] |= 1; 416879697Snon slp->sl_scp.scp_cmd = cb->ccb_scsi_cmd; 416979697Snon} 417079697Snon#endif /* SCSI_LOW_DEBUG */ 417179697Snon 417279697Snon/* static */ void 417367468Snonscsi_low_info(slp, ti, s) 417467468Snon struct scsi_low_softc *slp; 417567468Snon struct targ_info *ti; 417667468Snon u_char *s; 417767468Snon{ 417867468Snon 417979697Snon if (slp == NULL) 418079697Snon slp = LIST_FIRST(&sl_tab); 418179697Snon if (s == NULL) 418279697Snon s = "no message"; 418379697Snon 418479697Snon printf(">>>>> SCSI_LOW_INFO(0x%lx): %s\n", (u_long) slp->sl_Tnexus, s); 418567468Snon if (ti == NULL) 418667468Snon { 418779697Snon for (ti = TAILQ_FIRST(&slp->sl_titab); ti != NULL; 418879697Snon ti = TAILQ_NEXT(ti, ti_chain)) 418979697Snon { 419067468Snon scsi_low_print(slp, ti); 419179697Snon } 419267468Snon } 419367468Snon else 419479697Snon { 419567468Snon scsi_low_print(slp, ti); 419679697Snon } 419767468Snon} 419867468Snon 419967468Snonstatic u_char *phase[] = 420067468Snon{ 420167468Snon "FREE", "ARBSTART", "SELSTART", "SELECTED", 420267468Snon "CMDOUT", "DATA", "MSGIN", "MSGOUT", "STATIN", "DISC", "RESEL" 420367468Snon}; 420467468Snon 420567468Snonvoid 420667468Snonscsi_low_print(slp, ti) 420767468Snon struct scsi_low_softc *slp; 420867468Snon struct targ_info *ti; 420967468Snon{ 421079697Snon struct lun_info *li; 421179697Snon struct slccb *cb; 421279697Snon struct sc_p *sp; 421367468Snon 421479697Snon if (ti == NULL || ti == slp->sl_Tnexus) 421579697Snon { 421679697Snon ti = slp->sl_Tnexus; 421779697Snon li = slp->sl_Lnexus; 421879697Snon cb = slp->sl_Qnexus; 421979697Snon } 422079697Snon else 422179697Snon { 422279697Snon li = LIST_FIRST(&ti->ti_litab); 422379697Snon cb = TAILQ_FIRST(&li->li_discq); 422479697Snon } 422579697Snon sp = &slp->sl_scp; 422667468Snon 4227240325Sjhb device_printf(slp->sl_dev, 4228240325Sjhb "=== NEXUS T(0x%lx) L(0x%lx) Q(0x%lx) NIO(%d) ===\n", 4229240325Sjhb (u_long) ti, (u_long) li, (u_long) cb, slp->sl_nio); 423067468Snon 423167468Snon /* target stat */ 423267468Snon if (ti != NULL) 423367468Snon { 423479697Snon u_int flags = 0, maxnqio = 0, nqio = 0; 4235265632Smav int lun = CAM_LUN_WILDCARD; 423667468Snon 423767468Snon if (li != NULL) 423867468Snon { 423967468Snon lun = li->li_lun; 424067468Snon flags = li->li_flags; 424179697Snon maxnqio = li->li_maxnqio; 424279697Snon nqio = li->li_nqio; 424367468Snon } 424467468Snon 4245240325Sjhb device_printf(slp->sl_dev, 4246240325Sjhb "(%d:%d) ph<%s> => ph<%s> DISC(%d) QIO(%d:%d)\n", 424767468Snon ti->ti_id, lun, phase[(int) ti->ti_ophase], 424879697Snon phase[(int) ti->ti_phase], ti->ti_disc, 424979697Snon nqio, maxnqio); 425067468Snon 425179697Snon if (cb != NULL) 425279697Snon { 425379697Snonprintf("CCB: cmd[0] 0x%x clen 0x%x dlen 0x%x<0x%x stat 0x%x err %b\n", 425479697Snon (u_int) cb->ccb_scp.scp_cmd[0], 425579697Snon cb->ccb_scp.scp_cmdlen, 425679697Snon cb->ccb_datalen, 425779697Snon cb->ccb_scp.scp_datalen, 425879697Snon (u_int) cb->ccb_sscp.scp_status, 425979697Snon cb->ccb_error, SCSI_LOW_ERRORBITS); 426079697Snon } 426167468Snon 426279697Snonprintf("MSGIN: ptr(%x) [%x][%x][%x][%x][%x] attention: %d\n", 426379697Snon (u_int) (ti->ti_msginptr), 426479697Snon (u_int) (ti->ti_msgin[0]), 426579697Snon (u_int) (ti->ti_msgin[1]), 426679697Snon (u_int) (ti->ti_msgin[2]), 426779697Snon (u_int) (ti->ti_msgin[3]), 426879697Snon (u_int) (ti->ti_msgin[4]), 426979697Snon slp->sl_atten); 427079697Snon 427167468Snonprintf("MSGOUT: msgflags 0x%x [%x][%x][%x][%x][%x] msgoutlen %d C_FLAGS: %b\n", 427279697Snon (u_int) ti->ti_msgflags, 427379697Snon (u_int) (ti->ti_msgoutstr[0]), 427479697Snon (u_int) (ti->ti_msgoutstr[1]), 427579697Snon (u_int) (ti->ti_msgoutstr[2]), 427679697Snon (u_int) (ti->ti_msgoutstr[3]), 427779697Snon (u_int) (ti->ti_msgoutstr[4]), 427879697Snon ti->ti_msgoutlen, 427979697Snon flags, SCSI_LOW_BITS); 428067468Snon 428179697Snon#ifdef SCSI_LOW_DIAGNOSTIC 428279697Snon scsi_low_msg_log_show(&ti->ti_log_msgin, "MIN LOG ", 2); 428379697Snon scsi_low_msg_log_show(&ti->ti_log_msgout, "MOUT LOG", 2); 428479697Snon#endif /* SCSI_LOW_DIAGNOSTIC */ 428567468Snon 428667468Snon } 428779697Snon 428879697Snon printf("SCB: daddr 0x%lx dlen 0x%x stat 0x%x err %b\n", 428979697Snon (u_long) sp->scp_data, 429079697Snon sp->scp_datalen, 429179697Snon (u_int) sp->scp_status, 429279697Snon slp->sl_error, SCSI_LOW_ERRORBITS); 429367468Snon} 4294