1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte 22*fcf3ce44SJohn Forte /* Copyright 2008 QLogic Corporation */ 23*fcf3ce44SJohn Forte 24*fcf3ce44SJohn Forte /* 25*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*fcf3ce44SJohn Forte * Use is subject to license terms. 27*fcf3ce44SJohn Forte */ 28*fcf3ce44SJohn Forte 29*fcf3ce44SJohn Forte #pragma ident "Copyright 2008 QLogic Corporation; ql_isr.c" 30*fcf3ce44SJohn Forte 31*fcf3ce44SJohn Forte /* 32*fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 33*fcf3ce44SJohn Forte * 34*fcf3ce44SJohn Forte * *********************************************************************** 35*fcf3ce44SJohn Forte * * ** 36*fcf3ce44SJohn Forte * * NOTICE ** 37*fcf3ce44SJohn Forte * * COPYRIGHT (C) 1996-2008 QLOGIC CORPORATION ** 38*fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 39*fcf3ce44SJohn Forte * * ** 40*fcf3ce44SJohn Forte * *********************************************************************** 41*fcf3ce44SJohn Forte * 42*fcf3ce44SJohn Forte */ 43*fcf3ce44SJohn Forte 44*fcf3ce44SJohn Forte #include <ql_apps.h> 45*fcf3ce44SJohn Forte #include <ql_api.h> 46*fcf3ce44SJohn Forte #include <ql_debug.h> 47*fcf3ce44SJohn Forte #include <ql_iocb.h> 48*fcf3ce44SJohn Forte #include <ql_isr.h> 49*fcf3ce44SJohn Forte #include <ql_init.h> 50*fcf3ce44SJohn Forte #include <ql_mbx.h> 51*fcf3ce44SJohn Forte #include <ql_xioctl.h> 52*fcf3ce44SJohn Forte 53*fcf3ce44SJohn Forte /* 54*fcf3ce44SJohn Forte * Local Function Prototypes. 55*fcf3ce44SJohn Forte */ 56*fcf3ce44SJohn Forte static void ql_spurious_intr(ql_adapter_state_t *, int); 57*fcf3ce44SJohn Forte static void ql_mbx_completion(ql_adapter_state_t *, uint16_t, uint32_t *, 58*fcf3ce44SJohn Forte uint32_t *, int); 59*fcf3ce44SJohn Forte static void ql_async_event(ql_adapter_state_t *, uint32_t, ql_head_t *, 60*fcf3ce44SJohn Forte uint32_t *, uint32_t *, int); 61*fcf3ce44SJohn Forte static void ql_fast_fcp_post(ql_srb_t *); 62*fcf3ce44SJohn Forte static void ql_response_pkt(ql_adapter_state_t *, ql_head_t *, uint32_t *, 63*fcf3ce44SJohn Forte uint32_t *, int); 64*fcf3ce44SJohn Forte static void ql_error_entry(ql_adapter_state_t *, response_t *, ql_head_t *, 65*fcf3ce44SJohn Forte uint32_t *, uint32_t *); 66*fcf3ce44SJohn Forte static int ql_status_entry(ql_adapter_state_t *, sts_entry_t *, ql_head_t *, 67*fcf3ce44SJohn Forte uint32_t *, uint32_t *); 68*fcf3ce44SJohn Forte static int ql_24xx_status_entry(ql_adapter_state_t *, sts_24xx_entry_t *, 69*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 70*fcf3ce44SJohn Forte static int ql_status_error(ql_adapter_state_t *, ql_srb_t *, sts_entry_t *, 71*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 72*fcf3ce44SJohn Forte static void ql_status_cont_entry(ql_adapter_state_t *, sts_cont_entry_t *, 73*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 74*fcf3ce44SJohn Forte static void ql_immediate_notify_entry(ql_adapter_state_t *, 75*fcf3ce44SJohn Forte immediate_notify_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 76*fcf3ce44SJohn Forte static void ql_notify_acknowledge_entry(ql_adapter_state_t *, 77*fcf3ce44SJohn Forte notify_acknowledge_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 78*fcf3ce44SJohn Forte static void ql_accept_target_io_entry(ql_adapter_state_t *, 79*fcf3ce44SJohn Forte atio_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 80*fcf3ce44SJohn Forte static void ql_continue_target_io_entry(ql_adapter_state_t *, 81*fcf3ce44SJohn Forte ctio_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 82*fcf3ce44SJohn Forte static void ql_ip_entry(ql_adapter_state_t *, ip_entry_t *, ql_head_t *, 83*fcf3ce44SJohn Forte uint32_t *, uint32_t *); 84*fcf3ce44SJohn Forte static void ql_ip_rcv_entry(ql_adapter_state_t *, ip_rcv_entry_t *, 85*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 86*fcf3ce44SJohn Forte static void ql_ip_rcv_cont_entry(ql_adapter_state_t *, 87*fcf3ce44SJohn Forte ip_rcv_cont_entry_t *, ql_head_t *, uint32_t *, uint32_t *); 88*fcf3ce44SJohn Forte static void ql_ip_24xx_rcv_entry(ql_adapter_state_t *, ip_rcv_24xx_entry_t *, 89*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 90*fcf3ce44SJohn Forte static void ql_ms_entry(ql_adapter_state_t *, ms_entry_t *, ql_head_t *, 91*fcf3ce44SJohn Forte uint32_t *, uint32_t *); 92*fcf3ce44SJohn Forte static void ql_report_id_entry(ql_adapter_state_t *, report_id_1_t *, 93*fcf3ce44SJohn Forte ql_head_t *, uint32_t *, uint32_t *); 94*fcf3ce44SJohn Forte 95*fcf3ce44SJohn Forte /* TODO: temporary define until defined in LV */ 96*fcf3ce44SJohn Forte #ifndef FC_STATE_8GBIT_SPEED 97*fcf3ce44SJohn Forte #define FC_STATE_8GBIT_SPEED 0x0700 /* 8 Gbit/sec */ 98*fcf3ce44SJohn Forte #endif 99*fcf3ce44SJohn Forte 100*fcf3ce44SJohn Forte /* 101*fcf3ce44SJohn Forte * ql_isr 102*fcf3ce44SJohn Forte * Process all INTX intr types. 103*fcf3ce44SJohn Forte * 104*fcf3ce44SJohn Forte * Input: 105*fcf3ce44SJohn Forte * arg1: adapter state pointer. 106*fcf3ce44SJohn Forte * 107*fcf3ce44SJohn Forte * Returns: 108*fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 109*fcf3ce44SJohn Forte * 110*fcf3ce44SJohn Forte * Context: 111*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 112*fcf3ce44SJohn Forte */ 113*fcf3ce44SJohn Forte /* ARGSUSED */ 114*fcf3ce44SJohn Forte uint_t 115*fcf3ce44SJohn Forte ql_isr(caddr_t arg1) 116*fcf3ce44SJohn Forte { 117*fcf3ce44SJohn Forte return (ql_isr_aif(arg1, 0)); 118*fcf3ce44SJohn Forte } 119*fcf3ce44SJohn Forte 120*fcf3ce44SJohn Forte /* 121*fcf3ce44SJohn Forte * ql_isr_default 122*fcf3ce44SJohn Forte * Process unknown/unvectored intr types 123*fcf3ce44SJohn Forte * 124*fcf3ce44SJohn Forte * Input: 125*fcf3ce44SJohn Forte * arg1: adapter state pointer. 126*fcf3ce44SJohn Forte * arg2: interrupt vector. 127*fcf3ce44SJohn Forte * 128*fcf3ce44SJohn Forte * Returns: 129*fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 130*fcf3ce44SJohn Forte * 131*fcf3ce44SJohn Forte * Context: 132*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 133*fcf3ce44SJohn Forte */ 134*fcf3ce44SJohn Forte /* ARGSUSED */ 135*fcf3ce44SJohn Forte uint_t 136*fcf3ce44SJohn Forte ql_isr_default(caddr_t arg1, caddr_t arg2) 137*fcf3ce44SJohn Forte { 138*fcf3ce44SJohn Forte ql_adapter_state_t *ha = (void *)arg1; 139*fcf3ce44SJohn Forte 140*fcf3ce44SJohn Forte EL(ha, "isr_default called: idx=%x\n", arg2); 141*fcf3ce44SJohn Forte return (ql_isr_aif(arg1, arg2)); 142*fcf3ce44SJohn Forte } 143*fcf3ce44SJohn Forte 144*fcf3ce44SJohn Forte /* 145*fcf3ce44SJohn Forte * ql_isr_aif 146*fcf3ce44SJohn Forte * Process mailbox and I/O command completions. 147*fcf3ce44SJohn Forte * 148*fcf3ce44SJohn Forte * Input: 149*fcf3ce44SJohn Forte * arg: adapter state pointer. 150*fcf3ce44SJohn Forte * intvec: interrupt vector. 151*fcf3ce44SJohn Forte * 152*fcf3ce44SJohn Forte * Returns: 153*fcf3ce44SJohn Forte * DDI_INTR_CLAIMED or DDI_INTR_UNCLAIMED 154*fcf3ce44SJohn Forte * 155*fcf3ce44SJohn Forte * Context: 156*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 157*fcf3ce44SJohn Forte */ 158*fcf3ce44SJohn Forte /* ARGSUSED */ 159*fcf3ce44SJohn Forte uint_t 160*fcf3ce44SJohn Forte ql_isr_aif(caddr_t arg, caddr_t intvec) 161*fcf3ce44SJohn Forte { 162*fcf3ce44SJohn Forte uint16_t mbx; 163*fcf3ce44SJohn Forte uint32_t stat; 164*fcf3ce44SJohn Forte ql_adapter_state_t *ha = (void *)arg; 165*fcf3ce44SJohn Forte uint32_t set_flags = 0; 166*fcf3ce44SJohn Forte uint32_t reset_flags = 0; 167*fcf3ce44SJohn Forte ql_head_t isr_done_q = {NULL, NULL}; 168*fcf3ce44SJohn Forte uint_t rval = DDI_INTR_UNCLAIMED; 169*fcf3ce44SJohn Forte int spurious_intr = 0; 170*fcf3ce44SJohn Forte boolean_t intr = B_FALSE, daemon = B_FALSE; 171*fcf3ce44SJohn Forte int intr_loop = 4; 172*fcf3ce44SJohn Forte 173*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 174*fcf3ce44SJohn Forte 175*fcf3ce44SJohn Forte QL_PM_LOCK(ha); 176*fcf3ce44SJohn Forte if (ha->power_level != PM_LEVEL_D0) { 177*fcf3ce44SJohn Forte /* 178*fcf3ce44SJohn Forte * Looks like we are about to go down soon, exit early. 179*fcf3ce44SJohn Forte */ 180*fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 181*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): power down exit\n", ha->instance); 182*fcf3ce44SJohn Forte return (DDI_INTR_UNCLAIMED); 183*fcf3ce44SJohn Forte } 184*fcf3ce44SJohn Forte ha->busy++; 185*fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 186*fcf3ce44SJohn Forte 187*fcf3ce44SJohn Forte /* Acquire interrupt lock. */ 188*fcf3ce44SJohn Forte INTR_LOCK(ha); 189*fcf3ce44SJohn Forte 190*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2200)) { 191*fcf3ce44SJohn Forte while (RD16_IO_REG(ha, istatus) & RISC_INT) { 192*fcf3ce44SJohn Forte /* Reset idle timer. */ 193*fcf3ce44SJohn Forte ha->idle_timer = 0; 194*fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 195*fcf3ce44SJohn Forte if (intr_loop) { 196*fcf3ce44SJohn Forte intr_loop--; 197*fcf3ce44SJohn Forte } 198*fcf3ce44SJohn Forte 199*fcf3ce44SJohn Forte /* Special Fast Post 2200. */ 200*fcf3ce44SJohn Forte stat = 0; 201*fcf3ce44SJohn Forte if (ha->task_daemon_flags & FIRMWARE_LOADED && 202*fcf3ce44SJohn Forte ha->flags & ONLINE) { 203*fcf3ce44SJohn Forte ql_srb_t *sp; 204*fcf3ce44SJohn Forte 205*fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, mailbox[23]); 206*fcf3ce44SJohn Forte 207*fcf3ce44SJohn Forte if ((mbx & 3) == MBX23_SCSI_COMPLETION) { 208*fcf3ce44SJohn Forte /* Release mailbox registers. */ 209*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 210*fcf3ce44SJohn Forte 211*fcf3ce44SJohn Forte if (intr_loop) { 212*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, 213*fcf3ce44SJohn Forte HC_CLR_RISC_INT); 214*fcf3ce44SJohn Forte } 215*fcf3ce44SJohn Forte 216*fcf3ce44SJohn Forte /* Get handle. */ 217*fcf3ce44SJohn Forte mbx >>= 4; 218*fcf3ce44SJohn Forte stat = mbx & OSC_INDEX_MASK; 219*fcf3ce44SJohn Forte 220*fcf3ce44SJohn Forte /* Validate handle. */ 221*fcf3ce44SJohn Forte sp = stat < MAX_OUTSTANDING_COMMANDS ? 222*fcf3ce44SJohn Forte ha->outstanding_cmds[stat] : NULL; 223*fcf3ce44SJohn Forte 224*fcf3ce44SJohn Forte if (sp != NULL && (sp->handle & 0xfff) 225*fcf3ce44SJohn Forte == mbx) { 226*fcf3ce44SJohn Forte ha->outstanding_cmds[stat] = 227*fcf3ce44SJohn Forte NULL; 228*fcf3ce44SJohn Forte sp->handle = 0; 229*fcf3ce44SJohn Forte sp->flags &= 230*fcf3ce44SJohn Forte ~SRB_IN_TOKEN_ARRAY; 231*fcf3ce44SJohn Forte 232*fcf3ce44SJohn Forte /* Set completed status. */ 233*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 234*fcf3ce44SJohn Forte 235*fcf3ce44SJohn Forte /* Set completion status */ 236*fcf3ce44SJohn Forte sp->pkt->pkt_reason = 237*fcf3ce44SJohn Forte CS_COMPLETE; 238*fcf3ce44SJohn Forte 239*fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 240*fcf3ce44SJohn Forte } else if (mbx != 241*fcf3ce44SJohn Forte (QL_FCA_BRAND & 0xfff)) { 242*fcf3ce44SJohn Forte if (sp == NULL) { 243*fcf3ce44SJohn Forte EL(ha, "unknown IOCB" 244*fcf3ce44SJohn Forte " handle=%xh\n", 245*fcf3ce44SJohn Forte mbx); 246*fcf3ce44SJohn Forte } else { 247*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB" 248*fcf3ce44SJohn Forte " handle pkt=%xh, " 249*fcf3ce44SJohn Forte "sp=%xh\n", mbx, 250*fcf3ce44SJohn Forte sp->handle & 0xfff); 251*fcf3ce44SJohn Forte } 252*fcf3ce44SJohn Forte 253*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, 254*fcf3ce44SJohn Forte FALSE); 255*fcf3ce44SJohn Forte 256*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & 257*fcf3ce44SJohn Forte (ISP_ABORT_NEEDED | 258*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 259*fcf3ce44SJohn Forte EL(ha, "ISP Invalid " 260*fcf3ce44SJohn Forte "handle, " 261*fcf3ce44SJohn Forte "isp_abort_needed" 262*fcf3ce44SJohn Forte "\n"); 263*fcf3ce44SJohn Forte set_flags |= 264*fcf3ce44SJohn Forte ISP_ABORT_NEEDED; 265*fcf3ce44SJohn Forte } 266*fcf3ce44SJohn Forte } 267*fcf3ce44SJohn Forte } 268*fcf3ce44SJohn Forte } 269*fcf3ce44SJohn Forte 270*fcf3ce44SJohn Forte if (stat == 0) { 271*fcf3ce44SJohn Forte /* Check for mailbox interrupt. */ 272*fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, semaphore); 273*fcf3ce44SJohn Forte if (mbx & BIT_0) { 274*fcf3ce44SJohn Forte /* Release mailbox registers. */ 275*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 276*fcf3ce44SJohn Forte 277*fcf3ce44SJohn Forte /* Get mailbox data. */ 278*fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, mailbox[0]); 279*fcf3ce44SJohn Forte if (mbx > 0x3fff && mbx < 0x8000) { 280*fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, 281*fcf3ce44SJohn Forte &set_flags, &reset_flags, 282*fcf3ce44SJohn Forte intr_loop); 283*fcf3ce44SJohn Forte } else if (mbx > 0x7fff && 284*fcf3ce44SJohn Forte mbx < 0xc000) { 285*fcf3ce44SJohn Forte ql_async_event(ha, mbx, 286*fcf3ce44SJohn Forte &isr_done_q, &set_flags, 287*fcf3ce44SJohn Forte &reset_flags, intr_loop); 288*fcf3ce44SJohn Forte } else { 289*fcf3ce44SJohn Forte EL(ha, "UNKNOWN interrupt " 290*fcf3ce44SJohn Forte "type\n"); 291*fcf3ce44SJohn Forte intr = B_TRUE; 292*fcf3ce44SJohn Forte } 293*fcf3ce44SJohn Forte } else { 294*fcf3ce44SJohn Forte ha->isp_rsp_index = RD16_IO_REG(ha, 295*fcf3ce44SJohn Forte resp_in); 296*fcf3ce44SJohn Forte 297*fcf3ce44SJohn Forte if (ha->isp_rsp_index != 298*fcf3ce44SJohn Forte ha->rsp_ring_index) { 299*fcf3ce44SJohn Forte ql_response_pkt(ha, 300*fcf3ce44SJohn Forte &isr_done_q, &set_flags, 301*fcf3ce44SJohn Forte &reset_flags, intr_loop); 302*fcf3ce44SJohn Forte } else if (++spurious_intr == 303*fcf3ce44SJohn Forte MAX_SPURIOUS_INTR) { 304*fcf3ce44SJohn Forte /* 305*fcf3ce44SJohn Forte * Process excessive 306*fcf3ce44SJohn Forte * spurious intrrupts 307*fcf3ce44SJohn Forte */ 308*fcf3ce44SJohn Forte ql_spurious_intr(ha, 309*fcf3ce44SJohn Forte intr_loop); 310*fcf3ce44SJohn Forte EL(ha, "excessive spurious " 311*fcf3ce44SJohn Forte "interrupts, " 312*fcf3ce44SJohn Forte "isp_abort_needed\n"); 313*fcf3ce44SJohn Forte set_flags |= ISP_ABORT_NEEDED; 314*fcf3ce44SJohn Forte } else { 315*fcf3ce44SJohn Forte intr = B_TRUE; 316*fcf3ce44SJohn Forte } 317*fcf3ce44SJohn Forte } 318*fcf3ce44SJohn Forte } 319*fcf3ce44SJohn Forte 320*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 321*fcf3ce44SJohn Forte if (intr || intr_loop == 0) { 322*fcf3ce44SJohn Forte intr = B_FALSE; 323*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 324*fcf3ce44SJohn Forte } 325*fcf3ce44SJohn Forte 326*fcf3ce44SJohn Forte if (set_flags != 0 || reset_flags != 0) { 327*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 328*fcf3ce44SJohn Forte ha->task_daemon_flags |= set_flags; 329*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~reset_flags; 330*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 331*fcf3ce44SJohn Forte set_flags = 0; 332*fcf3ce44SJohn Forte reset_flags = 0; 333*fcf3ce44SJohn Forte daemon = B_TRUE; 334*fcf3ce44SJohn Forte } 335*fcf3ce44SJohn Forte } 336*fcf3ce44SJohn Forte } else { 337*fcf3ce44SJohn Forte while ((stat = RD32_IO_REG(ha, intr_info_lo)) & BIT_15) { 338*fcf3ce44SJohn Forte mbx = MSW(stat); 339*fcf3ce44SJohn Forte 340*fcf3ce44SJohn Forte /* Reset idle timer. */ 341*fcf3ce44SJohn Forte ha->idle_timer = 0; 342*fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 343*fcf3ce44SJohn Forte if (intr_loop) { 344*fcf3ce44SJohn Forte intr_loop--; 345*fcf3ce44SJohn Forte } 346*fcf3ce44SJohn Forte 347*fcf3ce44SJohn Forte switch (stat & 0x1ff) { 348*fcf3ce44SJohn Forte case ROM_MBX_SUCCESS: 349*fcf3ce44SJohn Forte case ROM_MBX_ERR: 350*fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, &set_flags, 351*fcf3ce44SJohn Forte &reset_flags, intr_loop); 352*fcf3ce44SJohn Forte 353*fcf3ce44SJohn Forte /* Release mailbox registers. */ 354*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 355*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 356*fcf3ce44SJohn Forte } 357*fcf3ce44SJohn Forte break; 358*fcf3ce44SJohn Forte 359*fcf3ce44SJohn Forte case MBX_SUCCESS: 360*fcf3ce44SJohn Forte case MBX_ERR: 361*fcf3ce44SJohn Forte /* Sun FW, Release mailbox registers. */ 362*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 363*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 364*fcf3ce44SJohn Forte } 365*fcf3ce44SJohn Forte ql_mbx_completion(ha, mbx, &set_flags, 366*fcf3ce44SJohn Forte &reset_flags, intr_loop); 367*fcf3ce44SJohn Forte break; 368*fcf3ce44SJohn Forte 369*fcf3ce44SJohn Forte case ASYNC_EVENT: 370*fcf3ce44SJohn Forte /* Sun FW, Release mailbox registers. */ 371*fcf3ce44SJohn Forte if ((CFG_IST(ha, CFG_CTRL_2425)) == 0) { 372*fcf3ce44SJohn Forte WRT16_IO_REG(ha, semaphore, 0); 373*fcf3ce44SJohn Forte } 374*fcf3ce44SJohn Forte ql_async_event(ha, (uint32_t)mbx, &isr_done_q, 375*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 376*fcf3ce44SJohn Forte break; 377*fcf3ce44SJohn Forte 378*fcf3ce44SJohn Forte case RESP_UPDATE: 379*fcf3ce44SJohn Forte if (mbx != ha->rsp_ring_index) { 380*fcf3ce44SJohn Forte ha->isp_rsp_index = mbx; 381*fcf3ce44SJohn Forte ql_response_pkt(ha, &isr_done_q, 382*fcf3ce44SJohn Forte &set_flags, &reset_flags, 383*fcf3ce44SJohn Forte intr_loop); 384*fcf3ce44SJohn Forte } else if (++spurious_intr == 385*fcf3ce44SJohn Forte MAX_SPURIOUS_INTR) { 386*fcf3ce44SJohn Forte /* Process excessive spurious intr. */ 387*fcf3ce44SJohn Forte ql_spurious_intr(ha, intr_loop); 388*fcf3ce44SJohn Forte EL(ha, "excessive spurious " 389*fcf3ce44SJohn Forte "interrupts, isp_abort_needed\n"); 390*fcf3ce44SJohn Forte set_flags |= ISP_ABORT_NEEDED; 391*fcf3ce44SJohn Forte } else { 392*fcf3ce44SJohn Forte intr = B_TRUE; 393*fcf3ce44SJohn Forte } 394*fcf3ce44SJohn Forte break; 395*fcf3ce44SJohn Forte 396*fcf3ce44SJohn Forte case SCSI_FAST_POST_16: 397*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_CMPLT_1_16BIT; 398*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 399*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 400*fcf3ce44SJohn Forte break; 401*fcf3ce44SJohn Forte 402*fcf3ce44SJohn Forte case SCSI_FAST_POST_32: 403*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_CMPLT_1_32BIT; 404*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 405*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 406*fcf3ce44SJohn Forte break; 407*fcf3ce44SJohn Forte 408*fcf3ce44SJohn Forte case CTIO_FAST_POST: 409*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | 410*fcf3ce44SJohn Forte MBA_CTIO_COMPLETION; 411*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 412*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 413*fcf3ce44SJohn Forte break; 414*fcf3ce44SJohn Forte 415*fcf3ce44SJohn Forte case IP_FAST_POST_XMT: 416*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_COMPLETION; 417*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 418*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 419*fcf3ce44SJohn Forte break; 420*fcf3ce44SJohn Forte 421*fcf3ce44SJohn Forte case IP_FAST_POST_RCV: 422*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_RECEIVE; 423*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 424*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 425*fcf3ce44SJohn Forte break; 426*fcf3ce44SJohn Forte 427*fcf3ce44SJohn Forte case IP_FAST_POST_BRD: 428*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | MBA_IP_BROADCAST; 429*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 430*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 431*fcf3ce44SJohn Forte break; 432*fcf3ce44SJohn Forte 433*fcf3ce44SJohn Forte case IP_FAST_POST_RCV_ALN: 434*fcf3ce44SJohn Forte stat = (stat & 0xffff0000) | 435*fcf3ce44SJohn Forte MBA_IP_HDR_DATA_SPLIT; 436*fcf3ce44SJohn Forte ql_async_event(ha, stat, &isr_done_q, 437*fcf3ce44SJohn Forte &set_flags, &reset_flags, intr_loop); 438*fcf3ce44SJohn Forte break; 439*fcf3ce44SJohn Forte 440*fcf3ce44SJohn Forte case ATIO_UPDATE: 441*fcf3ce44SJohn Forte EL(ha, "unsupported ATIO queue update" 442*fcf3ce44SJohn Forte " interrupt, status=%xh\n", stat); 443*fcf3ce44SJohn Forte intr = B_TRUE; 444*fcf3ce44SJohn Forte break; 445*fcf3ce44SJohn Forte 446*fcf3ce44SJohn Forte case ATIO_RESP_UPDATE: 447*fcf3ce44SJohn Forte EL(ha, "unsupported ATIO response queue " 448*fcf3ce44SJohn Forte "update interrupt, status=%xh\n", stat); 449*fcf3ce44SJohn Forte intr = B_TRUE; 450*fcf3ce44SJohn Forte break; 451*fcf3ce44SJohn Forte 452*fcf3ce44SJohn Forte default: 453*fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, hccr); 454*fcf3ce44SJohn Forte if (stat & BIT_8 || 455*fcf3ce44SJohn Forte mbx & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) { 456*fcf3ce44SJohn Forte 457*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 458*fcf3ce44SJohn Forte ha->flags |= PARITY_ERROR; 459*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 460*fcf3ce44SJohn Forte 461*fcf3ce44SJohn Forte if (ha->parity_pause_errors == 0 || 462*fcf3ce44SJohn Forte ha->parity_hccr_err != mbx || 463*fcf3ce44SJohn Forte ha->parity_stat_err != stat) { 464*fcf3ce44SJohn Forte cmn_err(CE_WARN, "qlc(%d): " 465*fcf3ce44SJohn Forte "isr, Internal Parity/" 466*fcf3ce44SJohn Forte "Pause Error - hccr=%xh, " 467*fcf3ce44SJohn Forte "stat=%xh, count=%d", 468*fcf3ce44SJohn Forte ha->instance, mbx, stat, 469*fcf3ce44SJohn Forte ha->parity_pause_errors); 470*fcf3ce44SJohn Forte ha->parity_hccr_err = mbx; 471*fcf3ce44SJohn Forte ha->parity_stat_err = stat; 472*fcf3ce44SJohn Forte } 473*fcf3ce44SJohn Forte 474*fcf3ce44SJohn Forte EL(ha, "parity/pause error, " 475*fcf3ce44SJohn Forte "isp_abort_needed\n"); 476*fcf3ce44SJohn Forte 477*fcf3ce44SJohn Forte if (ql_binary_fw_dump(ha, FALSE) != 478*fcf3ce44SJohn Forte QL_SUCCESS) { 479*fcf3ce44SJohn Forte /* Reset ISP chip. */ 480*fcf3ce44SJohn Forte ql_reset_chip(ha); 481*fcf3ce44SJohn Forte } 482*fcf3ce44SJohn Forte 483*fcf3ce44SJohn Forte if (ha->parity_pause_errors == 0) { 484*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, 485*fcf3ce44SJohn Forte FLASH_ERRLOG_PARITY_ERR, 0, 486*fcf3ce44SJohn Forte MSW(stat), LSW(stat)); 487*fcf3ce44SJohn Forte } 488*fcf3ce44SJohn Forte 489*fcf3ce44SJohn Forte if (ha->parity_pause_errors < 490*fcf3ce44SJohn Forte 0xffffffff) { 491*fcf3ce44SJohn Forte ha->parity_pause_errors++; 492*fcf3ce44SJohn Forte } 493*fcf3ce44SJohn Forte 494*fcf3ce44SJohn Forte set_flags |= ISP_ABORT_NEEDED; 495*fcf3ce44SJohn Forte 496*fcf3ce44SJohn Forte /* Disable ISP interrupts. */ 497*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, 0); 498*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 499*fcf3ce44SJohn Forte ha->flags &= ~INTERRUPTS_ENABLED; 500*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 501*fcf3ce44SJohn Forte } else { 502*fcf3ce44SJohn Forte EL(ha, "UNKNOWN interrupt status=%xh," 503*fcf3ce44SJohn Forte " hccr=%xh\n", stat, mbx); 504*fcf3ce44SJohn Forte } 505*fcf3ce44SJohn Forte intr = B_TRUE; 506*fcf3ce44SJohn Forte break; 507*fcf3ce44SJohn Forte } 508*fcf3ce44SJohn Forte 509*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 510*fcf3ce44SJohn Forte if (intr || intr_loop == 0) { 511*fcf3ce44SJohn Forte intr = B_FALSE; 512*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 513*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 514*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 515*fcf3ce44SJohn Forte } 516*fcf3ce44SJohn Forte 517*fcf3ce44SJohn Forte if (set_flags != 0 || reset_flags != 0) { 518*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 519*fcf3ce44SJohn Forte ha->task_daemon_flags |= set_flags; 520*fcf3ce44SJohn Forte ha->task_daemon_flags &= ~reset_flags; 521*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 522*fcf3ce44SJohn Forte set_flags = 0; 523*fcf3ce44SJohn Forte reset_flags = 0; 524*fcf3ce44SJohn Forte daemon = B_TRUE; 525*fcf3ce44SJohn Forte } 526*fcf3ce44SJohn Forte 527*fcf3ce44SJohn Forte if (ha->flags & PARITY_ERROR) { 528*fcf3ce44SJohn Forte EL(ha, "parity/pause exit\n"); 529*fcf3ce44SJohn Forte mbx = RD16_IO_REG(ha, hccr); /* PCI posting */ 530*fcf3ce44SJohn Forte break; 531*fcf3ce44SJohn Forte } 532*fcf3ce44SJohn Forte } 533*fcf3ce44SJohn Forte } 534*fcf3ce44SJohn Forte 535*fcf3ce44SJohn Forte /* Process claimed interrupts during polls. */ 536*fcf3ce44SJohn Forte if (rval == DDI_INTR_UNCLAIMED && ha->intr_claimed == B_TRUE) { 537*fcf3ce44SJohn Forte ha->intr_claimed = B_FALSE; 538*fcf3ce44SJohn Forte rval = DDI_INTR_CLAIMED; 539*fcf3ce44SJohn Forte } 540*fcf3ce44SJohn Forte 541*fcf3ce44SJohn Forte /* Release interrupt lock. */ 542*fcf3ce44SJohn Forte INTR_UNLOCK(ha); 543*fcf3ce44SJohn Forte 544*fcf3ce44SJohn Forte if (daemon) { 545*fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, 0, 0); 546*fcf3ce44SJohn Forte } 547*fcf3ce44SJohn Forte 548*fcf3ce44SJohn Forte if (isr_done_q.first != NULL) { 549*fcf3ce44SJohn Forte ql_done(isr_done_q.first); 550*fcf3ce44SJohn Forte } 551*fcf3ce44SJohn Forte 552*fcf3ce44SJohn Forte if (rval == DDI_INTR_CLAIMED) { 553*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 554*fcf3ce44SJohn Forte ha->xioctl->TotalInterrupts++; 555*fcf3ce44SJohn Forte } else { 556*fcf3ce44SJohn Forte /*EMPTY*/ 557*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): interrupt not claimed\n", 558*fcf3ce44SJohn Forte ha->instance); 559*fcf3ce44SJohn Forte } 560*fcf3ce44SJohn Forte 561*fcf3ce44SJohn Forte QL_PM_LOCK(ha); 562*fcf3ce44SJohn Forte ha->busy--; 563*fcf3ce44SJohn Forte QL_PM_UNLOCK(ha); 564*fcf3ce44SJohn Forte 565*fcf3ce44SJohn Forte return (rval); 566*fcf3ce44SJohn Forte } 567*fcf3ce44SJohn Forte 568*fcf3ce44SJohn Forte /* 569*fcf3ce44SJohn Forte * ql_spurious_intr 570*fcf3ce44SJohn Forte * Inform Solaris of spurious interrupts. 571*fcf3ce44SJohn Forte * 572*fcf3ce44SJohn Forte * Input: 573*fcf3ce44SJohn Forte * ha: adapter state pointer. 574*fcf3ce44SJohn Forte * intr_clr: early interrupt clear 575*fcf3ce44SJohn Forte * 576*fcf3ce44SJohn Forte * Context: 577*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 578*fcf3ce44SJohn Forte */ 579*fcf3ce44SJohn Forte static void 580*fcf3ce44SJohn Forte ql_spurious_intr(ql_adapter_state_t *ha, int intr_clr) 581*fcf3ce44SJohn Forte { 582*fcf3ce44SJohn Forte ddi_devstate_t state; 583*fcf3ce44SJohn Forte 584*fcf3ce44SJohn Forte EL(ha, "Spurious interrupt\n"); 585*fcf3ce44SJohn Forte 586*fcf3ce44SJohn Forte /* Disable ISP interrupts. */ 587*fcf3ce44SJohn Forte WRT16_IO_REG(ha, ictrl, 0); 588*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 589*fcf3ce44SJohn Forte ha->flags &= ~INTERRUPTS_ENABLED; 590*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 591*fcf3ce44SJohn Forte 592*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 593*fcf3ce44SJohn Forte if (intr_clr) { 594*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 595*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 596*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 597*fcf3ce44SJohn Forte } 598*fcf3ce44SJohn Forte 599*fcf3ce44SJohn Forte state = ddi_get_devstate(ha->dip); 600*fcf3ce44SJohn Forte if (state == DDI_DEVSTATE_UP) { 601*fcf3ce44SJohn Forte /*EMPTY*/ 602*fcf3ce44SJohn Forte ddi_dev_report_fault(ha->dip, DDI_SERVICE_DEGRADED, 603*fcf3ce44SJohn Forte DDI_DEVICE_FAULT, "spurious interrupts"); 604*fcf3ce44SJohn Forte } 605*fcf3ce44SJohn Forte } 606*fcf3ce44SJohn Forte 607*fcf3ce44SJohn Forte /* 608*fcf3ce44SJohn Forte * ql_mbx_completion 609*fcf3ce44SJohn Forte * Processes mailbox completions. 610*fcf3ce44SJohn Forte * 611*fcf3ce44SJohn Forte * Input: 612*fcf3ce44SJohn Forte * ha: adapter state pointer. 613*fcf3ce44SJohn Forte * mb0: Mailbox 0 contents. 614*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 615*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 616*fcf3ce44SJohn Forte * intr_clr: early interrupt clear 617*fcf3ce44SJohn Forte * 618*fcf3ce44SJohn Forte * Context: 619*fcf3ce44SJohn Forte * Interrupt context. 620*fcf3ce44SJohn Forte */ 621*fcf3ce44SJohn Forte /* ARGSUSED */ 622*fcf3ce44SJohn Forte static void 623*fcf3ce44SJohn Forte ql_mbx_completion(ql_adapter_state_t *ha, uint16_t mb0, uint32_t *set_flags, 624*fcf3ce44SJohn Forte uint32_t *reset_flags, int intr_clr) 625*fcf3ce44SJohn Forte { 626*fcf3ce44SJohn Forte uint32_t index; 627*fcf3ce44SJohn Forte uint16_t cnt; 628*fcf3ce44SJohn Forte 629*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 630*fcf3ce44SJohn Forte 631*fcf3ce44SJohn Forte /* Load return mailbox registers. */ 632*fcf3ce44SJohn Forte MBX_REGISTER_LOCK(ha); 633*fcf3ce44SJohn Forte 634*fcf3ce44SJohn Forte if (ha->mcp != NULL) { 635*fcf3ce44SJohn Forte ha->mcp->mb[0] = mb0; 636*fcf3ce44SJohn Forte index = ha->mcp->in_mb & ~MBX_0; 637*fcf3ce44SJohn Forte 638*fcf3ce44SJohn Forte for (cnt = 1; cnt < MAX_MBOX_COUNT && index != 0; cnt++) { 639*fcf3ce44SJohn Forte index >>= 1; 640*fcf3ce44SJohn Forte if (index & MBX_0) { 641*fcf3ce44SJohn Forte ha->mcp->mb[cnt] = RD16_IO_REG(ha, 642*fcf3ce44SJohn Forte mailbox[cnt]); 643*fcf3ce44SJohn Forte } 644*fcf3ce44SJohn Forte } 645*fcf3ce44SJohn Forte 646*fcf3ce44SJohn Forte } else { 647*fcf3ce44SJohn Forte EL(ha, "mcp == NULL\n"); 648*fcf3ce44SJohn Forte } 649*fcf3ce44SJohn Forte 650*fcf3ce44SJohn Forte if (intr_clr) { 651*fcf3ce44SJohn Forte /* Clear RISC interrupt. */ 652*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 653*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 654*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 655*fcf3ce44SJohn Forte } 656*fcf3ce44SJohn Forte 657*fcf3ce44SJohn Forte ha->mailbox_flags = (uint8_t)(ha->mailbox_flags | MBX_INTERRUPT); 658*fcf3ce44SJohn Forte if (ha->flags & INTERRUPTS_ENABLED) { 659*fcf3ce44SJohn Forte cv_broadcast(&ha->cv_mbx_intr); 660*fcf3ce44SJohn Forte } 661*fcf3ce44SJohn Forte 662*fcf3ce44SJohn Forte MBX_REGISTER_UNLOCK(ha); 663*fcf3ce44SJohn Forte 664*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 665*fcf3ce44SJohn Forte } 666*fcf3ce44SJohn Forte 667*fcf3ce44SJohn Forte /* 668*fcf3ce44SJohn Forte * ql_async_event 669*fcf3ce44SJohn Forte * Processes asynchronous events. 670*fcf3ce44SJohn Forte * 671*fcf3ce44SJohn Forte * Input: 672*fcf3ce44SJohn Forte * ha: adapter state pointer. 673*fcf3ce44SJohn Forte * mbx: Mailbox 0 register. 674*fcf3ce44SJohn Forte * done_q: head pointer to done queue. 675*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 676*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 677*fcf3ce44SJohn Forte * intr_clr: early interrupt clear 678*fcf3ce44SJohn Forte * 679*fcf3ce44SJohn Forte * Context: 680*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 681*fcf3ce44SJohn Forte */ 682*fcf3ce44SJohn Forte static void 683*fcf3ce44SJohn Forte ql_async_event(ql_adapter_state_t *ha, uint32_t mbx, ql_head_t *done_q, 684*fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags, int intr_clr) 685*fcf3ce44SJohn Forte { 686*fcf3ce44SJohn Forte uint32_t handle; 687*fcf3ce44SJohn Forte uint32_t index; 688*fcf3ce44SJohn Forte uint16_t cnt; 689*fcf3ce44SJohn Forte uint16_t mb[MAX_MBOX_COUNT]; 690*fcf3ce44SJohn Forte ql_srb_t *sp; 691*fcf3ce44SJohn Forte port_id_t s_id; 692*fcf3ce44SJohn Forte ql_tgt_t *tq; 693*fcf3ce44SJohn Forte boolean_t intr = B_TRUE; 694*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 695*fcf3ce44SJohn Forte 696*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 697*fcf3ce44SJohn Forte 698*fcf3ce44SJohn Forte /* Setup to process fast completion. */ 699*fcf3ce44SJohn Forte mb[0] = LSW(mbx); 700*fcf3ce44SJohn Forte switch (mb[0]) { 701*fcf3ce44SJohn Forte case MBA_SCSI_COMPLETION: 702*fcf3ce44SJohn Forte handle = SHORT_TO_LONG(RD16_IO_REG(ha, mailbox[1]), 703*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[2])); 704*fcf3ce44SJohn Forte break; 705*fcf3ce44SJohn Forte 706*fcf3ce44SJohn Forte case MBA_CMPLT_1_16BIT: 707*fcf3ce44SJohn Forte handle = MSW(mbx); 708*fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 709*fcf3ce44SJohn Forte break; 710*fcf3ce44SJohn Forte 711*fcf3ce44SJohn Forte case MBA_CMPLT_1_32BIT: 712*fcf3ce44SJohn Forte handle = SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox[2])); 713*fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 714*fcf3ce44SJohn Forte break; 715*fcf3ce44SJohn Forte 716*fcf3ce44SJohn Forte case MBA_CTIO_COMPLETION: 717*fcf3ce44SJohn Forte case MBA_IP_COMPLETION: 718*fcf3ce44SJohn Forte handle = CFG_IST(ha, CFG_CTRL_2200) ? SHORT_TO_LONG( 719*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2])) : 720*fcf3ce44SJohn Forte SHORT_TO_LONG(MSW(mbx), RD16_IO_REG(ha, mailbox[2])); 721*fcf3ce44SJohn Forte mb[0] = MBA_SCSI_COMPLETION; 722*fcf3ce44SJohn Forte break; 723*fcf3ce44SJohn Forte 724*fcf3ce44SJohn Forte default: 725*fcf3ce44SJohn Forte break; 726*fcf3ce44SJohn Forte } 727*fcf3ce44SJohn Forte 728*fcf3ce44SJohn Forte /* Handle asynchronous event */ 729*fcf3ce44SJohn Forte switch (mb[0]) { 730*fcf3ce44SJohn Forte case MBA_SCSI_COMPLETION: 731*fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): Fast post completion\n", 732*fcf3ce44SJohn Forte ha->instance); 733*fcf3ce44SJohn Forte 734*fcf3ce44SJohn Forte if (intr_clr) { 735*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 736*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 737*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 738*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 739*fcf3ce44SJohn Forte intr = B_FALSE; 740*fcf3ce44SJohn Forte } 741*fcf3ce44SJohn Forte 742*fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 743*fcf3ce44SJohn Forte break; 744*fcf3ce44SJohn Forte } 745*fcf3ce44SJohn Forte 746*fcf3ce44SJohn Forte /* Get handle. */ 747*fcf3ce44SJohn Forte index = handle & OSC_INDEX_MASK; 748*fcf3ce44SJohn Forte 749*fcf3ce44SJohn Forte /* Validate handle. */ 750*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? 751*fcf3ce44SJohn Forte ha->outstanding_cmds[index] : NULL; 752*fcf3ce44SJohn Forte 753*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == handle) { 754*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 755*fcf3ce44SJohn Forte sp->handle = 0; 756*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 757*fcf3ce44SJohn Forte 758*fcf3ce44SJohn Forte /* Set completed status. */ 759*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 760*fcf3ce44SJohn Forte 761*fcf3ce44SJohn Forte /* Set completion status */ 762*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 763*fcf3ce44SJohn Forte 764*fcf3ce44SJohn Forte if (!(sp->flags & SRB_FCP_CMD_PKT)) { 765*fcf3ce44SJohn Forte /* Place block on done queue */ 766*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 767*fcf3ce44SJohn Forte } else { 768*fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 769*fcf3ce44SJohn Forte } 770*fcf3ce44SJohn Forte } else if (handle != QL_FCA_BRAND) { 771*fcf3ce44SJohn Forte if (sp == NULL) { 772*fcf3ce44SJohn Forte EL(ha, "%xh unknown IOCB handle=%xh\n", 773*fcf3ce44SJohn Forte mb[0], handle); 774*fcf3ce44SJohn Forte } else { 775*fcf3ce44SJohn Forte EL(ha, "%xh mismatch IOCB handle pkt=%xh, " 776*fcf3ce44SJohn Forte "sp=%xh\n", mb[0], handle, sp->handle); 777*fcf3ce44SJohn Forte } 778*fcf3ce44SJohn Forte 779*fcf3ce44SJohn Forte EL(ha, "%xh Fast post, mbx1=%xh, mbx2=%xh, mbx3=%xh," 780*fcf3ce44SJohn Forte "mbx6=%xh, mbx7=%xh\n", mb[0], 781*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1]), 782*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[2]), 783*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[3]), 784*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[6]), 785*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[7])); 786*fcf3ce44SJohn Forte 787*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 788*fcf3ce44SJohn Forte 789*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & 790*fcf3ce44SJohn Forte (ISP_ABORT_NEEDED | ABORT_ISP_ACTIVE))) { 791*fcf3ce44SJohn Forte EL(ha, "%xh ISP Invalid handle, " 792*fcf3ce44SJohn Forte "isp_abort_needed\n", mb[0]); 793*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 794*fcf3ce44SJohn Forte } 795*fcf3ce44SJohn Forte } 796*fcf3ce44SJohn Forte break; 797*fcf3ce44SJohn Forte 798*fcf3ce44SJohn Forte case MBA_RESET: /* Reset */ 799*fcf3ce44SJohn Forte EL(ha, "%xh Reset received\n", mb[0]); 800*fcf3ce44SJohn Forte *set_flags |= RESET_MARKER_NEEDED; 801*fcf3ce44SJohn Forte break; 802*fcf3ce44SJohn Forte 803*fcf3ce44SJohn Forte case MBA_SYSTEM_ERR: /* System Error */ 804*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 805*fcf3ce44SJohn Forte mb[2] = RD16_IO_REG(ha, mailbox[2]); 806*fcf3ce44SJohn Forte mb[3] = RD16_IO_REG(ha, mailbox[3]); 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx1=%xh, " 809*fcf3ce44SJohn Forte "mbx2=%xh, mbx3=%xh, mbx4=%xh, mbx5=%xh, mbx6=%xh,\n " 810*fcf3ce44SJohn Forte "mbx7=%xh, mbx8=%xh, mbx9=%xh, mbx10=%xh, mbx11=%xh, " 811*fcf3ce44SJohn Forte "mbx12=%xh,\n", mb[0], mb[1], mb[2], mb[3], 812*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[4]), RD16_IO_REG(ha, mailbox[5]), 813*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[6]), RD16_IO_REG(ha, mailbox[7]), 814*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[8]), RD16_IO_REG(ha, mailbox[9]), 815*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[10]), RD16_IO_REG(ha, mailbox[11]), 816*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[12])); 817*fcf3ce44SJohn Forte 818*fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, isp_abort_needed\n mbx13=%xh, " 819*fcf3ce44SJohn Forte "mbx14=%xh, mbx15=%xh, mbx16=%xh, mbx17=%xh, mbx18=%xh,\n" 820*fcf3ce44SJohn Forte "mbx19=%xh, mbx20=%xh, mbx21=%xh, mbx22=%xh, mbx23=%xh\n", 821*fcf3ce44SJohn Forte mb[0], RD16_IO_REG(ha, mailbox[13]), 822*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[14]), RD16_IO_REG(ha, mailbox[15]), 823*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[16]), RD16_IO_REG(ha, mailbox[17]), 824*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[18]), RD16_IO_REG(ha, mailbox[19]), 825*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[20]), RD16_IO_REG(ha, mailbox[21]), 826*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[22]), 827*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[23])); 828*fcf3ce44SJohn Forte 829*fcf3ce44SJohn Forte if (ha->reg_off->mbox_cnt > 24) { 830*fcf3ce44SJohn Forte EL(ha, "%xh ISP System Error, mbx24=%xh, mbx25=%xh, " 831*fcf3ce44SJohn Forte "mbx26=%xh,\n mbx27=%xh, mbx28=%xh, mbx29=%xh, " 832*fcf3ce44SJohn Forte "mbx30=%xh, mbx31=%xh\n", mb[0], 833*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[24]), 834*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[25]), 835*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[26]), 836*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[27]), 837*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[28]), 838*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[29]), 839*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[30]), 840*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[31])); 841*fcf3ce44SJohn Forte } 842*fcf3ce44SJohn Forte 843*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 844*fcf3ce44SJohn Forte 845*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8002, mb[1], 846*fcf3ce44SJohn Forte mb[2], mb[3]); 847*fcf3ce44SJohn Forte 848*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 849*fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 850*fcf3ce44SJohn Forte break; 851*fcf3ce44SJohn Forte 852*fcf3ce44SJohn Forte case MBA_REQ_TRANSFER_ERR: /* Request Transfer Error */ 853*fcf3ce44SJohn Forte EL(ha, "%xh Request Transfer Error received, " 854*fcf3ce44SJohn Forte "isp_abort_needed\n", mb[0]); 855*fcf3ce44SJohn Forte 856*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8003, 857*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2]), 858*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[3])); 859*fcf3ce44SJohn Forte 860*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 861*fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 862*fcf3ce44SJohn Forte break; 863*fcf3ce44SJohn Forte 864*fcf3ce44SJohn Forte case MBA_RSP_TRANSFER_ERR: /* Response Xfer Err */ 865*fcf3ce44SJohn Forte EL(ha, "%xh Response Transfer Error received," 866*fcf3ce44SJohn Forte " isp_abort_needed\n", mb[0]); 867*fcf3ce44SJohn Forte 868*fcf3ce44SJohn Forte (void) ql_flash_errlog(ha, FLASH_ERRLOG_AEN_8004, 869*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1]), RD16_IO_REG(ha, mailbox[2]), 870*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[3])); 871*fcf3ce44SJohn Forte 872*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 873*fcf3ce44SJohn Forte ha->xioctl->ControllerErrorCount++; 874*fcf3ce44SJohn Forte break; 875*fcf3ce44SJohn Forte 876*fcf3ce44SJohn Forte case MBA_WAKEUP_THRES: /* Request Queue Wake-up */ 877*fcf3ce44SJohn Forte EL(ha, "%xh Request Queue Wake-up received\n", 878*fcf3ce44SJohn Forte mb[0]); 879*fcf3ce44SJohn Forte break; 880*fcf3ce44SJohn Forte 881*fcf3ce44SJohn Forte case MBA_MENLO_ALERT: /* Menlo Alert Notification */ 882*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 883*fcf3ce44SJohn Forte mb[2] = RD16_IO_REG(ha, mailbox[2]); 884*fcf3ce44SJohn Forte mb[3] = RD16_IO_REG(ha, mailbox[3]); 885*fcf3ce44SJohn Forte 886*fcf3ce44SJohn Forte EL(ha, "%xh Menlo Alert Notification received, mbx1=%xh," 887*fcf3ce44SJohn Forte " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 888*fcf3ce44SJohn Forte 889*fcf3ce44SJohn Forte switch (mb[1]) { 890*fcf3ce44SJohn Forte case MLA_LOGIN_OPERATIONAL_FW: 891*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 892*fcf3ce44SJohn Forte ha->flags |= MENLO_LOGIN_OPERATIONAL; 893*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 894*fcf3ce44SJohn Forte break; 895*fcf3ce44SJohn Forte case MLA_PANIC_RECOVERY: 896*fcf3ce44SJohn Forte case MLA_LOGIN_DIAGNOSTIC_FW: 897*fcf3ce44SJohn Forte case MLA_LOGIN_GOLDEN_FW: 898*fcf3ce44SJohn Forte case MLA_REJECT_RESPONSE: 899*fcf3ce44SJohn Forte default: 900*fcf3ce44SJohn Forte break; 901*fcf3ce44SJohn Forte } 902*fcf3ce44SJohn Forte break; 903*fcf3ce44SJohn Forte 904*fcf3ce44SJohn Forte case MBA_LIP_F8: /* Received a LIP F8. */ 905*fcf3ce44SJohn Forte case MBA_LIP_RESET: /* LIP reset occurred. */ 906*fcf3ce44SJohn Forte case MBA_LIP_OCCURRED: /* Loop Initialization Procedure */ 907*fcf3ce44SJohn Forte EL(ha, "%xh LIP received\n", mb[0]); 908*fcf3ce44SJohn Forte 909*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 910*fcf3ce44SJohn Forte ha->flags &= ~POINT_TO_POINT; 911*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 912*fcf3ce44SJohn Forte 913*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & LOOP_DOWN)) { 914*fcf3ce44SJohn Forte *set_flags |= LOOP_DOWN; 915*fcf3ce44SJohn Forte } 916*fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, 917*fcf3ce44SJohn Forte FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN); 918*fcf3ce44SJohn Forte 919*fcf3ce44SJohn Forte if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 920*fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_START; 921*fcf3ce44SJohn Forte } 922*fcf3ce44SJohn Forte 923*fcf3ce44SJohn Forte ha->adapter_stats->lip_count++; 924*fcf3ce44SJohn Forte 925*fcf3ce44SJohn Forte /* Update AEN queue. */ 926*fcf3ce44SJohn Forte ha->xioctl->TotalLipResets++; 927*fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 928*fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 929*fcf3ce44SJohn Forte } 930*fcf3ce44SJohn Forte break; 931*fcf3ce44SJohn Forte 932*fcf3ce44SJohn Forte case MBA_LOOP_UP: 933*fcf3ce44SJohn Forte if (CFG_IST(ha, (CFG_CTRL_2300|CFG_CTRL_6322|CFG_CTRL_2425))) { 934*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 935*fcf3ce44SJohn Forte if (mb[1] == 0) { /* 1GB */ 936*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 937*fcf3ce44SJohn Forte ha->state) | FC_STATE_1GBIT_SPEED; 938*fcf3ce44SJohn Forte index = 1; 939*fcf3ce44SJohn Forte } else if (mb[1] == 1) { /* 2GB */ 940*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 941*fcf3ce44SJohn Forte ha->state) | FC_STATE_2GBIT_SPEED; 942*fcf3ce44SJohn Forte index = 2; 943*fcf3ce44SJohn Forte } else if (mb[1] == 3) { /* 4GB */ 944*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 945*fcf3ce44SJohn Forte ha->state) | FC_STATE_4GBIT_SPEED; 946*fcf3ce44SJohn Forte index = 4; 947*fcf3ce44SJohn Forte } else if (mb[1] == 4) { /* 8GB */ 948*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 949*fcf3ce44SJohn Forte ha->state) | FC_STATE_8GBIT_SPEED; 950*fcf3ce44SJohn Forte index = 8; 951*fcf3ce44SJohn Forte } else { 952*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK( 953*fcf3ce44SJohn Forte ha->state); 954*fcf3ce44SJohn Forte index = 0; 955*fcf3ce44SJohn Forte } 956*fcf3ce44SJohn Forte } else { 957*fcf3ce44SJohn Forte ha->state = FC_PORT_STATE_MASK(ha->state) | 958*fcf3ce44SJohn Forte FC_STATE_FULL_SPEED; 959*fcf3ce44SJohn Forte index = 1; 960*fcf3ce44SJohn Forte } 961*fcf3ce44SJohn Forte 962*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 963*fcf3ce44SJohn Forte vha->state = FC_PORT_STATE_MASK(vha->state) | 964*fcf3ce44SJohn Forte FC_PORT_SPEED_MASK(ha->state); 965*fcf3ce44SJohn Forte } 966*fcf3ce44SJohn Forte EL(ha, "%d GB %xh Loop Up received\n", index, mb[0]); 967*fcf3ce44SJohn Forte 968*fcf3ce44SJohn Forte /* Update AEN queue. */ 969*fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 970*fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 971*fcf3ce44SJohn Forte } 972*fcf3ce44SJohn Forte break; 973*fcf3ce44SJohn Forte 974*fcf3ce44SJohn Forte case MBA_LOOP_DOWN: 975*fcf3ce44SJohn Forte EL(ha, "%xh Loop Down received, mbx1=%xh, mbx2=%xh, " 976*fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox[1]), 977*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[2]), RD16_IO_REG(ha, mailbox[3])); 978*fcf3ce44SJohn Forte 979*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & LOOP_DOWN)) { 980*fcf3ce44SJohn Forte *set_flags |= LOOP_DOWN; 981*fcf3ce44SJohn Forte } 982*fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, 983*fcf3ce44SJohn Forte FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN); 984*fcf3ce44SJohn Forte 985*fcf3ce44SJohn Forte if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 986*fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_START; 987*fcf3ce44SJohn Forte } 988*fcf3ce44SJohn Forte 989*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_25XX)) { 990*fcf3ce44SJohn Forte ha->sfp_stat = RD16_IO_REG(ha, mailbox[2]); 991*fcf3ce44SJohn Forte } 992*fcf3ce44SJohn Forte 993*fcf3ce44SJohn Forte /* Update AEN queue. */ 994*fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 995*fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 996*fcf3ce44SJohn Forte } 997*fcf3ce44SJohn Forte break; 998*fcf3ce44SJohn Forte 999*fcf3ce44SJohn Forte case MBA_PORT_UPDATE: 1000*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 1001*fcf3ce44SJohn Forte mb[2] = RD16_IO_REG(ha, mailbox[2]); 1002*fcf3ce44SJohn Forte mb[3] = (uint16_t)(ha->flags & VP_ENABLED ? 1003*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[3]) : 0); 1004*fcf3ce44SJohn Forte 1005*fcf3ce44SJohn Forte /* Locate port state structure. */ 1006*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 1007*fcf3ce44SJohn Forte if (vha->vp_index == LSB(mb[3])) { 1008*fcf3ce44SJohn Forte break; 1009*fcf3ce44SJohn Forte } 1010*fcf3ce44SJohn Forte } 1011*fcf3ce44SJohn Forte 1012*fcf3ce44SJohn Forte if (vha == NULL) { 1013*fcf3ce44SJohn Forte break; 1014*fcf3ce44SJohn Forte } 1015*fcf3ce44SJohn Forte 1016*fcf3ce44SJohn Forte if (FC_PORT_STATE_MASK(vha->state) != FC_STATE_OFFLINE || 1017*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_CTRL_2425) && (mb[1] != 0xffff || 1018*fcf3ce44SJohn Forte mb[2] != 6 || mb[3] != 0))) { 1019*fcf3ce44SJohn Forte EL(ha, "%xh Port Database Update, Login/Logout " 1020*fcf3ce44SJohn Forte "received, mbx1=%xh, mbx2=%xh, mbx3=%xh\n", 1021*fcf3ce44SJohn Forte mb[0], mb[1], mb[2], mb[3]); 1022*fcf3ce44SJohn Forte } else { 1023*fcf3ce44SJohn Forte EL(ha, "%xh Port Database Update received, mbx1=%xh," 1024*fcf3ce44SJohn Forte " mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], 1025*fcf3ce44SJohn Forte mb[3]); 1026*fcf3ce44SJohn Forte *set_flags |= LOOP_RESYNC_NEEDED; 1027*fcf3ce44SJohn Forte *set_flags &= ~LOOP_DOWN; 1028*fcf3ce44SJohn Forte *reset_flags |= LOOP_DOWN; 1029*fcf3ce44SJohn Forte *reset_flags &= ~LOOP_RESYNC_NEEDED; 1030*fcf3ce44SJohn Forte vha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 1031*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 1032*fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_RESYNC_NEEDED; 1033*fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_DOWN; 1034*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 1035*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1036*fcf3ce44SJohn Forte vha->flags &= ~COMMAND_ABORT_TIMEOUT; 1037*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1038*fcf3ce44SJohn Forte } 1039*fcf3ce44SJohn Forte 1040*fcf3ce44SJohn Forte /* Update AEN queue. */ 1041*fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1042*fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1043*fcf3ce44SJohn Forte } 1044*fcf3ce44SJohn Forte break; 1045*fcf3ce44SJohn Forte 1046*fcf3ce44SJohn Forte case MBA_RSCN_UPDATE: 1047*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 1048*fcf3ce44SJohn Forte mb[2] = RD16_IO_REG(ha, mailbox[2]); 1049*fcf3ce44SJohn Forte mb[3] = (uint16_t)(ha->flags & VP_ENABLED ? 1050*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[3]) : 0); 1051*fcf3ce44SJohn Forte 1052*fcf3ce44SJohn Forte /* Locate port state structure. */ 1053*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 1054*fcf3ce44SJohn Forte if (vha->vp_index == LSB(mb[3])) { 1055*fcf3ce44SJohn Forte break; 1056*fcf3ce44SJohn Forte } 1057*fcf3ce44SJohn Forte } 1058*fcf3ce44SJohn Forte 1059*fcf3ce44SJohn Forte if (vha == NULL) { 1060*fcf3ce44SJohn Forte break; 1061*fcf3ce44SJohn Forte } 1062*fcf3ce44SJohn Forte 1063*fcf3ce44SJohn Forte if (LSB(mb[1]) == vha->d_id.b.domain && 1064*fcf3ce44SJohn Forte MSB(mb[2]) == vha->d_id.b.area && 1065*fcf3ce44SJohn Forte LSB(mb[2]) == vha->d_id.b.al_pa) { 1066*fcf3ce44SJohn Forte EL(ha, "%xh RSCN match adapter, mbx1=%xh, mbx2=%xh, " 1067*fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1068*fcf3ce44SJohn Forte } else { 1069*fcf3ce44SJohn Forte EL(ha, "%xh RSCN received, mbx1=%xh, mbx2=%xh, " 1070*fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1071*fcf3ce44SJohn Forte if (FC_PORT_STATE_MASK(vha->state) != 1072*fcf3ce44SJohn Forte FC_STATE_OFFLINE) { 1073*fcf3ce44SJohn Forte ql_rcv_rscn_els(vha, &mb[0], done_q); 1074*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 1075*fcf3ce44SJohn Forte vha->task_daemon_flags |= RSCN_UPDATE_NEEDED; 1076*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 1077*fcf3ce44SJohn Forte *set_flags |= RSCN_UPDATE_NEEDED; 1078*fcf3ce44SJohn Forte } 1079*fcf3ce44SJohn Forte } 1080*fcf3ce44SJohn Forte 1081*fcf3ce44SJohn Forte /* Update AEN queue. */ 1082*fcf3ce44SJohn Forte if (ha->xioctl->flags & QL_AEN_TRACKING_ENABLE) { 1083*fcf3ce44SJohn Forte ql_enqueue_aen(ha, mb[0], NULL); 1084*fcf3ce44SJohn Forte } 1085*fcf3ce44SJohn Forte break; 1086*fcf3ce44SJohn Forte 1087*fcf3ce44SJohn Forte case MBA_LIP_ERROR: /* Loop initialization errors. */ 1088*fcf3ce44SJohn Forte EL(ha, "%xh LIP error received, mbx1=%xh\n", mb[0], 1089*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1])); 1090*fcf3ce44SJohn Forte break; 1091*fcf3ce44SJohn Forte 1092*fcf3ce44SJohn Forte case MBA_IP_RECEIVE: 1093*fcf3ce44SJohn Forte case MBA_IP_BROADCAST: 1094*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 1095*fcf3ce44SJohn Forte mb[2] = RD16_IO_REG(ha, mailbox[2]); 1096*fcf3ce44SJohn Forte mb[3] = RD16_IO_REG(ha, mailbox[3]); 1097*fcf3ce44SJohn Forte 1098*fcf3ce44SJohn Forte EL(ha, "%xh IP packet/broadcast received, mbx1=%xh, " 1099*fcf3ce44SJohn Forte "mbx2=%xh, mbx3=%xh\n", mb[0], mb[1], mb[2], mb[3]); 1100*fcf3ce44SJohn Forte 1101*fcf3ce44SJohn Forte /* Locate device queue. */ 1102*fcf3ce44SJohn Forte s_id.b.al_pa = LSB(mb[2]); 1103*fcf3ce44SJohn Forte s_id.b.area = MSB(mb[2]); 1104*fcf3ce44SJohn Forte s_id.b.domain = LSB(mb[1]); 1105*fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 1106*fcf3ce44SJohn Forte EL(ha, "Unknown IP device=%xh\n", s_id.b24); 1107*fcf3ce44SJohn Forte break; 1108*fcf3ce44SJohn Forte } 1109*fcf3ce44SJohn Forte 1110*fcf3ce44SJohn Forte cnt = (uint16_t)(CFG_IST(ha, CFG_CTRL_2425) ? 1111*fcf3ce44SJohn Forte CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb24.buf_size[0], 1112*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb24.buf_size[1]) : 1113*fcf3ce44SJohn Forte CHAR_TO_SHORT(ha->ip_init_ctrl_blk.cb.buf_size[0], 1114*fcf3ce44SJohn Forte ha->ip_init_ctrl_blk.cb.buf_size[1])); 1115*fcf3ce44SJohn Forte 1116*fcf3ce44SJohn Forte tq->ub_sequence_length = mb[3]; 1117*fcf3ce44SJohn Forte tq->ub_total_seg_cnt = (uint8_t)(mb[3] / cnt); 1118*fcf3ce44SJohn Forte if (mb[3] % cnt) { 1119*fcf3ce44SJohn Forte tq->ub_total_seg_cnt++; 1120*fcf3ce44SJohn Forte } 1121*fcf3ce44SJohn Forte cnt = (uint16_t)(tq->ub_total_seg_cnt + 10); 1122*fcf3ce44SJohn Forte 1123*fcf3ce44SJohn Forte for (index = 10; index < ha->reg_off->mbox_cnt && index < cnt; 1124*fcf3ce44SJohn Forte index++) { 1125*fcf3ce44SJohn Forte mb[index] = RD16_IO_REG(ha, mailbox[index]); 1126*fcf3ce44SJohn Forte } 1127*fcf3ce44SJohn Forte 1128*fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 1129*fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 1130*fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 1131*fcf3ce44SJohn Forte tq->ub_loop_id = (uint16_t)(mb[0] == MBA_IP_BROADCAST ? 1132*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_CTRL_2425) ? BROADCAST_24XX_HDL : 1133*fcf3ce44SJohn Forte IP_BROADCAST_LOOP_ID) : tq->loop_id); 1134*fcf3ce44SJohn Forte ha->rcv_dev_q = tq; 1135*fcf3ce44SJohn Forte 1136*fcf3ce44SJohn Forte for (cnt = 10; cnt < ha->reg_off->mbox_cnt && 1137*fcf3ce44SJohn Forte tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) { 1138*fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, mb[cnt], done_q) != 1139*fcf3ce44SJohn Forte QL_SUCCESS) { 1140*fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, " 1141*fcf3ce44SJohn Forte "isp_abort_needed\n"); 1142*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1143*fcf3ce44SJohn Forte break; 1144*fcf3ce44SJohn Forte } 1145*fcf3ce44SJohn Forte } 1146*fcf3ce44SJohn Forte break; 1147*fcf3ce44SJohn Forte 1148*fcf3ce44SJohn Forte case MBA_IP_LOW_WATER_MARK: 1149*fcf3ce44SJohn Forte case MBA_IP_RCV_BUFFER_EMPTY: 1150*fcf3ce44SJohn Forte EL(ha, "%xh IP low water mark / RCV buffer empty received\n", 1151*fcf3ce44SJohn Forte mb[0]); 1152*fcf3ce44SJohn Forte *set_flags |= NEED_UNSOLICITED_BUFFERS; 1153*fcf3ce44SJohn Forte break; 1154*fcf3ce44SJohn Forte 1155*fcf3ce44SJohn Forte case MBA_IP_HDR_DATA_SPLIT: 1156*fcf3ce44SJohn Forte EL(ha, "%xh IP HDR data split received\n", mb[0]); 1157*fcf3ce44SJohn Forte break; 1158*fcf3ce44SJohn Forte 1159*fcf3ce44SJohn Forte case MBA_POINT_TO_POINT: 1160*fcf3ce44SJohn Forte EL(ha, "%xh Point to Point Mode received\n", mb[0]); 1161*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1162*fcf3ce44SJohn Forte ha->flags |= POINT_TO_POINT; 1163*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1164*fcf3ce44SJohn Forte 1165*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & LOOP_DOWN)) { 1166*fcf3ce44SJohn Forte *set_flags |= LOOP_DOWN; 1167*fcf3ce44SJohn Forte } 1168*fcf3ce44SJohn Forte ql_port_state(ha, FC_STATE_OFFLINE, 1169*fcf3ce44SJohn Forte FC_STATE_CHANGE | COMMAND_WAIT_NEEDED | LOOP_DOWN); 1170*fcf3ce44SJohn Forte 1171*fcf3ce44SJohn Forte if (ha->loop_down_timer == LOOP_DOWN_TIMER_OFF) { 1172*fcf3ce44SJohn Forte ha->loop_down_timer = LOOP_DOWN_TIMER_START; 1173*fcf3ce44SJohn Forte } 1174*fcf3ce44SJohn Forte break; 1175*fcf3ce44SJohn Forte 1176*fcf3ce44SJohn Forte case MBA_CHG_IN_CONNECTION: 1177*fcf3ce44SJohn Forte mb[1] = RD16_IO_REG(ha, mailbox[1]); 1178*fcf3ce44SJohn Forte if (mb[1] == 2) { 1179*fcf3ce44SJohn Forte EL(ha, "%xh Change In Connection received, " 1180*fcf3ce44SJohn Forte "mbx1=%xh\n", mb[0], mb[1]); 1181*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1182*fcf3ce44SJohn Forte ha->flags &= ~POINT_TO_POINT; 1183*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1184*fcf3ce44SJohn Forte if (ha->topology & QL_N_PORT) { 1185*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology & 1186*fcf3ce44SJohn Forte ~QL_N_PORT); 1187*fcf3ce44SJohn Forte ha->topology = (uint8_t)(ha->topology | 1188*fcf3ce44SJohn Forte QL_NL_PORT); 1189*fcf3ce44SJohn Forte } 1190*fcf3ce44SJohn Forte } else { 1191*fcf3ce44SJohn Forte EL(ha, "%xh Change In Connection received, " 1192*fcf3ce44SJohn Forte "mbx1=%xh, isp_abort_needed\n", mb[0], mb[1]); 1193*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1194*fcf3ce44SJohn Forte } 1195*fcf3ce44SJohn Forte break; 1196*fcf3ce44SJohn Forte 1197*fcf3ce44SJohn Forte case MBA_ZIO_UPDATE: 1198*fcf3ce44SJohn Forte EL(ha, "%xh ZIO response received\n", mb[0]); 1199*fcf3ce44SJohn Forte 1200*fcf3ce44SJohn Forte ha->isp_rsp_index = RD16_IO_REG(ha, resp_in); 1201*fcf3ce44SJohn Forte ql_response_pkt(ha, done_q, set_flags, reset_flags, intr_clr); 1202*fcf3ce44SJohn Forte intr = B_FALSE; 1203*fcf3ce44SJohn Forte break; 1204*fcf3ce44SJohn Forte 1205*fcf3ce44SJohn Forte case MBA_PORT_BYPASS_CHANGED: 1206*fcf3ce44SJohn Forte EL(ha, "%xh Port Bypass Changed received, mbx1=%xh\n", 1207*fcf3ce44SJohn Forte mb[0], RD16_IO_REG(ha, mailbox[1])); 1208*fcf3ce44SJohn Forte /* 1209*fcf3ce44SJohn Forte * Event generated when there is a transition on 1210*fcf3ce44SJohn Forte * port bypass of crystal+. 1211*fcf3ce44SJohn Forte * Mailbox 1: Bit 0 - External. 1212*fcf3ce44SJohn Forte * Bit 2 - Internal. 1213*fcf3ce44SJohn Forte * When the bit is 0, the port is bypassed. 1214*fcf3ce44SJohn Forte * 1215*fcf3ce44SJohn Forte * For now we will generate a LIP for all cases. 1216*fcf3ce44SJohn Forte */ 1217*fcf3ce44SJohn Forte *set_flags |= HANDLE_PORT_BYPASS_CHANGE; 1218*fcf3ce44SJohn Forte break; 1219*fcf3ce44SJohn Forte 1220*fcf3ce44SJohn Forte case MBA_RECEIVE_ERROR: 1221*fcf3ce44SJohn Forte EL(ha, "%xh Receive Error received, mbx1=%xh, mbx2=%xh\n", 1222*fcf3ce44SJohn Forte mb[0], RD16_IO_REG(ha, mailbox[1]), 1223*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[2])); 1224*fcf3ce44SJohn Forte break; 1225*fcf3ce44SJohn Forte 1226*fcf3ce44SJohn Forte case MBA_LS_RJT_SENT: 1227*fcf3ce44SJohn Forte EL(ha, "%xh LS_RJT Response Sent ELS=%xh\n", mb[0], 1228*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[1])); 1229*fcf3ce44SJohn Forte break; 1230*fcf3ce44SJohn Forte 1231*fcf3ce44SJohn Forte case MBA_FW_RESTART_COMP: 1232*fcf3ce44SJohn Forte EL(ha, "%xh firmware restart complete received mb1=%xh\n", 1233*fcf3ce44SJohn Forte mb[0], RD16_IO_REG(ha, mailbox[1])); 1234*fcf3ce44SJohn Forte break; 1235*fcf3ce44SJohn Forte 1236*fcf3ce44SJohn Forte default: 1237*fcf3ce44SJohn Forte EL(ha, "%xh UNKNOWN event received, mbx1=%xh, mbx2=%xh, " 1238*fcf3ce44SJohn Forte "mbx3=%xh\n", mb[0], RD16_IO_REG(ha, mailbox[1]), 1239*fcf3ce44SJohn Forte RD16_IO_REG(ha, mailbox[2]), RD16_IO_REG(ha, mailbox[3])); 1240*fcf3ce44SJohn Forte break; 1241*fcf3ce44SJohn Forte } 1242*fcf3ce44SJohn Forte 1243*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 1244*fcf3ce44SJohn Forte if (intr && intr_clr) { 1245*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 1246*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 1247*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 1248*fcf3ce44SJohn Forte } 1249*fcf3ce44SJohn Forte 1250*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1251*fcf3ce44SJohn Forte } 1252*fcf3ce44SJohn Forte 1253*fcf3ce44SJohn Forte /* 1254*fcf3ce44SJohn Forte * ql_fast_fcp_post 1255*fcf3ce44SJohn Forte * Fast path for good SCSI I/O completion. 1256*fcf3ce44SJohn Forte * 1257*fcf3ce44SJohn Forte * Input: 1258*fcf3ce44SJohn Forte * sp: SRB pointer. 1259*fcf3ce44SJohn Forte * 1260*fcf3ce44SJohn Forte * Context: 1261*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1262*fcf3ce44SJohn Forte */ 1263*fcf3ce44SJohn Forte static void 1264*fcf3ce44SJohn Forte ql_fast_fcp_post(ql_srb_t *sp) 1265*fcf3ce44SJohn Forte { 1266*fcf3ce44SJohn Forte ql_adapter_state_t *ha = sp->ha; 1267*fcf3ce44SJohn Forte ql_lun_t *lq = sp->lun_queue; 1268*fcf3ce44SJohn Forte ql_tgt_t *tq = lq->target_queue; 1269*fcf3ce44SJohn Forte 1270*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1271*fcf3ce44SJohn Forte 1272*fcf3ce44SJohn Forte ASSERT(sp->flags & SRB_FCP_CMD_PKT && ha && 1273*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_COMPLETE); 1274*fcf3ce44SJohn Forte 1275*fcf3ce44SJohn Forte /* Acquire device queue lock. */ 1276*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 1277*fcf3ce44SJohn Forte 1278*fcf3ce44SJohn Forte /* Decrement outstanding commands on device. */ 1279*fcf3ce44SJohn Forte if (tq->outcnt != 0) { 1280*fcf3ce44SJohn Forte tq->outcnt--; 1281*fcf3ce44SJohn Forte } 1282*fcf3ce44SJohn Forte 1283*fcf3ce44SJohn Forte if (sp->flags & SRB_FCP_CMD_PKT) { 1284*fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_UNTAGGED) { 1285*fcf3ce44SJohn Forte /* 1286*fcf3ce44SJohn Forte * Clear the flag for this LUN so that 1287*fcf3ce44SJohn Forte * untagged commands can be submitted 1288*fcf3ce44SJohn Forte * for it. 1289*fcf3ce44SJohn Forte */ 1290*fcf3ce44SJohn Forte lq->flags &= ~LQF_UNTAGGED_PENDING; 1291*fcf3ce44SJohn Forte } 1292*fcf3ce44SJohn Forte 1293*fcf3ce44SJohn Forte if (lq->lun_outcnt != 0) { 1294*fcf3ce44SJohn Forte lq->lun_outcnt--; 1295*fcf3ce44SJohn Forte } 1296*fcf3ce44SJohn Forte } 1297*fcf3ce44SJohn Forte 1298*fcf3ce44SJohn Forte /* Reset port down retry count on good completion. */ 1299*fcf3ce44SJohn Forte tq->port_down_retry_count = ha->port_down_retry_count; 1300*fcf3ce44SJohn Forte tq->qfull_retry_count = ha->qfull_retry_count; 1301*fcf3ce44SJohn Forte 1302*fcf3ce44SJohn Forte /* Remove command from watchdog queue. */ 1303*fcf3ce44SJohn Forte if (sp->flags & SRB_WATCHDOG_ENABLED) { 1304*fcf3ce44SJohn Forte ql_remove_link(&tq->wdg, &sp->wdg); 1305*fcf3ce44SJohn Forte sp->flags &= ~SRB_WATCHDOG_ENABLED; 1306*fcf3ce44SJohn Forte } 1307*fcf3ce44SJohn Forte 1308*fcf3ce44SJohn Forte if (lq->cmd.first != NULL) { 1309*fcf3ce44SJohn Forte ql_next(ha, lq); 1310*fcf3ce44SJohn Forte } else { 1311*fcf3ce44SJohn Forte /* Release LU queue specific lock. */ 1312*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 1313*fcf3ce44SJohn Forte if (ha->pha->pending_cmds.first != NULL) { 1314*fcf3ce44SJohn Forte ql_start_iocb(ha, NULL); 1315*fcf3ce44SJohn Forte } 1316*fcf3ce44SJohn Forte } 1317*fcf3ce44SJohn Forte 1318*fcf3ce44SJohn Forte /* Sync buffers if required. */ 1319*fcf3ce44SJohn Forte if (sp->flags & SRB_MS_PKT) { 1320*fcf3ce44SJohn Forte (void) ddi_dma_sync(sp->pkt->pkt_resp_dma, 0, 0, 1321*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORCPU); 1322*fcf3ce44SJohn Forte } 1323*fcf3ce44SJohn Forte 1324*fcf3ce44SJohn Forte /* Map ISP completion codes. */ 1325*fcf3ce44SJohn Forte sp->pkt->pkt_expln = FC_EXPLN_NONE; 1326*fcf3ce44SJohn Forte sp->pkt->pkt_action = FC_ACTION_RETRYABLE; 1327*fcf3ce44SJohn Forte sp->pkt->pkt_state = FC_PKT_SUCCESS; 1328*fcf3ce44SJohn Forte 1329*fcf3ce44SJohn Forte /* Now call the pkt completion callback */ 1330*fcf3ce44SJohn Forte if (sp->flags & SRB_POLL) { 1331*fcf3ce44SJohn Forte sp->flags &= ~SRB_POLL; 1332*fcf3ce44SJohn Forte } else if (sp->pkt->pkt_comp) { 1333*fcf3ce44SJohn Forte INTR_UNLOCK(ha); 1334*fcf3ce44SJohn Forte (*sp->pkt->pkt_comp)(sp->pkt); 1335*fcf3ce44SJohn Forte INTR_LOCK(ha); 1336*fcf3ce44SJohn Forte } 1337*fcf3ce44SJohn Forte 1338*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1339*fcf3ce44SJohn Forte } 1340*fcf3ce44SJohn Forte 1341*fcf3ce44SJohn Forte /* 1342*fcf3ce44SJohn Forte * ql_response_pkt 1343*fcf3ce44SJohn Forte * Processes response entry. 1344*fcf3ce44SJohn Forte * 1345*fcf3ce44SJohn Forte * Input: 1346*fcf3ce44SJohn Forte * ha: adapter state pointer. 1347*fcf3ce44SJohn Forte * done_q: head pointer to done queue. 1348*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1349*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1350*fcf3ce44SJohn Forte * intr_clr: early interrupt clear 1351*fcf3ce44SJohn Forte * 1352*fcf3ce44SJohn Forte * Context: 1353*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1354*fcf3ce44SJohn Forte */ 1355*fcf3ce44SJohn Forte static void 1356*fcf3ce44SJohn Forte ql_response_pkt(ql_adapter_state_t *ha, ql_head_t *done_q, uint32_t *set_flags, 1357*fcf3ce44SJohn Forte uint32_t *reset_flags, int intr_clr) 1358*fcf3ce44SJohn Forte { 1359*fcf3ce44SJohn Forte response_t *pkt; 1360*fcf3ce44SJohn Forte uint32_t dma_sync_size_1 = 0; 1361*fcf3ce44SJohn Forte uint32_t dma_sync_size_2 = 0; 1362*fcf3ce44SJohn Forte int status = 0; 1363*fcf3ce44SJohn Forte 1364*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1365*fcf3ce44SJohn Forte 1366*fcf3ce44SJohn Forte /* Clear RISC interrupt */ 1367*fcf3ce44SJohn Forte if (intr_clr) { 1368*fcf3ce44SJohn Forte CFG_IST(ha, CFG_CTRL_2425) ? 1369*fcf3ce44SJohn Forte WRT32_IO_REG(ha, hccr, HC24_CLR_RISC_INT) : 1370*fcf3ce44SJohn Forte WRT16_IO_REG(ha, hccr, HC_CLR_RISC_INT); 1371*fcf3ce44SJohn Forte } 1372*fcf3ce44SJohn Forte 1373*fcf3ce44SJohn Forte if (ha->isp_rsp_index >= RESPONSE_ENTRY_CNT) { 1374*fcf3ce44SJohn Forte EL(ha, "index error = %xh, isp_abort_needed", 1375*fcf3ce44SJohn Forte ha->isp_rsp_index); 1376*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1377*fcf3ce44SJohn Forte return; 1378*fcf3ce44SJohn Forte } 1379*fcf3ce44SJohn Forte 1380*fcf3ce44SJohn Forte if ((ha->flags & ONLINE) == 0) { 1381*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): not onlne, done\n", ha->instance); 1382*fcf3ce44SJohn Forte return; 1383*fcf3ce44SJohn Forte } 1384*fcf3ce44SJohn Forte 1385*fcf3ce44SJohn Forte /* Calculate size of response queue entries to sync. */ 1386*fcf3ce44SJohn Forte if (ha->isp_rsp_index > ha->rsp_ring_index) { 1387*fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1388*fcf3ce44SJohn Forte ((uint32_t)(ha->isp_rsp_index - ha->rsp_ring_index) * 1389*fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1390*fcf3ce44SJohn Forte } else if (ha->isp_rsp_index == 0) { 1391*fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1392*fcf3ce44SJohn Forte ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) * 1393*fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1394*fcf3ce44SJohn Forte } else { 1395*fcf3ce44SJohn Forte /* Responses wrap around the Q */ 1396*fcf3ce44SJohn Forte dma_sync_size_1 = (uint32_t) 1397*fcf3ce44SJohn Forte ((uint32_t)(RESPONSE_ENTRY_CNT - ha->rsp_ring_index) * 1398*fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1399*fcf3ce44SJohn Forte dma_sync_size_2 = (uint32_t) 1400*fcf3ce44SJohn Forte (ha->isp_rsp_index * RESPONSE_ENTRY_SIZE); 1401*fcf3ce44SJohn Forte } 1402*fcf3ce44SJohn Forte 1403*fcf3ce44SJohn Forte /* Sync DMA buffer. */ 1404*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1405*fcf3ce44SJohn Forte (off_t)(ha->rsp_ring_index * RESPONSE_ENTRY_SIZE + 1406*fcf3ce44SJohn Forte RESPONSE_Q_BUFFER_OFFSET), dma_sync_size_1, 1407*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 1408*fcf3ce44SJohn Forte if (dma_sync_size_2) { 1409*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1410*fcf3ce44SJohn Forte RESPONSE_Q_BUFFER_OFFSET, dma_sync_size_2, 1411*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORKERNEL); 1412*fcf3ce44SJohn Forte } 1413*fcf3ce44SJohn Forte 1414*fcf3ce44SJohn Forte while (ha->rsp_ring_index != ha->isp_rsp_index) { 1415*fcf3ce44SJohn Forte pkt = ha->response_ring_ptr; 1416*fcf3ce44SJohn Forte 1417*fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): ha->rsp_rg_idx=%xh, mbx[5]=%xh\n", 1418*fcf3ce44SJohn Forte ha->instance, ha->rsp_ring_index, ha->isp_rsp_index); 1419*fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)ha->response_ring_ptr, 8, 1420*fcf3ce44SJohn Forte RESPONSE_ENTRY_SIZE); 1421*fcf3ce44SJohn Forte 1422*fcf3ce44SJohn Forte /* Adjust ring index. */ 1423*fcf3ce44SJohn Forte ha->rsp_ring_index++; 1424*fcf3ce44SJohn Forte if (ha->rsp_ring_index == RESPONSE_ENTRY_CNT) { 1425*fcf3ce44SJohn Forte ha->rsp_ring_index = 0; 1426*fcf3ce44SJohn Forte ha->response_ring_ptr = ha->response_ring_bp; 1427*fcf3ce44SJohn Forte } else { 1428*fcf3ce44SJohn Forte ha->response_ring_ptr++; 1429*fcf3ce44SJohn Forte } 1430*fcf3ce44SJohn Forte 1431*fcf3ce44SJohn Forte /* Process packet. */ 1432*fcf3ce44SJohn Forte if (ha->status_srb != NULL && pkt->entry_type != 1433*fcf3ce44SJohn Forte STATUS_CONT_TYPE) { 1434*fcf3ce44SJohn Forte ql_add_link_b(done_q, &ha->status_srb->cmd); 1435*fcf3ce44SJohn Forte ha->status_srb = NULL; 1436*fcf3ce44SJohn Forte } 1437*fcf3ce44SJohn Forte 1438*fcf3ce44SJohn Forte pkt->entry_status = (uint8_t)(CFG_IST(ha, CFG_CTRL_2425) ? 1439*fcf3ce44SJohn Forte pkt->entry_status & 0x3c : pkt->entry_status & 0x7e); 1440*fcf3ce44SJohn Forte 1441*fcf3ce44SJohn Forte if (pkt->entry_status != 0) { 1442*fcf3ce44SJohn Forte ql_error_entry(ha, pkt, done_q, set_flags, 1443*fcf3ce44SJohn Forte reset_flags); 1444*fcf3ce44SJohn Forte } else { 1445*fcf3ce44SJohn Forte switch (pkt->entry_type) { 1446*fcf3ce44SJohn Forte case STATUS_TYPE: 1447*fcf3ce44SJohn Forte status |= CFG_IST(ha, CFG_CTRL_2425) ? 1448*fcf3ce44SJohn Forte ql_24xx_status_entry(ha, 1449*fcf3ce44SJohn Forte (sts_24xx_entry_t *)pkt, done_q, set_flags, 1450*fcf3ce44SJohn Forte reset_flags) : 1451*fcf3ce44SJohn Forte ql_status_entry(ha, (sts_entry_t *)pkt, 1452*fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1453*fcf3ce44SJohn Forte break; 1454*fcf3ce44SJohn Forte 1455*fcf3ce44SJohn Forte case STATUS_CONT_TYPE: 1456*fcf3ce44SJohn Forte ql_status_cont_entry(ha, 1457*fcf3ce44SJohn Forte (sts_cont_entry_t *)pkt, done_q, set_flags, 1458*fcf3ce44SJohn Forte reset_flags); 1459*fcf3ce44SJohn Forte break; 1460*fcf3ce44SJohn Forte 1461*fcf3ce44SJohn Forte case IMMEDIATE_NOTIFY_TYPE: 1462*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) { 1463*fcf3ce44SJohn Forte ql_immediate_notify_entry(ha, 1464*fcf3ce44SJohn Forte (immediate_notify_entry_t *)pkt, 1465*fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1466*fcf3ce44SJohn Forte } 1467*fcf3ce44SJohn Forte break; 1468*fcf3ce44SJohn Forte 1469*fcf3ce44SJohn Forte case NOTIFY_ACKNOWLEDGE_TYPE: 1470*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) { 1471*fcf3ce44SJohn Forte ql_notify_acknowledge_entry(ha, 1472*fcf3ce44SJohn Forte (notify_acknowledge_entry_t *)pkt, 1473*fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1474*fcf3ce44SJohn Forte } 1475*fcf3ce44SJohn Forte break; 1476*fcf3ce44SJohn Forte 1477*fcf3ce44SJohn Forte case ATIO_TYPE: 1478*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) { 1479*fcf3ce44SJohn Forte ql_accept_target_io_entry(ha, 1480*fcf3ce44SJohn Forte (atio_entry_t *)pkt, done_q, 1481*fcf3ce44SJohn Forte set_flags, reset_flags); 1482*fcf3ce44SJohn Forte } 1483*fcf3ce44SJohn Forte break; 1484*fcf3ce44SJohn Forte 1485*fcf3ce44SJohn Forte case CTIO_TYPE_2: 1486*fcf3ce44SJohn Forte case CTIO_TYPE_3: 1487*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_TARGET_MODE)) { 1488*fcf3ce44SJohn Forte ql_continue_target_io_entry(ha, 1489*fcf3ce44SJohn Forte (ctio_entry_t *)pkt, done_q, 1490*fcf3ce44SJohn Forte set_flags, reset_flags); 1491*fcf3ce44SJohn Forte } 1492*fcf3ce44SJohn Forte break; 1493*fcf3ce44SJohn Forte 1494*fcf3ce44SJohn Forte case IP_TYPE: 1495*fcf3ce44SJohn Forte case IP_A64_TYPE: 1496*fcf3ce44SJohn Forte case IP_CMD_TYPE: 1497*fcf3ce44SJohn Forte ql_ip_entry(ha, (ip_entry_t *)pkt, done_q, 1498*fcf3ce44SJohn Forte set_flags, reset_flags); 1499*fcf3ce44SJohn Forte break; 1500*fcf3ce44SJohn Forte case IP_RECEIVE_TYPE: 1501*fcf3ce44SJohn Forte ql_ip_rcv_entry(ha, 1502*fcf3ce44SJohn Forte (ip_rcv_entry_t *)pkt, done_q, set_flags, 1503*fcf3ce44SJohn Forte reset_flags); 1504*fcf3ce44SJohn Forte break; 1505*fcf3ce44SJohn Forte case IP_RECEIVE_CONT_TYPE: 1506*fcf3ce44SJohn Forte ql_ip_rcv_cont_entry(ha, 1507*fcf3ce44SJohn Forte (ip_rcv_cont_entry_t *)pkt, done_q, 1508*fcf3ce44SJohn Forte set_flags, reset_flags); 1509*fcf3ce44SJohn Forte break; 1510*fcf3ce44SJohn Forte case IP_24XX_RECEIVE_TYPE: 1511*fcf3ce44SJohn Forte ql_ip_24xx_rcv_entry(ha, 1512*fcf3ce44SJohn Forte (ip_rcv_24xx_entry_t *)pkt, done_q, 1513*fcf3ce44SJohn Forte set_flags, reset_flags); 1514*fcf3ce44SJohn Forte break; 1515*fcf3ce44SJohn Forte case MS_TYPE: 1516*fcf3ce44SJohn Forte ql_ms_entry(ha, (ms_entry_t *)pkt, done_q, 1517*fcf3ce44SJohn Forte set_flags, reset_flags); 1518*fcf3ce44SJohn Forte break; 1519*fcf3ce44SJohn Forte case REPORT_ID_TYPE: 1520*fcf3ce44SJohn Forte ql_report_id_entry(ha, (report_id_1_t *)pkt, 1521*fcf3ce44SJohn Forte done_q, set_flags, reset_flags); 1522*fcf3ce44SJohn Forte break; 1523*fcf3ce44SJohn Forte case IP_BUF_POOL_TYPE: 1524*fcf3ce44SJohn Forte case MARKER_TYPE: 1525*fcf3ce44SJohn Forte case VP_MODIFY_TYPE: 1526*fcf3ce44SJohn Forte case VP_CONTROL_TYPE: 1527*fcf3ce44SJohn Forte break; 1528*fcf3ce44SJohn Forte default: 1529*fcf3ce44SJohn Forte EL(ha, "Unknown IOCB entry type=%xh\n", 1530*fcf3ce44SJohn Forte pkt->entry_type); 1531*fcf3ce44SJohn Forte break; 1532*fcf3ce44SJohn Forte } 1533*fcf3ce44SJohn Forte } 1534*fcf3ce44SJohn Forte } 1535*fcf3ce44SJohn Forte 1536*fcf3ce44SJohn Forte /* Inform RISC of processed responses. */ 1537*fcf3ce44SJohn Forte WRT16_IO_REG(ha, resp_out, ha->rsp_ring_index); 1538*fcf3ce44SJohn Forte 1539*fcf3ce44SJohn Forte /* RESET packet received delay for possible async event. */ 1540*fcf3ce44SJohn Forte if (status & BIT_0) { 1541*fcf3ce44SJohn Forte drv_usecwait(500000); 1542*fcf3ce44SJohn Forte } 1543*fcf3ce44SJohn Forte 1544*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1545*fcf3ce44SJohn Forte } 1546*fcf3ce44SJohn Forte 1547*fcf3ce44SJohn Forte /* 1548*fcf3ce44SJohn Forte * ql_error_entry 1549*fcf3ce44SJohn Forte * Processes error entry. 1550*fcf3ce44SJohn Forte * 1551*fcf3ce44SJohn Forte * Input: 1552*fcf3ce44SJohn Forte * ha = adapter state pointer. 1553*fcf3ce44SJohn Forte * pkt = entry pointer. 1554*fcf3ce44SJohn Forte * done_q = head pointer to done queue. 1555*fcf3ce44SJohn Forte * set_flags = task daemon flags to set. 1556*fcf3ce44SJohn Forte * reset_flags = task daemon flags to reset. 1557*fcf3ce44SJohn Forte * 1558*fcf3ce44SJohn Forte * Context: 1559*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1560*fcf3ce44SJohn Forte */ 1561*fcf3ce44SJohn Forte /* ARGSUSED */ 1562*fcf3ce44SJohn Forte static void 1563*fcf3ce44SJohn Forte ql_error_entry(ql_adapter_state_t *ha, response_t *pkt, ql_head_t *done_q, 1564*fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 1565*fcf3ce44SJohn Forte { 1566*fcf3ce44SJohn Forte ql_srb_t *sp; 1567*fcf3ce44SJohn Forte uint32_t index, cnt; 1568*fcf3ce44SJohn Forte 1569*fcf3ce44SJohn Forte if (pkt->entry_type == INVALID_ENTRY_TYPE) { 1570*fcf3ce44SJohn Forte EL(ha, "Aborted command\n"); 1571*fcf3ce44SJohn Forte return; 1572*fcf3ce44SJohn Forte } 1573*fcf3ce44SJohn Forte 1574*fcf3ce44SJohn Forte QL_PRINT_2(CE_CONT, "(%d): started, packet:\n", ha->instance); 1575*fcf3ce44SJohn Forte QL_DUMP_2((uint8_t *)pkt, 8, RESPONSE_ENTRY_SIZE); 1576*fcf3ce44SJohn Forte 1577*fcf3ce44SJohn Forte if (pkt->entry_status & BIT_6) { 1578*fcf3ce44SJohn Forte EL(ha, "Request Queue DMA error\n"); 1579*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_5) { 1580*fcf3ce44SJohn Forte EL(ha, "Invalid Entry Order\n"); 1581*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_4) { 1582*fcf3ce44SJohn Forte EL(ha, "Invalid Entry Count\n"); 1583*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_3) { 1584*fcf3ce44SJohn Forte EL(ha, "Invalid Entry Parameter\n"); 1585*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_2) { 1586*fcf3ce44SJohn Forte EL(ha, "Invalid Entry Type\n"); 1587*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_1) { 1588*fcf3ce44SJohn Forte EL(ha, "Busy\n"); 1589*fcf3ce44SJohn Forte } else { 1590*fcf3ce44SJohn Forte EL(ha, "UNKNOWN flag = %xh error\n", pkt->entry_status); 1591*fcf3ce44SJohn Forte } 1592*fcf3ce44SJohn Forte 1593*fcf3ce44SJohn Forte /* Get handle. */ 1594*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 1595*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 1596*fcf3ce44SJohn Forte 1597*fcf3ce44SJohn Forte /* Validate handle. */ 1598*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 1599*fcf3ce44SJohn Forte NULL; 1600*fcf3ce44SJohn Forte 1601*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 1602*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 1603*fcf3ce44SJohn Forte sp->handle = 0; 1604*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1605*fcf3ce44SJohn Forte 1606*fcf3ce44SJohn Forte /* Bad payload or header */ 1607*fcf3ce44SJohn Forte if (pkt->entry_status & (BIT_5 + BIT_4 + BIT_3 + BIT_2)) { 1608*fcf3ce44SJohn Forte /* Bad payload or header, set error status. */ 1609*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_BAD_PAYLOAD; 1610*fcf3ce44SJohn Forte } else if (pkt->entry_status & BIT_1) /* FULL flag */ { 1611*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_QUEUE_FULL; 1612*fcf3ce44SJohn Forte } else { 1613*fcf3ce44SJohn Forte /* Set error status. */ 1614*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_UNKNOWN; 1615*fcf3ce44SJohn Forte } 1616*fcf3ce44SJohn Forte 1617*fcf3ce44SJohn Forte /* Set completed status. */ 1618*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 1619*fcf3ce44SJohn Forte 1620*fcf3ce44SJohn Forte /* Place command on done queue. */ 1621*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 1622*fcf3ce44SJohn Forte 1623*fcf3ce44SJohn Forte } else { 1624*fcf3ce44SJohn Forte if (sp == NULL) { 1625*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 1626*fcf3ce44SJohn Forte } else { 1627*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 1628*fcf3ce44SJohn Forte cnt, sp->handle); 1629*fcf3ce44SJohn Forte } 1630*fcf3ce44SJohn Forte 1631*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 1632*fcf3ce44SJohn Forte 1633*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 1634*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 1635*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 1636*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1637*fcf3ce44SJohn Forte } 1638*fcf3ce44SJohn Forte } 1639*fcf3ce44SJohn Forte 1640*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1641*fcf3ce44SJohn Forte } 1642*fcf3ce44SJohn Forte 1643*fcf3ce44SJohn Forte /* 1644*fcf3ce44SJohn Forte * ql_status_entry 1645*fcf3ce44SJohn Forte * Processes received ISP2200-2300 status entry. 1646*fcf3ce44SJohn Forte * 1647*fcf3ce44SJohn Forte * Input: 1648*fcf3ce44SJohn Forte * ha: adapter state pointer. 1649*fcf3ce44SJohn Forte * pkt: entry pointer. 1650*fcf3ce44SJohn Forte * done_q: done queue pointer. 1651*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1652*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1653*fcf3ce44SJohn Forte * 1654*fcf3ce44SJohn Forte * Returns: 1655*fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 1656*fcf3ce44SJohn Forte * 1657*fcf3ce44SJohn Forte * Context: 1658*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1659*fcf3ce44SJohn Forte */ 1660*fcf3ce44SJohn Forte /* ARGSUSED */ 1661*fcf3ce44SJohn Forte static int 1662*fcf3ce44SJohn Forte ql_status_entry(ql_adapter_state_t *ha, sts_entry_t *pkt, 1663*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 1664*fcf3ce44SJohn Forte { 1665*fcf3ce44SJohn Forte ql_srb_t *sp; 1666*fcf3ce44SJohn Forte uint32_t index, cnt; 1667*fcf3ce44SJohn Forte uint16_t comp_status; 1668*fcf3ce44SJohn Forte int rval = 0; 1669*fcf3ce44SJohn Forte 1670*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1671*fcf3ce44SJohn Forte 1672*fcf3ce44SJohn Forte /* Get handle. */ 1673*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 1674*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 1675*fcf3ce44SJohn Forte 1676*fcf3ce44SJohn Forte /* Validate handle. */ 1677*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 1678*fcf3ce44SJohn Forte NULL; 1679*fcf3ce44SJohn Forte 1680*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 1681*fcf3ce44SJohn Forte comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 1682*fcf3ce44SJohn Forte &pkt->comp_status); 1683*fcf3ce44SJohn Forte 1684*fcf3ce44SJohn Forte /* 1685*fcf3ce44SJohn Forte * We dont care about SCSI QFULLs. 1686*fcf3ce44SJohn Forte */ 1687*fcf3ce44SJohn Forte if (comp_status == CS_QUEUE_FULL) { 1688*fcf3ce44SJohn Forte EL(ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n", 1689*fcf3ce44SJohn Forte sp->lun_queue->target_queue->d_id.b24, 1690*fcf3ce44SJohn Forte sp->lun_queue->lun_no); 1691*fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1692*fcf3ce44SJohn Forte } 1693*fcf3ce44SJohn Forte 1694*fcf3ce44SJohn Forte /* 1695*fcf3ce44SJohn Forte * 2300 firmware marks completion status as data underrun 1696*fcf3ce44SJohn Forte * for scsi qfulls. Make it transport complete. 1697*fcf3ce44SJohn Forte */ 1698*fcf3ce44SJohn Forte if ((CFG_IST(ha, (CFG_CTRL_2300 | CFG_CTRL_6322))) && 1699*fcf3ce44SJohn Forte (comp_status == CS_DATA_UNDERRUN) && 1700*fcf3ce44SJohn Forte (pkt->scsi_status_l != 0)) { 1701*fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1702*fcf3ce44SJohn Forte } 1703*fcf3ce44SJohn Forte 1704*fcf3ce44SJohn Forte /* 1705*fcf3ce44SJohn Forte * Workaround T3 issue where we do not get any data xferred 1706*fcf3ce44SJohn Forte * but get back a good status. 1707*fcf3ce44SJohn Forte */ 1708*fcf3ce44SJohn Forte if ((pkt->state_flags_h & SF_XFERRED_DATA) == 0 && 1709*fcf3ce44SJohn Forte comp_status == CS_COMPLETE && 1710*fcf3ce44SJohn Forte pkt->scsi_status_l == 0 && 1711*fcf3ce44SJohn Forte (pkt->scsi_status_h & FCP_RSP_MASK) == 0 && 1712*fcf3ce44SJohn Forte pkt->residual_length == 0 && 1713*fcf3ce44SJohn Forte sp->fcp && 1714*fcf3ce44SJohn Forte sp->fcp->fcp_data_len != 0 && 1715*fcf3ce44SJohn Forte (pkt->state_flags_l & (SF_DATA_OUT | SF_DATA_IN)) == 1716*fcf3ce44SJohn Forte SF_DATA_OUT) { 1717*fcf3ce44SJohn Forte comp_status = CS_ABORTED; 1718*fcf3ce44SJohn Forte } 1719*fcf3ce44SJohn Forte 1720*fcf3ce44SJohn Forte if (sp->flags & SRB_MS_PKT) { 1721*fcf3ce44SJohn Forte /* 1722*fcf3ce44SJohn Forte * Ideally it should never be true. But there 1723*fcf3ce44SJohn Forte * is a bug in FW which upon receiving invalid 1724*fcf3ce44SJohn Forte * parameters in MS IOCB returns it as 1725*fcf3ce44SJohn Forte * status entry and not as ms entry type. 1726*fcf3ce44SJohn Forte */ 1727*fcf3ce44SJohn Forte ql_ms_entry(ha, (ms_entry_t *)pkt, done_q, 1728*fcf3ce44SJohn Forte set_flags, reset_flags); 1729*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n", 1730*fcf3ce44SJohn Forte ha->instance); 1731*fcf3ce44SJohn Forte return (0); 1732*fcf3ce44SJohn Forte } 1733*fcf3ce44SJohn Forte 1734*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 1735*fcf3ce44SJohn Forte sp->handle = 0; 1736*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1737*fcf3ce44SJohn Forte 1738*fcf3ce44SJohn Forte /* 1739*fcf3ce44SJohn Forte * Fast path to good SCSI I/O completion 1740*fcf3ce44SJohn Forte */ 1741*fcf3ce44SJohn Forte if ((comp_status == CS_COMPLETE) & 1742*fcf3ce44SJohn Forte (!pkt->scsi_status_l) & 1743*fcf3ce44SJohn Forte (!(pkt->scsi_status_h & FCP_RSP_MASK))) { 1744*fcf3ce44SJohn Forte /* Set completed status. */ 1745*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 1746*fcf3ce44SJohn Forte sp->pkt->pkt_reason = comp_status; 1747*fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 1748*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n", 1749*fcf3ce44SJohn Forte ha->instance); 1750*fcf3ce44SJohn Forte return (0); 1751*fcf3ce44SJohn Forte } 1752*fcf3ce44SJohn Forte rval = ql_status_error(ha, sp, pkt, done_q, set_flags, 1753*fcf3ce44SJohn Forte reset_flags); 1754*fcf3ce44SJohn Forte } else { 1755*fcf3ce44SJohn Forte if (sp == NULL) { 1756*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 1757*fcf3ce44SJohn Forte } else { 1758*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 1759*fcf3ce44SJohn Forte cnt, sp->handle); 1760*fcf3ce44SJohn Forte } 1761*fcf3ce44SJohn Forte 1762*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 1763*fcf3ce44SJohn Forte 1764*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 1765*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 1766*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 1767*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1768*fcf3ce44SJohn Forte } 1769*fcf3ce44SJohn Forte } 1770*fcf3ce44SJohn Forte 1771*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1772*fcf3ce44SJohn Forte 1773*fcf3ce44SJohn Forte return (rval); 1774*fcf3ce44SJohn Forte } 1775*fcf3ce44SJohn Forte 1776*fcf3ce44SJohn Forte /* 1777*fcf3ce44SJohn Forte * ql_24xx_status_entry 1778*fcf3ce44SJohn Forte * Processes received ISP24xx status entry. 1779*fcf3ce44SJohn Forte * 1780*fcf3ce44SJohn Forte * Input: 1781*fcf3ce44SJohn Forte * ha: adapter state pointer. 1782*fcf3ce44SJohn Forte * pkt: entry pointer. 1783*fcf3ce44SJohn Forte * done_q: done queue pointer. 1784*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1785*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1786*fcf3ce44SJohn Forte * 1787*fcf3ce44SJohn Forte * Returns: 1788*fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 1789*fcf3ce44SJohn Forte * 1790*fcf3ce44SJohn Forte * Context: 1791*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1792*fcf3ce44SJohn Forte */ 1793*fcf3ce44SJohn Forte /* ARGSUSED */ 1794*fcf3ce44SJohn Forte static int 1795*fcf3ce44SJohn Forte ql_24xx_status_entry(ql_adapter_state_t *ha, sts_24xx_entry_t *pkt, 1796*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 1797*fcf3ce44SJohn Forte { 1798*fcf3ce44SJohn Forte ql_srb_t *sp; 1799*fcf3ce44SJohn Forte uint32_t index, cnt; 1800*fcf3ce44SJohn Forte uint16_t comp_status; 1801*fcf3ce44SJohn Forte int rval = 0; 1802*fcf3ce44SJohn Forte 1803*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1804*fcf3ce44SJohn Forte 1805*fcf3ce44SJohn Forte /* Get handle. */ 1806*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 1807*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 1808*fcf3ce44SJohn Forte 1809*fcf3ce44SJohn Forte /* Validate handle. */ 1810*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 1811*fcf3ce44SJohn Forte NULL; 1812*fcf3ce44SJohn Forte 1813*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 1814*fcf3ce44SJohn Forte comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 1815*fcf3ce44SJohn Forte &pkt->comp_status); 1816*fcf3ce44SJohn Forte 1817*fcf3ce44SJohn Forte /* 1818*fcf3ce44SJohn Forte * We dont care about SCSI QFULLs. 1819*fcf3ce44SJohn Forte */ 1820*fcf3ce44SJohn Forte if (comp_status == CS_QUEUE_FULL) { 1821*fcf3ce44SJohn Forte EL(sp->ha, "CS_QUEUE_FULL, d_id=%xh, lun=%xh\n", 1822*fcf3ce44SJohn Forte sp->lun_queue->target_queue->d_id.b24, 1823*fcf3ce44SJohn Forte sp->lun_queue->lun_no); 1824*fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1825*fcf3ce44SJohn Forte } 1826*fcf3ce44SJohn Forte 1827*fcf3ce44SJohn Forte /* 1828*fcf3ce44SJohn Forte * 2300 firmware marks completion status as data underrun 1829*fcf3ce44SJohn Forte * for scsi qfulls. Make it transport complete. 1830*fcf3ce44SJohn Forte */ 1831*fcf3ce44SJohn Forte if ((comp_status == CS_DATA_UNDERRUN) && 1832*fcf3ce44SJohn Forte (pkt->scsi_status_l != 0)) { 1833*fcf3ce44SJohn Forte comp_status = CS_COMPLETE; 1834*fcf3ce44SJohn Forte } 1835*fcf3ce44SJohn Forte 1836*fcf3ce44SJohn Forte /* 1837*fcf3ce44SJohn Forte * Workaround T3 issue where we do not get any data xferred 1838*fcf3ce44SJohn Forte * but get back a good status. 1839*fcf3ce44SJohn Forte */ 1840*fcf3ce44SJohn Forte if (comp_status == CS_COMPLETE && 1841*fcf3ce44SJohn Forte pkt->scsi_status_l == 0 && 1842*fcf3ce44SJohn Forte (pkt->scsi_status_h & FCP_RSP_MASK) == 0 && 1843*fcf3ce44SJohn Forte pkt->residual_length != 0 && 1844*fcf3ce44SJohn Forte sp->fcp && 1845*fcf3ce44SJohn Forte sp->fcp->fcp_data_len != 0 && 1846*fcf3ce44SJohn Forte sp->fcp->fcp_cntl.cntl_write_data) { 1847*fcf3ce44SJohn Forte comp_status = CS_ABORTED; 1848*fcf3ce44SJohn Forte } 1849*fcf3ce44SJohn Forte 1850*fcf3ce44SJohn Forte if (sp->flags & SRB_MS_PKT) { 1851*fcf3ce44SJohn Forte /* 1852*fcf3ce44SJohn Forte * Ideally it should never be true. But there 1853*fcf3ce44SJohn Forte * is a bug in FW which upon receiving invalid 1854*fcf3ce44SJohn Forte * parameters in MS IOCB returns it as 1855*fcf3ce44SJohn Forte * status entry and not as ms entry type. 1856*fcf3ce44SJohn Forte */ 1857*fcf3ce44SJohn Forte ql_ms_entry(ha, (ms_entry_t *)pkt, done_q, 1858*fcf3ce44SJohn Forte set_flags, reset_flags); 1859*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_ms_entry done\n", 1860*fcf3ce44SJohn Forte ha->instance); 1861*fcf3ce44SJohn Forte return (0); 1862*fcf3ce44SJohn Forte } 1863*fcf3ce44SJohn Forte 1864*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 1865*fcf3ce44SJohn Forte sp->handle = 0; 1866*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 1867*fcf3ce44SJohn Forte 1868*fcf3ce44SJohn Forte /* 1869*fcf3ce44SJohn Forte * Fast path to good SCSI I/O completion 1870*fcf3ce44SJohn Forte */ 1871*fcf3ce44SJohn Forte if ((comp_status == CS_COMPLETE) & 1872*fcf3ce44SJohn Forte (!pkt->scsi_status_l) & 1873*fcf3ce44SJohn Forte (!(pkt->scsi_status_h & FCP_RSP_MASK))) { 1874*fcf3ce44SJohn Forte /* Set completed status. */ 1875*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 1876*fcf3ce44SJohn Forte sp->pkt->pkt_reason = comp_status; 1877*fcf3ce44SJohn Forte ql_fast_fcp_post(sp); 1878*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): ql_fast_fcp_post done\n", 1879*fcf3ce44SJohn Forte ha->instance); 1880*fcf3ce44SJohn Forte return (0); 1881*fcf3ce44SJohn Forte } 1882*fcf3ce44SJohn Forte rval = ql_status_error(ha, sp, (sts_entry_t *)pkt, done_q, 1883*fcf3ce44SJohn Forte set_flags, reset_flags); 1884*fcf3ce44SJohn Forte } else { 1885*fcf3ce44SJohn Forte if (sp == NULL) { 1886*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 1887*fcf3ce44SJohn Forte } else { 1888*fcf3ce44SJohn Forte EL(sp->ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 1889*fcf3ce44SJohn Forte cnt, sp->handle); 1890*fcf3ce44SJohn Forte } 1891*fcf3ce44SJohn Forte 1892*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 1893*fcf3ce44SJohn Forte 1894*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 1895*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 1896*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 1897*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 1898*fcf3ce44SJohn Forte } 1899*fcf3ce44SJohn Forte } 1900*fcf3ce44SJohn Forte 1901*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1902*fcf3ce44SJohn Forte 1903*fcf3ce44SJohn Forte return (rval); 1904*fcf3ce44SJohn Forte } 1905*fcf3ce44SJohn Forte 1906*fcf3ce44SJohn Forte /* 1907*fcf3ce44SJohn Forte * ql_status_error 1908*fcf3ce44SJohn Forte * Processes received ISP status entry error. 1909*fcf3ce44SJohn Forte * 1910*fcf3ce44SJohn Forte * Input: 1911*fcf3ce44SJohn Forte * ha: adapter state pointer. 1912*fcf3ce44SJohn Forte * sp: SRB pointer. 1913*fcf3ce44SJohn Forte * pkt: entry pointer. 1914*fcf3ce44SJohn Forte * done_q: done queue pointer. 1915*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 1916*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 1917*fcf3ce44SJohn Forte * 1918*fcf3ce44SJohn Forte * Returns: 1919*fcf3ce44SJohn Forte * BIT_0 = CS_RESET status received. 1920*fcf3ce44SJohn Forte * 1921*fcf3ce44SJohn Forte * Context: 1922*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1923*fcf3ce44SJohn Forte */ 1924*fcf3ce44SJohn Forte /* ARGSUSED */ 1925*fcf3ce44SJohn Forte static int 1926*fcf3ce44SJohn Forte ql_status_error(ql_adapter_state_t *ha, ql_srb_t *sp, sts_entry_t *pkt23, 1927*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 1928*fcf3ce44SJohn Forte { 1929*fcf3ce44SJohn Forte uint32_t sense_sz = 0; 1930*fcf3ce44SJohn Forte uint32_t cnt; 1931*fcf3ce44SJohn Forte ql_tgt_t *tq; 1932*fcf3ce44SJohn Forte fcp_rsp_t *fcpr; 1933*fcf3ce44SJohn Forte struct fcp_rsp_info *rsp; 1934*fcf3ce44SJohn Forte int rval = 0; 1935*fcf3ce44SJohn Forte 1936*fcf3ce44SJohn Forte struct { 1937*fcf3ce44SJohn Forte uint8_t *rsp_info; 1938*fcf3ce44SJohn Forte uint8_t *req_sense_data; 1939*fcf3ce44SJohn Forte uint32_t residual_length; 1940*fcf3ce44SJohn Forte uint32_t fcp_residual_length; 1941*fcf3ce44SJohn Forte uint32_t rsp_info_length; 1942*fcf3ce44SJohn Forte uint32_t req_sense_length; 1943*fcf3ce44SJohn Forte uint16_t comp_status; 1944*fcf3ce44SJohn Forte uint8_t state_flags_l; 1945*fcf3ce44SJohn Forte uint8_t state_flags_h; 1946*fcf3ce44SJohn Forte uint8_t scsi_status_l; 1947*fcf3ce44SJohn Forte uint8_t scsi_status_h; 1948*fcf3ce44SJohn Forte } sts; 1949*fcf3ce44SJohn Forte 1950*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1951*fcf3ce44SJohn Forte 1952*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 1953*fcf3ce44SJohn Forte sts_24xx_entry_t *pkt24 = (sts_24xx_entry_t *)pkt23; 1954*fcf3ce44SJohn Forte 1955*fcf3ce44SJohn Forte /* Setup status. */ 1956*fcf3ce44SJohn Forte sts.comp_status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 1957*fcf3ce44SJohn Forte &pkt24->comp_status); 1958*fcf3ce44SJohn Forte sts.scsi_status_l = pkt24->scsi_status_l; 1959*fcf3ce44SJohn Forte sts.scsi_status_h = pkt24->scsi_status_h; 1960*fcf3ce44SJohn Forte 1961*fcf3ce44SJohn Forte /* Setup firmware residuals. */ 1962*fcf3ce44SJohn Forte sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ? 1963*fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 1964*fcf3ce44SJohn Forte (uint32_t *)&pkt24->residual_length) : 0; 1965*fcf3ce44SJohn Forte 1966*fcf3ce44SJohn Forte /* Setup FCP residuals. */ 1967*fcf3ce44SJohn Forte sts.fcp_residual_length = sts.scsi_status_h & 1968*fcf3ce44SJohn Forte (FCP_RESID_UNDER | FCP_RESID_OVER) ? 1969*fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 1970*fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_rsp_residual_count) : 0; 1971*fcf3ce44SJohn Forte 1972*fcf3ce44SJohn Forte if ((sts.comp_status == CS_DATA_UNDERRUN) && 1973*fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER) && 1974*fcf3ce44SJohn Forte (sts.residual_length != pkt24->fcp_rsp_residual_count)) { 1975*fcf3ce44SJohn Forte 1976*fcf3ce44SJohn Forte EL(sp->ha, "mismatch resid's: fw=%xh, pkt=%xh\n", 1977*fcf3ce44SJohn Forte sts.residual_length, 1978*fcf3ce44SJohn Forte pkt24->fcp_rsp_residual_count); 1979*fcf3ce44SJohn Forte sts.scsi_status_h = (uint8_t) 1980*fcf3ce44SJohn Forte (sts.scsi_status_h & ~FCP_RESID_UNDER); 1981*fcf3ce44SJohn Forte } 1982*fcf3ce44SJohn Forte 1983*fcf3ce44SJohn Forte /* Setup state flags. */ 1984*fcf3ce44SJohn Forte sts.state_flags_l = pkt24->state_flags_l; 1985*fcf3ce44SJohn Forte sts.state_flags_h = pkt24->state_flags_h; 1986*fcf3ce44SJohn Forte 1987*fcf3ce44SJohn Forte if (sp->fcp->fcp_data_len && 1988*fcf3ce44SJohn Forte (sts.comp_status != CS_DATA_UNDERRUN || 1989*fcf3ce44SJohn Forte sts.residual_length != sp->fcp->fcp_data_len)) { 1990*fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 1991*fcf3ce44SJohn Forte (sts.state_flags_h | SF_GOT_BUS | 1992*fcf3ce44SJohn Forte SF_GOT_TARGET | SF_SENT_CMD | 1993*fcf3ce44SJohn Forte SF_XFERRED_DATA | SF_GOT_STATUS); 1994*fcf3ce44SJohn Forte } else { 1995*fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 1996*fcf3ce44SJohn Forte (sts.state_flags_h | SF_GOT_BUS | 1997*fcf3ce44SJohn Forte SF_GOT_TARGET | SF_SENT_CMD | 1998*fcf3ce44SJohn Forte SF_GOT_STATUS); 1999*fcf3ce44SJohn Forte } 2000*fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_write_data) { 2001*fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2002*fcf3ce44SJohn Forte (sts.state_flags_l | SF_DATA_OUT); 2003*fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_read_data) { 2004*fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2005*fcf3ce44SJohn Forte (sts.state_flags_l | SF_DATA_IN); 2006*fcf3ce44SJohn Forte } 2007*fcf3ce44SJohn Forte if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) { 2008*fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2009*fcf3ce44SJohn Forte (sts.state_flags_l | SF_HEAD_OF_Q); 2010*fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) { 2011*fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2012*fcf3ce44SJohn Forte (sts.state_flags_l | SF_ORDERED_Q); 2013*fcf3ce44SJohn Forte } else if (sp->fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) { 2014*fcf3ce44SJohn Forte sts.state_flags_l = (uint8_t) 2015*fcf3ce44SJohn Forte (sts.state_flags_l | SF_SIMPLE_Q); 2016*fcf3ce44SJohn Forte } 2017*fcf3ce44SJohn Forte 2018*fcf3ce44SJohn Forte /* Setup FCP response info. */ 2019*fcf3ce44SJohn Forte sts.rsp_info = &pkt24->rsp_sense_data[0]; 2020*fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) { 2021*fcf3ce44SJohn Forte sts.rsp_info_length = ddi_get32(ha->hba_buf.acc_handle, 2022*fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_rsp_data_length); 2023*fcf3ce44SJohn Forte if (sts.rsp_info_length > 2024*fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info)) { 2025*fcf3ce44SJohn Forte sts.rsp_info_length = 2026*fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info); 2027*fcf3ce44SJohn Forte } 2028*fcf3ce44SJohn Forte for (cnt = 0; cnt < sts.rsp_info_length; cnt += 4) { 2029*fcf3ce44SJohn Forte ql_chg_endian(sts.rsp_info + cnt, 4); 2030*fcf3ce44SJohn Forte } 2031*fcf3ce44SJohn Forte } else { 2032*fcf3ce44SJohn Forte sts.rsp_info_length = 0; 2033*fcf3ce44SJohn Forte } 2034*fcf3ce44SJohn Forte 2035*fcf3ce44SJohn Forte /* Setup sense data. */ 2036*fcf3ce44SJohn Forte sts.req_sense_data = 2037*fcf3ce44SJohn Forte &pkt24->rsp_sense_data[sts.rsp_info_length]; 2038*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2039*fcf3ce44SJohn Forte sts.req_sense_length = 2040*fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2041*fcf3ce44SJohn Forte (uint32_t *)&pkt24->fcp_sense_length); 2042*fcf3ce44SJohn Forte sts.state_flags_h = (uint8_t) 2043*fcf3ce44SJohn Forte (sts.state_flags_h | SF_ARQ_DONE); 2044*fcf3ce44SJohn Forte sense_sz = (uint32_t) 2045*fcf3ce44SJohn Forte (((uintptr_t)pkt24 + sizeof (sts_24xx_entry_t)) - 2046*fcf3ce44SJohn Forte (uintptr_t)sts.req_sense_data); 2047*fcf3ce44SJohn Forte for (cnt = 0; cnt < sense_sz; cnt += 4) { 2048*fcf3ce44SJohn Forte ql_chg_endian(sts.req_sense_data + cnt, 4); 2049*fcf3ce44SJohn Forte } 2050*fcf3ce44SJohn Forte } else { 2051*fcf3ce44SJohn Forte sts.req_sense_length = 0; 2052*fcf3ce44SJohn Forte } 2053*fcf3ce44SJohn Forte } else { 2054*fcf3ce44SJohn Forte /* Setup status. */ 2055*fcf3ce44SJohn Forte sts.comp_status = (uint16_t)ddi_get16( 2056*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 2057*fcf3ce44SJohn Forte sts.scsi_status_l = pkt23->scsi_status_l; 2058*fcf3ce44SJohn Forte sts.scsi_status_h = pkt23->scsi_status_h; 2059*fcf3ce44SJohn Forte 2060*fcf3ce44SJohn Forte /* Setup firmware residuals. */ 2061*fcf3ce44SJohn Forte sts.residual_length = sts.comp_status == CS_DATA_UNDERRUN ? 2062*fcf3ce44SJohn Forte ddi_get32(ha->hba_buf.acc_handle, 2063*fcf3ce44SJohn Forte (uint32_t *)&pkt23->residual_length) : 0; 2064*fcf3ce44SJohn Forte 2065*fcf3ce44SJohn Forte /* Setup FCP residuals. */ 2066*fcf3ce44SJohn Forte sts.fcp_residual_length = sts.scsi_status_h & 2067*fcf3ce44SJohn Forte (FCP_RESID_UNDER | FCP_RESID_OVER) ? 2068*fcf3ce44SJohn Forte sts.residual_length : 0; 2069*fcf3ce44SJohn Forte 2070*fcf3ce44SJohn Forte /* Setup state flags. */ 2071*fcf3ce44SJohn Forte sts.state_flags_l = pkt23->state_flags_l; 2072*fcf3ce44SJohn Forte sts.state_flags_h = pkt23->state_flags_h; 2073*fcf3ce44SJohn Forte 2074*fcf3ce44SJohn Forte /* Setup FCP response info. */ 2075*fcf3ce44SJohn Forte sts.rsp_info = &pkt23->rsp_info[0]; 2076*fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) != 0) { 2077*fcf3ce44SJohn Forte sts.rsp_info_length = ddi_get16( 2078*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, 2079*fcf3ce44SJohn Forte (uint16_t *)&pkt23->rsp_info_length); 2080*fcf3ce44SJohn Forte if (sts.rsp_info_length > 2081*fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info)) { 2082*fcf3ce44SJohn Forte sts.rsp_info_length = 2083*fcf3ce44SJohn Forte sizeof (struct fcp_rsp_info); 2084*fcf3ce44SJohn Forte } 2085*fcf3ce44SJohn Forte } else { 2086*fcf3ce44SJohn Forte sts.rsp_info_length = 0; 2087*fcf3ce44SJohn Forte } 2088*fcf3ce44SJohn Forte 2089*fcf3ce44SJohn Forte /* Setup sense data. */ 2090*fcf3ce44SJohn Forte sts.req_sense_data = &pkt23->req_sense_data[0]; 2091*fcf3ce44SJohn Forte sts.req_sense_length = sts.scsi_status_h & FCP_SNS_LEN_VALID ? 2092*fcf3ce44SJohn Forte ddi_get16(ha->hba_buf.acc_handle, 2093*fcf3ce44SJohn Forte (uint16_t *)&pkt23->req_sense_length) : 0; 2094*fcf3ce44SJohn Forte } 2095*fcf3ce44SJohn Forte 2096*fcf3ce44SJohn Forte bzero(sp->pkt->pkt_resp, sp->pkt->pkt_rsplen); 2097*fcf3ce44SJohn Forte 2098*fcf3ce44SJohn Forte fcpr = (fcp_rsp_t *)sp->pkt->pkt_resp; 2099*fcf3ce44SJohn Forte rsp = (struct fcp_rsp_info *)(sp->pkt->pkt_resp + 2100*fcf3ce44SJohn Forte sizeof (fcp_rsp_t)); 2101*fcf3ce44SJohn Forte 2102*fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 2103*fcf3ce44SJohn Forte 2104*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.scsi_status = sts.scsi_status_l; 2105*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RSP_LEN_VALID) { 2106*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.rsp_len_set = 1; 2107*fcf3ce44SJohn Forte } 2108*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2109*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.sense_len_set = 1; 2110*fcf3ce44SJohn Forte } 2111*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RESID_OVER) { 2112*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.resid_over = 1; 2113*fcf3ce44SJohn Forte } 2114*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_RESID_UNDER) { 2115*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.resid_under = 1; 2116*fcf3ce44SJohn Forte } 2117*fcf3ce44SJohn Forte fcpr->fcp_u.fcp_status.reserved_1 = 0; 2118*fcf3ce44SJohn Forte 2119*fcf3ce44SJohn Forte /* Set ISP completion status */ 2120*fcf3ce44SJohn Forte sp->pkt->pkt_reason = sts.comp_status; 2121*fcf3ce44SJohn Forte 2122*fcf3ce44SJohn Forte /* Update statistics. */ 2123*fcf3ce44SJohn Forte if ((sts.scsi_status_h & FCP_RSP_LEN_VALID) && 2124*fcf3ce44SJohn Forte (sp->pkt->pkt_rsplen > sizeof (fcp_rsp_t))) { 2125*fcf3ce44SJohn Forte 2126*fcf3ce44SJohn Forte sense_sz = sp->pkt->pkt_rsplen - (uint32_t)sizeof (fcp_rsp_t); 2127*fcf3ce44SJohn Forte if (sense_sz > sts.rsp_info_length) { 2128*fcf3ce44SJohn Forte sense_sz = sts.rsp_info_length; 2129*fcf3ce44SJohn Forte } 2130*fcf3ce44SJohn Forte 2131*fcf3ce44SJohn Forte /* copy response information data. */ 2132*fcf3ce44SJohn Forte if (sense_sz) { 2133*fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, (uint8_t *)rsp, 2134*fcf3ce44SJohn Forte sts.rsp_info, sense_sz, DDI_DEV_AUTOINCR); 2135*fcf3ce44SJohn Forte } 2136*fcf3ce44SJohn Forte fcpr->fcp_response_len = sense_sz; 2137*fcf3ce44SJohn Forte 2138*fcf3ce44SJohn Forte rsp = (struct fcp_rsp_info *)((caddr_t)rsp + 2139*fcf3ce44SJohn Forte fcpr->fcp_response_len); 2140*fcf3ce44SJohn Forte 2141*fcf3ce44SJohn Forte switch (*(sts.rsp_info + 3)) { 2142*fcf3ce44SJohn Forte case FCP_NO_FAILURE: 2143*fcf3ce44SJohn Forte break; 2144*fcf3ce44SJohn Forte case FCP_DL_LEN_MISMATCH: 2145*fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2146*fcf3ce44SJohn Forte tq->loop_id)].dl_len_mismatches++; 2147*fcf3ce44SJohn Forte break; 2148*fcf3ce44SJohn Forte case FCP_CMND_INVALID: 2149*fcf3ce44SJohn Forte break; 2150*fcf3ce44SJohn Forte case FCP_DATA_RO_MISMATCH: 2151*fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2152*fcf3ce44SJohn Forte tq->loop_id)].data_ro_mismatches++; 2153*fcf3ce44SJohn Forte break; 2154*fcf3ce44SJohn Forte case FCP_TASK_MGMT_NOT_SUPPTD: 2155*fcf3ce44SJohn Forte break; 2156*fcf3ce44SJohn Forte case FCP_TASK_MGMT_FAILED: 2157*fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 2158*fcf3ce44SJohn Forte tq->loop_id)].task_mgmt_failures++; 2159*fcf3ce44SJohn Forte break; 2160*fcf3ce44SJohn Forte default: 2161*fcf3ce44SJohn Forte break; 2162*fcf3ce44SJohn Forte } 2163*fcf3ce44SJohn Forte } else { 2164*fcf3ce44SJohn Forte /* 2165*fcf3ce44SJohn Forte * EL(sp->ha, "scsi_h=%xh, pkt_rsplen=%xh\n", 2166*fcf3ce44SJohn Forte * sts.scsi_status_h, sp->pkt->pkt_rsplen); 2167*fcf3ce44SJohn Forte */ 2168*fcf3ce44SJohn Forte fcpr->fcp_response_len = 0; 2169*fcf3ce44SJohn Forte } 2170*fcf3ce44SJohn Forte 2171*fcf3ce44SJohn Forte /* Set reset status received. */ 2172*fcf3ce44SJohn Forte if (sts.comp_status == CS_RESET && LOOP_READY(ha)) { 2173*fcf3ce44SJohn Forte rval |= BIT_0; 2174*fcf3ce44SJohn Forte } 2175*fcf3ce44SJohn Forte 2176*fcf3ce44SJohn Forte if (!(tq->flags & TQF_TAPE_DEVICE) && 2177*fcf3ce44SJohn Forte (!(CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) || 2178*fcf3ce44SJohn Forte ha->loop_down_abort_time < LOOP_DOWN_TIMER_START) && 2179*fcf3ce44SJohn Forte ha->task_daemon_flags & LOOP_DOWN) { 2180*fcf3ce44SJohn Forte EL(sp->ha, "Loop Not Ready Retry, d_id=%xh, lun=%xh\n", 2181*fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2182*fcf3ce44SJohn Forte 2183*fcf3ce44SJohn Forte /* Set retry status. */ 2184*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2185*fcf3ce44SJohn Forte } else if (!(tq->flags & TQF_TAPE_DEVICE) && 2186*fcf3ce44SJohn Forte tq->port_down_retry_count != 0 && 2187*fcf3ce44SJohn Forte (sts.comp_status == CS_INCOMPLETE || 2188*fcf3ce44SJohn Forte sts.comp_status == CS_PORT_UNAVAILABLE || 2189*fcf3ce44SJohn Forte sts.comp_status == CS_PORT_LOGGED_OUT || 2190*fcf3ce44SJohn Forte sts.comp_status == CS_PORT_CONFIG_CHG || 2191*fcf3ce44SJohn Forte sts.comp_status == CS_PORT_BUSY)) { 2192*fcf3ce44SJohn Forte EL(sp->ha, "Port Down Retry=%xh, d_id=%xh, lun=%xh, count=%d" 2193*fcf3ce44SJohn Forte "\n", sts.comp_status, tq->d_id.b24, sp->lun_queue->lun_no, 2194*fcf3ce44SJohn Forte tq->port_down_retry_count); 2195*fcf3ce44SJohn Forte 2196*fcf3ce44SJohn Forte /* Set retry status. */ 2197*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2198*fcf3ce44SJohn Forte 2199*fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 2200*fcf3ce44SJohn Forte /* Acquire device queue lock. */ 2201*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 2202*fcf3ce44SJohn Forte 2203*fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 2204*fcf3ce44SJohn Forte 2205*fcf3ce44SJohn Forte /* Decrement port down count. */ 2206*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_LINK_DOWN_REPORTING)) { 2207*fcf3ce44SJohn Forte tq->port_down_retry_count--; 2208*fcf3ce44SJohn Forte } 2209*fcf3ce44SJohn Forte 2210*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 2211*fcf3ce44SJohn Forte 2212*fcf3ce44SJohn Forte if ((ha->task_daemon_flags & ABORT_ISP_ACTIVE) 2213*fcf3ce44SJohn Forte == 0 && 2214*fcf3ce44SJohn Forte (sts.comp_status == CS_PORT_LOGGED_OUT || 2215*fcf3ce44SJohn Forte sts.comp_status == CS_PORT_UNAVAILABLE)) { 2216*fcf3ce44SJohn Forte sp->ha->adapter_stats->d_stats[lobyte( 2217*fcf3ce44SJohn Forte tq->loop_id)].logouts_recvd++; 2218*fcf3ce44SJohn Forte ql_send_logo(sp->ha, tq, done_q); 2219*fcf3ce44SJohn Forte } 2220*fcf3ce44SJohn Forte 2221*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2222*fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 2223*fcf3ce44SJohn Forte if ((ha->port_retry_timer = 2224*fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 2225*fcf3ce44SJohn Forte *set_flags |= 2226*fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 2227*fcf3ce44SJohn Forte } 2228*fcf3ce44SJohn Forte } 2229*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2230*fcf3ce44SJohn Forte } 2231*fcf3ce44SJohn Forte } else if (!(tq->flags & TQF_TAPE_DEVICE) && 2232*fcf3ce44SJohn Forte (sts.comp_status == CS_RESET || 2233*fcf3ce44SJohn Forte (sts.comp_status == CS_QUEUE_FULL && tq->qfull_retry_count != 0) || 2234*fcf3ce44SJohn Forte (sts.comp_status == CS_ABORTED && !(sp->flags & SRB_ABORTING)))) { 2235*fcf3ce44SJohn Forte if (sts.comp_status == CS_RESET) { 2236*fcf3ce44SJohn Forte EL(sp->ha, "Reset Retry, d_id=%xh, lun=%xh\n", 2237*fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2238*fcf3ce44SJohn Forte } else if (sts.comp_status == CS_QUEUE_FULL) { 2239*fcf3ce44SJohn Forte EL(sp->ha, "Queue Full Retry, d_id=%xh, lun=%xh, " 2240*fcf3ce44SJohn Forte "cnt=%d\n", tq->d_id.b24, sp->lun_queue->lun_no, 2241*fcf3ce44SJohn Forte tq->qfull_retry_count); 2242*fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 2243*fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 2244*fcf3ce44SJohn Forte 2245*fcf3ce44SJohn Forte tq->qfull_retry_count--; 2246*fcf3ce44SJohn Forte 2247*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 2248*fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 2249*fcf3ce44SJohn Forte if ((ha->port_retry_timer = 2250*fcf3ce44SJohn Forte ha->qfull_retry_delay) == 2251*fcf3ce44SJohn Forte 0) { 2252*fcf3ce44SJohn Forte *set_flags |= 2253*fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 2254*fcf3ce44SJohn Forte } 2255*fcf3ce44SJohn Forte } 2256*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 2257*fcf3ce44SJohn Forte } 2258*fcf3ce44SJohn Forte } else { 2259*fcf3ce44SJohn Forte EL(sp->ha, "Abort Retry, d_id=%xh, lun=%xh\n", 2260*fcf3ce44SJohn Forte tq->d_id.b24, sp->lun_queue->lun_no); 2261*fcf3ce44SJohn Forte } 2262*fcf3ce44SJohn Forte 2263*fcf3ce44SJohn Forte /* Set retry status. */ 2264*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 2265*fcf3ce44SJohn Forte } else { 2266*fcf3ce44SJohn Forte fcpr->fcp_resid = 2267*fcf3ce44SJohn Forte sts.fcp_residual_length > sp->fcp->fcp_data_len ? 2268*fcf3ce44SJohn Forte sp->fcp->fcp_data_len : sts.fcp_residual_length; 2269*fcf3ce44SJohn Forte 2270*fcf3ce44SJohn Forte if ((sts.comp_status == CS_DATA_UNDERRUN) && 2271*fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER) == 0) { 2272*fcf3ce44SJohn Forte 2273*fcf3ce44SJohn Forte if (sts.scsi_status_l == STATUS_CHECK) { 2274*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 2275*fcf3ce44SJohn Forte } else { 2276*fcf3ce44SJohn Forte EL(ha, "transport error - " 2277*fcf3ce44SJohn Forte "underrun & invalid resid\n"); 2278*fcf3ce44SJohn Forte EL(ha, "ssh=%xh, ssl=%xh\n", 2279*fcf3ce44SJohn Forte sts.scsi_status_h, sts.scsi_status_l); 2280*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_FCP_RESPONSE_ERROR; 2281*fcf3ce44SJohn Forte } 2282*fcf3ce44SJohn Forte } 2283*fcf3ce44SJohn Forte 2284*fcf3ce44SJohn Forte /* Ignore firmware underrun error. */ 2285*fcf3ce44SJohn Forte if (sts.comp_status == CS_DATA_UNDERRUN && 2286*fcf3ce44SJohn Forte (sts.scsi_status_h & FCP_RESID_UNDER || 2287*fcf3ce44SJohn Forte (sts.scsi_status_l != STATUS_CHECK && 2288*fcf3ce44SJohn Forte sts.scsi_status_l != STATUS_GOOD))) { 2289*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 2290*fcf3ce44SJohn Forte } 2291*fcf3ce44SJohn Forte 2292*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason != CS_COMPLETE) { 2293*fcf3ce44SJohn Forte ha->xioctl->DeviceErrorCount++; 2294*fcf3ce44SJohn Forte EL(sp->ha, "Cmplt status err = %xh, d_id=%xh, lun=%xh" 2295*fcf3ce44SJohn Forte "\n", sts.comp_status, tq->d_id.b24, 2296*fcf3ce44SJohn Forte sp->lun_queue->lun_no); 2297*fcf3ce44SJohn Forte } 2298*fcf3ce44SJohn Forte 2299*fcf3ce44SJohn Forte /* Set target request sense data. */ 2300*fcf3ce44SJohn Forte if (sts.scsi_status_l == STATUS_CHECK) { 2301*fcf3ce44SJohn Forte if (sts.scsi_status_h & FCP_SNS_LEN_VALID) { 2302*fcf3ce44SJohn Forte 2303*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_COMPLETE && 2304*fcf3ce44SJohn Forte sts.req_sense_data[2] != KEY_NO_SENSE && 2305*fcf3ce44SJohn Forte sts.req_sense_data[2] != 2306*fcf3ce44SJohn Forte KEY_UNIT_ATTENTION) { 2307*fcf3ce44SJohn Forte ha->xioctl->DeviceErrorCount++; 2308*fcf3ce44SJohn Forte } 2309*fcf3ce44SJohn Forte 2310*fcf3ce44SJohn Forte sense_sz = sts.req_sense_length; 2311*fcf3ce44SJohn Forte 2312*fcf3ce44SJohn Forte /* Insure data does not exceed buf. */ 2313*fcf3ce44SJohn Forte if (sp->pkt->pkt_rsplen <= 2314*fcf3ce44SJohn Forte (uint32_t)sizeof (fcp_rsp_t) + 2315*fcf3ce44SJohn Forte fcpr->fcp_response_len) { 2316*fcf3ce44SJohn Forte sp->request_sense_length = 0; 2317*fcf3ce44SJohn Forte } else { 2318*fcf3ce44SJohn Forte sp->request_sense_length = (uint32_t) 2319*fcf3ce44SJohn Forte (sp->pkt->pkt_rsplen - 2320*fcf3ce44SJohn Forte sizeof (fcp_rsp_t) - 2321*fcf3ce44SJohn Forte fcpr->fcp_response_len); 2322*fcf3ce44SJohn Forte } 2323*fcf3ce44SJohn Forte 2324*fcf3ce44SJohn Forte if (sense_sz < 2325*fcf3ce44SJohn Forte sp->request_sense_length) { 2326*fcf3ce44SJohn Forte sp->request_sense_length = 2327*fcf3ce44SJohn Forte sense_sz; 2328*fcf3ce44SJohn Forte } 2329*fcf3ce44SJohn Forte 2330*fcf3ce44SJohn Forte sp->request_sense_ptr = (caddr_t)rsp; 2331*fcf3ce44SJohn Forte 2332*fcf3ce44SJohn Forte sense_sz = (uint32_t) 2333*fcf3ce44SJohn Forte (((uintptr_t)pkt23 + 2334*fcf3ce44SJohn Forte sizeof (sts_entry_t)) - 2335*fcf3ce44SJohn Forte (uintptr_t)sts.req_sense_data); 2336*fcf3ce44SJohn Forte if (sp->request_sense_length < 2337*fcf3ce44SJohn Forte sense_sz) { 2338*fcf3ce44SJohn Forte sense_sz = 2339*fcf3ce44SJohn Forte sp->request_sense_length; 2340*fcf3ce44SJohn Forte } 2341*fcf3ce44SJohn Forte 2342*fcf3ce44SJohn Forte fcpr->fcp_sense_len = sense_sz; 2343*fcf3ce44SJohn Forte 2344*fcf3ce44SJohn Forte /* Move sense data. */ 2345*fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, 2346*fcf3ce44SJohn Forte (uint8_t *)sp->request_sense_ptr, 2347*fcf3ce44SJohn Forte sts.req_sense_data, 2348*fcf3ce44SJohn Forte (size_t)sense_sz, 2349*fcf3ce44SJohn Forte DDI_DEV_AUTOINCR); 2350*fcf3ce44SJohn Forte 2351*fcf3ce44SJohn Forte sp->request_sense_ptr += sense_sz; 2352*fcf3ce44SJohn Forte sp->request_sense_length -= sense_sz; 2353*fcf3ce44SJohn Forte if (sp->request_sense_length != 0) { 2354*fcf3ce44SJohn Forte ha->status_srb = sp; 2355*fcf3ce44SJohn Forte } 2356*fcf3ce44SJohn Forte } 2357*fcf3ce44SJohn Forte 2358*fcf3ce44SJohn Forte if (sense_sz != 0) { 2359*fcf3ce44SJohn Forte EL(sp->ha, "check condition sense data, " 2360*fcf3ce44SJohn Forte "d_id=%xh, lun=%xh\n%2xh%3xh%3xh%3xh" 2361*fcf3ce44SJohn Forte "%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh%3xh" 2362*fcf3ce44SJohn Forte "%3xh%3xh%3xh%3xh%3xh\n", tq->d_id.b24, 2363*fcf3ce44SJohn Forte sp->lun_queue->lun_no, 2364*fcf3ce44SJohn Forte sts.req_sense_data[0], 2365*fcf3ce44SJohn Forte sts.req_sense_data[1], 2366*fcf3ce44SJohn Forte sts.req_sense_data[2], 2367*fcf3ce44SJohn Forte sts.req_sense_data[3], 2368*fcf3ce44SJohn Forte sts.req_sense_data[4], 2369*fcf3ce44SJohn Forte sts.req_sense_data[5], 2370*fcf3ce44SJohn Forte sts.req_sense_data[6], 2371*fcf3ce44SJohn Forte sts.req_sense_data[7], 2372*fcf3ce44SJohn Forte sts.req_sense_data[8], 2373*fcf3ce44SJohn Forte sts.req_sense_data[9], 2374*fcf3ce44SJohn Forte sts.req_sense_data[10], 2375*fcf3ce44SJohn Forte sts.req_sense_data[11], 2376*fcf3ce44SJohn Forte sts.req_sense_data[12], 2377*fcf3ce44SJohn Forte sts.req_sense_data[13], 2378*fcf3ce44SJohn Forte sts.req_sense_data[14], 2379*fcf3ce44SJohn Forte sts.req_sense_data[15], 2380*fcf3ce44SJohn Forte sts.req_sense_data[16], 2381*fcf3ce44SJohn Forte sts.req_sense_data[17]); 2382*fcf3ce44SJohn Forte } else { 2383*fcf3ce44SJohn Forte EL(sp->ha, "check condition, d_id=%xh, lun=%xh" 2384*fcf3ce44SJohn Forte "\n", tq->d_id.b24, sp->lun_queue->lun_no); 2385*fcf3ce44SJohn Forte } 2386*fcf3ce44SJohn Forte } 2387*fcf3ce44SJohn Forte } 2388*fcf3ce44SJohn Forte 2389*fcf3ce44SJohn Forte /* Set completed status. */ 2390*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2391*fcf3ce44SJohn Forte 2392*fcf3ce44SJohn Forte /* Place command on done queue. */ 2393*fcf3ce44SJohn Forte if (ha->status_srb == NULL) { 2394*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2395*fcf3ce44SJohn Forte } 2396*fcf3ce44SJohn Forte 2397*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2398*fcf3ce44SJohn Forte 2399*fcf3ce44SJohn Forte return (rval); 2400*fcf3ce44SJohn Forte } 2401*fcf3ce44SJohn Forte 2402*fcf3ce44SJohn Forte /* 2403*fcf3ce44SJohn Forte * ql_status_cont_entry 2404*fcf3ce44SJohn Forte * Processes status continuation entry. 2405*fcf3ce44SJohn Forte * 2406*fcf3ce44SJohn Forte * Input: 2407*fcf3ce44SJohn Forte * ha: adapter state pointer. 2408*fcf3ce44SJohn Forte * pkt: entry pointer. 2409*fcf3ce44SJohn Forte * done_q: done queue pointer. 2410*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2411*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2412*fcf3ce44SJohn Forte * 2413*fcf3ce44SJohn Forte * Context: 2414*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2415*fcf3ce44SJohn Forte */ 2416*fcf3ce44SJohn Forte /* ARGSUSED */ 2417*fcf3ce44SJohn Forte static void 2418*fcf3ce44SJohn Forte ql_status_cont_entry(ql_adapter_state_t *ha, sts_cont_entry_t *pkt, 2419*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2420*fcf3ce44SJohn Forte { 2421*fcf3ce44SJohn Forte uint32_t sense_sz, index; 2422*fcf3ce44SJohn Forte ql_srb_t *sp = ha->status_srb; 2423*fcf3ce44SJohn Forte 2424*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2425*fcf3ce44SJohn Forte 2426*fcf3ce44SJohn Forte if (sp != NULL && sp->request_sense_length) { 2427*fcf3ce44SJohn Forte if (sp->request_sense_length > sizeof (pkt->req_sense_data)) { 2428*fcf3ce44SJohn Forte sense_sz = sizeof (pkt->req_sense_data); 2429*fcf3ce44SJohn Forte } else { 2430*fcf3ce44SJohn Forte sense_sz = sp->request_sense_length; 2431*fcf3ce44SJohn Forte } 2432*fcf3ce44SJohn Forte 2433*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 2434*fcf3ce44SJohn Forte for (index = 0; index < sense_sz; index += 4) { 2435*fcf3ce44SJohn Forte ql_chg_endian((uint8_t *) 2436*fcf3ce44SJohn Forte &pkt->req_sense_data[0] + index, 4); 2437*fcf3ce44SJohn Forte } 2438*fcf3ce44SJohn Forte } 2439*fcf3ce44SJohn Forte 2440*fcf3ce44SJohn Forte /* Move sense data. */ 2441*fcf3ce44SJohn Forte ddi_rep_get8(ha->hba_buf.acc_handle, 2442*fcf3ce44SJohn Forte (uint8_t *)sp->request_sense_ptr, 2443*fcf3ce44SJohn Forte (uint8_t *)&pkt->req_sense_data[0], (size_t)sense_sz, 2444*fcf3ce44SJohn Forte DDI_DEV_AUTOINCR); 2445*fcf3ce44SJohn Forte 2446*fcf3ce44SJohn Forte sp->request_sense_ptr += sense_sz; 2447*fcf3ce44SJohn Forte sp->request_sense_length -= sense_sz; 2448*fcf3ce44SJohn Forte 2449*fcf3ce44SJohn Forte /* Place command on done queue. */ 2450*fcf3ce44SJohn Forte if (sp->request_sense_length == 0) { 2451*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2452*fcf3ce44SJohn Forte ha->status_srb = NULL; 2453*fcf3ce44SJohn Forte } 2454*fcf3ce44SJohn Forte } 2455*fcf3ce44SJohn Forte 2456*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2457*fcf3ce44SJohn Forte } 2458*fcf3ce44SJohn Forte 2459*fcf3ce44SJohn Forte /* 2460*fcf3ce44SJohn Forte * ql_immediate_notify_entry 2461*fcf3ce44SJohn Forte * Processes immediate notify entry. 2462*fcf3ce44SJohn Forte * 2463*fcf3ce44SJohn Forte * Input: 2464*fcf3ce44SJohn Forte * ha: adapter state pointer. 2465*fcf3ce44SJohn Forte * pkt: entry pointer. 2466*fcf3ce44SJohn Forte * done_q: done queue pointer. 2467*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2468*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2469*fcf3ce44SJohn Forte * 2470*fcf3ce44SJohn Forte * Context: 2471*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2472*fcf3ce44SJohn Forte */ 2473*fcf3ce44SJohn Forte /* ARGSUSED */ 2474*fcf3ce44SJohn Forte static void 2475*fcf3ce44SJohn Forte ql_immediate_notify_entry(ql_adapter_state_t *ha, 2476*fcf3ce44SJohn Forte immediate_notify_entry_t *pkt, ql_head_t *done_q, uint32_t *set_flags, 2477*fcf3ce44SJohn Forte uint32_t *reset_flags) 2478*fcf3ce44SJohn Forte { 2479*fcf3ce44SJohn Forte notify_acknowledge_entry_t *nack; 2480*fcf3ce44SJohn Forte ql_srb_t *sp; 2481*fcf3ce44SJohn Forte fcp_cmd_t *fcp; 2482*fcf3ce44SJohn Forte tgt_cmd_t *cmd, *nackcmd; 2483*fcf3ce44SJohn Forte ql_tgt_t *tq; 2484*fcf3ce44SJohn Forte fc_unsol_buf_t *ubp = NULL; 2485*fcf3ce44SJohn Forte int use_ubuffer; 2486*fcf3ce44SJohn Forte uint16_t loop_id; 2487*fcf3ce44SJohn Forte 2488*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2489*fcf3ce44SJohn Forte 2490*fcf3ce44SJohn Forte cmd = (tgt_cmd_t *)kmem_zalloc(sizeof (tgt_cmd_t), KM_NOSLEEP); 2491*fcf3ce44SJohn Forte if (cmd != NULL) { 2492*fcf3ce44SJohn Forte cmd->cmd.base_address = cmd; 2493*fcf3ce44SJohn Forte 2494*fcf3ce44SJohn Forte /* Save command context. */ 2495*fcf3ce44SJohn Forte cmd->type = pkt->entry_type; 2496*fcf3ce44SJohn Forte cmd->initiator_id_l = pkt->initiator_id_l; 2497*fcf3ce44SJohn Forte cmd->initiator_id_h = pkt->initiator_id_h; 2498*fcf3ce44SJohn Forte cmd->rx_id = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2499*fcf3ce44SJohn Forte &pkt->sequence_id); 2500*fcf3ce44SJohn Forte cmd->status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2501*fcf3ce44SJohn Forte &pkt->status); 2502*fcf3ce44SJohn Forte cmd->task_flags_l = pkt->task_flags_l; 2503*fcf3ce44SJohn Forte cmd->task_flags_h = pkt->task_flags_h; 2504*fcf3ce44SJohn Forte 2505*fcf3ce44SJohn Forte /* 2506*fcf3ce44SJohn Forte * TODO: flushing in case of pkt_status_l of 0x34 2507*fcf3ce44SJohn Forte * needs to be handled properly. 2508*fcf3ce44SJohn Forte */ 2509*fcf3ce44SJohn Forte 2510*fcf3ce44SJohn Forte EL(ha, "status = %xh\n", cmd->status); 2511*fcf3ce44SJohn Forte 2512*fcf3ce44SJohn Forte /* 2513*fcf3ce44SJohn Forte * For immediate notify situations that need attention, 2514*fcf3ce44SJohn Forte * we attempt to put the command in the array of notify 2515*fcf3ce44SJohn Forte * acknowledge slots for future handling. A LIP RESET 2516*fcf3ce44SJohn Forte * always gets slot 0, since we have to ensure that there's 2517*fcf3ce44SJohn Forte * always a slot available and we can't do any other 2518*fcf3ce44SJohn Forte * processsing if a LIP RESET is pending. 2519*fcf3ce44SJohn Forte * 2520*fcf3ce44SJohn Forte * Otherwise, immediate notifies take the next open slot. 2521*fcf3ce44SJohn Forte */ 2522*fcf3ce44SJohn Forte use_ubuffer = 0; 2523*fcf3ce44SJohn Forte nackcmd = NULL; 2524*fcf3ce44SJohn Forte mutex_enter(&ha->ql_nack_mtx); 2525*fcf3ce44SJohn Forte switch (cmd->status) { 2526*fcf3ce44SJohn Forte case 0x0E: 2527*fcf3ce44SJohn Forte if (ha->ql_nack != NULL) { 2528*fcf3ce44SJohn Forte /* 2529*fcf3ce44SJohn Forte * We're in the sticky situation of receiving 2530*fcf3ce44SJohn Forte * LIP reset while one is pending. What appears 2531*fcf3ce44SJohn Forte * to work is to drop the old request and 2532*fcf3ce44SJohn Forte * replace it with the new. We send a NACK 2533*fcf3ce44SJohn Forte * for the old to replenish the IOCB. 2534*fcf3ce44SJohn Forte */ 2535*fcf3ce44SJohn Forte nackcmd = ha->ql_nack; 2536*fcf3ce44SJohn Forte } 2537*fcf3ce44SJohn Forte ha->ql_nack = cmd; 2538*fcf3ce44SJohn Forte break; 2539*fcf3ce44SJohn Forte case 0x20: 2540*fcf3ce44SJohn Forte case 0x29: 2541*fcf3ce44SJohn Forte case 0x36: 2542*fcf3ce44SJohn Forte /* If this isn't NULL, a LIP RESET is outstanding */ 2543*fcf3ce44SJohn Forte if (ha->ql_nack == NULL) { 2544*fcf3ce44SJohn Forte use_ubuffer++; 2545*fcf3ce44SJohn Forte } 2546*fcf3ce44SJohn Forte break; 2547*fcf3ce44SJohn Forte default: 2548*fcf3ce44SJohn Forte EL(ha, "unknown status=%xh\n", 2549*fcf3ce44SJohn Forte cmd->status); 2550*fcf3ce44SJohn Forte break; 2551*fcf3ce44SJohn Forte } 2552*fcf3ce44SJohn Forte mutex_exit(&ha->ql_nack_mtx); 2553*fcf3ce44SJohn Forte 2554*fcf3ce44SJohn Forte if (use_ubuffer) { 2555*fcf3ce44SJohn Forte /* 2556*fcf3ce44SJohn Forte * Get an unsolicited buffer to send the message up in 2557*fcf3ce44SJohn Forte */ 2558*fcf3ce44SJohn Forte 2559*fcf3ce44SJohn Forte /* Locate a buffer to use. */ 2560*fcf3ce44SJohn Forte loop_id = (uint16_t) 2561*fcf3ce44SJohn Forte (CFG_IST(ha, CFG_EXT_FW_INTERFACE) ? 2562*fcf3ce44SJohn Forte CHAR_TO_SHORT(pkt->initiator_id_l, 2563*fcf3ce44SJohn Forte pkt->initiator_id_h) : pkt->initiator_id_h); 2564*fcf3ce44SJohn Forte if ((tq = ql_loop_id_to_queue(ha, loop_id)) != NULL) { 2565*fcf3ce44SJohn Forte ubp = ql_get_unsolicited_buffer(ha, 2566*fcf3ce44SJohn Forte FC_TYPE_SCSI_FCP); 2567*fcf3ce44SJohn Forte } 2568*fcf3ce44SJohn Forte if (ubp != NULL) { 2569*fcf3ce44SJohn Forte ubp->ub_resp_flags = FC_UB_FCP_CDB_FLAG; 2570*fcf3ce44SJohn Forte ubp->ub_resp_token = tq; 2571*fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 2572*fcf3ce44SJohn Forte 2573*fcf3ce44SJohn Forte fcp = (fcp_cmd_t *)ubp->ub_buffer; 2574*fcf3ce44SJohn Forte 2575*fcf3ce44SJohn Forte /* Set header. */ 2576*fcf3ce44SJohn Forte ubp->ub_frame.d_id = ha->d_id.b24; 2577*fcf3ce44SJohn Forte /* Set 0x06 for R_CTL_COMMAND */ 2578*fcf3ce44SJohn Forte ubp->ub_frame.r_ctl = R_CTL_COMMAND; 2579*fcf3ce44SJohn Forte ubp->ub_frame.s_id = tq->d_id.b24; 2580*fcf3ce44SJohn Forte ubp->ub_frame.rsvd = 0; 2581*fcf3ce44SJohn Forte ubp->ub_frame.f_ctl = F_CTL_FIRST_SEQ | 2582*fcf3ce44SJohn Forte F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 2583*fcf3ce44SJohn Forte ubp->ub_frame.type = FC_TYPE_SCSI_FCP; 2584*fcf3ce44SJohn Forte ubp->ub_frame.seq_cnt = 0; 2585*fcf3ce44SJohn Forte ubp->ub_frame.df_ctl = 0; 2586*fcf3ce44SJohn Forte ubp->ub_frame.seq_id = 0; 2587*fcf3ce44SJohn Forte ubp->ub_frame.rx_id = cmd->rx_id; 2588*fcf3ce44SJohn Forte ubp->ub_frame.ox_id = (uint16_t)ddi_get16( 2589*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->ox_id); 2590*fcf3ce44SJohn Forte ubp->ub_frame.ro = 0; 2591*fcf3ce44SJohn Forte 2592*fcf3ce44SJohn Forte /* Set command in buffer. */ 2593*fcf3ce44SJohn Forte bzero((void *)fcp, sizeof (fcp_cmd_t)); 2594*fcf3ce44SJohn Forte 2595*fcf3ce44SJohn Forte lobyte(fcp->fcp_ent_addr.ent_addr_0) = 2596*fcf3ce44SJohn Forte pkt->lun_l; 2597*fcf3ce44SJohn Forte hibyte(fcp->fcp_ent_addr.ent_addr_0) = 2598*fcf3ce44SJohn Forte pkt->lun_h; 2599*fcf3ce44SJohn Forte 2600*fcf3ce44SJohn Forte switch (cmd->status) { 2601*fcf3ce44SJohn Forte case 0x29: 2602*fcf3ce44SJohn Forte ubp->ub_resp_flags = (uint16_t) 2603*fcf3ce44SJohn Forte (ubp->ub_resp_flags | 2604*fcf3ce44SJohn Forte FC_UB_FCP_PORT_LOGOUT); 2605*fcf3ce44SJohn Forte break; 2606*fcf3ce44SJohn Forte case 0x20: 2607*fcf3ce44SJohn Forte ubp->ub_resp_flags = (uint16_t) 2608*fcf3ce44SJohn Forte (ubp->ub_resp_flags | 2609*fcf3ce44SJohn Forte FC_UB_FCP_ABORT_TASK); 2610*fcf3ce44SJohn Forte break; 2611*fcf3ce44SJohn Forte case 0x36: 2612*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_7) { 2613*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_kill_tsk = 2614*fcf3ce44SJohn Forte 1; 2615*fcf3ce44SJohn Forte } 2616*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_6) { 2617*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_clr_aca = 1; 2618*fcf3ce44SJohn Forte } 2619*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_5) { 2620*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_reset_tgt = 2621*fcf3ce44SJohn Forte 1; 2622*fcf3ce44SJohn Forte } 2623*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_4) { 2624*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_reset_lun = 2625*fcf3ce44SJohn Forte 1; 2626*fcf3ce44SJohn Forte } 2627*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_2) { 2628*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_clr_tsk = 1; 2629*fcf3ce44SJohn Forte } 2630*fcf3ce44SJohn Forte if (pkt->task_flags_h & BIT_1) { 2631*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_abort_tsk = 2632*fcf3ce44SJohn Forte 1; 2633*fcf3ce44SJohn Forte } 2634*fcf3ce44SJohn Forte break; 2635*fcf3ce44SJohn Forte default: 2636*fcf3ce44SJohn Forte EL(ha, "default, no action\n"); 2637*fcf3ce44SJohn Forte break; 2638*fcf3ce44SJohn Forte } 2639*fcf3ce44SJohn Forte 2640*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 2641*fcf3ce44SJohn Forte sp->flags |= SRB_UB_CALLBACK | SRB_UB_FCP; 2642*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 2643*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): Sent Up status = " 2644*fcf3ce44SJohn Forte "%xh\n", ha->instance, cmd->status); 2645*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2646*fcf3ce44SJohn Forte } 2647*fcf3ce44SJohn Forte } 2648*fcf3ce44SJohn Forte 2649*fcf3ce44SJohn Forte if (nackcmd) { 2650*fcf3ce44SJohn Forte if (ql_req_pkt(ha, (request_t **)&nack) == 2651*fcf3ce44SJohn Forte QL_SUCCESS) { 2652*fcf3ce44SJohn Forte 2653*fcf3ce44SJohn Forte ql_notify_acknowledge_iocb(ha, nackcmd, nack); 2654*fcf3ce44SJohn Forte 2655*fcf3ce44SJohn Forte nack->flags_l = 0; 2656*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): send clear " 2657*fcf3ce44SJohn Forte "notify_ack: status=%xh, flag=%xh\n", 2658*fcf3ce44SJohn Forte ha->instance, ddi_get16( 2659*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &nack->status), 2660*fcf3ce44SJohn Forte nack->flags_l); 2661*fcf3ce44SJohn Forte 2662*fcf3ce44SJohn Forte /* Issue command to ISP */ 2663*fcf3ce44SJohn Forte ql_isp_cmd(ha); 2664*fcf3ce44SJohn Forte } 2665*fcf3ce44SJohn Forte kmem_free(nackcmd, sizeof (tgt_cmd_t)); 2666*fcf3ce44SJohn Forte } 2667*fcf3ce44SJohn Forte 2668*fcf3ce44SJohn Forte /* 2669*fcf3ce44SJohn Forte * ql_nack can only be non-NULL if we got a LIP RESET and 2670*fcf3ce44SJohn Forte * are processing it. In that case, we don't want to send 2671*fcf3ce44SJohn Forte * a notify acknowledge right now. 2672*fcf3ce44SJohn Forte */ 2673*fcf3ce44SJohn Forte if (cmd->status != 0x0E) { 2674*fcf3ce44SJohn Forte if (ql_req_pkt(ha, (request_t **)&nack) == 2675*fcf3ce44SJohn Forte QL_SUCCESS) { 2676*fcf3ce44SJohn Forte ql_notify_acknowledge_iocb(ha, cmd, nack); 2677*fcf3ce44SJohn Forte 2678*fcf3ce44SJohn Forte EL(ha, "send notify_ack: status=%xh " 2679*fcf3ce44SJohn Forte "flag=%xh\n", cmd->status, nack->flags_l); 2680*fcf3ce44SJohn Forte 2681*fcf3ce44SJohn Forte /* Issue command to ISP */ 2682*fcf3ce44SJohn Forte ql_isp_cmd(ha); 2683*fcf3ce44SJohn Forte } 2684*fcf3ce44SJohn Forte kmem_free(cmd, sizeof (tgt_cmd_t)); 2685*fcf3ce44SJohn Forte } else { 2686*fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, 2687*fcf3ce44SJohn Forte LIP_RESET_PENDING, 0); 2688*fcf3ce44SJohn Forte } 2689*fcf3ce44SJohn Forte } 2690*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2691*fcf3ce44SJohn Forte } 2692*fcf3ce44SJohn Forte 2693*fcf3ce44SJohn Forte /* 2694*fcf3ce44SJohn Forte * ql_notify_acknowledge_entry 2695*fcf3ce44SJohn Forte * Processes notify acknowledge entry. 2696*fcf3ce44SJohn Forte * 2697*fcf3ce44SJohn Forte * Input: 2698*fcf3ce44SJohn Forte * ha: adapter state pointer. 2699*fcf3ce44SJohn Forte * pkt: entry pointer. 2700*fcf3ce44SJohn Forte * done_q: done queue pointer. 2701*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2702*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2703*fcf3ce44SJohn Forte * 2704*fcf3ce44SJohn Forte * Context: 2705*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2706*fcf3ce44SJohn Forte */ 2707*fcf3ce44SJohn Forte /* ARGSUSED */ 2708*fcf3ce44SJohn Forte static void 2709*fcf3ce44SJohn Forte ql_notify_acknowledge_entry(ql_adapter_state_t *ha, 2710*fcf3ce44SJohn Forte notify_acknowledge_entry_t *pkt, ql_head_t *done_q, uint32_t *set_flags, 2711*fcf3ce44SJohn Forte uint32_t *reset_flags) 2712*fcf3ce44SJohn Forte { 2713*fcf3ce44SJohn Forte ql_srb_t *sp; 2714*fcf3ce44SJohn Forte uint32_t index, cnt; 2715*fcf3ce44SJohn Forte 2716*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2717*fcf3ce44SJohn Forte 2718*fcf3ce44SJohn Forte /* Get handle. */ 2719*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 2720*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 2721*fcf3ce44SJohn Forte 2722*fcf3ce44SJohn Forte /* Validate handle. */ 2723*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 2724*fcf3ce44SJohn Forte NULL; 2725*fcf3ce44SJohn Forte 2726*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 2727*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 2728*fcf3ce44SJohn Forte sp->handle = 0; 2729*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 2730*fcf3ce44SJohn Forte 2731*fcf3ce44SJohn Forte /* Set completion status */ 2732*fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16(ha->hba_buf.acc_handle, 2733*fcf3ce44SJohn Forte &pkt->status) == 1 ? CS_COMPLETE : CS_PORT_UNAVAILABLE; 2734*fcf3ce44SJohn Forte 2735*fcf3ce44SJohn Forte /* Set completed status. */ 2736*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2737*fcf3ce44SJohn Forte 2738*fcf3ce44SJohn Forte /* Place command on done queue. */ 2739*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2740*fcf3ce44SJohn Forte 2741*fcf3ce44SJohn Forte } else if (cnt != QL_FCA_BRAND) { 2742*fcf3ce44SJohn Forte if (sp == NULL) { 2743*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 2744*fcf3ce44SJohn Forte } else { 2745*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 2746*fcf3ce44SJohn Forte cnt, sp->handle); 2747*fcf3ce44SJohn Forte } 2748*fcf3ce44SJohn Forte 2749*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 2750*fcf3ce44SJohn Forte 2751*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 2752*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 2753*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 2754*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 2755*fcf3ce44SJohn Forte } 2756*fcf3ce44SJohn Forte } 2757*fcf3ce44SJohn Forte 2758*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2759*fcf3ce44SJohn Forte } 2760*fcf3ce44SJohn Forte 2761*fcf3ce44SJohn Forte /* 2762*fcf3ce44SJohn Forte * ql_accept_target_io_entry 2763*fcf3ce44SJohn Forte * Processes accept target I/O entry. 2764*fcf3ce44SJohn Forte * 2765*fcf3ce44SJohn Forte * Input: 2766*fcf3ce44SJohn Forte * ha: adapter state pointer. 2767*fcf3ce44SJohn Forte * pkt: entry pointer. 2768*fcf3ce44SJohn Forte * done_q: done queue pointer. 2769*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2770*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2771*fcf3ce44SJohn Forte * 2772*fcf3ce44SJohn Forte * Context: 2773*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2774*fcf3ce44SJohn Forte */ 2775*fcf3ce44SJohn Forte /* ARGSUSED */ 2776*fcf3ce44SJohn Forte static void 2777*fcf3ce44SJohn Forte ql_accept_target_io_entry(ql_adapter_state_t *ha, atio_entry_t *pkt, 2778*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2779*fcf3ce44SJohn Forte { 2780*fcf3ce44SJohn Forte ctio_entry_t *ctio; 2781*fcf3ce44SJohn Forte atio_entry_t *atio; 2782*fcf3ce44SJohn Forte ql_srb_t *sp; 2783*fcf3ce44SJohn Forte fcp_cmd_t *fcp; 2784*fcf3ce44SJohn Forte ql_tgt_t *tq; 2785*fcf3ce44SJohn Forte uint16_t loop_id; 2786*fcf3ce44SJohn Forte fc_unsol_buf_t *ubp = NULL; 2787*fcf3ce44SJohn Forte 2788*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2789*fcf3ce44SJohn Forte 2790*fcf3ce44SJohn Forte /* Locate a buffer to use. */ 2791*fcf3ce44SJohn Forte loop_id = (uint16_t)(CFG_IST(ha, CFG_EXT_FW_INTERFACE) ? 2792*fcf3ce44SJohn Forte CHAR_TO_SHORT(pkt->initiator_id_l, pkt->initiator_id_h) : 2793*fcf3ce44SJohn Forte pkt->initiator_id_h); 2794*fcf3ce44SJohn Forte if ((tq = ql_loop_id_to_queue(ha, loop_id)) != NULL) { 2795*fcf3ce44SJohn Forte ubp = ql_get_unsolicited_buffer(ha, 2796*fcf3ce44SJohn Forte FC_TYPE_SCSI_FCP); 2797*fcf3ce44SJohn Forte } 2798*fcf3ce44SJohn Forte if (ubp != NULL) { 2799*fcf3ce44SJohn Forte ubp->ub_resp_flags = FC_UB_FCP_CDB_FLAG; 2800*fcf3ce44SJohn Forte ubp->ub_resp_token = tq; 2801*fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 2802*fcf3ce44SJohn Forte fcp = (fcp_cmd_t *)ubp->ub_buffer; 2803*fcf3ce44SJohn Forte 2804*fcf3ce44SJohn Forte /* Set header. */ 2805*fcf3ce44SJohn Forte ubp->ub_frame.d_id = ha->d_id.b24; 2806*fcf3ce44SJohn Forte ubp->ub_frame.r_ctl = R_CTL_COMMAND; 2807*fcf3ce44SJohn Forte ubp->ub_frame.s_id = tq->d_id.b24; 2808*fcf3ce44SJohn Forte ubp->ub_frame.rsvd = 0; 2809*fcf3ce44SJohn Forte ubp->ub_frame.f_ctl = F_CTL_FIRST_SEQ | 2810*fcf3ce44SJohn Forte F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE; 2811*fcf3ce44SJohn Forte ubp->ub_frame.type = FC_TYPE_SCSI_FCP; 2812*fcf3ce44SJohn Forte ubp->ub_frame.seq_cnt = 0; 2813*fcf3ce44SJohn Forte ubp->ub_frame.df_ctl = 0; 2814*fcf3ce44SJohn Forte ubp->ub_frame.seq_id = 0; 2815*fcf3ce44SJohn Forte ubp->ub_frame.rx_id = (uint16_t)ddi_get16( 2816*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->rx_id); 2817*fcf3ce44SJohn Forte ubp->ub_frame.ox_id = (uint16_t)ddi_get16( 2818*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->ox_id); 2819*fcf3ce44SJohn Forte ubp->ub_frame.ro = 0; 2820*fcf3ce44SJohn Forte 2821*fcf3ce44SJohn Forte /* Set command in buffer. */ 2822*fcf3ce44SJohn Forte 2823*fcf3ce44SJohn Forte bzero((void *)fcp, sizeof (fcp_cmd_t)); 2824*fcf3ce44SJohn Forte 2825*fcf3ce44SJohn Forte lobyte(fcp->fcp_ent_addr.ent_addr_0) = pkt->lun_l; 2826*fcf3ce44SJohn Forte hibyte(fcp->fcp_ent_addr.ent_addr_0) = pkt->lun_h; 2827*fcf3ce44SJohn Forte 2828*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_qtype = pkt->task_codes; 2829*fcf3ce44SJohn Forte 2830*fcf3ce44SJohn Forte if (pkt->execution_codes & BIT_1) 2831*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_read_data = 1; 2832*fcf3ce44SJohn Forte if (pkt->execution_codes & BIT_0) 2833*fcf3ce44SJohn Forte fcp->fcp_cntl.cntl_write_data = 1; 2834*fcf3ce44SJohn Forte 2835*fcf3ce44SJohn Forte ddi_rep_put8(ha->hba_buf.acc_handle, (uint8_t *)&pkt->cdb[0], 2836*fcf3ce44SJohn Forte (uint8_t *)&fcp->fcp_cdb[0], FCP_CDB_SIZE, 2837*fcf3ce44SJohn Forte DDI_DEV_AUTOINCR); 2838*fcf3ce44SJohn Forte 2839*fcf3ce44SJohn Forte fcp->fcp_data_len = (int)ddi_get32( 2840*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, (uint32_t *)&pkt->data_length); 2841*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 2842*fcf3ce44SJohn Forte sp->flags |= SRB_UB_CALLBACK | SRB_UB_FCP; 2843*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 2844*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2845*fcf3ce44SJohn Forte } 2846*fcf3ce44SJohn Forte 2847*fcf3ce44SJohn Forte /* If command not sent to transport layer. */ 2848*fcf3ce44SJohn Forte if (ubp == NULL) { 2849*fcf3ce44SJohn Forte 2850*fcf3ce44SJohn Forte if (ql_req_pkt(ha, (request_t **)&ctio) == QL_SUCCESS) { 2851*fcf3ce44SJohn Forte ctio->entry_type = CTIO_TYPE_2; 2852*fcf3ce44SJohn Forte ctio->initiator_id_l = pkt->initiator_id_l; 2853*fcf3ce44SJohn Forte ctio->initiator_id_h = pkt->initiator_id_h; 2854*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &ctio->rx_id, 2855*fcf3ce44SJohn Forte (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2856*fcf3ce44SJohn Forte &pkt->rx_id)); 2857*fcf3ce44SJohn Forte ctio->flags_l = BIT_7 | BIT_6; 2858*fcf3ce44SJohn Forte ctio->flags_h = BIT_7 | BIT_1 | BIT_0; 2859*fcf3ce44SJohn Forte ctio->timeout = 0xffff; 2860*fcf3ce44SJohn Forte ctio->type.s0_32bit.scsi_status_l = STATUS_BUSY; 2861*fcf3ce44SJohn Forte 2862*fcf3ce44SJohn Forte /* Issue command to ISP */ 2863*fcf3ce44SJohn Forte ql_isp_cmd(ha); 2864*fcf3ce44SJohn Forte } 2865*fcf3ce44SJohn Forte } else { 2866*fcf3ce44SJohn Forte if (ql_req_pkt(ha, (request_t **)&atio) == QL_SUCCESS) { 2867*fcf3ce44SJohn Forte atio->entry_type = ATIO_TYPE; 2868*fcf3ce44SJohn Forte atio->initiator_id_l = pkt->initiator_id_l; 2869*fcf3ce44SJohn Forte atio->initiator_id_h = pkt->initiator_id_h; 2870*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &atio->rx_id, 2871*fcf3ce44SJohn Forte (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2872*fcf3ce44SJohn Forte &pkt->rx_id)); 2873*fcf3ce44SJohn Forte atio->lun_l = pkt->lun_l; 2874*fcf3ce44SJohn Forte atio->lun_h = pkt->lun_h; 2875*fcf3ce44SJohn Forte 2876*fcf3ce44SJohn Forte /* Issue command to ISP */ 2877*fcf3ce44SJohn Forte ql_isp_cmd(ha); 2878*fcf3ce44SJohn Forte } 2879*fcf3ce44SJohn Forte } 2880*fcf3ce44SJohn Forte 2881*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2882*fcf3ce44SJohn Forte } 2883*fcf3ce44SJohn Forte 2884*fcf3ce44SJohn Forte /* 2885*fcf3ce44SJohn Forte * ql_continue_target_io_entry 2886*fcf3ce44SJohn Forte * Processes continue target IO entry. 2887*fcf3ce44SJohn Forte * 2888*fcf3ce44SJohn Forte * Input: 2889*fcf3ce44SJohn Forte * ha: adapter state pointer. 2890*fcf3ce44SJohn Forte * pkt: entry pointer. 2891*fcf3ce44SJohn Forte * done_q: done queue pointer. 2892*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2893*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2894*fcf3ce44SJohn Forte * 2895*fcf3ce44SJohn Forte * Context: 2896*fcf3ce44SJohn Forte * Interrupt context, no mailbox commands allowed. 2897*fcf3ce44SJohn Forte */ 2898*fcf3ce44SJohn Forte /* ARGSUSED */ 2899*fcf3ce44SJohn Forte static void 2900*fcf3ce44SJohn Forte ql_continue_target_io_entry(ql_adapter_state_t *ha, ctio_entry_t *pkt, 2901*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 2902*fcf3ce44SJohn Forte { 2903*fcf3ce44SJohn Forte ql_srb_t *sp; 2904*fcf3ce44SJohn Forte uint32_t index, cnt; 2905*fcf3ce44SJohn Forte uint16_t status; 2906*fcf3ce44SJohn Forte 2907*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 2908*fcf3ce44SJohn Forte 2909*fcf3ce44SJohn Forte /* Get handle. */ 2910*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt->handle); 2911*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 2912*fcf3ce44SJohn Forte 2913*fcf3ce44SJohn Forte /* Validate handle. */ 2914*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 2915*fcf3ce44SJohn Forte NULL; 2916*fcf3ce44SJohn Forte 2917*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 2918*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 2919*fcf3ce44SJohn Forte sp->handle = 0; 2920*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 2921*fcf3ce44SJohn Forte 2922*fcf3ce44SJohn Forte /* Set completion status */ 2923*fcf3ce44SJohn Forte status = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 2924*fcf3ce44SJohn Forte &pkt->status); 2925*fcf3ce44SJohn Forte 2926*fcf3ce44SJohn Forte switch (status) { 2927*fcf3ce44SJohn Forte case 1: 2928*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 2929*fcf3ce44SJohn Forte break; 2930*fcf3ce44SJohn Forte case 2: 2931*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_ABORTED; 2932*fcf3ce44SJohn Forte break; 2933*fcf3ce44SJohn Forte case 9: 2934*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_DATA_OVERRUN; 2935*fcf3ce44SJohn Forte break; 2936*fcf3ce44SJohn Forte case 0xa: 2937*fcf3ce44SJohn Forte case 0xb: 2938*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_TIMEOUT; 2939*fcf3ce44SJohn Forte break; 2940*fcf3ce44SJohn Forte case 0xe: 2941*fcf3ce44SJohn Forte case 0x17: 2942*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_RESET; 2943*fcf3ce44SJohn Forte break; 2944*fcf3ce44SJohn Forte case 0x10: 2945*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_DMA_ERROR; 2946*fcf3ce44SJohn Forte break; 2947*fcf3ce44SJohn Forte case 0x15: 2948*fcf3ce44SJohn Forte case 0x28: 2949*fcf3ce44SJohn Forte case 0x29: 2950*fcf3ce44SJohn Forte case 0x2A: 2951*fcf3ce44SJohn Forte sp->pkt->pkt_reason = status; 2952*fcf3ce44SJohn Forte break; 2953*fcf3ce44SJohn Forte default: 2954*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_PORT_UNAVAILABLE; 2955*fcf3ce44SJohn Forte break; 2956*fcf3ce44SJohn Forte } 2957*fcf3ce44SJohn Forte 2958*fcf3ce44SJohn Forte /* Set completed status. */ 2959*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 2960*fcf3ce44SJohn Forte 2961*fcf3ce44SJohn Forte /* Place command on done queue. */ 2962*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 2963*fcf3ce44SJohn Forte 2964*fcf3ce44SJohn Forte } else if (cnt != QL_FCA_BRAND) { 2965*fcf3ce44SJohn Forte if (sp == NULL) { 2966*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 2967*fcf3ce44SJohn Forte } else { 2968*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 2969*fcf3ce44SJohn Forte cnt, sp->handle); 2970*fcf3ce44SJohn Forte } 2971*fcf3ce44SJohn Forte 2972*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 2973*fcf3ce44SJohn Forte 2974*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 2975*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 2976*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 2977*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 2978*fcf3ce44SJohn Forte } 2979*fcf3ce44SJohn Forte } 2980*fcf3ce44SJohn Forte 2981*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 2982*fcf3ce44SJohn Forte } 2983*fcf3ce44SJohn Forte 2984*fcf3ce44SJohn Forte /* 2985*fcf3ce44SJohn Forte * ql_ip_entry 2986*fcf3ce44SJohn Forte * Processes received ISP IP entry. 2987*fcf3ce44SJohn Forte * 2988*fcf3ce44SJohn Forte * Input: 2989*fcf3ce44SJohn Forte * ha: adapter state pointer. 2990*fcf3ce44SJohn Forte * pkt: entry pointer. 2991*fcf3ce44SJohn Forte * done_q: done queue pointer. 2992*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 2993*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 2994*fcf3ce44SJohn Forte * 2995*fcf3ce44SJohn Forte * Context: 2996*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 2997*fcf3ce44SJohn Forte */ 2998*fcf3ce44SJohn Forte /* ARGSUSED */ 2999*fcf3ce44SJohn Forte static void 3000*fcf3ce44SJohn Forte ql_ip_entry(ql_adapter_state_t *ha, ip_entry_t *pkt23, ql_head_t *done_q, 3001*fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 3002*fcf3ce44SJohn Forte { 3003*fcf3ce44SJohn Forte ql_srb_t *sp; 3004*fcf3ce44SJohn Forte uint32_t index, cnt; 3005*fcf3ce44SJohn Forte ql_tgt_t *tq; 3006*fcf3ce44SJohn Forte 3007*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3008*fcf3ce44SJohn Forte 3009*fcf3ce44SJohn Forte /* Get handle. */ 3010*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle); 3011*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 3012*fcf3ce44SJohn Forte 3013*fcf3ce44SJohn Forte /* Validate handle. */ 3014*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 3015*fcf3ce44SJohn Forte NULL; 3016*fcf3ce44SJohn Forte 3017*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 3018*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 3019*fcf3ce44SJohn Forte sp->handle = 0; 3020*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 3021*fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 3022*fcf3ce44SJohn Forte 3023*fcf3ce44SJohn Forte /* Set ISP completion status */ 3024*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 3025*fcf3ce44SJohn Forte ip_cmd_entry_t *pkt24 = (ip_cmd_entry_t *)pkt23; 3026*fcf3ce44SJohn Forte 3027*fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3028*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt24->hdl_status); 3029*fcf3ce44SJohn Forte } else { 3030*fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3031*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 3032*fcf3ce44SJohn Forte } 3033*fcf3ce44SJohn Forte 3034*fcf3ce44SJohn Forte if (ha->task_daemon_flags & LOOP_DOWN) { 3035*fcf3ce44SJohn Forte EL(ha, "Loop Not Ready Retry, d_id=%xh\n", 3036*fcf3ce44SJohn Forte tq->d_id.b24); 3037*fcf3ce44SJohn Forte 3038*fcf3ce44SJohn Forte /* Set retry status. */ 3039*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3040*fcf3ce44SJohn Forte 3041*fcf3ce44SJohn Forte } else if (tq->port_down_retry_count && 3042*fcf3ce44SJohn Forte (sp->pkt->pkt_reason == CS_INCOMPLETE || 3043*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE || 3044*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT || 3045*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG || 3046*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_BUSY)) { 3047*fcf3ce44SJohn Forte EL(ha, "Port Down Retry=%xh, d_id=%xh, count=%d\n", 3048*fcf3ce44SJohn Forte sp->pkt->pkt_reason, tq->d_id.b24, 3049*fcf3ce44SJohn Forte tq->port_down_retry_count); 3050*fcf3ce44SJohn Forte 3051*fcf3ce44SJohn Forte /* Set retry status. */ 3052*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3053*fcf3ce44SJohn Forte 3054*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_PORT_LOGGED_OUT || 3055*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_UNAVAILABLE) { 3056*fcf3ce44SJohn Forte ha->adapter_stats->d_stats[lobyte( 3057*fcf3ce44SJohn Forte tq->loop_id)].logouts_recvd++; 3058*fcf3ce44SJohn Forte ql_send_logo(ha, tq, done_q); 3059*fcf3ce44SJohn Forte } 3060*fcf3ce44SJohn Forte 3061*fcf3ce44SJohn Forte /* Acquire device queue lock. */ 3062*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3063*fcf3ce44SJohn Forte 3064*fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 3065*fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 3066*fcf3ce44SJohn Forte 3067*fcf3ce44SJohn Forte tq->port_down_retry_count--; 3068*fcf3ce44SJohn Forte 3069*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3070*fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 3071*fcf3ce44SJohn Forte if ((ha->port_retry_timer = 3072*fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 3073*fcf3ce44SJohn Forte *set_flags |= 3074*fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 3075*fcf3ce44SJohn Forte } 3076*fcf3ce44SJohn Forte } 3077*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3078*fcf3ce44SJohn Forte } 3079*fcf3ce44SJohn Forte 3080*fcf3ce44SJohn Forte /* Release device queue specific lock. */ 3081*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3082*fcf3ce44SJohn Forte 3083*fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason == CS_RESET) { 3084*fcf3ce44SJohn Forte EL(ha, "Reset Retry, d_id=%xh\n", tq->d_id.b24); 3085*fcf3ce44SJohn Forte 3086*fcf3ce44SJohn Forte /* Set retry status. */ 3087*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3088*fcf3ce44SJohn Forte } else { 3089*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason != CS_COMPLETE) { 3090*fcf3ce44SJohn Forte EL(ha, "Cmplt status err=%xh, d_id=%xh\n", 3091*fcf3ce44SJohn Forte sp->pkt->pkt_reason, tq->d_id.b24); 3092*fcf3ce44SJohn Forte } 3093*fcf3ce44SJohn Forte } 3094*fcf3ce44SJohn Forte 3095*fcf3ce44SJohn Forte /* Set completed status. */ 3096*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 3097*fcf3ce44SJohn Forte 3098*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 3099*fcf3ce44SJohn Forte 3100*fcf3ce44SJohn Forte } else { 3101*fcf3ce44SJohn Forte if (sp == NULL) { 3102*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 3103*fcf3ce44SJohn Forte } else { 3104*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 3105*fcf3ce44SJohn Forte cnt, sp->handle); 3106*fcf3ce44SJohn Forte } 3107*fcf3ce44SJohn Forte 3108*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 3109*fcf3ce44SJohn Forte 3110*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 3111*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 3112*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 3113*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3114*fcf3ce44SJohn Forte } 3115*fcf3ce44SJohn Forte } 3116*fcf3ce44SJohn Forte 3117*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3118*fcf3ce44SJohn Forte } 3119*fcf3ce44SJohn Forte 3120*fcf3ce44SJohn Forte /* 3121*fcf3ce44SJohn Forte * ql_ip_rcv_entry 3122*fcf3ce44SJohn Forte * Processes received ISP IP buffers entry. 3123*fcf3ce44SJohn Forte * 3124*fcf3ce44SJohn Forte * Input: 3125*fcf3ce44SJohn Forte * ha: adapter state pointer. 3126*fcf3ce44SJohn Forte * pkt: entry pointer. 3127*fcf3ce44SJohn Forte * done_q: done queue pointer. 3128*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3129*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3130*fcf3ce44SJohn Forte * 3131*fcf3ce44SJohn Forte * Context: 3132*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3133*fcf3ce44SJohn Forte */ 3134*fcf3ce44SJohn Forte /* ARGSUSED */ 3135*fcf3ce44SJohn Forte static void 3136*fcf3ce44SJohn Forte ql_ip_rcv_entry(ql_adapter_state_t *ha, ip_rcv_entry_t *pkt, 3137*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 3138*fcf3ce44SJohn Forte { 3139*fcf3ce44SJohn Forte port_id_t s_id; 3140*fcf3ce44SJohn Forte uint16_t index; 3141*fcf3ce44SJohn Forte uint8_t cnt; 3142*fcf3ce44SJohn Forte ql_tgt_t *tq; 3143*fcf3ce44SJohn Forte 3144*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3145*fcf3ce44SJohn Forte 3146*fcf3ce44SJohn Forte /* Locate device queue. */ 3147*fcf3ce44SJohn Forte s_id.b.al_pa = pkt->s_id[0]; 3148*fcf3ce44SJohn Forte s_id.b.area = pkt->s_id[1]; 3149*fcf3ce44SJohn Forte s_id.b.domain = pkt->s_id[2]; 3150*fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 3151*fcf3ce44SJohn Forte EL(ha, "Unknown IP device ID=%xh\n", s_id.b24); 3152*fcf3ce44SJohn Forte return; 3153*fcf3ce44SJohn Forte } 3154*fcf3ce44SJohn Forte 3155*fcf3ce44SJohn Forte tq->ub_sequence_length = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 3156*fcf3ce44SJohn Forte &pkt->seq_length); 3157*fcf3ce44SJohn Forte tq->ub_total_seg_cnt = pkt->segment_count; 3158*fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 3159*fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 3160*fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 3161*fcf3ce44SJohn Forte tq->ub_loop_id = pkt->loop_id; 3162*fcf3ce44SJohn Forte ha->rcv_dev_q = tq; 3163*fcf3ce44SJohn Forte 3164*fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_RCVBUF_HANDLES && tq->ub_seq_cnt < 3165*fcf3ce44SJohn Forte tq->ub_total_seg_cnt; cnt++) { 3166*fcf3ce44SJohn Forte 3167*fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 3168*fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 3169*fcf3ce44SJohn Forte 3170*fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 3171*fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 3172*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3173*fcf3ce44SJohn Forte break; 3174*fcf3ce44SJohn Forte } 3175*fcf3ce44SJohn Forte } 3176*fcf3ce44SJohn Forte 3177*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3178*fcf3ce44SJohn Forte } 3179*fcf3ce44SJohn Forte 3180*fcf3ce44SJohn Forte /* 3181*fcf3ce44SJohn Forte * ql_ip_rcv_cont_entry 3182*fcf3ce44SJohn Forte * Processes received ISP IP buffers continuation entry. 3183*fcf3ce44SJohn Forte * 3184*fcf3ce44SJohn Forte * Input: 3185*fcf3ce44SJohn Forte * ha: adapter state pointer. 3186*fcf3ce44SJohn Forte * pkt: entry pointer. 3187*fcf3ce44SJohn Forte * done_q: done queue pointer. 3188*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3189*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3190*fcf3ce44SJohn Forte * 3191*fcf3ce44SJohn Forte * Context: 3192*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3193*fcf3ce44SJohn Forte */ 3194*fcf3ce44SJohn Forte /* ARGSUSED */ 3195*fcf3ce44SJohn Forte static void 3196*fcf3ce44SJohn Forte ql_ip_rcv_cont_entry(ql_adapter_state_t *ha, ip_rcv_cont_entry_t *pkt, 3197*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 3198*fcf3ce44SJohn Forte { 3199*fcf3ce44SJohn Forte uint16_t index; 3200*fcf3ce44SJohn Forte uint8_t cnt; 3201*fcf3ce44SJohn Forte ql_tgt_t *tq; 3202*fcf3ce44SJohn Forte 3203*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3204*fcf3ce44SJohn Forte 3205*fcf3ce44SJohn Forte if ((tq = ha->rcv_dev_q) == NULL) { 3206*fcf3ce44SJohn Forte EL(ha, "No IP receive device\n"); 3207*fcf3ce44SJohn Forte return; 3208*fcf3ce44SJohn Forte } 3209*fcf3ce44SJohn Forte 3210*fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_RCVBUF_CONT_HANDLES && 3211*fcf3ce44SJohn Forte tq->ub_seq_cnt < tq->ub_total_seg_cnt; cnt++) { 3212*fcf3ce44SJohn Forte 3213*fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 3214*fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 3215*fcf3ce44SJohn Forte 3216*fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 3217*fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 3218*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3219*fcf3ce44SJohn Forte break; 3220*fcf3ce44SJohn Forte } 3221*fcf3ce44SJohn Forte } 3222*fcf3ce44SJohn Forte 3223*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3224*fcf3ce44SJohn Forte } 3225*fcf3ce44SJohn Forte 3226*fcf3ce44SJohn Forte /* 3227*fcf3ce44SJohn Forte * ip_rcv_24xx_entry_t 3228*fcf3ce44SJohn Forte * Processes received ISP24xx IP buffers entry. 3229*fcf3ce44SJohn Forte * 3230*fcf3ce44SJohn Forte * Input: 3231*fcf3ce44SJohn Forte * ha: adapter state pointer. 3232*fcf3ce44SJohn Forte * pkt: entry pointer. 3233*fcf3ce44SJohn Forte * done_q: done queue pointer. 3234*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3235*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3236*fcf3ce44SJohn Forte * 3237*fcf3ce44SJohn Forte * Context: 3238*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3239*fcf3ce44SJohn Forte */ 3240*fcf3ce44SJohn Forte /* ARGSUSED */ 3241*fcf3ce44SJohn Forte static void 3242*fcf3ce44SJohn Forte ql_ip_24xx_rcv_entry(ql_adapter_state_t *ha, ip_rcv_24xx_entry_t *pkt, 3243*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 3244*fcf3ce44SJohn Forte { 3245*fcf3ce44SJohn Forte port_id_t s_id; 3246*fcf3ce44SJohn Forte uint16_t index; 3247*fcf3ce44SJohn Forte uint8_t cnt; 3248*fcf3ce44SJohn Forte ql_tgt_t *tq; 3249*fcf3ce44SJohn Forte 3250*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3251*fcf3ce44SJohn Forte 3252*fcf3ce44SJohn Forte /* Locate device queue. */ 3253*fcf3ce44SJohn Forte s_id.b.al_pa = pkt->s_id[0]; 3254*fcf3ce44SJohn Forte s_id.b.area = pkt->s_id[1]; 3255*fcf3ce44SJohn Forte s_id.b.domain = pkt->s_id[2]; 3256*fcf3ce44SJohn Forte if ((tq = ql_d_id_to_queue(ha, s_id)) == NULL) { 3257*fcf3ce44SJohn Forte EL(ha, "Unknown IP device ID=%xh\n", s_id.b24); 3258*fcf3ce44SJohn Forte return; 3259*fcf3ce44SJohn Forte } 3260*fcf3ce44SJohn Forte 3261*fcf3ce44SJohn Forte if (tq->ub_total_seg_cnt == 0) { 3262*fcf3ce44SJohn Forte tq->ub_sequence_length = (uint16_t)ddi_get16( 3263*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->seq_length); 3264*fcf3ce44SJohn Forte tq->ub_total_seg_cnt = pkt->segment_count; 3265*fcf3ce44SJohn Forte tq->ub_seq_id = ++ha->ub_seq_id; 3266*fcf3ce44SJohn Forte tq->ub_seq_cnt = 0; 3267*fcf3ce44SJohn Forte tq->ub_frame_ro = 0; 3268*fcf3ce44SJohn Forte tq->ub_loop_id = (uint16_t)ddi_get16( 3269*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt->n_port_hdl); 3270*fcf3ce44SJohn Forte } 3271*fcf3ce44SJohn Forte 3272*fcf3ce44SJohn Forte for (cnt = 0; cnt < IP_24XX_RCVBUF_HANDLES && tq->ub_seq_cnt < 3273*fcf3ce44SJohn Forte tq->ub_total_seg_cnt; cnt++) { 3274*fcf3ce44SJohn Forte 3275*fcf3ce44SJohn Forte index = (uint16_t)ddi_get16(ha->hba_buf.acc_handle, 3276*fcf3ce44SJohn Forte &pkt->buffer_handle[cnt]); 3277*fcf3ce44SJohn Forte 3278*fcf3ce44SJohn Forte if (ql_ub_frame_hdr(ha, tq, index, done_q) != QL_SUCCESS) { 3279*fcf3ce44SJohn Forte EL(ha, "ql_ub_frame_hdr failed, isp_abort_needed\n"); 3280*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3281*fcf3ce44SJohn Forte break; 3282*fcf3ce44SJohn Forte } 3283*fcf3ce44SJohn Forte } 3284*fcf3ce44SJohn Forte 3285*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3286*fcf3ce44SJohn Forte } 3287*fcf3ce44SJohn Forte 3288*fcf3ce44SJohn Forte /* 3289*fcf3ce44SJohn Forte * ql_ms_entry 3290*fcf3ce44SJohn Forte * Processes received Name/Management/CT Pass-Through entry. 3291*fcf3ce44SJohn Forte * 3292*fcf3ce44SJohn Forte * Input: 3293*fcf3ce44SJohn Forte * ha: adapter state pointer. 3294*fcf3ce44SJohn Forte * pkt23: entry pointer. 3295*fcf3ce44SJohn Forte * done_q: done queue pointer. 3296*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3297*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3298*fcf3ce44SJohn Forte * 3299*fcf3ce44SJohn Forte * Context: 3300*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3301*fcf3ce44SJohn Forte */ 3302*fcf3ce44SJohn Forte /* ARGSUSED */ 3303*fcf3ce44SJohn Forte static void 3304*fcf3ce44SJohn Forte ql_ms_entry(ql_adapter_state_t *ha, ms_entry_t *pkt23, ql_head_t *done_q, 3305*fcf3ce44SJohn Forte uint32_t *set_flags, uint32_t *reset_flags) 3306*fcf3ce44SJohn Forte { 3307*fcf3ce44SJohn Forte ql_srb_t *sp; 3308*fcf3ce44SJohn Forte uint32_t index, cnt; 3309*fcf3ce44SJohn Forte ql_tgt_t *tq; 3310*fcf3ce44SJohn Forte ct_passthru_entry_t *pkt24 = (ct_passthru_entry_t *)pkt23; 3311*fcf3ce44SJohn Forte 3312*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3313*fcf3ce44SJohn Forte 3314*fcf3ce44SJohn Forte /* Get handle. */ 3315*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, &pkt23->handle); 3316*fcf3ce44SJohn Forte index = cnt & OSC_INDEX_MASK; 3317*fcf3ce44SJohn Forte 3318*fcf3ce44SJohn Forte /* Validate handle. */ 3319*fcf3ce44SJohn Forte sp = index < MAX_OUTSTANDING_COMMANDS ? ha->outstanding_cmds[index] : 3320*fcf3ce44SJohn Forte NULL; 3321*fcf3ce44SJohn Forte 3322*fcf3ce44SJohn Forte if (sp != NULL && sp->handle == cnt) { 3323*fcf3ce44SJohn Forte if (!(sp->flags & SRB_MS_PKT)) { 3324*fcf3ce44SJohn Forte EL(ha, "Not SRB_MS_PKT flags=%xh, isp_abort_needed", 3325*fcf3ce44SJohn Forte sp->flags); 3326*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3327*fcf3ce44SJohn Forte return; 3328*fcf3ce44SJohn Forte } 3329*fcf3ce44SJohn Forte 3330*fcf3ce44SJohn Forte ha->outstanding_cmds[index] = NULL; 3331*fcf3ce44SJohn Forte sp->handle = 0; 3332*fcf3ce44SJohn Forte sp->flags &= ~SRB_IN_TOKEN_ARRAY; 3333*fcf3ce44SJohn Forte tq = sp->lun_queue->target_queue; 3334*fcf3ce44SJohn Forte 3335*fcf3ce44SJohn Forte /* Set ISP completion status */ 3336*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 3337*fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3338*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt24->status); 3339*fcf3ce44SJohn Forte } else { 3340*fcf3ce44SJohn Forte sp->pkt->pkt_reason = ddi_get16( 3341*fcf3ce44SJohn Forte ha->hba_buf.acc_handle, &pkt23->comp_status); 3342*fcf3ce44SJohn Forte } 3343*fcf3ce44SJohn Forte 3344*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_RESOUCE_UNAVAILABLE && 3345*fcf3ce44SJohn Forte sp->retry_count) { 3346*fcf3ce44SJohn Forte EL(ha, "Resouce Unavailable Retry = %d\n", 3347*fcf3ce44SJohn Forte sp->retry_count); 3348*fcf3ce44SJohn Forte 3349*fcf3ce44SJohn Forte /* Set retry status. */ 3350*fcf3ce44SJohn Forte sp->retry_count--; 3351*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3352*fcf3ce44SJohn Forte 3353*fcf3ce44SJohn Forte /* Acquire device queue lock. */ 3354*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3355*fcf3ce44SJohn Forte 3356*fcf3ce44SJohn Forte if (!(tq->flags & TQF_QUEUE_SUSPENDED)) { 3357*fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 3358*fcf3ce44SJohn Forte 3359*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3360*fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 3361*fcf3ce44SJohn Forte ha->port_retry_timer = 2; 3362*fcf3ce44SJohn Forte } 3363*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3364*fcf3ce44SJohn Forte } 3365*fcf3ce44SJohn Forte 3366*fcf3ce44SJohn Forte /* Release device queue specific lock. */ 3367*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3368*fcf3ce44SJohn Forte 3369*fcf3ce44SJohn Forte } else if (tq->port_down_retry_count && 3370*fcf3ce44SJohn Forte (sp->pkt->pkt_reason == CS_PORT_CONFIG_CHG || 3371*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_PORT_BUSY)) { 3372*fcf3ce44SJohn Forte EL(ha, "Port Down Retry\n"); 3373*fcf3ce44SJohn Forte 3374*fcf3ce44SJohn Forte /* Set retry status. */ 3375*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3376*fcf3ce44SJohn Forte 3377*fcf3ce44SJohn Forte /* Acquire device queue lock. */ 3378*fcf3ce44SJohn Forte DEVICE_QUEUE_LOCK(tq); 3379*fcf3ce44SJohn Forte 3380*fcf3ce44SJohn Forte if ((tq->flags & TQF_QUEUE_SUSPENDED) == 0) { 3381*fcf3ce44SJohn Forte tq->flags |= TQF_QUEUE_SUSPENDED; 3382*fcf3ce44SJohn Forte 3383*fcf3ce44SJohn Forte tq->port_down_retry_count--; 3384*fcf3ce44SJohn Forte 3385*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 3386*fcf3ce44SJohn Forte if (ha->port_retry_timer == 0) { 3387*fcf3ce44SJohn Forte if ((ha->port_retry_timer = 3388*fcf3ce44SJohn Forte ha->port_down_retry_delay) == 0) { 3389*fcf3ce44SJohn Forte *set_flags |= 3390*fcf3ce44SJohn Forte PORT_RETRY_NEEDED; 3391*fcf3ce44SJohn Forte } 3392*fcf3ce44SJohn Forte } 3393*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 3394*fcf3ce44SJohn Forte } 3395*fcf3ce44SJohn Forte 3396*fcf3ce44SJohn Forte /* Release device queue specific lock. */ 3397*fcf3ce44SJohn Forte DEVICE_QUEUE_UNLOCK(tq); 3398*fcf3ce44SJohn Forte 3399*fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason == CS_RESET) { 3400*fcf3ce44SJohn Forte EL(ha, "Reset Retry\n"); 3401*fcf3ce44SJohn Forte 3402*fcf3ce44SJohn Forte /* Set retry status. */ 3403*fcf3ce44SJohn Forte sp->flags |= SRB_RETRY; 3404*fcf3ce44SJohn Forte 3405*fcf3ce44SJohn Forte } else if (CFG_IST(ha, CFG_CTRL_2425) && 3406*fcf3ce44SJohn Forte sp->pkt->pkt_reason == CS_DATA_UNDERRUN) { 3407*fcf3ce44SJohn Forte cnt = ddi_get32(ha->hba_buf.acc_handle, 3408*fcf3ce44SJohn Forte &pkt24->resp_byte_count); 3409*fcf3ce44SJohn Forte if (cnt < sizeof (fc_ct_header_t)) { 3410*fcf3ce44SJohn Forte EL(ha, "Data underrrun\n"); 3411*fcf3ce44SJohn Forte } else { 3412*fcf3ce44SJohn Forte sp->pkt->pkt_reason = CS_COMPLETE; 3413*fcf3ce44SJohn Forte } 3414*fcf3ce44SJohn Forte 3415*fcf3ce44SJohn Forte } else if (sp->pkt->pkt_reason != CS_COMPLETE) { 3416*fcf3ce44SJohn Forte EL(ha, "status err=%xh\n", sp->pkt->pkt_reason); 3417*fcf3ce44SJohn Forte } 3418*fcf3ce44SJohn Forte 3419*fcf3ce44SJohn Forte if (sp->pkt->pkt_reason == CS_COMPLETE) { 3420*fcf3ce44SJohn Forte /*EMPTY*/ 3421*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): resp\n", ha->instance); 3422*fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_resp, 8, sp->pkt->pkt_rsplen); 3423*fcf3ce44SJohn Forte } 3424*fcf3ce44SJohn Forte 3425*fcf3ce44SJohn Forte /* For nameserver restore command, management change header. */ 3426*fcf3ce44SJohn Forte if ((sp->flags & SRB_RETRY) == 0) { 3427*fcf3ce44SJohn Forte tq->d_id.b24 == 0xfffffc ? 3428*fcf3ce44SJohn Forte ql_cthdr_endian(sp->pkt->pkt_cmd_acc, 3429*fcf3ce44SJohn Forte sp->pkt->pkt_cmd, B_TRUE) : 3430*fcf3ce44SJohn Forte ql_cthdr_endian(sp->pkt->pkt_resp_acc, 3431*fcf3ce44SJohn Forte sp->pkt->pkt_resp, B_TRUE); 3432*fcf3ce44SJohn Forte } 3433*fcf3ce44SJohn Forte 3434*fcf3ce44SJohn Forte /* Set completed status. */ 3435*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_COMPLETED; 3436*fcf3ce44SJohn Forte 3437*fcf3ce44SJohn Forte /* Place command on done queue. */ 3438*fcf3ce44SJohn Forte ql_add_link_b(done_q, &sp->cmd); 3439*fcf3ce44SJohn Forte 3440*fcf3ce44SJohn Forte } else { 3441*fcf3ce44SJohn Forte if (sp == NULL) { 3442*fcf3ce44SJohn Forte EL(ha, "unknown IOCB handle=%xh\n", cnt); 3443*fcf3ce44SJohn Forte } else { 3444*fcf3ce44SJohn Forte EL(ha, "mismatch IOCB handle pkt=%xh, sp=%xh\n", 3445*fcf3ce44SJohn Forte cnt, sp->handle); 3446*fcf3ce44SJohn Forte } 3447*fcf3ce44SJohn Forte 3448*fcf3ce44SJohn Forte (void) ql_binary_fw_dump(ha, FALSE); 3449*fcf3ce44SJohn Forte 3450*fcf3ce44SJohn Forte if (!(ha->task_daemon_flags & (ISP_ABORT_NEEDED | 3451*fcf3ce44SJohn Forte ABORT_ISP_ACTIVE))) { 3452*fcf3ce44SJohn Forte EL(ha, "ISP Invalid handle, isp_abort_needed\n"); 3453*fcf3ce44SJohn Forte *set_flags |= ISP_ABORT_NEEDED; 3454*fcf3ce44SJohn Forte } 3455*fcf3ce44SJohn Forte } 3456*fcf3ce44SJohn Forte 3457*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3458*fcf3ce44SJohn Forte } 3459*fcf3ce44SJohn Forte 3460*fcf3ce44SJohn Forte /* 3461*fcf3ce44SJohn Forte * ql_report_id_entry 3462*fcf3ce44SJohn Forte * Processes received Name/Management/CT Pass-Through entry. 3463*fcf3ce44SJohn Forte * 3464*fcf3ce44SJohn Forte * Input: 3465*fcf3ce44SJohn Forte * ha: adapter state pointer. 3466*fcf3ce44SJohn Forte * pkt23: entry pointer. 3467*fcf3ce44SJohn Forte * done_q: done queue pointer. 3468*fcf3ce44SJohn Forte * set_flags: task daemon flags to set. 3469*fcf3ce44SJohn Forte * reset_flags: task daemon flags to reset. 3470*fcf3ce44SJohn Forte * 3471*fcf3ce44SJohn Forte * Context: 3472*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 3473*fcf3ce44SJohn Forte */ 3474*fcf3ce44SJohn Forte /* ARGSUSED */ 3475*fcf3ce44SJohn Forte static void 3476*fcf3ce44SJohn Forte ql_report_id_entry(ql_adapter_state_t *ha, report_id_1_t *pkt, 3477*fcf3ce44SJohn Forte ql_head_t *done_q, uint32_t *set_flags, uint32_t *reset_flags) 3478*fcf3ce44SJohn Forte { 3479*fcf3ce44SJohn Forte ql_adapter_state_t *vha; 3480*fcf3ce44SJohn Forte 3481*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 3482*fcf3ce44SJohn Forte 3483*fcf3ce44SJohn Forte EL(ha, "format=%d, vp=%d, status=%d\n", 3484*fcf3ce44SJohn Forte pkt->format, pkt->vp_index, pkt->status); 3485*fcf3ce44SJohn Forte 3486*fcf3ce44SJohn Forte if (pkt->format == 1) { 3487*fcf3ce44SJohn Forte /* Locate port state structure. */ 3488*fcf3ce44SJohn Forte for (vha = ha; vha != NULL; vha = vha->vp_next) { 3489*fcf3ce44SJohn Forte if (vha->vp_index == pkt->vp_index) { 3490*fcf3ce44SJohn Forte break; 3491*fcf3ce44SJohn Forte } 3492*fcf3ce44SJohn Forte } 3493*fcf3ce44SJohn Forte if (vha != NULL && (pkt->status == CS_COMPLETE || 3494*fcf3ce44SJohn Forte pkt->status == CS_PORT_ID_CHANGE)) { 3495*fcf3ce44SJohn Forte *set_flags |= LOOP_RESYNC_NEEDED; 3496*fcf3ce44SJohn Forte *reset_flags &= ~LOOP_RESYNC_NEEDED; 3497*fcf3ce44SJohn Forte vha->loop_down_timer = LOOP_DOWN_TIMER_OFF; 3498*fcf3ce44SJohn Forte TASK_DAEMON_LOCK(ha); 3499*fcf3ce44SJohn Forte vha->task_daemon_flags |= LOOP_RESYNC_NEEDED; 3500*fcf3ce44SJohn Forte vha->task_daemon_flags &= ~LOOP_DOWN; 3501*fcf3ce44SJohn Forte TASK_DAEMON_UNLOCK(ha); 3502*fcf3ce44SJohn Forte } 3503*fcf3ce44SJohn Forte } 3504*fcf3ce44SJohn Forte 3505*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 3506*fcf3ce44SJohn Forte } 3507