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 22eb82ff87SDaniel Beauregard /* Copyright 2010 QLogic Corporation */ 23fcf3ce44SJohn Forte 24fcf3ce44SJohn Forte /* 25*f885d00fSDaniel Beauregard * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 26fcf3ce44SJohn Forte */ 27fcf3ce44SJohn Forte 28eb82ff87SDaniel Beauregard #pragma ident "Copyright 2010 QLogic Corporation; ql_iocb.c" 29fcf3ce44SJohn Forte 30fcf3ce44SJohn Forte /* 31fcf3ce44SJohn Forte * ISP2xxx Solaris Fibre Channel Adapter (FCA) driver source file. 32fcf3ce44SJohn Forte * 33fcf3ce44SJohn Forte * *********************************************************************** 34fcf3ce44SJohn Forte * * ** 35fcf3ce44SJohn Forte * * NOTICE ** 36eb82ff87SDaniel Beauregard * * COPYRIGHT (C) 1996-2010 QLOGIC CORPORATION ** 37fcf3ce44SJohn Forte * * ALL RIGHTS RESERVED ** 38fcf3ce44SJohn Forte * * ** 39fcf3ce44SJohn Forte * *********************************************************************** 40fcf3ce44SJohn Forte * 41fcf3ce44SJohn Forte */ 42fcf3ce44SJohn Forte 43fcf3ce44SJohn Forte #include <ql_apps.h> 44fcf3ce44SJohn Forte #include <ql_api.h> 45fcf3ce44SJohn Forte #include <ql_debug.h> 46fcf3ce44SJohn Forte #include <ql_iocb.h> 47fcf3ce44SJohn Forte #include <ql_isr.h> 48fcf3ce44SJohn Forte #include <ql_xioctl.h> 49fcf3ce44SJohn Forte 50fcf3ce44SJohn Forte /* 51fcf3ce44SJohn Forte * Local Function Prototypes. 52fcf3ce44SJohn Forte */ 535dfd244aSDaniel Beauregard static int ql_req_pkt(ql_adapter_state_t *, request_t **); 54fcf3ce44SJohn Forte static void ql_continuation_iocb(ql_adapter_state_t *, ddi_dma_cookie_t *, 55fcf3ce44SJohn Forte uint16_t, boolean_t); 56fcf3ce44SJohn Forte static void ql_isp24xx_rcvbuf(ql_adapter_state_t *); 57*f885d00fSDaniel Beauregard static void ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *, ql_srb_t *, void *); 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; 170*f885d00fSDaniel Beauregard sp->request_ring_ptr = pkt; 171fcf3ce44SJohn Forte sp->flags |= SRB_IN_TOKEN_ARRAY; 172fcf3ce44SJohn Forte 173fcf3ce44SJohn Forte /* Zero out packet. */ 174fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 175fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 176fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 177fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 178fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 179fcf3ce44SJohn Forte 180fcf3ce44SJohn Forte /* Setup IOCB common data. */ 181fcf3ce44SJohn Forte pkt->entry_count = (uint8_t)sp->req_cnt; 182fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 18316dd44c2SDaniel Beauregard /* mark the iocb with the response identifier */ 184fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->handle, 185fcf3ce44SJohn Forte (uint32_t)sp->handle); 186fcf3ce44SJohn Forte 18716dd44c2SDaniel Beauregard /* Setup IOCB unique data. */ 188fcf3ce44SJohn Forte (sp->iocb)(vha, sp, pkt); 189fcf3ce44SJohn Forte 190fcf3ce44SJohn Forte sp->flags |= SRB_ISP_STARTED; 191fcf3ce44SJohn Forte 192fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d,%d): req packet, sp=%p\n", 193fcf3ce44SJohn Forte ha->instance, vha->vp_index, (void *)sp); 194fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 195fcf3ce44SJohn Forte 196fcf3ce44SJohn Forte /* Sync DMA buffer. */ 197fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 198fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 199fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 200fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 201fcf3ce44SJohn Forte 202fcf3ce44SJohn Forte /* Adjust ring index. */ 203fcf3ce44SJohn Forte ha->req_ring_index++; 204fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 205fcf3ce44SJohn Forte ha->req_ring_index = 0; 206fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 207fcf3ce44SJohn Forte } else { 208fcf3ce44SJohn Forte ha->request_ring_ptr++; 209fcf3ce44SJohn Forte } 210fcf3ce44SJohn Forte 211fcf3ce44SJohn Forte /* Reset watchdog timer */ 212fcf3ce44SJohn Forte sp->wdg_q_time = sp->init_wdg_q_time; 213fcf3ce44SJohn Forte 21416dd44c2SDaniel Beauregard /* 21516dd44c2SDaniel Beauregard * Send it by setting the new ring index in the ISP Request 21616dd44c2SDaniel Beauregard * Ring In Pointer register. This is the mechanism 21716dd44c2SDaniel Beauregard * used to notify the isp that a new iocb has been 21816dd44c2SDaniel Beauregard * placed on the request ring. 21916dd44c2SDaniel Beauregard */ 220eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 221eb82ff87SDaniel Beauregard uint32_t w32; 222eb82ff87SDaniel Beauregard 223eb82ff87SDaniel Beauregard w32 = ha->req_ring_index << 16 | 224eb82ff87SDaniel Beauregard ha->function_number << 5 | 4; 225eb82ff87SDaniel Beauregard do { 226eb82ff87SDaniel Beauregard ddi_put32(ha->db_dev_handle, ha->nx_req_in, 227eb82ff87SDaniel Beauregard w32); 228eb82ff87SDaniel Beauregard } while (RD_REG_DWORD(ha, ha->db_read) != w32); 229eb82ff87SDaniel Beauregard 230eb82ff87SDaniel Beauregard } else { 231eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, req_in, ha->req_ring_index); 232eb82ff87SDaniel Beauregard } 233fcf3ce44SJohn Forte 234fcf3ce44SJohn Forte /* Update outstanding command count statistic. */ 235fcf3ce44SJohn Forte ha->adapter_stats->ncmds++; 236fcf3ce44SJohn Forte 23716dd44c2SDaniel Beauregard /* if there is a pending command, try to start it. */ 238fcf3ce44SJohn Forte if ((link = ha->pending_cmds.first) == NULL) { 239fcf3ce44SJohn Forte break; 240fcf3ce44SJohn Forte } 241fcf3ce44SJohn Forte 242fcf3ce44SJohn Forte /* Remove command from pending command queue */ 243fcf3ce44SJohn Forte sp = link->base_address; 244fcf3ce44SJohn Forte ql_remove_link(&ha->pending_cmds, &sp->cmd); 245fcf3ce44SJohn Forte } 246fcf3ce44SJohn Forte 247fcf3ce44SJohn Forte /* Release ring specific lock */ 248fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 249fcf3ce44SJohn Forte 250fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 251fcf3ce44SJohn Forte } 252fcf3ce44SJohn Forte 253fcf3ce44SJohn Forte /* 254fcf3ce44SJohn Forte * ql_req_pkt 255fcf3ce44SJohn Forte * Function is responsible for locking ring and 256fcf3ce44SJohn Forte * getting a zeroed out request packet. 257fcf3ce44SJohn Forte * 258fcf3ce44SJohn Forte * Input: 259fcf3ce44SJohn Forte * ha: adapter state pointer. 260fcf3ce44SJohn Forte * pkt: address for packet pointer. 261fcf3ce44SJohn Forte * 262fcf3ce44SJohn Forte * Returns: 263fcf3ce44SJohn Forte * ql local function return status code. 264fcf3ce44SJohn Forte * 265fcf3ce44SJohn Forte * Context: 266fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 267fcf3ce44SJohn Forte */ 2685dfd244aSDaniel Beauregard static int 269fcf3ce44SJohn Forte ql_req_pkt(ql_adapter_state_t *vha, request_t **pktp) 270fcf3ce44SJohn Forte { 271fcf3ce44SJohn Forte uint16_t cnt; 272fcf3ce44SJohn Forte uint32_t *long_ptr; 273fcf3ce44SJohn Forte uint32_t timer; 274fcf3ce44SJohn Forte int rval = QL_FUNCTION_TIMEOUT; 275fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 276fcf3ce44SJohn Forte 277fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 278fcf3ce44SJohn Forte 279fcf3ce44SJohn Forte /* Wait for 30 seconds for slot. */ 280fcf3ce44SJohn Forte for (timer = 30000; timer != 0; timer--) { 281fcf3ce44SJohn Forte /* Acquire ring lock. */ 282fcf3ce44SJohn Forte REQUEST_RING_LOCK(ha); 283fcf3ce44SJohn Forte 284fcf3ce44SJohn Forte if (ha->req_q_cnt == 0) { 285fcf3ce44SJohn Forte /* Calculate number of free request entries. */ 286fcf3ce44SJohn Forte cnt = RD16_IO_REG(ha, req_out); 287fcf3ce44SJohn Forte if (ha->req_ring_index < cnt) { 288fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 289fcf3ce44SJohn Forte (cnt - ha->req_ring_index); 290fcf3ce44SJohn Forte } else { 291fcf3ce44SJohn Forte ha->req_q_cnt = (uint16_t) 292fcf3ce44SJohn Forte (REQUEST_ENTRY_CNT - 293fcf3ce44SJohn Forte (ha->req_ring_index - cnt)); 294fcf3ce44SJohn Forte } 295fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 296fcf3ce44SJohn Forte ha->req_q_cnt--; 297fcf3ce44SJohn Forte } 298fcf3ce44SJohn Forte } 299fcf3ce44SJohn Forte 300fcf3ce44SJohn Forte /* Found empty request ring slot? */ 301fcf3ce44SJohn Forte if (ha->req_q_cnt != 0) { 302fcf3ce44SJohn Forte ha->req_q_cnt--; 303fcf3ce44SJohn Forte *pktp = ha->request_ring_ptr; 304fcf3ce44SJohn Forte 305fcf3ce44SJohn Forte /* Zero out packet. */ 306fcf3ce44SJohn Forte long_ptr = (uint32_t *)ha->request_ring_ptr; 307fcf3ce44SJohn Forte for (cnt = 0; cnt < REQUEST_ENTRY_SIZE/4; cnt++) { 308fcf3ce44SJohn Forte *long_ptr++ = 0; 309fcf3ce44SJohn Forte } 310fcf3ce44SJohn Forte 311fcf3ce44SJohn Forte /* Setup IOCB common data. */ 312fcf3ce44SJohn Forte ha->request_ring_ptr->entry_count = 1; 313fcf3ce44SJohn Forte ha->request_ring_ptr->sys_define = 314fcf3ce44SJohn Forte (uint8_t)ha->req_ring_index; 315fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 316fcf3ce44SJohn Forte &ha->request_ring_ptr->handle, 317fcf3ce44SJohn Forte (uint32_t)QL_FCA_BRAND); 318fcf3ce44SJohn Forte 319fcf3ce44SJohn Forte rval = QL_SUCCESS; 320fcf3ce44SJohn Forte 321fcf3ce44SJohn Forte break; 322fcf3ce44SJohn Forte } 323fcf3ce44SJohn Forte 324fcf3ce44SJohn Forte /* Release request queue lock. */ 325fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 326fcf3ce44SJohn Forte 327fcf3ce44SJohn Forte drv_usecwait(MILLISEC); 328fcf3ce44SJohn Forte 329fcf3ce44SJohn Forte /* Check for pending interrupts. */ 330fcf3ce44SJohn Forte /* 331fcf3ce44SJohn Forte * XXX protect interrupt routine from calling itself. 332fcf3ce44SJohn Forte * Need to revisit this routine. So far we never 333fcf3ce44SJohn Forte * hit this case as req slot was available 334fcf3ce44SJohn Forte */ 335fcf3ce44SJohn Forte if ((!(curthread->t_flag & T_INTR_THREAD)) && 336eb82ff87SDaniel Beauregard INTERRUPT_PENDING(ha)) { 337fcf3ce44SJohn Forte (void) ql_isr((caddr_t)ha); 338fcf3ce44SJohn Forte INTR_LOCK(ha); 339fcf3ce44SJohn Forte ha->intr_claimed = TRUE; 340fcf3ce44SJohn Forte INTR_UNLOCK(ha); 341fcf3ce44SJohn Forte } 342fcf3ce44SJohn Forte } 343fcf3ce44SJohn Forte 344fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 345fcf3ce44SJohn Forte ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0); 346fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval); 347fcf3ce44SJohn Forte } else { 348fcf3ce44SJohn Forte /*EMPTY*/ 349fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 350fcf3ce44SJohn Forte } 351fcf3ce44SJohn Forte return (rval); 352fcf3ce44SJohn Forte } 353fcf3ce44SJohn Forte 354fcf3ce44SJohn Forte /* 355fcf3ce44SJohn Forte * ql_isp_cmd 356fcf3ce44SJohn Forte * Function is responsible for modifying ISP input pointer. 35716dd44c2SDaniel Beauregard * This action notifies the isp that a new request has been 35816dd44c2SDaniel Beauregard * added to the request ring. 35916dd44c2SDaniel Beauregard * 360fcf3ce44SJohn Forte * Releases ring lock. 361fcf3ce44SJohn Forte * 362fcf3ce44SJohn Forte * Input: 363fcf3ce44SJohn Forte * ha: adapter state pointer. 364fcf3ce44SJohn Forte * 365fcf3ce44SJohn Forte * Context: 366fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 367fcf3ce44SJohn Forte */ 368fcf3ce44SJohn Forte void 369fcf3ce44SJohn Forte ql_isp_cmd(ql_adapter_state_t *vha) 370fcf3ce44SJohn Forte { 371fcf3ce44SJohn Forte ql_adapter_state_t *ha = vha->pha; 372fcf3ce44SJohn Forte 373fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 374fcf3ce44SJohn Forte 375fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): req packet:\n", ha->instance); 376fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)ha->request_ring_ptr, 8, REQUEST_ENTRY_SIZE); 377fcf3ce44SJohn Forte 378fcf3ce44SJohn Forte /* Sync DMA buffer. */ 379fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 380fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 381fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), (size_t)REQUEST_ENTRY_SIZE, 382fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 383fcf3ce44SJohn Forte 384fcf3ce44SJohn Forte /* Adjust ring index. */ 385fcf3ce44SJohn Forte ha->req_ring_index++; 386fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 387fcf3ce44SJohn Forte ha->req_ring_index = 0; 388fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 389fcf3ce44SJohn Forte } else { 390fcf3ce44SJohn Forte ha->request_ring_ptr++; 391fcf3ce44SJohn Forte } 392fcf3ce44SJohn Forte 393fcf3ce44SJohn Forte /* Set chip new ring index. */ 394eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_8021)) { 395eb82ff87SDaniel Beauregard uint32_t w32; 396eb82ff87SDaniel Beauregard 397eb82ff87SDaniel Beauregard w32 = ha->req_ring_index << 16 | 398eb82ff87SDaniel Beauregard ha->function_number << 5 | 4; 399eb82ff87SDaniel Beauregard do { 400eb82ff87SDaniel Beauregard ddi_put32(ha->db_dev_handle, ha->nx_req_in, w32); 401eb82ff87SDaniel Beauregard } while (RD_REG_DWORD(ha, ha->db_read) != w32); 402eb82ff87SDaniel Beauregard 403eb82ff87SDaniel Beauregard } else { 404eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, req_in, ha->req_ring_index); 405eb82ff87SDaniel Beauregard } 406fcf3ce44SJohn Forte 407fcf3ce44SJohn Forte /* Release ring lock. */ 408fcf3ce44SJohn Forte REQUEST_RING_UNLOCK(ha); 409fcf3ce44SJohn Forte 410fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 411fcf3ce44SJohn Forte } 412fcf3ce44SJohn Forte 413fcf3ce44SJohn Forte /* 414fcf3ce44SJohn Forte * ql_command_iocb 415fcf3ce44SJohn Forte * Setup of command IOCB. 416fcf3ce44SJohn Forte * 417fcf3ce44SJohn Forte * Input: 418fcf3ce44SJohn Forte * ha: adapter state pointer. 419fcf3ce44SJohn Forte * sp: srb structure pointer. 420fcf3ce44SJohn Forte * 421fcf3ce44SJohn Forte * arg: request queue packet. 422fcf3ce44SJohn Forte * 423fcf3ce44SJohn Forte * Context: 424fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 425fcf3ce44SJohn Forte */ 426fcf3ce44SJohn Forte void 427fcf3ce44SJohn Forte ql_command_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 428fcf3ce44SJohn Forte { 429fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 430fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 431fcf3ce44SJohn Forte uint16_t seg_cnt; 432fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 433fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 434fcf3ce44SJohn Forte cmd_entry_t *pkt = arg; 435fcf3ce44SJohn Forte 436fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 437fcf3ce44SJohn Forte 438fcf3ce44SJohn Forte /* Set LUN number */ 439fcf3ce44SJohn Forte pkt->lun_l = LSB(sp->lun_queue->lun_no); 440fcf3ce44SJohn Forte pkt->lun_h = MSB(sp->lun_queue->lun_no); 441fcf3ce44SJohn Forte 442fcf3ce44SJohn Forte /* Set target ID */ 443fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 444fcf3ce44SJohn Forte pkt->target_l = LSB(tq->loop_id); 445fcf3ce44SJohn Forte pkt->target_h = MSB(tq->loop_id); 446fcf3ce44SJohn Forte } else { 447fcf3ce44SJohn Forte pkt->target_h = LSB(tq->loop_id); 448fcf3ce44SJohn Forte } 449fcf3ce44SJohn Forte 450fcf3ce44SJohn Forte /* Set tag queue control flags */ 451fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) { 452fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 453fcf3ce44SJohn Forte (pkt->control_flags_l | CF_HTAG); 454fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) { 455fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 456fcf3ce44SJohn Forte (pkt->control_flags_l | CF_OTAG); 457fcf3ce44SJohn Forte /* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */ 458fcf3ce44SJohn Forte } else { 459fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 460fcf3ce44SJohn Forte (pkt->control_flags_l | CF_STAG); 461fcf3ce44SJohn Forte } 462fcf3ce44SJohn Forte 463fcf3ce44SJohn Forte /* Set ISP command timeout. */ 464fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 465fcf3ce44SJohn Forte 466fcf3ce44SJohn Forte /* Load SCSI CDB */ 467fcf3ce44SJohn Forte ddi_rep_put8(ha->hba_buf.acc_handle, fcp->fcp_cdb, 468fcf3ce44SJohn Forte pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR); 469fcf3ce44SJohn Forte 470fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 471fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_3; 472fcf3ce44SJohn Forte cnt = CMD_TYPE_3_DATA_SEGMENTS; 473fcf3ce44SJohn Forte } else { 474fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_2; 475fcf3ce44SJohn Forte cnt = CMD_TYPE_2_DATA_SEGMENTS; 476fcf3ce44SJohn Forte } 477fcf3ce44SJohn Forte 478fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 479fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 480fcf3ce44SJohn Forte ha->xioctl->IOControlRequests++; 481fcf3ce44SJohn Forte return; 482fcf3ce44SJohn Forte } 483fcf3ce44SJohn Forte 484fcf3ce44SJohn Forte /* 485fcf3ce44SJohn Forte * Set transfer direction. Load Data segments. 486fcf3ce44SJohn Forte */ 487fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 488fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 489fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_OUT); 490fcf3ce44SJohn Forte ha->xioctl->IOOutputRequests++; 491fcf3ce44SJohn Forte ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 492fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 493fcf3ce44SJohn Forte pkt->control_flags_l = (uint8_t) 494fcf3ce44SJohn Forte (pkt->control_flags_l | CF_DATA_IN); 495fcf3ce44SJohn Forte ha->xioctl->IOInputRequests++; 496fcf3ce44SJohn Forte ha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 497fcf3ce44SJohn Forte } 498fcf3ce44SJohn Forte 499fcf3ce44SJohn Forte /* Set data segment count. */ 500fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 501fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 502fcf3ce44SJohn Forte 503fcf3ce44SJohn Forte /* Load total byte count. */ 504fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, fcp->fcp_data_len); 505fcf3ce44SJohn Forte 506fcf3ce44SJohn Forte /* Load command data segment. */ 507fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 508fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 509fcf3ce44SJohn Forte while (cnt && seg_cnt) { 510fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 511fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 512fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 513fcf3ce44SJohn Forte cp->dmac_notused); 514fcf3ce44SJohn Forte } 515fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 516fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 517fcf3ce44SJohn Forte seg_cnt--; 518fcf3ce44SJohn Forte cnt--; 519fcf3ce44SJohn Forte cp++; 520fcf3ce44SJohn Forte } 521fcf3ce44SJohn Forte 522fcf3ce44SJohn Forte /* 523fcf3ce44SJohn Forte * Build continuation packets. 524fcf3ce44SJohn Forte */ 525fcf3ce44SJohn Forte if (seg_cnt) { 526fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 527fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 528fcf3ce44SJohn Forte } 529fcf3ce44SJohn Forte 530fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 531fcf3ce44SJohn Forte } 532fcf3ce44SJohn Forte 533fcf3ce44SJohn Forte /* 534fcf3ce44SJohn Forte * ql_continuation_iocb 535fcf3ce44SJohn Forte * Setup of continuation IOCB. 536fcf3ce44SJohn Forte * 537fcf3ce44SJohn Forte * Input: 538fcf3ce44SJohn Forte * ha: adapter state pointer. 539fcf3ce44SJohn Forte * cp: cookie list pointer. 540fcf3ce44SJohn Forte * seg_cnt: number of segments. 541fcf3ce44SJohn Forte * addr64: 64 bit addresses. 542fcf3ce44SJohn Forte * 543fcf3ce44SJohn Forte * Context: 544fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 545fcf3ce44SJohn Forte */ 546fcf3ce44SJohn Forte static void 547fcf3ce44SJohn Forte ql_continuation_iocb(ql_adapter_state_t *ha, ddi_dma_cookie_t *cp, 548fcf3ce44SJohn Forte uint16_t seg_cnt, boolean_t addr64) 549fcf3ce44SJohn Forte { 550fcf3ce44SJohn Forte cont_entry_t *pkt; 551fcf3ce44SJohn Forte uint64_t *ptr64; 552fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 553fcf3ce44SJohn Forte 554fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 555fcf3ce44SJohn Forte 556fcf3ce44SJohn Forte /* 557fcf3ce44SJohn Forte * Build continuation packets. 558fcf3ce44SJohn Forte */ 559fcf3ce44SJohn Forte while (seg_cnt) { 560fcf3ce44SJohn Forte /* Sync DMA buffer. */ 561fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 562fcf3ce44SJohn Forte (off_t)(ha->req_ring_index * REQUEST_ENTRY_SIZE + 563fcf3ce44SJohn Forte REQUEST_Q_BUFFER_OFFSET), REQUEST_ENTRY_SIZE, 564fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 565fcf3ce44SJohn Forte 566fcf3ce44SJohn Forte /* Adjust ring pointer, and deal with wrap. */ 567fcf3ce44SJohn Forte ha->req_ring_index++; 568fcf3ce44SJohn Forte if (ha->req_ring_index == REQUEST_ENTRY_CNT) { 569fcf3ce44SJohn Forte ha->req_ring_index = 0; 570fcf3ce44SJohn Forte ha->request_ring_ptr = ha->request_ring_bp; 571fcf3ce44SJohn Forte } else { 572fcf3ce44SJohn Forte ha->request_ring_ptr++; 573fcf3ce44SJohn Forte } 574fcf3ce44SJohn Forte pkt = (cont_entry_t *)ha->request_ring_ptr; 575fcf3ce44SJohn Forte 576fcf3ce44SJohn Forte /* Zero out packet. */ 577fcf3ce44SJohn Forte ptr64 = (uint64_t *)pkt; 578fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 579fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 580fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64++ = 0; 581fcf3ce44SJohn Forte *ptr64++ = 0; *ptr64 = 0; 582fcf3ce44SJohn Forte 583fcf3ce44SJohn Forte /* 584fcf3ce44SJohn Forte * Build continuation packet. 585fcf3ce44SJohn Forte */ 586fcf3ce44SJohn Forte pkt->entry_count = 1; 587fcf3ce44SJohn Forte pkt->sys_define = (uint8_t)ha->req_ring_index; 588fcf3ce44SJohn Forte if (addr64) { 589fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_1; 590fcf3ce44SJohn Forte cnt = CONT_TYPE_1_DATA_SEGMENTS; 591fcf3ce44SJohn Forte ptr32 = (uint32_t *) 592fcf3ce44SJohn Forte &((cont_type_1_entry_t *)pkt)->dseg_0_address; 593fcf3ce44SJohn Forte while (cnt && seg_cnt) { 594fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 595fcf3ce44SJohn Forte cp->dmac_address); 596fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 597fcf3ce44SJohn Forte cp->dmac_notused); 598fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 599fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 600fcf3ce44SJohn Forte seg_cnt--; 601fcf3ce44SJohn Forte cnt--; 602fcf3ce44SJohn Forte cp++; 603fcf3ce44SJohn Forte } 604fcf3ce44SJohn Forte } else { 605fcf3ce44SJohn Forte pkt->entry_type = CONTINUATION_TYPE_0; 606fcf3ce44SJohn Forte cnt = CONT_TYPE_0_DATA_SEGMENTS; 607fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 608fcf3ce44SJohn Forte while (cnt && seg_cnt) { 609fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 610fcf3ce44SJohn Forte cp->dmac_address); 611fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 612fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 613fcf3ce44SJohn Forte seg_cnt--; 614fcf3ce44SJohn Forte cnt--; 615fcf3ce44SJohn Forte cp++; 616fcf3ce44SJohn Forte } 617fcf3ce44SJohn Forte } 618fcf3ce44SJohn Forte 619fcf3ce44SJohn Forte QL_PRINT_5(CE_CONT, "(%d): packet:\n", ha->instance); 620fcf3ce44SJohn Forte QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE); 621fcf3ce44SJohn Forte } 622fcf3ce44SJohn Forte 623fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 624fcf3ce44SJohn Forte } 625fcf3ce44SJohn Forte 626fcf3ce44SJohn Forte /* 627fcf3ce44SJohn Forte * ql_command_24xx_iocb 628fcf3ce44SJohn Forte * Setup of ISP24xx command IOCB. 629fcf3ce44SJohn Forte * 630fcf3ce44SJohn Forte * Input: 631fcf3ce44SJohn Forte * ha: adapter state pointer. 632fcf3ce44SJohn Forte * sp: srb structure pointer. 633fcf3ce44SJohn Forte * arg: request queue packet. 634fcf3ce44SJohn Forte * 635fcf3ce44SJohn Forte * Context: 636fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 637fcf3ce44SJohn Forte */ 638fcf3ce44SJohn Forte void 639fcf3ce44SJohn Forte ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 640fcf3ce44SJohn Forte { 641fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 642fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 643fcf3ce44SJohn Forte uint16_t seg_cnt; 644fcf3ce44SJohn Forte fcp_cmd_t *fcp = sp->fcp; 645fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 646*f885d00fSDaniel Beauregard cmd7_24xx_entry_t *pkt = arg; 647fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 648fcf3ce44SJohn Forte 649fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 650fcf3ce44SJohn Forte 651*f885d00fSDaniel Beauregard if (fcp->fcp_data_len != 0 && sp->sg_dma.dma_handle != NULL && 652*f885d00fSDaniel Beauregard sp->pkt->pkt_data_cookie_cnt > 1) { 653*f885d00fSDaniel Beauregard ql_cmd_24xx_type_6_iocb(ha, sp, arg); 654*f885d00fSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): cmd6 exit\n", ha->instance); 655*f885d00fSDaniel Beauregard return; 656*f885d00fSDaniel Beauregard } 657*f885d00fSDaniel Beauregard 658fcf3ce44SJohn Forte pkt->entry_type = IOCB_CMD_TYPE_7; 659fcf3ce44SJohn Forte 660fcf3ce44SJohn Forte /* Set LUN number */ 661fcf3ce44SJohn Forte pkt->fcp_lun[2] = LSB(sp->lun_queue->lun_no); 662fcf3ce44SJohn Forte pkt->fcp_lun[3] = MSB(sp->lun_queue->lun_no); 663fcf3ce44SJohn Forte 664fcf3ce44SJohn Forte /* Set N_port handle */ 665fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 666fcf3ce44SJohn Forte 667fcf3ce44SJohn Forte /* Set target ID */ 668fcf3ce44SJohn Forte pkt->target_id[0] = tq->d_id.b.al_pa; 669fcf3ce44SJohn Forte pkt->target_id[1] = tq->d_id.b.area; 670fcf3ce44SJohn Forte pkt->target_id[2] = tq->d_id.b.domain; 671fcf3ce44SJohn Forte 672fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 673fcf3ce44SJohn Forte 674fcf3ce44SJohn Forte /* Set ISP command timeout. */ 675fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 676fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 677fcf3ce44SJohn Forte sp->isp_timeout); 678fcf3ce44SJohn Forte } 679fcf3ce44SJohn Forte 680fcf3ce44SJohn Forte /* Load SCSI CDB */ 681fcf3ce44SJohn Forte ddi_rep_put8(pha->hba_buf.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb, 682fcf3ce44SJohn Forte MAX_CMDSZ, DDI_DEV_AUTOINCR); 683fcf3ce44SJohn Forte for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) { 684fcf3ce44SJohn Forte ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4); 685fcf3ce44SJohn Forte } 686fcf3ce44SJohn Forte 687fcf3ce44SJohn Forte /* 688fcf3ce44SJohn Forte * Set tag queue control flags 689fcf3ce44SJohn Forte * Note: 690fcf3ce44SJohn Forte * Cannot copy fcp->fcp_cntl.cntl_qtype directly, 691fcf3ce44SJohn Forte * problem with x86 in 32bit kernel mode 692fcf3ce44SJohn Forte */ 693fcf3ce44SJohn Forte switch (fcp->fcp_cntl.cntl_qtype) { 694fcf3ce44SJohn Forte case FCP_QTYPE_SIMPLE: 695fcf3ce44SJohn Forte pkt->task = TA_STAG; 696fcf3ce44SJohn Forte break; 697fcf3ce44SJohn Forte case FCP_QTYPE_HEAD_OF_Q: 698fcf3ce44SJohn Forte pkt->task = TA_HTAG; 699fcf3ce44SJohn Forte break; 700fcf3ce44SJohn Forte case FCP_QTYPE_ORDERED: 701fcf3ce44SJohn Forte pkt->task = TA_OTAG; 702fcf3ce44SJohn Forte break; 703fcf3ce44SJohn Forte case FCP_QTYPE_ACA_Q_TAG: 704fcf3ce44SJohn Forte pkt->task = TA_ACA; 705fcf3ce44SJohn Forte break; 706fcf3ce44SJohn Forte case FCP_QTYPE_UNTAGGED: 707fcf3ce44SJohn Forte pkt->task = TA_UNTAGGED; 708fcf3ce44SJohn Forte break; 709fcf3ce44SJohn Forte default: 710fcf3ce44SJohn Forte break; 711fcf3ce44SJohn Forte } 712fcf3ce44SJohn Forte 713fcf3ce44SJohn Forte if (fcp->fcp_data_len == 0) { 714fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 715fcf3ce44SJohn Forte pha->xioctl->IOControlRequests++; 716fcf3ce44SJohn Forte return; 717fcf3ce44SJohn Forte } 718fcf3ce44SJohn Forte 719fcf3ce44SJohn Forte /* Set transfer direction. */ 720fcf3ce44SJohn Forte if (fcp->fcp_cntl.cntl_write_data) { 721fcf3ce44SJohn Forte pkt->control_flags = CF_WR; 722fcf3ce44SJohn Forte pha->xioctl->IOOutputRequests++; 723fcf3ce44SJohn Forte pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 724fcf3ce44SJohn Forte } else if (fcp->fcp_cntl.cntl_read_data) { 725fcf3ce44SJohn Forte pkt->control_flags = CF_RD; 726fcf3ce44SJohn Forte pha->xioctl->IOInputRequests++; 727fcf3ce44SJohn Forte pha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 728fcf3ce44SJohn Forte } 729fcf3ce44SJohn Forte 730fcf3ce44SJohn Forte /* Set data segment count. */ 731fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 732fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 733fcf3ce44SJohn Forte 734fcf3ce44SJohn Forte /* Load total byte count. */ 735fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count, 736fcf3ce44SJohn Forte fcp->fcp_data_len); 737fcf3ce44SJohn Forte 738fcf3ce44SJohn Forte /* Load command data segment. */ 739fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 740fcf3ce44SJohn Forte cp = sp->pkt->pkt_data_cookie; 741fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 742fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 743fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 744fcf3ce44SJohn Forte seg_cnt--; 745fcf3ce44SJohn Forte cp++; 746fcf3ce44SJohn Forte 747fcf3ce44SJohn Forte /* 748fcf3ce44SJohn Forte * Build continuation packets. 749fcf3ce44SJohn Forte */ 750fcf3ce44SJohn Forte if (seg_cnt) { 751fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 752fcf3ce44SJohn Forte } 753fcf3ce44SJohn Forte 754fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 755fcf3ce44SJohn Forte } 756fcf3ce44SJohn Forte 757*f885d00fSDaniel Beauregard /* 758*f885d00fSDaniel Beauregard * ql_cmd_24xx_type_6_iocb 759*f885d00fSDaniel Beauregard * Setup of ISP24xx command type 6 IOCB. 760*f885d00fSDaniel Beauregard * 761*f885d00fSDaniel Beauregard * Input: 762*f885d00fSDaniel Beauregard * ha: adapter state pointer. 763*f885d00fSDaniel Beauregard * sp: srb structure pointer. 764*f885d00fSDaniel Beauregard * arg: request queue packet. 765*f885d00fSDaniel Beauregard * 766*f885d00fSDaniel Beauregard * Context: 767*f885d00fSDaniel Beauregard * Interrupt or Kernel context, no mailbox commands allowed. 768*f885d00fSDaniel Beauregard */ 769*f885d00fSDaniel Beauregard static void 770*f885d00fSDaniel Beauregard ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 771*f885d00fSDaniel Beauregard { 772*f885d00fSDaniel Beauregard uint64_t addr; 773*f885d00fSDaniel Beauregard ddi_dma_cookie_t *cp; 774*f885d00fSDaniel Beauregard uint32_t *ptr32; 775*f885d00fSDaniel Beauregard uint16_t seg_cnt; 776*f885d00fSDaniel Beauregard fcp_cmd_t *fcp = sp->fcp; 777*f885d00fSDaniel Beauregard ql_tgt_t *tq = sp->lun_queue->target_queue; 778*f885d00fSDaniel Beauregard cmd6_24xx_entry_t *pkt = arg; 779*f885d00fSDaniel Beauregard ql_adapter_state_t *pha = ha->pha; 780*f885d00fSDaniel Beauregard dma_mem_t *cmem = &sp->sg_dma; 781*f885d00fSDaniel Beauregard cmd6_2400_dma_t *cdma = cmem->bp; 782*f885d00fSDaniel Beauregard 783*f885d00fSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 784*f885d00fSDaniel Beauregard 785*f885d00fSDaniel Beauregard pkt->entry_type = IOCB_CMD_TYPE_6; 786*f885d00fSDaniel Beauregard 787*f885d00fSDaniel Beauregard bzero(cdma, sizeof (cmd6_2400_dma_t)); 788*f885d00fSDaniel Beauregard 789*f885d00fSDaniel Beauregard /* Set LUN number */ 790*f885d00fSDaniel Beauregard pkt->fcp_lun[2] = cdma->cmd.fcp_lun[1] = LSB(sp->lun_queue->lun_no); 791*f885d00fSDaniel Beauregard pkt->fcp_lun[3] = cdma->cmd.fcp_lun[0] = MSB(sp->lun_queue->lun_no); 792*f885d00fSDaniel Beauregard 793*f885d00fSDaniel Beauregard /* Set N_port handle */ 794*f885d00fSDaniel Beauregard ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 795*f885d00fSDaniel Beauregard 796*f885d00fSDaniel Beauregard /* Set target ID */ 797*f885d00fSDaniel Beauregard pkt->target_id[0] = tq->d_id.b.al_pa; 798*f885d00fSDaniel Beauregard pkt->target_id[1] = tq->d_id.b.area; 799*f885d00fSDaniel Beauregard pkt->target_id[2] = tq->d_id.b.domain; 800*f885d00fSDaniel Beauregard 801*f885d00fSDaniel Beauregard pkt->vp_index = ha->vp_index; 802*f885d00fSDaniel Beauregard 803*f885d00fSDaniel Beauregard /* Set ISP command timeout. */ 804*f885d00fSDaniel Beauregard if (sp->isp_timeout < 0x1999) { 805*f885d00fSDaniel Beauregard ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 806*f885d00fSDaniel Beauregard sp->isp_timeout); 807*f885d00fSDaniel Beauregard } 808*f885d00fSDaniel Beauregard 809*f885d00fSDaniel Beauregard /* Load SCSI CDB */ 810*f885d00fSDaniel Beauregard ddi_rep_put8(cmem->acc_handle, fcp->fcp_cdb, cdma->cmd.scsi_cdb, 811*f885d00fSDaniel Beauregard MAX_CMDSZ, DDI_DEV_AUTOINCR); 812*f885d00fSDaniel Beauregard 813*f885d00fSDaniel Beauregard /* 814*f885d00fSDaniel Beauregard * Set tag queue control flags 815*f885d00fSDaniel Beauregard * Note: 816*f885d00fSDaniel Beauregard * Cannot copy fcp->fcp_cntl.cntl_qtype directly, 817*f885d00fSDaniel Beauregard * problem with x86 in 32bit kernel mode 818*f885d00fSDaniel Beauregard */ 819*f885d00fSDaniel Beauregard switch (fcp->fcp_cntl.cntl_qtype) { 820*f885d00fSDaniel Beauregard case FCP_QTYPE_SIMPLE: 821*f885d00fSDaniel Beauregard cdma->cmd.task = TA_STAG; 822*f885d00fSDaniel Beauregard break; 823*f885d00fSDaniel Beauregard case FCP_QTYPE_HEAD_OF_Q: 824*f885d00fSDaniel Beauregard cdma->cmd.task = TA_HTAG; 825*f885d00fSDaniel Beauregard break; 826*f885d00fSDaniel Beauregard case FCP_QTYPE_ORDERED: 827*f885d00fSDaniel Beauregard cdma->cmd.task = TA_OTAG; 828*f885d00fSDaniel Beauregard break; 829*f885d00fSDaniel Beauregard case FCP_QTYPE_ACA_Q_TAG: 830*f885d00fSDaniel Beauregard cdma->cmd.task = TA_ACA; 831*f885d00fSDaniel Beauregard break; 832*f885d00fSDaniel Beauregard case FCP_QTYPE_UNTAGGED: 833*f885d00fSDaniel Beauregard cdma->cmd.task = TA_UNTAGGED; 834*f885d00fSDaniel Beauregard break; 835*f885d00fSDaniel Beauregard default: 836*f885d00fSDaniel Beauregard break; 837*f885d00fSDaniel Beauregard } 838*f885d00fSDaniel Beauregard 839*f885d00fSDaniel Beauregard /* 840*f885d00fSDaniel Beauregard * FCP_CMND Payload Data Segment 841*f885d00fSDaniel Beauregard */ 842*f885d00fSDaniel Beauregard cp = cmem->cookies; 843*f885d00fSDaniel Beauregard ddi_put16(pha->hba_buf.acc_handle, &pkt->cmnd_length, 844*f885d00fSDaniel Beauregard sizeof (fcp_cmnd_t)); 845*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->cmnd_address[0], 846*f885d00fSDaniel Beauregard cp->dmac_address); 847*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->cmnd_address[1], 848*f885d00fSDaniel Beauregard cp->dmac_notused); 849*f885d00fSDaniel Beauregard 850*f885d00fSDaniel Beauregard /* Set transfer direction. */ 851*f885d00fSDaniel Beauregard if (fcp->fcp_cntl.cntl_write_data) { 852*f885d00fSDaniel Beauregard pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_WR); 853*f885d00fSDaniel Beauregard cdma->cmd.control_flags = CF_WR; 854*f885d00fSDaniel Beauregard pha->xioctl->IOOutputRequests++; 855*f885d00fSDaniel Beauregard pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len; 856*f885d00fSDaniel Beauregard } else if (fcp->fcp_cntl.cntl_read_data) { 857*f885d00fSDaniel Beauregard pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_RD); 858*f885d00fSDaniel Beauregard cdma->cmd.control_flags = CF_RD; 859*f885d00fSDaniel Beauregard pha->xioctl->IOInputRequests++; 860*f885d00fSDaniel Beauregard pha->xioctl->IOInputByteCnt += fcp->fcp_data_len; 861*f885d00fSDaniel Beauregard } 862*f885d00fSDaniel Beauregard 863*f885d00fSDaniel Beauregard /* 864*f885d00fSDaniel Beauregard * FCP_DATA Data Segment Descriptor. 865*f885d00fSDaniel Beauregard */ 866*f885d00fSDaniel Beauregard addr = cp->dmac_laddress + sizeof (fcp_cmnd_t); 867*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_address[0], LSD(addr)); 868*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_address[1], MSD(addr)); 869*f885d00fSDaniel Beauregard 870*f885d00fSDaniel Beauregard /* Set data segment count. */ 871*f885d00fSDaniel Beauregard seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt; 872*f885d00fSDaniel Beauregard ddi_put16(pha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 873*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->dseg_0_length, 874*f885d00fSDaniel Beauregard seg_cnt * 12 + 12); 875*f885d00fSDaniel Beauregard 876*f885d00fSDaniel Beauregard /* Load total byte count. */ 877*f885d00fSDaniel Beauregard ddi_put32(pha->hba_buf.acc_handle, &pkt->total_byte_count, 878*f885d00fSDaniel Beauregard fcp->fcp_data_len); 879*f885d00fSDaniel Beauregard ddi_put32(cmem->acc_handle, &cdma->cmd.dl, (uint32_t)fcp->fcp_data_len); 880*f885d00fSDaniel Beauregard ql_chg_endian((uint8_t *)&cdma->cmd.dl, 4); 881*f885d00fSDaniel Beauregard 882*f885d00fSDaniel Beauregard /* Load command data segments. */ 883*f885d00fSDaniel Beauregard ptr32 = (uint32_t *)cdma->cookie_list; 884*f885d00fSDaniel Beauregard cp = sp->pkt->pkt_data_cookie; 885*f885d00fSDaniel Beauregard while (seg_cnt--) { 886*f885d00fSDaniel Beauregard ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_address); 887*f885d00fSDaniel Beauregard ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_notused); 888*f885d00fSDaniel Beauregard ddi_put32(cmem->acc_handle, ptr32++, (uint32_t)cp->dmac_size); 889*f885d00fSDaniel Beauregard cp++; 890*f885d00fSDaniel Beauregard } 891*f885d00fSDaniel Beauregard 892*f885d00fSDaniel Beauregard /* Sync DMA buffer. */ 893*f885d00fSDaniel Beauregard (void) ddi_dma_sync(cmem->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV); 894*f885d00fSDaniel Beauregard 895*f885d00fSDaniel Beauregard QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 896*f885d00fSDaniel Beauregard } 897*f885d00fSDaniel Beauregard 898fcf3ce44SJohn Forte /* 899fcf3ce44SJohn Forte * ql_marker 900fcf3ce44SJohn Forte * Function issues marker IOCB. 901fcf3ce44SJohn Forte * 902fcf3ce44SJohn Forte * Input: 903fcf3ce44SJohn Forte * ha: adapter state pointer. 904fcf3ce44SJohn Forte * loop_id: device loop ID 905fcf3ce44SJohn Forte * lun: device LUN 906fcf3ce44SJohn Forte * type: marker modifier 907fcf3ce44SJohn Forte * 908fcf3ce44SJohn Forte * Returns: 909fcf3ce44SJohn Forte * ql local function return status code. 910fcf3ce44SJohn Forte * 911fcf3ce44SJohn Forte * Context: 912fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 913fcf3ce44SJohn Forte */ 914fcf3ce44SJohn Forte int 915fcf3ce44SJohn Forte ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, uint16_t lun, 916fcf3ce44SJohn Forte uint8_t type) 917fcf3ce44SJohn Forte { 918fcf3ce44SJohn Forte mrk_entry_t *pkt; 919fcf3ce44SJohn Forte int rval; 920fcf3ce44SJohn Forte 921fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 922fcf3ce44SJohn Forte 923fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 924fcf3ce44SJohn Forte if (rval == QL_SUCCESS) { 925fcf3ce44SJohn Forte pkt->entry_type = MARKER_TYPE; 926fcf3ce44SJohn Forte 927eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 928fcf3ce44SJohn Forte marker_24xx_entry_t *pkt24 = 929fcf3ce44SJohn Forte (marker_24xx_entry_t *)pkt; 930fcf3ce44SJohn Forte 931fcf3ce44SJohn Forte pkt24->modifier = type; 932fcf3ce44SJohn Forte 933fcf3ce44SJohn Forte /* Set LUN number */ 934fcf3ce44SJohn Forte pkt24->fcp_lun[2] = LSB(lun); 935fcf3ce44SJohn Forte pkt24->fcp_lun[3] = MSB(lun); 936fcf3ce44SJohn Forte 937fcf3ce44SJohn Forte pkt24->vp_index = ha->vp_index; 938fcf3ce44SJohn Forte 939fcf3ce44SJohn Forte /* Set N_port handle */ 940fcf3ce44SJohn Forte ddi_put16(ha->pha->hba_buf.acc_handle, 941fcf3ce44SJohn Forte &pkt24->n_port_hdl, loop_id); 942fcf3ce44SJohn Forte 943fcf3ce44SJohn Forte } else { 944fcf3ce44SJohn Forte pkt->modifier = type; 945fcf3ce44SJohn Forte 946fcf3ce44SJohn Forte pkt->lun_l = LSB(lun); 947fcf3ce44SJohn Forte pkt->lun_h = MSB(lun); 948fcf3ce44SJohn Forte 949fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 950fcf3ce44SJohn Forte pkt->target_l = LSB(loop_id); 951fcf3ce44SJohn Forte pkt->target_h = MSB(loop_id); 952fcf3ce44SJohn Forte } else { 953fcf3ce44SJohn Forte pkt->target_h = LSB(loop_id); 954fcf3ce44SJohn Forte } 955fcf3ce44SJohn Forte } 956fcf3ce44SJohn Forte 957fcf3ce44SJohn Forte /* Issue command to ISP */ 958fcf3ce44SJohn Forte ql_isp_cmd(ha); 959fcf3ce44SJohn Forte } 960fcf3ce44SJohn Forte 961fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 962fcf3ce44SJohn Forte EL(ha, "failed, rval = %xh\n", rval); 963fcf3ce44SJohn Forte } else { 964fcf3ce44SJohn Forte /*EMPTY*/ 965fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 966fcf3ce44SJohn Forte } 967fcf3ce44SJohn Forte return (rval); 968fcf3ce44SJohn Forte } 969fcf3ce44SJohn Forte 970fcf3ce44SJohn Forte /* 971fcf3ce44SJohn Forte * ql_ms_iocb 972fcf3ce44SJohn Forte * Setup of name/management server IOCB. 973fcf3ce44SJohn Forte * 974fcf3ce44SJohn Forte * Input: 975fcf3ce44SJohn Forte * ha = adapter state pointer. 976fcf3ce44SJohn Forte * sp = srb structure pointer. 977fcf3ce44SJohn Forte * arg = request queue packet. 978fcf3ce44SJohn Forte * 979fcf3ce44SJohn Forte * Context: 980fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 981fcf3ce44SJohn Forte */ 982fcf3ce44SJohn Forte void 983fcf3ce44SJohn Forte ql_ms_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 984fcf3ce44SJohn Forte { 985fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 986fcf3ce44SJohn Forte uint32_t *ptr32; 987fcf3ce44SJohn Forte uint16_t seg_cnt; 988fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 989fcf3ce44SJohn Forte ms_entry_t *pkt = arg; 990fcf3ce44SJohn Forte 991fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 992fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 993fcf3ce44SJohn Forte /* 994fcf3ce44SJohn Forte * Build command packet. 995fcf3ce44SJohn Forte */ 996fcf3ce44SJohn Forte pkt->entry_type = MS_TYPE; 997fcf3ce44SJohn Forte 998fcf3ce44SJohn Forte /* Set loop ID */ 999fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 1000fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 1001fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 1002fcf3ce44SJohn Forte } else { 1003fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 1004fcf3ce44SJohn Forte } 1005fcf3ce44SJohn Forte 1006fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1007fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 1008fcf3ce44SJohn Forte 1009fcf3ce44SJohn Forte /* Set cmd data segment count. */ 1010fcf3ce44SJohn Forte pkt->cmd_dseg_count_l = 1; 1011fcf3ce44SJohn Forte 1012fcf3ce44SJohn Forte /* Set total data segment count */ 1013fcf3ce44SJohn Forte seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1); 1014fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->total_dseg_count, seg_cnt); 1015fcf3ce44SJohn Forte 1016fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 1017fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->cmd_byte_count, 1018fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1019fcf3ce44SJohn Forte 1020fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 1021fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->resp_byte_count, 1022fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 1023fcf3ce44SJohn Forte 1024fcf3ce44SJohn Forte /* Load MS command data segments. */ 1025fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1026fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1027fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1028fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1029fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 1030fcf3ce44SJohn Forte seg_cnt--; 1031fcf3ce44SJohn Forte 1032fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 1033fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 1034fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1035fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1036fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 1037fcf3ce44SJohn Forte seg_cnt--; 1038fcf3ce44SJohn Forte cp++; 1039fcf3ce44SJohn Forte 1040fcf3ce44SJohn Forte /* 1041fcf3ce44SJohn Forte * Build continuation packets. 1042fcf3ce44SJohn Forte */ 1043fcf3ce44SJohn Forte if (seg_cnt) { 1044fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 1045fcf3ce44SJohn Forte } 1046fcf3ce44SJohn Forte 1047fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1048fcf3ce44SJohn Forte } 1049fcf3ce44SJohn Forte 1050fcf3ce44SJohn Forte /* 1051fcf3ce44SJohn Forte * ql_ms_24xx_iocb 1052fcf3ce44SJohn Forte * Setup of name/management server IOCB. 1053fcf3ce44SJohn Forte * 1054fcf3ce44SJohn Forte * Input: 1055fcf3ce44SJohn Forte * ha: adapter state pointer. 1056fcf3ce44SJohn Forte * sp: srb structure pointer. 1057fcf3ce44SJohn Forte * arg: request queue packet. 1058fcf3ce44SJohn Forte * 1059fcf3ce44SJohn Forte * Context: 1060fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1061fcf3ce44SJohn Forte */ 1062fcf3ce44SJohn Forte void 1063fcf3ce44SJohn Forte ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1064fcf3ce44SJohn Forte { 1065fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1066fcf3ce44SJohn Forte uint32_t *ptr32; 1067fcf3ce44SJohn Forte uint16_t seg_cnt; 1068fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 1069fcf3ce44SJohn Forte ct_passthru_entry_t *pkt = arg; 1070fcf3ce44SJohn Forte ql_adapter_state_t *pha = ha->pha; 1071fcf3ce44SJohn Forte 1072fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1073fcf3ce44SJohn Forte QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen); 1074fcf3ce44SJohn Forte /* 1075fcf3ce44SJohn Forte * Build command packet. 1076fcf3ce44SJohn Forte */ 1077fcf3ce44SJohn Forte pkt->entry_type = CT_PASSTHRU_TYPE; 1078fcf3ce44SJohn Forte 1079fcf3ce44SJohn Forte /* Set loop ID */ 1080fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->n_port_hdl, tq->loop_id); 1081fcf3ce44SJohn Forte 1082fcf3ce44SJohn Forte pkt->vp_index = ha->vp_index; 1083fcf3ce44SJohn Forte 1084fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1085fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 1086fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->timeout, 1087fcf3ce44SJohn Forte sp->isp_timeout); 1088fcf3ce44SJohn Forte } 1089fcf3ce44SJohn Forte 1090fcf3ce44SJohn Forte /* Set cmd/response data segment counts. */ 1091fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->cmd_dseg_count, 1); 1092fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt; 1093fcf3ce44SJohn Forte ddi_put16(pha->hba_buf.acc_handle, &pkt->resp_dseg_count, seg_cnt); 1094fcf3ce44SJohn Forte 1095fcf3ce44SJohn Forte /* Load ct cmd byte count. */ 1096fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->cmd_byte_count, 1097fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1098fcf3ce44SJohn Forte 1099fcf3ce44SJohn Forte /* Load ct rsp byte count. */ 1100fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, &pkt->resp_byte_count, 1101fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_rsplen); 1102fcf3ce44SJohn Forte 1103fcf3ce44SJohn Forte /* Load MS command entry data segments. */ 1104fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1105fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1106fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1107fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1108fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, (uint32_t)cp->dmac_size); 1109fcf3ce44SJohn Forte 1110fcf3ce44SJohn Forte /* Load MS response entry data segments. */ 1111fcf3ce44SJohn Forte cp = sp->pkt->pkt_resp_cookie; 1112fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1113fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1114fcf3ce44SJohn Forte ddi_put32(pha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 1115fcf3ce44SJohn Forte seg_cnt--; 1116fcf3ce44SJohn Forte cp++; 1117fcf3ce44SJohn Forte 1118fcf3ce44SJohn Forte /* 1119fcf3ce44SJohn Forte * Build continuation packets. 1120fcf3ce44SJohn Forte */ 1121fcf3ce44SJohn Forte if (seg_cnt) { 1122fcf3ce44SJohn Forte ql_continuation_iocb(pha, cp, seg_cnt, B_TRUE); 1123fcf3ce44SJohn Forte } 1124fcf3ce44SJohn Forte 1125fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1126fcf3ce44SJohn Forte } 1127fcf3ce44SJohn Forte 1128fcf3ce44SJohn Forte /* 1129fcf3ce44SJohn Forte * ql_ip_iocb 1130fcf3ce44SJohn Forte * Setup of IP IOCB. 1131fcf3ce44SJohn Forte * 1132fcf3ce44SJohn Forte * Input: 1133fcf3ce44SJohn Forte * ha: adapter state pointer. 1134fcf3ce44SJohn Forte * sp: srb structure pointer. 1135fcf3ce44SJohn Forte * arg: request queue packet. 1136fcf3ce44SJohn Forte * 1137fcf3ce44SJohn Forte * Context: 1138fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1139fcf3ce44SJohn Forte */ 1140fcf3ce44SJohn Forte void 1141fcf3ce44SJohn Forte ql_ip_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1142fcf3ce44SJohn Forte { 1143fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1144fcf3ce44SJohn Forte uint32_t *ptr32, cnt; 1145fcf3ce44SJohn Forte uint16_t seg_cnt; 1146fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 1147fcf3ce44SJohn Forte ip_entry_t *pkt = arg; 1148fcf3ce44SJohn Forte 1149fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1150fcf3ce44SJohn Forte 1151fcf3ce44SJohn Forte /* Set loop ID */ 1152fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) { 1153fcf3ce44SJohn Forte pkt->loop_id_l = LSB(tq->loop_id); 1154fcf3ce44SJohn Forte pkt->loop_id_h = MSB(tq->loop_id); 1155fcf3ce44SJohn Forte } else { 1156fcf3ce44SJohn Forte pkt->loop_id_h = LSB(tq->loop_id); 1157fcf3ce44SJohn Forte } 1158fcf3ce44SJohn Forte 1159fcf3ce44SJohn Forte /* Set control flags */ 1160fcf3ce44SJohn Forte pkt->control_flags_l = BIT_6; 1161fcf3ce44SJohn Forte if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) { 1162fcf3ce44SJohn Forte pkt->control_flags_h = BIT_7; 1163fcf3ce44SJohn Forte } 1164fcf3ce44SJohn Forte 1165fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1166fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout, sp->isp_timeout); 1167fcf3ce44SJohn Forte 1168fcf3ce44SJohn Forte /* Set data segment count. */ 1169fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 1170fcf3ce44SJohn Forte /* Load total byte count. */ 1171fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 1172fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1173fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 1174fcf3ce44SJohn Forte 1175fcf3ce44SJohn Forte /* 1176fcf3ce44SJohn Forte * Build command packet. 1177fcf3ce44SJohn Forte */ 1178fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1179fcf3ce44SJohn Forte pkt->entry_type = IP_A64_TYPE; 1180fcf3ce44SJohn Forte cnt = IP_A64_DATA_SEGMENTS; 1181fcf3ce44SJohn Forte } else { 1182fcf3ce44SJohn Forte pkt->entry_type = IP_TYPE; 1183fcf3ce44SJohn Forte cnt = IP_DATA_SEGMENTS; 1184fcf3ce44SJohn Forte } 1185fcf3ce44SJohn Forte 1186fcf3ce44SJohn Forte /* Load command entry data segments. */ 1187fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1188fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1189fcf3ce44SJohn Forte while (cnt && seg_cnt) { 1190fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1191fcf3ce44SJohn Forte if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) { 1192fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1193fcf3ce44SJohn Forte cp->dmac_notused); 1194fcf3ce44SJohn Forte } 1195fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, 1196fcf3ce44SJohn Forte (uint32_t)cp->dmac_size); 1197fcf3ce44SJohn Forte seg_cnt--; 1198fcf3ce44SJohn Forte cnt--; 1199fcf3ce44SJohn Forte cp++; 1200fcf3ce44SJohn Forte } 1201fcf3ce44SJohn Forte 1202fcf3ce44SJohn Forte /* 1203fcf3ce44SJohn Forte * Build continuation packets. 1204fcf3ce44SJohn Forte */ 1205fcf3ce44SJohn Forte if (seg_cnt) { 1206fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, 1207fcf3ce44SJohn Forte (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING))); 1208fcf3ce44SJohn Forte } 1209fcf3ce44SJohn Forte 1210fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1211fcf3ce44SJohn Forte } 1212fcf3ce44SJohn Forte 1213fcf3ce44SJohn Forte /* 1214fcf3ce44SJohn Forte * ql_ip_24xx_iocb 1215fcf3ce44SJohn Forte * Setup of IP IOCB for ISP24xx. 1216fcf3ce44SJohn Forte * 1217fcf3ce44SJohn Forte * Input: 1218fcf3ce44SJohn Forte * ha: adapter state pointer. 1219fcf3ce44SJohn Forte * sp: srb structure pointer. 1220fcf3ce44SJohn Forte * arg: request queue packet. 1221fcf3ce44SJohn Forte * 1222fcf3ce44SJohn Forte * Context: 1223fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1224fcf3ce44SJohn Forte */ 1225fcf3ce44SJohn Forte void 1226fcf3ce44SJohn Forte ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_srb_t *sp, void *arg) 1227fcf3ce44SJohn Forte { 1228fcf3ce44SJohn Forte ddi_dma_cookie_t *cp; 1229fcf3ce44SJohn Forte uint32_t *ptr32; 1230fcf3ce44SJohn Forte uint16_t seg_cnt; 1231fcf3ce44SJohn Forte ql_tgt_t *tq = sp->lun_queue->target_queue; 1232fcf3ce44SJohn Forte ip_cmd_entry_t *pkt = arg; 1233fcf3ce44SJohn Forte 1234fcf3ce44SJohn Forte pkt->entry_type = IP_CMD_TYPE; 1235fcf3ce44SJohn Forte 1236fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1237fcf3ce44SJohn Forte 1238fcf3ce44SJohn Forte /* Set N_port handle */ 1239fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->hdl_status, tq->loop_id); 1240fcf3ce44SJohn Forte 1241fcf3ce44SJohn Forte /* Set ISP command timeout. */ 1242fcf3ce44SJohn Forte if (sp->isp_timeout < 0x1999) { 1243fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->timeout_hdl, 1244fcf3ce44SJohn Forte sp->isp_timeout); 1245fcf3ce44SJohn Forte } 1246fcf3ce44SJohn Forte 1247fcf3ce44SJohn Forte /* Set data segment count. */ 1248fcf3ce44SJohn Forte seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt; 1249fcf3ce44SJohn Forte /* Load total byte count. */ 1250fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &pkt->byte_count, 1251fcf3ce44SJohn Forte (uint32_t)sp->pkt->pkt_cmdlen); 1252fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->dseg_count, seg_cnt); 1253fcf3ce44SJohn Forte 1254fcf3ce44SJohn Forte /* Set control flags */ 1255fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->control_flags, 1256fcf3ce44SJohn Forte (uint16_t)(BIT_0)); 1257fcf3ce44SJohn Forte 1258fcf3ce44SJohn Forte /* Set frame header control flags */ 1259fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &pkt->frame_hdr_cntrl_flgs, 1260fcf3ce44SJohn Forte (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ)); 1261fcf3ce44SJohn Forte 1262fcf3ce44SJohn Forte /* Load command data segment. */ 1263fcf3ce44SJohn Forte ptr32 = (uint32_t *)&pkt->dseg_0_address; 1264fcf3ce44SJohn Forte cp = sp->pkt->pkt_cmd_cookie; 1265fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_address); 1266fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32++, cp->dmac_notused); 1267fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, ptr32, (uint32_t)cp->dmac_size); 1268fcf3ce44SJohn Forte seg_cnt--; 1269fcf3ce44SJohn Forte cp++; 1270fcf3ce44SJohn Forte 1271fcf3ce44SJohn Forte /* 1272fcf3ce44SJohn Forte * Build continuation packets. 1273fcf3ce44SJohn Forte */ 1274fcf3ce44SJohn Forte if (seg_cnt) { 1275fcf3ce44SJohn Forte ql_continuation_iocb(ha, cp, seg_cnt, B_TRUE); 1276fcf3ce44SJohn Forte } 1277fcf3ce44SJohn Forte 1278fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1279fcf3ce44SJohn Forte } 1280fcf3ce44SJohn Forte 1281fcf3ce44SJohn Forte /* 1282fcf3ce44SJohn Forte * ql_isp_rcvbuf 1283fcf3ce44SJohn Forte * Locates free buffers and places it on the receive buffer queue. 1284fcf3ce44SJohn Forte * 1285fcf3ce44SJohn Forte * Input: 1286fcf3ce44SJohn Forte * ha = adapter state pointer. 1287fcf3ce44SJohn Forte * 1288fcf3ce44SJohn Forte * Context: 1289fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1290fcf3ce44SJohn Forte */ 1291fcf3ce44SJohn Forte void 1292fcf3ce44SJohn Forte ql_isp_rcvbuf(ql_adapter_state_t *ha) 1293fcf3ce44SJohn Forte { 1294fcf3ce44SJohn Forte rcvbuf_t *container; 129516dd44c2SDaniel Beauregard uint16_t rcv_q_cnt; 1296fcf3ce44SJohn Forte uint16_t index = 0; 1297fcf3ce44SJohn Forte uint16_t index1 = 1; 1298fcf3ce44SJohn Forte int debounce_count = QL_MAX_DEBOUNCE; 1299fcf3ce44SJohn Forte ql_srb_t *sp; 1300fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1301fcf3ce44SJohn Forte int ring_updated = FALSE; 1302fcf3ce44SJohn Forte 1303eb82ff87SDaniel Beauregard if (CFG_IST(ha, CFG_CTRL_24258081)) { 1304fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ha); 1305fcf3ce44SJohn Forte return; 1306fcf3ce44SJohn Forte } 1307fcf3ce44SJohn Forte 1308fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1309fcf3ce44SJohn Forte 1310fcf3ce44SJohn Forte /* Acquire adapter state lock. */ 1311fcf3ce44SJohn Forte ADAPTER_STATE_LOCK(ha); 1312fcf3ce44SJohn Forte 1313fcf3ce44SJohn Forte /* Calculate number of free receive buffer entries. */ 1314eb82ff87SDaniel Beauregard index = RD16_IO_REG(ha, mailbox_out[8]); 1315fcf3ce44SJohn Forte do { 1316eb82ff87SDaniel Beauregard index1 = RD16_IO_REG(ha, mailbox_out[8]); 1317fcf3ce44SJohn Forte if (index1 == index) { 1318fcf3ce44SJohn Forte break; 1319fcf3ce44SJohn Forte } else { 1320fcf3ce44SJohn Forte index = index1; 1321fcf3ce44SJohn Forte } 1322fcf3ce44SJohn Forte } while (debounce_count --); 1323fcf3ce44SJohn Forte 1324fcf3ce44SJohn Forte if (debounce_count < 0) { 1325fcf3ce44SJohn Forte /* This should never happen */ 1326fcf3ce44SJohn Forte EL(ha, "max mb8 debounce retries exceeded\n"); 1327fcf3ce44SJohn Forte } 1328fcf3ce44SJohn Forte 1329fcf3ce44SJohn Forte rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ? 1330fcf3ce44SJohn Forte index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT - 1331fcf3ce44SJohn Forte (ha->rcvbuf_ring_index - index)); 1332fcf3ce44SJohn Forte 1333fcf3ce44SJohn Forte if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) { 1334fcf3ce44SJohn Forte rcv_q_cnt--; 1335fcf3ce44SJohn Forte } 1336fcf3ce44SJohn Forte 1337fcf3ce44SJohn Forte /* Load all free buffers in ISP receive buffer ring. */ 1338fcf3ce44SJohn Forte index = 0; 133916dd44c2SDaniel Beauregard while (rcv_q_cnt > (uint16_t)0 && index < QL_UB_LIMIT) { 1340fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1341fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1342fcf3ce44SJohn Forte while (index < QL_UB_LIMIT) { 1343fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1344fcf3ce44SJohn Forte if (ubp != NULL) { 1345fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1346fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1347fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1348fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1349fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1350fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1351fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1352fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1353fcf3ce44SJohn Forte break; 1354fcf3ce44SJohn Forte } 1355fcf3ce44SJohn Forte } 1356fcf3ce44SJohn Forte index++; 1357fcf3ce44SJohn Forte } 1358fcf3ce44SJohn Forte 1359fcf3ce44SJohn Forte if (index < QL_UB_LIMIT) { 1360fcf3ce44SJohn Forte rcv_q_cnt--; 1361fcf3ce44SJohn Forte index++; 1362fcf3ce44SJohn Forte container = ha->rcvbuf_ring_ptr; 1363fcf3ce44SJohn Forte 1364fcf3ce44SJohn Forte /* 1365fcf3ce44SJohn Forte * Build container. 1366fcf3ce44SJohn Forte */ 1367fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1368fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[0], 1369fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1370fcf3ce44SJohn Forte 1371fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, 1372fcf3ce44SJohn Forte (uint32_t *)(void *)&container->bufp[1], 1373fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1374fcf3ce44SJohn Forte 1375fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1376fcf3ce44SJohn Forte LSW(sp->handle)); 1377fcf3ce44SJohn Forte 1378fcf3ce44SJohn Forte ha->ub_outcnt++; 1379fcf3ce44SJohn Forte 1380fcf3ce44SJohn Forte /* Adjust ring index. */ 1381fcf3ce44SJohn Forte ha->rcvbuf_ring_index++; 1382fcf3ce44SJohn Forte if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) { 1383fcf3ce44SJohn Forte ha->rcvbuf_ring_index = 0; 1384fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr = ha->rcvbuf_ring_bp; 1385fcf3ce44SJohn Forte } else { 1386fcf3ce44SJohn Forte ha->rcvbuf_ring_ptr++; 1387fcf3ce44SJohn Forte } 1388fcf3ce44SJohn Forte 1389fcf3ce44SJohn Forte ring_updated = TRUE; 1390fcf3ce44SJohn Forte } 1391fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1392fcf3ce44SJohn Forte } 1393fcf3ce44SJohn Forte 1394fcf3ce44SJohn Forte if (ring_updated) { 1395fcf3ce44SJohn Forte /* Sync queue. */ 1396fcf3ce44SJohn Forte (void) ddi_dma_sync(ha->hba_buf.dma_handle, 1397fcf3ce44SJohn Forte (off_t)RCVBUF_Q_BUFFER_OFFSET, (size_t)RCVBUF_QUEUE_SIZE, 1398fcf3ce44SJohn Forte DDI_DMA_SYNC_FORDEV); 1399fcf3ce44SJohn Forte 1400fcf3ce44SJohn Forte /* Set chip new ring index. */ 1401eb82ff87SDaniel Beauregard WRT16_IO_REG(ha, mailbox_in[8], ha->rcvbuf_ring_index); 1402fcf3ce44SJohn Forte } 1403fcf3ce44SJohn Forte 1404fcf3ce44SJohn Forte /* Release adapter state lock. */ 1405fcf3ce44SJohn Forte ADAPTER_STATE_UNLOCK(ha); 1406fcf3ce44SJohn Forte 1407fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1408fcf3ce44SJohn Forte } 1409fcf3ce44SJohn Forte 1410fcf3ce44SJohn Forte /* 1411fcf3ce44SJohn Forte * ql_isp24xx_rcvbuf 1412fcf3ce44SJohn Forte * Locates free buffers and send it to adapter. 1413fcf3ce44SJohn Forte * 1414fcf3ce44SJohn Forte * Input: 1415fcf3ce44SJohn Forte * ha = adapter state pointer. 1416fcf3ce44SJohn Forte * 1417fcf3ce44SJohn Forte * Context: 1418fcf3ce44SJohn Forte * Interrupt or Kernel context, no mailbox commands allowed. 1419fcf3ce44SJohn Forte */ 1420fcf3ce44SJohn Forte static void 1421fcf3ce44SJohn Forte ql_isp24xx_rcvbuf(ql_adapter_state_t *ha) 1422fcf3ce44SJohn Forte { 1423fcf3ce44SJohn Forte rcvbuf_t *container; 1424fcf3ce44SJohn Forte uint16_t index; 1425fcf3ce44SJohn Forte ql_srb_t *sp; 1426fcf3ce44SJohn Forte fc_unsol_buf_t *ubp; 1427fcf3ce44SJohn Forte int rval; 1428fcf3ce44SJohn Forte ip_buf_pool_entry_t *pkt = NULL; 1429fcf3ce44SJohn Forte 1430fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): started\n", ha->instance); 1431fcf3ce44SJohn Forte 1432fcf3ce44SJohn Forte for (;;) { 1433fcf3ce44SJohn Forte /* Locate a buffer to give. */ 1434fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1435fcf3ce44SJohn Forte for (index = 0; index < QL_UB_LIMIT; index++) { 1436fcf3ce44SJohn Forte ubp = ha->ub_array[index]; 1437fcf3ce44SJohn Forte if (ubp != NULL) { 1438fcf3ce44SJohn Forte sp = ubp->ub_fca_private; 1439fcf3ce44SJohn Forte if ((sp->ub_type == FC_TYPE_IS8802_SNAP) && 1440fcf3ce44SJohn Forte (ha->flags & IP_INITIALIZED) && 1441fcf3ce44SJohn Forte (sp->flags & SRB_UB_IN_FCA) && 1442fcf3ce44SJohn Forte (!(sp->flags & (SRB_UB_IN_ISP | 1443fcf3ce44SJohn Forte SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK | 1444fcf3ce44SJohn Forte SRB_UB_ACQUIRED)))) { 1445fcf3ce44SJohn Forte ha->ub_outcnt++; 1446fcf3ce44SJohn Forte sp->flags |= SRB_UB_IN_ISP; 1447fcf3ce44SJohn Forte break; 1448fcf3ce44SJohn Forte } 1449fcf3ce44SJohn Forte } 1450fcf3ce44SJohn Forte } 1451fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1452fcf3ce44SJohn Forte if (index == QL_UB_LIMIT) { 1453fcf3ce44SJohn Forte break; 1454fcf3ce44SJohn Forte } 1455fcf3ce44SJohn Forte 1456fcf3ce44SJohn Forte /* Get IOCB packet for buffers. */ 1457fcf3ce44SJohn Forte if (pkt == NULL) { 1458fcf3ce44SJohn Forte rval = ql_req_pkt(ha, (request_t **)&pkt); 1459fcf3ce44SJohn Forte if (rval != QL_SUCCESS) { 1460fcf3ce44SJohn Forte EL(ha, "failed, ql_req_pkt=%x\n", rval); 1461fcf3ce44SJohn Forte QL_UB_LOCK(ha); 1462fcf3ce44SJohn Forte ha->ub_outcnt--; 1463fcf3ce44SJohn Forte sp->flags &= ~SRB_UB_IN_ISP; 1464fcf3ce44SJohn Forte QL_UB_UNLOCK(ha); 1465fcf3ce44SJohn Forte break; 1466fcf3ce44SJohn Forte } 1467fcf3ce44SJohn Forte pkt->entry_type = IP_BUF_POOL_TYPE; 1468fcf3ce44SJohn Forte container = &pkt->buffers[0]; 1469fcf3ce44SJohn Forte } 1470fcf3ce44SJohn Forte 1471fcf3ce44SJohn Forte /* 1472fcf3ce44SJohn Forte * Build container. 1473fcf3ce44SJohn Forte */ 1474fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[0], 1475fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_address); 1476fcf3ce44SJohn Forte ddi_put32(ha->hba_buf.acc_handle, &container->bufp[1], 1477fcf3ce44SJohn Forte sp->ub_buffer.cookie.dmac_notused); 1478fcf3ce44SJohn Forte ddi_put16(ha->hba_buf.acc_handle, &container->handle, 1479fcf3ce44SJohn Forte LSW(sp->handle)); 1480fcf3ce44SJohn Forte 1481fcf3ce44SJohn Forte pkt->buffer_count++; 1482fcf3ce44SJohn Forte container++; 1483fcf3ce44SJohn Forte 1484fcf3ce44SJohn Forte if (pkt->buffer_count == IP_POOL_BUFFERS) { 1485fcf3ce44SJohn Forte ql_isp_cmd(ha); 1486fcf3ce44SJohn Forte pkt = NULL; 1487fcf3ce44SJohn Forte } 1488fcf3ce44SJohn Forte } 1489fcf3ce44SJohn Forte 1490fcf3ce44SJohn Forte if (pkt != NULL) { 1491fcf3ce44SJohn Forte ql_isp_cmd(ha); 1492fcf3ce44SJohn Forte } 1493fcf3ce44SJohn Forte 1494fcf3ce44SJohn Forte QL_PRINT_3(CE_CONT, "(%d): done\n", ha->instance); 1495fcf3ce44SJohn Forte } 1496