1098ca2bdSWarner Losh /*- 2ea49c6e4SMatt Jacob * Machine and OS Independent Target Mode Code for the Qlogic SCSI/FC adapters. 3ea49c6e4SMatt Jacob * 4e5265237SMatt Jacob * Copyright (c) 1997-2006 by Matthew Jacob 5ea49c6e4SMatt Jacob * All rights reserved. 6ea49c6e4SMatt Jacob * 7ea49c6e4SMatt Jacob * Redistribution and use in source and binary forms, with or without 8ea49c6e4SMatt Jacob * modification, are permitted provided that the following conditions 9ea49c6e4SMatt Jacob * are met: 10ea49c6e4SMatt Jacob * 1. Redistributions of source code must retain the above copyright 11ea49c6e4SMatt Jacob * notice immediately at the beginning of the file, without modification, 12ea49c6e4SMatt Jacob * this list of conditions, and the following disclaimer. 13aa57fd6fSMatt Jacob * 2. The name of the author may not be used to endorse or promote products 14ea49c6e4SMatt Jacob * derived from this software without specific prior written permission. 15ea49c6e4SMatt Jacob * 16ea49c6e4SMatt Jacob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17ea49c6e4SMatt Jacob * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18ea49c6e4SMatt Jacob * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19ea49c6e4SMatt Jacob * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20ea49c6e4SMatt Jacob * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21ea49c6e4SMatt Jacob * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22ea49c6e4SMatt Jacob * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23ea49c6e4SMatt Jacob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24ea49c6e4SMatt Jacob * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25ea49c6e4SMatt Jacob * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26ea49c6e4SMatt Jacob * SUCH DAMAGE. 27ea49c6e4SMatt Jacob */ 28ea49c6e4SMatt Jacob /* 2975c1e828SMatt Jacob * Bug fixes gratefully acknowledged from: 3075c1e828SMatt Jacob * Oded Kedem <oded@kashya.com> 3175c1e828SMatt Jacob */ 3275c1e828SMatt Jacob /* 33ea49c6e4SMatt Jacob * Include header file appropriate for platform we're building on. 34ea49c6e4SMatt Jacob */ 35ea49c6e4SMatt Jacob 36ea49c6e4SMatt Jacob #ifdef __NetBSD__ 37ea49c6e4SMatt Jacob #include <dev/ic/isp_netbsd.h> 38ea49c6e4SMatt Jacob #endif 39ea49c6e4SMatt Jacob #ifdef __FreeBSD__ 40799881e0SMatt Jacob #include <sys/cdefs.h> 41799881e0SMatt Jacob __FBSDID("$FreeBSD$"); 42ea49c6e4SMatt Jacob #include <dev/isp/isp_freebsd.h> 43ea49c6e4SMatt Jacob #endif 44ea49c6e4SMatt Jacob #ifdef __OpenBSD__ 45ea49c6e4SMatt Jacob #include <dev/ic/isp_openbsd.h> 46ea49c6e4SMatt Jacob #endif 47ea49c6e4SMatt Jacob #ifdef __linux__ 48ea49c6e4SMatt Jacob #include "isp_linux.h" 49ea49c6e4SMatt Jacob #endif 50ea49c6e4SMatt Jacob 51ea49c6e4SMatt Jacob #ifdef ISP_TARGET_MODE 52b25bcef8SMatt Jacob static const char atiocope[] = 5323ac1fceSMatt Jacob "ATIO returned for lun %d because it was in the middle of Bus Device Reset " 5423ac1fceSMatt Jacob "on bus %d"; 55b25bcef8SMatt Jacob static const char atior[] = 5610365e5aSMatt Jacob "ATIO returned on for lun %d on from loopid %d because a Bus Reset " 5710365e5aSMatt Jacob "occurred on bus %d"; 58ea49c6e4SMatt Jacob 599cd7268eSMatt Jacob static void isp_got_msg(ispsoftc_t *, in_entry_t *); 609cd7268eSMatt Jacob static void isp_got_msg_fc(ispsoftc_t *, in_fcentry_t *); 6110365e5aSMatt Jacob static void isp_got_tmf_24xx(ispsoftc_t *, at7_entry_t *); 629cd7268eSMatt Jacob static void isp_handle_atio(ispsoftc_t *, at_entry_t *); 639cd7268eSMatt Jacob static void isp_handle_atio2(ispsoftc_t *, at2_entry_t *); 649cd7268eSMatt Jacob static void isp_handle_ctio(ispsoftc_t *, ct_entry_t *); 659cd7268eSMatt Jacob static void isp_handle_ctio2(ispsoftc_t *, ct2_entry_t *); 6610365e5aSMatt Jacob static void isp_handle_ctio7(ispsoftc_t *, ct7_entry_t *); 67ea49c6e4SMatt Jacob 68ea49c6e4SMatt Jacob /* 69ea49c6e4SMatt Jacob * The Qlogic driver gets an interrupt to look at response queue entries. 70ea49c6e4SMatt Jacob * Some of these are status completions for initiatior mode commands, but 71ea49c6e4SMatt Jacob * if target mode is enabled, we get a whole wad of response queue entries 72ea49c6e4SMatt Jacob * to be handled here. 73ea49c6e4SMatt Jacob * 74ea49c6e4SMatt Jacob * Basically the split into 3 main groups: Lun Enable/Modification responses, 75ea49c6e4SMatt Jacob * SCSI Command processing, and Immediate Notification events. 76ea49c6e4SMatt Jacob * 77ea49c6e4SMatt Jacob * You start by writing a request queue entry to enable target mode (and 78ea49c6e4SMatt Jacob * establish some resource limitations which you can modify later). 79ea49c6e4SMatt Jacob * The f/w responds with a LUN ENABLE or LUN MODIFY response with 80ea49c6e4SMatt Jacob * the status of this action. If the enable was successful, you can expect... 81ea49c6e4SMatt Jacob * 82ea49c6e4SMatt Jacob * Response queue entries with SCSI commands encapsulate show up in an ATIO 83ea49c6e4SMatt Jacob * (Accept Target IO) type- sometimes with enough info to stop the command at 84ea49c6e4SMatt Jacob * this level. Ultimately the driver has to feed back to the f/w's request 85ea49c6e4SMatt Jacob * queue a sequence of CTIOs (continue target I/O) that describe data to 86ea49c6e4SMatt Jacob * be moved and/or status to be sent) and finally finishing with sending 87ea49c6e4SMatt Jacob * to the f/w's response queue an ATIO which then completes the handshake 88ea49c6e4SMatt Jacob * with the f/w for that command. There's a lot of variations on this theme, 89ea49c6e4SMatt Jacob * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel 90ea49c6e4SMatt Jacob * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic 91ea49c6e4SMatt Jacob * gist of it. 92ea49c6e4SMatt Jacob * 93ea49c6e4SMatt Jacob * The third group that can show up in the response queue are Immediate 94ea49c6e4SMatt Jacob * Notification events. These include things like notifications of SCSI bus 95ea49c6e4SMatt Jacob * resets, or Bus Device Reset messages or other messages received. This 96f09deb69SJeroen Ruigrok van der Werven * a classic oddbins area. It can get a little weird because you then turn 97ea49c6e4SMatt Jacob * around and acknowledge the Immediate Notify by writing an entry onto the 98ea49c6e4SMatt Jacob * request queue and then the f/w turns around and gives you an acknowledgement 99ea49c6e4SMatt Jacob * to *your* acknowledgement on the response queue (the idea being to let 100ea49c6e4SMatt Jacob * the f/w tell you when the event is *really* over I guess). 101ea49c6e4SMatt Jacob * 102ea49c6e4SMatt Jacob */ 103ea49c6e4SMatt Jacob 104ea49c6e4SMatt Jacob 105ea49c6e4SMatt Jacob /* 106ea49c6e4SMatt Jacob * A new response queue entry has arrived. The interrupt service code 107ea49c6e4SMatt Jacob * has already swizzled it into the platform dependent from canonical form. 108ea49c6e4SMatt Jacob * 109ea49c6e4SMatt Jacob * Because of the way this driver is designed, unfortunately most of the 110ea49c6e4SMatt Jacob * actual synchronization work has to be done in the platform specific 111ea49c6e4SMatt Jacob * code- we have no synchroniation primitives in the common code. 112ea49c6e4SMatt Jacob */ 113ea49c6e4SMatt Jacob 114ea49c6e4SMatt Jacob int 11510365e5aSMatt Jacob isp_target_notify(ispsoftc_t *isp, void *vptr, uint32_t *optrp) 116ea49c6e4SMatt Jacob { 11710365e5aSMatt Jacob uint16_t status; 11810365e5aSMatt Jacob uint32_t seqid; 119ea49c6e4SMatt Jacob union { 120ea49c6e4SMatt Jacob at_entry_t *atiop; 121ea49c6e4SMatt Jacob at2_entry_t *at2iop; 122e5265237SMatt Jacob at2e_entry_t *at2eiop; 12310365e5aSMatt Jacob at7_entry_t *at7iop; 124ea49c6e4SMatt Jacob ct_entry_t *ctiop; 125ea49c6e4SMatt Jacob ct2_entry_t *ct2iop; 126e5265237SMatt Jacob ct2e_entry_t *ct2eiop; 12710365e5aSMatt Jacob ct7_entry_t *ct7iop; 128ea49c6e4SMatt Jacob lun_entry_t *lunenp; 129ea49c6e4SMatt Jacob in_entry_t *inotp; 130ea49c6e4SMatt Jacob in_fcentry_t *inot_fcp; 131e5265237SMatt Jacob in_fcentry_e_t *inote_fcp; 13210365e5aSMatt Jacob in_fcentry_24xx_t *inot_24xx; 133ea49c6e4SMatt Jacob na_entry_t *nackp; 134ea49c6e4SMatt Jacob na_fcentry_t *nack_fcp; 135e5265237SMatt Jacob na_fcentry_e_t *nacke_fcp; 13610365e5aSMatt Jacob na_fcentry_24xx_t *nack_24xx; 137ea49c6e4SMatt Jacob isphdr_t *hp; 13810365e5aSMatt Jacob abts_t *abts; 13910365e5aSMatt Jacob abts_rsp_t *abts_rsp; 14010365e5aSMatt Jacob els_t *els; 141ea49c6e4SMatt Jacob void * *vp; 142ea49c6e4SMatt Jacob #define atiop unp.atiop 143ea49c6e4SMatt Jacob #define at2iop unp.at2iop 144e5265237SMatt Jacob #define at2eiop unp.at2eiop 14510365e5aSMatt Jacob #define at7iop unp.at7iop 146ea49c6e4SMatt Jacob #define ctiop unp.ctiop 147ea49c6e4SMatt Jacob #define ct2iop unp.ct2iop 148e5265237SMatt Jacob #define ct2eiop unp.ct2eiop 14910365e5aSMatt Jacob #define ct7iop unp.ct7iop 150ea49c6e4SMatt Jacob #define lunenp unp.lunenp 151ea49c6e4SMatt Jacob #define inotp unp.inotp 152ea49c6e4SMatt Jacob #define inot_fcp unp.inot_fcp 153e5265237SMatt Jacob #define inote_fcp unp.inote_fcp 15410365e5aSMatt Jacob #define inot_24xx unp.inot_24xx 155ea49c6e4SMatt Jacob #define nackp unp.nackp 156ea49c6e4SMatt Jacob #define nack_fcp unp.nack_fcp 157e5265237SMatt Jacob #define nacke_fcp unp.nacke_fcp 15810365e5aSMatt Jacob #define nack_24xx unp.nack_24xx 15910365e5aSMatt Jacob #define abts unp.abts 16010365e5aSMatt Jacob #define abts_rsp unp.abts_rsp 16110365e5aSMatt Jacob #define els unp.els 162ea49c6e4SMatt Jacob #define hdrp unp.hp 163ea49c6e4SMatt Jacob } unp; 1641dae40ebSMatt Jacob uint8_t local[QENTRY_LEN]; 16510365e5aSMatt Jacob int bus, type, level, rval = 1; 166ea49c6e4SMatt Jacob 1674fd13c1bSMatt Jacob type = isp_get_response_type(isp, (isphdr_t *)vptr); 168ea49c6e4SMatt Jacob unp.vp = vptr; 169ea49c6e4SMatt Jacob 170ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr); 171ea49c6e4SMatt Jacob 1724fd13c1bSMatt Jacob switch(type) { 173ea49c6e4SMatt Jacob case RQSTYPE_ATIO: 17410365e5aSMatt Jacob if (IS_24XX(isp)) { 17510365e5aSMatt Jacob int len; 17610365e5aSMatt Jacob 17710365e5aSMatt Jacob isp_get_atio7(isp, at7iop, (at7_entry_t *) local); 17810365e5aSMatt Jacob at7iop = (at7_entry_t *) local; 17910365e5aSMatt Jacob /* 18010365e5aSMatt Jacob * Check for and do something with commands whose IULEN 18110365e5aSMatt Jacob * extends past a singel queue entry. 18210365e5aSMatt Jacob */ 18310365e5aSMatt Jacob len = at7iop->at_ta_len & 0xfffff; 18410365e5aSMatt Jacob if (len > (QENTRY_LEN - 8)) { 18510365e5aSMatt Jacob len -= (QENTRY_LEN - 8); 18610365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, 18710365e5aSMatt Jacob "long IU length (%d) ignored", len); 18810365e5aSMatt Jacob while (len > 0) { 18910365e5aSMatt Jacob *optrp = ISP_NXT_QENTRY(*optrp, 19010365e5aSMatt Jacob RESULT_QUEUE_LEN(isp)); 19110365e5aSMatt Jacob len -= QENTRY_LEN; 19210365e5aSMatt Jacob } 19310365e5aSMatt Jacob } 19410365e5aSMatt Jacob /* 19510365e5aSMatt Jacob * Check for a task management function 19610365e5aSMatt Jacob */ 19710365e5aSMatt Jacob if (at7iop->at_cmnd.fcp_cmnd_task_management) { 19810365e5aSMatt Jacob isp_got_tmf_24xx(isp, at7iop); 19910365e5aSMatt Jacob break; 20010365e5aSMatt Jacob } 20110365e5aSMatt Jacob /* 20210365e5aSMatt Jacob * Just go straight to outer layer for this one. 20310365e5aSMatt Jacob */ 20410365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local); 20510365e5aSMatt Jacob } else { 2064fd13c1bSMatt Jacob isp_get_atio(isp, atiop, (at_entry_t *) local); 2074fd13c1bSMatt Jacob isp_handle_atio(isp, (at_entry_t *) local); 20810365e5aSMatt Jacob } 209ea49c6e4SMatt Jacob break; 21010365e5aSMatt Jacob 211ea49c6e4SMatt Jacob case RQSTYPE_CTIO: 2124fd13c1bSMatt Jacob isp_get_ctio(isp, ctiop, (ct_entry_t *) local); 2134fd13c1bSMatt Jacob isp_handle_ctio(isp, (ct_entry_t *) local); 214ea49c6e4SMatt Jacob break; 21510365e5aSMatt Jacob 216ea49c6e4SMatt Jacob case RQSTYPE_ATIO2: 21710365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 218e5265237SMatt Jacob isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); 21999ece8d6SMatt Jacob } else { 2204fd13c1bSMatt Jacob isp_get_atio2(isp, at2iop, (at2_entry_t *) local); 22199ece8d6SMatt Jacob } 2224fd13c1bSMatt Jacob isp_handle_atio2(isp, (at2_entry_t *) local); 223ea49c6e4SMatt Jacob break; 22410365e5aSMatt Jacob 225ac9d0a02SMatt Jacob case RQSTYPE_CTIO3: 226ea49c6e4SMatt Jacob case RQSTYPE_CTIO2: 22710365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 228e5265237SMatt Jacob isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); 22999ece8d6SMatt Jacob } else { 2304fd13c1bSMatt Jacob isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); 23199ece8d6SMatt Jacob } 2324fd13c1bSMatt Jacob isp_handle_ctio2(isp, (ct2_entry_t *) local); 233ea49c6e4SMatt Jacob break; 23410365e5aSMatt Jacob 23510365e5aSMatt Jacob case RQSTYPE_CTIO7: 23610365e5aSMatt Jacob isp_get_ctio7(isp, ct7iop, (ct7_entry_t *) local); 23710365e5aSMatt Jacob isp_handle_ctio7(isp, (ct7_entry_t *) local); 23810365e5aSMatt Jacob break; 23910365e5aSMatt Jacob 240ea49c6e4SMatt Jacob case RQSTYPE_ENABLE_LUN: 241ea49c6e4SMatt Jacob case RQSTYPE_MODIFY_LUN: 2424fd13c1bSMatt Jacob isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); 2434fd13c1bSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local); 244ea49c6e4SMatt Jacob break; 245ea49c6e4SMatt Jacob 246ea49c6e4SMatt Jacob case RQSTYPE_NOTIFY: 247ea49c6e4SMatt Jacob /* 248ea49c6e4SMatt Jacob * Either the ISP received a SCSI message it can't 249ea49c6e4SMatt Jacob * handle, or it's returning an Immed. Notify entry 250ea49c6e4SMatt Jacob * we sent. We can send Immed. Notify entries to 251ea49c6e4SMatt Jacob * increment the firmware's resource count for them 252ea49c6e4SMatt Jacob * (we set this initially in the Enable Lun entry). 253ea49c6e4SMatt Jacob */ 25414a37293SMatt Jacob bus = 0; 25510365e5aSMatt Jacob if (IS_24XX(isp)) { 25610365e5aSMatt Jacob isp_get_notify_24xx(isp, inot_24xx, 25710365e5aSMatt Jacob (in_fcentry_24xx_t *)local); 25810365e5aSMatt Jacob inot_24xx = (in_fcentry_24xx_t *) local; 25910365e5aSMatt Jacob status = inot_24xx->in_status; 26010365e5aSMatt Jacob seqid = inot_24xx->in_rxid; 26110365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 26210365e5aSMatt Jacob "Immediate Notify status=0x%x seqid=0x%x", 26310365e5aSMatt Jacob status, seqid); 26410365e5aSMatt Jacob switch (status) { 26510365e5aSMatt Jacob case IN24XX_LIP_RESET: 26610365e5aSMatt Jacob case IN24XX_LINK_RESET: 26710365e5aSMatt Jacob case IN24XX_PORT_LOGOUT: 26810365e5aSMatt Jacob case IN24XX_PORT_CHANGED: 26910365e5aSMatt Jacob case IN24XX_LINK_FAILED: 27010365e5aSMatt Jacob case IN24XX_SRR_RCVD: 27110365e5aSMatt Jacob case IN24XX_ELS_RCVD: 27210365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, 27310365e5aSMatt Jacob &local); 27410365e5aSMatt Jacob break; 27510365e5aSMatt Jacob default: 27610365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, 27710365e5aSMatt Jacob "isp_target_notify: unknown status (0x%x)", 27810365e5aSMatt Jacob status); 27910365e5aSMatt Jacob isp_notify_ack(isp, local); 28010365e5aSMatt Jacob break; 28110365e5aSMatt Jacob } 28210365e5aSMatt Jacob break; 28310365e5aSMatt Jacob } else if (IS_FC(isp)) { 28410365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 285b4110d46SMatt Jacob isp_get_notify_fc_e(isp, inote_fcp, 286b4110d46SMatt Jacob (in_fcentry_e_t *)local); 28799ece8d6SMatt Jacob } else { 288b4110d46SMatt Jacob isp_get_notify_fc(isp, inot_fcp, 289b4110d46SMatt Jacob (in_fcentry_t *)local); 29099ece8d6SMatt Jacob } 2914fd13c1bSMatt Jacob inot_fcp = (in_fcentry_t *) local; 292ea49c6e4SMatt Jacob status = inot_fcp->in_status; 293ea49c6e4SMatt Jacob seqid = inot_fcp->in_seqid; 294ea49c6e4SMatt Jacob } else { 2954fd13c1bSMatt Jacob isp_get_notify(isp, inotp, (in_entry_t *)local); 2964fd13c1bSMatt Jacob inotp = (in_entry_t *) local; 297ea49c6e4SMatt Jacob status = inotp->in_status & 0xff; 298ea49c6e4SMatt Jacob seqid = inotp->in_seqid; 29914a37293SMatt Jacob if (IS_DUALBUS(isp)) { 30023ac1fceSMatt Jacob bus = GET_BUS_VAL(inotp->in_iid); 30123ac1fceSMatt Jacob SET_BUS_VAL(inotp->in_iid, 0); 302ea49c6e4SMatt Jacob } 30314a37293SMatt Jacob } 304b4110d46SMatt Jacob 30523ac1fceSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 30623ac1fceSMatt Jacob "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", 30723ac1fceSMatt Jacob bus, status, seqid); 30823ac1fceSMatt Jacob 309ea49c6e4SMatt Jacob switch (status) { 310ea49c6e4SMatt Jacob case IN_MSG_RECEIVED: 311ea49c6e4SMatt Jacob case IN_IDE_RECEIVED: 312ea49c6e4SMatt Jacob if (IS_FC(isp)) { 313e5265237SMatt Jacob isp_got_msg_fc(isp, (in_fcentry_t *)local); 314ea49c6e4SMatt Jacob } else { 315e5265237SMatt Jacob isp_got_msg(isp, (in_entry_t *)local); 316ea49c6e4SMatt Jacob } 317ea49c6e4SMatt Jacob break; 318ea49c6e4SMatt Jacob case IN_RSRC_UNAVAIL: 31910365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, "Firmware out of ATIOs"); 320e5265237SMatt Jacob isp_notify_ack(isp, local); 321e5265237SMatt Jacob break; 322e5265237SMatt Jacob case IN_RESET: 32310365e5aSMatt Jacob { 32410365e5aSMatt Jacob /* 32510365e5aSMatt Jacob * We form the notify structure here because we need 32610365e5aSMatt Jacob * to mark it as needing a NOTIFY ACK on return. 32710365e5aSMatt Jacob */ 32810365e5aSMatt Jacob tmd_notify_t notify; 32910365e5aSMatt Jacob 33010365e5aSMatt Jacob MEMZERO(¬ify, sizeof (tmd_notify_t)); 33110365e5aSMatt Jacob notify.nt_hba = isp; 33210365e5aSMatt Jacob notify.nt_iid = INI_ANY; 33310365e5aSMatt Jacob /* nt_tgt set in outer layers */ 33410365e5aSMatt Jacob notify.nt_lun = LUN_ANY; 33510365e5aSMatt Jacob notify.nt_tagval = TAG_ANY; 33610365e5aSMatt Jacob notify.nt_ncode = NT_BUS_RESET; 33710365e5aSMatt Jacob notify.nt_need_ack = 1; 33810365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 339ea49c6e4SMatt Jacob break; 34010365e5aSMatt Jacob } 341ea49c6e4SMatt Jacob case IN_PORT_LOGOUT: 342e63442b6SMatt Jacob case IN_ABORT_TASK: 343ea49c6e4SMatt Jacob case IN_PORT_CHANGED: 344ea49c6e4SMatt Jacob case IN_GLOBAL_LOGO: 345e63442b6SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); 346ea49c6e4SMatt Jacob break; 347ea49c6e4SMatt Jacob default: 34810365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, 34910365e5aSMatt Jacob "isp_target_notify: unknown status (0x%x)", 35010365e5aSMatt Jacob status); 351e5265237SMatt Jacob isp_notify_ack(isp, local); 352ea49c6e4SMatt Jacob break; 353ea49c6e4SMatt Jacob } 354ea49c6e4SMatt Jacob break; 355ea49c6e4SMatt Jacob 356ea49c6e4SMatt Jacob case RQSTYPE_NOTIFY_ACK: 357ea49c6e4SMatt Jacob /* 358ea49c6e4SMatt Jacob * The ISP is acknowledging our acknowledgement of an 359ea49c6e4SMatt Jacob * Immediate Notify entry for some asynchronous event. 360ea49c6e4SMatt Jacob */ 36110365e5aSMatt Jacob if (IS_24XX(isp)) { 36210365e5aSMatt Jacob isp_get_notify_ack_24xx(isp, nack_24xx, 36310365e5aSMatt Jacob (na_fcentry_24xx_t *) local); 36410365e5aSMatt Jacob nack_24xx = (na_fcentry_24xx_t *) local; 36510365e5aSMatt Jacob if (nack_24xx->na_status != NA_OK) { 36610365e5aSMatt Jacob level = ISP_LOGINFO; 36710365e5aSMatt Jacob } else { 36810365e5aSMatt Jacob level = ISP_LOGTDEBUG1; 36910365e5aSMatt Jacob } 37010365e5aSMatt Jacob isp_prt(isp, level, 37110365e5aSMatt Jacob "Notify Ack Status=0x%x; Subcode 0x%x seqid=0x%x", 37210365e5aSMatt Jacob nack_24xx->na_status, nack_24xx->na_status_subcode, 37310365e5aSMatt Jacob nack_24xx->na_rxid); 37410365e5aSMatt Jacob } else if (IS_FC(isp)) { 37510365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 376e5265237SMatt Jacob isp_get_notify_ack_fc_e(isp, nacke_fcp, 377e5265237SMatt Jacob (na_fcentry_e_t *)local); 37899ece8d6SMatt Jacob } else { 3794fd13c1bSMatt Jacob isp_get_notify_ack_fc(isp, nack_fcp, 3804fd13c1bSMatt Jacob (na_fcentry_t *)local); 38199ece8d6SMatt Jacob } 3824fd13c1bSMatt Jacob nack_fcp = (na_fcentry_t *)local; 38310365e5aSMatt Jacob if (nack_fcp->na_status != NA_OK) { 38410365e5aSMatt Jacob level = ISP_LOGINFO; 38510365e5aSMatt Jacob } else { 38610365e5aSMatt Jacob level = ISP_LOGTDEBUG1; 38710365e5aSMatt Jacob } 38810365e5aSMatt Jacob isp_prt(isp, level, 38910365e5aSMatt Jacob "Notify Ack Status=0x%x seqid 0x%x", 39010549c05SMatt Jacob nack_fcp->na_status, nack_fcp->na_seqid); 391ea49c6e4SMatt Jacob } else { 3924fd13c1bSMatt Jacob isp_get_notify_ack(isp, nackp, (na_entry_t *)local); 3934fd13c1bSMatt Jacob nackp = (na_entry_t *)local; 39410365e5aSMatt Jacob if (nackp->na_status != NA_OK) { 39510365e5aSMatt Jacob level = ISP_LOGINFO; 39610365e5aSMatt Jacob } else { 39710365e5aSMatt Jacob level = ISP_LOGTDEBUG1; 39810365e5aSMatt Jacob } 39910365e5aSMatt Jacob isp_prt(isp, level, 40010549c05SMatt Jacob "Notify Ack event 0x%x status=0x%x seqid 0x%x", 40110549c05SMatt Jacob nackp->na_event, nackp->na_status, nackp->na_seqid); 402ea49c6e4SMatt Jacob } 403ea49c6e4SMatt Jacob break; 40410365e5aSMatt Jacob 40510365e5aSMatt Jacob case RQSTYPE_ABTS_RCVD: 40610365e5aSMatt Jacob isp_get_abts(isp, abts, (abts_t *)local); 40710365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); 40810365e5aSMatt Jacob break; 40910365e5aSMatt Jacob case RQSTYPE_ABTS_RSP: 41010365e5aSMatt Jacob isp_get_abts_rsp(isp, abts_rsp, (abts_rsp_t *)local); 41110365e5aSMatt Jacob abts_rsp = (abts_rsp_t *) local; 41210365e5aSMatt Jacob if (abts_rsp->abts_rsp_status) { 41310365e5aSMatt Jacob level = ISP_LOGINFO; 41410365e5aSMatt Jacob } else { 41510365e5aSMatt Jacob level = ISP_LOGTDEBUG0; 41610365e5aSMatt Jacob } 41710365e5aSMatt Jacob isp_prt(isp, level, 41810365e5aSMatt Jacob "ABTS RSP response[0x%x]: status=0x%x sub=(0x%x 0x%x)", 41910365e5aSMatt Jacob abts_rsp->abts_rsp_rxid_task, abts_rsp->abts_rsp_status, 42010365e5aSMatt Jacob abts_rsp->abts_rsp_payload.rsp.subcode1, 42110365e5aSMatt Jacob abts_rsp->abts_rsp_payload.rsp.subcode2); 42210365e5aSMatt Jacob break; 423ea49c6e4SMatt Jacob default: 42410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 4254fd13c1bSMatt Jacob "Unknown entry type 0x%x in isp_target_notify", type); 426e63442b6SMatt Jacob rval = 0; 427ea49c6e4SMatt Jacob break; 428ea49c6e4SMatt Jacob } 429ea49c6e4SMatt Jacob #undef atiop 430ea49c6e4SMatt Jacob #undef at2iop 431e5265237SMatt Jacob #undef at2eiop 43210365e5aSMatt Jacob #undef at7iop 433ea49c6e4SMatt Jacob #undef ctiop 434ea49c6e4SMatt Jacob #undef ct2iop 435e5265237SMatt Jacob #undef ct2eiop 43610365e5aSMatt Jacob #undef ct7iop 437ea49c6e4SMatt Jacob #undef lunenp 438ea49c6e4SMatt Jacob #undef inotp 439ea49c6e4SMatt Jacob #undef inot_fcp 440e5265237SMatt Jacob #undef inote_fcp 44110365e5aSMatt Jacob #undef inot_24xx 442ea49c6e4SMatt Jacob #undef nackp 443ea49c6e4SMatt Jacob #undef nack_fcp 444e5265237SMatt Jacob #undef nacke_fcp 44510365e5aSMatt Jacob #undef hack_24xx 44610365e5aSMatt Jacob #undef abts 44710365e5aSMatt Jacob #undef abts_rsp 44810365e5aSMatt Jacob #undef els 449ea49c6e4SMatt Jacob #undef hdrp 450ea49c6e4SMatt Jacob return (rval); 451ea49c6e4SMatt Jacob } 452ea49c6e4SMatt Jacob 453ea49c6e4SMatt Jacob 454ea49c6e4SMatt Jacob /* 455ea49c6e4SMatt Jacob * Toggle (on/off) target mode for bus/target/lun 456ea49c6e4SMatt Jacob * 457ea49c6e4SMatt Jacob * The caller has checked for overlap and legality. 458ea49c6e4SMatt Jacob * 459ea49c6e4SMatt Jacob * Note that not all of bus, target or lun can be paid attention to. 460ea49c6e4SMatt Jacob * Note also that this action will not be complete until the f/w writes 461ea49c6e4SMatt Jacob * response entry. The caller is responsible for synchronizing this. 462ea49c6e4SMatt Jacob */ 463ea49c6e4SMatt Jacob int 4649cd7268eSMatt Jacob isp_lun_cmd(ispsoftc_t *isp, int cmd, int bus, int tgt, int lun, 4651dae40ebSMatt Jacob int cmd_cnt, int inot_cnt, uint32_t opaque) 466ea49c6e4SMatt Jacob { 467ea49c6e4SMatt Jacob lun_entry_t el; 46810365e5aSMatt Jacob uint32_t nxti, optr; 469ea49c6e4SMatt Jacob void *outp; 470ea49c6e4SMatt Jacob 471ea49c6e4SMatt Jacob 472ea49c6e4SMatt Jacob MEMZERO(&el, sizeof (el)); 47314a37293SMatt Jacob if (IS_DUALBUS(isp)) { 47414a37293SMatt Jacob el.le_rsvd = (bus & 0x1) << 7; 47514a37293SMatt Jacob } 4765d571944SMatt Jacob el.le_cmd_count = cmd_cnt; 4775d571944SMatt Jacob el.le_in_count = inot_cnt; 478ea49c6e4SMatt Jacob if (cmd == RQSTYPE_ENABLE_LUN) { 479ea49c6e4SMatt Jacob if (IS_SCSI(isp)) { 4802133e16fSMatt Jacob el.le_flags = LUN_TQAE|LUN_DISAD; 481ea49c6e4SMatt Jacob el.le_cdb6len = 12; 482ea49c6e4SMatt Jacob el.le_cdb7len = 12; 483ea49c6e4SMatt Jacob } 484ea49c6e4SMatt Jacob } else if (cmd == -RQSTYPE_ENABLE_LUN) { 485ea49c6e4SMatt Jacob cmd = RQSTYPE_ENABLE_LUN; 486ea49c6e4SMatt Jacob el.le_cmd_count = 0; 487ea49c6e4SMatt Jacob el.le_in_count = 0; 488ea49c6e4SMatt Jacob } else if (cmd == -RQSTYPE_MODIFY_LUN) { 489ea49c6e4SMatt Jacob cmd = RQSTYPE_MODIFY_LUN; 490ea49c6e4SMatt Jacob el.le_ops = LUN_CCDECR | LUN_INDECR; 491ea49c6e4SMatt Jacob } else { 492ea49c6e4SMatt Jacob el.le_ops = LUN_CCINCR | LUN_ININCR; 493ea49c6e4SMatt Jacob } 494ea49c6e4SMatt Jacob el.le_header.rqs_entry_type = cmd; 495ea49c6e4SMatt Jacob el.le_header.rqs_entry_count = 1; 496ea49c6e4SMatt Jacob el.le_reserved = opaque; 497ea49c6e4SMatt Jacob if (IS_SCSI(isp)) { 498ea49c6e4SMatt Jacob el.le_tgt = tgt; 499ea49c6e4SMatt Jacob el.le_lun = lun; 50010365e5aSMatt Jacob } else if (FCPARAM(isp)->isp_sccfw == 0) { 501ea49c6e4SMatt Jacob el.le_lun = lun; 502ea49c6e4SMatt Jacob } 503351c7054SMatt Jacob el.le_timeout = 30; 504ea49c6e4SMatt Jacob 5054fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 5064fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGERR, 50710549c05SMatt Jacob "Request Queue Overflow in isp_lun_cmd"); 508ea49c6e4SMatt Jacob return (-1); 509ea49c6e4SMatt Jacob } 510ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el); 5114fd13c1bSMatt Jacob isp_put_enable_lun(isp, &el, outp); 5124fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 513ea49c6e4SMatt Jacob return (0); 514ea49c6e4SMatt Jacob } 515ea49c6e4SMatt Jacob 516ea49c6e4SMatt Jacob 517ea49c6e4SMatt Jacob int 5189cd7268eSMatt Jacob isp_target_put_entry(ispsoftc_t *isp, void *ap) 519ea49c6e4SMatt Jacob { 520ea49c6e4SMatt Jacob void *outp; 52110365e5aSMatt Jacob uint32_t nxti, optr; 5221dae40ebSMatt Jacob uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; 523ea49c6e4SMatt Jacob 5244fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 52510549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, 52610549c05SMatt Jacob "Request Queue Overflow in isp_target_put_entry"); 527ea49c6e4SMatt Jacob return (-1); 528ea49c6e4SMatt Jacob } 529ea49c6e4SMatt Jacob switch (etype) { 530ea49c6e4SMatt Jacob case RQSTYPE_ATIO: 5314fd13c1bSMatt Jacob isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); 532ea49c6e4SMatt Jacob break; 533ea49c6e4SMatt Jacob case RQSTYPE_ATIO2: 53410365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 53510365e5aSMatt Jacob isp_put_atio2e(isp, (at2e_entry_t *) ap, 53610365e5aSMatt Jacob (at2e_entry_t *) outp); 53799ece8d6SMatt Jacob } else { 53810365e5aSMatt Jacob isp_put_atio2(isp, (at2_entry_t *) ap, 53910365e5aSMatt Jacob (at2_entry_t *) outp); 54099ece8d6SMatt Jacob } 541ea49c6e4SMatt Jacob break; 542ea49c6e4SMatt Jacob case RQSTYPE_CTIO: 5434fd13c1bSMatt Jacob isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); 544ea49c6e4SMatt Jacob break; 545ea49c6e4SMatt Jacob case RQSTYPE_CTIO2: 54610365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 54710365e5aSMatt Jacob isp_put_ctio2e(isp, (ct2e_entry_t *) ap, 54810365e5aSMatt Jacob (ct2e_entry_t *) outp); 54999ece8d6SMatt Jacob } else { 55010365e5aSMatt Jacob isp_put_ctio2(isp, (ct2_entry_t *) ap, 55110365e5aSMatt Jacob (ct2_entry_t *) outp); 55299ece8d6SMatt Jacob } 553ea49c6e4SMatt Jacob break; 55410365e5aSMatt Jacob case RQSTYPE_CTIO7: 55510365e5aSMatt Jacob isp_put_ctio7(isp, (ct7_entry_t *) ap, (ct7_entry_t *) outp); 55610365e5aSMatt Jacob break; 557ea49c6e4SMatt Jacob default: 55810549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 55910549c05SMatt Jacob "Unknown type 0x%x in isp_put_entry", etype); 560ea49c6e4SMatt Jacob return (-1); 561ea49c6e4SMatt Jacob } 5622f9e7606SMatt Jacob ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap); 5634fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 564ea49c6e4SMatt Jacob return (0); 565ea49c6e4SMatt Jacob } 566ea49c6e4SMatt Jacob 567ea49c6e4SMatt Jacob int 5689cd7268eSMatt Jacob isp_target_put_atio(ispsoftc_t *isp, void *arg) 569ea49c6e4SMatt Jacob { 570ea49c6e4SMatt Jacob union { 571ea49c6e4SMatt Jacob at_entry_t _atio; 572ea49c6e4SMatt Jacob at2_entry_t _atio2; 573e5265237SMatt Jacob at2e_entry_t _atio2e; 574ea49c6e4SMatt Jacob } atun; 575ea49c6e4SMatt Jacob 576ea49c6e4SMatt Jacob MEMZERO(&atun, sizeof atun); 577ea49c6e4SMatt Jacob if (IS_FC(isp)) { 578b25bcef8SMatt Jacob at2_entry_t *aep = arg; 579ea49c6e4SMatt Jacob atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; 580ea49c6e4SMatt Jacob atun._atio2.at_header.rqs_entry_count = 1; 58110365e5aSMatt Jacob if (FCPARAM(isp)->isp_sccfw) { 58210365e5aSMatt Jacob atun._atio2.at_scclun = aep->at_scclun; 5832133e16fSMatt Jacob } else { 5841dae40ebSMatt Jacob atun._atio2.at_lun = (uint8_t) aep->at_lun; 5852133e16fSMatt Jacob } 58610365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 587e5265237SMatt Jacob atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; 588e5265237SMatt Jacob } else { 58903cf2fbaSMatt Jacob atun._atio2.at_iid = aep->at_iid; 590e5265237SMatt Jacob } 591e5824c5dSMatt Jacob atun._atio2.at_rxid = aep->at_rxid; 592ea49c6e4SMatt Jacob atun._atio2.at_status = CT_OK; 593ea49c6e4SMatt Jacob } else { 594b25bcef8SMatt Jacob at_entry_t *aep = arg; 595ea49c6e4SMatt Jacob atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO; 596ea49c6e4SMatt Jacob atun._atio.at_header.rqs_entry_count = 1; 597b25bcef8SMatt Jacob atun._atio.at_handle = aep->at_handle; 598b25bcef8SMatt Jacob atun._atio.at_iid = aep->at_iid; 599b25bcef8SMatt Jacob atun._atio.at_tgt = aep->at_tgt; 600b25bcef8SMatt Jacob atun._atio.at_lun = aep->at_lun; 601b25bcef8SMatt Jacob atun._atio.at_tag_type = aep->at_tag_type; 602b25bcef8SMatt Jacob atun._atio.at_tag_val = aep->at_tag_val; 603b25bcef8SMatt Jacob atun._atio.at_status = (aep->at_flags & AT_TQAE); 604b25bcef8SMatt Jacob atun._atio.at_status |= CT_OK; 605ea49c6e4SMatt Jacob } 606ea49c6e4SMatt Jacob return (isp_target_put_entry(isp, &atun)); 607ea49c6e4SMatt Jacob } 608ea49c6e4SMatt Jacob 609ea49c6e4SMatt Jacob /* 610ea49c6e4SMatt Jacob * Command completion- both for handling cases of no resources or 611ea49c6e4SMatt Jacob * no blackhole driver, or other cases where we have to, inline, 612ea49c6e4SMatt Jacob * finish the command sanely, or for normal command completion. 613ea49c6e4SMatt Jacob * 614ea49c6e4SMatt Jacob * The 'completion' code value has the scsi status byte in the low 8 bits. 615ea49c6e4SMatt Jacob * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have 616ea49c6e4SMatt Jacob * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC 617ea49c6e4SMatt Jacob * values. 618ea49c6e4SMatt Jacob * 619ea49c6e4SMatt Jacob * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't 620b25bcef8SMatt Jacob * NB: inline SCSI sense reporting. As such, we lose this information. XXX. 621ea49c6e4SMatt Jacob * 622ea49c6e4SMatt Jacob * For both parallel && fibre channel, we use the feature that does 623ea49c6e4SMatt Jacob * an automatic resource autoreplenish so we don't have then later do 624ea49c6e4SMatt Jacob * put of an atio to replenish the f/w's resource count. 625ea49c6e4SMatt Jacob */ 626ea49c6e4SMatt Jacob 627ea49c6e4SMatt Jacob int 62810365e5aSMatt Jacob isp_endcmd(ispsoftc_t *isp, void *arg, uint32_t code, uint32_t hdl) 629ea49c6e4SMatt Jacob { 630ea49c6e4SMatt Jacob int sts; 631ea49c6e4SMatt Jacob union { 632ea49c6e4SMatt Jacob ct_entry_t _ctio; 633ea49c6e4SMatt Jacob ct2_entry_t _ctio2; 634e5265237SMatt Jacob ct2e_entry_t _ctio2e; 63510365e5aSMatt Jacob ct7_entry_t _ctio7; 636ea49c6e4SMatt Jacob } un; 637ea49c6e4SMatt Jacob 638ea49c6e4SMatt Jacob MEMZERO(&un, sizeof un); 639ea49c6e4SMatt Jacob sts = code & 0xff; 640ea49c6e4SMatt Jacob 64110365e5aSMatt Jacob if (IS_24XX(isp)) { 64210365e5aSMatt Jacob at7_entry_t *aep = arg; 64310365e5aSMatt Jacob ct7_entry_t *cto = &un._ctio7; 64410365e5aSMatt Jacob 64510365e5aSMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 64610365e5aSMatt Jacob cto->ct_header.rqs_entry_count = 1; 64710365e5aSMatt Jacob /* XXXX */ cto->ct_nphdl = aep->at_hdr.seq_id; 64810365e5aSMatt Jacob cto->ct_rxid = aep->at_rxid; 64910365e5aSMatt Jacob cto->ct_iid_lo = (aep->at_hdr.s_id[1] << 8) | 65010365e5aSMatt Jacob aep->at_hdr.s_id[2]; 65110365e5aSMatt Jacob cto->ct_iid_hi = aep->at_hdr.s_id[0]; 65210365e5aSMatt Jacob cto->ct_oxid = aep->at_hdr.ox_id; 65310365e5aSMatt Jacob cto->ct_scsi_status = sts; 65410365e5aSMatt Jacob cto->ct_flags = CT7_FLAG_MODE1 | CT7_NO_DATA | CT7_SENDSTATUS; 65510365e5aSMatt Jacob if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { 65610365e5aSMatt Jacob cto->rsp.m1.ct_resplen = 16; 65710365e5aSMatt Jacob cto->rsp.m1.ct_resp[0] = 0xf0; 65810365e5aSMatt Jacob cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 65910365e5aSMatt Jacob cto->rsp.m1.ct_resp[7] = 8; 66010365e5aSMatt Jacob cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 66110365e5aSMatt Jacob cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 66210365e5aSMatt Jacob } 66310365e5aSMatt Jacob if (aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl) { 66410365e5aSMatt Jacob cto->ct_resid = aep->at_cmnd.cdb_dl.sf.fcp_cmnd_dl; 66510365e5aSMatt Jacob cto->ct_scsi_status |= CT2_DATA_UNDER; 66610365e5aSMatt Jacob } 66710365e5aSMatt Jacob cto->ct_syshandle = hdl; 66810365e5aSMatt Jacob } else if (IS_FC(isp)) { 669ea49c6e4SMatt Jacob at2_entry_t *aep = arg; 670ea49c6e4SMatt Jacob ct2_entry_t *cto = &un._ctio2; 671ea49c6e4SMatt Jacob 672ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 673ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_count = 1; 67410365e5aSMatt Jacob if (FCPARAM(isp)->isp_sccfw == 0) { 675ea49c6e4SMatt Jacob cto->ct_lun = aep->at_lun; 6762133e16fSMatt Jacob } 67710365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 678e5265237SMatt Jacob un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; 679e5265237SMatt Jacob } else { 680e5265237SMatt Jacob cto->ct_iid = aep->at_iid; 681e5265237SMatt Jacob } 682ea49c6e4SMatt Jacob cto->ct_rxid = aep->at_rxid; 683eedb2dfeSMatt Jacob cto->rsp.m1.ct_scsi_status = sts; 684ea49c6e4SMatt Jacob cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; 685ea49c6e4SMatt Jacob if (hdl == 0) { 686ea49c6e4SMatt Jacob cto->ct_flags |= CT2_CCINCR; 687ea49c6e4SMatt Jacob } 688ea49c6e4SMatt Jacob if (aep->at_datalen) { 689ea49c6e4SMatt Jacob cto->ct_resid = aep->at_datalen; 6905d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; 691ea49c6e4SMatt Jacob } 692eedb2dfeSMatt Jacob if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { 693ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[0] = 0xf0; 694ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 695ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[7] = 8; 696ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 697ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 698ea49c6e4SMatt Jacob cto->rsp.m1.ct_senselen = 16; 6995d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; 700ea49c6e4SMatt Jacob } 701b0bd9b71SMatt Jacob cto->ct_syshandle = hdl; 702ea49c6e4SMatt Jacob } else { 703ea49c6e4SMatt Jacob at_entry_t *aep = arg; 704ea49c6e4SMatt Jacob ct_entry_t *cto = &un._ctio; 705ea49c6e4SMatt Jacob 706ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 707ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_count = 1; 7085f5aafe1SMatt Jacob cto->ct_fwhandle = aep->at_handle; 709ea49c6e4SMatt Jacob cto->ct_iid = aep->at_iid; 710ea49c6e4SMatt Jacob cto->ct_tgt = aep->at_tgt; 711ea49c6e4SMatt Jacob cto->ct_lun = aep->at_lun; 712ea49c6e4SMatt Jacob cto->ct_tag_type = aep->at_tag_type; 713ea49c6e4SMatt Jacob cto->ct_tag_val = aep->at_tag_val; 714b25bcef8SMatt Jacob if (aep->at_flags & AT_TQAE) { 715b25bcef8SMatt Jacob cto->ct_flags |= CT_TQAE; 716b25bcef8SMatt Jacob } 717ea49c6e4SMatt Jacob cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA; 718ea49c6e4SMatt Jacob if (hdl == 0) { 719ea49c6e4SMatt Jacob cto->ct_flags |= CT_CCINCR; 720ea49c6e4SMatt Jacob } 721ea49c6e4SMatt Jacob cto->ct_scsi_status = sts; 722b0bd9b71SMatt Jacob cto->ct_syshandle = hdl; 723ea49c6e4SMatt Jacob } 724ea49c6e4SMatt Jacob return (isp_target_put_entry(isp, &un)); 725ea49c6e4SMatt Jacob } 726ea49c6e4SMatt Jacob 7279cd7268eSMatt Jacob /* 7289cd7268eSMatt Jacob * These are either broadcast events or specifically CTIO fast completion 7299cd7268eSMatt Jacob */ 730e63442b6SMatt Jacob int 7319cd7268eSMatt Jacob isp_target_async(ispsoftc_t *isp, int bus, int event) 732ea49c6e4SMatt Jacob { 733e5265237SMatt Jacob tmd_notify_t notify; 734e5265237SMatt Jacob 735e5265237SMatt Jacob MEMZERO(¬ify, sizeof (tmd_notify_t)); 736e5265237SMatt Jacob notify.nt_hba = isp; 737e5265237SMatt Jacob notify.nt_iid = INI_ANY; 738e5265237SMatt Jacob /* nt_tgt set in outer layers */ 739e5265237SMatt Jacob notify.nt_lun = LUN_ANY; 740e5265237SMatt Jacob notify.nt_tagval = TAG_ANY; 741e5265237SMatt Jacob 742e5265237SMatt Jacob if (IS_SCSI(isp)) { 743e5265237SMatt Jacob TAG_INSERT_BUS(notify.nt_tagval, bus); 744e5265237SMatt Jacob } 745ea49c6e4SMatt Jacob 746ea49c6e4SMatt Jacob switch (event) { 747e5265237SMatt Jacob case ASYNC_LOOP_UP: 748e5265237SMatt Jacob case ASYNC_PTPMODE: 749e5265237SMatt Jacob notify.nt_ncode = NT_LINK_UP; 750e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 751e5265237SMatt Jacob break; 752e5265237SMatt Jacob case ASYNC_LOOP_DOWN: 753e5265237SMatt Jacob notify.nt_ncode = NT_LINK_DOWN; 754e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 755e5265237SMatt Jacob break; 75610365e5aSMatt Jacob case ASYNC_LIP_ERROR: 75723ac1fceSMatt Jacob case ASYNC_LIP_F8: 758ea49c6e4SMatt Jacob case ASYNC_LIP_OCCURRED: 75923ac1fceSMatt Jacob case ASYNC_LOOP_RESET: 760e5265237SMatt Jacob notify.nt_ncode = NT_LIP_RESET; 761e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 762e5265237SMatt Jacob break; 763ea49c6e4SMatt Jacob case ASYNC_BUS_RESET: 764e5265237SMatt Jacob case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ 765e5265237SMatt Jacob notify.nt_ncode = NT_BUS_RESET; 766e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 767ea49c6e4SMatt Jacob break; 768ea49c6e4SMatt Jacob case ASYNC_DEVICE_RESET: 769e5265237SMatt Jacob notify.nt_ncode = NT_TARGET_RESET; 770e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 771ea49c6e4SMatt Jacob break; 7722f9e7606SMatt Jacob case ASYNC_CTIO_DONE: 773e5265237SMatt Jacob { 774e5265237SMatt Jacob uint8_t storage[QENTRY_LEN]; 775e5265237SMatt Jacob memset(storage, 0, QENTRY_LEN); 77610365e5aSMatt Jacob if (IS_24XX(isp)) { 77710365e5aSMatt Jacob ct7_entry_t *ct = (ct7_entry_t *) storage; 77810365e5aSMatt Jacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO7; 77910365e5aSMatt Jacob ct->ct_nphdl = CT7_OK; 78010365e5aSMatt Jacob ct->ct_syshandle = bus; 78110365e5aSMatt Jacob ct->ct_flags = CT7_SENDSTATUS|CT7_FASTPOST; 78210365e5aSMatt Jacob } else if (IS_FC(isp)) { 78399ece8d6SMatt Jacob /* This should also suffice for 2K login code */ 784e5265237SMatt Jacob ct2_entry_t *ct = (ct2_entry_t *) storage; 785e5265237SMatt Jacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 786e5265237SMatt Jacob ct->ct_status = CT_OK; 787e5265237SMatt Jacob ct->ct_syshandle = bus; 788e5265237SMatt Jacob ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; 789e5265237SMatt Jacob } else { 790e5265237SMatt Jacob ct_entry_t *ct = (ct_entry_t *) storage; 791e5265237SMatt Jacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; 792e5265237SMatt Jacob ct->ct_status = CT_OK; 793e5265237SMatt Jacob ct->ct_fwhandle = bus; 794e5265237SMatt Jacob ct->ct_flags = CT_SENDSTATUS; 795e5265237SMatt Jacob } 796e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); 79710365e5aSMatt Jacob break; 798e5265237SMatt Jacob } 799ea49c6e4SMatt Jacob default: 80010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 80110549c05SMatt Jacob "isp_target_async: unknown event 0x%x", event); 802e5265237SMatt Jacob if (isp->isp_state == ISP_RUNSTATE) { 803e5265237SMatt Jacob isp_notify_ack(isp, NULL); 804e5265237SMatt Jacob } 805ea49c6e4SMatt Jacob break; 806ea49c6e4SMatt Jacob } 807e63442b6SMatt Jacob return (0); 808ea49c6e4SMatt Jacob } 809ea49c6e4SMatt Jacob 810ea49c6e4SMatt Jacob 811ea49c6e4SMatt Jacob /* 812ea49c6e4SMatt Jacob * Process a received message. 813ea49c6e4SMatt Jacob * The ISP firmware can handle most messages, there are only 814ea49c6e4SMatt Jacob * a few that we need to deal with: 815ea49c6e4SMatt Jacob * - abort: clean up the current command 816ea49c6e4SMatt Jacob * - abort tag and clear queue 817ea49c6e4SMatt Jacob */ 818ea49c6e4SMatt Jacob 819ea49c6e4SMatt Jacob static void 8209cd7268eSMatt Jacob isp_got_msg(ispsoftc_t *isp, in_entry_t *inp) 821ea49c6e4SMatt Jacob { 822e5265237SMatt Jacob tmd_notify_t nt; 8231dae40ebSMatt Jacob uint8_t status = inp->in_status & ~QLTM_SVALID; 824ea49c6e4SMatt Jacob 825e5265237SMatt Jacob MEMZERO(&nt, sizeof (nt)); 826e5265237SMatt Jacob nt.nt_hba = isp; 827e5265237SMatt Jacob nt.nt_iid = GET_IID_VAL(inp->in_iid); 828e5265237SMatt Jacob nt.nt_tgt = inp->in_tgt; 829e5265237SMatt Jacob nt.nt_lun = inp->in_lun; 830e5265237SMatt Jacob IN_MAKE_TAGID(nt.nt_tagval, 0, inp); 831e5265237SMatt Jacob nt.nt_lreserved = inp; 832ea49c6e4SMatt Jacob 833e5265237SMatt Jacob if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { 834e5265237SMatt Jacob switch (inp->in_msg[0]) { 835e5265237SMatt Jacob case MSG_ABORT: 836e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK_SET; 837e5265237SMatt Jacob break; 838e5265237SMatt Jacob case MSG_BUS_DEV_RESET: 839e5265237SMatt Jacob nt.nt_ncode = NT_TARGET_RESET; 840e5265237SMatt Jacob break; 841e5265237SMatt Jacob case MSG_ABORT_TAG: 842e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK; 843e5265237SMatt Jacob break; 844e5265237SMatt Jacob case MSG_CLEAR_QUEUE: 845e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_TASK_SET; 846e5265237SMatt Jacob break; 847e5265237SMatt Jacob case MSG_REL_RECOVERY: 848e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_ACA; 849e5265237SMatt Jacob break; 850e5265237SMatt Jacob case MSG_TERM_IO_PROC: 851e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK; 852e5265237SMatt Jacob break; 853e5265237SMatt Jacob case MSG_LUN_RESET: 854e5265237SMatt Jacob nt.nt_ncode = NT_LUN_RESET; 855e5265237SMatt Jacob break; 856e5265237SMatt Jacob default: 857e5265237SMatt Jacob isp_prt(isp, ISP_LOGERR, 858e5265237SMatt Jacob "unhandled message 0x%x", inp->in_msg[0]); 859e5265237SMatt Jacob isp_notify_ack(isp, inp); 860e5265237SMatt Jacob return; 861e5265237SMatt Jacob } 862e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); 863ea49c6e4SMatt Jacob } else { 86410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 86510549c05SMatt Jacob "unknown immediate notify status 0x%x", inp->in_status); 866e5265237SMatt Jacob isp_notify_ack(isp, inp); 867ea49c6e4SMatt Jacob } 868ea49c6e4SMatt Jacob } 869ea49c6e4SMatt Jacob 870ea49c6e4SMatt Jacob /* 871ea49c6e4SMatt Jacob * Synthesize a message from the task management flags in a FCP_CMND_IU. 872ea49c6e4SMatt Jacob */ 873ea49c6e4SMatt Jacob static void 8749cd7268eSMatt Jacob isp_got_msg_fc(ispsoftc_t *isp, in_fcentry_t *inp) 875ea49c6e4SMatt Jacob { 876e5265237SMatt Jacob tmd_notify_t nt; 87710365e5aSMatt Jacob static const char f1[] = "%s from N-port handle 0x%x lun %d seq 0x%x"; 878b25bcef8SMatt Jacob static const char f2[] = 87910365e5aSMatt Jacob "unknown %s 0x%x lun %d N-Port handle 0x%x task flags 0x%x seq 0x%x\n"; 880b4110d46SMatt Jacob uint16_t seqid, loopid; 881ea49c6e4SMatt Jacob 882e5265237SMatt Jacob MEMZERO(&nt, sizeof (tmd_notify_t)); 883e5265237SMatt Jacob nt.nt_hba = isp; 88410365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 885e5265237SMatt Jacob nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; 886b4110d46SMatt Jacob loopid = ((in_fcentry_e_t *)inp)->in_iid; 8879cd7268eSMatt Jacob seqid = ((in_fcentry_e_t *)inp)->in_seqid; 888d82b6503SMatt Jacob } else { 8899cd7268eSMatt Jacob nt.nt_iid = inp->in_iid; 890b4110d46SMatt Jacob loopid = inp->in_iid; 8919cd7268eSMatt Jacob seqid = inp->in_seqid; 892d82b6503SMatt Jacob } 893e5265237SMatt Jacob /* nt_tgt set in outer layers */ 89410365e5aSMatt Jacob if (FCPARAM(isp)->isp_sccfw) { 895e5265237SMatt Jacob nt.nt_lun = inp->in_scclun; 896e5265237SMatt Jacob } else { 897e5265237SMatt Jacob nt.nt_lun = inp->in_lun; 898e5265237SMatt Jacob } 8999cd7268eSMatt Jacob IN_FC_MAKE_TAGID(nt.nt_tagval, 0, seqid); 90010365e5aSMatt Jacob nt.nt_need_ack = 1; 901e5265237SMatt Jacob nt.nt_lreserved = inp; 902d82b6503SMatt Jacob 903ea49c6e4SMatt Jacob if (inp->in_status != IN_MSG_RECEIVED) { 90410549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", 905b4110d46SMatt Jacob inp->in_status, nt.nt_lun, loopid, inp->in_task_flags, 906b4110d46SMatt Jacob inp->in_seqid); 907e5265237SMatt Jacob isp_notify_ack(isp, inp); 908e5265237SMatt Jacob return; 909e5265237SMatt Jacob } 910ea49c6e4SMatt Jacob 9112f9e7606SMatt Jacob if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { 9122f9e7606SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", 913b4110d46SMatt Jacob loopid, nt.nt_lun, inp->in_seqid); 914e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK_SET; 915ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { 91610549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", 917b4110d46SMatt Jacob loopid, nt.nt_lun, inp->in_seqid); 918e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_TASK_SET; 9192f9e7606SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { 9202f9e7606SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", 921b4110d46SMatt Jacob loopid, nt.nt_lun, inp->in_seqid); 922e5265237SMatt Jacob nt.nt_ncode = NT_LUN_RESET; 923ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { 92410549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", 925b4110d46SMatt Jacob loopid, nt.nt_lun, inp->in_seqid); 926e5265237SMatt Jacob nt.nt_ncode = NT_TARGET_RESET; 927ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { 92810549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", 929b4110d46SMatt Jacob loopid, nt.nt_lun, inp->in_seqid); 930e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_ACA; 931ea49c6e4SMatt Jacob } else { 932b4110d46SMatt Jacob isp_prt(isp, ISP_LOGWARN, f2, "task flag", inp->in_status, 933b4110d46SMatt Jacob nt.nt_lun, loopid, inp->in_task_flags, inp->in_seqid); 934e5265237SMatt Jacob isp_notify_ack(isp, inp); 935e5265237SMatt Jacob return; 936ea49c6e4SMatt Jacob } 937e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); 938ea49c6e4SMatt Jacob } 939ea49c6e4SMatt Jacob 94010365e5aSMatt Jacob static void 94110365e5aSMatt Jacob isp_got_tmf_24xx(ispsoftc_t *isp, at7_entry_t *aep) 94210365e5aSMatt Jacob { 94310365e5aSMatt Jacob tmd_notify_t nt; 94410365e5aSMatt Jacob static const char f1[] = "%s from PortID 0x%06x lun %d seq 0x%x"; 94510365e5aSMatt Jacob static const char f2[] = 94610365e5aSMatt Jacob "unknown Task Flag 0x%x lun %d PortID 0x%x tag 0x%x\n"; 94710365e5aSMatt Jacob uint32_t sid; 94810365e5aSMatt Jacob 94910365e5aSMatt Jacob MEMZERO(&nt, sizeof (tmd_notify_t)); 95010365e5aSMatt Jacob nt.nt_hba = isp; 95110365e5aSMatt Jacob nt.nt_iid = INI_ANY; 95210365e5aSMatt Jacob nt.nt_lun = 95310365e5aSMatt Jacob (aep->at_cmnd.fcp_cmnd_lun[0] << 8) | 95410365e5aSMatt Jacob (aep->at_cmnd.fcp_cmnd_lun[1]); 95510365e5aSMatt Jacob nt.nt_tagval = aep->at_rxid; 95610365e5aSMatt Jacob nt.nt_lreserved = aep; 95710365e5aSMatt Jacob sid = 95810365e5aSMatt Jacob (aep->at_hdr.s_id[0] << 16) | 95910365e5aSMatt Jacob (aep->at_hdr.s_id[1] << 8) | 96010365e5aSMatt Jacob (aep->at_hdr.s_id[2]); 96110365e5aSMatt Jacob 96210365e5aSMatt Jacob if (aep->at_cmnd.fcp_cmnd_task_management & 96310365e5aSMatt Jacob FCP_CMND_TMF_ABORT_TASK_SET) { 96410365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", 96510365e5aSMatt Jacob sid, nt.nt_lun, nt.nt_tagval); 96610365e5aSMatt Jacob nt.nt_ncode = NT_ABORT_TASK_SET; 96710365e5aSMatt Jacob } else if (aep->at_cmnd.fcp_cmnd_task_management & 96810365e5aSMatt Jacob FCP_CMND_TMF_CLEAR_TASK_SET) { 96910365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", 97010365e5aSMatt Jacob sid, nt.nt_lun, nt.nt_tagval); 97110365e5aSMatt Jacob nt.nt_ncode = NT_CLEAR_TASK_SET; 97210365e5aSMatt Jacob } else if (aep->at_cmnd.fcp_cmnd_task_management & 97310365e5aSMatt Jacob FCP_CMND_TMF_LUN_RESET) { 97410365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", 97510365e5aSMatt Jacob sid, nt.nt_lun, nt.nt_tagval); 97610365e5aSMatt Jacob nt.nt_ncode = NT_LUN_RESET; 97710365e5aSMatt Jacob } else if (aep->at_cmnd.fcp_cmnd_task_management & 97810365e5aSMatt Jacob FCP_CMND_TMF_TGT_RESET) { 97910365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", 98010365e5aSMatt Jacob sid, nt.nt_lun, nt.nt_tagval); 98110365e5aSMatt Jacob nt.nt_ncode = NT_TARGET_RESET; 98210365e5aSMatt Jacob nt.nt_lun = LUN_ANY; 98310365e5aSMatt Jacob } else if (aep->at_cmnd.fcp_cmnd_task_management & 98410365e5aSMatt Jacob FCP_CMND_TMF_CLEAR_ACA) { 98510365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", 98610365e5aSMatt Jacob sid, nt.nt_lun, nt.nt_tagval); 98710365e5aSMatt Jacob nt.nt_ncode = NT_CLEAR_ACA; 98810365e5aSMatt Jacob } else { 98910365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, f2, 99010365e5aSMatt Jacob aep->at_cmnd.fcp_cmnd_task_management, 99110365e5aSMatt Jacob nt.nt_lun, sid, nt.nt_tagval); 99210365e5aSMatt Jacob isp_endcmd(isp, aep, 0, 0); 99310365e5aSMatt Jacob return; 99410365e5aSMatt Jacob } 99510365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); 99610365e5aSMatt Jacob } 99710365e5aSMatt Jacob 998e5265237SMatt Jacob void 9999cd7268eSMatt Jacob isp_notify_ack(ispsoftc_t *isp, void *arg) 1000ea49c6e4SMatt Jacob { 1001ea49c6e4SMatt Jacob char storage[QENTRY_LEN]; 100210365e5aSMatt Jacob uint32_t nxti, optr; 1003ea49c6e4SMatt Jacob void *outp; 1004ea49c6e4SMatt Jacob 10054fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 100610549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, 100710549c05SMatt Jacob "Request Queue Overflow For isp_notify_ack"); 1008ea49c6e4SMatt Jacob return; 1009ea49c6e4SMatt Jacob } 1010ea49c6e4SMatt Jacob 10110c02c31bSMatt Jacob MEMZERO(storage, QENTRY_LEN); 1012ea49c6e4SMatt Jacob 101310365e5aSMatt Jacob if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ATIO)) { 101410365e5aSMatt Jacob at7_entry_t *aep = arg; 101510365e5aSMatt Jacob isp_endcmd(isp, aep, 0, 0); 101610365e5aSMatt Jacob return; 101710365e5aSMatt Jacob } else if (IS_24XX(isp) && arg != NULL && (((isphdr_t *)arg)->rqs_entry_type == RQSTYPE_ABTS_RSP)) { 101810365e5aSMatt Jacob abts_rsp_t *abts_rsp = (abts_rsp_t *) storage; 101910365e5aSMatt Jacob /* 102010365e5aSMatt Jacob * The caller will have set response values as appropriate 102110365e5aSMatt Jacob * in the ABTS structure just before calling us. 102210365e5aSMatt Jacob */ 102310365e5aSMatt Jacob MEMCPY(abts_rsp, arg, QENTRY_LEN); 102410365e5aSMatt Jacob isp_put_abts_rsp(isp, abts_rsp, (abts_rsp_t *)outp); 102510365e5aSMatt Jacob } else if (IS_24XX(isp)) { 102610365e5aSMatt Jacob na_fcentry_24xx_t *na = (na_fcentry_24xx_t *) storage; 102710365e5aSMatt Jacob if (arg) { 102810365e5aSMatt Jacob in_fcentry_24xx_t *in = arg; 102910365e5aSMatt Jacob na->na_nphdl = in->in_nphdl; 103010365e5aSMatt Jacob na->na_status = in->in_status; 103110365e5aSMatt Jacob na->na_status_subcode = in->in_status_subcode; 103210365e5aSMatt Jacob na->na_rxid = in->in_rxid; 103310365e5aSMatt Jacob na->na_oxid = in->in_oxid; 103410365e5aSMatt Jacob if (in->in_status == IN24XX_SRR_RCVD) { 103510365e5aSMatt Jacob na->na_srr_rxid = in->in_srr_rxid; 103610365e5aSMatt Jacob na->na_srr_reloff_hi = in->in_srr_reloff_hi; 103710365e5aSMatt Jacob na->na_srr_reloff_lo = in->in_srr_reloff_lo; 103810365e5aSMatt Jacob na->na_srr_iu = in->in_srr_iu; 103910365e5aSMatt Jacob na->na_srr_flags = 1; 104010365e5aSMatt Jacob na->na_srr_reject_vunique = 0; 104110365e5aSMatt Jacob na->na_srr_reject_explanation = 1; 104210365e5aSMatt Jacob na->na_srr_reject_code = 1; 104310365e5aSMatt Jacob } 104410365e5aSMatt Jacob } 104510365e5aSMatt Jacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 104610365e5aSMatt Jacob na->na_header.rqs_entry_count = 1; 104710365e5aSMatt Jacob isp_put_notify_24xx_ack(isp, na, (na_fcentry_24xx_t *)outp); 104810365e5aSMatt Jacob } else if (IS_FC(isp)) { 1049ea49c6e4SMatt Jacob na_fcentry_t *na = (na_fcentry_t *) storage; 1050b4110d46SMatt Jacob int iid = 0; 1051b4110d46SMatt Jacob 1052ea49c6e4SMatt Jacob if (arg) { 1053ea49c6e4SMatt Jacob in_fcentry_t *inp = arg; 10540c02c31bSMatt Jacob MEMCPY(storage, arg, sizeof (isphdr_t)); 105510365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 1056b4110d46SMatt Jacob ((na_fcentry_e_t *)na)->na_iid = 1057b4110d46SMatt Jacob ((in_fcentry_e_t *)inp)->in_iid; 1058b4110d46SMatt Jacob iid = ((na_fcentry_e_t *)na)->na_iid; 1059e5265237SMatt Jacob } else { 1060ea49c6e4SMatt Jacob na->na_iid = inp->in_iid; 1061b4110d46SMatt Jacob iid = na->na_iid; 1062e5265237SMatt Jacob } 1063b4110d46SMatt Jacob na->na_task_flags = 1064b4110d46SMatt Jacob inp->in_task_flags & TASK_FLAGS_RESERVED_MASK; 1065ea49c6e4SMatt Jacob na->na_seqid = inp->in_seqid; 1066ea49c6e4SMatt Jacob na->na_flags = NAFC_RCOUNT; 106775c1e828SMatt Jacob na->na_status = inp->in_status; 1068ea49c6e4SMatt Jacob if (inp->in_status == IN_RESET) { 1069ea49c6e4SMatt Jacob na->na_flags |= NAFC_RST_CLRD; 1070ea49c6e4SMatt Jacob } 1071b4110d46SMatt Jacob if (inp->in_status == IN_MSG_RECEIVED) { 1072b4110d46SMatt Jacob na->na_flags |= NAFC_TVALID; 1073b4110d46SMatt Jacob na->na_response = 0; /* XXX SUCCEEDED XXX */ 1074b4110d46SMatt Jacob } 1075ea49c6e4SMatt Jacob } else { 1076ea49c6e4SMatt Jacob na->na_flags = NAFC_RST_CLRD; 1077ea49c6e4SMatt Jacob } 10789dae8807SMatt Jacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 10799dae8807SMatt Jacob na->na_header.rqs_entry_count = 1; 108010365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 1081b4110d46SMatt Jacob isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, 1082b4110d46SMatt Jacob (na_fcentry_e_t *)outp); 1083e5265237SMatt Jacob } else { 10844fd13c1bSMatt Jacob isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); 1085e5265237SMatt Jacob } 108610365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u seqid %x " 108710365e5aSMatt Jacob "flags %x tflags %x response %x", iid, na->na_seqid, 1088b4110d46SMatt Jacob na->na_flags, na->na_task_flags, na->na_response); 1089ea49c6e4SMatt Jacob } else { 1090ea49c6e4SMatt Jacob na_entry_t *na = (na_entry_t *) storage; 1091ea49c6e4SMatt Jacob if (arg) { 1092ea49c6e4SMatt Jacob in_entry_t *inp = arg; 10930c02c31bSMatt Jacob MEMCPY(storage, arg, sizeof (isphdr_t)); 1094ea49c6e4SMatt Jacob na->na_iid = inp->in_iid; 1095ea49c6e4SMatt Jacob na->na_lun = inp->in_lun; 1096ea49c6e4SMatt Jacob na->na_tgt = inp->in_tgt; 1097ea49c6e4SMatt Jacob na->na_seqid = inp->in_seqid; 1098ea49c6e4SMatt Jacob if (inp->in_status == IN_RESET) { 10999dae8807SMatt Jacob na->na_event = NA_RST_CLRD; 1100ea49c6e4SMatt Jacob } 1101ea49c6e4SMatt Jacob } else { 11029dae8807SMatt Jacob na->na_event = NA_RST_CLRD; 1103ea49c6e4SMatt Jacob } 11049dae8807SMatt Jacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 11059dae8807SMatt Jacob na->na_header.rqs_entry_count = 1; 11064fd13c1bSMatt Jacob isp_put_notify_ack(isp, na, (na_entry_t *)outp); 110710365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, "notify ack loopid %u lun %u tgt " 110810365e5aSMatt Jacob "%u seqid %x event %x", na->na_iid, na->na_lun, na->na_tgt, 1109b4110d46SMatt Jacob na->na_seqid, na->na_event); 1110ea49c6e4SMatt Jacob } 1111ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage); 11124fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 1113ea49c6e4SMatt Jacob } 1114ea49c6e4SMatt Jacob 1115ea49c6e4SMatt Jacob static void 11169cd7268eSMatt Jacob isp_handle_atio(ispsoftc_t *isp, at_entry_t *aep) 1117ea49c6e4SMatt Jacob { 1118ea49c6e4SMatt Jacob int lun; 1119ea49c6e4SMatt Jacob lun = aep->at_lun; 1120ea49c6e4SMatt Jacob /* 1121ea49c6e4SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) indicates 1122ea49c6e4SMatt Jacob * why this ATIO was sent to us. 1123ea49c6e4SMatt Jacob * 1124ea49c6e4SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 1125ea49c6e4SMatt Jacob * 1126ea49c6e4SMatt Jacob * If the DISCONNECTS DISABLED bit is set in the flags field, 1127ea49c6e4SMatt Jacob * we're still connected on the SCSI bus - i.e. the initiator 1128ea49c6e4SMatt Jacob * did not set DiscPriv in the identify message. We don't care 1129ea49c6e4SMatt Jacob * about this so it's ignored. 1130ea49c6e4SMatt Jacob */ 1131ea49c6e4SMatt Jacob 1132ea49c6e4SMatt Jacob switch(aep->at_status & ~QLTM_SVALID) { 1133ea49c6e4SMatt Jacob case AT_PATH_INVALID: 1134ea49c6e4SMatt Jacob /* 1135ea49c6e4SMatt Jacob * ATIO rejected by the firmware due to disabled lun. 1136ea49c6e4SMatt Jacob */ 113710549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 113810549c05SMatt Jacob "rejected ATIO for disabled lun %d", lun); 1139ea49c6e4SMatt Jacob break; 1140ea49c6e4SMatt Jacob case AT_NOCAP: 1141ea49c6e4SMatt Jacob /* 1142ea49c6e4SMatt Jacob * Requested Capability not available 1143ea49c6e4SMatt Jacob * We sent an ATIO that overflowed the firmware's 1144ea49c6e4SMatt Jacob * command resource count. 1145ea49c6e4SMatt Jacob */ 114610549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 114710549c05SMatt Jacob "rejected ATIO for lun %d because of command count" 114810549c05SMatt Jacob " overflow", lun); 1149ea49c6e4SMatt Jacob break; 1150ea49c6e4SMatt Jacob 1151ea49c6e4SMatt Jacob case AT_BDR_MSG: 1152ea49c6e4SMatt Jacob /* 1153ea49c6e4SMatt Jacob * If we send an ATIO to the firmware to increment 1154ea49c6e4SMatt Jacob * its command resource count, and the firmware is 1155ea49c6e4SMatt Jacob * recovering from a Bus Device Reset, it returns 1156ea49c6e4SMatt Jacob * the ATIO with this status. We set the command 11574fd13c1bSMatt Jacob * resource count in the Enable Lun entry and do 1158ea49c6e4SMatt Jacob * not increment it. Therefore we should never get 1159ea49c6e4SMatt Jacob * this status here. 1160ea49c6e4SMatt Jacob */ 116123ac1fceSMatt Jacob isp_prt(isp, ISP_LOGERR, atiocope, lun, 116223ac1fceSMatt Jacob GET_BUS_VAL(aep->at_iid)); 1163ea49c6e4SMatt Jacob break; 1164ea49c6e4SMatt Jacob 1165ea49c6e4SMatt Jacob case AT_CDB: /* Got a CDB */ 1166ea49c6e4SMatt Jacob case AT_PHASE_ERROR: /* Bus Phase Sequence Error */ 1167ea49c6e4SMatt Jacob /* 1168ea49c6e4SMatt Jacob * Punt to platform specific layer. 1169ea49c6e4SMatt Jacob */ 1170ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 1171ea49c6e4SMatt Jacob break; 1172ea49c6e4SMatt Jacob 1173ea49c6e4SMatt Jacob case AT_RESET: 1174ea49c6e4SMatt Jacob /* 1175d64ada50SJens Schweikhardt * A bus reset came along and blew away this command. Why 1176ea49c6e4SMatt Jacob * they do this in addition the async event code stuff, 1177ea49c6e4SMatt Jacob * I dunno. 1178ea49c6e4SMatt Jacob * 1179ea49c6e4SMatt Jacob * Ignore it because the async event will clear things 1180ea49c6e4SMatt Jacob * up for us. 1181ea49c6e4SMatt Jacob */ 118223ac1fceSMatt Jacob isp_prt(isp, ISP_LOGWARN, atior, lun, 118323ac1fceSMatt Jacob GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid)); 1184ea49c6e4SMatt Jacob break; 1185ea49c6e4SMatt Jacob 1186ea49c6e4SMatt Jacob 1187ea49c6e4SMatt Jacob default: 118810549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 118910365e5aSMatt Jacob "Unknown ATIO status 0x%x from loopid %d for lun %d", 119010549c05SMatt Jacob aep->at_status, aep->at_iid, lun); 1191b25bcef8SMatt Jacob (void) isp_target_put_atio(isp, aep); 1192ea49c6e4SMatt Jacob break; 1193ea49c6e4SMatt Jacob } 1194ea49c6e4SMatt Jacob } 1195ea49c6e4SMatt Jacob 1196ea49c6e4SMatt Jacob static void 11979cd7268eSMatt Jacob isp_handle_atio2(ispsoftc_t *isp, at2_entry_t *aep) 1198ea49c6e4SMatt Jacob { 1199e5265237SMatt Jacob int lun, iid; 12002133e16fSMatt Jacob 120110365e5aSMatt Jacob if (FCPARAM(isp)->isp_sccfw) { 1202ea49c6e4SMatt Jacob lun = aep->at_scclun; 12032133e16fSMatt Jacob } else { 1204ea49c6e4SMatt Jacob lun = aep->at_lun; 12052133e16fSMatt Jacob } 12062133e16fSMatt Jacob 120710365e5aSMatt Jacob if (FCPARAM(isp)->isp_2klogin) { 1208e5265237SMatt Jacob iid = ((at2e_entry_t *)aep)->at_iid; 1209e5265237SMatt Jacob } else { 1210e5265237SMatt Jacob iid = aep->at_iid; 1211e5265237SMatt Jacob } 1212e5265237SMatt Jacob 1213ea49c6e4SMatt Jacob /* 1214ea49c6e4SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) indicates 1215ea49c6e4SMatt Jacob * why this ATIO was sent to us. 1216ea49c6e4SMatt Jacob * 1217ea49c6e4SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 1218ea49c6e4SMatt Jacob * 1219ea49c6e4SMatt Jacob * If the DISCONNECTS DISABLED bit is set in the flags field, 1220ea49c6e4SMatt Jacob * we're still connected on the SCSI bus - i.e. the initiator 1221ea49c6e4SMatt Jacob * did not set DiscPriv in the identify message. We don't care 1222ea49c6e4SMatt Jacob * about this so it's ignored. 1223ea49c6e4SMatt Jacob */ 1224ea49c6e4SMatt Jacob 1225ea49c6e4SMatt Jacob switch(aep->at_status & ~QLTM_SVALID) { 1226ea49c6e4SMatt Jacob case AT_PATH_INVALID: 1227ea49c6e4SMatt Jacob /* 1228ea49c6e4SMatt Jacob * ATIO rejected by the firmware due to disabled lun. 1229ea49c6e4SMatt Jacob */ 123010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 123110549c05SMatt Jacob "rejected ATIO2 for disabled lun %d", lun); 1232ea49c6e4SMatt Jacob break; 1233ea49c6e4SMatt Jacob case AT_NOCAP: 1234ea49c6e4SMatt Jacob /* 1235ea49c6e4SMatt Jacob * Requested Capability not available 1236ea49c6e4SMatt Jacob * We sent an ATIO that overflowed the firmware's 1237ea49c6e4SMatt Jacob * command resource count. 1238ea49c6e4SMatt Jacob */ 123910549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 124010549c05SMatt Jacob "rejected ATIO2 for lun %d- command count overflow", lun); 1241ea49c6e4SMatt Jacob break; 1242ea49c6e4SMatt Jacob 1243ea49c6e4SMatt Jacob case AT_BDR_MSG: 1244ea49c6e4SMatt Jacob /* 1245ea49c6e4SMatt Jacob * If we send an ATIO to the firmware to increment 1246ea49c6e4SMatt Jacob * its command resource count, and the firmware is 1247ea49c6e4SMatt Jacob * recovering from a Bus Device Reset, it returns 1248ea49c6e4SMatt Jacob * the ATIO with this status. We set the command 1249ea49c6e4SMatt Jacob * resource count in the Enable Lun entry and no 1250ea49c6e4SMatt Jacob * not increment it. Therefore we should never get 1251ea49c6e4SMatt Jacob * this status here. 1252ea49c6e4SMatt Jacob */ 125323ac1fceSMatt Jacob isp_prt(isp, ISP_LOGERR, atiocope, lun, 0); 1254ea49c6e4SMatt Jacob break; 1255ea49c6e4SMatt Jacob 1256ea49c6e4SMatt Jacob case AT_CDB: /* Got a CDB */ 1257ea49c6e4SMatt Jacob /* 1258ea49c6e4SMatt Jacob * Punt to platform specific layer. 1259ea49c6e4SMatt Jacob */ 1260ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 1261ea49c6e4SMatt Jacob break; 1262ea49c6e4SMatt Jacob 1263ea49c6e4SMatt Jacob case AT_RESET: 1264ea49c6e4SMatt Jacob /* 1265ea49c6e4SMatt Jacob * A bus reset came along an blew away this command. Why 1266ea49c6e4SMatt Jacob * they do this in addition the async event code stuff, 1267ea49c6e4SMatt Jacob * I dunno. 1268ea49c6e4SMatt Jacob * 1269ea49c6e4SMatt Jacob * Ignore it because the async event will clear things 1270ea49c6e4SMatt Jacob * up for us. 1271ea49c6e4SMatt Jacob */ 1272e5265237SMatt Jacob isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); 1273ea49c6e4SMatt Jacob break; 1274ea49c6e4SMatt Jacob 1275ea49c6e4SMatt Jacob 1276ea49c6e4SMatt Jacob default: 127710549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 127810365e5aSMatt Jacob "Unknown ATIO2 status 0x%x from loopid %d for lun %d", 1279e5265237SMatt Jacob aep->at_status, iid, lun); 1280b25bcef8SMatt Jacob (void) isp_target_put_atio(isp, aep); 1281ea49c6e4SMatt Jacob break; 1282ea49c6e4SMatt Jacob } 1283ea49c6e4SMatt Jacob } 1284ea49c6e4SMatt Jacob 1285ea49c6e4SMatt Jacob static void 12869cd7268eSMatt Jacob isp_handle_ctio(ispsoftc_t *isp, ct_entry_t *ct) 1287ea49c6e4SMatt Jacob { 1288b0bd9b71SMatt Jacob void *xs; 128910549c05SMatt Jacob int pl = ISP_LOGTDEBUG2; 1290ea49c6e4SMatt Jacob char *fmsg = NULL; 1291ea49c6e4SMatt Jacob 1292b0bd9b71SMatt Jacob if (ct->ct_syshandle) { 129351e23558SNate Lawson xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 129410365e5aSMatt Jacob if (xs == NULL) { 129510549c05SMatt Jacob pl = ISP_LOGALL; 129610365e5aSMatt Jacob } 1297ea49c6e4SMatt Jacob } else { 1298ea49c6e4SMatt Jacob xs = NULL; 1299ea49c6e4SMatt Jacob } 1300ea49c6e4SMatt Jacob 1301ea49c6e4SMatt Jacob switch(ct->ct_status & ~QLTM_SVALID) { 1302ea49c6e4SMatt Jacob case CT_OK: 1303ea49c6e4SMatt Jacob /* 1304ea49c6e4SMatt Jacob * There are generally 3 possibilities as to why we'd get 1305ea49c6e4SMatt Jacob * this condition: 1306ea49c6e4SMatt Jacob * We disconnected after receiving a CDB. 1307ea49c6e4SMatt Jacob * We sent or received data. 1308ea49c6e4SMatt Jacob * We sent status & command complete. 1309ea49c6e4SMatt Jacob */ 1310ea49c6e4SMatt Jacob 13119dae8807SMatt Jacob if (ct->ct_flags & CT_SENDSTATUS) { 13129dae8807SMatt Jacob break; 13139dae8807SMatt Jacob } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { 1314ea49c6e4SMatt Jacob /* 1315ea49c6e4SMatt Jacob * Nothing to do in this case. 1316ea49c6e4SMatt Jacob */ 131710549c05SMatt Jacob isp_prt(isp, pl, "CTIO- iid %d disconnected OK", 131810549c05SMatt Jacob ct->ct_iid); 1319ea49c6e4SMatt Jacob return; 1320ea49c6e4SMatt Jacob } 1321ea49c6e4SMatt Jacob break; 1322ea49c6e4SMatt Jacob 1323ea49c6e4SMatt Jacob case CT_BDR_MSG: 1324ea49c6e4SMatt Jacob /* 1325ea49c6e4SMatt Jacob * Bus Device Reset message received or the SCSI Bus has 1326ea49c6e4SMatt Jacob * been Reset; the firmware has gone to Bus Free. 1327ea49c6e4SMatt Jacob * 1328ea49c6e4SMatt Jacob * The firmware generates an async mailbox interupt to 1329ea49c6e4SMatt Jacob * notify us of this and returns outstanding CTIOs with this 1330ea49c6e4SMatt Jacob * status. These CTIOs are handled in that same way as 1331ea49c6e4SMatt Jacob * CT_ABORTED ones, so just fall through here. 1332ea49c6e4SMatt Jacob */ 1333ea49c6e4SMatt Jacob fmsg = "Bus Device Reset"; 1334ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1335ea49c6e4SMatt Jacob case CT_RESET: 1336ea49c6e4SMatt Jacob if (fmsg == NULL) 1337ea49c6e4SMatt Jacob fmsg = "Bus Reset"; 1338ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1339ea49c6e4SMatt Jacob case CT_ABORTED: 1340ea49c6e4SMatt Jacob /* 1341ea49c6e4SMatt Jacob * When an Abort message is received the firmware goes to 1342ea49c6e4SMatt Jacob * Bus Free and returns all outstanding CTIOs with the status 1343ea49c6e4SMatt Jacob * set, then sends us an Immediate Notify entry. 1344ea49c6e4SMatt Jacob */ 1345ea49c6e4SMatt Jacob if (fmsg == NULL) 134623ac1fceSMatt Jacob fmsg = "ABORT TAG message sent by Initiator"; 1347ea49c6e4SMatt Jacob 134810365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, "CTIO destroyed by %s", fmsg); 1349ea49c6e4SMatt Jacob break; 1350ea49c6e4SMatt Jacob 1351ea49c6e4SMatt Jacob case CT_INVAL: 1352ea49c6e4SMatt Jacob /* 1353ea49c6e4SMatt Jacob * CTIO rejected by the firmware due to disabled lun. 1354ea49c6e4SMatt Jacob * "Cannot Happen". 1355ea49c6e4SMatt Jacob */ 135610549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 135710549c05SMatt Jacob "Firmware rejected CTIO for disabled lun %d", 135810549c05SMatt Jacob ct->ct_lun); 1359ea49c6e4SMatt Jacob break; 1360ea49c6e4SMatt Jacob 1361ea49c6e4SMatt Jacob case CT_NOPATH: 1362ea49c6e4SMatt Jacob /* 1363ea49c6e4SMatt Jacob * CTIO rejected by the firmware due "no path for the 1364ea49c6e4SMatt Jacob * nondisconnecting nexus specified". This means that 1365ea49c6e4SMatt Jacob * we tried to access the bus while a non-disconnecting 1366ea49c6e4SMatt Jacob * command is in process. 1367ea49c6e4SMatt Jacob */ 136810549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 136910549c05SMatt Jacob "Firmware rejected CTIO for bad nexus %d/%d/%d", 137010549c05SMatt Jacob ct->ct_iid, ct->ct_tgt, ct->ct_lun); 1371ea49c6e4SMatt Jacob break; 1372ea49c6e4SMatt Jacob 1373ea49c6e4SMatt Jacob case CT_RSELTMO: 1374ea49c6e4SMatt Jacob fmsg = "Reselection"; 1375ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1376ea49c6e4SMatt Jacob case CT_TIMEOUT: 1377ea49c6e4SMatt Jacob if (fmsg == NULL) 1378ea49c6e4SMatt Jacob fmsg = "Command"; 137910549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); 1380ea49c6e4SMatt Jacob break; 1381ea49c6e4SMatt Jacob 1382b25bcef8SMatt Jacob case CT_PANIC: 1383b25bcef8SMatt Jacob if (fmsg == NULL) 1384b25bcef8SMatt Jacob fmsg = "Unrecoverable Error"; 1385b25bcef8SMatt Jacob /*FALLTHROUGH*/ 1386ea49c6e4SMatt Jacob case CT_ERR: 1387b25bcef8SMatt Jacob if (fmsg == NULL) 1388ea49c6e4SMatt Jacob fmsg = "Completed with Error"; 1389ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1390ea49c6e4SMatt Jacob case CT_PHASE_ERROR: 1391ea49c6e4SMatt Jacob if (fmsg == NULL) 1392ea49c6e4SMatt Jacob fmsg = "Phase Sequence Error"; 1393ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1394ea49c6e4SMatt Jacob case CT_TERMINATED: 1395ea49c6e4SMatt Jacob if (fmsg == NULL) 1396ea49c6e4SMatt Jacob fmsg = "terminated by TERMINATE TRANSFER"; 1397ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1398ea49c6e4SMatt Jacob case CT_NOACK: 1399ea49c6e4SMatt Jacob if (fmsg == NULL) 1400ea49c6e4SMatt Jacob fmsg = "unacknowledged Immediate Notify pending"; 140110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); 1402ea49c6e4SMatt Jacob break; 1403ea49c6e4SMatt Jacob default: 140410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", 1405ea49c6e4SMatt Jacob ct->ct_status & ~QLTM_SVALID); 1406ea49c6e4SMatt Jacob break; 1407ea49c6e4SMatt Jacob } 1408ea49c6e4SMatt Jacob 1409ea49c6e4SMatt Jacob if (xs == NULL) { 1410ea49c6e4SMatt Jacob /* 1411ea49c6e4SMatt Jacob * There may be more than one CTIO for a data transfer, 1412ea49c6e4SMatt Jacob * or this may be a status CTIO we're not monitoring. 1413ea49c6e4SMatt Jacob * 1414ea49c6e4SMatt Jacob * The assumption is that they'll all be returned in the 1415ea49c6e4SMatt Jacob * order we got them. 1416ea49c6e4SMatt Jacob */ 1417b0bd9b71SMatt Jacob if (ct->ct_syshandle == 0) { 1418ea49c6e4SMatt Jacob if ((ct->ct_flags & CT_SENDSTATUS) == 0) { 141910549c05SMatt Jacob isp_prt(isp, pl, 142010549c05SMatt Jacob "intermediate CTIO completed ok"); 1421ea49c6e4SMatt Jacob } else { 142210549c05SMatt Jacob isp_prt(isp, pl, 142310549c05SMatt Jacob "unmonitored CTIO completed ok"); 1424ea49c6e4SMatt Jacob } 1425ea49c6e4SMatt Jacob } else { 142610549c05SMatt Jacob isp_prt(isp, pl, 142710549c05SMatt Jacob "NO xs for CTIO (handle 0x%x) status 0x%x", 1428b0bd9b71SMatt Jacob ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1429ea49c6e4SMatt Jacob } 1430ea49c6e4SMatt Jacob } else { 1431ea49c6e4SMatt Jacob /* 1432ea49c6e4SMatt Jacob * Final CTIO completed. Release DMA resources and 1433ea49c6e4SMatt Jacob * notify platform dependent layers. 1434ea49c6e4SMatt Jacob */ 14355d571944SMatt Jacob if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { 1436b0bd9b71SMatt Jacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1437ea49c6e4SMatt Jacob } 1438b25bcef8SMatt Jacob isp_prt(isp, pl, "final CTIO complete"); 1439ea49c6e4SMatt Jacob /* 1440ea49c6e4SMatt Jacob * The platform layer will destroy the handle if appropriate. 1441ea49c6e4SMatt Jacob */ 1442b25bcef8SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1443ea49c6e4SMatt Jacob } 1444ea49c6e4SMatt Jacob } 1445ea49c6e4SMatt Jacob 1446ea49c6e4SMatt Jacob static void 14479cd7268eSMatt Jacob isp_handle_ctio2(ispsoftc_t *isp, ct2_entry_t *ct) 1448ea49c6e4SMatt Jacob { 144910365e5aSMatt Jacob void *xs; 145010549c05SMatt Jacob int pl = ISP_LOGTDEBUG2; 1451ea49c6e4SMatt Jacob char *fmsg = NULL; 1452ea49c6e4SMatt Jacob 1453b0bd9b71SMatt Jacob if (ct->ct_syshandle) { 145451e23558SNate Lawson xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 145510365e5aSMatt Jacob if (xs == NULL) { 145610549c05SMatt Jacob pl = ISP_LOGALL; 145710365e5aSMatt Jacob } 1458ea49c6e4SMatt Jacob } else { 1459ea49c6e4SMatt Jacob xs = NULL; 1460ea49c6e4SMatt Jacob } 1461ea49c6e4SMatt Jacob 1462ea49c6e4SMatt Jacob switch(ct->ct_status & ~QLTM_SVALID) { 14635d571944SMatt Jacob case CT_BUS_ERROR: 14645d571944SMatt Jacob isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 14655d571944SMatt Jacob /* FALL Through */ 14665d571944SMatt Jacob case CT_DATA_OVER: 14675d571944SMatt Jacob case CT_DATA_UNDER: 1468ea49c6e4SMatt Jacob case CT_OK: 1469ea49c6e4SMatt Jacob /* 1470ea49c6e4SMatt Jacob * There are generally 2 possibilities as to why we'd get 1471ea49c6e4SMatt Jacob * this condition: 1472ea49c6e4SMatt Jacob * We sent or received data. 1473ea49c6e4SMatt Jacob * We sent status & command complete. 1474ea49c6e4SMatt Jacob */ 1475ea49c6e4SMatt Jacob 1476ea49c6e4SMatt Jacob break; 1477ea49c6e4SMatt Jacob 1478ea49c6e4SMatt Jacob case CT_BDR_MSG: 1479ea49c6e4SMatt Jacob /* 14805d571944SMatt Jacob * Target Reset function received. 1481ea49c6e4SMatt Jacob * 1482ea49c6e4SMatt Jacob * The firmware generates an async mailbox interupt to 1483ea49c6e4SMatt Jacob * notify us of this and returns outstanding CTIOs with this 1484ea49c6e4SMatt Jacob * status. These CTIOs are handled in that same way as 1485ea49c6e4SMatt Jacob * CT_ABORTED ones, so just fall through here. 1486ea49c6e4SMatt Jacob */ 148710365e5aSMatt Jacob fmsg = "TARGET RESET"; 1488ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1489ea49c6e4SMatt Jacob case CT_RESET: 1490ea49c6e4SMatt Jacob if (fmsg == NULL) 14915d571944SMatt Jacob fmsg = "LIP Reset"; 1492ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1493ea49c6e4SMatt Jacob case CT_ABORTED: 1494ea49c6e4SMatt Jacob /* 1495ea49c6e4SMatt Jacob * When an Abort message is received the firmware goes to 1496ea49c6e4SMatt Jacob * Bus Free and returns all outstanding CTIOs with the status 1497ea49c6e4SMatt Jacob * set, then sends us an Immediate Notify entry. 1498ea49c6e4SMatt Jacob */ 149910365e5aSMatt Jacob if (fmsg == NULL) { 150010365e5aSMatt Jacob fmsg = "ABORT"; 150110365e5aSMatt Jacob } 1502ea49c6e4SMatt Jacob 150310365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 150410365e5aSMatt Jacob "CTIO2 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 1505ea49c6e4SMatt Jacob break; 1506ea49c6e4SMatt Jacob 1507ea49c6e4SMatt Jacob case CT_INVAL: 1508ea49c6e4SMatt Jacob /* 15090c02c31bSMatt Jacob * CTIO rejected by the firmware - invalid data direction. 1510ea49c6e4SMatt Jacob */ 15112f9e7606SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction"); 1512ea49c6e4SMatt Jacob break; 1513ea49c6e4SMatt Jacob 1514ea49c6e4SMatt Jacob case CT_RSELTMO: 15155d571944SMatt Jacob fmsg = "failure to reconnect to initiator"; 1516ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1517ea49c6e4SMatt Jacob case CT_TIMEOUT: 1518ea49c6e4SMatt Jacob if (fmsg == NULL) 15195d571944SMatt Jacob fmsg = "command"; 152010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); 1521ea49c6e4SMatt Jacob break; 1522ea49c6e4SMatt Jacob 1523ea49c6e4SMatt Jacob case CT_ERR: 1524ea49c6e4SMatt Jacob fmsg = "Completed with Error"; 1525ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1526ea49c6e4SMatt Jacob case CT_LOGOUT: 1527ea49c6e4SMatt Jacob if (fmsg == NULL) 1528ea49c6e4SMatt Jacob fmsg = "Port Logout"; 1529ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 153010365e5aSMatt Jacob case CT_PORTUNAVAIL: 1531ea49c6e4SMatt Jacob if (fmsg == NULL) 1532ea49c6e4SMatt Jacob fmsg = "Port not available"; 1533a0fb4cf1SPoul-Henning Kamp /*FALLTHROUGH*/ 15345d571944SMatt Jacob case CT_PORTCHANGED: 15355d571944SMatt Jacob if (fmsg == NULL) 15365d571944SMatt Jacob fmsg = "Port Changed"; 1537a0fb4cf1SPoul-Henning Kamp /*FALLTHROUGH*/ 1538ea49c6e4SMatt Jacob case CT_NOACK: 1539ea49c6e4SMatt Jacob if (fmsg == NULL) 1540ea49c6e4SMatt Jacob fmsg = "unacknowledged Immediate Notify pending"; 154110365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 1542ea49c6e4SMatt Jacob break; 1543ea49c6e4SMatt Jacob 1544ea49c6e4SMatt Jacob case CT_INVRXID: 1545ea49c6e4SMatt Jacob /* 1546ea49c6e4SMatt Jacob * CTIO rejected by the firmware because an invalid RX_ID. 1547ea49c6e4SMatt Jacob * Just print a message. 1548ea49c6e4SMatt Jacob */ 154910365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, 155010549c05SMatt Jacob "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1551ea49c6e4SMatt Jacob break; 1552ea49c6e4SMatt Jacob 1553ea49c6e4SMatt Jacob default: 1554b25bcef8SMatt Jacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", 155510549c05SMatt Jacob ct->ct_status & ~QLTM_SVALID); 1556ea49c6e4SMatt Jacob break; 1557ea49c6e4SMatt Jacob } 1558ea49c6e4SMatt Jacob 1559ea49c6e4SMatt Jacob if (xs == NULL) { 1560ea49c6e4SMatt Jacob /* 1561ea49c6e4SMatt Jacob * There may be more than one CTIO for a data transfer, 1562ea49c6e4SMatt Jacob * or this may be a status CTIO we're not monitoring. 1563ea49c6e4SMatt Jacob * 1564ea49c6e4SMatt Jacob * The assumption is that they'll all be returned in the 1565ea49c6e4SMatt Jacob * order we got them. 1566ea49c6e4SMatt Jacob */ 1567b0bd9b71SMatt Jacob if (ct->ct_syshandle == 0) { 1568ac9d0a02SMatt Jacob if ((ct->ct_flags & CT2_SENDSTATUS) == 0) { 156910549c05SMatt Jacob isp_prt(isp, pl, 157010549c05SMatt Jacob "intermediate CTIO completed ok"); 1571ea49c6e4SMatt Jacob } else { 157210549c05SMatt Jacob isp_prt(isp, pl, 157310549c05SMatt Jacob "unmonitored CTIO completed ok"); 1574ea49c6e4SMatt Jacob } 1575ea49c6e4SMatt Jacob } else { 157610549c05SMatt Jacob isp_prt(isp, pl, 157710549c05SMatt Jacob "NO xs for CTIO (handle 0x%x) status 0x%x", 1578b0bd9b71SMatt Jacob ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1579ea49c6e4SMatt Jacob } 1580ea49c6e4SMatt Jacob } else { 15815d571944SMatt Jacob if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { 15825d571944SMatt Jacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 15835d571944SMatt Jacob } 1584ac9d0a02SMatt Jacob if (ct->ct_flags & CT2_SENDSTATUS) { 1585ea49c6e4SMatt Jacob /* 1586ea49c6e4SMatt Jacob * Sent status and command complete. 1587ea49c6e4SMatt Jacob * 1588ea49c6e4SMatt Jacob * We're now really done with this command, so we 1589ea49c6e4SMatt Jacob * punt to the platform dependent layers because 1590ea49c6e4SMatt Jacob * only there can we do the appropriate command 1591ea49c6e4SMatt Jacob * complete thread synchronization. 1592ea49c6e4SMatt Jacob */ 159310549c05SMatt Jacob isp_prt(isp, pl, "status CTIO complete"); 1594ea49c6e4SMatt Jacob } else { 1595ea49c6e4SMatt Jacob /* 1596ea49c6e4SMatt Jacob * Final CTIO completed. Release DMA resources and 1597ea49c6e4SMatt Jacob * notify platform dependent layers. 1598ea49c6e4SMatt Jacob */ 159910549c05SMatt Jacob isp_prt(isp, pl, "data CTIO complete"); 1600ea49c6e4SMatt Jacob } 1601ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1602ea49c6e4SMatt Jacob /* 1603ea49c6e4SMatt Jacob * The platform layer will destroy the handle if appropriate. 1604ea49c6e4SMatt Jacob */ 1605ea49c6e4SMatt Jacob } 1606ea49c6e4SMatt Jacob } 160710365e5aSMatt Jacob 160810365e5aSMatt Jacob static void 160910365e5aSMatt Jacob isp_handle_ctio7(ispsoftc_t *isp, ct7_entry_t *ct) 161010365e5aSMatt Jacob { 161110365e5aSMatt Jacob void *xs; 161210365e5aSMatt Jacob int pl = ISP_LOGTDEBUG2; 161310365e5aSMatt Jacob char *fmsg = NULL; 161410365e5aSMatt Jacob 161510365e5aSMatt Jacob if (ct->ct_syshandle) { 161610365e5aSMatt Jacob xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 161710365e5aSMatt Jacob if (xs == NULL) { 161810365e5aSMatt Jacob pl = ISP_LOGALL; 161910365e5aSMatt Jacob } 162010365e5aSMatt Jacob } else { 162110365e5aSMatt Jacob xs = NULL; 162210365e5aSMatt Jacob } 162310365e5aSMatt Jacob 162410365e5aSMatt Jacob switch(ct->ct_nphdl) { 162510365e5aSMatt Jacob case CT7_BUS_ERROR: 162610365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 162710365e5aSMatt Jacob /* FALL Through */ 162810365e5aSMatt Jacob case CT7_DATA_OVER: 162910365e5aSMatt Jacob case CT7_DATA_UNDER: 163010365e5aSMatt Jacob case CT7_OK: 163110365e5aSMatt Jacob /* 163210365e5aSMatt Jacob * There are generally 2 possibilities as to why we'd get 163310365e5aSMatt Jacob * this condition: 163410365e5aSMatt Jacob * We sent or received data. 163510365e5aSMatt Jacob * We sent status & command complete. 163610365e5aSMatt Jacob */ 163710365e5aSMatt Jacob 163810365e5aSMatt Jacob break; 163910365e5aSMatt Jacob 164010365e5aSMatt Jacob case CT7_RESET: 164110365e5aSMatt Jacob if (fmsg == NULL) { 164210365e5aSMatt Jacob fmsg = "LIP Reset"; 164310365e5aSMatt Jacob } 164410365e5aSMatt Jacob /*FALLTHROUGH*/ 164510365e5aSMatt Jacob case CT7_ABORTED: 164610365e5aSMatt Jacob /* 164710365e5aSMatt Jacob * When an Abort message is received the firmware goes to 164810365e5aSMatt Jacob * Bus Free and returns all outstanding CTIOs with the status 164910365e5aSMatt Jacob * set, then sends us an Immediate Notify entry. 165010365e5aSMatt Jacob */ 165110365e5aSMatt Jacob if (fmsg == NULL) { 165210365e5aSMatt Jacob fmsg = "ABORT"; 165310365e5aSMatt Jacob } 165410365e5aSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 165510365e5aSMatt Jacob "CTIO7 destroyed by %s: RX_ID=0x%x", fmsg, ct->ct_rxid); 165610365e5aSMatt Jacob break; 165710365e5aSMatt Jacob 165810365e5aSMatt Jacob case CT7_TIMEOUT: 165910365e5aSMatt Jacob if (fmsg == NULL) { 166010365e5aSMatt Jacob fmsg = "command"; 166110365e5aSMatt Jacob } 166210365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); 166310365e5aSMatt Jacob break; 166410365e5aSMatt Jacob 166510365e5aSMatt Jacob case CT7_ERR: 166610365e5aSMatt Jacob fmsg = "Completed with Error"; 166710365e5aSMatt Jacob /*FALLTHROUGH*/ 166810365e5aSMatt Jacob case CT7_LOGOUT: 166910365e5aSMatt Jacob if (fmsg == NULL) { 167010365e5aSMatt Jacob fmsg = "Port Logout"; 167110365e5aSMatt Jacob } 167210365e5aSMatt Jacob /*FALLTHROUGH*/ 167310365e5aSMatt Jacob case CT7_PORTUNAVAIL: 167410365e5aSMatt Jacob if (fmsg == NULL) { 167510365e5aSMatt Jacob fmsg = "Port not available"; 167610365e5aSMatt Jacob } 167710365e5aSMatt Jacob /*FALLTHROUGH*/ 167810365e5aSMatt Jacob case CT7_PORTCHANGED: 167910365e5aSMatt Jacob if (fmsg == NULL) { 168010365e5aSMatt Jacob fmsg = "Port Changed"; 168110365e5aSMatt Jacob } 168210365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "CTIO returned by f/w- %s", fmsg); 168310365e5aSMatt Jacob break; 168410365e5aSMatt Jacob 168510365e5aSMatt Jacob case CT7_INVRXID: 168610365e5aSMatt Jacob /* 168710365e5aSMatt Jacob * CTIO rejected by the firmware because an invalid RX_ID. 168810365e5aSMatt Jacob * Just print a message. 168910365e5aSMatt Jacob */ 169010365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, 169110365e5aSMatt Jacob "CTIO7 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 169210365e5aSMatt Jacob break; 169310365e5aSMatt Jacob 169410365e5aSMatt Jacob case CT7_REASSY_ERR: 169510365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "reassembly error"); 169610365e5aSMatt Jacob break; 169710365e5aSMatt Jacob 169810365e5aSMatt Jacob case CT7_SRR: 169910365e5aSMatt Jacob isp_prt(isp, ISP_LOGWARN, "SRR received"); 170010365e5aSMatt Jacob break; 170110365e5aSMatt Jacob 170210365e5aSMatt Jacob default: 170310365e5aSMatt Jacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO7 status 0x%x", 170410365e5aSMatt Jacob ct->ct_nphdl); 170510365e5aSMatt Jacob break; 170610365e5aSMatt Jacob } 170710365e5aSMatt Jacob 170810365e5aSMatt Jacob if (xs == NULL) { 170910365e5aSMatt Jacob /* 171010365e5aSMatt Jacob * There may be more than one CTIO for a data transfer, 171110365e5aSMatt Jacob * or this may be a status CTIO we're not monitoring. 171210365e5aSMatt Jacob * 171310365e5aSMatt Jacob * The assumption is that they'll all be returned in the 171410365e5aSMatt Jacob * order we got them. 171510365e5aSMatt Jacob */ 171610365e5aSMatt Jacob if (ct->ct_syshandle == 0) { 171710365e5aSMatt Jacob if (ct->ct_flags & CT7_TERMINATE) { 171810365e5aSMatt Jacob isp_prt(isp, ISP_LOGINFO, 171910365e5aSMatt Jacob "termination of 0x%x complete", 172010365e5aSMatt Jacob ct->ct_rxid); 172110365e5aSMatt Jacob } else if ((ct->ct_flags & CT7_SENDSTATUS) == 0) { 172210365e5aSMatt Jacob isp_prt(isp, pl, 172310365e5aSMatt Jacob "intermediate CTIO completed ok"); 172410365e5aSMatt Jacob } else { 172510365e5aSMatt Jacob isp_prt(isp, pl, 172610365e5aSMatt Jacob "unmonitored CTIO completed ok"); 172710365e5aSMatt Jacob } 172810365e5aSMatt Jacob } else { 172910365e5aSMatt Jacob isp_prt(isp, pl, 173010365e5aSMatt Jacob "NO xs for CTIO (handle 0x%x) status 0x%x", 173110365e5aSMatt Jacob ct->ct_syshandle, ct->ct_nphdl); 173210365e5aSMatt Jacob } 173310365e5aSMatt Jacob } else { 173410365e5aSMatt Jacob if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { 173510365e5aSMatt Jacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 173610365e5aSMatt Jacob } 173710365e5aSMatt Jacob if (ct->ct_flags & CT2_SENDSTATUS) { 173810365e5aSMatt Jacob /* 173910365e5aSMatt Jacob * Sent status and command complete. 174010365e5aSMatt Jacob * 174110365e5aSMatt Jacob * We're now really done with this command, so we 174210365e5aSMatt Jacob * punt to the platform dependent layers because 174310365e5aSMatt Jacob * only there can we do the appropriate command 174410365e5aSMatt Jacob * complete thread synchronization. 174510365e5aSMatt Jacob */ 174610365e5aSMatt Jacob isp_prt(isp, pl, "status CTIO complete"); 174710365e5aSMatt Jacob } else { 174810365e5aSMatt Jacob /* 174910365e5aSMatt Jacob * Final CTIO completed. Release DMA resources and 175010365e5aSMatt Jacob * notify platform dependent layers. 175110365e5aSMatt Jacob */ 175210365e5aSMatt Jacob isp_prt(isp, pl, "data CTIO complete"); 175310365e5aSMatt Jacob } 175410365e5aSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 175510365e5aSMatt Jacob /* 175610365e5aSMatt Jacob * The platform layer will destroy the handle if appropriate. 175710365e5aSMatt Jacob */ 175810365e5aSMatt Jacob } 175910365e5aSMatt Jacob } 1760ea49c6e4SMatt Jacob #endif 1761