1fcf3ce44SJohn Forte /* 2fcf3ce44SJohn Forte * CDDL HEADER START 3fcf3ce44SJohn Forte * 4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the 5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License"). 6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License. 7fcf3ce44SJohn Forte * 8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing. 10fcf3ce44SJohn Forte * See the License for the specific language governing permissions 11fcf3ce44SJohn Forte * and limitations under the License. 12fcf3ce44SJohn Forte * 13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each 14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the 16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying 17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner] 18fcf3ce44SJohn Forte * 19fcf3ce44SJohn Forte * CDDL HEADER END 20fcf3ce44SJohn Forte */ 21fcf3ce44SJohn Forte 22*eb82ff87SDaniel Beauregard /* Copyright 2010 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 29*eb82ff87SDaniel Beauregard #pragma ident "Copyright 2010 QLogic Corporation; ql_iocb.c" 30fcf3ce44SJohn Forte 31fcf3ce44SJohn Forte /* 32fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 33fcf3ce44SJohn Forte * 34fcf3ce44SJohn Forte * *********************************************************************** 35fcf3ce44SJohn Forte * * ** 36fcf3ce44SJohn Forte * * NOTICE ** 37*eb82ff87SDaniel Beauregard * * COPYRIGHT (C) 1996-2010 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_xioctl.h> 50fcf3ce44SJohn Forte 51fcf3ce44SJohn Forte /* 52fcf3ce44SJohn Forte * Local Function Prototypes. 53fcf3ce44SJohn Forte */ 545dfd244aSDaniel Beauregard static int ql_req_pkt(ql_adapter_state_t *, request_t **); 55fcf3ce44SJohn Forte static void ql_continuation_iocb(ql_adapter_state_t *, ddi_dma_cookie_t *, 56fcf3ce44SJohn Forte uint16_t, boolean_t); 57fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *); 58fcf3ce44SJohn Forte 59fcf3ce44SJohn Forte /* 60fcf3ce44SJohn Forte * ql_start_iocb 61fcf3ce44SJohn Forte * The start IOCB is responsible for building request packets 62fcf3ce44SJohn Forte * on request ring and modifying ISP input pointer. 63fcf3ce44SJohn Forte * 64fcf3ce44SJohn Forte * Input: 65fcf3ce44SJohn Forte * ha: adapter state pointer. 66fcf3ce44SJohn Forte * sp: srb structure pointer. 67fcf3ce44SJohn Forte * 68fcf3ce44SJohn Forte * Context: 69fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 70fcf3ce44SJohn Forte */ 71fcf3ce44SJohn Forte void 72fcf3ce44SJohn Forte ql_start_iocb(ql_adapter_state_t *vha, ql_srb_t *sp) 73fcf3ce44SJohn Forte { 74fcf3ce44SJohn Forte ql_link_t *link; 75fcf3ce44SJohn Forte request_t *pkt; 76fcf3ce44SJohn Forte uint64_t *ptr64; 77fcf3ce44SJohn Forte uint32_t cnt; 78fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 79fcf3ce44SJohn Forte 80fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 81fcf3ce44SJohn Forte 82fcf3ce44SJohn Forte /* Acquire ring lock. */ 83fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 84fcf3ce44SJohn Forte 85fcf3ce44SJohn Forte if (sp != NULL) { 86fcf3ce44SJohn Forte /* 8716dd44c2SDaniel Beauregard * If the pending queue is not empty maintain order 8816dd44c2SDaniel Beauregard * by puting this srb at the tail and geting the head. 89fcf3ce44SJohn Forte */ 90fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) != NULL) { 91fcf3ce44SJohn Forte ql_add_link_b(&ha->pending_cmds, &sp->cmd); 92fcf3ce44SJohn Forte /* Remove command from pending command queue */ 93fcf3ce44SJohn Forte sp = link->base_address; 94fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 95fcf3ce44SJohn Forte } 96fcf3ce44SJohn Forte } else { 97fcf3ce44SJohn Forte /* Get command from pending command queue if not empty. */ 98fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) == NULL) { 99fcf3ce44SJohn Forte /* Release ring specific lock */ 100fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 101fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): empty done\n", 102fcf3ce44SJohn Forte ha->instance); 103fcf3ce44SJohn Forte return; 104fcf3ce44SJohn Forte } 105fcf3ce44SJohn Forte /* Remove command from pending command queue */ 106fcf3ce44SJohn Forte sp = link->base_address; 107fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 108fcf3ce44SJohn Forte } 109fcf3ce44SJohn Forte 11016dd44c2SDaniel Beauregard /* start this request and as many others as possible */ 111fcf3ce44SJohn Forte for (;;) { 112fcf3ce44SJohn Forte if (ha->req_q_cnt < sp->req_cnt) { 113fcf3ce44SJohn Forte /* Calculate number of free request entries. */ 114fcf3ce44SJohn Forte cnt = RD16_IO_REG(ha, req_out); 115fcf3ce44SJohn Forte if (ha->req_ring_index < cnt) { 116fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 117fcf3ce44SJohn Forte (cnt - ha->req_ring_index); 118fcf3ce44SJohn Forte } else { 119fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t)(REQUEST_ENTRY_CNT - 120fcf3ce44SJohn Forte (ha->req_ring_index - cnt)); 121fcf3ce44SJohn Forte } 122fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 123fcf3ce44SJohn Forte ha->req_q_cnt--; 124fcf3ce44SJohn Forte } 125fcf3ce44SJohn Forte 12616dd44c2SDaniel Beauregard /* 12716dd44c2SDaniel Beauregard * If no room in request ring put this srb at 12816dd44c2SDaniel Beauregard * the head of the pending queue and exit. 12916dd44c2SDaniel Beauregard */ 130fcf3ce44SJohn Forte if (ha->req_q_cnt < sp->req_cnt) { 131fcf3ce44SJohn Forte QL_PRINT_8(CE_CONT, "(%d): request ring full," 132fcf3ce44SJohn Forte " req_q_cnt=%d, req_ring_index=%d\n", 133fcf3ce44SJohn Forte ha->instance, ha->req_q_cnt, 134fcf3ce44SJohn Forte ha->req_ring_index); 135fcf3ce44SJohn Forte ql_add_link_t(&ha->pending_cmds, &sp->cmd); 136fcf3ce44SJohn Forte break; 137fcf3ce44SJohn Forte } 138fcf3ce44SJohn Forte } 139fcf3ce44SJohn Forte 140fcf3ce44SJohn Forte /* Check for room in outstanding command list. */ 141fcf3ce44SJohn Forte for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) { 142fcf3ce44SJohn Forte ha->osc_index++; 143fcf3ce44SJohn Forte if (ha->osc_index == MAX_OUTSTANDING_COMMANDS) { 144fcf3ce44SJohn Forte ha->osc_index = 1; 145fcf3ce44SJohn Forte } 146fcf3ce44SJohn Forte if (ha->outstanding_cmds[ha->osc_index] == NULL) { 147fcf3ce44SJohn Forte break; 148fcf3ce44SJohn Forte } 149fcf3ce44SJohn Forte } 15016dd44c2SDaniel Beauregard /* 15116dd44c2SDaniel Beauregard * If no room in outstanding array put this srb at 15216dd44c2SDaniel Beauregard * the head of the pending queue and exit. 15316dd44c2SDaniel Beauregard */ 154fcf3ce44SJohn Forte if (cnt == MAX_OUTSTANDING_COMMANDS) { 155fcf3ce44SJohn Forte QL_PRINT_8(CE_CONT, "(%d): no room in outstanding " 156fcf3ce44SJohn Forte "array\n", ha->instance); 157fcf3ce44SJohn Forte ql_add_link_t(&ha->pending_cmds, &sp->cmd); 158fcf3ce44SJohn Forte break; 159fcf3ce44SJohn Forte } 160fcf3ce44SJohn Forte 16116dd44c2SDaniel Beauregard /* nothing to stop us now. */ 162fcf3ce44SJohn Forte ha->outstanding_cmds[ha->osc_index] = sp; 16316dd44c2SDaniel Beauregard /* create and save a unique response identifier in the srb */ 164fcf3ce44SJohn Forte sp->handle = ha->adapter_stats->ncmds << OSC_INDEX_SHIFT | 165fcf3ce44SJohn Forte ha->osc_index; 166fcf3ce44SJohn Forte ha->req_q_cnt -= sp->req_cnt; 16716dd44c2SDaniel Beauregard 16816dd44c2SDaniel Beauregard /* build the iocb in the request ring */ 169fcf3ce44SJohn Forte pkt = ha->request_ring_ptr; 170fcf3ce44SJohn Forte sp->flags |= SRB_IN_TOKEN_ARRAY; 171fcf3ce44SJohn Forte 172fcf3ce44SJohn Forte /* Zero out packet. */ 173fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 174fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 175fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 176fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 177fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 178fcf3ce44SJohn Forte 179fcf3ce44SJohn Forte /* Setup IOCB common data. */ 180fcf3ce44SJohn Forte pkt->entry_count = (uint8_t)sp->req_cnt; 181fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 18216dd44c2SDaniel Beauregard /* mark the iocb with the response identifier */ 183fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->handle, 184fcf3ce44SJohn Forte (uint32_t)sp->handle); 185fcf3ce44SJohn Forte 18616dd44c2SDaniel Beauregard /* Setup IOCB unique data. */ 187fcf3ce44SJohn Forte (sp->iocb)(vha, sp, pkt); 188fcf3ce44SJohn Forte 189fcf3ce44SJohn Forte sp->flags |= SRB_ISP_STARTED; 190fcf3ce44SJohn Forte 191fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d,%d): req packet, sp=%p\n", 192fcf3ce44SJohn Forte ha->instance, vha->vp_index, (void *)sp); 193fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 194fcf3ce44SJohn Forte 195fcf3ce44SJohn Forte /* Sync DMA buffer. */ 196fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 197fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 198fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 199fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 200fcf3ce44SJohn Forte 201fcf3ce44SJohn Forte /* Adjust ring index. */ 202fcf3ce44SJohn Forte ha->req_ring_index++; 203fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 204fcf3ce44SJohn Forte ha->req_ring_index = 0; 205fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 206fcf3ce44SJohn Forte } else { 207fcf3ce44SJohn Forte ha->request_ring_ptr++; 208fcf3ce44SJohn Forte } 209fcf3ce44SJohn Forte 210fcf3ce44SJohn Forte /* Reset watchdog timer */ 211fcf3ce44SJohn Forte sp->wdg_q_time = sp->init_wdg_q_time; 212fcf3ce44SJohn Forte 21316dd44c2SDaniel Beauregard /* 21416dd44c2SDaniel Beauregard * Send it by setting the new ring index in the ISP Request 21516dd44c2SDaniel Beauregard * Ring In Pointer register. This is the mechanism 21616dd44c2SDaniel Beauregard * used to notify the isp that a new iocb has been 21716dd44c2SDaniel Beauregard * placed on the request ring. 21816dd44c2SDaniel Beauregard */ 219*eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 220*eb82ff87SDaniel Beauregard uint32_t w32; 221*eb82ff87SDaniel Beauregard 222*eb82ff87SDaniel Beauregard w32 = ha->req_ring_index << 16 | 223*eb82ff87SDaniel Beauregard ha->function_number << 5 | 4; 224*eb82ff87SDaniel Beauregard do { 225*eb82ff87SDaniel Beauregard ddi_put32(ha->db_dev_handle, ha->nx_req_in, 226*eb82ff87SDaniel Beauregard w32); 227*eb82ff87SDaniel Beauregard } while (RD_REG_DWORD(ha, ha->db_read) != w32); 228*eb82ff87SDaniel Beauregard 229*eb82ff87SDaniel Beauregard } else { 230*eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, req_in, ha->req_ring_index); 231*eb82ff87SDaniel Beauregard } 232fcf3ce44SJohn Forte 233fcf3ce44SJohn Forte /* Update outstanding command count statistic. */ 234fcf3ce44SJohn Forte ha->adapter_stats->ncmds++; 235fcf3ce44SJohn Forte 23616dd44c2SDaniel Beauregard /* if there is a pending command, try to start it. */ 237fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) == NULL) { 238fcf3ce44SJohn Forte break; 239fcf3ce44SJohn Forte } 240fcf3ce44SJohn Forte 241fcf3ce44SJohn Forte /* Remove command from pending command queue */ 242fcf3ce44SJohn Forte sp = link->base_address; 243fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 244fcf3ce44SJohn Forte } 245fcf3ce44SJohn Forte 246fcf3ce44SJohn Forte /* Release ring specific lock */ 247fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 248fcf3ce44SJohn Forte 249fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 250fcf3ce44SJohn Forte } 251fcf3ce44SJohn Forte 252fcf3ce44SJohn Forte /* 253fcf3ce44SJohn Forte * ql_req_pkt 254fcf3ce44SJohn Forte * Function is responsible for locking ring and 255fcf3ce44SJohn Forte * getting a zeroed out request packet. 256fcf3ce44SJohn Forte * 257fcf3ce44SJohn Forte * Input: 258fcf3ce44SJohn Forte * ha: adapter state pointer. 259fcf3ce44SJohn Forte * pkt: address for packet pointer. 260fcf3ce44SJohn Forte * 261fcf3ce44SJohn Forte * Returns: 262fcf3ce44SJohn Forte * ql local function return status code. 263fcf3ce44SJohn Forte * 264fcf3ce44SJohn Forte * Context: 265fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 266fcf3ce44SJohn Forte */ 2675dfd244aSDaniel Beauregard static int 268fcf3ce44SJohn Forte ql_req_pkt(ql_adapter_state_t *vha, request_t **pktp) 269fcf3ce44SJohn Forte { 270fcf3ce44SJohn Forte uint16_t cnt; 271fcf3ce44SJohn Forte uint32_t *long_ptr; 272fcf3ce44SJohn Forte uint32_t timer; 273fcf3ce44SJohn Forte int rval = QL_FUNCTION_TIMEOUT; 274fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 275fcf3ce44SJohn Forte 276fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 277fcf3ce44SJohn Forte 278fcf3ce44SJohn Forte /* Wait for 30 seconds for slot. */ 279fcf3ce44SJohn Forte for (timer = 30000; timer != 0; timer--) { 280fcf3ce44SJohn Forte /* Acquire ring lock. */ 281fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 282fcf3ce44SJohn Forte 283fcf3ce44SJohn Forte if (ha->req_q_cnt == 0) { 284fcf3ce44SJohn Forte /* Calculate number of free request entries. */ 285fcf3ce44SJohn Forte cnt = RD16_IO_REG(ha, req_out); 286fcf3ce44SJohn Forte if (ha->req_ring_index < cnt) { 287fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 288fcf3ce44SJohn Forte (cnt - ha->req_ring_index); 289fcf3ce44SJohn Forte } else { 290fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 291fcf3ce44SJohn Forte (REQUEST_ENTRY_CNT - 292fcf3ce44SJohn Forte (ha->req_ring_index - cnt)); 293fcf3ce44SJohn Forte } 294fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 295fcf3ce44SJohn Forte ha->req_q_cnt--; 296fcf3ce44SJohn Forte } 297fcf3ce44SJohn Forte } 298fcf3ce44SJohn Forte 299fcf3ce44SJohn Forte /* Found empty request ring slot? */ 300fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 301fcf3ce44SJohn Forte ha->req_q_cnt--; 302fcf3ce44SJohn Forte *pktp = ha->request_ring_ptr; 303fcf3ce44SJohn Forte 304fcf3ce44SJohn Forte /* Zero out packet. */ 305fcf3ce44SJohn Forte long_ptr = (uint32_t *)ha->request_ring_ptr; 306fcf3ce44SJohn Forte for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) { 307fcf3ce44SJohn Forte *long_ptr++ = 0; 308fcf3ce44SJohn Forte } 309fcf3ce44SJohn Forte 310fcf3ce44SJohn Forte /* Setup IOCB common data. */ 311fcf3ce44SJohn Forte ha->request_ring_ptr->entry_count = 1; 312fcf3ce44SJohn Forte ha->request_ring_ptr->sys_define = 313fcf3ce44SJohn Forte (uint8_t)ha->req_ring_index; 314fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 315fcf3ce44SJohn Forte &ha->request_ring_ptr->handle, 316fcf3ce44SJohn Forte (uint32_t)QL_FCA_BRAND); 317fcf3ce44SJohn Forte 318fcf3ce44SJohn Forte rval = QL_SUCCESS; 319fcf3ce44SJohn Forte 320fcf3ce44SJohn Forte break; 321fcf3ce44SJohn Forte } 322fcf3ce44SJohn Forte 323fcf3ce44SJohn Forte /* Release request queue lock. */ 324fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 325fcf3ce44SJohn Forte 326fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 327fcf3ce44SJohn Forte 328fcf3ce44SJohn Forte /* Check for pending interrupts. */ 329fcf3ce44SJohn Forte /* 330fcf3ce44SJohn Forte * XXX protect interrupt routine from calling itself. 331fcf3ce44SJohn Forte * Need to revisit this routine. So far we never 332fcf3ce44SJohn Forte * hit this case as req slot was available 333fcf3ce44SJohn Forte */ 334fcf3ce44SJohn Forte if ((!(curthread->t_flag & T_INTR_THREAD)) && 335*eb82ff87SDaniel Beauregard INTERRUPT_PENDING(ha)) { 336fcf3ce44SJohn Forte (void) ql_isr((caddr_t)ha); 337fcf3ce44SJohn Forte INTR_LOCK(ha); 338fcf3ce44SJohn Forte ha->intr_claimed = TRUE; 339fcf3ce44SJohn Forte INTR_UNLOCK(ha); 340fcf3ce44SJohn Forte } 341fcf3ce44SJohn Forte } 342fcf3ce44SJohn Forte 343fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 344fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0); 345fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval); 346fcf3ce44SJohn Forte } else { 347fcf3ce44SJohn Forte /*EMPTY*/ 348fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 349fcf3ce44SJohn Forte } 350fcf3ce44SJohn Forte return (rval); 351fcf3ce44SJohn Forte } 352fcf3ce44SJohn Forte 353fcf3ce44SJohn Forte /* 354fcf3ce44SJohn Forte * ql_isp_cmd 355fcf3ce44SJohn Forte * Function is responsible for modifying ISP input pointer. 35616dd44c2SDaniel Beauregard * This action notifies the isp that a new request has been 35716dd44c2SDaniel Beauregard * added to the request ring. 35816dd44c2SDaniel Beauregard * 359fcf3ce44SJohn Forte * Releases ring lock. 360fcf3ce44SJohn Forte * 361fcf3ce44SJohn Forte * Input: 362fcf3ce44SJohn Forte * ha: adapter state pointer. 363fcf3ce44SJohn Forte * 364fcf3ce44SJohn Forte * Context: 365fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 366fcf3ce44SJohn Forte */ 367fcf3ce44SJohn Forte void 368fcf3ce44SJohn Forte ql_isp_cmd(ql_adapter_state_t *vha) 369fcf3ce44SJohn Forte { 370fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 371fcf3ce44SJohn Forte 372fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 373fcf3ce44SJohn Forte 374fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): req packet:\n", ha->instance); 375fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)ha->request_ring_ptr, 8, REQUEST_ENTRY_SIZE); 376fcf3ce44SJohn Forte 377fcf3ce44SJohn Forte /* Sync DMA buffer. */ 378fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 379fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 380fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 381fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 382fcf3ce44SJohn Forte 383fcf3ce44SJohn Forte /* Adjust ring index. */ 384fcf3ce44SJohn Forte ha->req_ring_index++; 385fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 386fcf3ce44SJohn Forte ha->req_ring_index = 0; 387fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 388fcf3ce44SJohn Forte } else { 389fcf3ce44SJohn Forte ha->request_ring_ptr++; 390fcf3ce44SJohn Forte } 391fcf3ce44SJohn Forte 392fcf3ce44SJohn Forte /* Set chip new ring index. */ 393*eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 394*eb82ff87SDaniel Beauregard uint32_t w32; 395*eb82ff87SDaniel Beauregard 396*eb82ff87SDaniel Beauregard w32 = ha->req_ring_index << 16 | 397*eb82ff87SDaniel Beauregard ha->function_number << 5 | 4; 398*eb82ff87SDaniel Beauregard do { 399*eb82ff87SDaniel Beauregard ddi_put32(ha->db_dev_handle, ha->nx_req_in, w32); 400*eb82ff87SDaniel Beauregard } while (RD_REG_DWORD(ha, ha->db_read) != w32); 401*eb82ff87SDaniel Beauregard 402*eb82ff87SDaniel Beauregard } else { 403*eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, req_in, ha->req_ring_index); 404*eb82ff87SDaniel Beauregard } 405fcf3ce44SJohn Forte 406fcf3ce44SJohn Forte /* Release ring lock. */ 407fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 408fcf3ce44SJohn Forte 409fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 410fcf3ce44SJohn Forte } 411fcf3ce44SJohn Forte 412fcf3ce44SJohn Forte /* 413fcf3ce44SJohn Forte * ql_command_iocb 414fcf3ce44SJohn Forte * Setup of command IOCB. 415fcf3ce44SJohn Forte * 416fcf3ce44SJohn Forte * Input: 417fcf3ce44SJohn Forte * ha: adapter state pointer. 418fcf3ce44SJohn Forte * sp: srb structure pointer. 419fcf3ce44SJohn Forte * 420fcf3ce44SJohn Forte * arg: request queue packet. 421fcf3ce44SJohn Forte * 422fcf3ce44SJohn Forte * Context: 423fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 424fcf3ce44SJohn Forte */ 425fcf3ce44SJohn Forte void 426fcf3ce44SJohn Forte ql_command_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 427fcf3ce44SJohn Forte { 428fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 429fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 430fcf3ce44SJohn Forte uint16_t seg_cnt; 431fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 432fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 433fcf3ce44SJohn Forte cmd_entry_t *pkt = arg; 434fcf3ce44SJohn Forte 435fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 436fcf3ce44SJohn Forte 437fcf3ce44SJohn Forte /* Set LUN number */ 438fcf3ce44SJohn Forte pkt->lun_l = LSB(sp->lun_queue->lun_no); 439fcf3ce44SJohn Forte pkt->lun_h = MSB(sp->lun_queue->lun_no); 440fcf3ce44SJohn Forte 441fcf3ce44SJohn Forte /* Set target ID */ 442fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 443fcf3ce44SJohn Forte pkt->target_l = LSB(tq->loop_id); 444fcf3ce44SJohn Forte pkt->target_h = MSB(tq->loop_id); 445fcf3ce44SJohn Forte } else { 446fcf3ce44SJohn Forte pkt->target_h = LSB(tq->loop_id); 447fcf3ce44SJohn Forte } 448fcf3ce44SJohn Forte 449fcf3ce44SJohn Forte /* Set tag queue control flags */ 450fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) { 451fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 452fcf3ce44SJohn Forte (pkt->control_flags_l | CF_HTAG); 453fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) { 454fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 455fcf3ce44SJohn Forte (pkt->control_flags_l | CF_OTAG); 456fcf3ce44SJohn Forte /* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */ 457fcf3ce44SJohn Forte } else { 458fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 459fcf3ce44SJohn Forte (pkt->control_flags_l | CF_STAG); 460fcf3ce44SJohn Forte } 461fcf3ce44SJohn Forte 462fcf3ce44SJohn Forte /* Set ISP command timeout. */ 463fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 464fcf3ce44SJohn Forte 465fcf3ce44SJohn Forte /* Load SCSI CDB */ 466fcf3ce44SJohn Forte ddi_rep_put8(ha->hba_buf.acc_handle, fcp->fcp_cdb, 467fcf3ce44SJohn Forte pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR); 468fcf3ce44SJohn Forte 469fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 470fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_3; 471fcf3ce44SJohn Forte cnt = CMD_TYPE_3_DATA_SEGMENTS; 472fcf3ce44SJohn Forte } else { 473fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_2; 474fcf3ce44SJohn Forte cnt = CMD_TYPE_2_DATA_SEGMENTS; 475fcf3ce44SJohn Forte } 476fcf3ce44SJohn Forte 477fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 478fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 479fcf3ce44SJohn Forte ha->xioctl->IOControlRequests++; 480fcf3ce44SJohn Forte return; 481fcf3ce44SJohn Forte } 482fcf3ce44SJohn Forte 483fcf3ce44SJohn Forte /* 484fcf3ce44SJohn Forte * Set transfer direction. Load Data segments. 485fcf3ce44SJohn Forte */ 486fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 487fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 488fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_OUT); 489fcf3ce44SJohn Forte ha->xioctl->IOOutputRequests++; 490fcf3ce44SJohn Forte ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 491fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 492fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 493fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_IN); 494fcf3ce44SJohn Forte ha->xioctl->IOInputRequests++; 495fcf3ce44SJohn Forte ha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 496fcf3ce44SJohn Forte } 497fcf3ce44SJohn Forte 498fcf3ce44SJohn Forte /* Set data segment count. */ 499fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 500fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 501fcf3ce44SJohn Forte 502fcf3ce44SJohn Forte /* Load total byte count. */ 503fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, fcp->fcp_data_len); 504fcf3ce44SJohn Forte 505fcf3ce44SJohn Forte /* Load command data segment. */ 506fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 507fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 508fcf3ce44SJohn Forte while (cnt && seg_cnt) { 509fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 510fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 511fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 512fcf3ce44SJohn Forte cp->dmac_notused); 513fcf3ce44SJohn Forte } 514fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 515fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 516fcf3ce44SJohn Forte seg_cnt--; 517fcf3ce44SJohn Forte cnt--; 518fcf3ce44SJohn Forte cp++; 519fcf3ce44SJohn Forte } 520fcf3ce44SJohn Forte 521fcf3ce44SJohn Forte /* 522fcf3ce44SJohn Forte * Build continuation packets. 523fcf3ce44SJohn Forte */ 524fcf3ce44SJohn Forte if (seg_cnt) { 525fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 526fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 527fcf3ce44SJohn Forte } 528fcf3ce44SJohn Forte 529fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 530fcf3ce44SJohn Forte } 531fcf3ce44SJohn Forte 532fcf3ce44SJohn Forte /* 533fcf3ce44SJohn Forte * ql_continuation_iocb 534fcf3ce44SJohn Forte * Setup of continuation IOCB. 535fcf3ce44SJohn Forte * 536fcf3ce44SJohn Forte * Input: 537fcf3ce44SJohn Forte * ha: adapter state pointer. 538fcf3ce44SJohn Forte * cp: cookie list pointer. 539fcf3ce44SJohn Forte * seg_cnt: number of segments. 540fcf3ce44SJohn Forte * addr64: 64 bit addresses. 541fcf3ce44SJohn Forte * 542fcf3ce44SJohn Forte * Context: 543fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 544fcf3ce44SJohn Forte */ 545fcf3ce44SJohn Forte static void 546fcf3ce44SJohn Forte ql_continuation_iocb(ql_adapter_state_t *ha, ddi_dma_cookie_t *cp, 547fcf3ce44SJohn Forte uint16_t seg_cnt, boolean_t addr64) 548fcf3ce44SJohn Forte { 549fcf3ce44SJohn Forte cont_entry_t *pkt; 550fcf3ce44SJohn Forte uint64_t *ptr64; 551fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 552fcf3ce44SJohn Forte 553fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 554fcf3ce44SJohn Forte 555fcf3ce44SJohn Forte /* 556fcf3ce44SJohn Forte * Build continuation packets. 557fcf3ce44SJohn Forte */ 558fcf3ce44SJohn Forte while (seg_cnt) { 559fcf3ce44SJohn Forte /* Sync DMA buffer. */ 560fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 561fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 562fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), REQUEST_ENTRY_SIZE, 563fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 564fcf3ce44SJohn Forte 565fcf3ce44SJohn Forte /* Adjust ring pointer, and deal with wrap. */ 566fcf3ce44SJohn Forte ha->req_ring_index++; 567fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 568fcf3ce44SJohn Forte ha->req_ring_index = 0; 569fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 570fcf3ce44SJohn Forte } else { 571fcf3ce44SJohn Forte ha->request_ring_ptr++; 572fcf3ce44SJohn Forte } 573fcf3ce44SJohn Forte pkt = (cont_entry_t *)ha->request_ring_ptr; 574fcf3ce44SJohn Forte 575fcf3ce44SJohn Forte /* Zero out packet. */ 576fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 577fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 578fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 579fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 580fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 581fcf3ce44SJohn Forte 582fcf3ce44SJohn Forte /* 583fcf3ce44SJohn Forte * Build continuation packet. 584fcf3ce44SJohn Forte */ 585fcf3ce44SJohn Forte pkt->entry_count = 1; 586fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 587fcf3ce44SJohn Forte if (addr64) { 588fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_1; 589fcf3ce44SJohn Forte cnt = CONT_TYPE_1_DATA_SEGMENTS; 590fcf3ce44SJohn Forte ptr32 = (uint32_t *) 591fcf3ce44SJohn Forte &((cont_type_1_entry_t *)pkt)->dseg_0_address; 592fcf3ce44SJohn Forte while (cnt && seg_cnt) { 593fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 594fcf3ce44SJohn Forte cp->dmac_address); 595fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 596fcf3ce44SJohn Forte cp->dmac_notused); 597fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 598fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 599fcf3ce44SJohn Forte seg_cnt--; 600fcf3ce44SJohn Forte cnt--; 601fcf3ce44SJohn Forte cp++; 602fcf3ce44SJohn Forte } 603fcf3ce44SJohn Forte } else { 604fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_0; 605fcf3ce44SJohn Forte cnt = CONT_TYPE_0_DATA_SEGMENTS; 606fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 607fcf3ce44SJohn Forte while (cnt && seg_cnt) { 608fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 609fcf3ce44SJohn Forte cp->dmac_address); 610fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 611fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 612fcf3ce44SJohn Forte seg_cnt--; 613fcf3ce44SJohn Forte cnt--; 614fcf3ce44SJohn Forte cp++; 615fcf3ce44SJohn Forte } 616fcf3ce44SJohn Forte } 617fcf3ce44SJohn Forte 618fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): packet:\n", ha->instance); 619fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 620fcf3ce44SJohn Forte } 621fcf3ce44SJohn Forte 622fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 623fcf3ce44SJohn Forte } 624fcf3ce44SJohn Forte 625fcf3ce44SJohn Forte /* 626fcf3ce44SJohn Forte * ql_command_24xx_iocb 627fcf3ce44SJohn Forte * Setup of ISP24xx command IOCB. 628fcf3ce44SJohn Forte * 629fcf3ce44SJohn Forte * Input: 630fcf3ce44SJohn Forte * ha: adapter state pointer. 631fcf3ce44SJohn Forte * sp: srb structure pointer. 632fcf3ce44SJohn Forte * arg: request queue packet. 633fcf3ce44SJohn Forte * 634fcf3ce44SJohn Forte * Context: 635fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 636fcf3ce44SJohn Forte */ 637fcf3ce44SJohn Forte void 638fcf3ce44SJohn Forte ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 639fcf3ce44SJohn Forte { 640fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 641fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 642fcf3ce44SJohn Forte uint16_t seg_cnt; 643fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 644fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 645fcf3ce44SJohn Forte cmd_24xx_entry_t *pkt = arg; 646fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 647fcf3ce44SJohn Forte 648fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 649fcf3ce44SJohn Forte 650fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_7; 651fcf3ce44SJohn Forte 652fcf3ce44SJohn Forte /* Set LUN number */ 653fcf3ce44SJohn Forte pkt->fcp_lun[2] = LSB(sp->lun_queue->lun_no); 654fcf3ce44SJohn Forte pkt->fcp_lun[3] = MSB(sp->lun_queue->lun_no); 655fcf3ce44SJohn Forte 656fcf3ce44SJohn Forte /* Set N_port handle */ 657fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 658fcf3ce44SJohn Forte 659fcf3ce44SJohn Forte /* Set target ID */ 660fcf3ce44SJohn Forte pkt->target_id[0] = tq->d_id.b.al_pa; 661fcf3ce44SJohn Forte pkt->target_id[1] = tq->d_id.b.area; 662fcf3ce44SJohn Forte pkt->target_id[2] = tq->d_id.b.domain; 663fcf3ce44SJohn Forte 664fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 665fcf3ce44SJohn Forte 666fcf3ce44SJohn Forte /* Set ISP command timeout. */ 667fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 668fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 669fcf3ce44SJohn Forte sp->isp_timeout); 670fcf3ce44SJohn Forte } 671fcf3ce44SJohn Forte 672fcf3ce44SJohn Forte /* Load SCSI CDB */ 673fcf3ce44SJohn Forte ddi_rep_put8(pha->hba_buf.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb, 674fcf3ce44SJohn Forte MAX_CMDSZ, DDI_DEV_AUTOINCR); 675fcf3ce44SJohn Forte for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) { 676fcf3ce44SJohn Forte ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4); 677fcf3ce44SJohn Forte } 678fcf3ce44SJohn Forte 679fcf3ce44SJohn Forte /* 680fcf3ce44SJohn Forte * Set tag queue control flags 681fcf3ce44SJohn Forte * Note: 682fcf3ce44SJohn Forte * Cannot copy fcp->fcp_cntl.cntl_qtype directly, 683fcf3ce44SJohn Forte * problem with x86 in 32bit kernel mode 684fcf3ce44SJohn Forte */ 685fcf3ce44SJohn Forte switch (fcp->fcp_cntl.cntl_qtype) { 686fcf3ce44SJohn Forte case FCP_QTYPE_SIMPLE: 687fcf3ce44SJohn Forte pkt->task = TA_STAG; 688fcf3ce44SJohn Forte break; 689fcf3ce44SJohn Forte case FCP_QTYPE_HEAD_OF_Q: 690fcf3ce44SJohn Forte pkt->task = TA_HTAG; 691fcf3ce44SJohn Forte break; 692fcf3ce44SJohn Forte case FCP_QTYPE_ORDERED: 693fcf3ce44SJohn Forte pkt->task = TA_OTAG; 694fcf3ce44SJohn Forte break; 695fcf3ce44SJohn Forte case FCP_QTYPE_ACA_Q_TAG: 696fcf3ce44SJohn Forte pkt->task = TA_ACA; 697fcf3ce44SJohn Forte break; 698fcf3ce44SJohn Forte case FCP_QTYPE_UNTAGGED: 699fcf3ce44SJohn Forte pkt->task = TA_UNTAGGED; 700fcf3ce44SJohn Forte break; 701fcf3ce44SJohn Forte default: 702fcf3ce44SJohn Forte break; 703fcf3ce44SJohn Forte } 704fcf3ce44SJohn Forte 705fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 706fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 707fcf3ce44SJohn Forte pha->xioctl->IOControlRequests++; 708fcf3ce44SJohn Forte return; 709fcf3ce44SJohn Forte } 710fcf3ce44SJohn Forte 711fcf3ce44SJohn Forte /* Set transfer direction. */ 712fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 713fcf3ce44SJohn Forte pkt->control_flags = CF_WR; 714fcf3ce44SJohn Forte pha->xioctl->IOOutputRequests++; 715fcf3ce44SJohn Forte pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 716fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 717fcf3ce44SJohn Forte pkt->control_flags = CF_RD; 718fcf3ce44SJohn Forte pha->xioctl->IOInputRequests++; 719fcf3ce44SJohn Forte pha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 720fcf3ce44SJohn Forte } 721fcf3ce44SJohn Forte 722fcf3ce44SJohn Forte /* Set data segment count. */ 723fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 724fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 725fcf3ce44SJohn Forte 726fcf3ce44SJohn Forte /* Load total byte count. */ 727fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count, 728fcf3ce44SJohn Forte fcp->fcp_data_len); 729fcf3ce44SJohn Forte 730fcf3ce44SJohn Forte /* Load command data segment. */ 731fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 732fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 733fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 734fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 735fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 736fcf3ce44SJohn Forte seg_cnt--; 737fcf3ce44SJohn Forte cp++; 738fcf3ce44SJohn Forte 739fcf3ce44SJohn Forte /* 740fcf3ce44SJohn Forte * Build continuation packets. 741fcf3ce44SJohn Forte */ 742fcf3ce44SJohn Forte if (seg_cnt) { 743fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 744fcf3ce44SJohn Forte } 745fcf3ce44SJohn Forte 746fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 747fcf3ce44SJohn Forte } 748fcf3ce44SJohn Forte 749fcf3ce44SJohn Forte /* 750fcf3ce44SJohn Forte * ql_marker 751fcf3ce44SJohn Forte * Function issues marker IOCB. 752fcf3ce44SJohn Forte * 753fcf3ce44SJohn Forte * Input: 754fcf3ce44SJohn Forte * ha: adapter state pointer. 755fcf3ce44SJohn Forte * loop_id: device loop ID 756fcf3ce44SJohn Forte * lun: device LUN 757fcf3ce44SJohn Forte * type: marker modifier 758fcf3ce44SJohn Forte * 759fcf3ce44SJohn Forte * Returns: 760fcf3ce44SJohn Forte * ql local function return status code. 761fcf3ce44SJohn Forte * 762fcf3ce44SJohn Forte * Context: 763fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 764fcf3ce44SJohn Forte */ 765fcf3ce44SJohn Forte int 766fcf3ce44SJohn Forte ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, uint16_t lun, 767fcf3ce44SJohn Forte uint8_t type) 768fcf3ce44SJohn Forte { 769fcf3ce44SJohn Forte mrk_entry_t *pkt; 770fcf3ce44SJohn Forte int rval; 771fcf3ce44SJohn Forte 772fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 773fcf3ce44SJohn Forte 774fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 775fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 776fcf3ce44SJohn Forte pkt->entry_type = MARKER_TYPE; 777fcf3ce44SJohn Forte 778*eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 779fcf3ce44SJohn Forte marker_24xx_entry_t *pkt24 = 780fcf3ce44SJohn Forte (marker_24xx_entry_t *)pkt; 781fcf3ce44SJohn Forte 782fcf3ce44SJohn Forte pkt24->modifier = type; 783fcf3ce44SJohn Forte 784fcf3ce44SJohn Forte /* Set LUN number */ 785fcf3ce44SJohn Forte pkt24->fcp_lun[2] = LSB(lun); 786fcf3ce44SJohn Forte pkt24->fcp_lun[3] = MSB(lun); 787fcf3ce44SJohn Forte 788fcf3ce44SJohn Forte pkt24->vp_index = ha->vp_index; 789fcf3ce44SJohn Forte 790fcf3ce44SJohn Forte /* Set N_port handle */ 791fcf3ce44SJohn Forte ddi_put16(ha->pha->hba_buf.acc_handle, 792fcf3ce44SJohn Forte &pkt24->n_port_hdl, loop_id); 793fcf3ce44SJohn Forte 794fcf3ce44SJohn Forte } else { 795fcf3ce44SJohn Forte pkt->modifier = type; 796fcf3ce44SJohn Forte 797fcf3ce44SJohn Forte pkt->lun_l = LSB(lun); 798fcf3ce44SJohn Forte pkt->lun_h = MSB(lun); 799fcf3ce44SJohn Forte 800fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 801fcf3ce44SJohn Forte pkt->target_l = LSB(loop_id); 802fcf3ce44SJohn Forte pkt->target_h = MSB(loop_id); 803fcf3ce44SJohn Forte } else { 804fcf3ce44SJohn Forte pkt->target_h = LSB(loop_id); 805fcf3ce44SJohn Forte } 806fcf3ce44SJohn Forte } 807fcf3ce44SJohn Forte 808fcf3ce44SJohn Forte /* Issue command to ISP */ 809fcf3ce44SJohn Forte ql_isp_cmd(ha); 810fcf3ce44SJohn Forte } 811fcf3ce44SJohn Forte 812fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 813fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 814fcf3ce44SJohn Forte } else { 815fcf3ce44SJohn Forte /*EMPTY*/ 816fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 817fcf3ce44SJohn Forte } 818fcf3ce44SJohn Forte return (rval); 819fcf3ce44SJohn Forte } 820fcf3ce44SJohn Forte 821fcf3ce44SJohn Forte /* 822fcf3ce44SJohn Forte * ql_ms_iocb 823fcf3ce44SJohn Forte * Setup of name/management server IOCB. 824fcf3ce44SJohn Forte * 825fcf3ce44SJohn Forte * Input: 826fcf3ce44SJohn Forte * ha = adapter state pointer. 827fcf3ce44SJohn Forte * sp = srb structure pointer. 828fcf3ce44SJohn Forte * arg = request queue packet. 829fcf3ce44SJohn Forte * 830fcf3ce44SJohn Forte * Context: 831fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 832fcf3ce44SJohn Forte */ 833fcf3ce44SJohn Forte void 834fcf3ce44SJohn Forte ql_ms_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 835fcf3ce44SJohn Forte { 836fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 837fcf3ce44SJohn Forte uint32_t *ptr32; 838fcf3ce44SJohn Forte uint16_t seg_cnt; 839fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 840fcf3ce44SJohn Forte ms_entry_t *pkt = arg; 841fcf3ce44SJohn Forte 842fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 843fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 844fcf3ce44SJohn Forte /* 845fcf3ce44SJohn Forte * Build command packet. 846fcf3ce44SJohn Forte */ 847fcf3ce44SJohn Forte pkt->entry_type = MS_TYPE; 848fcf3ce44SJohn Forte 849fcf3ce44SJohn Forte /* Set loop ID */ 850fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 851fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 852fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 853fcf3ce44SJohn Forte } else { 854fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 855fcf3ce44SJohn Forte } 856fcf3ce44SJohn Forte 857fcf3ce44SJohn Forte /* Set ISP command timeout. */ 858fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 859fcf3ce44SJohn Forte 860fcf3ce44SJohn Forte /* Set cmd data segment count. */ 861fcf3ce44SJohn Forte pkt->cmd_dseg_count_l = 1; 862fcf3ce44SJohn Forte 863fcf3ce44SJohn Forte /* Set total data segment count */ 864fcf3ce44SJohn Forte seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1); 865fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->total_dseg_count, seg_cnt); 866fcf3ce44SJohn Forte 867fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 868fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->cmd_byte_count, 869fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 870fcf3ce44SJohn Forte 871fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 872fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->resp_byte_count, 873fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 874fcf3ce44SJohn Forte 875fcf3ce44SJohn Forte /* Load MS command data segments. */ 876fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 877fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 878fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 879fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 880fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 881fcf3ce44SJohn Forte seg_cnt--; 882fcf3ce44SJohn Forte 883fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 884fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 885fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 886fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 887fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 888fcf3ce44SJohn Forte seg_cnt--; 889fcf3ce44SJohn Forte cp++; 890fcf3ce44SJohn Forte 891fcf3ce44SJohn Forte /* 892fcf3ce44SJohn Forte * Build continuation packets. 893fcf3ce44SJohn Forte */ 894fcf3ce44SJohn Forte if (seg_cnt) { 895fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 896fcf3ce44SJohn Forte } 897fcf3ce44SJohn Forte 898fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 899fcf3ce44SJohn Forte } 900fcf3ce44SJohn Forte 901fcf3ce44SJohn Forte /* 902fcf3ce44SJohn Forte * ql_ms_24xx_iocb 903fcf3ce44SJohn Forte * Setup of name/management server IOCB. 904fcf3ce44SJohn Forte * 905fcf3ce44SJohn Forte * Input: 906fcf3ce44SJohn Forte * ha: adapter state pointer. 907fcf3ce44SJohn Forte * sp: srb structure pointer. 908fcf3ce44SJohn Forte * arg: request queue packet. 909fcf3ce44SJohn Forte * 910fcf3ce44SJohn Forte * Context: 911fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 912fcf3ce44SJohn Forte */ 913fcf3ce44SJohn Forte void 914fcf3ce44SJohn Forte ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 915fcf3ce44SJohn Forte { 916fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 917fcf3ce44SJohn Forte uint32_t *ptr32; 918fcf3ce44SJohn Forte uint16_t seg_cnt; 919fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 920fcf3ce44SJohn Forte ct_passthru_entry_t *pkt = arg; 921fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 922fcf3ce44SJohn Forte 923fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 924fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 925fcf3ce44SJohn Forte /* 926fcf3ce44SJohn Forte * Build command packet. 927fcf3ce44SJohn Forte */ 928fcf3ce44SJohn Forte pkt->entry_type = CT_PASSTHRU_TYPE; 929fcf3ce44SJohn Forte 930fcf3ce44SJohn Forte /* Set loop ID */ 931fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 932fcf3ce44SJohn Forte 933fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 934fcf3ce44SJohn Forte 935fcf3ce44SJohn Forte /* Set ISP command timeout. */ 936fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 937fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 938fcf3ce44SJohn Forte sp->isp_timeout); 939fcf3ce44SJohn Forte } 940fcf3ce44SJohn Forte 941fcf3ce44SJohn Forte /* Set cmd/response data segment counts. */ 942fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->cmd_dseg_count, 1); 943fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt; 944fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->resp_dseg_count, seg_cnt); 945fcf3ce44SJohn Forte 946fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 947fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->cmd_byte_count, 948fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 949fcf3ce44SJohn Forte 950fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 951fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->resp_byte_count, 952fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 953fcf3ce44SJohn Forte 954fcf3ce44SJohn Forte /* Load MS command entry data segments. */ 955fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 956fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 957fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 958fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 959fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 960fcf3ce44SJohn Forte 961fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 962fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 963fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 964fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 965fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 966fcf3ce44SJohn Forte seg_cnt--; 967fcf3ce44SJohn Forte cp++; 968fcf3ce44SJohn Forte 969fcf3ce44SJohn Forte /* 970fcf3ce44SJohn Forte * Build continuation packets. 971fcf3ce44SJohn Forte */ 972fcf3ce44SJohn Forte if (seg_cnt) { 973fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 974fcf3ce44SJohn Forte } 975fcf3ce44SJohn Forte 976fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 977fcf3ce44SJohn Forte } 978fcf3ce44SJohn Forte 979fcf3ce44SJohn Forte /* 980fcf3ce44SJohn Forte * ql_ip_iocb 981fcf3ce44SJohn Forte * Setup of IP IOCB. 982fcf3ce44SJohn Forte * 983fcf3ce44SJohn Forte * Input: 984fcf3ce44SJohn Forte * ha: adapter state pointer. 985fcf3ce44SJohn Forte * sp: srb structure pointer. 986fcf3ce44SJohn Forte * arg: request queue packet. 987fcf3ce44SJohn Forte * 988fcf3ce44SJohn Forte * Context: 989fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 990fcf3ce44SJohn Forte */ 991fcf3ce44SJohn Forte void 992fcf3ce44SJohn Forte ql_ip_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 993fcf3ce44SJohn Forte { 994fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 995fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 996fcf3ce44SJohn Forte uint16_t seg_cnt; 997fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 998fcf3ce44SJohn Forte ip_entry_t *pkt = arg; 999fcf3ce44SJohn Forte 1000fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1001fcf3ce44SJohn Forte 1002fcf3ce44SJohn Forte /* Set loop ID */ 1003fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 1004fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 1005fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 1006fcf3ce44SJohn Forte } else { 1007fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 1008fcf3ce44SJohn Forte } 1009fcf3ce44SJohn Forte 1010fcf3ce44SJohn Forte /* Set control flags */ 1011fcf3ce44SJohn Forte pkt->control_flags_l = BIT_6; 1012fcf3ce44SJohn Forte if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) { 1013fcf3ce44SJohn Forte pkt->control_flags_h = BIT_7; 1014fcf3ce44SJohn Forte } 1015fcf3ce44SJohn Forte 1016fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1017fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 1018fcf3ce44SJohn Forte 1019fcf3ce44SJohn Forte /* Set data segment count. */ 1020fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 1021fcf3ce44SJohn Forte /* Load total byte count. */ 1022fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 1023fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1024fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 1025fcf3ce44SJohn Forte 1026fcf3ce44SJohn Forte /* 1027fcf3ce44SJohn Forte * Build command packet. 1028fcf3ce44SJohn Forte */ 1029fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1030fcf3ce44SJohn Forte pkt->entry_type = IP_A64_TYPE; 1031fcf3ce44SJohn Forte cnt = IP_A64_DATA_SEGMENTS; 1032fcf3ce44SJohn Forte } else { 1033fcf3ce44SJohn Forte pkt->entry_type = IP_TYPE; 1034fcf3ce44SJohn Forte cnt = IP_DATA_SEGMENTS; 1035fcf3ce44SJohn Forte } 1036fcf3ce44SJohn Forte 1037fcf3ce44SJohn Forte /* Load command entry data segments. */ 1038fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1039fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1040fcf3ce44SJohn Forte while (cnt && seg_cnt) { 1041fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1042fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1043fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1044fcf3ce44SJohn Forte cp->dmac_notused); 1045fcf3ce44SJohn Forte } 1046fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1047fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1048fcf3ce44SJohn Forte seg_cnt--; 1049fcf3ce44SJohn Forte cnt--; 1050fcf3ce44SJohn Forte cp++; 1051fcf3ce44SJohn Forte } 1052fcf3ce44SJohn Forte 1053fcf3ce44SJohn Forte /* 1054fcf3ce44SJohn Forte * Build continuation packets. 1055fcf3ce44SJohn Forte */ 1056fcf3ce44SJohn Forte if (seg_cnt) { 1057fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 1058fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 1059fcf3ce44SJohn Forte } 1060fcf3ce44SJohn Forte 1061fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1062fcf3ce44SJohn Forte } 1063fcf3ce44SJohn Forte 1064fcf3ce44SJohn Forte /* 1065fcf3ce44SJohn Forte * ql_ip_24xx_iocb 1066fcf3ce44SJohn Forte * Setup of IP IOCB for ISP24xx. 1067fcf3ce44SJohn Forte * 1068fcf3ce44SJohn Forte * Input: 1069fcf3ce44SJohn Forte * ha: adapter state pointer. 1070fcf3ce44SJohn Forte * sp: srb structure pointer. 1071fcf3ce44SJohn Forte * arg: request queue packet. 1072fcf3ce44SJohn Forte * 1073fcf3ce44SJohn Forte * Context: 1074fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1075fcf3ce44SJohn Forte */ 1076fcf3ce44SJohn Forte void 1077fcf3ce44SJohn Forte ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1078fcf3ce44SJohn Forte { 1079fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1080fcf3ce44SJohn Forte uint32_t *ptr32; 1081fcf3ce44SJohn Forte uint16_t seg_cnt; 1082fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 1083fcf3ce44SJohn Forte ip_cmd_entry_t *pkt = arg; 1084fcf3ce44SJohn Forte 1085fcf3ce44SJohn Forte pkt->entry_type = IP_CMD_TYPE; 1086fcf3ce44SJohn Forte 1087fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1088fcf3ce44SJohn Forte 1089fcf3ce44SJohn Forte /* Set N_port handle */ 1090fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->hdl_status, tq->loop_id); 1091fcf3ce44SJohn Forte 1092fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1093fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 1094fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout_hdl, 1095fcf3ce44SJohn Forte sp->isp_timeout); 1096fcf3ce44SJohn Forte } 1097fcf3ce44SJohn Forte 1098fcf3ce44SJohn Forte /* Set data segment count. */ 1099fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 1100fcf3ce44SJohn Forte /* Load total byte count. */ 1101fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 1102fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1103fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 1104fcf3ce44SJohn Forte 1105fcf3ce44SJohn Forte /* Set control flags */ 1106fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->control_flags, 1107fcf3ce44SJohn Forte (uint16_t)(BIT_0)); 1108fcf3ce44SJohn Forte 1109fcf3ce44SJohn Forte /* Set frame header control flags */ 1110fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->frame_hdr_cntrl_flgs, 1111fcf3ce44SJohn Forte (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ)); 1112fcf3ce44SJohn Forte 1113fcf3ce44SJohn Forte /* Load command data segment. */ 1114fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1115fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1116fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1117fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1118fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 1119fcf3ce44SJohn Forte seg_cnt--; 1120fcf3ce44SJohn Forte cp++; 1121fcf3ce44SJohn Forte 1122fcf3ce44SJohn Forte /* 1123fcf3ce44SJohn Forte * Build continuation packets. 1124fcf3ce44SJohn Forte */ 1125fcf3ce44SJohn Forte if (seg_cnt) { 1126fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 1127fcf3ce44SJohn Forte } 1128fcf3ce44SJohn Forte 1129fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1130fcf3ce44SJohn Forte } 1131fcf3ce44SJohn Forte 1132fcf3ce44SJohn Forte /* 1133fcf3ce44SJohn Forte * ql_isp_rcvbuf 1134fcf3ce44SJohn Forte * Locates free buffers and places it on the receive buffer queue. 1135fcf3ce44SJohn Forte * 1136fcf3ce44SJohn Forte * Input: 1137fcf3ce44SJohn Forte * ha = adapter state pointer. 1138fcf3ce44SJohn Forte * 1139fcf3ce44SJohn Forte * Context: 1140fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1141fcf3ce44SJohn Forte */ 1142fcf3ce44SJohn Forte void 1143fcf3ce44SJohn Forte ql_isp_rcvbuf(ql_adapter_state_t *ha) 1144fcf3ce44SJohn Forte { 1145fcf3ce44SJohn Forte rcvbuf_t *container; 114616dd44c2SDaniel Beauregard uint16_t rcv_q_cnt; 1147fcf3ce44SJohn Forte uint16_t index = 0; 1148fcf3ce44SJohn Forte uint16_t index1 = 1; 1149fcf3ce44SJohn Forte int debounce_count = QL_MAX_DEBOUNCE; 1150fcf3ce44SJohn Forte ql_srb_t *sp; 1151fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1152fcf3ce44SJohn Forte int ring_updated = FALSE; 1153fcf3ce44SJohn Forte 1154*eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 1155fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ha); 1156fcf3ce44SJohn Forte return; 1157fcf3ce44SJohn Forte } 1158fcf3ce44SJohn Forte 1159fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1160fcf3ce44SJohn Forte 1161fcf3ce44SJohn Forte /* Acquire adapter state lock. */ 1162fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1163fcf3ce44SJohn Forte 1164fcf3ce44SJohn Forte /* Calculate number of free receive buffer entries. */ 1165*eb82ff87SDaniel Beauregard index = RD16_IO_REG(ha, mailbox_out[8]); 1166fcf3ce44SJohn Forte do { 1167*eb82ff87SDaniel Beauregard index1 = RD16_IO_REG(ha, mailbox_out[8]); 1168fcf3ce44SJohn Forte if (index1 == index) { 1169fcf3ce44SJohn Forte break; 1170fcf3ce44SJohn Forte } else { 1171fcf3ce44SJohn Forte index = index1; 1172fcf3ce44SJohn Forte } 1173fcf3ce44SJohn Forte } while (debounce_count --); 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte if (debounce_count < 0) { 1176fcf3ce44SJohn Forte /* This should never happen */ 1177fcf3ce44SJohn Forte EL(ha, "max mb8 debounce retries exceeded\n"); 1178fcf3ce44SJohn Forte } 1179fcf3ce44SJohn Forte 1180fcf3ce44SJohn Forte rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ? 1181fcf3ce44SJohn Forte index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT - 1182fcf3ce44SJohn Forte (ha->rcvbuf_ring_index - index)); 1183fcf3ce44SJohn Forte 1184fcf3ce44SJohn Forte if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) { 1185fcf3ce44SJohn Forte rcv_q_cnt--; 1186fcf3ce44SJohn Forte } 1187fcf3ce44SJohn Forte 1188fcf3ce44SJohn Forte /* Load all free buffers in ISP receive buffer ring. */ 1189fcf3ce44SJohn Forte index = 0; 119016dd44c2SDaniel Beauregard while (rcv_q_cnt > (uint16_t)0 && index < QL_UB_LIMIT) { 1191fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1192fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1193fcf3ce44SJohn Forte while (index < QL_UB_LIMIT) { 1194fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1195fcf3ce44SJohn Forte if (ubp != NULL) { 1196fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1197fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1198fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1199fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1200fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1201fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1202fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1203fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1204fcf3ce44SJohn Forte break; 1205fcf3ce44SJohn Forte } 1206fcf3ce44SJohn Forte } 1207fcf3ce44SJohn Forte index++; 1208fcf3ce44SJohn Forte } 1209fcf3ce44SJohn Forte 1210fcf3ce44SJohn Forte if (index < QL_UB_LIMIT) { 1211fcf3ce44SJohn Forte rcv_q_cnt--; 1212fcf3ce44SJohn Forte index++; 1213fcf3ce44SJohn Forte container = ha->rcvbuf_ring_ptr; 1214fcf3ce44SJohn Forte 1215fcf3ce44SJohn Forte /* 1216fcf3ce44SJohn Forte * Build container. 1217fcf3ce44SJohn Forte */ 1218fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1219fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[0], 1220fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1221fcf3ce44SJohn Forte 1222fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1223fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[1], 1224fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1225fcf3ce44SJohn Forte 1226fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1227fcf3ce44SJohn Forte LSW(sp->handle)); 1228fcf3ce44SJohn Forte 1229fcf3ce44SJohn Forte ha->ub_outcnt++; 1230fcf3ce44SJohn Forte 1231fcf3ce44SJohn Forte /* Adjust ring index. */ 1232fcf3ce44SJohn Forte ha->rcvbuf_ring_index++; 1233fcf3ce44SJohn Forte if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) { 1234fcf3ce44SJohn Forte ha->rcvbuf_ring_index = 0; 1235fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp; 1236fcf3ce44SJohn Forte } else { 1237fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr++; 1238fcf3ce44SJohn Forte } 1239fcf3ce44SJohn Forte 1240fcf3ce44SJohn Forte ring_updated = TRUE; 1241fcf3ce44SJohn Forte } 1242fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1243fcf3ce44SJohn Forte } 1244fcf3ce44SJohn Forte 1245fcf3ce44SJohn Forte if (ring_updated) { 1246fcf3ce44SJohn Forte /* Sync queue. */ 1247fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1248fcf3ce44SJohn Forte (off_t)RCVBUF_Q_BUFFER_OFFSET, (size_t)RCVBUF_QUEUE_SIZE, 1249fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 1250fcf3ce44SJohn Forte 1251fcf3ce44SJohn Forte /* Set chip new ring index. */ 1252*eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[8], ha->rcvbuf_ring_index); 1253fcf3ce44SJohn Forte } 1254fcf3ce44SJohn Forte 1255fcf3ce44SJohn Forte /* Release adapter state lock. */ 1256fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1257fcf3ce44SJohn Forte 1258fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1259fcf3ce44SJohn Forte } 1260fcf3ce44SJohn Forte 1261fcf3ce44SJohn Forte /* 1262fcf3ce44SJohn Forte * ql_isp24xx_rcvbuf 1263fcf3ce44SJohn Forte * Locates free buffers and send it to adapter. 1264fcf3ce44SJohn Forte * 1265fcf3ce44SJohn Forte * Input: 1266fcf3ce44SJohn Forte * ha = adapter state pointer. 1267fcf3ce44SJohn Forte * 1268fcf3ce44SJohn Forte * Context: 1269fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1270fcf3ce44SJohn Forte */ 1271fcf3ce44SJohn Forte static void 1272fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ql_adapter_state_t *ha) 1273fcf3ce44SJohn Forte { 1274fcf3ce44SJohn Forte rcvbuf_t *container; 1275fcf3ce44SJohn Forte uint16_t index; 1276fcf3ce44SJohn Forte ql_srb_t *sp; 1277fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1278fcf3ce44SJohn Forte int rval; 1279fcf3ce44SJohn Forte ip_buf_pool_entry_t *pkt = NULL; 1280fcf3ce44SJohn Forte 1281fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1282fcf3ce44SJohn Forte 1283fcf3ce44SJohn Forte for (;;) { 1284fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1285fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1286fcf3ce44SJohn Forte for (index = 0; index < QL_UB_LIMIT; index++) { 1287fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1288fcf3ce44SJohn Forte if (ubp != NULL) { 1289fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1290fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1291fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1292fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1293fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1294fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1295fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1296fcf3ce44SJohn Forte ha->ub_outcnt++; 1297fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1298fcf3ce44SJohn Forte break; 1299fcf3ce44SJohn Forte } 1300fcf3ce44SJohn Forte } 1301fcf3ce44SJohn Forte } 1302fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1303fcf3ce44SJohn Forte if (index == QL_UB_LIMIT) { 1304fcf3ce44SJohn Forte break; 1305fcf3ce44SJohn Forte } 1306fcf3ce44SJohn Forte 1307fcf3ce44SJohn Forte /* Get IOCB packet for buffers. */ 1308fcf3ce44SJohn Forte if (pkt == NULL) { 1309fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 1310fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1311fcf3ce44SJohn Forte EL(ha, "failed, ql_req_pkt=%x\n", rval); 1312fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1313fcf3ce44SJohn Forte ha->ub_outcnt--; 1314fcf3ce44SJohn Forte sp->flags &= ~SRB_UB_IN_ISP; 1315fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1316fcf3ce44SJohn Forte break; 1317fcf3ce44SJohn Forte } 1318fcf3ce44SJohn Forte pkt->entry_type = IP_BUF_POOL_TYPE; 1319fcf3ce44SJohn Forte container = &pkt->buffers[0]; 1320fcf3ce44SJohn Forte } 1321fcf3ce44SJohn Forte 1322fcf3ce44SJohn Forte /* 1323fcf3ce44SJohn Forte * Build container. 1324fcf3ce44SJohn Forte */ 1325fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[0], 1326fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1327fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[1], 1328fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1329fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1330fcf3ce44SJohn Forte LSW(sp->handle)); 1331fcf3ce44SJohn Forte 1332fcf3ce44SJohn Forte pkt->buffer_count++; 1333fcf3ce44SJohn Forte container++; 1334fcf3ce44SJohn Forte 1335fcf3ce44SJohn Forte if (pkt->buffer_count == IP_POOL_BUFFERS) { 1336fcf3ce44SJohn Forte ql_isp_cmd(ha); 1337fcf3ce44SJohn Forte pkt = NULL; 1338fcf3ce44SJohn Forte } 1339fcf3ce44SJohn Forte } 1340fcf3ce44SJohn Forte 1341fcf3ce44SJohn Forte if (pkt != NULL) { 1342fcf3ce44SJohn Forte ql_isp_cmd(ha); 1343fcf3ce44SJohn Forte } 1344fcf3ce44SJohn Forte 1345fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1346fcf3ce44SJohn Forte } 1347