1*fcf3ce44SJohn Forte /* 2*fcf3ce44SJohn Forte * CDDL HEADER START 3*fcf3ce44SJohn Forte * 4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7*fcf3ce44SJohn Forte * 8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11*fcf3ce44SJohn Forte * and limitations under the License. 12*fcf3ce44SJohn Forte * 13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18*fcf3ce44SJohn Forte * 19*fcf3ce44SJohn Forte * CDDL HEADER END 20*fcf3ce44SJohn Forte */ 21*fcf3ce44SJohn Forte 22*fcf3ce44SJohn Forte /* Copyright 2008 QLogic Corporation */ 23*fcf3ce44SJohn Forte 24*fcf3ce44SJohn Forte /* 25*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26*fcf3ce44SJohn Forte * Use is subject to license terms. 27*fcf3ce44SJohn Forte */ 28*fcf3ce44SJohn Forte 29*fcf3ce44SJohn Forte #pragma ident "Copyright 2008 QLogic Corporation; ql_iocb.c" 30*fcf3ce44SJohn Forte 31*fcf3ce44SJohn Forte /* 32*fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 33*fcf3ce44SJohn Forte * 34*fcf3ce44SJohn Forte * *********************************************************************** 35*fcf3ce44SJohn Forte * * ** 36*fcf3ce44SJohn Forte * * NOTICE ** 37*fcf3ce44SJohn Forte * * COPYRIGHT (C) 1996-2008 QLOGIC CORPORATION ** 38*fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 39*fcf3ce44SJohn Forte * * ** 40*fcf3ce44SJohn Forte * *********************************************************************** 41*fcf3ce44SJohn Forte * 42*fcf3ce44SJohn Forte */ 43*fcf3ce44SJohn Forte 44*fcf3ce44SJohn Forte #include <ql_apps.h> 45*fcf3ce44SJohn Forte #include <ql_api.h> 46*fcf3ce44SJohn Forte #include <ql_debug.h> 47*fcf3ce44SJohn Forte #include <ql_iocb.h> 48*fcf3ce44SJohn Forte #include <ql_isr.h> 49*fcf3ce44SJohn Forte #include <ql_xioctl.h> 50*fcf3ce44SJohn Forte 51*fcf3ce44SJohn Forte /* 52*fcf3ce44SJohn Forte * Local Function Prototypes. 53*fcf3ce44SJohn Forte */ 54*fcf3ce44SJohn Forte static void ql_continuation_iocb(ql_adapter_state_t *, ddi_dma_cookie_t *, 55*fcf3ce44SJohn Forte uint16_t, boolean_t); 56*fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *); 57*fcf3ce44SJohn Forte 58*fcf3ce44SJohn Forte /* 59*fcf3ce44SJohn Forte * ql_start_iocb 60*fcf3ce44SJohn Forte * The start IOCB is responsible for building request packets 61*fcf3ce44SJohn Forte * on request ring and modifying ISP input pointer. 62*fcf3ce44SJohn Forte * 63*fcf3ce44SJohn Forte * Input: 64*fcf3ce44SJohn Forte * ha: adapter state pointer. 65*fcf3ce44SJohn Forte * sp: srb structure pointer. 66*fcf3ce44SJohn Forte * 67*fcf3ce44SJohn Forte * Context: 68*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 69*fcf3ce44SJohn Forte */ 70*fcf3ce44SJohn Forte void 71*fcf3ce44SJohn Forte ql_start_iocb(ql_adapter_state_t *vha, ql_srb_t *sp) 72*fcf3ce44SJohn Forte { 73*fcf3ce44SJohn Forte ql_link_t *link; 74*fcf3ce44SJohn Forte request_t *pkt; 75*fcf3ce44SJohn Forte uint64_t *ptr64; 76*fcf3ce44SJohn Forte uint32_t cnt; 77*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 78*fcf3ce44SJohn Forte 79*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 80*fcf3ce44SJohn Forte 81*fcf3ce44SJohn Forte /* Acquire ring lock. */ 82*fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 83*fcf3ce44SJohn Forte 84*fcf3ce44SJohn Forte if (sp != NULL) { 85*fcf3ce44SJohn Forte /* 86*fcf3ce44SJohn Forte * Start any pending ones before this one. 87*fcf3ce44SJohn Forte * Add command to pending command queue if not empty. 88*fcf3ce44SJohn Forte */ 89*fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) != NULL) { 90*fcf3ce44SJohn Forte ql_add_link_b(&ha->pending_cmds, &sp->cmd); 91*fcf3ce44SJohn Forte /* Remove command from pending command queue */ 92*fcf3ce44SJohn Forte sp = link->base_address; 93*fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 94*fcf3ce44SJohn Forte } 95*fcf3ce44SJohn Forte } else { 96*fcf3ce44SJohn Forte /* Get command from pending command queue if not empty. */ 97*fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) == NULL) { 98*fcf3ce44SJohn Forte /* Release ring specific lock */ 99*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 100*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): empty done\n", 101*fcf3ce44SJohn Forte ha->instance); 102*fcf3ce44SJohn Forte return; 103*fcf3ce44SJohn Forte } 104*fcf3ce44SJohn Forte /* Remove command from pending command queue */ 105*fcf3ce44SJohn Forte sp = link->base_address; 106*fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 107*fcf3ce44SJohn Forte } 108*fcf3ce44SJohn Forte 109*fcf3ce44SJohn Forte /* start as many as possible */ 110*fcf3ce44SJohn Forte for (;;) { 111*fcf3ce44SJohn Forte if (ha->req_q_cnt < sp->req_cnt) { 112*fcf3ce44SJohn Forte /* Calculate number of free request entries. */ 113*fcf3ce44SJohn Forte cnt = RD16_IO_REG(ha, req_out); 114*fcf3ce44SJohn Forte if (ha->req_ring_index < cnt) { 115*fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 116*fcf3ce44SJohn Forte (cnt - ha->req_ring_index); 117*fcf3ce44SJohn Forte } else { 118*fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t)(REQUEST_ENTRY_CNT - 119*fcf3ce44SJohn Forte (ha->req_ring_index - cnt)); 120*fcf3ce44SJohn Forte } 121*fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 122*fcf3ce44SJohn Forte ha->req_q_cnt--; 123*fcf3ce44SJohn Forte } 124*fcf3ce44SJohn Forte 125*fcf3ce44SJohn Forte /* If no room for request in request ring. */ 126*fcf3ce44SJohn Forte if (ha->req_q_cnt < sp->req_cnt) { 127*fcf3ce44SJohn Forte QL_PRINT_8(CE_CONT, "(%d): request ring full," 128*fcf3ce44SJohn Forte " req_q_cnt=%d, req_ring_index=%d\n", 129*fcf3ce44SJohn Forte ha->instance, ha->req_q_cnt, 130*fcf3ce44SJohn Forte ha->req_ring_index); 131*fcf3ce44SJohn Forte ql_add_link_t(&ha->pending_cmds, &sp->cmd); 132*fcf3ce44SJohn Forte break; 133*fcf3ce44SJohn Forte } 134*fcf3ce44SJohn Forte } 135*fcf3ce44SJohn Forte 136*fcf3ce44SJohn Forte /* Check for room in outstanding command list. */ 137*fcf3ce44SJohn Forte for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { 138*fcf3ce44SJohn Forte ha->osc_index++; 139*fcf3ce44SJohn Forte if (ha->osc_index == MAX_OUTSTANDING_COMMANDS) { 140*fcf3ce44SJohn Forte ha->osc_index = 1; 141*fcf3ce44SJohn Forte } 142*fcf3ce44SJohn Forte if (ha->outstanding_cmds[ha->osc_index] == NULL) { 143*fcf3ce44SJohn Forte break; 144*fcf3ce44SJohn Forte } 145*fcf3ce44SJohn Forte } 146*fcf3ce44SJohn Forte 147*fcf3ce44SJohn Forte if (cnt == MAX_OUTSTANDING_COMMANDS) { 148*fcf3ce44SJohn Forte QL_PRINT_8(CE_CONT, "(%d): no room in outstanding " 149*fcf3ce44SJohn Forte "array\n", ha->instance); 150*fcf3ce44SJohn Forte ql_add_link_t(&ha->pending_cmds, &sp->cmd); 151*fcf3ce44SJohn Forte break; 152*fcf3ce44SJohn Forte } 153*fcf3ce44SJohn Forte 154*fcf3ce44SJohn Forte /* If room for request in request ring. */ 155*fcf3ce44SJohn Forte ha->outstanding_cmds[ha->osc_index] = sp; 156*fcf3ce44SJohn Forte sp->handle = ha->adapter_stats->ncmds << OSC_INDEX_SHIFT | 157*fcf3ce44SJohn Forte ha->osc_index; 158*fcf3ce44SJohn Forte ha->req_q_cnt -= sp->req_cnt; 159*fcf3ce44SJohn Forte pkt = ha->request_ring_ptr; 160*fcf3ce44SJohn Forte sp->flags |= SRB_IN_TOKEN_ARRAY; 161*fcf3ce44SJohn Forte 162*fcf3ce44SJohn Forte /* Zero out packet. */ 163*fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 164*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 165*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 166*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 167*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 168*fcf3ce44SJohn Forte 169*fcf3ce44SJohn Forte /* Setup IOCB common data. */ 170*fcf3ce44SJohn Forte pkt->entry_count = (uint8_t)sp->req_cnt; 171*fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 172*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->handle, 173*fcf3ce44SJohn Forte (uint32_t)sp->handle); 174*fcf3ce44SJohn Forte 175*fcf3ce44SJohn Forte /* Setup remaining IOCB data. */ 176*fcf3ce44SJohn Forte (sp->iocb)(vha, sp, pkt); 177*fcf3ce44SJohn Forte 178*fcf3ce44SJohn Forte sp->flags |= SRB_ISP_STARTED; 179*fcf3ce44SJohn Forte 180*fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d,%d): req packet, sp=%p\n", 181*fcf3ce44SJohn Forte ha->instance, vha->vp_index, (void *)sp); 182*fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 183*fcf3ce44SJohn Forte 184*fcf3ce44SJohn Forte /* Sync DMA buffer. */ 185*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 186*fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 187*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 188*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 189*fcf3ce44SJohn Forte 190*fcf3ce44SJohn Forte /* Adjust ring index. */ 191*fcf3ce44SJohn Forte ha->req_ring_index++; 192*fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 193*fcf3ce44SJohn Forte ha->req_ring_index = 0; 194*fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 195*fcf3ce44SJohn Forte } else { 196*fcf3ce44SJohn Forte ha->request_ring_ptr++; 197*fcf3ce44SJohn Forte } 198*fcf3ce44SJohn Forte 199*fcf3ce44SJohn Forte /* Reset watchdog timer */ 200*fcf3ce44SJohn Forte sp->wdg_q_time = sp->init_wdg_q_time; 201*fcf3ce44SJohn Forte 202*fcf3ce44SJohn Forte /* Set chip new ring index. */ 203*fcf3ce44SJohn Forte WRT16_IO_REG(ha, req_in, ha->req_ring_index); 204*fcf3ce44SJohn Forte 205*fcf3ce44SJohn Forte /* Update outstanding command count statistic. */ 206*fcf3ce44SJohn Forte ha->adapter_stats->ncmds++; 207*fcf3ce44SJohn Forte 208*fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) == NULL) { 209*fcf3ce44SJohn Forte break; 210*fcf3ce44SJohn Forte } 211*fcf3ce44SJohn Forte 212*fcf3ce44SJohn Forte /* Remove command from pending command queue */ 213*fcf3ce44SJohn Forte sp = link->base_address; 214*fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 215*fcf3ce44SJohn Forte } 216*fcf3ce44SJohn Forte 217*fcf3ce44SJohn Forte /* Release ring specific lock */ 218*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 219*fcf3ce44SJohn Forte 220*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 221*fcf3ce44SJohn Forte } 222*fcf3ce44SJohn Forte 223*fcf3ce44SJohn Forte /* 224*fcf3ce44SJohn Forte * ql_req_pkt 225*fcf3ce44SJohn Forte * Function is responsible for locking ring and 226*fcf3ce44SJohn Forte * getting a zeroed out request packet. 227*fcf3ce44SJohn Forte * 228*fcf3ce44SJohn Forte * Input: 229*fcf3ce44SJohn Forte * ha: adapter state pointer. 230*fcf3ce44SJohn Forte * pkt: address for packet pointer. 231*fcf3ce44SJohn Forte * 232*fcf3ce44SJohn Forte * Returns: 233*fcf3ce44SJohn Forte * ql local function return status code. 234*fcf3ce44SJohn Forte * 235*fcf3ce44SJohn Forte * Context: 236*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 237*fcf3ce44SJohn Forte */ 238*fcf3ce44SJohn Forte int 239*fcf3ce44SJohn Forte ql_req_pkt(ql_adapter_state_t *vha, request_t **pktp) 240*fcf3ce44SJohn Forte { 241*fcf3ce44SJohn Forte uint16_t cnt; 242*fcf3ce44SJohn Forte uint32_t *long_ptr; 243*fcf3ce44SJohn Forte uint32_t timer; 244*fcf3ce44SJohn Forte int rval = QL_FUNCTION_TIMEOUT; 245*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 246*fcf3ce44SJohn Forte 247*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 248*fcf3ce44SJohn Forte 249*fcf3ce44SJohn Forte /* Wait for 30 seconds for slot. */ 250*fcf3ce44SJohn Forte for (timer = 30000; timer != 0; timer--) { 251*fcf3ce44SJohn Forte /* Acquire ring lock. */ 252*fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 253*fcf3ce44SJohn Forte 254*fcf3ce44SJohn Forte if (ha->req_q_cnt == 0) { 255*fcf3ce44SJohn Forte /* Calculate number of free request entries. */ 256*fcf3ce44SJohn Forte cnt = RD16_IO_REG(ha, req_out); 257*fcf3ce44SJohn Forte if (ha->req_ring_index < cnt) { 258*fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 259*fcf3ce44SJohn Forte (cnt - ha->req_ring_index); 260*fcf3ce44SJohn Forte } else { 261*fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 262*fcf3ce44SJohn Forte (REQUEST_ENTRY_CNT - 263*fcf3ce44SJohn Forte (ha->req_ring_index - cnt)); 264*fcf3ce44SJohn Forte } 265*fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 266*fcf3ce44SJohn Forte ha->req_q_cnt--; 267*fcf3ce44SJohn Forte } 268*fcf3ce44SJohn Forte } 269*fcf3ce44SJohn Forte 270*fcf3ce44SJohn Forte /* Found empty request ring slot? */ 271*fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 272*fcf3ce44SJohn Forte ha->req_q_cnt--; 273*fcf3ce44SJohn Forte *pktp = ha->request_ring_ptr; 274*fcf3ce44SJohn Forte 275*fcf3ce44SJohn Forte /* Zero out packet. */ 276*fcf3ce44SJohn Forte long_ptr = (uint32_t *)ha->request_ring_ptr; 277*fcf3ce44SJohn Forte for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) { 278*fcf3ce44SJohn Forte *long_ptr++ = 0; 279*fcf3ce44SJohn Forte } 280*fcf3ce44SJohn Forte 281*fcf3ce44SJohn Forte /* Setup IOCB common data. */ 282*fcf3ce44SJohn Forte ha->request_ring_ptr->entry_count = 1; 283*fcf3ce44SJohn Forte ha->request_ring_ptr->sys_define = 284*fcf3ce44SJohn Forte (uint8_t)ha->req_ring_index; 285*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 286*fcf3ce44SJohn Forte &ha->request_ring_ptr->handle, 287*fcf3ce44SJohn Forte (uint32_t)QL_FCA_BRAND); 288*fcf3ce44SJohn Forte 289*fcf3ce44SJohn Forte rval = QL_SUCCESS; 290*fcf3ce44SJohn Forte 291*fcf3ce44SJohn Forte break; 292*fcf3ce44SJohn Forte } 293*fcf3ce44SJohn Forte 294*fcf3ce44SJohn Forte /* Release request queue lock. */ 295*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 296*fcf3ce44SJohn Forte 297*fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 298*fcf3ce44SJohn Forte 299*fcf3ce44SJohn Forte /* Check for pending interrupts. */ 300*fcf3ce44SJohn Forte /* 301*fcf3ce44SJohn Forte * XXX protect interrupt routine from calling itself. 302*fcf3ce44SJohn Forte * Need to revisit this routine. So far we never 303*fcf3ce44SJohn Forte * hit this case as req slot was available 304*fcf3ce44SJohn Forte */ 305*fcf3ce44SJohn Forte if ((!(curthread->t_flag & T_INTR_THREAD)) && 306*fcf3ce44SJohn Forte (RD16_IO_REG(ha, istatus) & RISC_INT)) { 307*fcf3ce44SJohn Forte (void) ql_isr((caddr_t)ha); 308*fcf3ce44SJohn Forte INTR_LOCK(ha); 309*fcf3ce44SJohn Forte ha->intr_claimed = TRUE; 310*fcf3ce44SJohn Forte INTR_UNLOCK(ha); 311*fcf3ce44SJohn Forte } 312*fcf3ce44SJohn Forte } 313*fcf3ce44SJohn Forte 314*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 315*fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0); 316*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval); 317*fcf3ce44SJohn Forte } else { 318*fcf3ce44SJohn Forte /*EMPTY*/ 319*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 320*fcf3ce44SJohn Forte } 321*fcf3ce44SJohn Forte return (rval); 322*fcf3ce44SJohn Forte } 323*fcf3ce44SJohn Forte 324*fcf3ce44SJohn Forte /* 325*fcf3ce44SJohn Forte * ql_isp_cmd 326*fcf3ce44SJohn Forte * Function is responsible for modifying ISP input pointer. 327*fcf3ce44SJohn Forte * Releases ring lock. 328*fcf3ce44SJohn Forte * 329*fcf3ce44SJohn Forte * Input: 330*fcf3ce44SJohn Forte * ha: adapter state pointer. 331*fcf3ce44SJohn Forte * 332*fcf3ce44SJohn Forte * Context: 333*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 334*fcf3ce44SJohn Forte */ 335*fcf3ce44SJohn Forte void 336*fcf3ce44SJohn Forte ql_isp_cmd(ql_adapter_state_t *vha) 337*fcf3ce44SJohn Forte { 338*fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 339*fcf3ce44SJohn Forte 340*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 341*fcf3ce44SJohn Forte 342*fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): req packet:\n", ha->instance); 343*fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)ha->request_ring_ptr, 8, REQUEST_ENTRY_SIZE); 344*fcf3ce44SJohn Forte 345*fcf3ce44SJohn Forte /* Sync DMA buffer. */ 346*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 347*fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 348*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 349*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 350*fcf3ce44SJohn Forte 351*fcf3ce44SJohn Forte /* Adjust ring index. */ 352*fcf3ce44SJohn Forte ha->req_ring_index++; 353*fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 354*fcf3ce44SJohn Forte ha->req_ring_index = 0; 355*fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 356*fcf3ce44SJohn Forte } else { 357*fcf3ce44SJohn Forte ha->request_ring_ptr++; 358*fcf3ce44SJohn Forte } 359*fcf3ce44SJohn Forte 360*fcf3ce44SJohn Forte /* Set chip new ring index. */ 361*fcf3ce44SJohn Forte WRT16_IO_REG(ha, req_in, ha->req_ring_index); 362*fcf3ce44SJohn Forte 363*fcf3ce44SJohn Forte /* Release ring lock. */ 364*fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 365*fcf3ce44SJohn Forte 366*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 367*fcf3ce44SJohn Forte } 368*fcf3ce44SJohn Forte 369*fcf3ce44SJohn Forte /* 370*fcf3ce44SJohn Forte * ql_command_iocb 371*fcf3ce44SJohn Forte * Setup of command IOCB. 372*fcf3ce44SJohn Forte * 373*fcf3ce44SJohn Forte * Input: 374*fcf3ce44SJohn Forte * ha: adapter state pointer. 375*fcf3ce44SJohn Forte * sp: srb structure pointer. 376*fcf3ce44SJohn Forte * 377*fcf3ce44SJohn Forte * arg: request queue packet. 378*fcf3ce44SJohn Forte * 379*fcf3ce44SJohn Forte * Context: 380*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 381*fcf3ce44SJohn Forte */ 382*fcf3ce44SJohn Forte void 383*fcf3ce44SJohn Forte ql_command_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 384*fcf3ce44SJohn Forte { 385*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 386*fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 387*fcf3ce44SJohn Forte uint16_t seg_cnt; 388*fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 389*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 390*fcf3ce44SJohn Forte cmd_entry_t *pkt = arg; 391*fcf3ce44SJohn Forte 392*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 393*fcf3ce44SJohn Forte 394*fcf3ce44SJohn Forte /* Set LUN number */ 395*fcf3ce44SJohn Forte pkt->lun_l = LSB(sp->lun_queue->lun_no); 396*fcf3ce44SJohn Forte pkt->lun_h = MSB(sp->lun_queue->lun_no); 397*fcf3ce44SJohn Forte 398*fcf3ce44SJohn Forte /* Set target ID */ 399*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 400*fcf3ce44SJohn Forte pkt->target_l = LSB(tq->loop_id); 401*fcf3ce44SJohn Forte pkt->target_h = MSB(tq->loop_id); 402*fcf3ce44SJohn Forte } else { 403*fcf3ce44SJohn Forte pkt->target_h = LSB(tq->loop_id); 404*fcf3ce44SJohn Forte } 405*fcf3ce44SJohn Forte 406*fcf3ce44SJohn Forte /* Set tag queue control flags */ 407*fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) { 408*fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 409*fcf3ce44SJohn Forte (pkt->control_flags_l | CF_HTAG); 410*fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) { 411*fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 412*fcf3ce44SJohn Forte (pkt->control_flags_l | CF_OTAG); 413*fcf3ce44SJohn Forte /* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */ 414*fcf3ce44SJohn Forte } else { 415*fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 416*fcf3ce44SJohn Forte (pkt->control_flags_l | CF_STAG); 417*fcf3ce44SJohn Forte } 418*fcf3ce44SJohn Forte 419*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 420*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 421*fcf3ce44SJohn Forte 422*fcf3ce44SJohn Forte /* Load SCSI CDB */ 423*fcf3ce44SJohn Forte ddi_rep_put8(ha->hba_buf.acc_handle, fcp->fcp_cdb, 424*fcf3ce44SJohn Forte pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR); 425*fcf3ce44SJohn Forte 426*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 427*fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_3; 428*fcf3ce44SJohn Forte cnt = CMD_TYPE_3_DATA_SEGMENTS; 429*fcf3ce44SJohn Forte } else { 430*fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_2; 431*fcf3ce44SJohn Forte cnt = CMD_TYPE_2_DATA_SEGMENTS; 432*fcf3ce44SJohn Forte } 433*fcf3ce44SJohn Forte 434*fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 435*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 436*fcf3ce44SJohn Forte ha->xioctl->IOControlRequests++; 437*fcf3ce44SJohn Forte return; 438*fcf3ce44SJohn Forte } 439*fcf3ce44SJohn Forte 440*fcf3ce44SJohn Forte /* 441*fcf3ce44SJohn Forte * Set transfer direction. Load Data segments. 442*fcf3ce44SJohn Forte */ 443*fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 444*fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 445*fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_OUT); 446*fcf3ce44SJohn Forte ha->xioctl->IOOutputRequests++; 447*fcf3ce44SJohn Forte ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 448*fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 449*fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 450*fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_IN); 451*fcf3ce44SJohn Forte ha->xioctl->IOInputRequests++; 452*fcf3ce44SJohn Forte ha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 453*fcf3ce44SJohn Forte } 454*fcf3ce44SJohn Forte 455*fcf3ce44SJohn Forte /* Set data segment count. */ 456*fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 457*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 458*fcf3ce44SJohn Forte 459*fcf3ce44SJohn Forte /* Load total byte count. */ 460*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, fcp->fcp_data_len); 461*fcf3ce44SJohn Forte 462*fcf3ce44SJohn Forte /* Load command data segment. */ 463*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 464*fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 465*fcf3ce44SJohn Forte while (cnt && seg_cnt) { 466*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 467*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 468*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 469*fcf3ce44SJohn Forte cp->dmac_notused); 470*fcf3ce44SJohn Forte } 471*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 472*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 473*fcf3ce44SJohn Forte seg_cnt--; 474*fcf3ce44SJohn Forte cnt--; 475*fcf3ce44SJohn Forte cp++; 476*fcf3ce44SJohn Forte } 477*fcf3ce44SJohn Forte 478*fcf3ce44SJohn Forte /* 479*fcf3ce44SJohn Forte * Build continuation packets. 480*fcf3ce44SJohn Forte */ 481*fcf3ce44SJohn Forte if (seg_cnt) { 482*fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 483*fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 484*fcf3ce44SJohn Forte } 485*fcf3ce44SJohn Forte 486*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 487*fcf3ce44SJohn Forte } 488*fcf3ce44SJohn Forte 489*fcf3ce44SJohn Forte /* 490*fcf3ce44SJohn Forte * ql_continuation_iocb 491*fcf3ce44SJohn Forte * Setup of continuation IOCB. 492*fcf3ce44SJohn Forte * 493*fcf3ce44SJohn Forte * Input: 494*fcf3ce44SJohn Forte * ha: adapter state pointer. 495*fcf3ce44SJohn Forte * cp: cookie list pointer. 496*fcf3ce44SJohn Forte * seg_cnt: number of segments. 497*fcf3ce44SJohn Forte * addr64: 64 bit addresses. 498*fcf3ce44SJohn Forte * 499*fcf3ce44SJohn Forte * Context: 500*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 501*fcf3ce44SJohn Forte */ 502*fcf3ce44SJohn Forte static void 503*fcf3ce44SJohn Forte ql_continuation_iocb(ql_adapter_state_t *ha, ddi_dma_cookie_t *cp, 504*fcf3ce44SJohn Forte uint16_t seg_cnt, boolean_t addr64) 505*fcf3ce44SJohn Forte { 506*fcf3ce44SJohn Forte cont_entry_t *pkt; 507*fcf3ce44SJohn Forte uint64_t *ptr64; 508*fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 509*fcf3ce44SJohn Forte 510*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 511*fcf3ce44SJohn Forte 512*fcf3ce44SJohn Forte /* 513*fcf3ce44SJohn Forte * Build continuation packets. 514*fcf3ce44SJohn Forte */ 515*fcf3ce44SJohn Forte while (seg_cnt) { 516*fcf3ce44SJohn Forte /* Sync DMA buffer. */ 517*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 518*fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 519*fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), REQUEST_ENTRY_SIZE, 520*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 521*fcf3ce44SJohn Forte 522*fcf3ce44SJohn Forte /* Adjust ring pointer, and deal with wrap. */ 523*fcf3ce44SJohn Forte ha->req_ring_index++; 524*fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 525*fcf3ce44SJohn Forte ha->req_ring_index = 0; 526*fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 527*fcf3ce44SJohn Forte } else { 528*fcf3ce44SJohn Forte ha->request_ring_ptr++; 529*fcf3ce44SJohn Forte } 530*fcf3ce44SJohn Forte pkt = (cont_entry_t *)ha->request_ring_ptr; 531*fcf3ce44SJohn Forte 532*fcf3ce44SJohn Forte /* Zero out packet. */ 533*fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 534*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 535*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 536*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 537*fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 538*fcf3ce44SJohn Forte 539*fcf3ce44SJohn Forte /* 540*fcf3ce44SJohn Forte * Build continuation packet. 541*fcf3ce44SJohn Forte */ 542*fcf3ce44SJohn Forte pkt->entry_count = 1; 543*fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 544*fcf3ce44SJohn Forte if (addr64) { 545*fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_1; 546*fcf3ce44SJohn Forte cnt = CONT_TYPE_1_DATA_SEGMENTS; 547*fcf3ce44SJohn Forte ptr32 = (uint32_t *) 548*fcf3ce44SJohn Forte &((cont_type_1_entry_t *)pkt)->dseg_0_address; 549*fcf3ce44SJohn Forte while (cnt && seg_cnt) { 550*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 551*fcf3ce44SJohn Forte cp->dmac_address); 552*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 553*fcf3ce44SJohn Forte cp->dmac_notused); 554*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 555*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 556*fcf3ce44SJohn Forte seg_cnt--; 557*fcf3ce44SJohn Forte cnt--; 558*fcf3ce44SJohn Forte cp++; 559*fcf3ce44SJohn Forte } 560*fcf3ce44SJohn Forte } else { 561*fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_0; 562*fcf3ce44SJohn Forte cnt = CONT_TYPE_0_DATA_SEGMENTS; 563*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 564*fcf3ce44SJohn Forte while (cnt && seg_cnt) { 565*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 566*fcf3ce44SJohn Forte cp->dmac_address); 567*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 568*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 569*fcf3ce44SJohn Forte seg_cnt--; 570*fcf3ce44SJohn Forte cnt--; 571*fcf3ce44SJohn Forte cp++; 572*fcf3ce44SJohn Forte } 573*fcf3ce44SJohn Forte } 574*fcf3ce44SJohn Forte 575*fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): packet:\n", ha->instance); 576*fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 577*fcf3ce44SJohn Forte } 578*fcf3ce44SJohn Forte 579*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 580*fcf3ce44SJohn Forte } 581*fcf3ce44SJohn Forte 582*fcf3ce44SJohn Forte /* 583*fcf3ce44SJohn Forte * ql_command_24xx_iocb 584*fcf3ce44SJohn Forte * Setup of ISP24xx command IOCB. 585*fcf3ce44SJohn Forte * 586*fcf3ce44SJohn Forte * Input: 587*fcf3ce44SJohn Forte * ha: adapter state pointer. 588*fcf3ce44SJohn Forte * sp: srb structure pointer. 589*fcf3ce44SJohn Forte * arg: request queue packet. 590*fcf3ce44SJohn Forte * 591*fcf3ce44SJohn Forte * Context: 592*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 593*fcf3ce44SJohn Forte */ 594*fcf3ce44SJohn Forte void 595*fcf3ce44SJohn Forte ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 596*fcf3ce44SJohn Forte { 597*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 598*fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 599*fcf3ce44SJohn Forte uint16_t seg_cnt; 600*fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 601*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 602*fcf3ce44SJohn Forte cmd_24xx_entry_t *pkt = arg; 603*fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 604*fcf3ce44SJohn Forte 605*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 606*fcf3ce44SJohn Forte 607*fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_7; 608*fcf3ce44SJohn Forte 609*fcf3ce44SJohn Forte /* Set LUN number */ 610*fcf3ce44SJohn Forte pkt->fcp_lun[2] = LSB(sp->lun_queue->lun_no); 611*fcf3ce44SJohn Forte pkt->fcp_lun[3] = MSB(sp->lun_queue->lun_no); 612*fcf3ce44SJohn Forte 613*fcf3ce44SJohn Forte /* Set N_port handle */ 614*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 615*fcf3ce44SJohn Forte 616*fcf3ce44SJohn Forte /* Set target ID */ 617*fcf3ce44SJohn Forte pkt->target_id[0] = tq->d_id.b.al_pa; 618*fcf3ce44SJohn Forte pkt->target_id[1] = tq->d_id.b.area; 619*fcf3ce44SJohn Forte pkt->target_id[2] = tq->d_id.b.domain; 620*fcf3ce44SJohn Forte 621*fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 622*fcf3ce44SJohn Forte 623*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 624*fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 625*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 626*fcf3ce44SJohn Forte sp->isp_timeout); 627*fcf3ce44SJohn Forte } 628*fcf3ce44SJohn Forte 629*fcf3ce44SJohn Forte /* Load SCSI CDB */ 630*fcf3ce44SJohn Forte ddi_rep_put8(pha->hba_buf.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb, 631*fcf3ce44SJohn Forte MAX_CMDSZ, DDI_DEV_AUTOINCR); 632*fcf3ce44SJohn Forte for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) { 633*fcf3ce44SJohn Forte ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4); 634*fcf3ce44SJohn Forte } 635*fcf3ce44SJohn Forte 636*fcf3ce44SJohn Forte /* 637*fcf3ce44SJohn Forte * Set tag queue control flags 638*fcf3ce44SJohn Forte * Note: 639*fcf3ce44SJohn Forte * Cannot copy fcp->fcp_cntl.cntl_qtype directly, 640*fcf3ce44SJohn Forte * problem with x86 in 32bit kernel mode 641*fcf3ce44SJohn Forte */ 642*fcf3ce44SJohn Forte switch (fcp->fcp_cntl.cntl_qtype) { 643*fcf3ce44SJohn Forte case FCP_QTYPE_SIMPLE: 644*fcf3ce44SJohn Forte pkt->task = TA_STAG; 645*fcf3ce44SJohn Forte break; 646*fcf3ce44SJohn Forte case FCP_QTYPE_HEAD_OF_Q: 647*fcf3ce44SJohn Forte pkt->task = TA_HTAG; 648*fcf3ce44SJohn Forte break; 649*fcf3ce44SJohn Forte case FCP_QTYPE_ORDERED: 650*fcf3ce44SJohn Forte pkt->task = TA_OTAG; 651*fcf3ce44SJohn Forte break; 652*fcf3ce44SJohn Forte case FCP_QTYPE_ACA_Q_TAG: 653*fcf3ce44SJohn Forte pkt->task = TA_ACA; 654*fcf3ce44SJohn Forte break; 655*fcf3ce44SJohn Forte case FCP_QTYPE_UNTAGGED: 656*fcf3ce44SJohn Forte pkt->task = TA_UNTAGGED; 657*fcf3ce44SJohn Forte break; 658*fcf3ce44SJohn Forte default: 659*fcf3ce44SJohn Forte break; 660*fcf3ce44SJohn Forte } 661*fcf3ce44SJohn Forte 662*fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 663*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 664*fcf3ce44SJohn Forte pha->xioctl->IOControlRequests++; 665*fcf3ce44SJohn Forte return; 666*fcf3ce44SJohn Forte } 667*fcf3ce44SJohn Forte 668*fcf3ce44SJohn Forte /* Set transfer direction. */ 669*fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 670*fcf3ce44SJohn Forte pkt->control_flags = CF_WR; 671*fcf3ce44SJohn Forte pha->xioctl->IOOutputRequests++; 672*fcf3ce44SJohn Forte pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 673*fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 674*fcf3ce44SJohn Forte pkt->control_flags = CF_RD; 675*fcf3ce44SJohn Forte pha->xioctl->IOInputRequests++; 676*fcf3ce44SJohn Forte pha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 677*fcf3ce44SJohn Forte } 678*fcf3ce44SJohn Forte 679*fcf3ce44SJohn Forte /* Set data segment count. */ 680*fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 681*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 682*fcf3ce44SJohn Forte 683*fcf3ce44SJohn Forte /* Load total byte count. */ 684*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count, 685*fcf3ce44SJohn Forte fcp->fcp_data_len); 686*fcf3ce44SJohn Forte 687*fcf3ce44SJohn Forte /* Load command data segment. */ 688*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 689*fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 690*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 691*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 692*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 693*fcf3ce44SJohn Forte seg_cnt--; 694*fcf3ce44SJohn Forte cp++; 695*fcf3ce44SJohn Forte 696*fcf3ce44SJohn Forte /* 697*fcf3ce44SJohn Forte * Build continuation packets. 698*fcf3ce44SJohn Forte */ 699*fcf3ce44SJohn Forte if (seg_cnt) { 700*fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 701*fcf3ce44SJohn Forte } 702*fcf3ce44SJohn Forte 703*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 704*fcf3ce44SJohn Forte } 705*fcf3ce44SJohn Forte 706*fcf3ce44SJohn Forte /* 707*fcf3ce44SJohn Forte * ql_marker 708*fcf3ce44SJohn Forte * Function issues marker IOCB. 709*fcf3ce44SJohn Forte * 710*fcf3ce44SJohn Forte * Input: 711*fcf3ce44SJohn Forte * ha: adapter state pointer. 712*fcf3ce44SJohn Forte * loop_id: device loop ID 713*fcf3ce44SJohn Forte * lun: device LUN 714*fcf3ce44SJohn Forte * type: marker modifier 715*fcf3ce44SJohn Forte * 716*fcf3ce44SJohn Forte * Returns: 717*fcf3ce44SJohn Forte * ql local function return status code. 718*fcf3ce44SJohn Forte * 719*fcf3ce44SJohn Forte * Context: 720*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 721*fcf3ce44SJohn Forte */ 722*fcf3ce44SJohn Forte int 723*fcf3ce44SJohn Forte ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, uint16_t lun, 724*fcf3ce44SJohn Forte uint8_t type) 725*fcf3ce44SJohn Forte { 726*fcf3ce44SJohn Forte mrk_entry_t *pkt; 727*fcf3ce44SJohn Forte int rval; 728*fcf3ce44SJohn Forte 729*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 730*fcf3ce44SJohn Forte 731*fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 732*fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 733*fcf3ce44SJohn Forte pkt->entry_type = MARKER_TYPE; 734*fcf3ce44SJohn Forte 735*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 736*fcf3ce44SJohn Forte marker_24xx_entry_t *pkt24 = 737*fcf3ce44SJohn Forte (marker_24xx_entry_t *)pkt; 738*fcf3ce44SJohn Forte 739*fcf3ce44SJohn Forte pkt24->modifier = type; 740*fcf3ce44SJohn Forte 741*fcf3ce44SJohn Forte /* Set LUN number */ 742*fcf3ce44SJohn Forte pkt24->fcp_lun[2] = LSB(lun); 743*fcf3ce44SJohn Forte pkt24->fcp_lun[3] = MSB(lun); 744*fcf3ce44SJohn Forte 745*fcf3ce44SJohn Forte pkt24->vp_index = ha->vp_index; 746*fcf3ce44SJohn Forte 747*fcf3ce44SJohn Forte /* Set N_port handle */ 748*fcf3ce44SJohn Forte ddi_put16(ha->pha->hba_buf.acc_handle, 749*fcf3ce44SJohn Forte &pkt24->n_port_hdl, loop_id); 750*fcf3ce44SJohn Forte 751*fcf3ce44SJohn Forte } else { 752*fcf3ce44SJohn Forte pkt->modifier = type; 753*fcf3ce44SJohn Forte 754*fcf3ce44SJohn Forte pkt->lun_l = LSB(lun); 755*fcf3ce44SJohn Forte pkt->lun_h = MSB(lun); 756*fcf3ce44SJohn Forte 757*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 758*fcf3ce44SJohn Forte pkt->target_l = LSB(loop_id); 759*fcf3ce44SJohn Forte pkt->target_h = MSB(loop_id); 760*fcf3ce44SJohn Forte } else { 761*fcf3ce44SJohn Forte pkt->target_h = LSB(loop_id); 762*fcf3ce44SJohn Forte } 763*fcf3ce44SJohn Forte } 764*fcf3ce44SJohn Forte 765*fcf3ce44SJohn Forte /* Issue command to ISP */ 766*fcf3ce44SJohn Forte ql_isp_cmd(ha); 767*fcf3ce44SJohn Forte } 768*fcf3ce44SJohn Forte 769*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 770*fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 771*fcf3ce44SJohn Forte } else { 772*fcf3ce44SJohn Forte /*EMPTY*/ 773*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 774*fcf3ce44SJohn Forte } 775*fcf3ce44SJohn Forte return (rval); 776*fcf3ce44SJohn Forte } 777*fcf3ce44SJohn Forte 778*fcf3ce44SJohn Forte /* 779*fcf3ce44SJohn Forte * ql_ms_iocb 780*fcf3ce44SJohn Forte * Setup of name/management server IOCB. 781*fcf3ce44SJohn Forte * 782*fcf3ce44SJohn Forte * Input: 783*fcf3ce44SJohn Forte * ha = adapter state pointer. 784*fcf3ce44SJohn Forte * sp = srb structure pointer. 785*fcf3ce44SJohn Forte * arg = request queue packet. 786*fcf3ce44SJohn Forte * 787*fcf3ce44SJohn Forte * Context: 788*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 789*fcf3ce44SJohn Forte */ 790*fcf3ce44SJohn Forte void 791*fcf3ce44SJohn Forte ql_ms_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 792*fcf3ce44SJohn Forte { 793*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 794*fcf3ce44SJohn Forte uint32_t *ptr32; 795*fcf3ce44SJohn Forte uint16_t seg_cnt; 796*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 797*fcf3ce44SJohn Forte ms_entry_t *pkt = arg; 798*fcf3ce44SJohn Forte 799*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 800*fcf3ce44SJohn Forte #if 0 801*fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 802*fcf3ce44SJohn Forte #endif 803*fcf3ce44SJohn Forte /* 804*fcf3ce44SJohn Forte * Build command packet. 805*fcf3ce44SJohn Forte */ 806*fcf3ce44SJohn Forte pkt->entry_type = MS_TYPE; 807*fcf3ce44SJohn Forte 808*fcf3ce44SJohn Forte /* Set loop ID */ 809*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 810*fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 811*fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 812*fcf3ce44SJohn Forte } else { 813*fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 814*fcf3ce44SJohn Forte } 815*fcf3ce44SJohn Forte 816*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 817*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 818*fcf3ce44SJohn Forte 819*fcf3ce44SJohn Forte /* Set cmd data segment count. */ 820*fcf3ce44SJohn Forte pkt->cmd_dseg_count_l = 1; 821*fcf3ce44SJohn Forte 822*fcf3ce44SJohn Forte /* Set total data segment count */ 823*fcf3ce44SJohn Forte seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1); 824*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->total_dseg_count, seg_cnt); 825*fcf3ce44SJohn Forte 826*fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 827*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->cmd_byte_count, 828*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 829*fcf3ce44SJohn Forte 830*fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 831*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->resp_byte_count, 832*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 833*fcf3ce44SJohn Forte 834*fcf3ce44SJohn Forte /* Load MS command data segments. */ 835*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 836*fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 837*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 838*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 839*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 840*fcf3ce44SJohn Forte seg_cnt--; 841*fcf3ce44SJohn Forte 842*fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 843*fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 844*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 845*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 846*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 847*fcf3ce44SJohn Forte seg_cnt--; 848*fcf3ce44SJohn Forte cp++; 849*fcf3ce44SJohn Forte 850*fcf3ce44SJohn Forte /* 851*fcf3ce44SJohn Forte * Build continuation packets. 852*fcf3ce44SJohn Forte */ 853*fcf3ce44SJohn Forte if (seg_cnt) { 854*fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 855*fcf3ce44SJohn Forte } 856*fcf3ce44SJohn Forte 857*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 858*fcf3ce44SJohn Forte } 859*fcf3ce44SJohn Forte 860*fcf3ce44SJohn Forte /* 861*fcf3ce44SJohn Forte * ql_ms_24xx_iocb 862*fcf3ce44SJohn Forte * Setup of name/management server IOCB. 863*fcf3ce44SJohn Forte * 864*fcf3ce44SJohn Forte * Input: 865*fcf3ce44SJohn Forte * ha: adapter state pointer. 866*fcf3ce44SJohn Forte * sp: srb structure pointer. 867*fcf3ce44SJohn Forte * arg: request queue packet. 868*fcf3ce44SJohn Forte * 869*fcf3ce44SJohn Forte * Context: 870*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 871*fcf3ce44SJohn Forte */ 872*fcf3ce44SJohn Forte void 873*fcf3ce44SJohn Forte ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 874*fcf3ce44SJohn Forte { 875*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 876*fcf3ce44SJohn Forte uint32_t *ptr32; 877*fcf3ce44SJohn Forte uint16_t seg_cnt; 878*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 879*fcf3ce44SJohn Forte ct_passthru_entry_t *pkt = arg; 880*fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 881*fcf3ce44SJohn Forte 882*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 883*fcf3ce44SJohn Forte #if 0 884*fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 885*fcf3ce44SJohn Forte #endif 886*fcf3ce44SJohn Forte /* 887*fcf3ce44SJohn Forte * Build command packet. 888*fcf3ce44SJohn Forte */ 889*fcf3ce44SJohn Forte pkt->entry_type = CT_PASSTHRU_TYPE; 890*fcf3ce44SJohn Forte 891*fcf3ce44SJohn Forte /* Set loop ID */ 892*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 893*fcf3ce44SJohn Forte 894*fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 895*fcf3ce44SJohn Forte 896*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 897*fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 898*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 899*fcf3ce44SJohn Forte sp->isp_timeout); 900*fcf3ce44SJohn Forte } 901*fcf3ce44SJohn Forte 902*fcf3ce44SJohn Forte /* Set cmd/response data segment counts. */ 903*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->cmd_dseg_count, 1); 904*fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt; 905*fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->resp_dseg_count, seg_cnt); 906*fcf3ce44SJohn Forte 907*fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 908*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->cmd_byte_count, 909*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 910*fcf3ce44SJohn Forte 911*fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 912*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->resp_byte_count, 913*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 914*fcf3ce44SJohn Forte 915*fcf3ce44SJohn Forte /* Load MS command entry data segments. */ 916*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 917*fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 918*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 919*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 920*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 921*fcf3ce44SJohn Forte 922*fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 923*fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 924*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 925*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 926*fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 927*fcf3ce44SJohn Forte seg_cnt--; 928*fcf3ce44SJohn Forte cp++; 929*fcf3ce44SJohn Forte 930*fcf3ce44SJohn Forte /* 931*fcf3ce44SJohn Forte * Build continuation packets. 932*fcf3ce44SJohn Forte */ 933*fcf3ce44SJohn Forte if (seg_cnt) { 934*fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 935*fcf3ce44SJohn Forte } 936*fcf3ce44SJohn Forte 937*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 938*fcf3ce44SJohn Forte } 939*fcf3ce44SJohn Forte 940*fcf3ce44SJohn Forte /* 941*fcf3ce44SJohn Forte * ql_ip_iocb 942*fcf3ce44SJohn Forte * Setup of IP IOCB. 943*fcf3ce44SJohn Forte * 944*fcf3ce44SJohn Forte * Input: 945*fcf3ce44SJohn Forte * ha: adapter state pointer. 946*fcf3ce44SJohn Forte * sp: srb structure pointer. 947*fcf3ce44SJohn Forte * arg: request queue packet. 948*fcf3ce44SJohn Forte * 949*fcf3ce44SJohn Forte * Context: 950*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 951*fcf3ce44SJohn Forte */ 952*fcf3ce44SJohn Forte void 953*fcf3ce44SJohn Forte ql_ip_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 954*fcf3ce44SJohn Forte { 955*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 956*fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 957*fcf3ce44SJohn Forte uint16_t seg_cnt; 958*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 959*fcf3ce44SJohn Forte ip_entry_t *pkt = arg; 960*fcf3ce44SJohn Forte 961*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 962*fcf3ce44SJohn Forte 963*fcf3ce44SJohn Forte /* Set loop ID */ 964*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 965*fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 966*fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 967*fcf3ce44SJohn Forte } else { 968*fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 969*fcf3ce44SJohn Forte } 970*fcf3ce44SJohn Forte 971*fcf3ce44SJohn Forte /* Set control flags */ 972*fcf3ce44SJohn Forte pkt->control_flags_l = BIT_6; 973*fcf3ce44SJohn Forte if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) { 974*fcf3ce44SJohn Forte pkt->control_flags_h = BIT_7; 975*fcf3ce44SJohn Forte } 976*fcf3ce44SJohn Forte 977*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 978*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 979*fcf3ce44SJohn Forte 980*fcf3ce44SJohn Forte /* Set data segment count. */ 981*fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 982*fcf3ce44SJohn Forte /* Load total byte count. */ 983*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 984*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 985*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 986*fcf3ce44SJohn Forte 987*fcf3ce44SJohn Forte /* 988*fcf3ce44SJohn Forte * Build command packet. 989*fcf3ce44SJohn Forte */ 990*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 991*fcf3ce44SJohn Forte pkt->entry_type = IP_A64_TYPE; 992*fcf3ce44SJohn Forte cnt = IP_A64_DATA_SEGMENTS; 993*fcf3ce44SJohn Forte } else { 994*fcf3ce44SJohn Forte pkt->entry_type = IP_TYPE; 995*fcf3ce44SJohn Forte cnt = IP_DATA_SEGMENTS; 996*fcf3ce44SJohn Forte } 997*fcf3ce44SJohn Forte 998*fcf3ce44SJohn Forte /* Load command entry data segments. */ 999*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1000*fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1001*fcf3ce44SJohn Forte while (cnt && seg_cnt) { 1002*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1003*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1004*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1005*fcf3ce44SJohn Forte cp->dmac_notused); 1006*fcf3ce44SJohn Forte } 1007*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1008*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1009*fcf3ce44SJohn Forte seg_cnt--; 1010*fcf3ce44SJohn Forte cnt--; 1011*fcf3ce44SJohn Forte cp++; 1012*fcf3ce44SJohn Forte } 1013*fcf3ce44SJohn Forte 1014*fcf3ce44SJohn Forte /* 1015*fcf3ce44SJohn Forte * Build continuation packets. 1016*fcf3ce44SJohn Forte */ 1017*fcf3ce44SJohn Forte if (seg_cnt) { 1018*fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 1019*fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 1020*fcf3ce44SJohn Forte } 1021*fcf3ce44SJohn Forte 1022*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1023*fcf3ce44SJohn Forte } 1024*fcf3ce44SJohn Forte 1025*fcf3ce44SJohn Forte /* 1026*fcf3ce44SJohn Forte * ql_ip_24xx_iocb 1027*fcf3ce44SJohn Forte * Setup of IP IOCB for ISP24xx. 1028*fcf3ce44SJohn Forte * 1029*fcf3ce44SJohn Forte * Input: 1030*fcf3ce44SJohn Forte * ha: adapter state pointer. 1031*fcf3ce44SJohn Forte * sp: srb structure pointer. 1032*fcf3ce44SJohn Forte * arg: request queue packet. 1033*fcf3ce44SJohn Forte * 1034*fcf3ce44SJohn Forte * Context: 1035*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1036*fcf3ce44SJohn Forte */ 1037*fcf3ce44SJohn Forte void 1038*fcf3ce44SJohn Forte ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1039*fcf3ce44SJohn Forte { 1040*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1041*fcf3ce44SJohn Forte uint32_t *ptr32; 1042*fcf3ce44SJohn Forte uint16_t seg_cnt; 1043*fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 1044*fcf3ce44SJohn Forte ip_cmd_entry_t *pkt = arg; 1045*fcf3ce44SJohn Forte 1046*fcf3ce44SJohn Forte pkt->entry_type = IP_CMD_TYPE; 1047*fcf3ce44SJohn Forte 1048*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1049*fcf3ce44SJohn Forte 1050*fcf3ce44SJohn Forte /* Set N_port handle */ 1051*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->hdl_status, tq->loop_id); 1052*fcf3ce44SJohn Forte 1053*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1054*fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 1055*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout_hdl, 1056*fcf3ce44SJohn Forte sp->isp_timeout); 1057*fcf3ce44SJohn Forte } 1058*fcf3ce44SJohn Forte 1059*fcf3ce44SJohn Forte /* Set data segment count. */ 1060*fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 1061*fcf3ce44SJohn Forte /* Load total byte count. */ 1062*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 1063*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1064*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 1065*fcf3ce44SJohn Forte 1066*fcf3ce44SJohn Forte /* Set control flags */ 1067*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->control_flags, 1068*fcf3ce44SJohn Forte (uint16_t)(BIT_0)); 1069*fcf3ce44SJohn Forte 1070*fcf3ce44SJohn Forte /* Set frame header control flags */ 1071*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->frame_hdr_cntrl_flgs, 1072*fcf3ce44SJohn Forte (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ)); 1073*fcf3ce44SJohn Forte 1074*fcf3ce44SJohn Forte /* Load command data segment. */ 1075*fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1076*fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1077*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1078*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1079*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 1080*fcf3ce44SJohn Forte seg_cnt--; 1081*fcf3ce44SJohn Forte cp++; 1082*fcf3ce44SJohn Forte 1083*fcf3ce44SJohn Forte /* 1084*fcf3ce44SJohn Forte * Build continuation packets. 1085*fcf3ce44SJohn Forte */ 1086*fcf3ce44SJohn Forte if (seg_cnt) { 1087*fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 1088*fcf3ce44SJohn Forte } 1089*fcf3ce44SJohn Forte 1090*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1091*fcf3ce44SJohn Forte } 1092*fcf3ce44SJohn Forte 1093*fcf3ce44SJohn Forte /* 1094*fcf3ce44SJohn Forte * ql_isp_rcvbuf 1095*fcf3ce44SJohn Forte * Locates free buffers and places it on the receive buffer queue. 1096*fcf3ce44SJohn Forte * 1097*fcf3ce44SJohn Forte * Input: 1098*fcf3ce44SJohn Forte * ha = adapter state pointer. 1099*fcf3ce44SJohn Forte * 1100*fcf3ce44SJohn Forte * Context: 1101*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1102*fcf3ce44SJohn Forte */ 1103*fcf3ce44SJohn Forte void 1104*fcf3ce44SJohn Forte ql_isp_rcvbuf(ql_adapter_state_t *ha) 1105*fcf3ce44SJohn Forte { 1106*fcf3ce44SJohn Forte rcvbuf_t *container; 1107*fcf3ce44SJohn Forte int16_t rcv_q_cnt; 1108*fcf3ce44SJohn Forte uint16_t index = 0; 1109*fcf3ce44SJohn Forte uint16_t index1 = 1; 1110*fcf3ce44SJohn Forte int debounce_count = QL_MAX_DEBOUNCE; 1111*fcf3ce44SJohn Forte ql_srb_t *sp; 1112*fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1113*fcf3ce44SJohn Forte int ring_updated = FALSE; 1114*fcf3ce44SJohn Forte 1115*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_CTRL_2425)) { 1116*fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ha); 1117*fcf3ce44SJohn Forte return; 1118*fcf3ce44SJohn Forte } 1119*fcf3ce44SJohn Forte 1120*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1121*fcf3ce44SJohn Forte 1122*fcf3ce44SJohn Forte /* Acquire adapter state lock. */ 1123*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1124*fcf3ce44SJohn Forte 1125*fcf3ce44SJohn Forte /* Calculate number of free receive buffer entries. */ 1126*fcf3ce44SJohn Forte index = RD16_IO_REG(ha, mailbox[8]); 1127*fcf3ce44SJohn Forte do { 1128*fcf3ce44SJohn Forte index1 = RD16_IO_REG(ha, mailbox[8]); 1129*fcf3ce44SJohn Forte if (index1 == index) { 1130*fcf3ce44SJohn Forte break; 1131*fcf3ce44SJohn Forte } else { 1132*fcf3ce44SJohn Forte index = index1; 1133*fcf3ce44SJohn Forte } 1134*fcf3ce44SJohn Forte } while (debounce_count --); 1135*fcf3ce44SJohn Forte 1136*fcf3ce44SJohn Forte if (debounce_count < 0) { 1137*fcf3ce44SJohn Forte /* This should never happen */ 1138*fcf3ce44SJohn Forte EL(ha, "max mb8 debounce retries exceeded\n"); 1139*fcf3ce44SJohn Forte } 1140*fcf3ce44SJohn Forte 1141*fcf3ce44SJohn Forte rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ? 1142*fcf3ce44SJohn Forte index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT - 1143*fcf3ce44SJohn Forte (ha->rcvbuf_ring_index - index)); 1144*fcf3ce44SJohn Forte 1145*fcf3ce44SJohn Forte if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) { 1146*fcf3ce44SJohn Forte rcv_q_cnt--; 1147*fcf3ce44SJohn Forte } 1148*fcf3ce44SJohn Forte 1149*fcf3ce44SJohn Forte /* Load all free buffers in ISP receive buffer ring. */ 1150*fcf3ce44SJohn Forte index = 0; 1151*fcf3ce44SJohn Forte while (rcv_q_cnt >= (uint16_t)0 && index < QL_UB_LIMIT) { 1152*fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1153*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1154*fcf3ce44SJohn Forte while (index < QL_UB_LIMIT) { 1155*fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1156*fcf3ce44SJohn Forte if (ubp != NULL) { 1157*fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1158*fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1159*fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1160*fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1161*fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1162*fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1163*fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1164*fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1165*fcf3ce44SJohn Forte break; 1166*fcf3ce44SJohn Forte } 1167*fcf3ce44SJohn Forte } 1168*fcf3ce44SJohn Forte index++; 1169*fcf3ce44SJohn Forte } 1170*fcf3ce44SJohn Forte 1171*fcf3ce44SJohn Forte if (index < QL_UB_LIMIT) { 1172*fcf3ce44SJohn Forte rcv_q_cnt--; 1173*fcf3ce44SJohn Forte index++; 1174*fcf3ce44SJohn Forte container = ha->rcvbuf_ring_ptr; 1175*fcf3ce44SJohn Forte 1176*fcf3ce44SJohn Forte /* 1177*fcf3ce44SJohn Forte * Build container. 1178*fcf3ce44SJohn Forte */ 1179*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1180*fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[0], 1181*fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1182*fcf3ce44SJohn Forte 1183*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1184*fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[1], 1185*fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1186*fcf3ce44SJohn Forte 1187*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1188*fcf3ce44SJohn Forte LSW(sp->handle)); 1189*fcf3ce44SJohn Forte 1190*fcf3ce44SJohn Forte ha->ub_outcnt++; 1191*fcf3ce44SJohn Forte 1192*fcf3ce44SJohn Forte /* Adjust ring index. */ 1193*fcf3ce44SJohn Forte ha->rcvbuf_ring_index++; 1194*fcf3ce44SJohn Forte if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) { 1195*fcf3ce44SJohn Forte ha->rcvbuf_ring_index = 0; 1196*fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp; 1197*fcf3ce44SJohn Forte } else { 1198*fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr++; 1199*fcf3ce44SJohn Forte } 1200*fcf3ce44SJohn Forte 1201*fcf3ce44SJohn Forte ring_updated = TRUE; 1202*fcf3ce44SJohn Forte } 1203*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1204*fcf3ce44SJohn Forte } 1205*fcf3ce44SJohn Forte 1206*fcf3ce44SJohn Forte if (ring_updated) { 1207*fcf3ce44SJohn Forte /* Sync queue. */ 1208*fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1209*fcf3ce44SJohn Forte (off_t)RCVBUF_Q_BUFFER_OFFSET, (size_t)RCVBUF_QUEUE_SIZE, 1210*fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 1211*fcf3ce44SJohn Forte 1212*fcf3ce44SJohn Forte /* Set chip new ring index. */ 1213*fcf3ce44SJohn Forte WRT16_IO_REG(ha, mailbox[8], ha->rcvbuf_ring_index); 1214*fcf3ce44SJohn Forte } 1215*fcf3ce44SJohn Forte 1216*fcf3ce44SJohn Forte /* Release adapter state lock. */ 1217*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1218*fcf3ce44SJohn Forte 1219*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1220*fcf3ce44SJohn Forte } 1221*fcf3ce44SJohn Forte 1222*fcf3ce44SJohn Forte /* 1223*fcf3ce44SJohn Forte * ql_isp24xx_rcvbuf 1224*fcf3ce44SJohn Forte * Locates free buffers and send it to adapter. 1225*fcf3ce44SJohn Forte * 1226*fcf3ce44SJohn Forte * Input: 1227*fcf3ce44SJohn Forte * ha = adapter state pointer. 1228*fcf3ce44SJohn Forte * 1229*fcf3ce44SJohn Forte * Context: 1230*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1231*fcf3ce44SJohn Forte */ 1232*fcf3ce44SJohn Forte static void 1233*fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ql_adapter_state_t *ha) 1234*fcf3ce44SJohn Forte { 1235*fcf3ce44SJohn Forte rcvbuf_t *container; 1236*fcf3ce44SJohn Forte uint16_t index; 1237*fcf3ce44SJohn Forte ql_srb_t *sp; 1238*fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1239*fcf3ce44SJohn Forte int rval; 1240*fcf3ce44SJohn Forte ip_buf_pool_entry_t *pkt = NULL; 1241*fcf3ce44SJohn Forte 1242*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1243*fcf3ce44SJohn Forte 1244*fcf3ce44SJohn Forte for (;;) { 1245*fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1246*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1247*fcf3ce44SJohn Forte for (index = 0; index < QL_UB_LIMIT; index++) { 1248*fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1249*fcf3ce44SJohn Forte if (ubp != NULL) { 1250*fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1251*fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1252*fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1253*fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1254*fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1255*fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1256*fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1257*fcf3ce44SJohn Forte ha->ub_outcnt++; 1258*fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1259*fcf3ce44SJohn Forte break; 1260*fcf3ce44SJohn Forte } 1261*fcf3ce44SJohn Forte } 1262*fcf3ce44SJohn Forte } 1263*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1264*fcf3ce44SJohn Forte if (index == QL_UB_LIMIT) { 1265*fcf3ce44SJohn Forte break; 1266*fcf3ce44SJohn Forte } 1267*fcf3ce44SJohn Forte 1268*fcf3ce44SJohn Forte /* Get IOCB packet for buffers. */ 1269*fcf3ce44SJohn Forte if (pkt == NULL) { 1270*fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 1271*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1272*fcf3ce44SJohn Forte EL(ha, "failed, ql_req_pkt=%x\n", rval); 1273*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1274*fcf3ce44SJohn Forte ha->ub_outcnt--; 1275*fcf3ce44SJohn Forte sp->flags &= ~SRB_UB_IN_ISP; 1276*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1277*fcf3ce44SJohn Forte break; 1278*fcf3ce44SJohn Forte } 1279*fcf3ce44SJohn Forte pkt->entry_type = IP_BUF_POOL_TYPE; 1280*fcf3ce44SJohn Forte container = &pkt->buffers[0]; 1281*fcf3ce44SJohn Forte } 1282*fcf3ce44SJohn Forte 1283*fcf3ce44SJohn Forte /* 1284*fcf3ce44SJohn Forte * Build container. 1285*fcf3ce44SJohn Forte */ 1286*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[0], 1287*fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1288*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[1], 1289*fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1290*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1291*fcf3ce44SJohn Forte LSW(sp->handle)); 1292*fcf3ce44SJohn Forte 1293*fcf3ce44SJohn Forte pkt->buffer_count++; 1294*fcf3ce44SJohn Forte container++; 1295*fcf3ce44SJohn Forte 1296*fcf3ce44SJohn Forte if (pkt->buffer_count == IP_POOL_BUFFERS) { 1297*fcf3ce44SJohn Forte ql_isp_cmd(ha); 1298*fcf3ce44SJohn Forte pkt = NULL; 1299*fcf3ce44SJohn Forte } 1300*fcf3ce44SJohn Forte } 1301*fcf3ce44SJohn Forte 1302*fcf3ce44SJohn Forte if (pkt != NULL) { 1303*fcf3ce44SJohn Forte ql_isp_cmd(ha); 1304*fcf3ce44SJohn Forte } 1305*fcf3ce44SJohn Forte 1306*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1307*fcf3ce44SJohn Forte } 1308*fcf3ce44SJohn Forte 1309*fcf3ce44SJohn Forte /* 1310*fcf3ce44SJohn Forte * ql_modify_lun 1311*fcf3ce44SJohn Forte * Function enables, modifies or disables ISP to respond as a target. 1312*fcf3ce44SJohn Forte * 1313*fcf3ce44SJohn Forte * Input: 1314*fcf3ce44SJohn Forte * ha = adapter state pointer. 1315*fcf3ce44SJohn Forte * count = number buffers for incoming commands. 1316*fcf3ce44SJohn Forte * 1317*fcf3ce44SJohn Forte * Returns: 1318*fcf3ce44SJohn Forte * ql local function return status code. 1319*fcf3ce44SJohn Forte * 1320*fcf3ce44SJohn Forte * Context: 1321*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1322*fcf3ce44SJohn Forte */ 1323*fcf3ce44SJohn Forte int 1324*fcf3ce44SJohn Forte ql_modify_lun(ql_adapter_state_t *ha) 1325*fcf3ce44SJohn Forte { 1326*fcf3ce44SJohn Forte enable_lun_entry_t *pkt; 1327*fcf3ce44SJohn Forte int rval = QL_SUCCESS; 1328*fcf3ce44SJohn Forte uint32_t index, ubcount; 1329*fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1330*fcf3ce44SJohn Forte 1331*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1332*fcf3ce44SJohn Forte 1333*fcf3ce44SJohn Forte /* 1334*fcf3ce44SJohn Forte * Count the number of SCSI unsolicited buffers, that have been 1335*fcf3ce44SJohn Forte * allocated. 1336*fcf3ce44SJohn Forte */ 1337*fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1338*fcf3ce44SJohn Forte 1339*fcf3ce44SJohn Forte ubp = NULL; 1340*fcf3ce44SJohn Forte ubcount = 0; 1341*fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1342*fcf3ce44SJohn Forte for (index = 0; index < QL_UB_LIMIT; index++) { 1343*fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1344*fcf3ce44SJohn Forte if (ubp != NULL) { 1345*fcf3ce44SJohn Forte ql_srb_t *sp = ubp->ub_fca_private; 1346*fcf3ce44SJohn Forte 1347*fcf3ce44SJohn Forte if (sp->ub_type == FC_TYPE_SCSI_FCP && 1348*fcf3ce44SJohn Forte !(sp->flags & SRB_UB_FREE_REQUESTED)) { 1349*fcf3ce44SJohn Forte ubcount++; 1350*fcf3ce44SJohn Forte } 1351*fcf3ce44SJohn Forte } 1352*fcf3ce44SJohn Forte } 1353*fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1354*fcf3ce44SJohn Forte 1355*fcf3ce44SJohn Forte if (!(ha->flags & TARGET_MODE_INITIALIZED) && (ubcount == 0)) { 1356*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1357*fcf3ce44SJohn Forte return (rval); 1358*fcf3ce44SJohn Forte } 1359*fcf3ce44SJohn Forte 1360*fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 1361*fcf3ce44SJohn Forte 1362*fcf3ce44SJohn Forte if (ha->flags & TARGET_MODE_INITIALIZED) { 1363*fcf3ce44SJohn Forte if (ubcount == 0) { 1364*fcf3ce44SJohn Forte /* Disable the target mode Luns */ 1365*fcf3ce44SJohn Forte ASSERT(ha->ub_command_count != 0); 1366*fcf3ce44SJohn Forte ASSERT(ha->ub_notify_count != 0); 1367*fcf3ce44SJohn Forte 1368*fcf3ce44SJohn Forte ha->flags &= ~(TARGET_MODE_INITIALIZED); 1369*fcf3ce44SJohn Forte 1370*fcf3ce44SJohn Forte ha->ub_command_count = 0; 1371*fcf3ce44SJohn Forte ha->ub_notify_count = 0; 1372*fcf3ce44SJohn Forte 1373*fcf3ce44SJohn Forte pkt->entry_type = ENABLE_LUN_TYPE; 1374*fcf3ce44SJohn Forte pkt->command_count = 0; 1375*fcf3ce44SJohn Forte pkt->immediate_notify_count = 0; 1376*fcf3ce44SJohn Forte 1377*fcf3ce44SJohn Forte } else { 1378*fcf3ce44SJohn Forte /* Modify the command count for target mode */ 1379*fcf3ce44SJohn Forte modify_lun_entry_t *ml_pkt; 1380*fcf3ce44SJohn Forte uint8_t cmd_count, notify_count; 1381*fcf3ce44SJohn Forte 1382*fcf3ce44SJohn Forte ASSERT(ha->ub_command_count != 0); 1383*fcf3ce44SJohn Forte ASSERT(ha->ub_notify_count != 0); 1384*fcf3ce44SJohn Forte 1385*fcf3ce44SJohn Forte /* 1386*fcf3ce44SJohn Forte * calculate the new value of command count 1387*fcf3ce44SJohn Forte * and notify count and then issue the command 1388*fcf3ce44SJohn Forte * to change the values in the firmware. 1389*fcf3ce44SJohn Forte */ 1390*fcf3ce44SJohn Forte ml_pkt = (modify_lun_entry_t *)pkt; 1391*fcf3ce44SJohn Forte ml_pkt->entry_type = MODIFY_LUN_TYPE; 1392*fcf3ce44SJohn Forte if (ubcount < 255) { 1393*fcf3ce44SJohn Forte /* Save one for immediate notify. */ 1394*fcf3ce44SJohn Forte if (ubcount > 1) { 1395*fcf3ce44SJohn Forte cmd_count = (uint8_t)(ubcount - 1); 1396*fcf3ce44SJohn Forte } else { 1397*fcf3ce44SJohn Forte cmd_count = (uint8_t)ubcount; 1398*fcf3ce44SJohn Forte } 1399*fcf3ce44SJohn Forte notify_count = 1; 1400*fcf3ce44SJohn Forte } else { 1401*fcf3ce44SJohn Forte cmd_count = 255; 1402*fcf3ce44SJohn Forte if (ubcount - 255 < 255) { 1403*fcf3ce44SJohn Forte notify_count = (uint8_t) 1404*fcf3ce44SJohn Forte (ubcount - 255); 1405*fcf3ce44SJohn Forte } else { 1406*fcf3ce44SJohn Forte notify_count = 255; 1407*fcf3ce44SJohn Forte } 1408*fcf3ce44SJohn Forte } 1409*fcf3ce44SJohn Forte 1410*fcf3ce44SJohn Forte if (cmd_count > ha->ub_command_count) { 1411*fcf3ce44SJohn Forte /* cmd_count value increased */ 1412*fcf3ce44SJohn Forte ml_pkt->command_count = (uint8_t) 1413*fcf3ce44SJohn Forte (cmd_count - ha->ub_command_count); 1414*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1415*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_0); 1416*fcf3ce44SJohn Forte 1417*fcf3ce44SJohn Forte if (notify_count > ha->ub_notify_count) { 1418*fcf3ce44SJohn Forte ml_pkt->immediate_notify_count = 1419*fcf3ce44SJohn Forte (uint8_t)(notify_count - 1420*fcf3ce44SJohn Forte ha->ub_notify_count); 1421*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1422*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_2); 1423*fcf3ce44SJohn Forte } else if (notify_count < 1424*fcf3ce44SJohn Forte ha->ub_notify_count) { 1425*fcf3ce44SJohn Forte ml_pkt->immediate_notify_count = 1426*fcf3ce44SJohn Forte (uint8_t)(ha->ub_notify_count - 1427*fcf3ce44SJohn Forte notify_count); 1428*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1429*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_3); 1430*fcf3ce44SJohn Forte } 1431*fcf3ce44SJohn Forte } else { 1432*fcf3ce44SJohn Forte /* cmd_count value reduced */ 1433*fcf3ce44SJohn Forte ml_pkt->command_count = (uint8_t) 1434*fcf3ce44SJohn Forte (ha->ub_command_count - cmd_count); 1435*fcf3ce44SJohn Forte if (ml_pkt->command_count != 0) { 1436*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1437*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_1); 1438*fcf3ce44SJohn Forte } 1439*fcf3ce44SJohn Forte if (notify_count > ha->ub_notify_count) { 1440*fcf3ce44SJohn Forte ml_pkt->immediate_notify_count = 1441*fcf3ce44SJohn Forte (uint8_t)(notify_count - 1442*fcf3ce44SJohn Forte ha->ub_notify_count); 1443*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1444*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_2); 1445*fcf3ce44SJohn Forte } else if (notify_count < 1446*fcf3ce44SJohn Forte ha->ub_notify_count) { 1447*fcf3ce44SJohn Forte ml_pkt->immediate_notify_count = 1448*fcf3ce44SJohn Forte (uint8_t)(ha->ub_notify_count - 1449*fcf3ce44SJohn Forte notify_count); 1450*fcf3ce44SJohn Forte ml_pkt->operators = (uint8_t) 1451*fcf3ce44SJohn Forte (ml_pkt->operators | BIT_3); 1452*fcf3ce44SJohn Forte } 1453*fcf3ce44SJohn Forte } 1454*fcf3ce44SJohn Forte 1455*fcf3ce44SJohn Forte /* Update the driver's command/notify count values */ 1456*fcf3ce44SJohn Forte ha->ub_command_count = cmd_count; 1457*fcf3ce44SJohn Forte ha->ub_notify_count = notify_count; 1458*fcf3ce44SJohn Forte } 1459*fcf3ce44SJohn Forte } else { 1460*fcf3ce44SJohn Forte ASSERT(ubcount != 0); 1461*fcf3ce44SJohn Forte 1462*fcf3ce44SJohn Forte /* Enable the Luns for the target mode */ 1463*fcf3ce44SJohn Forte pkt->entry_type = ENABLE_LUN_TYPE; 1464*fcf3ce44SJohn Forte 1465*fcf3ce44SJohn Forte if (ubcount < 255) { 1466*fcf3ce44SJohn Forte /* Save one for immediate notify. */ 1467*fcf3ce44SJohn Forte if (ubcount > 1) { 1468*fcf3ce44SJohn Forte ha->ub_command_count = (uint8_t)(ubcount - 1); 1469*fcf3ce44SJohn Forte } else { 1470*fcf3ce44SJohn Forte ha->ub_command_count = (uint8_t)ubcount; 1471*fcf3ce44SJohn Forte } 1472*fcf3ce44SJohn Forte ha->ub_notify_count = 1; 1473*fcf3ce44SJohn Forte } else { 1474*fcf3ce44SJohn Forte ha->ub_command_count = 255; 1475*fcf3ce44SJohn Forte if (ubcount - 255 < 255) { 1476*fcf3ce44SJohn Forte ha->ub_notify_count = (uint8_t)(ubcount - 255); 1477*fcf3ce44SJohn Forte } else { 1478*fcf3ce44SJohn Forte ha->ub_notify_count = 255; 1479*fcf3ce44SJohn Forte } 1480*fcf3ce44SJohn Forte } 1481*fcf3ce44SJohn Forte ha->flags |= TARGET_MODE_INITIALIZED; 1482*fcf3ce44SJohn Forte 1483*fcf3ce44SJohn Forte pkt->command_count = ha->ub_command_count; 1484*fcf3ce44SJohn Forte pkt->immediate_notify_count = ha->ub_notify_count; 1485*fcf3ce44SJohn Forte } 1486*fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1487*fcf3ce44SJohn Forte 1488*fcf3ce44SJohn Forte /* Issue command to ISP */ 1489*fcf3ce44SJohn Forte ql_isp_cmd(ha); 1490*fcf3ce44SJohn Forte 1491*fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1492*fcf3ce44SJohn Forte EL(ha, "failed=%xh\n", rval); 1493*fcf3ce44SJohn Forte } else { 1494*fcf3ce44SJohn Forte /*EMPTY*/ 1495*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1496*fcf3ce44SJohn Forte } 1497*fcf3ce44SJohn Forte return (rval); 1498*fcf3ce44SJohn Forte } 1499*fcf3ce44SJohn Forte 1500*fcf3ce44SJohn Forte /* 1501*fcf3ce44SJohn Forte * ql_notify_acknowledge_iocb 1502*fcf3ce44SJohn Forte * Setup of notify acknowledge IOCB for pending 1503*fcf3ce44SJohn Forte * immediate notify entry. 1504*fcf3ce44SJohn Forte * 1505*fcf3ce44SJohn Forte * Input: 1506*fcf3ce44SJohn Forte * ha: adapter state pointer. 1507*fcf3ce44SJohn Forte * cmd: target command context pointer. 1508*fcf3ce44SJohn Forte * pkt: request queue packet. 1509*fcf3ce44SJohn Forte * 1510*fcf3ce44SJohn Forte * Context: 1511*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1512*fcf3ce44SJohn Forte */ 1513*fcf3ce44SJohn Forte void 1514*fcf3ce44SJohn Forte ql_notify_acknowledge_iocb(ql_adapter_state_t *ha, tgt_cmd_t *cmd, 1515*fcf3ce44SJohn Forte notify_acknowledge_entry_t *pkt) 1516*fcf3ce44SJohn Forte { 1517*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1518*fcf3ce44SJohn Forte 1519*fcf3ce44SJohn Forte pkt->entry_type = NOTIFY_ACKNOWLEDGE_TYPE; 1520*fcf3ce44SJohn Forte pkt->initiator_id_l = cmd->initiator_id_l; 1521*fcf3ce44SJohn Forte pkt->initiator_id_h = cmd->initiator_id_h; 1522*fcf3ce44SJohn Forte 1523*fcf3ce44SJohn Forte /* Handle LIP reset event. */ 1524*fcf3ce44SJohn Forte if (cmd->status == 0xe) { 1525*fcf3ce44SJohn Forte pkt->flags_l = BIT_5; 1526*fcf3ce44SJohn Forte } 1527*fcf3ce44SJohn Forte 1528*fcf3ce44SJohn Forte pkt->flags_h = BIT_0; 1529*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->status, cmd->status); 1530*fcf3ce44SJohn Forte pkt->task_flags_l = cmd->task_flags_l; 1531*fcf3ce44SJohn Forte pkt->task_flags_h = cmd->task_flags_h; 1532*fcf3ce44SJohn Forte pkt->sequence_id = cmd->rx_id; 1533*fcf3ce44SJohn Forte 1534*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1535*fcf3ce44SJohn Forte } 1536*fcf3ce44SJohn Forte 1537*fcf3ce44SJohn Forte /* 1538*fcf3ce44SJohn Forte * ql_continue_target_io_iocb 1539*fcf3ce44SJohn Forte * Setup of continue target I/O IOCB for pending 1540*fcf3ce44SJohn Forte * accept target I/O entry. 1541*fcf3ce44SJohn Forte * 1542*fcf3ce44SJohn Forte * Input: 1543*fcf3ce44SJohn Forte * ha = adapter state pointer. 1544*fcf3ce44SJohn Forte * sp = srb structure pointer. 1545*fcf3ce44SJohn Forte * arg = request queue packet. 1546*fcf3ce44SJohn Forte * 1547*fcf3ce44SJohn Forte * Context: 1548*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1549*fcf3ce44SJohn Forte */ 1550*fcf3ce44SJohn Forte void 1551*fcf3ce44SJohn Forte ql_continue_target_io_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1552*fcf3ce44SJohn Forte { 1553*fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1554*fcf3ce44SJohn Forte port_id_t d_id; 1555*fcf3ce44SJohn Forte ql_tgt_t *tq; 1556*fcf3ce44SJohn Forte ctio_entry_t *pkt = arg; 1557*fcf3ce44SJohn Forte 1558*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1559*fcf3ce44SJohn Forte 1560*fcf3ce44SJohn Forte d_id.b24 = sp->pkt->pkt_cmd_fhdr.d_id; 1561*fcf3ce44SJohn Forte tq = ql_d_id_to_queue(ha, d_id); 1562*fcf3ce44SJohn Forte 1563*fcf3ce44SJohn Forte if (tq == NULL) { 1564*fcf3ce44SJohn Forte EL(ha, "Unknown Initiator d_id %xh", d_id.b24); 1565*fcf3ce44SJohn Forte return; 1566*fcf3ce44SJohn Forte } 1567*fcf3ce44SJohn Forte 1568*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 1569*fcf3ce44SJohn Forte pkt->initiator_id_l = LSB(tq->loop_id); 1570*fcf3ce44SJohn Forte pkt->initiator_id_h = MSB(tq->loop_id); 1571*fcf3ce44SJohn Forte } else { 1572*fcf3ce44SJohn Forte pkt->initiator_id_h = LSB(tq->loop_id); 1573*fcf3ce44SJohn Forte } 1574*fcf3ce44SJohn Forte pkt->rx_id = sp->pkt->pkt_cmd_fhdr.rx_id; 1575*fcf3ce44SJohn Forte 1576*fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1577*fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 1578*fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, 1579*fcf3ce44SJohn Forte sp->isp_timeout); 1580*fcf3ce44SJohn Forte } 1581*fcf3ce44SJohn Forte 1582*fcf3ce44SJohn Forte if (sp->flags & SRB_FCP_DATA_PKT) { 1583*fcf3ce44SJohn Forte 1584*fcf3ce44SJohn Forte if (sp->pkt->pkt_tran_type == FC_PKT_OUTBOUND) { 1585*fcf3ce44SJohn Forte pkt->flags_l = BIT_6; 1586*fcf3ce44SJohn Forte } else if (sp->pkt->pkt_tran_type == FC_PKT_INBOUND) { 1587*fcf3ce44SJohn Forte pkt->flags_l = BIT_7; 1588*fcf3ce44SJohn Forte } 1589*fcf3ce44SJohn Forte 1590*fcf3ce44SJohn Forte pkt->flags_h = BIT_1; 1591*fcf3ce44SJohn Forte /* Set relative offset. */ 1592*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1593*fcf3ce44SJohn Forte (uint32_t *)(void *)&pkt->relative_offset, 1594*fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmd_fhdr.ro); 1595*fcf3ce44SJohn Forte } else { 1596*fcf3ce44SJohn Forte /* (sp->flags & SRB_FCP_RSP_PKT) */ 1597*fcf3ce44SJohn Forte pkt->flags_l = BIT_7 | BIT_6 | BIT_1; 1598*fcf3ce44SJohn Forte pkt->flags_h = BIT_7 | BIT_1; 1599*fcf3ce44SJohn Forte } 1600*fcf3ce44SJohn Forte 1601*fcf3ce44SJohn Forte /* 1602*fcf3ce44SJohn Forte * Load data segments. 1603*fcf3ce44SJohn Forte */ 1604*fcf3ce44SJohn Forte if (sp->pkt->pkt_cmdlen != 0) { 1605*fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1606*fcf3ce44SJohn Forte 1607*fcf3ce44SJohn Forte /* Transfer length. */ 1608*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1609*fcf3ce44SJohn Forte (uint32_t *)(void *)&pkt->type.s0_32bit.byte_count, 1610*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1611*fcf3ce44SJohn Forte 1612*fcf3ce44SJohn Forte /* Load data segments. */ 1613*fcf3ce44SJohn Forte pkt->dseg_count_l = 1; 1614*fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1615*fcf3ce44SJohn Forte pkt->entry_type = CTIO_TYPE_3; 1616*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1617*fcf3ce44SJohn Forte (uint32_t *)(void *) 1618*fcf3ce44SJohn Forte &pkt->type.s0_64bit.dseg_0_address[0], 1619*fcf3ce44SJohn Forte cp->dmac_address); 1620*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1621*fcf3ce44SJohn Forte (uint32_t *)(void *) 1622*fcf3ce44SJohn Forte &pkt->type.s0_64bit.dseg_0_address[1], 1623*fcf3ce44SJohn Forte cp->dmac_notused); 1624*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1625*fcf3ce44SJohn Forte (uint32_t *)(void *) 1626*fcf3ce44SJohn Forte &pkt->type.s0_64bit.dseg_0_length, 1627*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1628*fcf3ce44SJohn Forte } else { 1629*fcf3ce44SJohn Forte pkt->entry_type = CTIO_TYPE_2; 1630*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1631*fcf3ce44SJohn Forte (uint32_t *)(void *) 1632*fcf3ce44SJohn Forte &pkt->type.s0_32bit.dseg_0_address, 1633*fcf3ce44SJohn Forte cp->dmac_address); 1634*fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1635*fcf3ce44SJohn Forte (uint32_t *)(void *) 1636*fcf3ce44SJohn Forte &pkt->type.s0_32bit.dseg_0_length, 1637*fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1638*fcf3ce44SJohn Forte } 1639*fcf3ce44SJohn Forte } 1640*fcf3ce44SJohn Forte 1641*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1642*fcf3ce44SJohn Forte } 1643*fcf3ce44SJohn Forte 1644*fcf3ce44SJohn Forte /* 1645*fcf3ce44SJohn Forte * ql_continue_target_io_2400_iocb 1646*fcf3ce44SJohn Forte * Setup of continue target I/O IOCB for pending 1647*fcf3ce44SJohn Forte * accept target I/O entry. 1648*fcf3ce44SJohn Forte * 1649*fcf3ce44SJohn Forte * Input: 1650*fcf3ce44SJohn Forte * ha = adapter state pointer. 1651*fcf3ce44SJohn Forte * sp = srb structure pointer. 1652*fcf3ce44SJohn Forte * arg = request queue packet. 1653*fcf3ce44SJohn Forte * 1654*fcf3ce44SJohn Forte * Context: 1655*fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1656*fcf3ce44SJohn Forte */ 1657*fcf3ce44SJohn Forte /* ARGSUSED */ 1658*fcf3ce44SJohn Forte void 1659*fcf3ce44SJohn Forte ql_continue_target_io_2400_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, 1660*fcf3ce44SJohn Forte void *arg) 1661*fcf3ce44SJohn Forte { 1662*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1663*fcf3ce44SJohn Forte 1664*fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1665*fcf3ce44SJohn Forte } 1666