Print this page
NEX-1889 upstream

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
          +++ new/usr/src/uts/common/io/scsi/adapters/mpt_sas/mptsas.c
↓ open down ↓ 16 lines elided ↑ open up ↑
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
  24   24   * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
  25   25   * Copyright (c) 2014, Joyent, Inc. All rights reserved.
  26   26   * Copyright 2014 OmniTI Computer Consulting, Inc. All rights reserved.
       27 + * Copyright (c) 2014, Tegile Systems Inc. All rights reserved.
  27   28   */
  28   29  
  29   30  /*
  30   31   * Copyright (c) 2000 to 2010, LSI Corporation.
  31   32   * All rights reserved.
  32   33   *
  33   34   * Redistribution and use in source and binary forms of all code within
  34   35   * this file that is exclusively owned by LSI, with or without
  35   36   * modification, is permitted provided that, in addition to the CDDL 1.0
  36   37   * License requirements, the following conditions are met:
↓ open down ↓ 201 lines elided ↑ open up ↑
 238  239  static void mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd,
 239  240      uint32_t *control, pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl);
 240  241  
 241  242  static void mptsas_watch(void *arg);
 242  243  static void mptsas_watchsubr(mptsas_t *mpt);
 243  244  static void mptsas_cmd_timeout(mptsas_t *mpt, mptsas_target_t *ptgt);
 244  245  
 245  246  static void mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd);
 246  247  static int mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
 247  248      uint8_t *data, uint32_t request_size, uint32_t reply_size,
 248      -    uint32_t data_size, uint32_t direction, uint8_t *dataout,
      249 +    uint32_t data_size, uint8_t direction, uint8_t *dataout,
 249  250      uint32_t dataout_size, short timeout, int mode);
 250  251  static int mptsas_free_devhdl(mptsas_t *mpt, uint16_t devhdl);
 251  252  
 252  253  static uint8_t mptsas_get_fw_diag_buffer_number(mptsas_t *mpt,
 253  254      uint32_t unique_id);
 254  255  static void mptsas_start_diag(mptsas_t *mpt, mptsas_cmd_t *cmd);
 255  256  static int mptsas_post_fw_diag_buffer(mptsas_t *mpt,
 256  257      mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code);
 257  258  static int mptsas_release_fw_diag_buffer(mptsas_t *mpt,
 258  259      mptsas_fw_diagnostic_buffer_t *pBuffer, uint32_t *return_code,
↓ open down ↓ 225 lines elided ↑ open up ↑
 484  485          0x0ull,         /* address low - should be 0 (longlong) */
 485  486          0xffffffffffffffffull,  /* address high - 64-bit max    */
 486  487          0x00ffffffull,  /* count max - max DMA object size      */
 487  488          4,              /* allocation alignment requirements    */
 488  489          0x78,           /* burstsizes - binary encoded values   */
 489  490          1,              /* minxfer - gran. of DMA engine        */
 490  491          0x00ffffffull,  /* maxxfer - gran. of DMA engine        */
 491  492          0xffffffffull,  /* max segment size (DMA boundary)      */
 492  493          MPTSAS_MAX_DMA_SEGS, /* scatter/gather list length      */
 493  494          512,            /* granularity - device transfer size   */
 494      -        DDI_DMA_RELAXED_ORDERING        /* flags, enable relaxed ordering */
      495 +        0               /* flags, set to 0 */
 495  496  };
 496  497  
 497  498  ddi_device_acc_attr_t mptsas_dev_attr = {
 498  499          DDI_DEVICE_ATTR_V1,
 499  500          DDI_STRUCTURE_LE_ACC,
 500  501          DDI_STRICTORDER_ACC,
 501  502          DDI_DEFAULT_ACC
 502  503  };
 503  504  
 504  505  static struct cb_ops mptsas_cb_ops = {
↓ open down ↓ 57 lines elided ↑ open up ↑
 562  563  #define LUN64_PROP      "lun64"
 563  564  #define SAS_PROP        "sas-mpt"
 564  565  #define MDI_GUID        "wwn"
 565  566  #define NDI_GUID        "guid"
 566  567  #define MPTSAS_DEV_GONE "mptsas_dev_gone"
 567  568  
 568  569  /*
 569  570   * Local static data
 570  571   */
 571  572  #if defined(MPTSAS_DEBUG)
 572      -uint32_t mptsas_debug_flags = 0;
      573 +uint32_t mptsas_debug_flags = 0x0;
 573  574  #endif  /* defined(MPTSAS_DEBUG) */
 574  575  uint32_t mptsas_debug_resets = 0;
 575  576  
 576  577  static kmutex_t         mptsas_global_mutex;
 577  578  static void             *mptsas_state;          /* soft state ptr */
 578  579  static krwlock_t        mptsas_global_rwlock;
 579  580  
 580  581  static kmutex_t         mptsas_log_mutex;
 581  582  static char             mptsas_log_buf[256];
 582  583  _NOTE(MUTEX_PROTECTS_DATA(mptsas_log_mutex, mptsas_log_buf))
 583  584  
 584  585  static mptsas_t *mptsas_head, *mptsas_tail;
 585  586  static clock_t mptsas_scsi_watchdog_tick;
 586  587  static clock_t mptsas_tick;
 587  588  static timeout_id_t mptsas_reset_watch;
 588  589  static timeout_id_t mptsas_timeout_id;
 589  590  static int mptsas_timeouts_enabled = 0;
      591 +
 590  592  /*
      593 + * The only software retriction on switching msg buffers to 64 bit seems to
      594 + * be the Auto Request Sense interface. The high 32 bits for all such
      595 + * requests appear to be required to sit in the same 4G segment.
      596 + * See initialization of SenseBufferAddressHigh in mptsas_init.c, and
      597 + * the use of SenseBufferLowAddress in requests. Note that there is
      598 + * currently a dependency on scsi_alloc_consistent_buf() adhering to
      599 + * this requirement.
      600 + * There is also a question about improved performance over PCI/PCIX
      601 + * if transfers are within the first 4Gb.
      602 + */
      603 +static int mptsas_use_64bit_msgaddr = 0;
      604 +
      605 +/*
 591  606   * warlock directives
 592  607   */
 593  608  _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", scsi_pkt \
 594  609          mptsas_cmd NcrTableIndirect buf scsi_cdb scsi_status))
 595  610  _NOTE(SCHEME_PROTECTS_DATA("unique per pkt", smp_pkt))
 596  611  _NOTE(SCHEME_PROTECTS_DATA("stable data", scsi_device scsi_address))
 597  612  _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", mptsas_tgt_private))
 598  613  _NOTE(SCHEME_PROTECTS_DATA("No Mutex Needed", scsi_hba_tran::tran_tgt_private))
 599  614  
 600  615  /*
↓ open down ↓ 557 lines elided ↑ open up ↑
1158 1173          }
1159 1174  
1160 1175          /* Indicate that we are 'sizeof (scsi_*(9S))' clean. */
1161 1176          scsi_size_clean(dip);
1162 1177  
1163 1178          mpt->m_dip = dip;
1164 1179          mpt->m_instance = instance;
1165 1180  
1166 1181          /* Make a per-instance copy of the structures */
1167 1182          mpt->m_io_dma_attr = mptsas_dma_attrs64;
1168      -        mpt->m_msg_dma_attr = mptsas_dma_attrs;
     1183 +        if (mptsas_use_64bit_msgaddr) {
     1184 +                mpt->m_msg_dma_attr = mptsas_dma_attrs64;
     1185 +        } else {
     1186 +                mpt->m_msg_dma_attr = mptsas_dma_attrs;
     1187 +        }
1169 1188          mpt->m_reg_acc_attr = mptsas_dev_attr;
1170 1189          mpt->m_dev_acc_attr = mptsas_dev_attr;
1171 1190  
1172 1191          /*
1173 1192           * Initialize FMA
1174 1193           */
1175 1194          mpt->m_fm_capabilities = ddi_getprop(DDI_DEV_T_ANY, mpt->m_dip,
1176 1195              DDI_PROP_CANSLEEP | DDI_PROP_DONTPASS, "fm-capable",
1177 1196              DDI_FM_EREPORT_CAPABLE | DDI_FM_ACCCHK_CAPABLE |
1178 1197              DDI_FM_DMACHK_CAPABLE | DDI_FM_ERRCB_CAPABLE);
↓ open down ↓ 75 lines elided ↑ open up ↑
1254 1273                              &mpt->m_doneq_thread_id[j].arg,
1255 1274                              0, &p0, TS_RUN, minclsyspri);
1256 1275                          mpt->m_doneq_thread_id[j].donetail =
1257 1276                              &mpt->m_doneq_thread_id[j].doneq;
1258 1277                          mutex_exit(&mpt->m_doneq_thread_id[j].mutex);
1259 1278                  }
1260 1279                  mutex_exit(&mpt->m_doneq_mutex);
1261 1280                  doneq_thread_create++;
1262 1281          }
1263 1282  
     1283 +        /*
     1284 +         * Disable hardware interrupt since we're not ready to
     1285 +         * handle it yet.
     1286 +         */
     1287 +        MPTSAS_DISABLE_INTR(mpt);
     1288 +        if (mptsas_register_intrs(mpt) == FALSE)
     1289 +                goto fail;
     1290 +        intr_added++;
     1291 +
1264 1292          /* Initialize mutex used in interrupt handler */
1265 1293          mutex_init(&mpt->m_mutex, NULL, MUTEX_DRIVER,
1266 1294              DDI_INTR_PRI(mpt->m_intr_pri));
1267 1295          mutex_init(&mpt->m_passthru_mutex, NULL, MUTEX_DRIVER, NULL);
1268 1296          mutex_init(&mpt->m_tx_waitq_mutex, NULL, MUTEX_DRIVER,
1269 1297              DDI_INTR_PRI(mpt->m_intr_pri));
1270 1298          for (i = 0; i < MPTSAS_MAX_PHYS; i++) {
1271 1299                  mutex_init(&mpt->m_phy_info[i].smhba_info.phy_mutex,
1272 1300                      NULL, MUTEX_DRIVER,
1273 1301                      DDI_INTR_PRI(mpt->m_intr_pri));
1274 1302          }
1275 1303  
1276 1304          cv_init(&mpt->m_cv, NULL, CV_DRIVER, NULL);
1277 1305          cv_init(&mpt->m_passthru_cv, NULL, CV_DRIVER, NULL);
1278 1306          cv_init(&mpt->m_fw_cv, NULL, CV_DRIVER, NULL);
1279 1307          cv_init(&mpt->m_config_cv, NULL, CV_DRIVER, NULL);
1280 1308          cv_init(&mpt->m_fw_diag_cv, NULL, CV_DRIVER, NULL);
1281 1309          mutex_init_done++;
1282 1310  
1283      -        /*
1284      -         * Disable hardware interrupt since we're not ready to
1285      -         * handle it yet.
1286      -         */
1287      -        MPTSAS_DISABLE_INTR(mpt);
1288      -        if (mptsas_register_intrs(mpt) == FALSE)
1289      -                goto fail;
1290      -        intr_added++;
1291      -
1292 1311          mutex_enter(&mpt->m_mutex);
1293 1312          /*
1294 1313           * Initialize power management component
1295 1314           */
1296 1315          if (mpt->m_options & MPTSAS_OPT_PM) {
1297 1316                  if (mptsas_init_pm(mpt)) {
1298 1317                          mutex_exit(&mpt->m_mutex);
1299 1318                          mptsas_log(mpt, CE_WARN, "mptsas pm initialization "
1300 1319                              "failed");
1301 1320                          goto fail;
↓ open down ↓ 913 lines elided ↑ open up ↑
2215 2234  mptsas_cache_create(mptsas_t *mpt)
2216 2235  {
2217 2236          int instance = mpt->m_instance;
2218 2237          char buf[64];
2219 2238  
2220 2239          /*
2221 2240           * create kmem cache for packets
2222 2241           */
2223 2242          (void) sprintf(buf, "mptsas%d_cache", instance);
2224 2243          mpt->m_kmem_cache = kmem_cache_create(buf,
2225      -            sizeof (struct mptsas_cmd) + scsi_pkt_size(), 8,
     2244 +            sizeof (struct mptsas_cmd) + scsi_pkt_size(), 16,
2226 2245              mptsas_kmem_cache_constructor, mptsas_kmem_cache_destructor,
2227 2246              NULL, (void *)mpt, NULL, 0);
2228 2247  
2229 2248          if (mpt->m_kmem_cache == NULL) {
2230 2249                  mptsas_log(mpt, CE_WARN, "creating kmem cache failed");
2231 2250                  return (FALSE);
2232 2251          }
2233 2252  
2234 2253          /*
2235 2254           * create kmem cache for extra SGL frames if SGL cannot
2236 2255           * be accomodated into main request frame.
2237 2256           */
2238 2257          (void) sprintf(buf, "mptsas%d_cache_frames", instance);
2239 2258          mpt->m_cache_frames = kmem_cache_create(buf,
2240      -            sizeof (mptsas_cache_frames_t), 8,
     2259 +            sizeof (mptsas_cache_frames_t), 16,
2241 2260              mptsas_cache_frames_constructor, mptsas_cache_frames_destructor,
2242 2261              NULL, (void *)mpt, NULL, 0);
2243 2262  
2244 2263          if (mpt->m_cache_frames == NULL) {
2245 2264                  mptsas_log(mpt, CE_WARN, "creating cache for frames failed");
2246 2265                  return (FALSE);
2247 2266          }
2248 2267  
2249 2268          return (TRUE);
2250 2269  }
↓ open down ↓ 1713 lines elided ↑ open up ↑
3964 3983                  mptsas_log(mpt, CE_WARN, "Unable to bind DMA resources for"
3965 3984                      " extra SGL");
3966 3985                  return (DDI_FAILURE);
3967 3986          }
3968 3987  
3969 3988          /*
3970 3989           * Store the SGL memory address.  This chip uses this
3971 3990           * address to dma to and from the driver.  The second
3972 3991           * address is the address mpt uses to fill in the SGL.
3973 3992           */
3974      -        p->m_phys_addr = cookie.dmac_address;
     3993 +        p->m_phys_addr = cookie.dmac_laddress;
3975 3994  
3976 3995          return (DDI_SUCCESS);
3977 3996  }
3978 3997  
3979 3998  static void
3980 3999  mptsas_cache_frames_destructor(void *buf, void *cdrarg)
3981 4000  {
3982 4001  #ifndef __lock_lint
3983 4002          _NOTE(ARGUNUSED(cdrarg))
3984 4003  #endif
↓ open down ↓ 186 lines elided ↑ open up ↑
4171 4190  {
4172 4191          if ((cmd->cmd_flags & CFLAG_CMDIOPB) &&
4173 4192              (!(cmd->cmd_flags & CFLAG_DMASEND))) {
4174 4193                  (void) ddi_dma_sync(cmd->cmd_dmahandle, 0, 0,
4175 4194                      DDI_DMA_SYNC_FORCPU);
4176 4195          }
4177 4196          (*pkt->pkt_comp)(pkt);
4178 4197  }
4179 4198  
4180 4199  static void
4181      -mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
4182      -        pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
     4200 +mptsas_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
     4201 +                ddi_acc_handle_t acc_hdl, uint_t cookiec,
     4202 +                uint32_t end_flags)
