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