Print this page
NEX-5717 import QLogic 16G FC drivers
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>


   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) {


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 }


   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 2015 QLogic Corporation */
  23 
  24 /*
  25  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  26  */
  27 
  28 #pragma ident   "Copyright 2015 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-2015 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_nx.h>
  49 #include <ql_xioctl.h>
  50 #include <ql_fm.h>
  51 
  52 
  53 /*
  54  * Local Function Prototypes.
  55  */
  56 static int ql_req_pkt(ql_adapter_state_t *, ql_request_q_t *, request_t **);
  57 static void ql_isp_cmd(ql_adapter_state_t *, ql_request_q_t *);
  58 static void ql_continuation_iocb(ql_adapter_state_t *, ql_request_q_t *,
  59     ddi_dma_cookie_t *, uint16_t, boolean_t);
  60 static void ql_isp24xx_rcvbuf(ql_adapter_state_t *);
  61 static void ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *, ql_request_q_t *,
  62     ql_srb_t *, void *);
  63 
  64 /*
  65  * ql_start_iocb
  66  *      The start IOCB is responsible for building request packets
  67  *      on request ring and modifying ISP input pointer.
  68  *
  69  * Input:
  70  *      ha:     adapter state pointer.
  71  *      sp:     srb structure pointer.
  72  *
  73  * Context:
  74  *      Interrupt or Kernel context, no mailbox commands allowed.
  75  */
  76 void
  77 ql_start_iocb(ql_adapter_state_t *vha, ql_srb_t *sp)
  78 {
  79         ql_link_t               *link;
  80         ql_request_q_t          *req_q;
  81         request_t               *pkt;
  82         uint64_t                *ptr64;
  83         uint32_t                cnt;
  84         ql_adapter_state_t      *ha = vha->pha;
  85 
  86         QL_PRINT_3(ha, "started\n");
  87 
  88         /* Acquire ring lock. */
  89         REQUEST_RING_LOCK(ha);
  90 
  91         if (sp != NULL) {
  92                 /*
  93                  * If the pending queue is not empty maintain order
  94                  * by puting this srb at the tail and geting the head.
  95                  */
  96                 if ((link = ha->pending_cmds.first) != NULL) {
  97                         ql_add_link_b(&ha->pending_cmds, &sp->cmd);
  98                         /* Remove command from pending command queue */
  99                         sp = link->base_address;
 100                         ql_remove_link(&ha->pending_cmds, &sp->cmd);
 101                 }
 102         } else {
 103                 /* Get command from pending command queue if not empty. */
 104                 if ((link = ha->pending_cmds.first) == NULL) {
 105                         /* Release ring specific lock */
 106                         REQUEST_RING_UNLOCK(ha);
 107                         QL_PRINT_3(ha, "empty done\n");

 108                         return;
 109                 }
 110                 /* Remove command from pending command queue */
 111                 sp = link->base_address;
 112                 ql_remove_link(&ha->pending_cmds, &sp->cmd);
 113         }
 114 
 115         /* start this request and as many others as possible */
 116         for (;;) {
 117                 if (ha->req_q[1] != NULL && sp->rsp_q_number != 0) {
 118                         req_q = ha->req_q[1];
 119                 } else {
 120                         req_q = ha->req_q[0];
 121                 }
 122 
 123                 if (req_q->req_q_cnt < sp->req_cnt) {
 124                         /* Calculate number of free request entries. */
 125                         if (ha->flags & QUEUE_SHADOW_PTRS) {
 126                                 (void) ddi_dma_sync(req_q->req_ring.dma_handle,
 127                                     (off_t)req_q->req_out_shadow_ofst,
 128                                     SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
 129                                 cnt = ddi_get32(req_q->req_ring.acc_handle,
 130                                     req_q->req_out_shadow_ptr);
 131                         } else if (ha->flags & MULTI_QUEUE) {
 132                                 cnt = RD16_MBAR_REG(ha, req_q->mbar_req_out);
 133                         } else {
 134                                 cnt = RD16_IO_REG(ha, req_out);
 135                         }
 136                         if (req_q->req_ring_index < cnt) {
 137                                 req_q->req_q_cnt = (uint16_t)
 138                                     (cnt - req_q->req_ring_index);
 139                         } else {
 140                                 req_q->req_q_cnt =
 141                                     (uint16_t)(req_q->req_entry_cnt -
 142                                     (req_q->req_ring_index - cnt));
 143                         }
 144                         if (req_q->req_q_cnt != 0) {
 145                                 req_q->req_q_cnt--;
 146                         }
 147 
 148                         /*
 149                          * If no room in request ring put this srb at
 150                          * the head of the pending queue and exit.
 151                          */
 152                         if (req_q->req_q_cnt < sp->req_cnt) {
 153                                 QL_PRINT_8(ha, "request ring full,"
 154                                     " req_q_cnt=%d, req_ring_index=%d\n",
 155                                     req_q->req_q_cnt, req_q->req_ring_index);

 156                                 ql_add_link_t(&ha->pending_cmds, &sp->cmd);
 157                                 break;
 158                         }
 159                 }
 160 
 161                 /* Check for room in outstanding command list. */
 162                 for (cnt = 1; cnt < ha->osc_max_cnt; cnt++) {
 163                         ha->osc_index++;
 164                         if (ha->osc_index == ha->osc_max_cnt) {
 165                                 ha->osc_index = 1;
 166                         }
 167                         if (ha->outstanding_cmds[ha->osc_index] == NULL) {
 168                                 break;
 169                         }
 170                 }
 171                 /*
 172                  * If no room in outstanding array put this srb at
 173                  * the head of the pending queue and exit.
 174                  */
 175                 if (cnt == ha->osc_max_cnt) {
 176                         QL_PRINT_8(ha, "no room in outstanding array\n");

 177                         ql_add_link_t(&ha->pending_cmds, &sp->cmd);
 178                         break;
 179                 }
 180 
 181                 /* nothing to stop us now. */
 182                 ha->outstanding_cmds[ha->osc_index] = sp;
 183                 /* create and save a unique response identifier in the srb */
 184                 sp->handle = ha->adapter_stats->ncmds << OSC_INDEX_SHIFT |
 185                     ha->osc_index;
 186                 req_q->req_q_cnt = (uint16_t)(req_q->req_q_cnt - sp->req_cnt);
 187 
 188                 /* build the iocb in the request ring */
 189                 pkt = req_q->req_ring_ptr;
 190                 sp->request_ring_ptr = pkt;
 191                 sp->req_q_number = req_q->req_q_number;
 192                 sp->flags |= SRB_IN_TOKEN_ARRAY;
 193 
 194                 /* Zero out packet. */
 195                 ptr64 = (uint64_t *)pkt;
 196                 *ptr64++ = 0; *ptr64++ = 0;
 197                 *ptr64++ = 0; *ptr64++ = 0;
 198                 *ptr64++ = 0; *ptr64++ = 0;
 199                 *ptr64++ = 0; *ptr64 = 0;
 200 
 201                 /* Setup IOCB common data. */
 202                 pkt->entry_count = (uint8_t)sp->req_cnt;
 203                 if (ha->req_q[1] != NULL && sp->rsp_q_number != 0) {
 204                         pkt->entry_status = sp->rsp_q_number;
 205                 }
 206                 pkt->sys_define = (uint8_t)req_q->req_ring_index;
 207 
 208                 /* mark the iocb with the response identifier */
 209                 ddi_put32(req_q->req_ring.acc_handle, &pkt->handle,
 210                     (uint32_t)sp->handle);
 211 
 212                 /* Setup IOCB unique data. */
 213                 (sp->iocb)(vha, req_q, sp, pkt);
 214 
 215                 sp->flags |= SRB_ISP_STARTED;
 216 
 217                 QL_PRINT_5(ha, "req packet, sp=%p\n", (void *)sp);

 218                 QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
 219 
 220                 /* Sync DMA buffer. */
 221                 (void) ddi_dma_sync(req_q->req_ring.dma_handle,
 222                     (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
 223                     (size_t)REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);

 224 
 225                 /* Adjust ring index. */
 226                 req_q->req_ring_index++;
 227                 if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
 228                         req_q->req_ring_index = 0;
 229                         req_q->req_ring_ptr = req_q->req_ring.bp;
 230                 } else {
 231                         req_q->req_ring_ptr++;
 232                 }
 233 
 234                 /* Reset watchdog timer */
 235                 sp->wdg_q_time = sp->init_wdg_q_time;
 236 
 237                 /*
 238                  * Send it by setting the new ring index in the ISP Request
 239                  * Ring In Pointer register.  This is the mechanism
 240                  * used to notify the isp that a new iocb has been
 241                  * placed on the request ring.
 242                  */
 243                 if (ha->flags & MULTI_QUEUE) {
 244                         WR16_MBAR_REG(ha, req_q->mbar_req_in,
 245                             req_q->req_ring_index);
 246                 } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
 247                         ql_8021_wr_req_in(ha, req_q->req_ring_index);





 248                 } else {
 249                         WRT16_IO_REG(ha, req_in, req_q->req_ring_index);
 250                 }
 251 
 252                 /* Update outstanding command count statistic. */
 253                 ha->adapter_stats->ncmds++;
 254 
 255                 /* if there is a pending command, try to start it. */
 256                 if ((link = ha->pending_cmds.first) == NULL) {
 257                         break;
 258                 }
 259 
 260                 /* Remove command from pending command queue */
 261                 sp = link->base_address;
 262                 ql_remove_link(&ha->pending_cmds, &sp->cmd);
 263         }
 264 
 265         if (qlc_fm_check_acc_handle(ha, ha->dev_handle)
 266             != DDI_FM_OK) {
 267                 qlc_fm_report_err_impact(ha,
 268                     QL_FM_EREPORT_ACC_HANDLE_CHECK);
 269         }
 270 
 271         /* Release ring specific lock */
 272         REQUEST_RING_UNLOCK(ha);
 273 
 274         QL_PRINT_3(ha, "done\n");
 275 }
 276 
 277 /*
 278  * ql_req_pkt
 279  *      Function is responsible for locking ring and
 280  *      getting a zeroed out request packet.
 281  *
 282  * Input:
 283  *      ha:     adapter state pointer.
 284  *      req_q:  request queue structure pointer.
 285  *      pkt:    address for packet pointer.
 286  *
 287  * Returns:
 288  *      ql local function return status code.
 289  *
 290  * Context:
 291  *      Interrupt or Kernel context, no mailbox commands allowed.
 292  */
 293 static int
 294 ql_req_pkt(ql_adapter_state_t *vha, ql_request_q_t *req_q, request_t **pktp)
 295 {
 296         uint16_t                cnt;
 297         uint64_t                *ptr64;
 298         uint32_t                timer;
 299         int                     rval = QL_FUNCTION_TIMEOUT;
 300         ql_adapter_state_t      *ha = vha->pha;
 301 
 302         QL_PRINT_3(ha, "started\n");
 303 
 304         /* Wait for 30 seconds for slot. */
 305         for (timer = 30000; timer != 0; timer--) {
 306                 /* Acquire ring lock. */
 307                 REQUEST_RING_LOCK(ha);
 308 
 309                 if (req_q->req_q_cnt == 0) {
 310                         /* Calculate number of free request entries. */
 311                         if (ha->flags & QUEUE_SHADOW_PTRS) {
 312                                 (void) ddi_dma_sync(req_q->req_ring.dma_handle,
 313                                     (off_t)req_q->req_out_shadow_ofst,
 314                                     SHADOW_ENTRY_SIZE, DDI_DMA_SYNC_FORCPU);
 315                                 cnt = ddi_get32(req_q->req_ring.acc_handle,
 316                                     req_q->req_out_shadow_ptr);
 317                         } else if (ha->flags & MULTI_QUEUE) {
 318                                 cnt = RD16_MBAR_REG(ha, req_q->mbar_req_out);
 319                         } else {
 320                                 cnt = RD16_IO_REG(ha, req_out);
 321                         }
 322                         if (req_q->req_ring_index < cnt) {
 323                                 req_q->req_q_cnt = (uint16_t)
 324                                     (cnt - req_q->req_ring_index);
 325                         } else {
 326                                 req_q->req_q_cnt = (uint16_t)
 327                                     (REQUEST_ENTRY_CNT -
 328                                     (req_q->req_ring_index - cnt));
 329                         }
 330                         if (req_q->req_q_cnt != 0) {
 331                                 req_q->req_q_cnt--;
 332                         }
 333                 }
 334 
 335                 /* Found empty request ring slot? */
 336                 if (req_q->req_q_cnt != 0) {
 337                         req_q->req_q_cnt--;
 338                         *pktp = req_q->req_ring_ptr;
 339 
 340                         /* Zero out packet. */
 341                         ptr64 = (uint64_t *)req_q->req_ring_ptr;
 342                         *ptr64++ = 0; *ptr64++ = 0;
 343                         *ptr64++ = 0; *ptr64++ = 0;
 344                         *ptr64++ = 0; *ptr64++ = 0;
 345                         *ptr64++ = 0; *ptr64 = 0;
 346 
 347                         /* Setup IOCB common data. */
 348                         req_q->req_ring_ptr->entry_count = 1;
 349                         req_q->req_ring_ptr->sys_define =
 350                             (uint8_t)req_q->req_ring_index;
 351                         ddi_put32(req_q->req_ring.acc_handle,
 352                             &req_q->req_ring_ptr->handle,
 353                             (uint32_t)QL_FCA_BRAND);
 354 
 355                         rval = QL_SUCCESS;
 356 
 357                         break;
 358                 }
 359 
 360                 /* Release request queue lock. */
 361                 REQUEST_RING_UNLOCK(ha);
 362 
 363                 drv_usecwait(MILLISEC);
 364 
 365                 /* Check for pending interrupts. */
 366                 /*
 367                  * XXX protect interrupt routine from calling itself.
 368                  * Need to revisit this routine. So far we never
 369                  * hit this case as req slot was available
 370                  */
 371                 if ((!(curthread->t_flag & T_INTR_THREAD)) &&
 372                     INTERRUPT_PENDING(ha)) {
 373                         (void) ql_isr((caddr_t)ha);
 374                         INTR_LOCK(ha);
 375                         ha->intr_claimed = TRUE;
 376                         INTR_UNLOCK(ha);
 377                 }
 378         }
 379 
 380         if (rval != QL_SUCCESS) {
 381                 ql_awaken_task_daemon(ha, NULL, ISP_ABORT_NEEDED, 0);
 382                 EL(ha, "failed, rval = %xh, isp_abort_needed\n", rval);
 383         } else {
 384                 /*EMPTY*/
 385                 QL_PRINT_3(ha, "done\n");
 386         }
 387         return (rval);
 388 }
 389 
 390 /*
 391  * ql_isp_cmd
 392  *      Function is responsible for modifying ISP input pointer.
 393  *      This action notifies the isp that a new request has been
 394  *      added to the request ring.
 395  *
 396  *      Releases ring lock.
 397  *
 398  * Input:
 399  *      vha:    adapter state pointer.
 400  *      req_q:  request queue structure pointer.
 401  *
 402  * Context:
 403  *      Interrupt or Kernel context, no mailbox commands allowed.
 404  */
 405 static void
 406 ql_isp_cmd(ql_adapter_state_t *vha, ql_request_q_t *req_q)
 407 {
 408         ql_adapter_state_t      *ha = vha->pha;
 409 
 410         QL_PRINT_3(ha, "started\n");
 411 
 412         QL_PRINT_5(ha, "req packet:\n");
 413         QL_DUMP_5((uint8_t *)req_q->req_ring_ptr, 8, REQUEST_ENTRY_SIZE);
 414 
 415         /* Sync DMA buffer. */
 416         (void) ddi_dma_sync(req_q->req_ring.dma_handle,
 417             (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
 418             (size_t)REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);

 419 
 420         /* Adjust ring index. */
 421         req_q->req_ring_index++;
 422         if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
 423                 req_q->req_ring_index = 0;
 424                 req_q->req_ring_ptr = req_q->req_ring.bp;
 425         } else {
 426                 req_q->req_ring_ptr++;
 427         }
 428 
 429         /* Set chip new ring index. */
 430         if (ha->flags & MULTI_QUEUE) {
 431                 WR16_MBAR_REG(ha, req_q->mbar_req_in,
 432                     req_q->req_ring_index);
 433         } else if (CFG_IST(ha, CFG_CTRL_82XX)) {
 434                 ql_8021_wr_req_in(ha, req_q->req_ring_index);




 435         } else {
 436                 WRT16_IO_REG(ha, req_in, req_q->req_ring_index);
 437         }
 438 
 439         /* Release ring lock. */
 440         REQUEST_RING_UNLOCK(ha);
 441 
 442         QL_PRINT_3(ha, "done\n");
 443 }
 444 
 445 /*
 446  * ql_command_iocb
 447  *      Setup of command IOCB.
 448  *
 449  * Input:
 450  *      ha:     adapter state pointer.
 451  *      req_q:  request queue structure pointer.
 452  *      sp:     srb structure pointer.

 453  *      arg:    request queue packet.
 454  *
 455  * Context:
 456  *      Interrupt or Kernel context, no mailbox commands allowed.
 457  */
 458 void
 459 ql_command_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
 460     void *arg)
 461 {
 462         ddi_dma_cookie_t        *cp;
 463         uint32_t                *ptr32, cnt;
 464         uint16_t                seg_cnt;
 465         fcp_cmd_t               *fcp = sp->fcp;
 466         ql_tgt_t                *tq = sp->lun_queue->target_queue;
 467         cmd_entry_t             *pkt = arg;
 468         cmd_3_entry_t           *pkt3 = arg;
 469 
 470         QL_PRINT_3(ha, "started\n");
 471 
 472         /* Set LUN number */
 473         pkt->lun_l = LSB(sp->lun_queue->lun_no);
 474         pkt->lun_h = MSB(sp->lun_queue->lun_no);
 475 
 476         /* Set target ID */
 477         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
 478                 pkt->target_l = LSB(tq->loop_id);
 479                 pkt->target_h = MSB(tq->loop_id);
 480         } else {
 481                 pkt->target_h = LSB(tq->loop_id);
 482         }
 483 
 484         /* Set tag queue control flags */
 485         if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_HEAD_OF_Q) {
 486                 pkt->control_flags_l = (uint8_t)
 487                     (pkt->control_flags_l | CF_HTAG);
 488         } else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_ORDERED) {
 489                 pkt->control_flags_l = (uint8_t)
 490                     (pkt->control_flags_l | CF_OTAG);
 491         /* else if (fcp->fcp_cntl.cntl_qtype == FCP_QTYPE_SIMPLE) */
 492         } else {
 493                 pkt->control_flags_l = (uint8_t)
 494                     (pkt->control_flags_l | CF_STAG);
 495         }
 496 
 497         /* Set ISP command timeout. */
 498         ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
 499 
 500         /* Load SCSI CDB */
 501         ddi_rep_put8(req_q->req_ring.acc_handle, fcp->fcp_cdb,
 502             pkt->scsi_cdb, MAX_CMDSZ, DDI_DEV_AUTOINCR);
 503 








 504         if (fcp->fcp_data_len == 0) {
 505                 QL_PRINT_3(ha, "done\n");
 506                 pkt->entry_type = IOCB_CMD_TYPE_2;
 507                 ha->xioctl->IOControlRequests++;
 508                 return;
 509         }
 510 
 511         /*
 512          * Set transfer direction. Load Data segments.
 513          */
 514         if (fcp->fcp_cntl.cntl_write_data) {
 515                 pkt->control_flags_l = (uint8_t)
 516                     (pkt->control_flags_l | CF_DATA_OUT);
 517                 ha->xioctl->IOOutputRequests++;
 518                 ha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
 519         } else if (fcp->fcp_cntl.cntl_read_data) {
 520                 pkt->control_flags_l = (uint8_t)
 521                     (pkt->control_flags_l | CF_DATA_IN);
 522                 ha->xioctl->IOInputRequests++;
 523                 ha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
 524         }
 525 
 526         /* Set data segment count. */
 527         seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
 528         ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
 529 
 530         /* Load total byte count. */
 531         ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
 532             fcp->fcp_data_len);
 533 
 534         /* Load command data segment. */

 535         cp = sp->pkt->pkt_data_cookie;
 536 

 537         if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
 538                 pkt3->entry_type = IOCB_CMD_TYPE_3;
 539                 cnt = CMD_TYPE_3_DATA_SEGMENTS;
 540 
 541                 ptr32 = (uint32_t *)&pkt3->dseg;
 542                 while (cnt && seg_cnt) {
 543                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 544                             cp->dmac_address);
 545                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 546                             cp->dmac_notused);
 547                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 548                             (uint32_t)cp->dmac_size);
 549                         seg_cnt--;
 550                         cnt--;
 551                         cp++;
 552                 }
 553         } else {
 554                 pkt->entry_type = IOCB_CMD_TYPE_2;
 555                 cnt = CMD_TYPE_2_DATA_SEGMENTS;
 556 
 557                 ptr32 = (uint32_t *)&pkt->dseg;
 558                 while (cnt && seg_cnt) {
 559                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 560                             cp->dmac_address);
 561                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 562                             (uint32_t)cp->dmac_size);
 563                         seg_cnt--;
 564                         cnt--;
 565                         cp++;
 566                 }
 567         }
 568 
 569         /*
 570          * Build continuation packets.
 571          */
 572         if (seg_cnt) {
 573                 ql_continuation_iocb(ha, req_q, cp, seg_cnt,
 574                     (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
 575         }
 576 
 577         QL_PRINT_3(ha, "done\n");
 578 }
 579 
 580 /*
 581  * ql_continuation_iocb
 582  *      Setup of continuation IOCB.
 583  *
 584  * Input:
 585  *      ha:             adapter state pointer.
 586  *      req_q:          request queue structure pointer.
 587  *      cp:             cookie list pointer.
 588  *      seg_cnt:        number of segments.
 589  *      addr64:         64 bit addresses.
 590  *
 591  * Context:
 592  *      Interrupt or Kernel context, no mailbox commands allowed.
 593  */
 594 /* ARGSUSED */
 595 static void
 596 ql_continuation_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
 597     ddi_dma_cookie_t *cp, uint16_t seg_cnt, boolean_t addr64)
 598 {
 599         cont_entry_t            *pkt;
 600         cont_type_1_entry_t     *pkt1;
 601         uint64_t                *ptr64;
 602         uint32_t                *ptr32, cnt;
 603 
 604         QL_PRINT_3(ha, "started\n");
 605 
 606         /*
 607          * Build continuation packets.
 608          */
 609         while (seg_cnt) {
 610                 /* Sync DMA buffer. */
 611                 (void) ddi_dma_sync(req_q->req_ring.dma_handle,
 612                     (off_t)(req_q->req_ring_index * REQUEST_ENTRY_SIZE),
 613                     REQUEST_ENTRY_SIZE, DDI_DMA_SYNC_FORDEV);

 614 
 615                 /* Adjust ring pointer, and deal with wrap. */
 616                 req_q->req_ring_index++;
 617                 if (req_q->req_ring_index == REQUEST_ENTRY_CNT) {
 618                         req_q->req_ring_index = 0;
 619                         req_q->req_ring_ptr = req_q->req_ring.bp;
 620                 } else {
 621                         req_q->req_ring_ptr++;
 622                 }
 623                 pkt = (cont_entry_t *)req_q->req_ring_ptr;
 624                 pkt1 = (cont_type_1_entry_t *)req_q->req_ring_ptr;
 625 
 626                 /* Zero out packet. */
 627                 ptr64 = (uint64_t *)pkt;
 628                 *ptr64++ = 0; *ptr64++ = 0;
 629                 *ptr64++ = 0; *ptr64++ = 0;
 630                 *ptr64++ = 0; *ptr64++ = 0;
 631                 *ptr64++ = 0; *ptr64 = 0;
 632 
 633                 /*
 634                  * Build continuation packet.
 635                  */
 636                 pkt->entry_count = 1;
 637                 pkt->sys_define = (uint8_t)req_q->req_ring_index;
 638                 if (addr64) {
 639                         pkt1->entry_type = CONTINUATION_TYPE_1;
 640                         cnt = CONT_TYPE_1_DATA_SEGMENTS;
 641                         ptr32 = (uint32_t *)&pkt1->dseg;

 642                         while (cnt && seg_cnt) {
 643                                 ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 644                                     cp->dmac_address);
 645                                 ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 646                                     cp->dmac_notused);
 647                                 ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 648                                     (uint32_t)cp->dmac_size);
 649                                 seg_cnt--;
 650                                 cnt--;
 651                                 cp++;
 652                         }
 653                 } else {
 654                         pkt->entry_type = CONTINUATION_TYPE_0;
 655                         cnt = CONT_TYPE_0_DATA_SEGMENTS;
 656                         ptr32 = (uint32_t *)&pkt->dseg;
 657                         while (cnt && seg_cnt) {
 658                                 ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 659                                     cp->dmac_address);
 660                                 ddi_put32(req_q->req_ring.acc_handle, ptr32++,
 661                                     (uint32_t)cp->dmac_size);
 662                                 seg_cnt--;
 663                                 cnt--;
 664                                 cp++;
 665                         }
 666                 }
 667 
 668                 QL_PRINT_5(ha, "packet:\n");
 669                 QL_DUMP_5((uint8_t *)pkt, 8, REQUEST_ENTRY_SIZE);
 670         }
 671 
 672         QL_PRINT_3(ha, "done\n");
 673 }
 674 
 675 /*
 676  * ql_command_24xx_iocb
 677  *      Setup of ISP24xx command IOCB.
 678  *
 679  * Input:
 680  *      ha:     adapter state pointer.
 681  *      req_q:  request queue structure pointer.
 682  *      sp:     srb structure pointer.
 683  *      arg:    request queue packet.
 684  *
 685  * Context:
 686  *      Interrupt or Kernel context, no mailbox commands allowed.
 687  */
 688 void
 689 ql_command_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
 690     ql_srb_t *sp, void *arg)
 691 {
 692         ddi_dma_cookie_t        *cp;
 693         uint32_t                *ptr32, cnt;
 694         uint16_t                seg_cnt;
 695         fcp_cmd_t               *fcp = sp->fcp;
 696         ql_tgt_t                *tq = sp->lun_queue->target_queue;
 697         cmd7_24xx_entry_t       *pkt = arg;
 698         ql_adapter_state_t      *pha = ha->pha;
 699         fcp_ent_addr_t          *fcp_ent_addr;
 700 
 701         QL_PRINT_3(ha, "started\n");
 702 
 703         if (fcp->fcp_data_len != 0 && sp->sg_dma.dma_handle != NULL &&
 704             sp->pkt->pkt_data_cookie_cnt > 1) {
 705                 ql_cmd_24xx_type_6_iocb(ha, req_q, sp, arg);
 706                 QL_PRINT_3(ha, "cmd6 exit\n");
 707                 return;
 708         }
 709 
 710         pkt->entry_type = IOCB_CMD_TYPE_7;
 711 
 712         /* Set LUN number */
 713         fcp_ent_addr = (fcp_ent_addr_t *)&sp->lun_queue->lun_addr;
 714         pkt->fcp_lun[2] = lobyte(fcp_ent_addr->ent_addr_0);
 715         pkt->fcp_lun[3] = hibyte(fcp_ent_addr->ent_addr_0);
 716         pkt->fcp_lun[0] = lobyte(fcp_ent_addr->ent_addr_1);
 717         pkt->fcp_lun[1] = hibyte(fcp_ent_addr->ent_addr_1);
 718         pkt->fcp_lun[6] = lobyte(fcp_ent_addr->ent_addr_2);
 719         pkt->fcp_lun[7] = hibyte(fcp_ent_addr->ent_addr_2);
 720         pkt->fcp_lun[4] = lobyte(fcp_ent_addr->ent_addr_3);
 721         pkt->fcp_lun[5] = hibyte(fcp_ent_addr->ent_addr_3);
 722 
 723         /* Set N_port handle */
 724         ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
 725 
 726         /* Set target ID */
 727         pkt->target_id[0] = tq->d_id.b.al_pa;
 728         pkt->target_id[1] = tq->d_id.b.area;
 729         pkt->target_id[2] = tq->d_id.b.domain;
 730 
 731         pkt->vp_index = ha->vp_index;
 732 
 733         /* Set ISP command timeout. */
 734         if (sp->isp_timeout < 0x1999) {
 735                 ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
 736                     sp->isp_timeout);
 737         }
 738 
 739         /* Load SCSI CDB */
 740         ddi_rep_put8(req_q->req_ring.acc_handle, fcp->fcp_cdb, pkt->scsi_cdb,
 741             MAX_CMDSZ, DDI_DEV_AUTOINCR);
 742         for (cnt = 0; cnt < MAX_CMDSZ; cnt += 4) {
 743                 ql_chg_endian((uint8_t *)&pkt->scsi_cdb + cnt, 4);
 744         }
 745 
 746         /*
 747          * Set tag queue control flags
 748          * Note:
 749          *      Cannot copy fcp->fcp_cntl.cntl_qtype directly,
 750          *      problem with x86 in 32bit kernel mode
 751          */
 752         switch (fcp->fcp_cntl.cntl_qtype) {
 753         case FCP_QTYPE_SIMPLE:
 754                 pkt->task = TA_STAG;
 755                 break;
 756         case FCP_QTYPE_HEAD_OF_Q:
 757                 pkt->task = TA_HTAG;
 758                 break;
 759         case FCP_QTYPE_ORDERED:
 760                 pkt->task = TA_OTAG;
 761                 break;
 762         case FCP_QTYPE_ACA_Q_TAG:
 763                 pkt->task = TA_ACA;
 764                 break;
 765         case FCP_QTYPE_UNTAGGED:
 766                 pkt->task = TA_UNTAGGED;
 767                 break;
 768         default:
 769                 break;
 770         }
 771 
 772         if (fcp->fcp_data_len == 0) {
 773                 QL_PRINT_3(ha, "done\n");
 774                 pha->xioctl->IOControlRequests++;
 775                 return;
 776         }
 777 
 778         /* Set transfer direction. */
 779         if (fcp->fcp_cntl.cntl_write_data) {
 780                 pkt->control_flags = CF_WR;
 781                 pha->xioctl->IOOutputRequests++;
 782                 pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
 783         } else if (fcp->fcp_cntl.cntl_read_data) {
 784                 pkt->control_flags = CF_RD;
 785                 pha->xioctl->IOInputRequests++;
 786                 pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
 787         }
 788 
 789         /* Set data segment count. */
 790         seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
 791         ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
 792 
 793         /* Load total byte count. */
 794         ddi_put32(req_q->req_ring.acc_handle, &pkt->total_byte_count,
 795             fcp->fcp_data_len);
 796 
 797         /* Load command data segment. */
 798         ptr32 = (uint32_t *)&pkt->dseg;
 799         cp = sp->pkt->pkt_data_cookie;
 800         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
 801         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
 802         ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
 803         seg_cnt--;
 804         cp++;
 805 
 806         /*
 807          * Build continuation packets.
 808          */
 809         if (seg_cnt) {
 810                 ql_continuation_iocb(pha, req_q, cp, seg_cnt, B_TRUE);
 811         }
 812 
 813         QL_PRINT_3(ha, "done\n");
 814 }
 815 
 816 /*
 817  * ql_cmd_24xx_type_6_iocb
 818  *      Setup of ISP24xx command type 6 IOCB.
 819  *
 820  * Input:
 821  *      ha:     adapter state pointer.
 822  *      req_q:  request queue structure pointer.
 823  *      sp:     srb structure pointer.
 824  *      arg:    request queue packet.
 825  *
 826  * Context:
 827  *      Interrupt or Kernel context, no mailbox commands allowed.
 828  */
 829 static void
 830 ql_cmd_24xx_type_6_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q,
 831     ql_srb_t *sp, void *arg)
 832 {
 833         uint64_t                addr;
 834         ddi_dma_cookie_t        *cp;
 835         uint32_t                *ptr32;
 836         uint16_t                seg_cnt;
 837         fcp_cmd_t               *fcp = sp->fcp;
 838         ql_tgt_t                *tq = sp->lun_queue->target_queue;
 839         cmd6_24xx_entry_t       *pkt = arg;
 840         ql_adapter_state_t      *pha = ha->pha;
 841         dma_mem_t               *cmem = &sp->sg_dma;
 842         cmd6_2400_dma_t         *cdma = cmem->bp;
 843         fcp_ent_addr_t          *fcp_ent_addr;
 844 
 845         QL_PRINT_3(ha, "started\n");
 846 
 847         pkt->entry_type = IOCB_CMD_TYPE_6;
 848 
 849         bzero(cdma, sizeof (cmd6_2400_dma_t));
 850 
 851         /* Set LUN number */
 852         fcp_ent_addr = (fcp_ent_addr_t *)&sp->lun_queue->lun_addr;
 853         pkt->fcp_lun[2] = cdma->cmd.fcp_lun[2] =
 854             lobyte(fcp_ent_addr->ent_addr_0);
 855         pkt->fcp_lun[3] = cdma->cmd.fcp_lun[3] =
 856             hibyte(fcp_ent_addr->ent_addr_0);
 857         pkt->fcp_lun[0] = cdma->cmd.fcp_lun[0] =
 858             lobyte(fcp_ent_addr->ent_addr_1);
 859         pkt->fcp_lun[1] = cdma->cmd.fcp_lun[1] =
 860             hibyte(fcp_ent_addr->ent_addr_1);
 861         pkt->fcp_lun[6] = cdma->cmd.fcp_lun[6] =
 862             lobyte(fcp_ent_addr->ent_addr_2);
 863         pkt->fcp_lun[7] = cdma->cmd.fcp_lun[7] =
 864             hibyte(fcp_ent_addr->ent_addr_2);
 865         pkt->fcp_lun[4] = cdma->cmd.fcp_lun[4] =
 866             lobyte(fcp_ent_addr->ent_addr_3);
 867         pkt->fcp_lun[5] = cdma->cmd.fcp_lun[5] =
 868             hibyte(fcp_ent_addr->ent_addr_3);
 869 
 870         /* Set N_port handle */
 871         ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
 872 
 873         /* Set target ID */
 874         pkt->target_id[0] = tq->d_id.b.al_pa;
 875         pkt->target_id[1] = tq->d_id.b.area;
 876         pkt->target_id[2] = tq->d_id.b.domain;
 877 
 878         pkt->vp_index = ha->vp_index;
 879 
 880         /* Set ISP command timeout. */
 881         if (sp->isp_timeout < 0x1999) {
 882                 ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
 883                     sp->isp_timeout);
 884         }
 885 
 886         /* Load SCSI CDB */
 887         ddi_rep_put8(cmem->acc_handle, fcp->fcp_cdb, cdma->cmd.scsi_cdb,
 888             MAX_CMDSZ, DDI_DEV_AUTOINCR);
 889 
 890         /*
 891          * Set tag queue control flags
 892          * Note:
 893          *      Cannot copy fcp->fcp_cntl.cntl_qtype directly,
 894          *      problem with x86 in 32bit kernel mode
 895          */
 896         switch (fcp->fcp_cntl.cntl_qtype) {
 897         case FCP_QTYPE_SIMPLE:
 898                 cdma->cmd.task = TA_STAG;
 899                 break;
 900         case FCP_QTYPE_HEAD_OF_Q:
 901                 cdma->cmd.task = TA_HTAG;
 902                 break;
 903         case FCP_QTYPE_ORDERED:
 904                 cdma->cmd.task = TA_OTAG;
 905                 break;
 906         case FCP_QTYPE_ACA_Q_TAG:
 907                 cdma->cmd.task = TA_ACA;
 908                 break;
 909         case FCP_QTYPE_UNTAGGED:
 910                 cdma->cmd.task = TA_UNTAGGED;
 911                 break;
 912         default:
 913                 break;
 914         }
 915 
 916         /*
 917          * FCP_CMND Payload Data Segment
 918          */
 919         cp = cmem->cookies;
 920         ddi_put16(req_q->req_ring.acc_handle, &pkt->cmnd_length,
 921             sizeof (fcp_cmnd_t));
 922         ddi_put32(req_q->req_ring.acc_handle, &pkt->cmnd_address[0],
 923             cp->dmac_address);
 924         ddi_put32(req_q->req_ring.acc_handle, &pkt->cmnd_address[1],
 925             cp->dmac_notused);
 926 
 927         /* Set transfer direction. */
 928         if (fcp->fcp_cntl.cntl_write_data) {
 929                 pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_WR);
 930                 cdma->cmd.control_flags = CF_WR;
 931                 pha->xioctl->IOOutputRequests++;
 932                 pha->xioctl->IOOutputByteCnt += fcp->fcp_data_len;
 933         } else if (fcp->fcp_cntl.cntl_read_data) {
 934                 pkt->control_flags = (uint8_t)(CF_DSD_PTR | CF_RD);
 935                 cdma->cmd.control_flags = CF_RD;
 936                 pha->xioctl->IOInputRequests++;
 937                 pha->xioctl->IOInputByteCnt += fcp->fcp_data_len;
 938         }
 939 
 940         /*
 941          * FCP_DATA Data Segment Descriptor.
 942          */
 943         addr = cp->dmac_laddress + sizeof (fcp_cmnd_t);
 944         ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.address[0], LSD(addr));
 945         ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.address[1], MSD(addr));
 946 
 947         /* Set data segment count. */
 948         seg_cnt = (uint16_t)sp->pkt->pkt_data_cookie_cnt;
 949         ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
 950         ddi_put32(req_q->req_ring.acc_handle, &pkt->dseg.length,
 951             seg_cnt * 12 + 12);
 952 
 953         /* Load total byte count. */
 954         ddi_put32(req_q->req_ring.acc_handle, &pkt->total_byte_count,
 955             fcp->fcp_data_len);
 956         ddi_put32(cmem->acc_handle, &cdma->cmd.dl, (uint32_t)fcp->fcp_data_len);
 957         ql_chg_endian((uint8_t *)&cdma->cmd.dl, 4);
 958 
 959         /* Load command data segments. */
 960         ptr32 = (uint32_t *)cdma->cookie_list;
 961         cp = sp->pkt->pkt_data_cookie;
 962         while (seg_cnt--) {
 963                 ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_address);
 964                 ddi_put32(cmem->acc_handle, ptr32++, cp->dmac_notused);
 965                 ddi_put32(cmem->acc_handle, ptr32++, (uint32_t)cp->dmac_size);
 966                 cp++;
 967         }
 968 
 969         /* Sync DMA buffer. */
 970         (void) ddi_dma_sync(cmem->dma_handle, 0, 0, DDI_DMA_SYNC_FORDEV);
 971 
 972         QL_PRINT_3(ha, "done\n");
 973 }
 974 
 975 /*
 976  * ql_marker
 977  *      Function issues marker IOCB.
 978  *
 979  * Input:
 980  *      ha:             adapter state pointer.
 981  *      loop_id:        device loop ID
 982  *      lq:             LUN queue pointer.
 983  *      type:           marker modifier
 984  *
 985  * Returns:
 986  *      ql local function return status code.
 987  *
 988  * Context:
 989  *      Interrupt or Kernel context, no mailbox commands allowed.
 990  */
 991 int
 992 ql_marker(ql_adapter_state_t *ha, uint16_t loop_id, ql_lun_t *lq,
 993     uint8_t type)
 994 {
 995         mrk_entry_t     *pkt;
 996         int             rval;
 997         ql_request_q_t  *req_q = ha->req_q[0];
 998         fcp_ent_addr_t  *fcp_ent_addr;
 999 
1000         QL_PRINT_3(ha, "started\n");
1001 
1002         rval = ql_req_pkt(ha, req_q, (request_t **)&pkt);
1003         if (rval == QL_SUCCESS) {
1004                 pkt->entry_type = MARKER_TYPE;
1005 
1006                 if (CFG_IST(ha, CFG_ISP_FW_TYPE_2)) {
1007                         marker_24xx_entry_t     *pkt24 =
1008                             (marker_24xx_entry_t *)pkt;
1009 
1010                         pkt24->modifier = type;
1011 
1012                         /* Set LUN number */
1013                         if (lq) {
1014                                 fcp_ent_addr = (fcp_ent_addr_t *)&lq->lun_addr;
1015                                 pkt24->fcp_lun[2] =
1016                                     lobyte(fcp_ent_addr->ent_addr_0);
1017                                 pkt24->fcp_lun[3] =
1018                                     hibyte(fcp_ent_addr->ent_addr_0);
1019                                 pkt24->fcp_lun[0] =
1020                                     lobyte(fcp_ent_addr->ent_addr_1);
1021                                 pkt24->fcp_lun[1] =
1022                                     hibyte(fcp_ent_addr->ent_addr_1);
1023                                 pkt24->fcp_lun[6] =
1024                                     lobyte(fcp_ent_addr->ent_addr_2);
1025                                 pkt24->fcp_lun[7] =
1026                                     hibyte(fcp_ent_addr->ent_addr_2);
1027                                 pkt24->fcp_lun[4] =
1028                                     lobyte(fcp_ent_addr->ent_addr_3);
1029                                 pkt24->fcp_lun[5] =
1030                                     hibyte(fcp_ent_addr->ent_addr_3);
1031                         }
1032 
1033                         pkt24->vp_index = ha->vp_index;
1034 
1035                         /* Set N_port handle */
1036                         ddi_put16(req_q->req_ring.acc_handle,
1037                             &pkt24->n_port_hdl, loop_id);
1038 
1039                 } else {
1040                         pkt->modifier = type;
1041 
1042                         if (lq) {
1043                                 pkt->lun_l = LSB(lq->lun_no);
1044                                 pkt->lun_h = MSB(lq->lun_no);
1045                         }
1046 
1047                         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1048                                 pkt->target_l = LSB(loop_id);
1049                                 pkt->target_h = MSB(loop_id);
1050                         } else {
1051                                 pkt->target_h = LSB(loop_id);
1052                         }
1053                 }
1054 
1055                 /* Issue command to ISP */
1056                 ql_isp_cmd(ha, req_q);
1057         }
1058 
1059         if (rval != QL_SUCCESS) {
1060                 EL(ha, "failed, rval = %xh\n", rval);
1061         } else {
1062                 /*EMPTY*/
1063                 QL_PRINT_3(ha, "done\n");
1064         }
1065         return (rval);
1066 }
1067 
1068 /*
1069  * ql_ms_iocb
1070  *      Setup of name/management server IOCB.
1071  *
1072  * Input:
1073  *      ha:     adapter state pointer.
1074  *      req_q:  request queue structure pointer.
1075  *      sp:     srb structure pointer.
1076  *      arg:    request queue packet.
1077  *
1078  * Context:
1079  *      Interrupt or Kernel context, no mailbox commands allowed.
1080  */
1081 void
1082 ql_ms_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1083     void *arg)
1084 {
1085         ddi_dma_cookie_t        *cp;
1086         uint32_t                *ptr32;
1087         uint16_t                seg_cnt;
1088         ql_tgt_t                *tq = sp->lun_queue->target_queue;
1089         ms_entry_t              *pkt = arg;
1090 
1091         QL_PRINT_3(ha, "started\n");
1092         QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
1093         /*
1094          * Build command packet.
1095          */
1096         pkt->entry_type = MS_TYPE;
1097 
1098         /* Set loop ID */
1099         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1100                 pkt->loop_id_l = LSB(tq->loop_id);
1101                 pkt->loop_id_h = MSB(tq->loop_id);
1102         } else {
1103                 pkt->loop_id_h = LSB(tq->loop_id);
1104         }
1105 
1106         /* Set ISP command timeout. */
1107         ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
1108 
1109         /* Set cmd data segment count. */
1110         pkt->cmd_dseg_count_l = 1;
1111 
1112         /* Set total data segment count */
1113         seg_cnt = (uint16_t)(sp->pkt->pkt_resp_cookie_cnt + 1);
1114         ddi_put16(req_q->req_ring.acc_handle, &pkt->total_dseg_count, seg_cnt);
1115 
1116         /* Load ct cmd byte count. */
1117         ddi_put32(req_q->req_ring.acc_handle, &pkt->cmd_byte_count,
1118             (uint32_t)sp->pkt->pkt_cmdlen);
1119 
1120         /* Load ct rsp byte count. */
1121         ddi_put32(req_q->req_ring.acc_handle, &pkt->resp_byte_count,
1122             (uint32_t)sp->pkt->pkt_rsplen);
1123 
1124         /* Load MS command data segments. */
1125         ptr32 = (uint32_t *)&pkt->dseg;
1126         cp = sp->pkt->pkt_cmd_cookie;
1127         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1128         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1129         ddi_put32(req_q->req_ring.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
1130         seg_cnt--;
1131 
1132         /* Load MS response entry data segments. */
1133         cp = sp->pkt->pkt_resp_cookie;
1134         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1135         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1136         ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1137         seg_cnt--;
1138         cp++;
1139 
1140         /*
1141          * Build continuation packets.
1142          */
1143         if (seg_cnt) {
1144                 ql_continuation_iocb(ha, req_q, cp, seg_cnt, B_TRUE);
1145         }
1146 
1147         QL_PRINT_3(ha, "done\n");
1148 }
1149 
1150 /*
1151  * ql_ms_24xx_iocb
1152  *      Setup of name/management server IOCB.
1153  *
1154  * Input:
1155  *      ha:     adapter state pointer.
1156  *      req_q:  request queue structure pointer.
1157  *      sp:     srb structure pointer.
1158  *      arg:    request queue packet.
1159  *
1160  * Context:
1161  *      Interrupt or Kernel context, no mailbox commands allowed.
1162  */
1163 void
1164 ql_ms_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1165     void *arg)
1166 {
1167         ddi_dma_cookie_t        *cp;
1168         uint32_t                *ptr32;
1169         uint16_t                seg_cnt;
1170         ql_tgt_t                *tq = sp->lun_queue->target_queue;
1171         ct_passthru_entry_t     *pkt = arg;
1172         ql_adapter_state_t      *pha = ha->pha;
1173 
1174         QL_PRINT_3(ha, "started\n");
1175         QL_DUMP_3(sp->pkt->pkt_cmd, 8, sp->pkt->pkt_cmdlen);
1176         /*
1177          * Build command packet.
1178          */
1179         pkt->entry_type = CT_PASSTHRU_TYPE;
1180 
1181         /* Set loop ID */
1182         ddi_put16(req_q->req_ring.acc_handle, &pkt->n_port_hdl, tq->loop_id);
1183 
1184         pkt->vp_index = ha->vp_index;
1185 
1186         /* Set ISP command timeout. */
1187         if (sp->isp_timeout < 0x1999) {
1188                 ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout,
1189                     sp->isp_timeout);
1190         }
1191 
1192         /* Set cmd/response data segment counts. */
1193         ddi_put16(req_q->req_ring.acc_handle, &pkt->cmd_dseg_count, 1);
1194         seg_cnt = (uint16_t)sp->pkt->pkt_resp_cookie_cnt;
1195         ddi_put16(req_q->req_ring.acc_handle, &pkt->resp_dseg_count, seg_cnt);
1196 
1197         /* Load ct cmd byte count. */
1198         ddi_put32(req_q->req_ring.acc_handle, &pkt->cmd_byte_count,
1199             (uint32_t)sp->pkt->pkt_cmdlen);
1200 
1201         /* Load ct rsp byte count. */
1202         ddi_put32(req_q->req_ring.acc_handle, &pkt->resp_byte_count,
1203             (uint32_t)sp->pkt->pkt_rsplen);
1204 
1205         /* Load MS command entry data segments. */
1206         ptr32 = (uint32_t *)&pkt->dseg;
1207         cp = sp->pkt->pkt_cmd_cookie;
1208         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1209         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1210         ddi_put32(req_q->req_ring.acc_handle, ptr32++, (uint32_t)cp->dmac_size);
1211 
1212         /* Load MS response entry data segments. */
1213         cp = sp->pkt->pkt_resp_cookie;
1214         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1215         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1216         ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1217         seg_cnt--;
1218         cp++;
1219 
1220         /*
1221          * Build continuation packets.
1222          */
1223         if (seg_cnt) {
1224                 ql_continuation_iocb(pha, req_q, cp, seg_cnt, B_TRUE);
1225         }
1226 
1227         QL_PRINT_3(ha, "done\n");
1228 }
1229 
1230 /*
1231  * ql_ip_iocb
1232  *      Setup of IP IOCB.
1233  *
1234  * Input:
1235  *      ha:     adapter state pointer.
1236  *      req_q:  request queue structure pointer.
1237  *      sp:     srb structure pointer.
1238  *      arg:    request queue packet.
1239  *
1240  * Context:
1241  *      Interrupt or Kernel context, no mailbox commands allowed.
1242  */
1243 void
1244 ql_ip_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1245     void *arg)
1246 {
1247         ddi_dma_cookie_t        *cp;
1248         uint32_t                *ptr32, cnt;
1249         uint16_t                seg_cnt;
1250         ql_tgt_t                *tq = sp->lun_queue->target_queue;
1251         ip_entry_t              *pkt = arg;
1252         ip_a64_entry_t          *pkt64 = arg;
1253 
1254         QL_PRINT_3(ha, "started\n");
1255 
1256         /* Set loop ID */
1257         if (CFG_IST(ha, CFG_EXT_FW_INTERFACE)) {
1258                 pkt->loop_id_l = LSB(tq->loop_id);
1259                 pkt->loop_id_h = MSB(tq->loop_id);
1260         } else {
1261                 pkt->loop_id_h = LSB(tq->loop_id);
1262         }
1263 
1264         /* Set control flags */
1265         pkt->control_flags_l = BIT_6;
1266         if (sp->pkt->pkt_tran_flags & FC_TRAN_HI_PRIORITY) {
1267                 pkt->control_flags_h = BIT_7;
1268         }
1269 
1270         /* Set ISP command timeout. */
1271         ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout, sp->isp_timeout);
1272 
1273         /* Set data segment count. */
1274         seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1275         /* Load total byte count. */
1276         ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
1277             (uint32_t)sp->pkt->pkt_cmdlen);
1278         ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
1279 
1280         /*
1281          * Build command packet.
1282          */







