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