4183 4203  {
4184      -        uint_t                  cookiec;
     4204 +        pMpi2SGESimple64_t      sge;
4185 4205          mptti_t                 *dmap;
4186 4206          uint32_t                flags;
     4207 +
     4208 +        dmap = cmd->cmd_sg;
     4209 +
     4210 +        sge = (pMpi2SGESimple64_t)(&frame->SGL);
     4211 +        while (cookiec--) {
     4212 +                ddi_put32(acc_hdl, &sge->Address.Low,
     4213 +                    dmap->addr.address64.Low);
     4214 +                ddi_put32(acc_hdl, &sge->Address.High,
     4215 +                    dmap->addr.address64.High);
     4216 +                ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
     4217 +                flags = ddi_get32(acc_hdl, &sge->FlagsLength);
     4218 +                flags |= ((uint32_t)
     4219 +                    (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
     4220 +                    MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
     4221 +                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
     4222 +                    MPI2_SGE_FLAGS_SHIFT);
     4223 +
     4224 +                /*
     4225 +                 * If this is the last cookie, we set the flags
     4226 +                 * to indicate so
     4227 +                 */
     4228 +                if (cookiec == 0) {
     4229 +                        flags |= end_flags;
     4230 +                }
     4231 +                if (cmd->cmd_flags & CFLAG_DMASEND) {
     4232 +                        flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
     4233 +                            MPI2_SGE_FLAGS_SHIFT);
     4234 +                } else {
     4235 +                        flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
     4236 +                            MPI2_SGE_FLAGS_SHIFT);
     4237 +                }
     4238 +                ddi_put32(acc_hdl, &sge->FlagsLength, flags);
     4239 +                dmap++;
     4240 +                sge++;
     4241 +        }
     4242 +}
     4243 +
     4244 +static void
     4245 +mptsas_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
     4246 +    pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
     4247 +{
4187 4248          pMpi2SGESimple64_t      sge;
4188 4249          pMpi2SGEChain64_t       sgechain;
4189      -        ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
     4250 +        uint64_t                nframe_phys_addr;
     4251 +        uint_t                  cookiec;
     4252 +        mptti_t                 *dmap;
     4253 +        uint32_t                flags;
     4254 +        int                     i, j, k, l, frames, sgemax;
     4255 +        int                     temp, maxframe_sges;
     4256 +        uint8_t                 chainflags;
     4257 +        uint16_t                chainlength;
     4258 +        mptsas_cache_frames_t   *p;
4190 4259  
     4260 +        cookiec = cmd->cmd_cookiec;
     4261 +
4191 4262          /*
4192      -         * Save the number of entries in the DMA
4193      -         * Scatter/Gather list
     4263 +         * Hereby we start to deal with multiple frames.
     4264 +         * The process is as follows:
     4265 +         * 1. Determine how many frames are needed for SGL element
     4266 +         *    storage; Note that all frames are stored in contiguous
     4267 +         *    memory space and in 64-bit DMA mode each element is
     4268 +         *    3 double-words (12 bytes) long.
     4269 +         * 2. Fill up the main frame. We need to do this separately
     4270 +         *    since it contains the SCSI IO request header and needs
     4271 +         *    dedicated processing. Note that the last 4 double-words
     4272 +         *    of the SCSI IO header is for SGL element storage
     4273 +         *    (MPI2_SGE_IO_UNION).
     4274 +         * 3. Fill the chain element in the main frame, so the DMA
     4275 +         *    engine can use the following frames.
     4276 +         * 4. Enter a loop to fill the remaining frames. Note that the
     4277 +         *    last frame contains no chain element.  The remaining
     4278 +         *    frames go into the mpt SGL buffer allocated on the fly,
     4279 +         *    not immediately following the main message frame, as in
     4280 +         *    Gen1.
     4281 +         * Some restrictions:
     4282 +         * 1. For 64-bit DMA, the simple element and chain element
     4283 +         *    are both of 3 double-words (12 bytes) in size, even
     4284 +         *    though all frames are stored in the first 4G of mem
     4285 +         *    range and the higher 32-bits of the address are always 0.
     4286 +         * 2. On some controllers (like the 1064/1068), a frame can
     4287 +         *    hold SGL elements with the last 1 or 2 double-words
     4288 +         *    (4 or 8 bytes) un-used. On these controllers, we should
     4289 +         *    recognize that there's not enough room for another SGL
     4290 +         *    element and move the sge pointer to the next frame.
4194 4291           */
4195      -        cookiec = cmd->cmd_cookiec;
4196 4292  
4197      -        NDBG1(("mptsas_sge_setup: cookiec=%d", cookiec));
     4293 +        /*
     4294 +         * Sgemax is the number of SGE's that will fit
     4295 +         * each extra frame and frames is total
     4296 +         * number of frames we'll need.  1 sge entry per
     4297 +         * frame is reseverd for the chain element thus the -1 below.
     4298 +         */
     4299 +        sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64)) - 1);
     4300 +        maxframe_sges = MPTSAS_MAX_FRAME_SGES64(mpt);
     4301 +        temp = (cookiec - (maxframe_sges - 1)) / sgemax;
4198 4302  
4199 4303          /*
4200      -         * Set read/write bit in control.
     4304 +         * A little check to see if we need to round up the number
     4305 +         * of frames we need
4201 4306           */
4202      -        if (cmd->cmd_flags & CFLAG_DMASEND) {
4203      -                *control |= MPI2_SCSIIO_CONTROL_WRITE;
     4307 +        if ((cookiec - (maxframe_sges - 1)) - (temp * sgemax) > 1) {
     4308 +                frames = (temp + 1);
4204 4309          } else {
4205      -                *control |= MPI2_SCSIIO_CONTROL_READ;
     4310 +                frames = temp;
4206 4311          }
     4312 +        dmap = cmd->cmd_sg;
     4313 +        sge = (pMpi2SGESimple64_t)(&frame->SGL);
4207 4314  
4208      -        ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
     4315 +        /*
     4316 +         * First fill in the main frame
     4317 +         */
     4318 +        j = maxframe_sges - 1;
     4319 +        mptsas_sge_mainframe(cmd, frame, acc_hdl, j,
     4320 +            ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT) <<
     4321 +            MPI2_SGE_FLAGS_SHIFT));
     4322 +        dmap += j;
     4323 +        sge += j;
     4324 +        j++;