1283 
1284         /* Load command entry data segments. */

1285         cp = sp->pkt->pkt_cmd_cookie;
1286 

1287         if (CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)) {
1288                 pkt64->entry_type = IP_A64_TYPE;
1289                 cnt = IP_A64_DATA_SEGMENTS;
1290                 ptr32 = (uint32_t *)&pkt64->dseg;
1291                 while (cnt && seg_cnt) {
1292                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1293                             cp->dmac_address);
1294                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1295                             cp->dmac_notused);
1296                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1297                             (uint32_t)cp->dmac_size);
1298                         seg_cnt--;
1299                         cnt--;
1300                         cp++;
1301                 }
1302         } else {
1303                 pkt->entry_type = IP_TYPE;
1304                 cnt = IP_DATA_SEGMENTS;
1305                 ptr32 = (uint32_t *)&pkt->dseg;
1306                 while (cnt && seg_cnt) {
1307                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1308                             cp->dmac_address);
1309                         ddi_put32(req_q->req_ring.acc_handle, ptr32++,
1310                             (uint32_t)cp->dmac_size);
1311                         seg_cnt--;
1312                         cnt--;
1313                         cp++;
1314                 }
1315         }
1316 
1317         /*
1318          * Build continuation packets.
1319          */
1320         if (seg_cnt) {
1321                 ql_continuation_iocb(ha, req_q, cp, seg_cnt,
1322                     (boolean_t)(CFG_IST(ha, CFG_ENABLE_64BIT_ADDRESSING)));
1323         }
1324 
1325         QL_PRINT_3(ha, "done\n");
1326 }
1327 
1328 /*
1329  * ql_ip_24xx_iocb
1330  *      Setup of IP IOCB for ISP24xx.
1331  *
1332  * Input:
1333  *      ha:     adapter state pointer.
1334  *      req_q:  request queue structure pointer.
1335  *      sp:     srb structure pointer.
1336  *      arg:    request queue packet.
1337  *
1338  * Context:
1339  *      Interrupt or Kernel context, no mailbox commands allowed.
1340  */
1341 void
1342 ql_ip_24xx_iocb(ql_adapter_state_t *ha, ql_request_q_t *req_q, ql_srb_t *sp,
1343     void *arg)
1344 {
1345         ddi_dma_cookie_t        *cp;
1346         uint32_t                *ptr32;
1347         uint16_t                seg_cnt;
1348         ql_tgt_t                *tq = sp->lun_queue->target_queue;
1349         ip_cmd_entry_t          *pkt = arg;
1350 
1351         pkt->entry_type = IP_CMD_TYPE;
1352 
1353         QL_PRINT_3(ha, "started\n");
1354 
1355         /* Set N_port handle */
1356         ddi_put16(req_q->req_ring.acc_handle, &pkt->hdl_status, tq->loop_id);
1357 
1358         /* Set ISP command timeout. */
1359         if (sp->isp_timeout < 0x1999) {
1360                 ddi_put16(req_q->req_ring.acc_handle, &pkt->timeout_hdl,
1361                     sp->isp_timeout);
1362         }
1363 
1364         /* Set data segment count. */
1365         seg_cnt = (uint16_t)sp->pkt->pkt_cmd_cookie_cnt;
1366         /* Load total byte count. */
1367         ddi_put32(req_q->req_ring.acc_handle, &pkt->byte_count,
1368             (uint32_t)sp->pkt->pkt_cmdlen);
1369         ddi_put16(req_q->req_ring.acc_handle, &pkt->dseg_count, seg_cnt);
1370 
1371         /* Set control flags */
1372         ddi_put16(req_q->req_ring.acc_handle, &pkt->control_flags,
1373             (uint16_t)(BIT_0));
1374 
1375         /* Set frame header control flags */
1376         ddi_put16(req_q->req_ring.acc_handle, &pkt->frame_hdr_cntrl_flgs,
1377             (uint16_t)(IPCF_LAST_SEQ | IPCF_FIRST_SEQ));
1378 
1379         /* Load command data segment. */
1380         ptr32 = (uint32_t *)&pkt->dseg;
1381         cp = sp->pkt->pkt_cmd_cookie;
1382         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_address);
1383         ddi_put32(req_q->req_ring.acc_handle, ptr32++, cp->dmac_notused);
1384         ddi_put32(req_q->req_ring.acc_handle, ptr32, (uint32_t)cp->dmac_size);
1385         seg_cnt--;
1386         cp++;
1387 
1388         /*
1389          * Build continuation packets.
1390          */
1391         if (seg_cnt) {
1392                 ql_continuation_iocb(ha, req_q, cp, seg_cnt, B_TRUE);
1393         }
1394 
1395         QL_PRINT_3(ha, "done\n");
1396 }
1397 
1398 /*
1399  * ql_isp_rcvbuf
1400  *      Locates free buffers and places it on the receive buffer queue.
1401  *
1402  * Input:
1403  *      ha = adapter state pointer.
1404  *
1405  * Context:
1406  *      Interrupt or Kernel context, no mailbox commands allowed.
1407  */
1408 void
1409 ql_isp_rcvbuf(ql_adapter_state_t *ha)
1410 {
1411         rcvbuf_t        *container;
1412         uint16_t        rcv_q_cnt;
1413         uint16_t        index = 0;
1414         uint16_t        index1 = 1;
1415         int             debounce_count = QL_MAX_DEBOUNCE;
1416         ql_srb_t        *sp;
1417         fc_unsol_buf_t  *ubp;
1418         int             ring_updated = FALSE;
1419 
1420         if (CFG_IST(ha, CFG_CTRL_24XX)) {
1421                 ql_isp24xx_rcvbuf(ha);
1422                 return;
1423         }
1424 
1425         QL_PRINT_3(ha, "started\n");
1426 
1427         /* Acquire adapter state lock. */
1428         ADAPTER_STATE_LOCK(ha);
1429 
1430         /* Calculate number of free receive buffer entries. */
1431         index = RD16_IO_REG(ha, mailbox_out[8]);
1432         do {
1433                 index1 = RD16_IO_REG(ha, mailbox_out[8]);
1434                 if (index1 == index) {
1435                         break;
1436                 } else {
1437                         index = index1;
1438                 }
1439         } while (debounce_count--);
1440 
1441         if (debounce_count < 0) {
1442                 /* This should never happen */
1443                 EL(ha, "max mb8 debounce retries exceeded\n");
1444         }
1445 
1446         rcv_q_cnt = (uint16_t)(ha->rcvbuf_ring_index < index ?
1447             index - ha->rcvbuf_ring_index : RCVBUF_CONTAINER_CNT -
1448             (ha->rcvbuf_ring_index - index));
1449 
1450         if (rcv_q_cnt == RCVBUF_CONTAINER_CNT) {
1451                 rcv_q_cnt--;
1452         }
1453 
1454         /* Load all free buffers in ISP receive buffer ring. */
1455         index = 0;
1456         while (rcv_q_cnt > (uint16_t)0 && index < QL_UB_LIMIT) {
1457                 /* Locate a buffer to give. */
1458                 QL_UB_LOCK(ha);
1459                 while (index < QL_UB_LIMIT) {


1464                                     (ha->flags & IP_INITIALIZED) &&
1465                                     (sp->flags & SRB_UB_IN_FCA) &&
1466                                     (!(sp->flags & (SRB_UB_IN_ISP |
1467                                     SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1468                                     SRB_UB_ACQUIRED)))) {
1469                                         sp->flags |= SRB_UB_IN_ISP;
1470                                         break;
1471                                 }
1472                         }
1473                         index++;
1474                 }
1475 
1476                 if (index < QL_UB_LIMIT) {
1477                         rcv_q_cnt--;
1478                         index++;
1479                         container = ha->rcvbuf_ring_ptr;
1480 
1481                         /*
1482                          * Build container.
1483                          */
1484                         ddi_put32(ha->rcv_ring.acc_handle,
1485                             (uint32_t *)(void *)&container->bufp[0],
1486                             sp->ub_buffer.cookie.dmac_address);
1487 
1488                         ddi_put32(ha->rcv_ring.acc_handle,
1489                             (uint32_t *)(void *)&container->bufp[1],
1490                             sp->ub_buffer.cookie.dmac_notused);
1491 
1492                         ddi_put16(ha->rcv_ring.acc_handle, &container->handle,
1493                             LSW(sp->handle));
1494 
1495                         ha->ub_outcnt++;
1496 
1497                         /* Adjust ring index. */
1498                         ha->rcvbuf_ring_index++;
1499                         if (ha->rcvbuf_ring_index == RCVBUF_CONTAINER_CNT) {
1500                                 ha->rcvbuf_ring_index = 0;
1501                                 ha->rcvbuf_ring_ptr = ha->rcv_ring.bp;
1502                         } else {
1503                                 ha->rcvbuf_ring_ptr++;
1504                         }
1505 
1506                         ring_updated = TRUE;
1507                 }
1508                 QL_UB_UNLOCK(ha);
1509         }
1510 
1511         if (ring_updated) {
1512                 /* Sync queue. */
1513                 (void) ddi_dma_sync(ha->rcv_ring.dma_handle, 0,
1514                     (size_t)RCVBUF_QUEUE_SIZE, DDI_DMA_SYNC_FORDEV);

1515 
1516                 /* Set chip new ring index. */
1517                 WRT16_IO_REG(ha, mailbox_in[8], ha->rcvbuf_ring_index);
1518         }
1519 
1520         /* Release adapter state lock. */
1521         ADAPTER_STATE_UNLOCK(ha);
1522 
1523         QL_PRINT_3(ha, "done\n");
1524 }
1525 
1526 /*
1527  * ql_isp24xx_rcvbuf
1528  *      Locates free buffers and send it to adapter.
1529  *
1530  * Input:
1531  *      ha = adapter state pointer.
1532  *
1533  * Context:
1534  *      Interrupt or Kernel context, no mailbox commands allowed.
1535  */
1536 static void
1537 ql_isp24xx_rcvbuf(ql_adapter_state_t *ha)
1538 {
1539         rcvbuf_t                *container;
1540         uint16_t                index;
1541         ql_srb_t                *sp;
1542         fc_unsol_buf_t          *ubp;
1543         int                     rval;
1544         ip_buf_pool_entry_t     *pkt = NULL;
1545         ql_request_q_t          *req_q = ha->req_q[0];
1546 
1547         QL_PRINT_3(ha, "started\n");
1548 
1549         for (;;) {
1550                 /* Locate a buffer to give. */
1551                 QL_UB_LOCK(ha);
1552                 for (index = 0; index < QL_UB_LIMIT; index++) {
1553                         ubp = ha->ub_array[index];
1554                         if (ubp != NULL) {
1555                                 sp = ubp->ub_fca_private;
1556                                 if ((sp->ub_type == FC_TYPE_IS8802_SNAP) &&
1557                                     (ha->flags & IP_INITIALIZED) &&
1558                                     (sp->flags & SRB_UB_IN_FCA) &&
1559                                     (!(sp->flags & (SRB_UB_IN_ISP |
1560                                     SRB_UB_FREE_REQUESTED | SRB_UB_CALLBACK |
1561                                     SRB_UB_ACQUIRED)))) {
1562                                         ha->ub_outcnt++;
1563                                         sp->flags |= SRB_UB_IN_ISP;
1564                                         break;
1565                                 }
1566                         }
1567                 }
1568                 QL_UB_UNLOCK(ha);
1569                 if (index == QL_UB_LIMIT) {
1570                         break;
1571                 }
1572 
1573                 /* Get IOCB packet for buffers. */
1574                 if (pkt == NULL) {
1575                         rval = ql_req_pkt(ha, req_q, (request_t **)&pkt);
1576                         if (rval != QL_SUCCESS) {
1577                                 EL(ha, "failed, ql_req_pkt=%x\n", rval);
1578                                 QL_UB_LOCK(ha);
1579                                 ha->ub_outcnt--;
1580                                 sp->flags &= ~SRB_UB_IN_ISP;
1581                                 QL_UB_UNLOCK(ha);
1582                                 break;
1583                         }
1584                         pkt->entry_type = IP_BUF_POOL_TYPE;
1585                         container = &pkt->buffers[0];
1586                 }
1587 
1588                 /*
1589                  * Build container.
1590                  */
1591                 ddi_put32(req_q->req_ring.acc_handle, &container->bufp[0],
1592                     sp->ub_buffer.cookie.dmac_address);
1593                 ddi_put32(req_q->req_ring.acc_handle, &container->bufp[1],
1594                     sp->ub_buffer.cookie.dmac_notused);
1595                 ddi_put16(req_q->req_ring.acc_handle, &container->handle,
1596                     LSW(sp->handle));
1597 
1598                 pkt->buffer_count++;
1599                 container++;
1600 
1601                 if (pkt->buffer_count == IP_POOL_BUFFERS) {
1602                         ql_isp_cmd(ha, req_q);
1603                         pkt = NULL;
1604                 }
1605         }
1606 
1607         if (pkt != NULL) {
1608                 ql_isp_cmd(ha, req_q);
1609         }
1610 
1611         QL_PRINT_3(ha, "done\n");
1612 }