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 */ 281dae40ebSMatt Jacob #ifdef __FreeBSD__ 291dae40ebSMatt Jacob #include <sys/cdefs.h> 301dae40ebSMatt Jacob __FBSDID("$FreeBSD$"); 311dae40ebSMatt Jacob #endif 32ea49c6e4SMatt Jacob 33ea49c6e4SMatt Jacob /* 3475c1e828SMatt Jacob * Bug fixes gratefully acknowledged from: 3575c1e828SMatt Jacob * Oded Kedem <oded@kashya.com> 3675c1e828SMatt Jacob */ 3775c1e828SMatt Jacob /* 38ea49c6e4SMatt Jacob * Include header file appropriate for platform we're building on. 39ea49c6e4SMatt Jacob */ 40ea49c6e4SMatt Jacob 41ea49c6e4SMatt Jacob #ifdef __NetBSD__ 42ea49c6e4SMatt Jacob #include <dev/ic/isp_netbsd.h> 43ea49c6e4SMatt Jacob #endif 44ea49c6e4SMatt Jacob #ifdef __FreeBSD__ 45ea49c6e4SMatt Jacob #include <dev/isp/isp_freebsd.h> 46ea49c6e4SMatt Jacob #endif 47ea49c6e4SMatt Jacob #ifdef __OpenBSD__ 48ea49c6e4SMatt Jacob #include <dev/ic/isp_openbsd.h> 49ea49c6e4SMatt Jacob #endif 50ea49c6e4SMatt Jacob #ifdef __linux__ 51ea49c6e4SMatt Jacob #include "isp_linux.h" 52ea49c6e4SMatt Jacob #endif 53ea49c6e4SMatt Jacob 54ea49c6e4SMatt Jacob #ifdef ISP_TARGET_MODE 55b25bcef8SMatt Jacob static const char atiocope[] = 5623ac1fceSMatt Jacob "ATIO returned for lun %d because it was in the middle of Bus Device Reset " 5723ac1fceSMatt Jacob "on bus %d"; 58b25bcef8SMatt Jacob static const char atior[] = 5923ac1fceSMatt Jacob "ATIO returned on for lun %d on from IID %d because a Bus Reset occurred " 6023ac1fceSMatt Jacob "on bus %d"; 61ea49c6e4SMatt Jacob 62e5265237SMatt Jacob static void isp_got_msg(struct ispsoftc *, in_entry_t *); 63e5265237SMatt Jacob static void isp_got_msg_fc(struct ispsoftc *, in_fcentry_t *); 64ea49c6e4SMatt Jacob static void isp_handle_atio(struct ispsoftc *, at_entry_t *); 65ea49c6e4SMatt Jacob static void isp_handle_atio2(struct ispsoftc *, at2_entry_t *); 66ea49c6e4SMatt Jacob static void isp_handle_ctio(struct ispsoftc *, ct_entry_t *); 67ea49c6e4SMatt Jacob static void isp_handle_ctio2(struct ispsoftc *, ct2_entry_t *); 68ea49c6e4SMatt Jacob 69ea49c6e4SMatt Jacob /* 70ea49c6e4SMatt Jacob * The Qlogic driver gets an interrupt to look at response queue entries. 71ea49c6e4SMatt Jacob * Some of these are status completions for initiatior mode commands, but 72ea49c6e4SMatt Jacob * if target mode is enabled, we get a whole wad of response queue entries 73ea49c6e4SMatt Jacob * to be handled here. 74ea49c6e4SMatt Jacob * 75ea49c6e4SMatt Jacob * Basically the split into 3 main groups: Lun Enable/Modification responses, 76ea49c6e4SMatt Jacob * SCSI Command processing, and Immediate Notification events. 77ea49c6e4SMatt Jacob * 78ea49c6e4SMatt Jacob * You start by writing a request queue entry to enable target mode (and 79ea49c6e4SMatt Jacob * establish some resource limitations which you can modify later). 80ea49c6e4SMatt Jacob * The f/w responds with a LUN ENABLE or LUN MODIFY response with 81ea49c6e4SMatt Jacob * the status of this action. If the enable was successful, you can expect... 82ea49c6e4SMatt Jacob * 83ea49c6e4SMatt Jacob * Response queue entries with SCSI commands encapsulate show up in an ATIO 84ea49c6e4SMatt Jacob * (Accept Target IO) type- sometimes with enough info to stop the command at 85ea49c6e4SMatt Jacob * this level. Ultimately the driver has to feed back to the f/w's request 86ea49c6e4SMatt Jacob * queue a sequence of CTIOs (continue target I/O) that describe data to 87ea49c6e4SMatt Jacob * be moved and/or status to be sent) and finally finishing with sending 88ea49c6e4SMatt Jacob * to the f/w's response queue an ATIO which then completes the handshake 89ea49c6e4SMatt Jacob * with the f/w for that command. There's a lot of variations on this theme, 90ea49c6e4SMatt Jacob * including flags you can set in the CTIO for the Qlogic 2X00 fibre channel 91ea49c6e4SMatt Jacob * cards that 'auto-replenish' the f/w's ATIO count, but this is the basic 92ea49c6e4SMatt Jacob * gist of it. 93ea49c6e4SMatt Jacob * 94ea49c6e4SMatt Jacob * The third group that can show up in the response queue are Immediate 95ea49c6e4SMatt Jacob * Notification events. These include things like notifications of SCSI bus 96ea49c6e4SMatt Jacob * resets, or Bus Device Reset messages or other messages received. This 97f09deb69SJeroen Ruigrok van der Werven * a classic oddbins area. It can get a little weird because you then turn 98ea49c6e4SMatt Jacob * around and acknowledge the Immediate Notify by writing an entry onto the 99ea49c6e4SMatt Jacob * request queue and then the f/w turns around and gives you an acknowledgement 100ea49c6e4SMatt Jacob * to *your* acknowledgement on the response queue (the idea being to let 101ea49c6e4SMatt Jacob * the f/w tell you when the event is *really* over I guess). 102ea49c6e4SMatt Jacob * 103ea49c6e4SMatt Jacob */ 104ea49c6e4SMatt Jacob 105ea49c6e4SMatt Jacob 106ea49c6e4SMatt Jacob /* 107ea49c6e4SMatt Jacob * A new response queue entry has arrived. The interrupt service code 108ea49c6e4SMatt Jacob * has already swizzled it into the platform dependent from canonical form. 109ea49c6e4SMatt Jacob * 110ea49c6e4SMatt Jacob * Because of the way this driver is designed, unfortunately most of the 111ea49c6e4SMatt Jacob * actual synchronization work has to be done in the platform specific 112ea49c6e4SMatt Jacob * code- we have no synchroniation primitives in the common code. 113ea49c6e4SMatt Jacob */ 114ea49c6e4SMatt Jacob 115ea49c6e4SMatt Jacob int 1161dae40ebSMatt Jacob isp_target_notify(struct ispsoftc *isp, void *vptr, uint16_t *optrp) 117ea49c6e4SMatt Jacob { 1181dae40ebSMatt Jacob uint16_t status, seqid; 119ea49c6e4SMatt Jacob union { 120ea49c6e4SMatt Jacob at_entry_t *atiop; 121ea49c6e4SMatt Jacob at2_entry_t *at2iop; 122e5265237SMatt Jacob at2e_entry_t *at2eiop; 123ea49c6e4SMatt Jacob ct_entry_t *ctiop; 124ea49c6e4SMatt Jacob ct2_entry_t *ct2iop; 125e5265237SMatt Jacob ct2e_entry_t *ct2eiop; 126ea49c6e4SMatt Jacob lun_entry_t *lunenp; 127ea49c6e4SMatt Jacob in_entry_t *inotp; 128ea49c6e4SMatt Jacob in_fcentry_t *inot_fcp; 129e5265237SMatt Jacob in_fcentry_e_t *inote_fcp; 130ea49c6e4SMatt Jacob na_entry_t *nackp; 131ea49c6e4SMatt Jacob na_fcentry_t *nack_fcp; 132e5265237SMatt Jacob na_fcentry_e_t *nacke_fcp; 133ea49c6e4SMatt Jacob isphdr_t *hp; 134ea49c6e4SMatt Jacob void * *vp; 135ea49c6e4SMatt Jacob #define atiop unp.atiop 136ea49c6e4SMatt Jacob #define at2iop unp.at2iop 137e5265237SMatt Jacob #define at2eiop unp.at2eiop 138ea49c6e4SMatt Jacob #define ctiop unp.ctiop 139ea49c6e4SMatt Jacob #define ct2iop unp.ct2iop 140e5265237SMatt Jacob #define ct2eiop unp.ct2eiop 141ea49c6e4SMatt Jacob #define lunenp unp.lunenp 142ea49c6e4SMatt Jacob #define inotp unp.inotp 143ea49c6e4SMatt Jacob #define inot_fcp unp.inot_fcp 144e5265237SMatt Jacob #define inote_fcp unp.inote_fcp 145ea49c6e4SMatt Jacob #define nackp unp.nackp 146ea49c6e4SMatt Jacob #define nack_fcp unp.nack_fcp 147e5265237SMatt Jacob #define nacke_fcp unp.nacke_fcp 148ea49c6e4SMatt Jacob #define hdrp unp.hp 149ea49c6e4SMatt Jacob } unp; 1501dae40ebSMatt Jacob uint8_t local[QENTRY_LEN]; 151e63442b6SMatt Jacob int bus, type, rval = 1; 152ea49c6e4SMatt Jacob 1534fd13c1bSMatt Jacob type = isp_get_response_type(isp, (isphdr_t *)vptr); 154ea49c6e4SMatt Jacob unp.vp = vptr; 155ea49c6e4SMatt Jacob 156ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_target_notify", (int) *optrp, vptr); 157ea49c6e4SMatt Jacob 1584fd13c1bSMatt Jacob switch(type) { 159ea49c6e4SMatt Jacob case RQSTYPE_ATIO: 1604fd13c1bSMatt Jacob isp_get_atio(isp, atiop, (at_entry_t *) local); 1614fd13c1bSMatt Jacob isp_handle_atio(isp, (at_entry_t *) local); 162ea49c6e4SMatt Jacob break; 163ea49c6e4SMatt Jacob case RQSTYPE_CTIO: 1644fd13c1bSMatt Jacob isp_get_ctio(isp, ctiop, (ct_entry_t *) local); 1654fd13c1bSMatt Jacob isp_handle_ctio(isp, (ct_entry_t *) local); 166ea49c6e4SMatt Jacob break; 167ea49c6e4SMatt Jacob case RQSTYPE_ATIO2: 168e5265237SMatt Jacob if (IS_2KLOGIN(isp)) 169e5265237SMatt Jacob isp_get_atio2e(isp, at2eiop, (at2e_entry_t *) local); 170e5265237SMatt Jacob else 1714fd13c1bSMatt Jacob isp_get_atio2(isp, at2iop, (at2_entry_t *) local); 1724fd13c1bSMatt Jacob isp_handle_atio2(isp, (at2_entry_t *) local); 173ea49c6e4SMatt Jacob break; 174ac9d0a02SMatt Jacob case RQSTYPE_CTIO3: 175ea49c6e4SMatt Jacob case RQSTYPE_CTIO2: 176e5265237SMatt Jacob if (IS_2KLOGIN(isp)) 177e5265237SMatt Jacob isp_get_ctio2e(isp, ct2eiop, (ct2e_entry_t *) local); 178e5265237SMatt Jacob else 1794fd13c1bSMatt Jacob isp_get_ctio2(isp, ct2iop, (ct2_entry_t *) local); 1804fd13c1bSMatt Jacob isp_handle_ctio2(isp, (ct2_entry_t *) local); 181ea49c6e4SMatt Jacob break; 182ea49c6e4SMatt Jacob case RQSTYPE_ENABLE_LUN: 183ea49c6e4SMatt Jacob case RQSTYPE_MODIFY_LUN: 1844fd13c1bSMatt Jacob isp_get_enable_lun(isp, lunenp, (lun_entry_t *) local); 1854fd13c1bSMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, local); 186ea49c6e4SMatt Jacob break; 187ea49c6e4SMatt Jacob 188ea49c6e4SMatt Jacob case RQSTYPE_NOTIFY: 189ea49c6e4SMatt Jacob /* 190ea49c6e4SMatt Jacob * Either the ISP received a SCSI message it can't 191ea49c6e4SMatt Jacob * handle, or it's returning an Immed. Notify entry 192ea49c6e4SMatt Jacob * we sent. We can send Immed. Notify entries to 193ea49c6e4SMatt Jacob * increment the firmware's resource count for them 194ea49c6e4SMatt Jacob * (we set this initially in the Enable Lun entry). 195ea49c6e4SMatt Jacob */ 19614a37293SMatt Jacob bus = 0; 197ea49c6e4SMatt Jacob if (IS_FC(isp)) { 198e5265237SMatt Jacob if (IS_2KLOGIN(isp)) 199e5265237SMatt Jacob isp_get_notify_fc_e(isp, inote_fcp, (in_fcentry_e_t *)local); 2004fd13c1bSMatt Jacob isp_get_notify_fc(isp, inot_fcp, (in_fcentry_t *)local); 2014fd13c1bSMatt Jacob inot_fcp = (in_fcentry_t *) local; 202ea49c6e4SMatt Jacob status = inot_fcp->in_status; 203ea49c6e4SMatt Jacob seqid = inot_fcp->in_seqid; 204ea49c6e4SMatt Jacob } else { 2054fd13c1bSMatt Jacob isp_get_notify(isp, inotp, (in_entry_t *)local); 2064fd13c1bSMatt Jacob inotp = (in_entry_t *) local; 207ea49c6e4SMatt Jacob status = inotp->in_status & 0xff; 208ea49c6e4SMatt Jacob seqid = inotp->in_seqid; 20914a37293SMatt Jacob if (IS_DUALBUS(isp)) { 21023ac1fceSMatt Jacob bus = GET_BUS_VAL(inotp->in_iid); 21123ac1fceSMatt Jacob SET_BUS_VAL(inotp->in_iid, 0); 212ea49c6e4SMatt Jacob } 21314a37293SMatt Jacob } 21423ac1fceSMatt Jacob isp_prt(isp, ISP_LOGTDEBUG0, 21523ac1fceSMatt Jacob "Immediate Notify On Bus %d, status=0x%x seqid=0x%x", 21623ac1fceSMatt Jacob bus, status, seqid); 21723ac1fceSMatt Jacob 218ea49c6e4SMatt Jacob switch (status) { 219ea49c6e4SMatt Jacob case IN_MSG_RECEIVED: 220ea49c6e4SMatt Jacob case IN_IDE_RECEIVED: 221ea49c6e4SMatt Jacob if (IS_FC(isp)) { 222e5265237SMatt Jacob isp_got_msg_fc(isp, (in_fcentry_t *)local); 223ea49c6e4SMatt Jacob } else { 224e5265237SMatt Jacob isp_got_msg(isp, (in_entry_t *)local); 225ea49c6e4SMatt Jacob } 226ea49c6e4SMatt Jacob break; 227ea49c6e4SMatt Jacob case IN_RSRC_UNAVAIL: 22810549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, "Firmware out of ATIOs"); 229e5265237SMatt Jacob isp_notify_ack(isp, local); 230e5265237SMatt Jacob break; 231e5265237SMatt Jacob case IN_RESET: 232e5265237SMatt Jacob isp_target_async(isp, 0, ASYNC_BUS_RESET); 233ea49c6e4SMatt Jacob break; 234ea49c6e4SMatt Jacob case IN_PORT_LOGOUT: 235e63442b6SMatt Jacob case IN_ABORT_TASK: 236ea49c6e4SMatt Jacob case IN_PORT_CHANGED: 237ea49c6e4SMatt Jacob case IN_GLOBAL_LOGO: 238e63442b6SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, &local); 239ea49c6e4SMatt Jacob break; 240ea49c6e4SMatt Jacob default: 24110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 24210549c05SMatt Jacob "bad status (0x%x) in isp_target_notify", status); 243e5265237SMatt Jacob isp_notify_ack(isp, local); 244ea49c6e4SMatt Jacob break; 245ea49c6e4SMatt Jacob } 246ea49c6e4SMatt Jacob break; 247ea49c6e4SMatt Jacob 248ea49c6e4SMatt Jacob case RQSTYPE_NOTIFY_ACK: 249ea49c6e4SMatt Jacob /* 250ea49c6e4SMatt Jacob * The ISP is acknowledging our acknowledgement of an 251ea49c6e4SMatt Jacob * Immediate Notify entry for some asynchronous event. 252ea49c6e4SMatt Jacob */ 253ea49c6e4SMatt Jacob if (IS_FC(isp)) { 254e5265237SMatt Jacob if (IS_2KLOGIN(isp)) 255e5265237SMatt Jacob isp_get_notify_ack_fc_e(isp, nacke_fcp, 256e5265237SMatt Jacob (na_fcentry_e_t *)local); 257e5265237SMatt Jacob else 2584fd13c1bSMatt Jacob isp_get_notify_ack_fc(isp, nack_fcp, 2594fd13c1bSMatt Jacob (na_fcentry_t *)local); 2604fd13c1bSMatt Jacob nack_fcp = (na_fcentry_t *)local; 26110549c05SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 26210549c05SMatt Jacob "Notify Ack status=0x%x seqid 0x%x", 26310549c05SMatt Jacob nack_fcp->na_status, nack_fcp->na_seqid); 264ea49c6e4SMatt Jacob } else { 2654fd13c1bSMatt Jacob isp_get_notify_ack(isp, nackp, (na_entry_t *)local); 2664fd13c1bSMatt Jacob nackp = (na_entry_t *)local; 26710549c05SMatt Jacob isp_prt(isp, ISP_LOGTDEBUG1, 26810549c05SMatt Jacob "Notify Ack event 0x%x status=0x%x seqid 0x%x", 26910549c05SMatt Jacob nackp->na_event, nackp->na_status, nackp->na_seqid); 270ea49c6e4SMatt Jacob } 271ea49c6e4SMatt Jacob break; 272ea49c6e4SMatt Jacob default: 27310549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 2744fd13c1bSMatt Jacob "Unknown entry type 0x%x in isp_target_notify", type); 275e63442b6SMatt Jacob rval = 0; 276ea49c6e4SMatt Jacob break; 277ea49c6e4SMatt Jacob } 278ea49c6e4SMatt Jacob #undef atiop 279ea49c6e4SMatt Jacob #undef at2iop 280e5265237SMatt Jacob #undef at2eiop 281ea49c6e4SMatt Jacob #undef ctiop 282ea49c6e4SMatt Jacob #undef ct2iop 283e5265237SMatt Jacob #undef ct2eiop 284ea49c6e4SMatt Jacob #undef lunenp 285ea49c6e4SMatt Jacob #undef inotp 286ea49c6e4SMatt Jacob #undef inot_fcp 287e5265237SMatt Jacob #undef inote_fcp 288ea49c6e4SMatt Jacob #undef nackp 289ea49c6e4SMatt Jacob #undef nack_fcp 290e5265237SMatt Jacob #undef nacke_fcp 291ea49c6e4SMatt Jacob #undef hdrp 292ea49c6e4SMatt Jacob return (rval); 293ea49c6e4SMatt Jacob } 294ea49c6e4SMatt Jacob 295ea49c6e4SMatt Jacob 296ea49c6e4SMatt Jacob /* 297ea49c6e4SMatt Jacob * Toggle (on/off) target mode for bus/target/lun 298ea49c6e4SMatt Jacob * 299ea49c6e4SMatt Jacob * The caller has checked for overlap and legality. 300ea49c6e4SMatt Jacob * 301ea49c6e4SMatt Jacob * Note that not all of bus, target or lun can be paid attention to. 302ea49c6e4SMatt Jacob * Note also that this action will not be complete until the f/w writes 303ea49c6e4SMatt Jacob * response entry. The caller is responsible for synchronizing this. 304ea49c6e4SMatt Jacob */ 305ea49c6e4SMatt Jacob int 306b25bcef8SMatt Jacob isp_lun_cmd(struct ispsoftc *isp, int cmd, int bus, int tgt, int lun, 3071dae40ebSMatt Jacob int cmd_cnt, int inot_cnt, uint32_t opaque) 308ea49c6e4SMatt Jacob { 309ea49c6e4SMatt Jacob lun_entry_t el; 3101dae40ebSMatt Jacob uint16_t nxti, optr; 311ea49c6e4SMatt Jacob void *outp; 312ea49c6e4SMatt Jacob 313ea49c6e4SMatt Jacob 314ea49c6e4SMatt Jacob MEMZERO(&el, sizeof (el)); 31514a37293SMatt Jacob if (IS_DUALBUS(isp)) { 31614a37293SMatt Jacob el.le_rsvd = (bus & 0x1) << 7; 31714a37293SMatt Jacob } 3185d571944SMatt Jacob el.le_cmd_count = cmd_cnt; 3195d571944SMatt Jacob el.le_in_count = inot_cnt; 320ea49c6e4SMatt Jacob if (cmd == RQSTYPE_ENABLE_LUN) { 321ea49c6e4SMatt Jacob if (IS_SCSI(isp)) { 3222133e16fSMatt Jacob el.le_flags = LUN_TQAE|LUN_DISAD; 323ea49c6e4SMatt Jacob el.le_cdb6len = 12; 324ea49c6e4SMatt Jacob el.le_cdb7len = 12; 325ea49c6e4SMatt Jacob } 326ea49c6e4SMatt Jacob } else if (cmd == -RQSTYPE_ENABLE_LUN) { 327ea49c6e4SMatt Jacob cmd = RQSTYPE_ENABLE_LUN; 328ea49c6e4SMatt Jacob el.le_cmd_count = 0; 329ea49c6e4SMatt Jacob el.le_in_count = 0; 330ea49c6e4SMatt Jacob } else if (cmd == -RQSTYPE_MODIFY_LUN) { 331ea49c6e4SMatt Jacob cmd = RQSTYPE_MODIFY_LUN; 332ea49c6e4SMatt Jacob el.le_ops = LUN_CCDECR | LUN_INDECR; 333ea49c6e4SMatt Jacob } else { 334ea49c6e4SMatt Jacob el.le_ops = LUN_CCINCR | LUN_ININCR; 335ea49c6e4SMatt Jacob } 336ea49c6e4SMatt Jacob el.le_header.rqs_entry_type = cmd; 337ea49c6e4SMatt Jacob el.le_header.rqs_entry_count = 1; 338ea49c6e4SMatt Jacob el.le_reserved = opaque; 339ea49c6e4SMatt Jacob if (IS_SCSI(isp)) { 340ea49c6e4SMatt Jacob el.le_tgt = tgt; 341ea49c6e4SMatt Jacob el.le_lun = lun; 34223ac1fceSMatt Jacob } else if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { 343ea49c6e4SMatt Jacob el.le_lun = lun; 344ea49c6e4SMatt Jacob } 345b25bcef8SMatt Jacob el.le_timeout = 2; 346ea49c6e4SMatt Jacob 3474fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 3484fd13c1bSMatt Jacob isp_prt(isp, ISP_LOGERR, 34910549c05SMatt Jacob "Request Queue Overflow in isp_lun_cmd"); 350ea49c6e4SMatt Jacob return (-1); 351ea49c6e4SMatt Jacob } 352ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_lun_cmd", (int) optr, &el); 3534fd13c1bSMatt Jacob isp_put_enable_lun(isp, &el, outp); 3544fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 355ea49c6e4SMatt Jacob return (0); 356ea49c6e4SMatt Jacob } 357ea49c6e4SMatt Jacob 358ea49c6e4SMatt Jacob 359ea49c6e4SMatt Jacob int 360b25bcef8SMatt Jacob isp_target_put_entry(struct ispsoftc *isp, void *ap) 361ea49c6e4SMatt Jacob { 362ea49c6e4SMatt Jacob void *outp; 3631dae40ebSMatt Jacob uint16_t nxti, optr; 3641dae40ebSMatt Jacob uint8_t etype = ((isphdr_t *) ap)->rqs_entry_type; 365ea49c6e4SMatt Jacob 3664fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 36710549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, 36810549c05SMatt Jacob "Request Queue Overflow in isp_target_put_entry"); 369ea49c6e4SMatt Jacob return (-1); 370ea49c6e4SMatt Jacob } 371ea49c6e4SMatt Jacob switch (etype) { 372ea49c6e4SMatt Jacob case RQSTYPE_ATIO: 3734fd13c1bSMatt Jacob isp_put_atio(isp, (at_entry_t *) ap, (at_entry_t *) outp); 374ea49c6e4SMatt Jacob break; 375ea49c6e4SMatt Jacob case RQSTYPE_ATIO2: 3764fd13c1bSMatt Jacob isp_put_atio2(isp, (at2_entry_t *) ap, (at2_entry_t *) outp); 377ea49c6e4SMatt Jacob break; 378ea49c6e4SMatt Jacob case RQSTYPE_CTIO: 3794fd13c1bSMatt Jacob isp_put_ctio(isp, (ct_entry_t *) ap, (ct_entry_t *) outp); 380ea49c6e4SMatt Jacob break; 381ea49c6e4SMatt Jacob case RQSTYPE_CTIO2: 3824fd13c1bSMatt Jacob isp_put_ctio2(isp, (ct2_entry_t *) ap, (ct2_entry_t *) outp); 383ea49c6e4SMatt Jacob break; 384ea49c6e4SMatt Jacob default: 38510549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 38610549c05SMatt Jacob "Unknown type 0x%x in isp_put_entry", etype); 387ea49c6e4SMatt Jacob return (-1); 388ea49c6e4SMatt Jacob } 389ea49c6e4SMatt Jacob 3902f9e7606SMatt Jacob ISP_TDQE(isp, "isp_target_put_entry", (int) optr, ap); 3914fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 392ea49c6e4SMatt Jacob return (0); 393ea49c6e4SMatt Jacob } 394ea49c6e4SMatt Jacob 395ea49c6e4SMatt Jacob int 396b25bcef8SMatt Jacob isp_target_put_atio(struct ispsoftc *isp, void *arg) 397ea49c6e4SMatt Jacob { 398ea49c6e4SMatt Jacob union { 399ea49c6e4SMatt Jacob at_entry_t _atio; 400ea49c6e4SMatt Jacob at2_entry_t _atio2; 401e5265237SMatt Jacob at2e_entry_t _atio2e; 402ea49c6e4SMatt Jacob } atun; 403ea49c6e4SMatt Jacob 404ea49c6e4SMatt Jacob MEMZERO(&atun, sizeof atun); 405ea49c6e4SMatt Jacob if (IS_FC(isp)) { 406b25bcef8SMatt Jacob at2_entry_t *aep = arg; 407ea49c6e4SMatt Jacob atun._atio2.at_header.rqs_entry_type = RQSTYPE_ATIO2; 408ea49c6e4SMatt Jacob atun._atio2.at_header.rqs_entry_count = 1; 409d82b6503SMatt Jacob if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { 4101dae40ebSMatt Jacob atun._atio2.at_scclun = (uint16_t) aep->at_scclun; 4112133e16fSMatt Jacob } else { 4121dae40ebSMatt Jacob atun._atio2.at_lun = (uint8_t) aep->at_lun; 4132133e16fSMatt Jacob } 414e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 415e5265237SMatt Jacob atun._atio2e.at_iid = ((at2e_entry_t *)aep)->at_iid; 416e5265237SMatt Jacob } else { 41703cf2fbaSMatt Jacob atun._atio2.at_iid = aep->at_iid; 418e5265237SMatt Jacob } 419e5824c5dSMatt Jacob atun._atio2.at_rxid = aep->at_rxid; 420ea49c6e4SMatt Jacob atun._atio2.at_status = CT_OK; 421ea49c6e4SMatt Jacob } else { 422b25bcef8SMatt Jacob at_entry_t *aep = arg; 423ea49c6e4SMatt Jacob atun._atio.at_header.rqs_entry_type = RQSTYPE_ATIO; 424ea49c6e4SMatt Jacob atun._atio.at_header.rqs_entry_count = 1; 425b25bcef8SMatt Jacob atun._atio.at_handle = aep->at_handle; 426b25bcef8SMatt Jacob atun._atio.at_iid = aep->at_iid; 427b25bcef8SMatt Jacob atun._atio.at_tgt = aep->at_tgt; 428b25bcef8SMatt Jacob atun._atio.at_lun = aep->at_lun; 429b25bcef8SMatt Jacob atun._atio.at_tag_type = aep->at_tag_type; 430b25bcef8SMatt Jacob atun._atio.at_tag_val = aep->at_tag_val; 431b25bcef8SMatt Jacob atun._atio.at_status = (aep->at_flags & AT_TQAE); 432b25bcef8SMatt Jacob atun._atio.at_status |= CT_OK; 433ea49c6e4SMatt Jacob } 434ea49c6e4SMatt Jacob return (isp_target_put_entry(isp, &atun)); 435ea49c6e4SMatt Jacob } 436ea49c6e4SMatt Jacob 437ea49c6e4SMatt Jacob /* 438ea49c6e4SMatt Jacob * Command completion- both for handling cases of no resources or 439ea49c6e4SMatt Jacob * no blackhole driver, or other cases where we have to, inline, 440ea49c6e4SMatt Jacob * finish the command sanely, or for normal command completion. 441ea49c6e4SMatt Jacob * 442ea49c6e4SMatt Jacob * The 'completion' code value has the scsi status byte in the low 8 bits. 443ea49c6e4SMatt Jacob * If status is a CHECK CONDITION and bit 8 is nonzero, then bits 12..15 have 444ea49c6e4SMatt Jacob * the sense key and bits 16..23 have the ASCQ and bits 24..31 have the ASC 445ea49c6e4SMatt Jacob * values. 446ea49c6e4SMatt Jacob * 447ea49c6e4SMatt Jacob * NB: the key, asc, ascq, cannot be used for parallel SCSI as it doesn't 448b25bcef8SMatt Jacob * NB: inline SCSI sense reporting. As such, we lose this information. XXX. 449ea49c6e4SMatt Jacob * 450ea49c6e4SMatt Jacob * For both parallel && fibre channel, we use the feature that does 451ea49c6e4SMatt Jacob * an automatic resource autoreplenish so we don't have then later do 452ea49c6e4SMatt Jacob * put of an atio to replenish the f/w's resource count. 453ea49c6e4SMatt Jacob */ 454ea49c6e4SMatt Jacob 455ea49c6e4SMatt Jacob int 4561dae40ebSMatt Jacob isp_endcmd(struct ispsoftc *isp, void *arg, uint32_t code, uint16_t hdl) 457ea49c6e4SMatt Jacob { 458ea49c6e4SMatt Jacob int sts; 459ea49c6e4SMatt Jacob union { 460ea49c6e4SMatt Jacob ct_entry_t _ctio; 461ea49c6e4SMatt Jacob ct2_entry_t _ctio2; 462e5265237SMatt Jacob ct2e_entry_t _ctio2e; 463ea49c6e4SMatt Jacob } un; 464ea49c6e4SMatt Jacob 465ea49c6e4SMatt Jacob MEMZERO(&un, sizeof un); 466ea49c6e4SMatt Jacob sts = code & 0xff; 467ea49c6e4SMatt Jacob 468ea49c6e4SMatt Jacob if (IS_FC(isp)) { 469ea49c6e4SMatt Jacob at2_entry_t *aep = arg; 470ea49c6e4SMatt Jacob ct2_entry_t *cto = &un._ctio2; 471ea49c6e4SMatt Jacob 472ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 473ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_count = 1; 47423ac1fceSMatt Jacob if ((FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) == 0) { 475ea49c6e4SMatt Jacob cto->ct_lun = aep->at_lun; 4762133e16fSMatt Jacob } 477e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 478e5265237SMatt Jacob un._ctio2e.ct_iid = ((at2e_entry_t *)aep)->at_iid; 479e5265237SMatt Jacob } else { 480e5265237SMatt Jacob cto->ct_iid = aep->at_iid; 481e5265237SMatt Jacob } 482ea49c6e4SMatt Jacob cto->ct_rxid = aep->at_rxid; 483eedb2dfeSMatt Jacob cto->rsp.m1.ct_scsi_status = sts; 484ea49c6e4SMatt Jacob cto->ct_flags = CT2_SENDSTATUS | CT2_NO_DATA | CT2_FLAG_MODE1; 485ea49c6e4SMatt Jacob if (hdl == 0) { 486ea49c6e4SMatt Jacob cto->ct_flags |= CT2_CCINCR; 487ea49c6e4SMatt Jacob } 488ea49c6e4SMatt Jacob if (aep->at_datalen) { 489ea49c6e4SMatt Jacob cto->ct_resid = aep->at_datalen; 4905d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_DATA_UNDER; 491ea49c6e4SMatt Jacob } 492eedb2dfeSMatt Jacob if (sts == SCSI_CHECK && (code & ECMD_SVALID)) { 493ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[0] = 0xf0; 494ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[2] = (code >> 12) & 0xf; 495ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[7] = 8; 496ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[12] = (code >> 24) & 0xff; 497ea49c6e4SMatt Jacob cto->rsp.m1.ct_resp[13] = (code >> 16) & 0xff; 498ea49c6e4SMatt Jacob cto->rsp.m1.ct_senselen = 16; 4995d571944SMatt Jacob cto->rsp.m1.ct_scsi_status |= CT2_SNSLEN_VALID; 500ea49c6e4SMatt Jacob } 501b0bd9b71SMatt Jacob cto->ct_syshandle = hdl; 502ea49c6e4SMatt Jacob } else { 503ea49c6e4SMatt Jacob at_entry_t *aep = arg; 504ea49c6e4SMatt Jacob ct_entry_t *cto = &un._ctio; 505ea49c6e4SMatt Jacob 506ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_type = RQSTYPE_CTIO; 507ea49c6e4SMatt Jacob cto->ct_header.rqs_entry_count = 1; 5085f5aafe1SMatt Jacob cto->ct_fwhandle = aep->at_handle; 509ea49c6e4SMatt Jacob cto->ct_iid = aep->at_iid; 510ea49c6e4SMatt Jacob cto->ct_tgt = aep->at_tgt; 511ea49c6e4SMatt Jacob cto->ct_lun = aep->at_lun; 512ea49c6e4SMatt Jacob cto->ct_tag_type = aep->at_tag_type; 513ea49c6e4SMatt Jacob cto->ct_tag_val = aep->at_tag_val; 514b25bcef8SMatt Jacob if (aep->at_flags & AT_TQAE) { 515b25bcef8SMatt Jacob cto->ct_flags |= CT_TQAE; 516b25bcef8SMatt Jacob } 517ea49c6e4SMatt Jacob cto->ct_flags = CT_SENDSTATUS | CT_NO_DATA; 518ea49c6e4SMatt Jacob if (hdl == 0) { 519ea49c6e4SMatt Jacob cto->ct_flags |= CT_CCINCR; 520ea49c6e4SMatt Jacob } 521ea49c6e4SMatt Jacob cto->ct_scsi_status = sts; 522b0bd9b71SMatt Jacob cto->ct_syshandle = hdl; 523ea49c6e4SMatt Jacob } 524ea49c6e4SMatt Jacob return (isp_target_put_entry(isp, &un)); 525ea49c6e4SMatt Jacob } 526ea49c6e4SMatt Jacob 527e63442b6SMatt Jacob int 528b25bcef8SMatt Jacob isp_target_async(struct ispsoftc *isp, int bus, int event) 529ea49c6e4SMatt Jacob { 530e5265237SMatt Jacob tmd_notify_t notify; 531e5265237SMatt Jacob 532e5265237SMatt Jacob MEMZERO(¬ify, sizeof (tmd_notify_t)); 533e5265237SMatt Jacob notify.nt_hba = isp; 534e5265237SMatt Jacob /* nt_str set in outer layers */ 535e5265237SMatt Jacob notify.nt_iid = INI_ANY; 536e5265237SMatt Jacob /* nt_tgt set in outer layers */ 537e5265237SMatt Jacob notify.nt_lun = LUN_ANY; 538e5265237SMatt Jacob notify.nt_tagval = TAG_ANY; 539e5265237SMatt Jacob 540e5265237SMatt Jacob if (IS_SCSI(isp)) { 541e5265237SMatt Jacob TAG_INSERT_BUS(notify.nt_tagval, bus); 542e5265237SMatt Jacob } 543ea49c6e4SMatt Jacob 544ea49c6e4SMatt Jacob switch (event) { 545e5265237SMatt Jacob case ASYNC_LOOP_UP: 546e5265237SMatt Jacob case ASYNC_PTPMODE: 547e5265237SMatt Jacob notify.nt_ncode = NT_LINK_UP; 548e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 549e5265237SMatt Jacob break; 550e5265237SMatt Jacob case ASYNC_LOOP_DOWN: 551e5265237SMatt Jacob notify.nt_ncode = NT_LINK_DOWN; 552e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 553e5265237SMatt Jacob break; 55423ac1fceSMatt Jacob case ASYNC_LIP_F8: 555ea49c6e4SMatt Jacob case ASYNC_LIP_OCCURRED: 55623ac1fceSMatt Jacob case ASYNC_LOOP_RESET: 557e5265237SMatt Jacob notify.nt_ncode = NT_LIP_RESET; 558e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 559e5265237SMatt Jacob break; 560ea49c6e4SMatt Jacob case ASYNC_BUS_RESET: 561e5265237SMatt Jacob case ASYNC_TIMEOUT_RESET: /* XXX: where does this come from ? */ 562e5265237SMatt Jacob notify.nt_ncode = NT_BUS_RESET; 563e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 564ea49c6e4SMatt Jacob break; 565ea49c6e4SMatt Jacob case ASYNC_DEVICE_RESET: 566e5265237SMatt Jacob notify.nt_ncode = NT_TARGET_RESET; 567e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, ¬ify); 568ea49c6e4SMatt Jacob break; 5692f9e7606SMatt Jacob case ASYNC_CTIO_DONE: 570e5265237SMatt Jacob { 571e5265237SMatt Jacob uint8_t storage[QENTRY_LEN]; 572e5265237SMatt Jacob memset(storage, 0, QENTRY_LEN); 573e5265237SMatt Jacob if (IS_FC(isp)) { 574e5265237SMatt Jacob ct2_entry_t *ct = (ct2_entry_t *) storage; 575e5265237SMatt Jacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO2; 576e5265237SMatt Jacob ct->ct_status = CT_OK; 577e5265237SMatt Jacob ct->ct_syshandle = bus; 578e5265237SMatt Jacob ct->ct_flags = CT2_SENDSTATUS|CT2_FASTPOST; 579e5265237SMatt Jacob } else { 580e5265237SMatt Jacob ct_entry_t *ct = (ct_entry_t *) storage; 581e5265237SMatt Jacob ct->ct_header.rqs_entry_type = RQSTYPE_CTIO; 582e5265237SMatt Jacob ct->ct_status = CT_OK; 583e5265237SMatt Jacob ct->ct_fwhandle = bus; 584e5265237SMatt Jacob ct->ct_flags = CT_SENDSTATUS; 585e5265237SMatt Jacob } 586e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, storage); 5872f9e7606SMatt Jacob return (0); 588e5265237SMatt Jacob } 589ea49c6e4SMatt Jacob default: 59010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 59110549c05SMatt Jacob "isp_target_async: unknown event 0x%x", event); 592e5265237SMatt Jacob if (isp->isp_state == ISP_RUNSTATE) { 593e5265237SMatt Jacob isp_notify_ack(isp, NULL); 594e5265237SMatt Jacob } 595ea49c6e4SMatt Jacob break; 596ea49c6e4SMatt Jacob } 597e63442b6SMatt Jacob return (0); 598ea49c6e4SMatt Jacob } 599ea49c6e4SMatt Jacob 600ea49c6e4SMatt Jacob 601ea49c6e4SMatt Jacob /* 602ea49c6e4SMatt Jacob * Process a received message. 603ea49c6e4SMatt Jacob * The ISP firmware can handle most messages, there are only 604ea49c6e4SMatt Jacob * a few that we need to deal with: 605ea49c6e4SMatt Jacob * - abort: clean up the current command 606ea49c6e4SMatt Jacob * - abort tag and clear queue 607ea49c6e4SMatt Jacob */ 608ea49c6e4SMatt Jacob 609ea49c6e4SMatt Jacob static void 610e5265237SMatt Jacob isp_got_msg(struct ispsoftc *isp, in_entry_t *inp) 611ea49c6e4SMatt Jacob { 612e5265237SMatt Jacob tmd_notify_t nt; 6131dae40ebSMatt Jacob uint8_t status = inp->in_status & ~QLTM_SVALID; 614ea49c6e4SMatt Jacob 615e5265237SMatt Jacob MEMZERO(&nt, sizeof (nt)); 616e5265237SMatt Jacob nt.nt_hba = isp; 617e5265237SMatt Jacob /* nt_str set in outer layers */ 618e5265237SMatt Jacob nt.nt_iid = GET_IID_VAL(inp->in_iid); 619e5265237SMatt Jacob nt.nt_tgt = inp->in_tgt; 620e5265237SMatt Jacob nt.nt_lun = inp->in_lun; 621e5265237SMatt Jacob IN_MAKE_TAGID(nt.nt_tagval, 0, inp); 622e5265237SMatt Jacob nt.nt_lreserved = inp; 623ea49c6e4SMatt Jacob 624e5265237SMatt Jacob if (status == IN_IDE_RECEIVED || status == IN_MSG_RECEIVED) { 625e5265237SMatt Jacob switch (inp->in_msg[0]) { 626e5265237SMatt Jacob case MSG_ABORT: 627e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK_SET; 628e5265237SMatt Jacob break; 629e5265237SMatt Jacob case MSG_BUS_DEV_RESET: 630e5265237SMatt Jacob nt.nt_ncode = NT_TARGET_RESET; 631e5265237SMatt Jacob break; 632e5265237SMatt Jacob case MSG_ABORT_TAG: 633e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK; 634e5265237SMatt Jacob break; 635e5265237SMatt Jacob case MSG_CLEAR_QUEUE: 636e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_TASK_SET; 637e5265237SMatt Jacob break; 638e5265237SMatt Jacob case MSG_REL_RECOVERY: 639e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_ACA; 640e5265237SMatt Jacob break; 641e5265237SMatt Jacob case MSG_TERM_IO_PROC: 642e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK; 643e5265237SMatt Jacob break; 644e5265237SMatt Jacob case MSG_LUN_RESET: 645e5265237SMatt Jacob nt.nt_ncode = NT_LUN_RESET; 646e5265237SMatt Jacob break; 647e5265237SMatt Jacob default: 648e5265237SMatt Jacob isp_prt(isp, ISP_LOGERR, 649e5265237SMatt Jacob "unhandled message 0x%x", inp->in_msg[0]); 650e5265237SMatt Jacob isp_notify_ack(isp, inp); 651e5265237SMatt Jacob return; 652e5265237SMatt Jacob } 653e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); 654ea49c6e4SMatt Jacob } else { 65510549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 65610549c05SMatt Jacob "unknown immediate notify status 0x%x", inp->in_status); 657e5265237SMatt Jacob isp_notify_ack(isp, inp); 658ea49c6e4SMatt Jacob } 659ea49c6e4SMatt Jacob } 660ea49c6e4SMatt Jacob 661ea49c6e4SMatt Jacob /* 662ea49c6e4SMatt Jacob * Synthesize a message from the task management flags in a FCP_CMND_IU. 663ea49c6e4SMatt Jacob */ 664ea49c6e4SMatt Jacob static void 665e5265237SMatt Jacob isp_got_msg_fc(struct ispsoftc *isp, in_fcentry_t *inp) 666ea49c6e4SMatt Jacob { 667e5265237SMatt Jacob tmd_notify_t nt; 668e5265237SMatt Jacob static const char f1[] = "%s from iid 0x%08x%08x lun %d seq 0x%x"; 669b25bcef8SMatt Jacob static const char f2[] = 670e5265237SMatt Jacob "unknown %s 0x%x lun %d iid 0x%08x%08x task flags 0x%x seq 0x%x\n"; 671ea49c6e4SMatt Jacob 672e5265237SMatt Jacob MEMZERO(&nt, sizeof (tmd_notify_t)); 673e5265237SMatt Jacob nt.nt_hba = isp; 674e5265237SMatt Jacob /* 675e5265237SMatt Jacob * XXX: LOOK UP TRANSLATION IN CURRENT LPORTDB 676e5265237SMatt Jacob */ 677e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 678e5265237SMatt Jacob nt.nt_iid = ((in_fcentry_e_t *)inp)->in_iid; 679d82b6503SMatt Jacob } else { 680e5265237SMatt Jacob nt.nt_iid = inp->in_iid; /* possibly reset in outer layer */ 681d82b6503SMatt Jacob } 682e5265237SMatt Jacob /* nt_tgt set in outer layers */ 683e5265237SMatt Jacob if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { 684e5265237SMatt Jacob nt.nt_lun = inp->in_scclun; 685e5265237SMatt Jacob } else { 686e5265237SMatt Jacob nt.nt_lun = inp->in_lun; 687e5265237SMatt Jacob } 688e5265237SMatt Jacob IN_FC_MAKE_TAGID(nt.nt_tagval, 0, inp); 689e5265237SMatt Jacob nt.nt_lreserved = inp; 690d82b6503SMatt Jacob 691ea49c6e4SMatt Jacob if (inp->in_status != IN_MSG_RECEIVED) { 69210549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f2, "immediate notify status", 6931dae40ebSMatt Jacob inp->in_status, nt.nt_lun, (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, 694ea49c6e4SMatt Jacob inp->in_task_flags, inp->in_seqid); 695e5265237SMatt Jacob isp_notify_ack(isp, inp); 696e5265237SMatt Jacob return; 697e5265237SMatt Jacob } 698ea49c6e4SMatt Jacob 6992f9e7606SMatt Jacob if (inp->in_task_flags & TASK_FLAGS_ABORT_TASK_SET) { 7002f9e7606SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "ABORT TASK SET", 7011dae40ebSMatt Jacob (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); 702e5265237SMatt Jacob nt.nt_ncode = NT_ABORT_TASK_SET; 703ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_TASK_SET) { 70410549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR TASK SET", 7051dae40ebSMatt Jacob (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); 706e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_TASK_SET; 7072f9e7606SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_LUN_RESET) { 7082f9e7606SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "LUN RESET", 7091dae40ebSMatt Jacob (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); 710e5265237SMatt Jacob nt.nt_ncode = NT_LUN_RESET; 711ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_TARGET_RESET) { 71210549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "TARGET RESET", 7131dae40ebSMatt Jacob (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); 714e5265237SMatt Jacob nt.nt_ncode = NT_TARGET_RESET; 715ea49c6e4SMatt Jacob } else if (inp->in_task_flags & TASK_FLAGS_CLEAR_ACA) { 71610549c05SMatt Jacob isp_prt(isp, ISP_LOGINFO, f1, "CLEAR ACA", 7171dae40ebSMatt Jacob (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, nt.nt_lun, inp->in_seqid); 718e5265237SMatt Jacob nt.nt_ncode = NT_CLEAR_ACA; 719ea49c6e4SMatt Jacob } else { 72010549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, f2, "task flag", 7211dae40ebSMatt Jacob inp->in_status, nt.nt_lun, (uint32_t) (nt.nt_iid >> 32), (uint32_t) nt.nt_iid, 722ea49c6e4SMatt Jacob inp->in_task_flags, inp->in_seqid); 723e5265237SMatt Jacob isp_notify_ack(isp, inp); 724e5265237SMatt Jacob return; 725ea49c6e4SMatt Jacob } 726e5265237SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_NOTIFY, &nt); 727ea49c6e4SMatt Jacob } 728ea49c6e4SMatt Jacob 729e5265237SMatt Jacob void 730b25bcef8SMatt Jacob isp_notify_ack(struct ispsoftc *isp, void *arg) 731ea49c6e4SMatt Jacob { 732ea49c6e4SMatt Jacob char storage[QENTRY_LEN]; 7331dae40ebSMatt Jacob uint16_t nxti, optr; 734ea49c6e4SMatt Jacob void *outp; 735ea49c6e4SMatt Jacob 7364fd13c1bSMatt Jacob if (isp_getrqentry(isp, &nxti, &optr, &outp)) { 73710549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, 73810549c05SMatt Jacob "Request Queue Overflow For isp_notify_ack"); 739ea49c6e4SMatt Jacob return; 740ea49c6e4SMatt Jacob } 741ea49c6e4SMatt Jacob 7420c02c31bSMatt Jacob MEMZERO(storage, QENTRY_LEN); 743ea49c6e4SMatt Jacob 744ea49c6e4SMatt Jacob if (IS_FC(isp)) { 745ea49c6e4SMatt Jacob na_fcentry_t *na = (na_fcentry_t *) storage; 746ea49c6e4SMatt Jacob if (arg) { 747ea49c6e4SMatt Jacob in_fcentry_t *inp = arg; 7480c02c31bSMatt Jacob MEMCPY(storage, arg, sizeof (isphdr_t)); 749e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 750e5265237SMatt Jacob ((na_fcentry_e_t *)na)->na_iid = ((in_fcentry_e_t *)inp)->in_iid; 751e5265237SMatt Jacob } else { 752ea49c6e4SMatt Jacob na->na_iid = inp->in_iid; 753e5265237SMatt Jacob } 754d82b6503SMatt Jacob if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { 755ea49c6e4SMatt Jacob na->na_lun = inp->in_scclun; 7562133e16fSMatt Jacob } else { 757ea49c6e4SMatt Jacob na->na_lun = inp->in_lun; 7582133e16fSMatt Jacob } 759ea49c6e4SMatt Jacob na->na_task_flags = inp->in_task_flags; 760ea49c6e4SMatt Jacob na->na_seqid = inp->in_seqid; 761ea49c6e4SMatt Jacob na->na_flags = NAFC_RCOUNT; 76275c1e828SMatt Jacob na->na_status = inp->in_status; 763ea49c6e4SMatt Jacob if (inp->in_status == IN_RESET) { 764ea49c6e4SMatt Jacob na->na_flags |= NAFC_RST_CLRD; 765ea49c6e4SMatt Jacob } 766ea49c6e4SMatt Jacob } else { 767ea49c6e4SMatt Jacob na->na_flags = NAFC_RST_CLRD; 768ea49c6e4SMatt Jacob } 7699dae8807SMatt Jacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 7709dae8807SMatt Jacob na->na_header.rqs_entry_count = 1; 771e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 772e5265237SMatt Jacob isp_put_notify_ack_fc_e(isp, (na_fcentry_e_t *) na, (na_fcentry_e_t *)outp); 773e5265237SMatt Jacob } else { 7744fd13c1bSMatt Jacob isp_put_notify_ack_fc(isp, na, (na_fcentry_t *)outp); 775e5265237SMatt Jacob } 776ea49c6e4SMatt Jacob } else { 777ea49c6e4SMatt Jacob na_entry_t *na = (na_entry_t *) storage; 778ea49c6e4SMatt Jacob if (arg) { 779ea49c6e4SMatt Jacob in_entry_t *inp = arg; 7800c02c31bSMatt Jacob MEMCPY(storage, arg, sizeof (isphdr_t)); 781ea49c6e4SMatt Jacob na->na_iid = inp->in_iid; 782ea49c6e4SMatt Jacob na->na_lun = inp->in_lun; 783ea49c6e4SMatt Jacob na->na_tgt = inp->in_tgt; 784ea49c6e4SMatt Jacob na->na_seqid = inp->in_seqid; 785ea49c6e4SMatt Jacob if (inp->in_status == IN_RESET) { 7869dae8807SMatt Jacob na->na_event = NA_RST_CLRD; 787ea49c6e4SMatt Jacob } 788ea49c6e4SMatt Jacob } else { 7899dae8807SMatt Jacob na->na_event = NA_RST_CLRD; 790ea49c6e4SMatt Jacob } 7919dae8807SMatt Jacob na->na_header.rqs_entry_type = RQSTYPE_NOTIFY_ACK; 7929dae8807SMatt Jacob na->na_header.rqs_entry_count = 1; 7934fd13c1bSMatt Jacob isp_put_notify_ack(isp, na, (na_entry_t *)outp); 794ea49c6e4SMatt Jacob } 795ea49c6e4SMatt Jacob ISP_TDQE(isp, "isp_notify_ack", (int) optr, storage); 7964fd13c1bSMatt Jacob ISP_ADD_REQUEST(isp, nxti); 797ea49c6e4SMatt Jacob } 798ea49c6e4SMatt Jacob 799ea49c6e4SMatt Jacob static void 800b25bcef8SMatt Jacob isp_handle_atio(struct ispsoftc *isp, at_entry_t *aep) 801ea49c6e4SMatt Jacob { 802ea49c6e4SMatt Jacob int lun; 803ea49c6e4SMatt Jacob lun = aep->at_lun; 804ea49c6e4SMatt Jacob /* 805ea49c6e4SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) indicates 806ea49c6e4SMatt Jacob * why this ATIO was sent to us. 807ea49c6e4SMatt Jacob * 808ea49c6e4SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 809ea49c6e4SMatt Jacob * 810ea49c6e4SMatt Jacob * If the DISCONNECTS DISABLED bit is set in the flags field, 811ea49c6e4SMatt Jacob * we're still connected on the SCSI bus - i.e. the initiator 812ea49c6e4SMatt Jacob * did not set DiscPriv in the identify message. We don't care 813ea49c6e4SMatt Jacob * about this so it's ignored. 814ea49c6e4SMatt Jacob */ 815ea49c6e4SMatt Jacob 816ea49c6e4SMatt Jacob switch(aep->at_status & ~QLTM_SVALID) { 817ea49c6e4SMatt Jacob case AT_PATH_INVALID: 818ea49c6e4SMatt Jacob /* 819ea49c6e4SMatt Jacob * ATIO rejected by the firmware due to disabled lun. 820ea49c6e4SMatt Jacob */ 82110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 82210549c05SMatt Jacob "rejected ATIO for disabled lun %d", lun); 823ea49c6e4SMatt Jacob break; 824ea49c6e4SMatt Jacob case AT_NOCAP: 825ea49c6e4SMatt Jacob /* 826ea49c6e4SMatt Jacob * Requested Capability not available 827ea49c6e4SMatt Jacob * We sent an ATIO that overflowed the firmware's 828ea49c6e4SMatt Jacob * command resource count. 829ea49c6e4SMatt Jacob */ 83010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 83110549c05SMatt Jacob "rejected ATIO for lun %d because of command count" 83210549c05SMatt Jacob " overflow", lun); 833ea49c6e4SMatt Jacob break; 834ea49c6e4SMatt Jacob 835ea49c6e4SMatt Jacob case AT_BDR_MSG: 836ea49c6e4SMatt Jacob /* 837ea49c6e4SMatt Jacob * If we send an ATIO to the firmware to increment 838ea49c6e4SMatt Jacob * its command resource count, and the firmware is 839ea49c6e4SMatt Jacob * recovering from a Bus Device Reset, it returns 840ea49c6e4SMatt Jacob * the ATIO with this status. We set the command 8414fd13c1bSMatt Jacob * resource count in the Enable Lun entry and do 842ea49c6e4SMatt Jacob * not increment it. Therefore we should never get 843ea49c6e4SMatt Jacob * this status here. 844ea49c6e4SMatt Jacob */ 84523ac1fceSMatt Jacob isp_prt(isp, ISP_LOGERR, atiocope, lun, 84623ac1fceSMatt Jacob GET_BUS_VAL(aep->at_iid)); 847ea49c6e4SMatt Jacob break; 848ea49c6e4SMatt Jacob 849ea49c6e4SMatt Jacob case AT_CDB: /* Got a CDB */ 850ea49c6e4SMatt Jacob case AT_PHASE_ERROR: /* Bus Phase Sequence Error */ 851ea49c6e4SMatt Jacob /* 852ea49c6e4SMatt Jacob * Punt to platform specific layer. 853ea49c6e4SMatt Jacob */ 854ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 855ea49c6e4SMatt Jacob break; 856ea49c6e4SMatt Jacob 857ea49c6e4SMatt Jacob case AT_RESET: 858ea49c6e4SMatt Jacob /* 859d64ada50SJens Schweikhardt * A bus reset came along and blew away this command. Why 860ea49c6e4SMatt Jacob * they do this in addition the async event code stuff, 861ea49c6e4SMatt Jacob * I dunno. 862ea49c6e4SMatt Jacob * 863ea49c6e4SMatt Jacob * Ignore it because the async event will clear things 864ea49c6e4SMatt Jacob * up for us. 865ea49c6e4SMatt Jacob */ 86623ac1fceSMatt Jacob isp_prt(isp, ISP_LOGWARN, atior, lun, 86723ac1fceSMatt Jacob GET_IID_VAL(aep->at_iid), GET_BUS_VAL(aep->at_iid)); 868ea49c6e4SMatt Jacob break; 869ea49c6e4SMatt Jacob 870ea49c6e4SMatt Jacob 871ea49c6e4SMatt Jacob default: 87210549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 87310549c05SMatt Jacob "Unknown ATIO status 0x%x from initiator %d for lun %d", 87410549c05SMatt Jacob aep->at_status, aep->at_iid, lun); 875b25bcef8SMatt Jacob (void) isp_target_put_atio(isp, aep); 876ea49c6e4SMatt Jacob break; 877ea49c6e4SMatt Jacob } 878ea49c6e4SMatt Jacob } 879ea49c6e4SMatt Jacob 880ea49c6e4SMatt Jacob static void 881b25bcef8SMatt Jacob isp_handle_atio2(struct ispsoftc *isp, at2_entry_t *aep) 882ea49c6e4SMatt Jacob { 883e5265237SMatt Jacob int lun, iid; 8842133e16fSMatt Jacob 885d82b6503SMatt Jacob if (FCPARAM(isp)->isp_fwattr & ISP_FW_ATTR_SCCLUN) { 886ea49c6e4SMatt Jacob lun = aep->at_scclun; 8872133e16fSMatt Jacob } else { 888ea49c6e4SMatt Jacob lun = aep->at_lun; 8892133e16fSMatt Jacob } 8902133e16fSMatt Jacob 891e5265237SMatt Jacob if (IS_2KLOGIN(isp)) { 892e5265237SMatt Jacob iid = ((at2e_entry_t *)aep)->at_iid; 893e5265237SMatt Jacob } else { 894e5265237SMatt Jacob iid = aep->at_iid; 895e5265237SMatt Jacob } 896e5265237SMatt Jacob 897ea49c6e4SMatt Jacob /* 898ea49c6e4SMatt Jacob * The firmware status (except for the QLTM_SVALID bit) indicates 899ea49c6e4SMatt Jacob * why this ATIO was sent to us. 900ea49c6e4SMatt Jacob * 901ea49c6e4SMatt Jacob * If QLTM_SVALID is set, the firware has recommended Sense Data. 902ea49c6e4SMatt Jacob * 903ea49c6e4SMatt Jacob * If the DISCONNECTS DISABLED bit is set in the flags field, 904ea49c6e4SMatt Jacob * we're still connected on the SCSI bus - i.e. the initiator 905ea49c6e4SMatt Jacob * did not set DiscPriv in the identify message. We don't care 906ea49c6e4SMatt Jacob * about this so it's ignored. 907ea49c6e4SMatt Jacob */ 908ea49c6e4SMatt Jacob 909ea49c6e4SMatt Jacob switch(aep->at_status & ~QLTM_SVALID) { 910ea49c6e4SMatt Jacob case AT_PATH_INVALID: 911ea49c6e4SMatt Jacob /* 912ea49c6e4SMatt Jacob * ATIO rejected by the firmware due to disabled lun. 913ea49c6e4SMatt Jacob */ 91410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 91510549c05SMatt Jacob "rejected ATIO2 for disabled lun %d", lun); 916ea49c6e4SMatt Jacob break; 917ea49c6e4SMatt Jacob case AT_NOCAP: 918ea49c6e4SMatt Jacob /* 919ea49c6e4SMatt Jacob * Requested Capability not available 920ea49c6e4SMatt Jacob * We sent an ATIO that overflowed the firmware's 921ea49c6e4SMatt Jacob * command resource count. 922ea49c6e4SMatt Jacob */ 92310549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 92410549c05SMatt Jacob "rejected ATIO2 for lun %d- command count overflow", lun); 925ea49c6e4SMatt Jacob break; 926ea49c6e4SMatt Jacob 927ea49c6e4SMatt Jacob case AT_BDR_MSG: 928ea49c6e4SMatt Jacob /* 929ea49c6e4SMatt Jacob * If we send an ATIO to the firmware to increment 930ea49c6e4SMatt Jacob * its command resource count, and the firmware is 931ea49c6e4SMatt Jacob * recovering from a Bus Device Reset, it returns 932ea49c6e4SMatt Jacob * the ATIO with this status. We set the command 933ea49c6e4SMatt Jacob * resource count in the Enable Lun entry and no 934ea49c6e4SMatt Jacob * not increment it. Therefore we should never get 935ea49c6e4SMatt Jacob * this status here. 936ea49c6e4SMatt Jacob */ 93723ac1fceSMatt Jacob isp_prt(isp, ISP_LOGERR, atiocope, lun, 0); 938ea49c6e4SMatt Jacob break; 939ea49c6e4SMatt Jacob 940ea49c6e4SMatt Jacob case AT_CDB: /* Got a CDB */ 941ea49c6e4SMatt Jacob /* 942ea49c6e4SMatt Jacob * Punt to platform specific layer. 943ea49c6e4SMatt Jacob */ 944ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, aep); 945ea49c6e4SMatt Jacob break; 946ea49c6e4SMatt Jacob 947ea49c6e4SMatt Jacob case AT_RESET: 948ea49c6e4SMatt Jacob /* 949ea49c6e4SMatt Jacob * A bus reset came along an blew away this command. Why 950ea49c6e4SMatt Jacob * they do this in addition the async event code stuff, 951ea49c6e4SMatt Jacob * I dunno. 952ea49c6e4SMatt Jacob * 953ea49c6e4SMatt Jacob * Ignore it because the async event will clear things 954ea49c6e4SMatt Jacob * up for us. 955ea49c6e4SMatt Jacob */ 956e5265237SMatt Jacob isp_prt(isp, ISP_LOGERR, atior, lun, iid, 0); 957ea49c6e4SMatt Jacob break; 958ea49c6e4SMatt Jacob 959ea49c6e4SMatt Jacob 960ea49c6e4SMatt Jacob default: 96110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 96210549c05SMatt Jacob "Unknown ATIO2 status 0x%x from initiator %d for lun %d", 963e5265237SMatt Jacob aep->at_status, iid, lun); 964b25bcef8SMatt Jacob (void) isp_target_put_atio(isp, aep); 965ea49c6e4SMatt Jacob break; 966ea49c6e4SMatt Jacob } 967ea49c6e4SMatt Jacob } 968ea49c6e4SMatt Jacob 969ea49c6e4SMatt Jacob static void 970b25bcef8SMatt Jacob isp_handle_ctio(struct ispsoftc *isp, ct_entry_t *ct) 971ea49c6e4SMatt Jacob { 972b0bd9b71SMatt Jacob void *xs; 97310549c05SMatt Jacob int pl = ISP_LOGTDEBUG2; 974ea49c6e4SMatt Jacob char *fmsg = NULL; 975ea49c6e4SMatt Jacob 976b0bd9b71SMatt Jacob if (ct->ct_syshandle) { 97751e23558SNate Lawson xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 978ea49c6e4SMatt Jacob if (xs == NULL) 97910549c05SMatt Jacob pl = ISP_LOGALL; 980ea49c6e4SMatt Jacob } else { 981ea49c6e4SMatt Jacob xs = NULL; 982ea49c6e4SMatt Jacob } 983ea49c6e4SMatt Jacob 984ea49c6e4SMatt Jacob switch(ct->ct_status & ~QLTM_SVALID) { 985ea49c6e4SMatt Jacob case CT_OK: 986ea49c6e4SMatt Jacob /* 987ea49c6e4SMatt Jacob * There are generally 3 possibilities as to why we'd get 988ea49c6e4SMatt Jacob * this condition: 989ea49c6e4SMatt Jacob * We disconnected after receiving a CDB. 990ea49c6e4SMatt Jacob * We sent or received data. 991ea49c6e4SMatt Jacob * We sent status & command complete. 992ea49c6e4SMatt Jacob */ 993ea49c6e4SMatt Jacob 9949dae8807SMatt Jacob if (ct->ct_flags & CT_SENDSTATUS) { 9959dae8807SMatt Jacob break; 9969dae8807SMatt Jacob } else if ((ct->ct_flags & CT_DATAMASK) == CT_NO_DATA) { 997ea49c6e4SMatt Jacob /* 998ea49c6e4SMatt Jacob * Nothing to do in this case. 999ea49c6e4SMatt Jacob */ 100010549c05SMatt Jacob isp_prt(isp, pl, "CTIO- iid %d disconnected OK", 100110549c05SMatt Jacob ct->ct_iid); 1002ea49c6e4SMatt Jacob return; 1003ea49c6e4SMatt Jacob } 1004ea49c6e4SMatt Jacob break; 1005ea49c6e4SMatt Jacob 1006ea49c6e4SMatt Jacob case CT_BDR_MSG: 1007ea49c6e4SMatt Jacob /* 1008ea49c6e4SMatt Jacob * Bus Device Reset message received or the SCSI Bus has 1009ea49c6e4SMatt Jacob * been Reset; the firmware has gone to Bus Free. 1010ea49c6e4SMatt Jacob * 1011ea49c6e4SMatt Jacob * The firmware generates an async mailbox interupt to 1012ea49c6e4SMatt Jacob * notify us of this and returns outstanding CTIOs with this 1013ea49c6e4SMatt Jacob * status. These CTIOs are handled in that same way as 1014ea49c6e4SMatt Jacob * CT_ABORTED ones, so just fall through here. 1015ea49c6e4SMatt Jacob */ 1016ea49c6e4SMatt Jacob fmsg = "Bus Device Reset"; 1017ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1018ea49c6e4SMatt Jacob case CT_RESET: 1019ea49c6e4SMatt Jacob if (fmsg == NULL) 1020ea49c6e4SMatt Jacob fmsg = "Bus Reset"; 1021ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1022ea49c6e4SMatt Jacob case CT_ABORTED: 1023ea49c6e4SMatt Jacob /* 1024ea49c6e4SMatt Jacob * When an Abort message is received the firmware goes to 1025ea49c6e4SMatt Jacob * Bus Free and returns all outstanding CTIOs with the status 1026ea49c6e4SMatt Jacob * set, then sends us an Immediate Notify entry. 1027ea49c6e4SMatt Jacob */ 1028ea49c6e4SMatt Jacob if (fmsg == NULL) 102923ac1fceSMatt Jacob fmsg = "ABORT TAG message sent by Initiator"; 1030ea49c6e4SMatt Jacob 103110549c05SMatt Jacob isp_prt(isp, ISP_LOGWARN, "CTIO destroyed by %s", fmsg); 1032ea49c6e4SMatt Jacob break; 1033ea49c6e4SMatt Jacob 1034ea49c6e4SMatt Jacob case CT_INVAL: 1035ea49c6e4SMatt Jacob /* 1036ea49c6e4SMatt Jacob * CTIO rejected by the firmware due to disabled lun. 1037ea49c6e4SMatt Jacob * "Cannot Happen". 1038ea49c6e4SMatt Jacob */ 103910549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 104010549c05SMatt Jacob "Firmware rejected CTIO for disabled lun %d", 104110549c05SMatt Jacob ct->ct_lun); 1042ea49c6e4SMatt Jacob break; 1043ea49c6e4SMatt Jacob 1044ea49c6e4SMatt Jacob case CT_NOPATH: 1045ea49c6e4SMatt Jacob /* 1046ea49c6e4SMatt Jacob * CTIO rejected by the firmware due "no path for the 1047ea49c6e4SMatt Jacob * nondisconnecting nexus specified". This means that 1048ea49c6e4SMatt Jacob * we tried to access the bus while a non-disconnecting 1049ea49c6e4SMatt Jacob * command is in process. 1050ea49c6e4SMatt Jacob */ 105110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 105210549c05SMatt Jacob "Firmware rejected CTIO for bad nexus %d/%d/%d", 105310549c05SMatt Jacob ct->ct_iid, ct->ct_tgt, ct->ct_lun); 1054ea49c6e4SMatt Jacob break; 1055ea49c6e4SMatt Jacob 1056ea49c6e4SMatt Jacob case CT_RSELTMO: 1057ea49c6e4SMatt Jacob fmsg = "Reselection"; 1058ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1059ea49c6e4SMatt Jacob case CT_TIMEOUT: 1060ea49c6e4SMatt Jacob if (fmsg == NULL) 1061ea49c6e4SMatt Jacob fmsg = "Command"; 106210549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); 1063ea49c6e4SMatt Jacob break; 1064ea49c6e4SMatt Jacob 1065b25bcef8SMatt Jacob case CT_PANIC: 1066b25bcef8SMatt Jacob if (fmsg == NULL) 1067b25bcef8SMatt Jacob fmsg = "Unrecoverable Error"; 1068b25bcef8SMatt Jacob /*FALLTHROUGH*/ 1069ea49c6e4SMatt Jacob case CT_ERR: 1070b25bcef8SMatt Jacob if (fmsg == NULL) 1071ea49c6e4SMatt Jacob fmsg = "Completed with Error"; 1072ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1073ea49c6e4SMatt Jacob case CT_PHASE_ERROR: 1074ea49c6e4SMatt Jacob if (fmsg == NULL) 1075ea49c6e4SMatt Jacob fmsg = "Phase Sequence Error"; 1076ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1077ea49c6e4SMatt Jacob case CT_TERMINATED: 1078ea49c6e4SMatt Jacob if (fmsg == NULL) 1079ea49c6e4SMatt Jacob fmsg = "terminated by TERMINATE TRANSFER"; 1080ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1081ea49c6e4SMatt Jacob case CT_NOACK: 1082ea49c6e4SMatt Jacob if (fmsg == NULL) 1083ea49c6e4SMatt Jacob fmsg = "unacknowledged Immediate Notify pending"; 108410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); 1085ea49c6e4SMatt Jacob break; 1086ea49c6e4SMatt Jacob default: 108710549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO status 0x%x", 1088ea49c6e4SMatt Jacob ct->ct_status & ~QLTM_SVALID); 1089ea49c6e4SMatt Jacob break; 1090ea49c6e4SMatt Jacob } 1091ea49c6e4SMatt Jacob 1092ea49c6e4SMatt Jacob if (xs == NULL) { 1093ea49c6e4SMatt Jacob /* 1094ea49c6e4SMatt Jacob * There may be more than one CTIO for a data transfer, 1095ea49c6e4SMatt Jacob * or this may be a status CTIO we're not monitoring. 1096ea49c6e4SMatt Jacob * 1097ea49c6e4SMatt Jacob * The assumption is that they'll all be returned in the 1098ea49c6e4SMatt Jacob * order we got them. 1099ea49c6e4SMatt Jacob */ 1100b0bd9b71SMatt Jacob if (ct->ct_syshandle == 0) { 1101ea49c6e4SMatt Jacob if ((ct->ct_flags & CT_SENDSTATUS) == 0) { 110210549c05SMatt Jacob isp_prt(isp, pl, 110310549c05SMatt Jacob "intermediate CTIO completed ok"); 1104ea49c6e4SMatt Jacob } else { 110510549c05SMatt Jacob isp_prt(isp, pl, 110610549c05SMatt Jacob "unmonitored CTIO completed ok"); 1107ea49c6e4SMatt Jacob } 1108ea49c6e4SMatt Jacob } else { 110910549c05SMatt Jacob isp_prt(isp, pl, 111010549c05SMatt Jacob "NO xs for CTIO (handle 0x%x) status 0x%x", 1111b0bd9b71SMatt Jacob ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1112ea49c6e4SMatt Jacob } 1113ea49c6e4SMatt Jacob } else { 1114ea49c6e4SMatt Jacob /* 1115ea49c6e4SMatt Jacob * Final CTIO completed. Release DMA resources and 1116ea49c6e4SMatt Jacob * notify platform dependent layers. 1117ea49c6e4SMatt Jacob */ 11185d571944SMatt Jacob if ((ct->ct_flags & CT_DATAMASK) != CT_NO_DATA) { 1119b0bd9b71SMatt Jacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 1120ea49c6e4SMatt Jacob } 1121b25bcef8SMatt Jacob isp_prt(isp, pl, "final CTIO complete"); 1122ea49c6e4SMatt Jacob /* 1123ea49c6e4SMatt Jacob * The platform layer will destroy the handle if appropriate. 1124ea49c6e4SMatt Jacob */ 1125b25bcef8SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1126ea49c6e4SMatt Jacob } 1127ea49c6e4SMatt Jacob } 1128ea49c6e4SMatt Jacob 1129ea49c6e4SMatt Jacob static void 1130b25bcef8SMatt Jacob isp_handle_ctio2(struct ispsoftc *isp, ct2_entry_t *ct) 1131ea49c6e4SMatt Jacob { 113210549c05SMatt Jacob XS_T *xs; 113310549c05SMatt Jacob int pl = ISP_LOGTDEBUG2; 1134ea49c6e4SMatt Jacob char *fmsg = NULL; 1135ea49c6e4SMatt Jacob 1136b0bd9b71SMatt Jacob if (ct->ct_syshandle) { 113751e23558SNate Lawson xs = isp_find_xs_tgt(isp, ct->ct_syshandle); 1138ea49c6e4SMatt Jacob if (xs == NULL) 113910549c05SMatt Jacob pl = ISP_LOGALL; 1140ea49c6e4SMatt Jacob } else { 1141ea49c6e4SMatt Jacob xs = NULL; 1142ea49c6e4SMatt Jacob } 1143ea49c6e4SMatt Jacob 1144ea49c6e4SMatt Jacob switch(ct->ct_status & ~QLTM_SVALID) { 11455d571944SMatt Jacob case CT_BUS_ERROR: 11465d571944SMatt Jacob isp_prt(isp, ISP_LOGERR, "PCI DMA Bus Error"); 11475d571944SMatt Jacob /* FALL Through */ 11485d571944SMatt Jacob case CT_DATA_OVER: 11495d571944SMatt Jacob case CT_DATA_UNDER: 1150ea49c6e4SMatt Jacob case CT_OK: 1151ea49c6e4SMatt Jacob /* 1152ea49c6e4SMatt Jacob * There are generally 2 possibilities as to why we'd get 1153ea49c6e4SMatt Jacob * this condition: 1154ea49c6e4SMatt Jacob * We sent or received data. 1155ea49c6e4SMatt Jacob * We sent status & command complete. 1156ea49c6e4SMatt Jacob */ 1157ea49c6e4SMatt Jacob 1158ea49c6e4SMatt Jacob break; 1159ea49c6e4SMatt Jacob 1160ea49c6e4SMatt Jacob case CT_BDR_MSG: 1161ea49c6e4SMatt Jacob /* 11625d571944SMatt Jacob * Target Reset function received. 1163ea49c6e4SMatt Jacob * 1164ea49c6e4SMatt Jacob * The firmware generates an async mailbox interupt to 1165ea49c6e4SMatt Jacob * notify us of this and returns outstanding CTIOs with this 1166ea49c6e4SMatt Jacob * status. These CTIOs are handled in that same way as 1167ea49c6e4SMatt Jacob * CT_ABORTED ones, so just fall through here. 1168ea49c6e4SMatt Jacob */ 11695d571944SMatt Jacob fmsg = "TARGET RESET Task Management Function Received"; 1170ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1171ea49c6e4SMatt Jacob case CT_RESET: 1172ea49c6e4SMatt Jacob if (fmsg == NULL) 11735d571944SMatt Jacob fmsg = "LIP Reset"; 1174ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1175ea49c6e4SMatt Jacob case CT_ABORTED: 1176ea49c6e4SMatt Jacob /* 1177ea49c6e4SMatt Jacob * When an Abort message is received the firmware goes to 1178ea49c6e4SMatt Jacob * Bus Free and returns all outstanding CTIOs with the status 1179ea49c6e4SMatt Jacob * set, then sends us an Immediate Notify entry. 1180ea49c6e4SMatt Jacob */ 1181ea49c6e4SMatt Jacob if (fmsg == NULL) 11825d571944SMatt Jacob fmsg = "ABORT Task Management Function Received"; 1183ea49c6e4SMatt Jacob 118410549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO2 destroyed by %s", fmsg); 1185ea49c6e4SMatt Jacob break; 1186ea49c6e4SMatt Jacob 1187ea49c6e4SMatt Jacob case CT_INVAL: 1188ea49c6e4SMatt Jacob /* 11890c02c31bSMatt Jacob * CTIO rejected by the firmware - invalid data direction. 1190ea49c6e4SMatt Jacob */ 11912f9e7606SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO2 had wrong data direction"); 1192ea49c6e4SMatt Jacob break; 1193ea49c6e4SMatt Jacob 1194ea49c6e4SMatt Jacob case CT_RSELTMO: 11955d571944SMatt Jacob fmsg = "failure to reconnect to initiator"; 1196ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1197ea49c6e4SMatt Jacob case CT_TIMEOUT: 1198ea49c6e4SMatt Jacob if (fmsg == NULL) 11995d571944SMatt Jacob fmsg = "command"; 120010549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "Firmware timed out on %s", fmsg); 1201ea49c6e4SMatt Jacob break; 1202ea49c6e4SMatt Jacob 1203ea49c6e4SMatt Jacob case CT_ERR: 1204ea49c6e4SMatt Jacob fmsg = "Completed with Error"; 1205ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1206ea49c6e4SMatt Jacob case CT_LOGOUT: 1207ea49c6e4SMatt Jacob if (fmsg == NULL) 1208ea49c6e4SMatt Jacob fmsg = "Port Logout"; 1209ea49c6e4SMatt Jacob /*FALLTHROUGH*/ 1210ea49c6e4SMatt Jacob case CT_PORTNOTAVAIL: 1211ea49c6e4SMatt Jacob if (fmsg == NULL) 1212ea49c6e4SMatt Jacob fmsg = "Port not available"; 1213a0fb4cf1SPoul-Henning Kamp /*FALLTHROUGH*/ 12145d571944SMatt Jacob case CT_PORTCHANGED: 12155d571944SMatt Jacob if (fmsg == NULL) 12165d571944SMatt Jacob fmsg = "Port Changed"; 1217a0fb4cf1SPoul-Henning Kamp /*FALLTHROUGH*/ 1218ea49c6e4SMatt Jacob case CT_NOACK: 1219ea49c6e4SMatt Jacob if (fmsg == NULL) 1220ea49c6e4SMatt Jacob fmsg = "unacknowledged Immediate Notify pending"; 122110549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, "CTIO returned by f/w- %s", fmsg); 1222ea49c6e4SMatt Jacob break; 1223ea49c6e4SMatt Jacob 1224ea49c6e4SMatt Jacob case CT_INVRXID: 1225ea49c6e4SMatt Jacob /* 1226ea49c6e4SMatt Jacob * CTIO rejected by the firmware because an invalid RX_ID. 1227ea49c6e4SMatt Jacob * Just print a message. 1228ea49c6e4SMatt Jacob */ 122910549c05SMatt Jacob isp_prt(isp, ISP_LOGERR, 123010549c05SMatt Jacob "CTIO2 completed with Invalid RX_ID 0x%x", ct->ct_rxid); 1231ea49c6e4SMatt Jacob break; 1232ea49c6e4SMatt Jacob 1233ea49c6e4SMatt Jacob default: 1234b25bcef8SMatt Jacob isp_prt(isp, ISP_LOGERR, "Unknown CTIO2 status 0x%x", 123510549c05SMatt Jacob ct->ct_status & ~QLTM_SVALID); 1236ea49c6e4SMatt Jacob break; 1237ea49c6e4SMatt Jacob } 1238ea49c6e4SMatt Jacob 1239ea49c6e4SMatt Jacob if (xs == NULL) { 1240ea49c6e4SMatt Jacob /* 1241ea49c6e4SMatt Jacob * There may be more than one CTIO for a data transfer, 1242ea49c6e4SMatt Jacob * or this may be a status CTIO we're not monitoring. 1243ea49c6e4SMatt Jacob * 1244ea49c6e4SMatt Jacob * The assumption is that they'll all be returned in the 1245ea49c6e4SMatt Jacob * order we got them. 1246ea49c6e4SMatt Jacob */ 1247b0bd9b71SMatt Jacob if (ct->ct_syshandle == 0) { 1248ac9d0a02SMatt Jacob if ((ct->ct_flags & CT2_SENDSTATUS) == 0) { 124910549c05SMatt Jacob isp_prt(isp, pl, 125010549c05SMatt Jacob "intermediate CTIO completed ok"); 1251ea49c6e4SMatt Jacob } else { 125210549c05SMatt Jacob isp_prt(isp, pl, 125310549c05SMatt Jacob "unmonitored CTIO completed ok"); 1254ea49c6e4SMatt Jacob } 1255ea49c6e4SMatt Jacob } else { 125610549c05SMatt Jacob isp_prt(isp, pl, 125710549c05SMatt Jacob "NO xs for CTIO (handle 0x%x) status 0x%x", 1258b0bd9b71SMatt Jacob ct->ct_syshandle, ct->ct_status & ~QLTM_SVALID); 1259ea49c6e4SMatt Jacob } 1260ea49c6e4SMatt Jacob } else { 12615d571944SMatt Jacob if ((ct->ct_flags & CT2_DATAMASK) != CT2_NO_DATA) { 12625d571944SMatt Jacob ISP_DMAFREE(isp, xs, ct->ct_syshandle); 12635d571944SMatt Jacob } 1264ac9d0a02SMatt Jacob if (ct->ct_flags & CT2_SENDSTATUS) { 1265ea49c6e4SMatt Jacob /* 1266ea49c6e4SMatt Jacob * Sent status and command complete. 1267ea49c6e4SMatt Jacob * 1268ea49c6e4SMatt Jacob * We're now really done with this command, so we 1269ea49c6e4SMatt Jacob * punt to the platform dependent layers because 1270ea49c6e4SMatt Jacob * only there can we do the appropriate command 1271ea49c6e4SMatt Jacob * complete thread synchronization. 1272ea49c6e4SMatt Jacob */ 127310549c05SMatt Jacob isp_prt(isp, pl, "status CTIO complete"); 1274ea49c6e4SMatt Jacob } else { 1275ea49c6e4SMatt Jacob /* 1276ea49c6e4SMatt Jacob * Final CTIO completed. Release DMA resources and 1277ea49c6e4SMatt Jacob * notify platform dependent layers. 1278ea49c6e4SMatt Jacob */ 127910549c05SMatt Jacob isp_prt(isp, pl, "data CTIO complete"); 1280ea49c6e4SMatt Jacob } 1281ea49c6e4SMatt Jacob (void) isp_async(isp, ISPASYNC_TARGET_ACTION, ct); 1282ea49c6e4SMatt Jacob /* 1283ea49c6e4SMatt Jacob * The platform layer will destroy the handle if appropriate. 1284ea49c6e4SMatt Jacob */ 1285ea49c6e4SMatt Jacob } 1286ea49c6e4SMatt Jacob } 1287ea49c6e4SMatt Jacob #endif 1288