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