4209 4325  
4210 4326          /*
4211      -         * We have 2 cases here.  First where we can fit all the
4212      -         * SG elements into the main frame, and the case
4213      -         * where we can't.
4214      -         * If we have more cookies than we can attach to a frame
4215      -         * we will need to use a chain element to point
4216      -         * a location of memory where the rest of the S/G
4217      -         * elements reside.
     4327 +         * Fill in the chain element in the main frame.
     4328 +         * About calculation on ChainOffset:
     4329 +         * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
     4330 +         *    in the end reserved for SGL element storage
     4331 +         *    (MPI2_SGE_IO_UNION); we should count it in our
     4332 +         *    calculation.  See its definition in the header file.
     4333 +         * 2. Constant j is the counter of the current SGL element
     4334 +         *    that will be processed, and (j - 1) is the number of
     4335 +         *    SGL elements that have been processed (stored in the
     4336 +         *    main frame).
     4337 +         * 3. ChainOffset value should be in units of double-words (4
     4338 +         *    bytes) so the last value should be divided by 4.
4218 4339           */
4219      -        if (cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
4220      -                dmap = cmd->cmd_sg;
4221      -                sge = (pMpi2SGESimple64_t)(&frame->SGL);
4222      -                while (cookiec--) {
4223      -                        ddi_put32(acc_hdl,
4224      -                            &sge->Address.Low, dmap->addr.address64.Low);
4225      -                        ddi_put32(acc_hdl,
4226      -                            &sge->Address.High, dmap->addr.address64.High);
4227      -                        ddi_put32(acc_hdl, &sge->FlagsLength,
4228      -                            dmap->count);
4229      -                        flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4230      -                        flags |= ((uint32_t)
4231      -                            (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4232      -                            MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4233      -                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4234      -                            MPI2_SGE_FLAGS_SHIFT);
     4340 +        ddi_put8(acc_hdl, &frame->ChainOffset,
     4341 +            (sizeof (MPI2_SCSI_IO_REQUEST) -
     4342 +            sizeof (MPI2_SGE_IO_UNION) +
     4343 +            (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
     4344 +        sgechain = (pMpi2SGEChain64_t)sge;
     4345 +        chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
     4346 +            MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
     4347 +            MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
     4348 +        ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
4235 4349  
     4350 +        /*
     4351 +         * The size of the next frame is the accurate size of space
     4352 +         * (in bytes) used to store the SGL elements. j is the counter
     4353 +         * of SGL elements. (j - 1) is the number of SGL elements that
     4354 +         * have been processed (stored in frames).
     4355 +         */
     4356 +        if (frames >= 2) {
     4357 +                chainlength = mpt->m_req_frame_size /
     4358 +                    sizeof (MPI2_SGE_SIMPLE64) *
     4359 +                    sizeof (MPI2_SGE_SIMPLE64);
     4360 +        } else {
     4361 +                chainlength = ((cookiec - (j - 1)) *
     4362 +                    sizeof (MPI2_SGE_SIMPLE64));
     4363 +        }
     4364 +
     4365 +        p = cmd->cmd_extra_frames;
     4366 +
     4367 +        ddi_put16(acc_hdl, &sgechain->Length, chainlength);
     4368 +        ddi_put32(acc_hdl, &sgechain->Address.Low,
     4369 +            (p->m_phys_addr&0xffffffffull));
     4370 +        ddi_put32(acc_hdl, &sgechain->Address.High, p->m_phys_addr>>32);
     4371 +
     4372 +        /*
     4373 +         * If there are more than 2 frames left we have to
     4374 +         * fill in the next chain offset to the location of
     4375 +         * the chain element in the next frame.
     4376 +         * sgemax is the number of simple elements in an extra
     4377 +         * frame. Note that the value NextChainOffset should be
     4378 +         * in double-words (4 bytes).
     4379 +         */
     4380 +        if (frames >= 2) {
     4381 +                ddi_put8(acc_hdl, &sgechain->NextChainOffset,
     4382 +                    (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
     4383 +        } else {
     4384 +                ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
     4385 +        }
     4386 +
     4387 +        /*
     4388 +         * Jump to next frame;
     4389 +         * Starting here, chain buffers go into the per command SGL.
     4390 +         * This buffer is allocated when chain buffers are needed.
     4391 +         */
     4392 +        sge = (pMpi2SGESimple64_t)p->m_frames_addr;
     4393 +        i = cookiec;
     4394 +
     4395 +        /*
     4396 +         * Start filling in frames with SGE's.  If we
     4397 +         * reach the end of frame and still have SGE's
     4398 +         * to fill we need to add a chain element and
     4399 +         * use another frame.  j will be our counter
     4400 +         * for what cookie we are at and i will be
     4401 +         * the total cookiec. k is the current frame
     4402 +         */
     4403 +        for (k = 1; k <= frames; k++) {
     4404 +                for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
     4405 +
4236 4406                          /*
4237      -                         * If this is the last cookie, we set the flags
4238      -                         * to indicate so
     4407 +                         * If we have reached the end of frame
     4408 +                         * and we have more SGE's to fill in
     4409 +                         * we have to fill the final entry
     4410 +                         * with a chain element and then
     4411 +                         * continue to the next frame
4239 4412                           */
4240      -                        if (cookiec == 0) {
4241      -                                flags |=
4242      -                                    ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
4243      -                                    | MPI2_SGE_FLAGS_END_OF_BUFFER
4244      -                                    | MPI2_SGE_FLAGS_END_OF_LIST) <<
4245      -                                    MPI2_SGE_FLAGS_SHIFT);
4246      -                        }
4247      -                        if (cmd->cmd_flags & CFLAG_DMASEND) {
4248      -                                flags |= (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4249      -                                    MPI2_SGE_FLAGS_SHIFT);
4250      -                        } else {
4251      -                                flags |= (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4252      -                                    MPI2_SGE_FLAGS_SHIFT);
4253      -                        }
4254      -                        ddi_put32(acc_hdl, &sge->FlagsLength, flags);
4255      -                        dmap++;
4256      -                        sge++;
4257      -                }
4258      -        } else {
4259      -                /*
4260      -                 * Hereby we start to deal with multiple frames.
4261      -                 * The process is as follows:
4262      -                 * 1. Determine how many frames are needed for SGL element
4263      -                 *    storage; Note that all frames are stored in contiguous
4264      -                 *    memory space and in 64-bit DMA mode each element is
4265      -                 *    3 double-words (12 bytes) long.
4266      -                 * 2. Fill up the main frame. We need to do this separately
4267      -                 *    since it contains the SCSI IO request header and needs
4268      -                 *    dedicated processing. Note that the last 4 double-words
4269      -                 *    of the SCSI IO header is for SGL element storage
4270      -                 *    (MPI2_SGE_IO_UNION).
4271      -                 * 3. Fill the chain element in the main frame, so the DMA
4272      -                 *    engine can use the following frames.
4273      -                 * 4. Enter a loop to fill the remaining frames. Note that the
4274      -                 *    last frame contains no chain element.  The remaining
4275      -                 *    frames go into the mpt SGL buffer allocated on the fly,
4276      -                 *    not immediately following the main message frame, as in
4277      -                 *    Gen1.
4278      -                 * Some restrictions:
4279      -                 * 1. For 64-bit DMA, the simple element and chain element
4280      -                 *    are both of 3 double-words (12 bytes) in size, even
4281      -                 *    though all frames are stored in the first 4G of mem
4282      -                 *    range and the higher 32-bits of the address are always 0.
4283      -                 * 2. On some controllers (like the 1064/1068), a frame can
4284      -                 *    hold SGL elements with the last 1 or 2 double-words
4285      -                 *    (4 or 8 bytes) un-used. On these controllers, we should
4286      -                 *    recognize that there's not enough room for another SGL
4287      -                 *    element and move the sge pointer to the next frame.
4288      -                 */
4289      -                int             i, j, k, l, frames, sgemax;
4290      -                int             temp;
4291      -                uint8_t         chainflags;
4292      -                uint16_t        chainlength;
4293      -                mptsas_cache_frames_t *p;
     4413 +                        if ((l == (sgemax + 1)) && (k != frames)) {
     4414 +                                sgechain = (pMpi2SGEChain64_t)sge;
     4415 +                                j--;
     4416 +                                chainflags = (
     4417 +                                    MPI2_SGE_FLAGS_CHAIN_ELEMENT |
     4418 +                                    MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
     4419 +                                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
     4420 +                                ddi_put8(p->m_acc_hdl,
     4421 +                                    &sgechain->Flags, chainflags);
     4422 +                                /*
     4423 +                                 * k is the frame counter and (k + 1)
     4424 +                                 * is the number of the next frame.
     4425 +                                 * Note that frames are in contiguous
     4426 +                                 * memory space.
     4427 +                                 */
     4428 +                                nframe_phys_addr = p->m_phys_addr +
     4429 +                                    (mpt->m_req_frame_size * k);
     4430 +                                ddi_put32(p->m_acc_hdl,
     4431 +                                    &sgechain->Address.Low,
     4432 +                                    nframe_phys_addr&0xffffffffull);
     4433 +                                ddi_put32(p->m_acc_hdl,
     4434 +                                    &sgechain->Address.High,
     4435 +                                    nframe_phys_addr>>32);
4294 4436  
4295      -                /*
4296      -                 * Sgemax is the number of SGE's that will fit
4297      -                 * each extra frame and frames is total
4298      -                 * number of frames we'll need.  1 sge entry per
4299      -                 * frame is reseverd for the chain element thus the -1 below.
4300      -                 */
4301      -                sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_SGE_SIMPLE64))
4302      -                    - 1);
4303      -                temp = (cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) / sgemax;
     4437 +                                /*
     4438 +                                 * If there are more than 2 frames left
     4439 +                                 * we have to next chain offset to
     4440 +                                 * the location of the chain element
     4441 +                                 * in the next frame and fill in the
     4442 +                                 * length of the next chain
     4443 +                                 */
     4444 +                                if ((frames - k) >= 2) {
     4445 +                                        ddi_put8(p->m_acc_hdl,
     4446 +                                            &sgechain->NextChainOffset,
     4447 +                                            (sgemax *
     4448 +                                            sizeof (MPI2_SGE_SIMPLE64))
     4449 +                                            >> 2);
     4450 +                                        ddi_put16(p->m_acc_hdl,
     4451 +                                            &sgechain->Length,
     4452 +                                            mpt->m_req_frame_size /
     4453 +                                            sizeof (MPI2_SGE_SIMPLE64) *
     4454 +                                            sizeof (MPI2_SGE_SIMPLE64));
     4455 +                                } else {
     4456 +                                        /*
     4457 +                                         * This is the last frame. Set
     4458 +                                         * the NextChainOffset to 0 and
     4459 +                                         * Length is the total size of
     4460 +                                         * all remaining simple elements
     4461 +                                         */
     4462 +                                        ddi_put8(p->m_acc_hdl,
     4463 +                                            &sgechain->NextChainOffset,
     4464 +                                            0);
     4465 +                                        ddi_put16(p->m_acc_hdl,
     4466 +                                            &sgechain->Length,
     4467 +                                            (cookiec - j) *
     4468 +                                            sizeof (MPI2_SGE_SIMPLE64));
     4469 +                                }
4304 4470  
4305      -                /*
4306      -                 * A little check to see if we need to round up the number
4307      -                 * of frames we need
4308      -                 */
4309      -                if ((cookiec - (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) - (temp *
4310      -                    sgemax) > 1) {
4311      -                        frames = (temp + 1);
4312      -                } else {
4313      -                        frames = temp;
4314      -                }
4315      -                dmap = cmd->cmd_sg;
4316      -                sge = (pMpi2SGESimple64_t)(&frame->SGL);
     4471 +                                /* Jump to the next frame */
     4472 +                                sge = (pMpi2SGESimple64_t)
     4473 +                                    ((char *)p->m_frames_addr +
     4474 +                                    (int)mpt->m_req_frame_size * k);
4317 4475  
4318      -                /*
4319      -                 * First fill in the main frame
4320      -                 */
4321      -                for (j = 1; j < MPTSAS_MAX_FRAME_SGES64(mpt); j++) {
4322      -                        ddi_put32(acc_hdl, &sge->Address.Low,
     4476 +                                continue;
     4477 +                        }
     4478 +
     4479 +                        ddi_put32(p->m_acc_hdl,
     4480 +                            &sge->Address.Low,
4323 4481                              dmap->addr.address64.Low);
4324      -                        ddi_put32(acc_hdl, &sge->Address.High,
     4482 +                        ddi_put32(p->m_acc_hdl,
     4483 +                            &sge->Address.High,
4325 4484                              dmap->addr.address64.High);
4326      -                        ddi_put32(acc_hdl, &sge->FlagsLength, dmap->count);
4327      -                        flags = ddi_get32(acc_hdl, &sge->FlagsLength);
4328      -                        flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
     4485 +                        ddi_put32(p->m_acc_hdl,
     4486 +                            &sge->FlagsLength, dmap->count);
     4487 +                        flags = ddi_get32(p->m_acc_hdl,
     4488 +                            &sge->FlagsLength);
     4489 +                        flags |= ((uint32_t)(
     4490 +                            MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4329 4491                              MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4330 4492                              MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4331 4493                              MPI2_SGE_FLAGS_SHIFT);
4332 4494  
4333 4495                          /*
4334      -                         * If this is the last SGE of this frame
4335      -                         * we set the end of list flag
     4496 +                         * If we are at the end of the frame and
     4497 +                         * there is another frame to fill in
     4498 +                         * we set the last simple element as last
     4499 +                         * element
4336 4500                           */
4337      -                        if (j == (MPTSAS_MAX_FRAME_SGES64(mpt) - 1)) {
     4501 +                        if ((l == sgemax) && (k != frames)) {
4338 4502                                  flags |= ((uint32_t)
4339 4503                                      (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4340 4504                                      MPI2_SGE_FLAGS_SHIFT);
4341 4505                          }
     4506 +
     4507 +                        /*
     4508 +                         * If this is the final cookie we
     4509 +                         * indicate it by setting the flags
     4510 +                         */
     4511 +                        if (j == i) {
     4512 +                                flags |= ((uint32_t)
     4513 +                                    (MPI2_SGE_FLAGS_LAST_ELEMENT |
     4514 +                                    MPI2_SGE_FLAGS_END_OF_BUFFER |
     4515 +                                    MPI2_SGE_FLAGS_END_OF_LIST) <<
     4516 +                                    MPI2_SGE_FLAGS_SHIFT);
     4517 +                        }
4342 4518                          if (cmd->cmd_flags & CFLAG_DMASEND) {
4343 4519                                  flags |=
4344 4520                                      (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4345 4521                                      MPI2_SGE_FLAGS_SHIFT);
4346 4522                          } else {
4347 4523                                  flags |=
4348 4524                                      (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4349 4525                                      MPI2_SGE_FLAGS_SHIFT);
4350 4526                          }
4351      -                        ddi_put32(acc_hdl, &sge->FlagsLength, flags);
     4527 +                        ddi_put32(p->m_acc_hdl,
     4528 +                            &sge->FlagsLength, flags);
4352 4529                          dmap++;
4353 4530                          sge++;
4354 4531                  }
     4532 +        }
4355 4533  
4356      -                /*
4357      -                 * Fill in the chain element in the main frame.
4358      -                 * About calculation on ChainOffset:
4359      -                 * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
4360      -                 *    in the end reserved for SGL element storage
4361      -                 *    (MPI2_SGE_IO_UNION); we should count it in our
4362      -                 *    calculation.  See its definition in the header file.
4363      -                 * 2. Constant j is the counter of the current SGL element
4364      -                 *    that will be processed, and (j - 1) is the number of
4365      -                 *    SGL elements that have been processed (stored in the
4366      -                 *    main frame).
4367      -                 * 3. ChainOffset value should be in units of double-words (4
4368      -                 *    bytes) so the last value should be divided by 4.
4369      -                 */
4370      -                ddi_put8(acc_hdl, &frame->ChainOffset,
4371      -                    (sizeof (MPI2_SCSI_IO_REQUEST) -
4372      -                    sizeof (MPI2_SGE_IO_UNION) +
4373      -                    (j - 1) * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4374      -                sgechain = (pMpi2SGEChain64_t)sge;
4375      -                chainflags = (MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4376      -                    MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4377      -                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4378      -                ddi_put8(acc_hdl, &sgechain->Flags, chainflags);
     4534 +        /*
     4535 +         * Sync DMA with the chain buffers that were just created
     4536 +         */
     4537 +        (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
     4538 +}
4379 4539  
4380      -                /*
4381      -                 * The size of the next frame is the accurate size of space
4382      -                 * (in bytes) used to store the SGL elements. j is the counter
4383      -                 * of SGL elements. (j - 1) is the number of SGL elements that
4384      -                 * have been processed (stored in frames).
4385      -                 */
4386      -                if (frames >= 2) {
4387      -                        chainlength = mpt->m_req_frame_size /
4388      -                            sizeof (MPI2_SGE_SIMPLE64) *
4389      -                            sizeof (MPI2_SGE_SIMPLE64);
4390      -                } else {
4391      -                        chainlength = ((cookiec - (j - 1)) *
4392      -                            sizeof (MPI2_SGE_SIMPLE64));
4393      -                }
     4540 +static void
     4541 +mptsas_ieee_sge_mainframe(mptsas_cmd_t *cmd, pMpi2SCSIIORequest_t frame,
     4542 +    ddi_acc_handle_t acc_hdl, uint_t cookiec,
     4543 +    uint8_t end_flag)
     4544 +{
     4545 +        pMpi2IeeeSgeSimple64_t  ieeesge;
     4546 +        mptti_t                 *dmap;
     4547 +        uint8_t                 flags;
4394 4548  
4395      -                p = cmd->cmd_extra_frames;
     4549 +        dmap = cmd->cmd_sg;
4396 4550  
4397      -                ddi_put16(acc_hdl, &sgechain->Length, chainlength);
4398      -                ddi_put32(acc_hdl, &sgechain->Address.Low,
4399      -                    p->m_phys_addr);
4400      -                /* SGL is allocated in the first 4G mem range */
4401      -                ddi_put32(acc_hdl, &sgechain->Address.High, 0);
     4551 +        NDBG1(("mptsas_ieee_sge_mainframe: cookiec=%d, %s", cookiec,
     4552 +            cmd->cmd_flags & CFLAG_DMASEND?"Out":"In"));
4402 4553  
     4554 +        ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
     4555 +        while (cookiec--) {
     4556 +                ddi_put32(acc_hdl, &ieeesge->Address.Low,
     4557 +                    dmap->addr.address64.Low);
     4558 +                ddi_put32(acc_hdl, &ieeesge->Address.High,
     4559 +                    dmap->addr.address64.High);
     4560 +                ddi_put32(acc_hdl, &ieeesge->Length, dmap->count);
     4561 +                NDBG1(("mptsas_ieee_sge_mainframe: len=%d", dmap->count));
     4562 +                flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
     4563 +                    MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
     4564 +
4403 4565                  /*
4404      -                 * If there are more than 2 frames left we have to
4405      -                 * fill in the next chain offset to the location of
4406      -                 * the chain element in the next frame.
4407      -                 * sgemax is the number of simple elements in an extra
4408      -                 * frame. Note that the value NextChainOffset should be
4409      -                 * in double-words (4 bytes).
     4566 +                 * If this is the last cookie, we set the flags
     4567 +                 * to indicate so
4410 4568                   */
4411      -                if (frames >= 2) {
4412      -                        ddi_put8(acc_hdl, &sgechain->NextChainOffset,
4413      -                            (sgemax * sizeof (MPI2_SGE_SIMPLE64)) >> 2);
4414      -                } else {
4415      -                        ddi_put8(acc_hdl, &sgechain->NextChainOffset, 0);
     4569 +                if (cookiec == 0) {
     4570 +                        flags |= end_flag;
4416 4571                  }
4417 4572  
4418 4573                  /*
4419      -                 * Jump to next frame;
4420      -                 * Starting here, chain buffers go into the per command SGL.
4421      -                 * This buffer is allocated when chain buffers are needed.
     4574 +                 * XXX: Hmmm, what about the direction based on
     4575 +                 * cmd->cmd_flags & CFLAG_DMASEND?
4422 4576                   */
4423      -                sge = (pMpi2SGESimple64_t)p->m_frames_addr;
4424      -                i = cookiec;
     4577 +                ddi_put8(acc_hdl, &ieeesge->Flags, flags);
     4578 +                dmap++;
     4579 +                ieeesge++;
     4580 +        }
     4581 +}
4425 4582  
4426      -                /*
4427      -                 * Start filling in frames with SGE's.  If we
4428      -                 * reach the end of frame and still have SGE's
4429      -                 * to fill we need to add a chain element and
4430      -                 * use another frame.  j will be our counter
4431      -                 * for what cookie we are at and i will be
4432      -                 * the total cookiec. k is the current frame
4433      -                 */
4434      -                for (k = 1; k <= frames; k++) {
4435      -                        for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
     4583 +static void
     4584 +mptsas_ieee_sge_chain(mptsas_t *mpt, mptsas_cmd_t *cmd,
     4585 +    pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
     4586 +{
     4587 +        pMpi2IeeeSgeSimple64_t  ieeesge;
     4588 +        pMpi25IeeeSgeChain64_t  ieeesgechain;
     4589 +        uint64_t                nframe_phys_addr;
     4590 +        uint_t                  cookiec;
     4591 +        mptti_t                 *dmap;
     4592 +        uint8_t                 flags;
     4593 +        int                     i, j, k, l, frames, sgemax;
     4594 +        int                     temp, maxframe_sges;
     4595 +        uint8_t                 chainflags;
     4596 +        uint32_t                chainlength;
     4597 +        mptsas_cache_frames_t   *p;
4436 4598  
4437      -                                /*
4438      -                                 * If we have reached the end of frame
4439      -                                 * and we have more SGE's to fill in
4440      -                                 * we have to fill the final entry
4441      -                                 * with a chain element and then
4442      -                                 * continue to the next frame
4443      -                                 */
4444      -                                if ((l == (sgemax + 1)) && (k != frames)) {
4445      -                                        sgechain = (pMpi2SGEChain64_t)sge;
4446      -                                        j--;
4447      -                                        chainflags = (
4448      -                                            MPI2_SGE_FLAGS_CHAIN_ELEMENT |
4449      -                                            MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4450      -                                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING);
4451      -                                        ddi_put8(p->m_acc_hdl,
4452      -                                            &sgechain->Flags, chainflags);
4453      -                                        /*
4454      -                                         * k is the frame counter and (k + 1)
4455      -                                         * is the number of the next frame.
4456      -                                         * Note that frames are in contiguous
4457      -                                         * memory space.
4458      -                                         */
4459      -                                        ddi_put32(p->m_acc_hdl,
4460      -                                            &sgechain->Address.Low,
4461      -                                            (p->m_phys_addr +
4462      -                                            (mpt->m_req_frame_size * k)));
4463      -                                        ddi_put32(p->m_acc_hdl,
4464      -                                            &sgechain->Address.High, 0);
     4599 +        cookiec = cmd->cmd_cookiec;
4465 4600  
4466      -                                        /*
4467      -                                         * If there are more than 2 frames left
4468      -                                         * we have to next chain offset to
4469      -                                         * the location of the chain element
4470      -                                         * in the next frame and fill in the
4471      -                                         * length of the next chain
4472      -                                         */
4473      -                                        if ((frames - k) >= 2) {
4474      -                                                ddi_put8(p->m_acc_hdl,
4475      -                                                    &sgechain->NextChainOffset,
4476      -                                                    (sgemax *
4477      -                                                    sizeof (MPI2_SGE_SIMPLE64))
4478      -                                                    >> 2);
4479      -                                                ddi_put16(p->m_acc_hdl,
4480      -                                                    &sgechain->Length,
4481      -                                                    mpt->m_req_frame_size /
4482      -                                                    sizeof (MPI2_SGE_SIMPLE64) *
4483      -                                                    sizeof (MPI2_SGE_SIMPLE64));
4484      -                                        } else {
4485      -                                                /*
4486      -                                                 * This is the last frame. Set
4487      -                                                 * the NextChainOffset to 0 and
4488      -                                                 * Length is the total size of
4489      -                                                 * all remaining simple elements
4490      -                                                 */
4491      -                                                ddi_put8(p->m_acc_hdl,
4492      -                                                    &sgechain->NextChainOffset,
4493      -                                                    0);
4494      -                                                ddi_put16(p->m_acc_hdl,
4495      -                                                    &sgechain->Length,
4496      -                                                    (cookiec - j) *
4497      -                                                    sizeof (MPI2_SGE_SIMPLE64));
4498      -                                        }
     4601 +        NDBG1(("mptsas_ieee_sge_chain: cookiec=%d", cookiec));
4499 4602  
4500      -                                        /* Jump to the next frame */
4501      -                                        sge = (pMpi2SGESimple64_t)
4502      -                                            ((char *)p->m_frames_addr +
4503      -                                            (int)mpt->m_req_frame_size * k);
     4603 +        /*
     4604 +         * Hereby we start to deal with multiple frames.
     4605 +         * The process is as follows:
     4606 +         * 1. Determine how many frames are needed for SGL element
     4607 +         *    storage; Note that all frames are stored in contiguous
     4608 +         *    memory space and in 64-bit DMA mode each element is
     4609 +         *    4 double-words (16 bytes) long.
     4610 +         * 2. Fill up the main frame. We need to do this separately
     4611 +         *    since it contains the SCSI IO request header and needs
     4612 +         *    dedicated processing. Note that the last 4 double-words
     4613 +         *    of the SCSI IO header is for SGL element storage
     4614 +         *    (MPI2_SGE_IO_UNION).
     4615 +         * 3. Fill the chain element in the main frame, so the DMA
     4616 +         *    engine can use the following frames.
     4617 +         * 4. Enter a loop to fill the remaining frames. Note that the
     4618 +         *    last frame contains no chain element.  The remaining
     4619 +         *    frames go into the mpt SGL buffer allocated on the fly,
     4620 +         *    not immediately following the main message frame, as in
     4621 +         *    Gen1.
     4622 +         * Some restrictions:
     4623 +         * 1. For 64-bit DMA, the simple element and chain element
     4624 +         *    are both of 4 double-words (16 bytes) in size, even
     4625 +         *    though all frames are stored in the first 4G of mem
     4626 +         *    range and the higher 32-bits of the address are always 0.
     4627 +         * 2. On some controllers (like the 1064/1068), a frame can
     4628 +         *    hold SGL elements with the last 1 or 2 double-words
     4629 +         *    (4 or 8 bytes) un-used. On these controllers, we should
     4630 +         *    recognize that there's not enough room for another SGL
     4631 +         *    element and move the sge pointer to the next frame.
     4632 +         */
4504 4633  
4505      -                                        continue;
4506      -                                }
     4634 +        /*
     4635 +         * Sgemax is the number of SGE's that will fit
     4636 +         * each extra frame and frames is total
     4637 +         * number of frames we'll need.  1 sge entry per
     4638 +         * frame is reseverd for the chain element thus the -1 below.
     4639 +         */
     4640 +        sgemax = ((mpt->m_req_frame_size / sizeof (MPI2_IEEE_SGE_SIMPLE64))
     4641 +            - 1);
     4642 +        maxframe_sges = MPTSAS_MAX_FRAME_SGES64(mpt);
     4643 +        temp = (cookiec - (maxframe_sges - 1)) / sgemax;
4507 4644  
4508      -                                ddi_put32(p->m_acc_hdl,
4509      -                                    &sge->Address.Low,
4510      -                                    dmap->addr.address64.Low);
4511      -                                ddi_put32(p->m_acc_hdl,
4512      -                                    &sge->Address.High,
4513      -                                    dmap->addr.address64.High);
4514      -                                ddi_put32(p->m_acc_hdl,
4515      -                                    &sge->FlagsLength, dmap->count);
4516      -                                flags = ddi_get32(p->m_acc_hdl,
4517      -                                    &sge->FlagsLength);
4518      -                                flags |= ((uint32_t)(
4519      -                                    MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
4520      -                                    MPI2_SGE_FLAGS_SYSTEM_ADDRESS |
4521      -                                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
4522      -                                    MPI2_SGE_FLAGS_SHIFT);
     4645 +        /*
     4646 +         * A little check to see if we need to round up the number
     4647 +         * of frames we need
     4648 +         */
     4649 +        if ((cookiec - (maxframe_sges - 1)) - (temp * sgemax) > 1) {
     4650 +                frames = (temp + 1);
     4651 +        } else {
     4652 +                frames = temp;
     4653 +        }
     4654 +        NDBG1(("mptsas_ieee_sge_chain: temp=%d, frames=%d", temp, frames));
     4655 +        dmap = cmd->cmd_sg;
     4656 +        ieeesge = (pMpi2IeeeSgeSimple64_t)(&frame->SGL);
4523 4657  
     4658 +        /*
     4659 +         * First fill in the main frame
     4660 +         */
     4661 +        j = maxframe_sges - 1;
     4662 +        mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl, j, 0);
     4663 +        dmap += j;
     4664 +        ieeesge += j;
     4665 +        j++;
     4666 +
     4667 +        /*
     4668 +         * Fill in the chain element in the main frame.
     4669 +         * About calculation on ChainOffset:
     4670 +         * 1. Struct msg_scsi_io_request has 4 double-words (16 bytes)
     4671 +         *    in the end reserved for SGL element storage
     4672 +         *    (MPI2_SGE_IO_UNION); we should count it in our
     4673 +         *    calculation.  See its definition in the header file.
     4674 +         * 2. Constant j is the counter of the current SGL element
     4675 +         *    that will be processed, and (j - 1) is the number of
     4676 +         *    SGL elements that have been processed (stored in the
     4677 +         *    main frame).
     4678 +         * 3. ChainOffset value should be in units of quad-words (16
     4679 +         *    bytes) so the last value should be divided by 16.
     4680 +         */
     4681 +        ddi_put8(acc_hdl, &frame->ChainOffset,
     4682 +            (sizeof (MPI2_SCSI_IO_REQUEST) -
     4683 +            sizeof (MPI2_SGE_IO_UNION) +
     4684 +            (j - 1) * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
     4685 +        ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
     4686 +        chainflags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
     4687 +            MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
     4688 +        ddi_put8(acc_hdl, &ieeesgechain->Flags, chainflags);
     4689 +
     4690 +        /*
     4691 +         * The size of the next frame is the accurate size of space
     4692 +         * (in bytes) used to store the SGL elements. j is the counter
     4693 +         * of SGL elements. (j - 1) is the number of SGL elements that
     4694 +         * have been processed (stored in frames).
     4695 +         */
     4696 +        if (frames >= 2) {
     4697 +                chainlength = mpt->m_req_frame_size /
     4698 +                    sizeof (MPI2_IEEE_SGE_SIMPLE64) *
     4699 +                    sizeof (MPI2_IEEE_SGE_SIMPLE64);
     4700 +        } else {
     4701 +                chainlength = ((cookiec - (j - 1)) *
     4702 +                    sizeof (MPI2_IEEE_SGE_SIMPLE64));
     4703 +        }
     4704 +
     4705 +        p = cmd->cmd_extra_frames;
     4706 +
     4707 +        ddi_put32(acc_hdl, &ieeesgechain->Length, chainlength);
     4708 +        ddi_put32(acc_hdl, &ieeesgechain->Address.Low,
     4709 +            p->m_phys_addr&0xffffffffull);
     4710 +        ddi_put32(acc_hdl, &ieeesgechain->Address.High, p->m_phys_addr>>32);
     4711 +
     4712 +        /*
     4713 +         * If there are more than 2 frames left we have to
     4714 +         * fill in the next chain offset to the location of
     4715 +         * the chain element in the next frame.
     4716 +         * sgemax is the number of simple elements in an extra
     4717 +         * frame. Note that the value NextChainOffset should be
     4718 +         * in double-words (4 bytes).
     4719 +         */
     4720 +        if (frames >= 2) {
     4721 +                ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset,
     4722 +                    (sgemax * sizeof (MPI2_IEEE_SGE_SIMPLE64)) >> 4);
     4723 +        } else {
     4724 +                ddi_put8(acc_hdl, &ieeesgechain->NextChainOffset, 0);
     4725 +        }
     4726 +
     4727 +        /*
     4728 +         * Jump to next frame;
     4729 +         * Starting here, chain buffers go into the per command SGL.
     4730 +         * This buffer is allocated when chain buffers are needed.
     4731 +         */
     4732 +        ieeesge = (pMpi2IeeeSgeSimple64_t)p->m_frames_addr;
     4733 +        i = cookiec;
     4734 +
     4735 +        /*
     4736 +         * Start filling in frames with SGE's.  If we
     4737 +         * reach the end of frame and still have SGE's
     4738 +         * to fill we need to add a chain element and
     4739 +         * use another frame.  j will be our counter
     4740 +         * for what cookie we are at and i will be
     4741 +         * the total cookiec. k is the current frame
     4742 +         */
     4743 +        for (k = 1; k <= frames; k++) {
     4744 +                for (l = 1; (l <= (sgemax + 1)) && (j <= i); j++, l++) {
     4745 +
     4746 +                        /*
     4747 +                         * If we have reached the end of frame
     4748 +                         * and we have more SGE's to fill in
     4749 +                         * we have to fill the final entry
     4750 +                         * with a chain element and then
     4751 +                         * continue to the next frame
     4752 +                         */
     4753 +                        if ((l == (sgemax + 1)) && (k != frames)) {
     4754 +                                ieeesgechain = (pMpi25IeeeSgeChain64_t)ieeesge;
     4755 +                                j--;
     4756 +                                chainflags =
     4757 +                                    MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT |
     4758 +                                    MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR;
     4759 +                                ddi_put8(p->m_acc_hdl,
     4760 +                                    &ieeesgechain->Flags, chainflags);
4524 4761                                  /*
4525      -                                 * If we are at the end of the frame and
4526      -                                 * there is another frame to fill in
4527      -                                 * we set the last simple element as last
4528      -                                 * element
     4762 +                                 * k is the frame counter and (k + 1)
     4763 +                                 * is the number of the next frame.
     4764 +                                 * Note that frames are in contiguous
     4765 +                                 * memory space.
4529 4766                                   */
4530      -                                if ((l == sgemax) && (k != frames)) {
4531      -                                        flags |= ((uint32_t)
4532      -                                            (MPI2_SGE_FLAGS_LAST_ELEMENT) <<
4533      -                                            MPI2_SGE_FLAGS_SHIFT);
4534      -                                }
     4767 +                                nframe_phys_addr = p->m_phys_addr +
     4768 +                                    (mpt->m_req_frame_size * k);
     4769 +                                ddi_put32(p->m_acc_hdl,
     4770 +                                    &ieeesgechain->Address.Low,
     4771 +                                    nframe_phys_addr&0xffffffffull);
     4772 +                                ddi_put32(p->m_acc_hdl,
     4773 +                                    &ieeesgechain->Address.High,
     4774 +                                    nframe_phys_addr>>32);
4535 4775  
4536 4776                                  /*
4537      -                                 * If this is the final cookie we
4538      -                                 * indicate it by setting the flags
     4777 +                                 * If there are more than 2 frames left
     4778 +                                 * we have to next chain offset to
     4779 +                                 * the location of the chain element
     4780 +                                 * in the next frame and fill in the
     4781 +                                 * length of the next chain
4539 4782                                   */
4540      -                                if (j == i) {
4541      -                                        flags |= ((uint32_t)
4542      -                                            (MPI2_SGE_FLAGS_LAST_ELEMENT |
4543      -                                            MPI2_SGE_FLAGS_END_OF_BUFFER |
4544      -                                            MPI2_SGE_FLAGS_END_OF_LIST) <<
4545      -                                            MPI2_SGE_FLAGS_SHIFT);
4546      -                                }
4547      -                                if (cmd->cmd_flags & CFLAG_DMASEND) {
4548      -                                        flags |=
4549      -                                            (MPI2_SGE_FLAGS_HOST_TO_IOC <<
4550      -                                            MPI2_SGE_FLAGS_SHIFT);
     4783 +                                if ((frames - k) >= 2) {
     4784 +                                        ddi_put8(p->m_acc_hdl,
     4785 +                                            &ieeesgechain->NextChainOffset,
     4786 +                                            (sgemax *
     4787 +                                            sizeof (MPI2_IEEE_SGE_SIMPLE64))
     4788 +                                            >> 4);
     4789 +                                        ddi_put32(p->m_acc_hdl,
     4790 +                                            &ieeesgechain->Length,
     4791 +                                            mpt->m_req_frame_size /
     4792 +                                            sizeof (MPI2_IEEE_SGE_SIMPLE64) *
     4793 +                                            sizeof (MPI2_IEEE_SGE_SIMPLE64));
4551 4794                                  } else {
4552      -                                        flags |=
4553      -                                            (MPI2_SGE_FLAGS_IOC_TO_HOST <<
4554      -                                            MPI2_SGE_FLAGS_SHIFT);
     4795 +                                        /*
     4796 +                                         * This is the last frame. Set
     4797 +                                         * the NextChainOffset to 0 and
     4798 +                                         * Length is the total size of
     4799 +                                         * all remaining simple elements
     4800 +                                         */
     4801 +                                        ddi_put8(p->m_acc_hdl,
     4802 +                                            &ieeesgechain->NextChainOffset,
     4803 +                                            0);
     4804 +                                        ddi_put32(p->m_acc_hdl,
     4805 +                                            &ieeesgechain->Length,
     4806 +                                            (cookiec - j) *
     4807 +                                            sizeof (MPI2_IEEE_SGE_SIMPLE64));
4555 4808                                  }
4556      -                                ddi_put32(p->m_acc_hdl,
4557      -                                    &sge->FlagsLength, flags);
4558      -                                dmap++;
4559      -                                sge++;
     4809 +
     4810 +                                /* Jump to the next frame */
     4811 +                                ieeesge = (pMpi2IeeeSgeSimple64_t)
     4812 +                                    ((char *)p->m_frames_addr +
     4813 +                                    (int)mpt->m_req_frame_size * k);
     4814 +
     4815 +                                continue;
4560 4816                          }
     4817 +
     4818 +                        ddi_put32(p->m_acc_hdl,
     4819 +                            &ieeesge->Address.Low,
     4820 +                            dmap->addr.address64.Low);
     4821 +                        ddi_put32(p->m_acc_hdl,
     4822 +                            &ieeesge->Address.High,
     4823 +                            dmap->addr.address64.High);
     4824 +                        ddi_put32(p->m_acc_hdl,
     4825 +                            &ieeesge->Length, dmap->count);
     4826 +                        flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
     4827 +                            MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
     4828 +
     4829 +                        /*
     4830 +                         * If we are at the end of the frame and
     4831 +                         * there is another frame to fill in
     4832 +                         * do we need to do anything?
     4833 +                         * if ((l == sgemax) && (k != frames)) {
     4834 +                         * }
     4835 +                         */
     4836 +
     4837 +                        /*
     4838 +                         * If this is the final cookie set end of list.
     4839 +                         */
     4840 +                        if (j == i) {
     4841 +                                flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
     4842 +                        }
     4843 +
     4844 +                        ddi_put8(p->m_acc_hdl, &ieeesge->Flags, flags);
     4845 +                        dmap++;
     4846 +                        ieeesge++;
4561 4847                  }
     4848 +        }
4562 4849  
4563      -                /*
4564      -                 * Sync DMA with the chain buffers that were just created
4565      -                 */
4566      -                (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
     4850 +        /*
     4851 +         * Sync DMA with the chain buffers that were just created
     4852 +         */
     4853 +        (void) ddi_dma_sync(p->m_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
     4854 +}
     4855 +
     4856 +static void
     4857 +mptsas_sge_setup(mptsas_t *mpt, mptsas_cmd_t *cmd, uint32_t *control,
     4858 +    pMpi2SCSIIORequest_t frame, ddi_acc_handle_t acc_hdl)
     4859 +{
     4860 +        ASSERT(cmd->cmd_flags & CFLAG_DMAVALID);
     4861 +
     4862 +        NDBG1(("mptsas_sge_setup: cookiec=%d", cmd->cmd_cookiec));
     4863 +
     4864 +        /*
     4865 +         * Set read/write bit in control.
     4866 +         */
     4867 +        if (cmd->cmd_flags & CFLAG_DMASEND) {
     4868 +                *control |= MPI2_SCSIIO_CONTROL_WRITE;
     4869 +        } else {
     4870 +                *control |= MPI2_SCSIIO_CONTROL_READ;
4567 4871          }
     4872 +
     4873 +        ddi_put32(acc_hdl, &frame->DataLength, cmd->cmd_dmacount);
     4874 +
     4875 +        /*
     4876 +         * We have 4 cases here.  First where we can fit all the
     4877 +         * SG elements into the main frame, and the case
     4878 +         * where we can't. The SG element is also different when using
     4879 +         * MPI2.5 interface.
     4880 +         * If we have more cookies than we can attach to a frame
     4881 +         * we will need to use a chain element to point
     4882 +         * a location of memory where the rest of the S/G
     4883 +         * elements reside.
     4884 +         */
     4885 +        if (cmd->cmd_cookiec <= MPTSAS_MAX_FRAME_SGES64(mpt)) {
     4886 +                if (mpt->m_MPI25) {
     4887 +                        mptsas_ieee_sge_mainframe(cmd, frame, acc_hdl,
     4888 +                            cmd->cmd_cookiec,
     4889 +                            MPI25_IEEE_SGE_FLAGS_END_OF_LIST);
     4890 +                } else {
     4891 +                        mptsas_sge_mainframe(cmd, frame, acc_hdl,
     4892 +                            cmd->cmd_cookiec,
     4893 +                            ((uint32_t)(MPI2_SGE_FLAGS_LAST_ELEMENT
     4894 +                            | MPI2_SGE_FLAGS_END_OF_BUFFER
     4895 +                            | MPI2_SGE_FLAGS_END_OF_LIST) <<
     4896 +                            MPI2_SGE_FLAGS_SHIFT));
     4897 +                }
     4898 +        } else {
     4899 +                if (mpt->m_MPI25) {
     4900 +                        mptsas_ieee_sge_chain(mpt, cmd, frame, acc_hdl);
     4901 +                } else {
     4902 +                        mptsas_sge_chain(mpt, cmd, frame, acc_hdl);
     4903 +                }
     4904 +        }
4568 4905  }
4569 4906  
4570 4907  /*
4571 4908   * Interrupt handling
4572 4909   * Utility routine.  Poll for status of a command sent to HBA
4573 4910   * without interrupts (a FLAG_NOINTR command).
4574 4911   */
4575 4912  int
4576 4913  mptsas_poll(mptsas_t *mpt, mptsas_cmd_t *poll_cmd, int polltime)
4577 4914  {
↓ open down ↓ 906 lines elided ↑ open up ↑
5484 5821          ASSERT(mutex_owned(&mpt->m_mutex));
5485 5822  
5486 5823          /*
5487 5824           * The reply is valid, process it according to its
5488 5825           * type.  Also, set a flag for updated the reply index
5489 5826           * after they've all been processed.
5490 5827           */
5491 5828          reply_type = ddi_get8(mpt->m_acc_post_queue_hdl,
5492 5829              &reply_desc_union->Default.ReplyFlags);
5493 5830          reply_type &= MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
5494      -        if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) {
     5831 +        if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS ||
     5832 +            reply_type == MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS) {
5495 5833                  mptsas_handle_scsi_io_success(mpt, reply_desc_union);
5496 5834          } else if (reply_type == MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
5497 5835                  mptsas_handle_address_reply(mpt, reply_desc_union);
5498 5836          } else {
5499 5837                  mptsas_log(mpt, CE_WARN, "?Bad reply type %x", reply_type);
5500 5838                  ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
5501 5839          }
5502 5840  
5503 5841          /*
5504 5842           * Clear the reply descriptor for re-use and increment
↓ open down ↓ 3793 lines elided ↑ open up ↑
9298 9636  
9299 9637          mutex_enter(&mptsas_log_mutex);
9300 9638  
9301 9639          va_start(ap, fmt);
9302 9640          (void) vsprintf(mptsas_log_buf, fmt, ap);
9303 9641          va_end(ap);
9304 9642  
9305 9643  #ifdef PROM_PRINTF
9306 9644          prom_printf("%s:\t%s\n", mptsas_label, mptsas_log_buf);
9307 9645  #else
9308      -        scsi_log(dev, mptsas_label, SCSI_DEBUG, "%s\n", mptsas_log_buf);
     9646 +        scsi_log(dev, mptsas_label, CE_CONT, "!%s\n", mptsas_log_buf);
9309 9647  #endif
9310 9648          mutex_exit(&mptsas_log_mutex);
9311 9649  }
9312 9650  #endif
9313 9651  
9314 9652  /*
9315 9653   * timeout handling
9316 9654   */
9317 9655  static void
9318 9656  mptsas_watch(void *arg)
↓ open down ↓ 341 lines elided ↑ open up ↑
9660 9998          (void) sprintf(&buf[strlen(buf)], " ]");
9661 9999          NDBG25(("?%s\n", buf));
9662 10000          NDBG25(("?pkt_flags=0x%x pkt_statistics=0x%x pkt_state=0x%x\n",
9663 10001              cmd->cmd_pkt->pkt_flags, cmd->cmd_pkt->pkt_statistics,
9664 10002              cmd->cmd_pkt->pkt_state));
9665 10003          NDBG25(("?pkt_scbp=0x%x cmd_flags=0x%x\n", cmd->cmd_pkt->pkt_scbp ?
9666 10004              *(cmd->cmd_pkt->pkt_scbp) : 0, cmd->cmd_flags));
9667 10005  }
9668 10006  
9669 10007  static void
     10008 +mptsas_passthru_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
     10009 +    pMpi2SGESimple64_t sgep)
     10010 +{
     10011 +        uint32_t                sge_flags;
     10012 +        uint32_t                data_size, dataout_size;
     10013 +        ddi_dma_cookie_t        data_cookie;
     10014 +        ddi_dma_cookie_t        dataout_cookie;
     10015 +
     10016 +        data_size = pt->data_size;
     10017 +        dataout_size = pt->dataout_size;
     10018 +        data_cookie = pt->data_cookie;
     10019 +        dataout_cookie = pt->dataout_cookie;
     10020 +
     10021 +        if (dataout_size) {
     10022 +                sge_flags = dataout_size |
     10023 +                    ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
     10024 +                    MPI2_SGE_FLAGS_END_OF_BUFFER |
     10025 +                    MPI2_SGE_FLAGS_HOST_TO_IOC |
     10026 +                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
     10027 +                    MPI2_SGE_FLAGS_SHIFT);
     10028 +                ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
     10029 +                ddi_put32(acc_hdl, &sgep->Address.Low,
     10030 +                    (uint32_t)(dataout_cookie.dmac_laddress & 0xffffffffull));
     10031 +                ddi_put32(acc_hdl, &sgep->Address.High,
     10032 +                    (uint32_t)(dataout_cookie.dmac_laddress >> 32));
     10033 +                sgep++;
     10034 +        }
     10035 +        sge_flags = data_size;
     10036 +        sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
     10037 +            MPI2_SGE_FLAGS_LAST_ELEMENT |
     10038 +            MPI2_SGE_FLAGS_END_OF_BUFFER |
     10039 +            MPI2_SGE_FLAGS_END_OF_LIST |
     10040 +            MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
     10041 +            MPI2_SGE_FLAGS_SHIFT);
     10042 +        if (pt->direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
     10043 +                sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
     10044 +                    MPI2_SGE_FLAGS_SHIFT);
     10045 +        } else {
     10046 +                sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
     10047 +                    MPI2_SGE_FLAGS_SHIFT);
     10048 +        }
     10049 +        ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
     10050 +        ddi_put32(acc_hdl, &sgep->Address.Low,
     10051 +            (uint32_t)(data_cookie.dmac_laddress & 0xffffffffull));
     10052 +        ddi_put32(acc_hdl, &sgep->Address.High,
     10053 +            (uint32_t)(data_cookie.dmac_laddress >> 32));
     10054 +}
     10055 +
     10056 +static void
     10057 +mptsas_passthru_ieee_sge(ddi_acc_handle_t acc_hdl, mptsas_pt_request_t *pt,
     10058 +    pMpi2IeeeSgeSimple64_t ieeesgep)
     10059 +{
     10060 +        uint8_t                 sge_flags;
     10061 +        uint32_t                data_size, dataout_size;
     10062 +        ddi_dma_cookie_t        data_cookie;
     10063 +        ddi_dma_cookie_t        dataout_cookie;
     10064 +
     10065 +        data_size = pt->data_size;
     10066 +        dataout_size = pt->dataout_size;
     10067 +        data_cookie = pt->data_cookie;
     10068 +        dataout_cookie = pt->dataout_cookie;
     10069 +
     10070 +        sge_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT |
     10071 +            MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR);
     10072 +        if (dataout_size) {
     10073 +                ddi_put32(acc_hdl, &ieeesgep->Length, dataout_size);
     10074 +                ddi_put32(acc_hdl, &ieeesgep->Address.Low,
     10075 +                    (uint32_t)(dataout_cookie.dmac_laddress &
     10076 +                    0xffffffffull));
     10077 +                ddi_put32(acc_hdl, &ieeesgep->Address.High,
     10078 +                    (uint32_t)(dataout_cookie.dmac_laddress >> 32));
     10079 +                ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
     10080 +                ieeesgep++;
     10081 +        }
     10082 +        sge_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST;
     10083 +        ddi_put32(acc_hdl, &ieeesgep->Length, data_size);
     10084 +        ddi_put32(acc_hdl, &ieeesgep->Address.Low,
     10085 +            (uint32_t)(data_cookie.dmac_laddress & 0xffffffffull));
     10086 +        ddi_put32(acc_hdl, &ieeesgep->Address.High,
     10087 +            (uint32_t)(data_cookie.dmac_laddress >> 32));
     10088 +        ddi_put8(acc_hdl, &ieeesgep->Flags, sge_flags);
     10089 +}
     10090 +
     10091 +static void
9670 10092  mptsas_start_passthru(mptsas_t *mpt, mptsas_cmd_t *cmd)
9671 10093  {
9672 10094          caddr_t                 memp;
9673 10095          pMPI2RequestHeader_t    request_hdrp;
9674 10096          struct scsi_pkt         *pkt = cmd->cmd_pkt;
9675 10097          mptsas_pt_request_t     *pt = pkt->pkt_ha_private;
9676      -        uint32_t                request_size, data_size, dataout_size;
9677      -        uint32_t                direction;
9678      -        ddi_dma_cookie_t        data_cookie;
9679      -        ddi_dma_cookie_t        dataout_cookie;
     10098 +        uint32_t                request_size;
9680 10099          uint32_t                request_desc_low, request_desc_high = 0;
9681      -        uint32_t                i, sense_bufp;
     10100 +        uint64_t                sense_bufp;
9682 10101          uint8_t                 desc_type;
9683 10102          uint8_t                 *request, function;
9684 10103          ddi_dma_handle_t        dma_hdl = mpt->m_dma_req_frame_hdl;
9685 10104          ddi_acc_handle_t        acc_hdl = mpt->m_acc_req_frame_hdl;
9686 10105  
9687 10106          desc_type = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
9688 10107  
9689 10108          request = pt->request;
9690      -        direction = pt->direction;
9691 10109          request_size = pt->request_size;
9692      -        data_size = pt->data_size;
9693      -        dataout_size = pt->dataout_size;
9694      -        data_cookie = pt->data_cookie;
9695      -        dataout_cookie = pt->dataout_cookie;
9696 10110  
9697 10111          /*
9698 10112           * Store the passthrough message in memory location
9699 10113           * corresponding to our slot number
9700 10114           */
9701 10115          memp = mpt->m_req_frame + (mpt->m_req_frame_size * cmd->cmd_slot);
9702 10116          request_hdrp = (pMPI2RequestHeader_t)memp;
9703 10117          bzero(memp, mpt->m_req_frame_size);
9704 10118  
9705      -        for (i = 0; i < request_size; i++) {
9706      -                bcopy(request + i, memp + i, 1);
9707      -        }
     10119 +        bcopy(request, memp, request_size);
9708 10120  
9709      -        if (data_size || dataout_size) {
9710      -                pMpi2SGESimple64_t      sgep;
9711      -                uint32_t                sge_flags;
     10121 +        NDBG15(("mptsas_start_passthru: Func 0x%x, MsgFlags 0x%x, "
     10122 +            "size=%d, in %d, out %d", request_hdrp->Function,
     10123 +            request_hdrp->MsgFlags, request_size,
     10124 +            pt->data_size, pt->dataout_size));
9712 10125  
9713      -                sgep = (pMpi2SGESimple64_t)((uint8_t *)request_hdrp +
9714      -                    request_size);
9715      -                if (dataout_size) {
9716      -
9717      -                        sge_flags = dataout_size |
9718      -                            ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9719      -                            MPI2_SGE_FLAGS_END_OF_BUFFER |
9720      -                            MPI2_SGE_FLAGS_HOST_TO_IOC |
9721      -                            MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9722      -                            MPI2_SGE_FLAGS_SHIFT);
9723      -                        ddi_put32(acc_hdl, &sgep->FlagsLength, sge_flags);
9724      -                        ddi_put32(acc_hdl, &sgep->Address.Low,
9725      -                            (uint32_t)(dataout_cookie.dmac_laddress &
9726      -                            0xffffffffull));
9727      -                        ddi_put32(acc_hdl, &sgep->Address.High,
9728      -                            (uint32_t)(dataout_cookie.dmac_laddress
9729      -                            >> 32));
9730      -                        sgep++;
9731      -                }
9732      -                sge_flags = data_size;
9733      -                sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
9734      -                    MPI2_SGE_FLAGS_LAST_ELEMENT |
9735      -                    MPI2_SGE_FLAGS_END_OF_BUFFER |
9736      -                    MPI2_SGE_FLAGS_END_OF_LIST |
9737      -                    MPI2_SGE_FLAGS_64_BIT_ADDRESSING) <<
9738      -                    MPI2_SGE_FLAGS_SHIFT);
9739      -                if (direction == MPTSAS_PASS_THRU_DIRECTION_WRITE) {
9740      -                        sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_HOST_TO_IOC) <<
9741      -                            MPI2_SGE_FLAGS_SHIFT);
9742      -                } else {
9743      -                        sge_flags |= ((uint32_t)(MPI2_SGE_FLAGS_IOC_TO_HOST) <<
9744      -                            MPI2_SGE_FLAGS_SHIFT);
9745      -                }
9746      -                ddi_put32(acc_hdl, &sgep->FlagsLength,
9747      -                    sge_flags);
9748      -                ddi_put32(acc_hdl, &sgep->Address.Low,
9749      -                    (uint32_t)(data_cookie.dmac_laddress &
9750      -                    0xffffffffull));
9751      -                ddi_put32(acc_hdl, &sgep->Address.High,
9752      -                    (uint32_t)(data_cookie.dmac_laddress >> 32));
     10126 +        /*
     10127 +         * Add an SGE, even if the length is zero.
     10128 +         */
     10129 +        if (mpt->m_MPI25 && pt->simple == 0) {
     10130 +                mptsas_passthru_ieee_sge(acc_hdl, pt,
     10131 +                    (pMpi2IeeeSgeSimple64_t)
     10132 +                    ((uint8_t *)request_hdrp + pt->sgl_offset));
     10133 +        } else {
     10134 +                mptsas_passthru_sge(acc_hdl, pt,
     10135 +                    (pMpi2SGESimple64_t)
     10136 +                    ((uint8_t *)request_hdrp + pt->sgl_offset));
9753 10137          }
9754 10138  
9755 10139          function = request_hdrp->Function;
9756 10140          if ((function == MPI2_FUNCTION_SCSI_IO_REQUEST) ||
9757 10141              (function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
9758 10142                  pMpi2SCSIIORequest_t    scsi_io_req;
9759 10143  
     10144 +                NDBG15(("mptsas_start_passthru: Is SCSI IO Req"));
9760 10145                  scsi_io_req = (pMpi2SCSIIORequest_t)request_hdrp;
9761 10146                  /*
9762 10147                   * Put SGE for data and data_out buffer at the end of
9763 10148                   * scsi_io_request message header.(64 bytes in total)
9764 10149                   * Following above SGEs, the residual space will be
9765 10150                   * used by sense data.
9766 10151                   */
9767 10152                  ddi_put8(acc_hdl,
9768 10153                      &scsi_io_req->SenseBufferLength,
9769 10154                      (uint8_t)(request_size - 64));
9770 10155  
9771      -                sense_bufp = mpt->m_req_frame_dma_addr +
9772      -                    (mpt->m_req_frame_size * cmd->cmd_slot);
     10156 +                sense_bufp = (uint32_t)(mpt->m_req_frame_dma_addr +
     10157 +                    (mpt->m_req_frame_size * cmd->cmd_slot) & 0xffffffffull);
9773 10158                  sense_bufp += 64;
9774 10159                  ddi_put32(acc_hdl,
9775 10160                      &scsi_io_req->SenseBufferLowAddress, sense_bufp);
9776 10161  
9777 10162                  /*
9778 10163                   * Set SGLOffset0 value
9779 10164                   */
9780 10165                  ddi_put8(acc_hdl, &scsi_io_req->SGLOffset0,
9781 10166                      offsetof(MPI2_SCSI_IO_REQUEST, SGL) / 4);
9782 10167  
↓ open down ↓ 17 lines elided ↑ open up ↑
9800 10185          (void) ddi_dma_sync(dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
9801 10186          request_desc_low = (cmd->cmd_slot << 16) + desc_type;
9802 10187          cmd->cmd_rfm = NULL;
9803 10188          MPTSAS_START_CMD(mpt, request_desc_low, request_desc_high);
9804 10189          if ((mptsas_check_dma_handle(dma_hdl) != DDI_SUCCESS) ||
9805 10190              (mptsas_check_acc_handle(acc_hdl) != DDI_SUCCESS)) {
9806 10191                  ddi_fm_service_impact(mpt->m_dip, DDI_SERVICE_UNAFFECTED);
9807 10192          }
9808 10193  }
9809 10194  
     10195 +typedef void (mptsas_pre_f)(mptsas_t *, mptsas_pt_request_t *);
     10196 +static mptsas_pre_f     mpi_pre_ioc_facts;
     10197 +static mptsas_pre_f     mpi_pre_port_facts;
     10198 +static mptsas_pre_f     mpi_pre_fw_download;
     10199 +static mptsas_pre_f     mpi_pre_fw_25_download;
     10200 +static mptsas_pre_f     mpi_pre_fw_upload;
     10201 +static mptsas_pre_f     mpi_pre_fw_25_upload;
     10202 +static mptsas_pre_f     mpi_pre_sata_passthrough;
     10203 +static mptsas_pre_f     mpi_pre_smp_passthrough;
     10204 +static mptsas_pre_f     mpi_pre_config;
     10205 +static mptsas_pre_f     mpi_pre_sas_io_unit_control;
     10206 +static mptsas_pre_f     mpi_pre_scsi_io_req;
9810 10207  
     10208 +/*
     10209 + * Prepare the pt for a SAS2 FW_DOWNLOAD request.
     10210 + */
     10211 +static void
     10212 +mpi_pre_fw_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10213 +{
     10214 +        pMpi2FWDownloadTCSGE_t tcsge;
     10215 +        pMpi2FWDownloadRequest req;
9811 10216  
     10217 +        /*
     10218 +         * If SAS3, call separate function.
     10219 +         */
     10220 +        if (mpt->m_MPI25) {
     10221 +                mpi_pre_fw_25_download(mpt, pt);
     10222 +                return;
     10223 +        }
     10224 +
     10225 +        /*
     10226 +         * User requests should come in with the Transaction
     10227 +         * context element where the SGL will go. Putting the
     10228 +         * SGL after that seems to work, but don't really know
     10229 +         * why. Other drivers tend to create an extra SGL and
     10230 +         * refer to the TCE through that.
     10231 +         */
     10232 +        req = (pMpi2FWDownloadRequest)pt->request;
     10233 +        tcsge = (pMpi2FWDownloadTCSGE_t)&req->SGL;
     10234 +        if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
     10235 +            tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
     10236 +                mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
     10237 +        }
     10238 +
     10239 +        pt->sgl_offset = offsetof(MPI2_FW_DOWNLOAD_REQUEST, SGL) +
     10240 +            sizeof (*tcsge);
     10241 +        if (pt->request_size != pt->sgl_offset)
     10242 +                NDBG15(("mpi_pre_fw_download(): Incorrect req size, "
     10243 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10244 +                    (int)pt->request_size, (int)pt->sgl_offset,
     10245 +                    (int)pt->dataout_size));
     10246 +        if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
     10247 +                NDBG15(("mpi_pre_fw_download(): Incorrect rep size, "
     10248 +                    "0x%x, should be 0x%x", pt->data_size,
     10249 +                    (int)sizeof (MPI2_FW_DOWNLOAD_REPLY)));
     10250 +}
     10251 +
     10252 +/*
     10253 + * Prepare the pt for a SAS3 FW_DOWNLOAD request.
     10254 + */
     10255 +static void
     10256 +mpi_pre_fw_25_download(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10257 +{
     10258 +        pMpi2FWDownloadTCSGE_t tcsge;
     10259 +        pMpi2FWDownloadRequest req2;
     10260 +        pMpi25FWDownloadRequest req25;
     10261 +
     10262 +        /*
     10263 +         * User requests should come in with the Transaction
     10264 +         * context element where the SGL will go. The new firmware
     10265 +         * Doesn't use TCE and has space in the main request for
     10266 +         * this information. So move to the right place.
     10267 +         */
     10268 +        req2 = (pMpi2FWDownloadRequest)pt->request;
     10269 +        req25 = (pMpi25FWDownloadRequest)pt->request;
     10270 +        tcsge = (pMpi2FWDownloadTCSGE_t)&req2->SGL;
     10271 +        if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
     10272 +            tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
     10273 +                mptsas_log(mpt, CE_WARN, "FW Download tce invalid!");
     10274 +        }
     10275 +        req25->ImageOffset = tcsge->ImageOffset;
     10276 +        req25->ImageSize = tcsge->ImageSize;
     10277 +
     10278 +        pt->sgl_offset = offsetof(MPI25_FW_DOWNLOAD_REQUEST, SGL);
     10279 +        if (pt->request_size != pt->sgl_offset)
     10280 +                NDBG15(("mpi_pre_fw_25_download(): Incorrect req size, "
     10281 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10282 +                    pt->request_size, pt->sgl_offset,
     10283 +                    pt->dataout_size));
     10284 +        if (pt->data_size < sizeof (MPI2_FW_DOWNLOAD_REPLY))
     10285 +                NDBG15(("mpi_pre_fw_25_download(): Incorrect rep size, "
     10286 +                    "0x%x, should be 0x%x", pt->data_size,
     10287 +                    (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
     10288 +}
     10289 +
     10290 +/*
     10291 + * Prepare the pt for a SAS2 FW_UPLOAD request.
     10292 + */
     10293 +static void
     10294 +mpi_pre_fw_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10295 +{
     10296 +        pMpi2FWUploadTCSGE_t tcsge;
     10297 +        pMpi2FWUploadRequest_t req;
     10298 +
     10299 +        /*
     10300 +         * If SAS3, call separate function.
     10301 +         */
     10302 +        if (mpt->m_MPI25) {
     10303 +                mpi_pre_fw_25_upload(mpt, pt);
     10304 +                return;
     10305 +        }
     10306 +
     10307 +        /*
     10308 +         * User requests should come in with the Transaction
     10309 +         * context element where the SGL will go. Putting the
     10310 +         * SGL after that seems to work, but don't really know
     10311 +         * why. Other drivers tend to create an extra SGL and
     10312 +         * refer to the TCE through that.
     10313 +         */
     10314 +        req = (pMpi2FWUploadRequest_t)pt->request;
     10315 +        tcsge = (pMpi2FWUploadTCSGE_t)&req->SGL;
     10316 +        if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
     10317 +            tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
     10318 +                mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
     10319 +        }
     10320 +
     10321 +        pt->sgl_offset = offsetof(MPI2_FW_UPLOAD_REQUEST, SGL) +
     10322 +            sizeof (*tcsge);
     10323 +        if (pt->request_size != pt->sgl_offset)
     10324 +                NDBG15(("mpi_pre_fw_upload(): Incorrect req size, "
     10325 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10326 +                    pt->request_size, pt->sgl_offset,
     10327 +                    pt->dataout_size));
     10328 +        if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
     10329 +                NDBG15(("mpi_pre_fw_upload(): Incorrect rep size, "
     10330 +                    "0x%x, should be 0x%x", pt->data_size,
     10331 +                    (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
     10332 +}
     10333 +
     10334 +/*
     10335 + * Prepare the pt a SAS3 FW_UPLOAD request.
     10336 + */
     10337 +static void
     10338 +mpi_pre_fw_25_upload(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10339 +{
     10340 +        pMpi2FWUploadTCSGE_t tcsge;
     10341 +        pMpi2FWUploadRequest_t req2;
     10342 +        pMpi25FWUploadRequest_t req25;
     10343 +
     10344 +        /*
     10345 +         * User requests should come in with the Transaction
     10346 +         * context element where the SGL will go. The new firmware
     10347 +         * Doesn't use TCE and has space in the main request for
     10348 +         * this information. So move to the right place.
     10349 +         */
     10350 +        req2 = (pMpi2FWUploadRequest_t)pt->request;
     10351 +        req25 = (pMpi25FWUploadRequest_t)pt->request;
     10352 +        tcsge = (pMpi2FWUploadTCSGE_t)&req2->SGL;
     10353 +        if (tcsge->ContextSize != 0 || tcsge->DetailsLength != 12 ||
     10354 +            tcsge->Flags != MPI2_SGE_FLAGS_TRANSACTION_ELEMENT) {
     10355 +                mptsas_log(mpt, CE_WARN, "FW Upload tce invalid!");
     10356 +        }
     10357 +        req25->ImageOffset = tcsge->ImageOffset;
     10358 +        req25->ImageSize = tcsge->ImageSize;
     10359 +
     10360 +        pt->sgl_offset = offsetof(MPI25_FW_UPLOAD_REQUEST, SGL);
     10361 +        if (pt->request_size != pt->sgl_offset)
     10362 +                NDBG15(("mpi_pre_fw_25_upload(): Incorrect req size, "
     10363 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10364 +                    pt->request_size, pt->sgl_offset,
     10365 +                    pt->dataout_size));
     10366 +        if (pt->data_size < sizeof (MPI2_FW_UPLOAD_REPLY))
     10367 +                NDBG15(("mpi_pre_fw_25_upload(): Incorrect rep size, "
     10368 +                    "0x%x, should be 0x%x", pt->data_size,
     10369 +                    (int)sizeof (MPI2_FW_UPLOAD_REPLY)));
     10370 +}
     10371 +
     10372 +/*
     10373 + * Prepare the pt for an IOC_FACTS request.
     10374 + */
     10375 +static void
     10376 +mpi_pre_ioc_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10377 +{
     10378 +#ifndef __lock_lint
     10379 +        _NOTE(ARGUNUSED(mpt))
     10380 +#endif
     10381 +        if (pt->request_size != sizeof (MPI2_IOC_FACTS_REQUEST))
     10382 +                NDBG15(("mpi_pre_ioc_facts(): Incorrect req size, "
     10383 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10384 +                    pt->request_size,
     10385 +                    (int)sizeof (MPI2_IOC_FACTS_REQUEST),
     10386 +                    pt->dataout_size));
     10387 +        if (pt->data_size != sizeof (MPI2_IOC_FACTS_REPLY))
     10388 +                NDBG15(("mpi_pre_ioc_facts(): Incorrect rep size, "
     10389 +                    "0x%x, should be 0x%x", pt->data_size,
     10390 +                    (int)sizeof (MPI2_IOC_FACTS_REPLY)));
     10391 +        pt->sgl_offset = (uint16_t)pt->request_size;
     10392 +}
     10393 +
     10394 +/*
     10395 + * Prepare the pt for a PORT_FACTS request.
     10396 + */
     10397 +static void
     10398 +mpi_pre_port_facts(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10399 +{
     10400 +#ifndef __lock_lint
     10401 +        _NOTE(ARGUNUSED(mpt))
     10402 +#endif
     10403 +        if (pt->request_size != sizeof (MPI2_PORT_FACTS_REQUEST))
     10404 +                NDBG15(("mpi_pre_port_facts(): Incorrect req size, "
     10405 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10406 +                    pt->request_size,
     10407 +                    (int)sizeof (MPI2_PORT_FACTS_REQUEST),
     10408 +                    pt->dataout_size));
     10409 +        if (pt->data_size != sizeof (MPI2_PORT_FACTS_REPLY))
     10410 +                NDBG15(("mpi_pre_port_facts(): Incorrect rep size, "
     10411 +                    "0x%x, should be 0x%x", pt->data_size,
     10412 +                    (int)sizeof (MPI2_PORT_FACTS_REPLY)));
     10413 +        pt->sgl_offset = (uint16_t)pt->request_size;
     10414 +}
     10415 +
     10416 +/*
     10417 + * Prepare pt for a SATA_PASSTHROUGH request.
     10418 + */
     10419 +static void
     10420 +mpi_pre_sata_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10421 +{
     10422 +#ifndef __lock_lint
     10423 +        _NOTE(ARGUNUSED(mpt))
     10424 +#endif
     10425 +        pt->sgl_offset = offsetof(MPI2_SATA_PASSTHROUGH_REQUEST, SGL);
     10426 +        if (pt->request_size != pt->sgl_offset)
     10427 +                NDBG15(("mpi_pre_sata_passthrough(): Incorrect req size, "
     10428 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10429 +                    pt->request_size, pt->sgl_offset,
     10430 +                    pt->dataout_size));
     10431 +        if (pt->data_size != sizeof (MPI2_SATA_PASSTHROUGH_REPLY))
     10432 +                NDBG15(("mpi_pre_sata_passthrough(): Incorrect rep size, "
     10433 +                    "0x%x, should be 0x%x", pt->data_size,
     10434 +                    (int)sizeof (MPI2_SATA_PASSTHROUGH_REPLY)));
     10435 +}
     10436 +
     10437 +static void
     10438 +mpi_pre_smp_passthrough(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10439 +{
     10440 +#ifndef __lock_lint
     10441 +        _NOTE(ARGUNUSED(mpt))
     10442 +#endif
     10443 +        pt->sgl_offset = offsetof(MPI2_SMP_PASSTHROUGH_REQUEST, SGL);
     10444 +        if (pt->request_size != pt->sgl_offset)
     10445 +                NDBG15(("mpi_pre_smp_passthrough(): Incorrect req size, "
     10446 +                    "0x%x, should be 0x%x, dataoutsz 0x%x",
     10447 +                    pt->request_size, pt->sgl_offset,
     10448 +                    pt->dataout_size));
     10449 +        if (pt->data_size != sizeof (MPI2_SMP_PASSTHROUGH_REPLY))
     10450 +                NDBG15(("mpi_pre_smp_passthrough(): Incorrect rep size, "
     10451 +                    "0x%x, should be 0x%x", pt->data_size,
     10452 +                    (int)sizeof (MPI2_SMP_PASSTHROUGH_REPLY)));
     10453 +}
     10454 +
     10455 +/*
     10456 + * Prepare pt for a CONFIG request.
     10457 + */
     10458 +static void
     10459 +mpi_pre_config(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10460 +{
     10461 +#ifndef __lock_lint
     10462 +        _NOTE(ARGUNUSED(mpt))
     10463 +#endif
     10464 +        pt->sgl_offset = offsetof(MPI2_CONFIG_REQUEST, PageBufferSGE);
     10465 +        if (pt->request_size != pt->sgl_offset)
     10466 +                NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
     10467 +                    "should be 0x%x, dataoutsz 0x%x", pt->request_size,
     10468 +                    pt->sgl_offset, pt->dataout_size));
     10469 +        if (pt->data_size != sizeof (MPI2_CONFIG_REPLY))
     10470 +                NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
     10471 +                    "should be 0x%x", pt->data_size,
     10472 +                    (int)sizeof (MPI2_CONFIG_REPLY)));
     10473 +        pt->simple = 1;
     10474 +}
     10475 +
     10476 +/*
     10477 + * Prepare pt for a SCSI_IO_REQ request.
     10478 + */
     10479 +static void
     10480 +mpi_pre_scsi_io_req(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10481 +{
     10482 +#ifndef __lock_lint
     10483 +        _NOTE(ARGUNUSED(mpt))
     10484 +#endif
     10485 +        pt->sgl_offset = offsetof(MPI2_SCSI_IO_REQUEST, SGL);
     10486 +        if (pt->request_size != pt->sgl_offset)
     10487 +                NDBG15(("mpi_pre_config(): Incorrect req size, 0x%x, "
     10488 +                    "should be 0x%x, dataoutsz 0x%x", pt->request_size,
     10489 +                    pt->sgl_offset,
     10490 +                    pt->dataout_size));
     10491 +        if (pt->data_size != sizeof (MPI2_SCSI_IO_REPLY))
     10492 +                NDBG15(("mpi_pre_config(): Incorrect rep size, 0x%x, "
     10493 +                    "should be 0x%x", pt->data_size,
     10494 +                    (int)sizeof (MPI2_SCSI_IO_REPLY)));
     10495 +}
     10496 +
     10497 +/*
     10498 + * Prepare the mptsas_cmd for a SAS_IO_UNIT_CONTROL request.
     10499 + */
     10500 +static void
     10501 +mpi_pre_sas_io_unit_control(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10502 +{
     10503 +#ifndef __lock_lint
     10504 +        _NOTE(ARGUNUSED(mpt))
     10505 +#endif
     10506 +        pt->sgl_offset = (uint16_t)pt->request_size;
     10507 +}
     10508 +
     10509 +/*
     10510 + * A set of functions to prepare an mptsas_cmd for the various
     10511 + * supported requests.
     10512 + */
     10513 +static struct mptsas_func {
     10514 +        U8              Function;
     10515 +        char            *Name;
     10516 +        mptsas_pre_f    *f_pre;
     10517 +} mptsas_func_list[] = {
     10518 +        { MPI2_FUNCTION_IOC_FACTS, "IOC_FACTS",         mpi_pre_ioc_facts },
     10519 +        { MPI2_FUNCTION_PORT_FACTS, "PORT_FACTS",       mpi_pre_port_facts },
     10520 +        { MPI2_FUNCTION_FW_DOWNLOAD, "FW_DOWNLOAD",     mpi_pre_fw_download },
     10521 +        { MPI2_FUNCTION_FW_UPLOAD, "FW_UPLOAD",         mpi_pre_fw_upload },
     10522 +        { MPI2_FUNCTION_SATA_PASSTHROUGH, "SATA_PASSTHROUGH",
     10523 +            mpi_pre_sata_passthrough },
     10524 +        { MPI2_FUNCTION_SMP_PASSTHROUGH, "SMP_PASSTHROUGH",
     10525 +            mpi_pre_smp_passthrough},
     10526 +        { MPI2_FUNCTION_SCSI_IO_REQUEST, "SCSI_IO_REQUEST",
     10527 +            mpi_pre_scsi_io_req},
     10528 +        { MPI2_FUNCTION_CONFIG, "CONFIG",               mpi_pre_config},
     10529 +        { MPI2_FUNCTION_SAS_IO_UNIT_CONTROL, "SAS_IO_UNIT_CONTROL",
     10530 +            mpi_pre_sas_io_unit_control },
     10531 +        { 0xFF, NULL,                           NULL } /* list end */
     10532 +};
     10533 +
     10534 +static void
     10535 +mptsas_prep_sgl_offset(mptsas_t *mpt, mptsas_pt_request_t *pt)
     10536 +{
     10537 +        pMPI2RequestHeader_t    hdr;
     10538 +        struct mptsas_func      *f;
     10539 +
     10540 +        hdr = (pMPI2RequestHeader_t)pt->request;
     10541 +
     10542 +        for (f = mptsas_func_list; f->f_pre != NULL; f++) {
     10543 +                if (hdr->Function == f->Function) {
     10544 +                        f->f_pre(mpt, pt);
     10545 +                        NDBG15(("mptsas_prep_sgl_offset: Function %s,"
     10546 +                            " sgl_offset 0x%x", f->Name,
     10547 +                            pt->sgl_offset));
     10548 +                        return;
     10549 +                }
     10550 +        }
     10551 +        NDBG15(("mptsas_prep_sgl_offset: Unknown Function 0x%02x,"
     10552 +            " returning req_size 0x%x for sgl_offset",
     10553 +            hdr->Function, pt->request_size));
     10554 +        pt->sgl_offset = (uint16_t)pt->request_size;
     10555 +}
     10556 +
     10557 +
9812 10558  static int
9813 10559  mptsas_do_passthru(mptsas_t *mpt, uint8_t *request, uint8_t *reply,
9814 10560      uint8_t *data, uint32_t request_size, uint32_t reply_size,
9815      -    uint32_t data_size, uint32_t direction, uint8_t *dataout,
     10561 +    uint32_t data_size, uint8_t direction, uint8_t *dataout,
9816 10562      uint32_t dataout_size, short timeout, int mode)
9817 10563  {
9818 10564          mptsas_pt_request_t             pt;
9819 10565          mptsas_dma_alloc_state_t        data_dma_state;
9820 10566          mptsas_dma_alloc_state_t        dataout_dma_state;
9821 10567          caddr_t                         memp;
9822 10568          mptsas_cmd_t                    *cmd = NULL;
9823 10569          struct scsi_pkt                 *pkt;
9824 10570          uint32_t                        reply_len = 0, sense_len = 0;
9825 10571          pMPI2RequestHeader_t            request_hdrp;
↓ open down ↓ 56 lines elided ↑ open up ↑
9882 10628                                          mutex_enter(&mpt->m_mutex);
9883 10629                                          status = EFAULT;
9884 10630                                          mptsas_log(mpt, CE_WARN, "failed to "
9885 10631                                              "copy read data");
9886 10632                                          goto out;
9887 10633                                  }
9888 10634                          }
9889 10635                          mutex_enter(&mpt->m_mutex);
9890 10636                  }
9891 10637          }
     10638 +        else
     10639 +                bzero(&data_dma_state, sizeof (data_dma_state));
9892 10640  
9893 10641          if (dataout_size != 0) {
9894 10642                  dataout_dma_state.size = dataout_size;
9895 10643                  if (mptsas_dma_alloc(mpt, &dataout_dma_state) != DDI_SUCCESS) {
9896 10644                          status = ENOMEM;
9897 10645                          mptsas_log(mpt, CE_WARN, "failed to alloc DMA "
9898 10646                              "resource");
9899 10647                          goto out;
9900 10648                  }
9901 10649                  pt_flags |= MPTSAS_DATAOUT_ALLOCATED;
↓ open down ↓ 3 lines elided ↑ open up ↑
9905 10653                              dataout_dma_state.memp + i, 1, mode)) {
9906 10654                                  mutex_enter(&mpt->m_mutex);
9907 10655                                  mptsas_log(mpt, CE_WARN, "failed to copy out"
9908 10656                                      " data");
9909 10657                                  status = EFAULT;
9910 10658                                  goto out;
9911 10659                          }
9912 10660                  }
9913 10661                  mutex_enter(&mpt->m_mutex);
9914 10662          }
     10663 +        else
     10664 +                bzero(&dataout_dma_state, sizeof (dataout_dma_state));
9915 10665  
9916 10666          if ((rvalue = (mptsas_request_from_pool(mpt, &cmd, &pkt))) == -1) {
9917 10667                  status = EAGAIN;
9918 10668                  mptsas_log(mpt, CE_NOTE, "event ack command pool is full");
9919 10669                  goto out;
9920 10670          }
9921 10671          pt_flags |= MPTSAS_REQUEST_POOL_CMD;
9922 10672  
9923 10673          bzero((caddr_t)cmd, sizeof (*cmd));
9924 10674          bzero((caddr_t)pkt, scsi_pkt_size());
9925 10675          bzero((caddr_t)&pt, sizeof (pt));
9926 10676  
9927 10677          cmd->ioc_cmd_slot = (uint32_t)(rvalue);
9928 10678  
9929 10679          pt.request = (uint8_t *)request_msg;
9930 10680          pt.direction = direction;
     10681 +        pt.simple = 0;
9931 10682          pt.request_size = request_size;
9932 10683          pt.data_size = data_size;
9933 10684          pt.dataout_size = dataout_size;
9934 10685          pt.data_cookie = data_dma_state.cookie;
9935 10686          pt.dataout_cookie = dataout_dma_state.cookie;
     10687 +        mptsas_prep_sgl_offset(mpt, &pt);
9936 10688  
9937 10689          /*
9938 10690           * Form a blank cmd/pkt to store the acknowledgement message
9939 10691           */
9940 10692          pkt->pkt_cdbp           = (opaque_t)&cmd->cmd_cdb[0];
9941 10693          pkt->pkt_scbp           = (opaque_t)&cmd->cmd_scb;
9942 10694          pkt->pkt_ha_private     = (opaque_t)&pt;
9943 10695          pkt->pkt_flags          = FLAG_HEAD;
9944 10696          pkt->pkt_time           = timeout;
9945 10697          cmd->cmd_pkt            = pkt;
↓ open down ↓ 192 lines elided ↑ open up ↑
10138 10890                          data->DataOutSize = 0;
10139 10891                  }
10140 10892                  /*
10141 10893                   * Send passthru request messages
10142 10894                   */
10143 10895                  return (mptsas_do_passthru(mpt,
10144 10896                      (uint8_t *)((uintptr_t)data->PtrRequest),
10145 10897                      (uint8_t *)((uintptr_t)data->PtrReply),
10146 10898                      (uint8_t *)((uintptr_t)data->PtrData),
10147 10899                      data->RequestSize, data->ReplySize,
10148      -                    data->DataSize, data->DataDirection,
     10900 +                    data->DataSize, (uint8_t)data->DataDirection,
10149 10901                      (uint8_t *)((uintptr_t)data->PtrDataOut),
10150 10902                      data->DataOutSize, data->Timeout, mode));
10151 10903          } else {
10152 10904                  return (EINVAL);
10153 10905          }
10154 10906  }
10155 10907  
10156 10908  static uint8_t
10157 10909  mptsas_get_fw_diag_buffer_number(mptsas_t *mpt, uint32_t unique_id)
10158 10910  {
↓ open down ↓ 1064 lines elided ↑ open up ↑
11223 11975           */
11224 11976          adapter_data->MpiFirmwareVersion = mpt->m_fwversion;
11225 11977  }
11226 11978  
11227 11979  static void
11228 11980  mptsas_read_adapter_data(mptsas_t *mpt, mptsas_adapter_data_t *adapter_data)
11229 11981  {
11230 11982          char    *driver_verstr = MPTSAS_MOD_STRING;
11231 11983  
11232 11984          mptsas_lookup_pci_data(mpt, adapter_data);
11233      -        adapter_data->AdapterType = MPTIOCTL_ADAPTER_TYPE_SAS2;
     11985 +        adapter_data->AdapterType = mpt->m_MPI25 ?
     11986 +            MPTIOCTL_ADAPTER_TYPE_SAS3 :
     11987 +            MPTIOCTL_ADAPTER_TYPE_SAS2;
11234 11988          adapter_data->PCIDeviceHwId = (uint32_t)mpt->m_devid;
11235 11989          adapter_data->PCIDeviceHwRev = (uint32_t)mpt->m_revid;
11236 11990          adapter_data->SubSystemId = (uint32_t)mpt->m_ssid;
11237 11991          adapter_data->SubsystemVendorId = (uint32_t)mpt->m_svid;
11238 11992          (void) strcpy((char *)&adapter_data->DriverVersion[0], driver_verstr);
11239 11993          adapter_data->BiosVersion = 0;
11240 11994          (void) mptsas_get_bios_page3(mpt, &adapter_data->BiosVersion);
11241 11995  }
11242 11996  
11243 11997  static void
↓ open down ↓ 3731 lines elided ↑ open up ↑
14975 15729  
14976 15730          return ((ndi_rtn == NDI_SUCCESS) ? DDI_SUCCESS : DDI_FAILURE);
14977 15731  }
14978 15732  
14979 15733  /* smp transport routine */
14980 15734  static int mptsas_smp_start(struct smp_pkt *smp_pkt)
14981 15735  {
14982 15736          uint64_t                        wwn;
14983 15737          Mpi2SmpPassthroughRequest_t     req;
14984 15738          Mpi2SmpPassthroughReply_t       rep;
14985      -        uint32_t                        direction = 0;
     15739 +        uint8_t                         direction = 0;
14986 15740          mptsas_t                        *mpt;
14987 15741          int                             ret;
14988 15742          uint64_t                        tmp64;
14989 15743  
14990 15744          mpt = (mptsas_t *)smp_pkt->smp_pkt_address->
14991 15745              smp_a_hba_tran->smp_tran_hba_private;
14992 15746  
14993 15747          bcopy(smp_pkt->smp_pkt_address->smp_a_wwn, &wwn, SAS_WWN_BYTE_SIZE);
14994 15748          /*
14995 15749           * Need to compose a SMP request message
↓ open down ↓ 520 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX