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