1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * 1394 mass storage SBP-2 driver routines
  28  */
  29 
  30 #include <sys/param.h>
  31 #include <sys/errno.h>
  32 #include <sys/cred.h>
  33 #include <sys/conf.h>
  34 #include <sys/modctl.h>
  35 #include <sys/stat.h>
  36 #include <sys/ddi.h>
  37 #include <sys/sunddi.h>
  38 
  39 #include <sys/1394/targets/scsa1394/impl.h>
  40 #include <sys/1394/targets/scsa1394/cmd.h>
  41 #include <sys/sbp2/bus.h>
  42 #include <sys/sbp2/driver.h>
  43 
  44 static void     scsa1394_sbp2_detect_symbios(scsa1394_state_t *);
  45 static void     scsa1394_sbp2_worker_thread(void *);
  46 static void     scsa1394_sbp2_status_cb(void *, sbp2_task_t *);
  47 static void     scsa1394_sbp2_seg2pt_default(scsa1394_lun_t *,
  48                 scsa1394_cmd_t *);
  49 static void     scsa1394_sbp2_seg2pt_symbios(scsa1394_lun_t *,
  50                 scsa1394_cmd_t *);
  51 static void     scsa1394_sbp2_req_status(scsa1394_lun_t *);
  52 static void     scsa1394_sbp2_status_proc(scsa1394_lun_t *, scsa1394_cmd_t *,
  53                 scsa1394_status_t *);
  54 static int      scsa1394_sbp2_conv_status(scsa1394_cmd_t *,
  55                 scsa1394_status_t *);
  56 static void     scsa1394_sbp2_reset_proc(scsa1394_lun_t *, int,
  57                 scsa1394_cmd_t *);
  58 static boolean_t scsa1394_sbp2_logged_in(scsa1394_lun_t *);
  59 
  60 extern sbp2_bus_t scsa1394_sbp2_bus;
  61 
  62 /* tunables */
  63 uint_t scsa1394_sbp2_max_payload_sub = 2;
  64 extern int scsa1394_symbios_size_max;
  65 extern int scsa1394_symbios_page_size;
  66 extern int scsa1394_wrka_symbios;
  67 
  68 /* symbios workaround will be applied unless device is on this list */
  69 scsa1394_bw_list_t scsa1394_sbp2_symbios_whitelist[] = {
  70         { SCSA1394_BW_ONE, 0x0a27 },            /* Apple */
  71         { SCSA1394_BW_ONE, 0xd04b }             /* LaCie */
  72 };
  73 
  74 /*
  75  *
  76  * --- SBP-2 routines
  77  *
  78  */
  79 int
  80 scsa1394_sbp2_attach(scsa1394_state_t *sp)
  81 {
  82         sbp2_tgt_t      *tp;
  83         scsa1394_lun_t  *lp;
  84         int             i;
  85 
  86         /*
  87          * target
  88          */
  89         if (sbp2_tgt_init(sp, &scsa1394_sbp2_bus, NLUNS_PER_TARGET,
  90             &sp->s_tgt) != SBP2_SUCCESS) {
  91                 return (DDI_FAILURE);
  92         }
  93         tp = sp->s_tgt;
  94 
  95         /*
  96          * luns
  97          */
  98         sp->s_nluns = tp->t_nluns;
  99         sp->s_lun = kmem_zalloc(sp->s_nluns * sizeof (scsa1394_lun_t),
 100             KM_SLEEP);
 101 
 102         for (i = 0; i < sp->s_nluns; i++) {
 103                 lp = &sp->s_lun[i];
 104 
 105                 mutex_init(&lp->l_mutex, NULL, MUTEX_DRIVER,
 106                     sp->s_attachinfo.iblock_cookie);
 107 
 108                 lp->l_rmb_orig = -1;
 109                 lp->l_lun = &tp->t_lun[i];
 110                 lp->l_sp = sp;
 111                 lp->l_lba_size = DEV_BSIZE;
 112         }
 113 
 114         scsa1394_sbp2_detect_symbios(sp);
 115 
 116         return (DDI_SUCCESS);
 117 }
 118 
 119 void
 120 scsa1394_sbp2_detach(scsa1394_state_t *sp)
 121 {
 122         int             i;
 123         scsa1394_lun_t  *lp;
 124 
 125         for (i = 0; i < sp->s_nluns; i++) {
 126                 lp = &sp->s_lun[i];
 127                 if (lp->l_sp != NULL) {
 128                         mutex_destroy(&lp->l_mutex);
 129                 }
 130         }
 131 
 132         kmem_free(sp->s_lun, sp->s_nluns * sizeof (scsa1394_lun_t));
 133         sbp2_tgt_fini(sp->s_tgt);
 134 }
 135 
 136 static void
 137 scsa1394_sbp2_detect_symbios(scsa1394_state_t *sp)
 138 {
 139         sbp2_cfgrom_ent_t *root = &sp->s_tgt->t_cfgrom.cr_root;
 140         sbp2_cfgrom_ent_t *ent;
 141         scsa1394_bw_list_t *wl;
 142         int     vid;
 143         int     i;
 144 
 145 
 146         if (!scsa1394_wrka_symbios) {
 147                 sp->s_symbios = B_FALSE;
 148                 return;
 149         } else {
 150                 sp->s_symbios = B_TRUE;
 151         }
 152 
 153         /* get device's vendor ID */
 154         if ((ent = sbp2_cfgrom_ent_by_key(root, IEEE1212_IMMEDIATE_TYPE,
 155             IEEE1212_MODULE_VENDOR_ID, 0)) == NULL) {
 156                 return;
 157         }
 158         vid = ent->ce_data.imm;
 159 
 160         /* find a match in the whitelist */
 161         for (i = 0; i < NELEM(scsa1394_sbp2_symbios_whitelist); i++) {
 162                 wl = &scsa1394_sbp2_symbios_whitelist[i];
 163                 if ((wl->vid_match == SCSA1394_BW_ONE) && (wl->vid == vid)) {
 164                         sp->s_symbios = B_FALSE;
 165                         break;
 166                 }
 167         }
 168 }
 169 
 170 
 171 /*
 172  * functional equivalent of ddi_rep_get32() with big endian access handle
 173  */
 174 static void
 175 bcopy_swap32(uint32_t *from, uint32_t *to, int count)
 176 {
 177         int             i;
 178         uint32_t        data;
 179 
 180         ASSERT((uintptr_t)to % 4 == 0);
 181 
 182         for (i = 0; i < count; i++) {
 183                 data = *from++;
 184                 *to++ = SBP2_SWAP32(data);
 185         }
 186 }
 187 
 188 /*
 189  * Build an inquiry for a given device that doesn't like inquiry commands.
 190  */
 191 void
 192 scsa1394_sbp2_fake_inquiry(scsa1394_state_t *sp, struct scsi_inquiry *inq)
 193 {
 194         sbp2_cfgrom_ent_t *r = &sp->s_tgt->t_cfgrom.cr_root;
 195         sbp2_cfgrom_ent_t *e, *eref, *evid;
 196         int     i, len;
 197 
 198         bzero(inq, sizeof (struct scsi_inquiry));
 199 
 200         inq->inq_dtype = DTYPE_DIRECT;
 201         inq->inq_rmb = 1;
 202         inq->inq_ansi = 2;
 203         inq->inq_rdf = RDF_SCSI2;
 204         inq->inq_len = sizeof (struct scsi_inquiry) - 4;
 205 
 206         (void) memset(inq->inq_vid, ' ', sizeof (inq->inq_vid));
 207         (void) memset(inq->inq_pid, ' ', sizeof (inq->inq_pid));
 208         (void) memset(inq->inq_revision, ' ', sizeof (inq->inq_revision));
 209 
 210         /*
 211          * vid/pid/rev can be derived from Config ROM textual descriptors
 212          */
 213         for (i = 0; i < 256; i++) {
 214                 if ((e = sbp2_cfgrom_ent_by_key(r, IEEE1212_LEAF_TYPE,
 215                     IEEE1212_TEXTUAL_DESCRIPTOR, i)) == NULL) {
 216                         break;
 217                 }
 218                 eref = e->ce_ref;
 219                 if ((eref == NULL) || (eref->ce_len < 3) &&
 220                     (eref->ce_kt != IEEE1212_IMMEDIATE_TYPE)) {
 221                         continue;
 222                 }
 223 
 224                 len = e->ce_len - 2;
 225                 if (eref->ce_kv == IEEE1212_MODULE_VENDOR_ID) {
 226                         evid = e;
 227                         bcopy_swap32(&e->ce_data.leaf[2],
 228                             (uint32_t *)inq->inq_vid,
 229                             min(sizeof (inq->inq_vid) / 4, len));
 230                 } else if (eref->ce_kv == 0x17) {
 231                         bcopy_swap32(&e->ce_data.leaf[2],
 232                             (uint32_t *)inq->inq_pid,
 233                             min(sizeof (inq->inq_pid) / 4, len));
 234                 } else if ((eref->ce_kv == IEEE1212_MODULE_HW_VERSION) ||
 235                     (eref == evid)) {
 236                         bcopy_swap32(&e->ce_data.leaf[2],
 237                             (uint32_t *)inq->inq_revision,
 238                             min(sizeof (inq->inq_revision) / 4, len));
 239                 }
 240         }
 241 }
 242 
 243 int
 244 scsa1394_sbp2_threads_init(scsa1394_state_t *sp)
 245 {
 246         scsa1394_lun_t          *lp;
 247         scsa1394_thread_t       *thr;
 248         int                     i;
 249 
 250         for (i = 0; i < sp->s_nluns; i++) {
 251                 lp = &sp->s_lun[i];
 252                 thr = &lp->l_worker_thread;
 253 
 254                 thr->thr_func = scsa1394_sbp2_worker_thread;
 255                 thr->thr_arg = thr;
 256                 thr->thr_state = SCSA1394_THR_INIT;
 257                 cv_init(&thr->thr_cv, NULL, CV_DRIVER, NULL);
 258                 thr->thr_lun = lp;
 259                 thr->thr_req = 0;
 260 
 261                 mutex_enter(&lp->l_mutex);
 262                 if (scsa1394_thr_dispatch(thr) != DDI_SUCCESS) {
 263                         mutex_exit(&lp->l_mutex);
 264                         scsa1394_sbp2_threads_fini(sp);
 265                         return (DDI_FAILURE);
 266                 }
 267                 mutex_exit(&lp->l_mutex);
 268         }
 269 
 270         return (DDI_SUCCESS);
 271 }
 272 
 273 void
 274 scsa1394_sbp2_threads_fini(scsa1394_state_t *sp)
 275 {
 276         scsa1394_lun_t          *lp;
 277         scsa1394_thread_t       *thr;
 278         int                     i;
 279 
 280         for (i = 0; i < sp->s_nluns; i++) {
 281                 lp = &sp->s_lun[i];
 282                 thr = &lp->l_worker_thread;
 283 
 284                 /* if thread wasn't initialized, thr_lun will be NULL */
 285                 if (thr->thr_lun == lp) {
 286                         mutex_enter(&lp->l_mutex);
 287                         scsa1394_thr_cancel(thr);
 288                         mutex_exit(&lp->l_mutex);
 289                         ASSERT(thr->thr_state != SCSA1394_THR_RUN);
 290                         cv_destroy(&thr->thr_cv);
 291                 }
 292         }
 293 }
 294 
 295 int
 296 scsa1394_sbp2_get_lun_type(scsa1394_lun_t *lp)
 297 {
 298         return (lp->l_lun->l_type);
 299 }
 300 
 301 int
 302 scsa1394_sbp2_login(scsa1394_state_t *sp, int lun)
 303 {
 304         scsa1394_lun_t  *lp = &sp->s_lun[lun];
 305         int             berr;
 306 
 307         if (sbp2_lun_login(lp->l_lun, &lp->l_ses,
 308             scsa1394_sbp2_status_cb, lp, &berr) != SBP2_SUCCESS) {
 309                 return (DDI_FAILURE);
 310         }
 311         ASSERT(lp->l_ses != NULL);
 312         return (DDI_SUCCESS);
 313 }
 314 
 315 void
 316 scsa1394_sbp2_logout(scsa1394_state_t *sp, int lun, boolean_t phys)
 317 {
 318         scsa1394_lun_t  *lp = &sp->s_lun[lun];
 319         int             berr;
 320 
 321         if (scsa1394_sbp2_logged_in(lp)) {
 322                 (void) sbp2_lun_logout(lp->l_lun, &lp->l_ses, &berr, phys);
 323         }
 324 }
 325 
 326 void
 327 scsa1394_sbp2_req(scsa1394_state_t *sp, int lun, int req)
 328 {
 329         scsa1394_lun_t  *lp = &sp->s_lun[lun];
 330 
 331         if (lp != NULL) {
 332                 mutex_enter(&lp->l_mutex);
 333                 scsa1394_thr_wake(&lp->l_worker_thread, req);
 334                 mutex_exit(&lp->l_mutex);
 335         }
 336 }
 337 
 338 void
 339 scsa1394_sbp2_req_bus_reset(scsa1394_lun_t *lp)
 340 {
 341         scsa1394_state_t        *sp = lp->l_sp;
 342         int                     berr = 0;
 343 
 344         if (t1394_get_targetinfo(sp->s_t1394_hdl, SCSA1394_BUSGEN(sp), 0,
 345             &sp->s_targetinfo) != DDI_SUCCESS) {
 346                 goto disconnect;
 347         }
 348 
 349         if (sp->s_targetinfo.target_nodeID == T1394_INVALID_NODEID) {
 350                 goto disconnect;
 351         }
 352 
 353         if (!scsa1394_sbp2_logged_in(lp)) {
 354                 /* reconnect procedure is only for logged in hosts */
 355                 return;
 356         }
 357 
 358         /*
 359          * Try SBP-2 RECONNECT procedure first. Note that we're passing
 360          * local Node ID, which might have changed during bus reset.
 361          * sbp2_ses_reconnect() will use it to update the ORBs.
 362          */
 363         if (sbp2_ses_reconnect(lp->l_ses, &berr,
 364             SCSA1394_NODEID(sp)) == SBP2_SUCCESS) {
 365                 mutex_enter(&sp->s_mutex);
 366                 sp->s_dev_state = SCSA1394_DEV_ONLINE;
 367                 mutex_exit(&sp->s_mutex);
 368 
 369                 /* resume task processing */
 370                 scsa1394_sbp2_nudge(lp);
 371 
 372                 return;
 373         }
 374 
 375         if (berr == CMD1394_EDEVICE_REMOVED) {
 376                 goto disconnect;
 377         }
 378 
 379         /* reconnect failed, try to logout and login again */
 380         scsa1394_sbp2_flush_cmds(lp, CMD_TRAN_ERR, 0, STAT_BUS_RESET);
 381         (void) sbp2_lun_logout(lp->l_lun, &lp->l_ses, &berr, B_FALSE);
 382 
 383         if (scsa1394_sbp2_login(sp, 0) != SBP2_SUCCESS) {
 384                 goto disconnect;
 385         }
 386 
 387         mutex_enter(&sp->s_mutex);
 388         sp->s_dev_state = SCSA1394_DEV_ONLINE;
 389         mutex_exit(&sp->s_mutex);
 390 
 391         return;
 392 
 393 disconnect:
 394         mutex_enter(&sp->s_mutex);
 395         sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
 396         mutex_exit(&sp->s_mutex);
 397         if (scsa1394_sbp2_logged_in(lp)) {
 398                 scsa1394_sbp2_flush_cmds(lp, CMD_DEV_GONE, 0, STAT_BUS_RESET);
 399                 (void) sbp2_lun_logout(lp->l_lun, &lp->l_ses, &berr, B_FALSE);
 400         }
 401 }
 402 
 403 /*ARGSUSED*/
 404 void
 405 scsa1394_sbp2_req_reconnect(scsa1394_lun_t *lp)
 406 {
 407         scsa1394_state_t        *sp = lp->l_sp;
 408 
 409         if (t1394_get_targetinfo(sp->s_t1394_hdl, SCSA1394_BUSGEN(sp), 0,
 410             &sp->s_targetinfo) != DDI_SUCCESS) {
 411                 return;
 412         }
 413 
 414         mutex_enter(&sp->s_mutex);
 415         sp->s_dev_state = SCSA1394_DEV_ONLINE;
 416         mutex_exit(&sp->s_mutex);
 417 
 418         if (sbp2_tgt_reconnect(sp->s_tgt) != SBP2_SUCCESS) {
 419                 goto disconnect;
 420         }
 421 
 422         if (scsa1394_sbp2_login(sp, 0) != SBP2_SUCCESS) {
 423                 goto disconnect;
 424         }
 425 
 426         cmn_err(CE_WARN, "scsa1394(%d): "
 427             "Reinserted device is accessible again.\n", sp->s_instance);
 428 
 429         return;
 430 
 431 disconnect:
 432         mutex_enter(&sp->s_mutex);
 433         sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
 434         mutex_exit(&sp->s_mutex);
 435 }
 436 
 437 void
 438 scsa1394_sbp2_disconnect(scsa1394_state_t *sp)
 439 {
 440         scsa1394_lun_t  *lp = &sp->s_lun[0];
 441         int             berr;
 442 
 443         scsa1394_sbp2_flush_cmds(lp, CMD_DEV_GONE, 0, STAT_BUS_RESET);
 444         if (scsa1394_sbp2_logged_in(lp)) {
 445                 (void) sbp2_lun_logout(lp->l_lun, &lp->l_ses, &berr, B_FALSE);
 446         }
 447         sbp2_tgt_disconnect(sp->s_tgt);
 448 }
 449 
 450 /*
 451  * convert segment array into DMA-mapped SBP-2 page table
 452  */
 453 void
 454 scsa1394_sbp2_seg2pt(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 455 {
 456         scsa1394_state_t        *sp = lp->l_sp;
 457 
 458         ASSERT(cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID);
 459 
 460         if (sp->s_symbios) {
 461                 scsa1394_sbp2_seg2pt_symbios(lp, cmd);
 462         } else {
 463                 scsa1394_sbp2_seg2pt_default(lp, cmd);
 464         }
 465 }
 466 
 467 /*ARGSUSED*/
 468 static void
 469 scsa1394_sbp2_seg2pt_default(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 470 {
 471         sbp2_pt_unrestricted_t *pt;
 472         scsa1394_cmd_seg_t *seg;
 473         int             i;
 474 
 475         pt = (sbp2_pt_unrestricted_t *)cmd->sc_pt_kaddr;
 476         seg = &cmd->sc_buf_seg[0];
 477         for (i = 0; i < cmd->sc_buf_nsegs; i++) {
 478                 pt->pt_seg_len = SBP2_SWAP16(seg->ss_len);
 479                 pt->pt_seg_base_hi = SBP2_SWAP16(seg->ss_baddr >> 32);
 480                 pt->pt_seg_base_lo = SBP2_SWAP32(seg->ss_baddr & 0xFFFFFFFF);
 481 
 482                 pt++;
 483                 seg++;
 484         }
 485         (void) ddi_dma_sync(cmd->sc_pt_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
 486 
 487         cmd->sc_pt_cmd_size = cmd->sc_buf_nsegs;
 488 }
 489 
 490 /*
 491  * fill page table for Symbios workaround
 492  */
 493 /*ARGSUSED*/
 494 static void
 495 scsa1394_sbp2_seg2pt_symbios(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 496 {
 497         sbp2_pt_unrestricted_t *pt;
 498         scsa1394_cmd_seg_t *seg;
 499         int             nsegs;
 500         size_t          resid, skiplen, dataoff, segoff, seglen;
 501         uint64_t        baddr;
 502 
 503         /* data offset within command */
 504         if (cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP) {
 505                 dataoff = (cmd->sc_total_blks - cmd->sc_resid_blks) *
 506                     cmd->sc_blk_size;
 507         } else {
 508                 dataoff = 0;
 509         }
 510 
 511         /* skip dataoff bytes */
 512         seg = &cmd->sc_buf_seg[0];
 513         skiplen = 0;
 514         while (skiplen + seg->ss_len <= dataoff) {
 515                 skiplen += seg->ss_len;
 516                 seg++;
 517         }
 518         segoff = dataoff - skiplen; /* offset within segment */
 519 
 520         pt = (sbp2_pt_unrestricted_t *)cmd->sc_pt_kaddr;
 521         resid = cmd->sc_xfer_bytes;
 522         nsegs = 0;
 523         while (resid > 0) {
 524                 ASSERT(seg->ss_len <= scsa1394_symbios_page_size);
 525 
 526                 seglen = min(seg->ss_len, resid) - segoff;
 527                 baddr = seg->ss_baddr + segoff;
 528 
 529                 pt->pt_seg_len = SBP2_SWAP16(seglen);
 530                 pt->pt_seg_base_hi = SBP2_SWAP16(baddr >> 32);
 531                 pt->pt_seg_base_lo = SBP2_SWAP32(baddr & 0xFFFFFFFF);
 532 
 533                 segoff = 0;
 534                 resid -= seglen;
 535                 nsegs++;
 536                 pt++;
 537                 seg++;
 538         }
 539         (void) ddi_dma_sync(cmd->sc_pt_dma_hdl, 0, 0, DDI_DMA_SYNC_FORDEV);
 540 
 541         cmd->sc_pt_cmd_size = nsegs;
 542 }
 543 
 544 /*
 545  * convert command into DMA-mapped SBP-2 ORB
 546  */
 547 void
 548 scsa1394_sbp2_cmd2orb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 549 {
 550         scsa1394_state_t *sp = lp->l_sp;
 551         scsa1394_cmd_orb_t *orb = sbp2_task_orb_kaddr(&cmd->sc_task);
 552 
 553         mutex_enter(&lp->l_mutex);
 554 
 555         lp->l_stat.stat_cmd_cnt++;
 556 
 557         bzero(orb->co_cdb, sizeof (orb->co_cdb));
 558 
 559         /* CDB */
 560         bcopy(cmd->sc_cdb, orb->co_cdb, cmd->sc_cdb_actual_len);
 561 
 562         /*
 563          * ORB parameters
 564          *
 565          * use max speed and max payload for this speed.
 566          * max async data transfer for a given speed is 512<<speed
 567          * SBP-2 defines (see 5.1.2) max data transfer as 2^(max_payload+2),
 568          * hence max_payload = 7 + speed
 569          */
 570         orb->co_params = SBP2_ORB_NOTIFY | SBP2_ORB_RQ_FMT_SBP2 |
 571             (sp->s_targetinfo.current_max_speed << SBP2_ORB_CMD_SPD_SHIFT) |
 572             ((7 + sp->s_targetinfo.current_max_speed -
 573             scsa1394_sbp2_max_payload_sub) << SBP2_ORB_CMD_MAX_PAYLOAD_SHIFT);
 574 
 575         /* direction: initiator's read is target's write (and vice versa) */
 576         if (cmd->sc_flags & SCSA1394_CMD_READ) {
 577                 orb->co_params |= SBP2_ORB_CMD_DIR;
 578         }
 579 
 580         /*
 581          * data_size and data_descriptor
 582          */
 583         if (cmd->sc_buf_nsegs == 0) {
 584                 /* no data */
 585                 orb->co_data_size = 0;
 586                 SCSA1394_ADDR_SET(sp, orb->co_data_descr, 0);
 587         } else if (cmd->sc_buf_nsegs == 1) {
 588                 /* contiguous buffer - use direct addressing */
 589                 ASSERT(cmd->sc_buf_seg[0].ss_len != 0);
 590                 orb->co_data_size = SBP2_SWAP16(cmd->sc_buf_seg[0].ss_len);
 591                 SCSA1394_ADDR_SET(sp, orb->co_data_descr,
 592                     cmd->sc_buf_seg[0].ss_baddr);
 593         } else {
 594                 /* non-contiguous s/g list - page table */
 595                 ASSERT(cmd->sc_pt_cmd_size > 0);
 596                 orb->co_params |= SBP2_ORB_CMD_PT;
 597                 orb->co_data_size = SBP2_SWAP16(cmd->sc_pt_cmd_size);
 598                 SCSA1394_ADDR_SET(sp, orb->co_data_descr, cmd->sc_pt_baddr);
 599         }
 600 
 601         SBP2_SWAP16_1(orb->co_params);
 602 
 603         SBP2_ORBP_SET(orb->co_next_orb, SBP2_ORBP_NULL);
 604 
 605         mutex_exit(&lp->l_mutex);
 606 
 607         sbp2_task_orb_sync(lp->l_lun, &cmd->sc_task, DDI_DMA_SYNC_FORDEV);
 608 }
 609 
 610 
 611 /*ARGSUSED*/
 612 int
 613 scsa1394_sbp2_start(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
 614 {
 615         sbp2_task_t     *task = CMD2TASK(cmd);
 616         int             ret;
 617 
 618         ASSERT(lp->l_ses != NULL);
 619 
 620         task->ts_timeout = cmd->sc_timeout;
 621         task->ts_error = SBP2_TASK_ERR_NONE;
 622         task->ts_bus_error = 0;
 623         task->ts_state = SBP2_TASK_INIT;
 624 
 625         ret = sbp2_ses_submit_task(lp->l_ses, task);
 626 
 627         if ((ret == SBP2_SUCCESS) || (ret == SBP2_ECONTEXT)) {
 628                 return (TRAN_ACCEPT);
 629         } if (task->ts_error == SBP2_TASK_ERR_BUS) {
 630                 if (task->ts_bus_error == CMD1394_EDEVICE_BUSY) {
 631                         return (TRAN_BUSY);
 632                 } else {
 633                         return (TRAN_FATAL_ERROR);
 634                 }
 635         } else {
 636                 return (TRAN_FATAL_ERROR);
 637         }
 638 }
 639 
 640 /*
 641  * This function is called by SBP-2 layer when task status is received,
 642  * typically from interrupt handler. Just wake the thread to do the actual work.
 643  */
 644 /*ARGSUSED*/
 645 static void
 646 scsa1394_sbp2_status_cb(void *arg, sbp2_task_t *task)
 647 {
 648         scsa1394_lun_t          *lp = (scsa1394_lun_t *)arg;
 649 
 650         mutex_enter(&lp->l_mutex);
 651         scsa1394_thr_wake(&lp->l_worker_thread, SCSA1394_THREQ_TASK_STATUS);
 652         mutex_exit(&lp->l_mutex);
 653 }
 654 
 655 void
 656 scsa1394_sbp2_nudge(scsa1394_lun_t *lp)
 657 {
 658         mutex_enter(&lp->l_mutex);
 659         scsa1394_thr_wake(&lp->l_worker_thread, SCSA1394_THREQ_NUDGE);
 660         mutex_exit(&lp->l_mutex);
 661 }
 662 
 663 /*
 664  * worker thread
 665  */
 666 static void
 667 scsa1394_sbp2_worker_thread(void *arg)
 668 {
 669         scsa1394_thread_t       *thr = (scsa1394_thread_t *)arg;
 670         scsa1394_lun_t          *lp = thr->thr_lun;
 671 
 672         mutex_enter(&lp->l_mutex);
 673         for (;;) {
 674                 while (thr->thr_req == 0) {
 675                         cv_wait(&thr->thr_cv, &lp->l_mutex);
 676                 }
 677                 if (thr->thr_req & SCSA1394_THREQ_EXIT) {
 678                         break;
 679                 }
 680                 if (thr->thr_req & SCSA1394_THREQ_BUS_RESET) {
 681                         thr->thr_req &= ~SCSA1394_THREQ_BUS_RESET;
 682                         mutex_exit(&lp->l_mutex);
 683                         scsa1394_sbp2_req_bus_reset(lp);
 684                         mutex_enter(&lp->l_mutex);
 685                         continue;
 686                 }
 687                 if (thr->thr_req & SCSA1394_THREQ_RECONNECT) {
 688                         thr->thr_req &= ~SCSA1394_THREQ_RECONNECT;
 689                         mutex_exit(&lp->l_mutex);
 690                         scsa1394_sbp2_req_reconnect(lp);
 691                         mutex_enter(&lp->l_mutex);
 692                         continue;
 693                 }
 694                 if (thr->thr_req & SCSA1394_THREQ_TASK_STATUS) {
 695                         thr->thr_req &= ~SCSA1394_THREQ_TASK_STATUS;
 696                         mutex_exit(&lp->l_mutex);
 697                         scsa1394_sbp2_req_status(lp);
 698                         mutex_enter(&lp->l_mutex);
 699                         continue;
 700                 }
 701                 if (thr->thr_req & SCSA1394_THREQ_NUDGE) {
 702                         thr->thr_req &= ~SCSA1394_THREQ_NUDGE;
 703                         mutex_exit(&lp->l_mutex);
 704                         if (scsa1394_sbp2_logged_in(lp)) {
 705                                 sbp2_ses_nudge(lp->l_ses);
 706                         }
 707                         mutex_enter(&lp->l_mutex);
 708                         continue;
 709                 }
 710         }
 711         thr->thr_state = SCSA1394_THR_EXIT;
 712         cv_signal(&thr->thr_cv);
 713         mutex_exit(&lp->l_mutex);
 714 }
 715 
 716 /*
 717  * task status handler
 718  */
 719 static void
 720 scsa1394_sbp2_req_status(scsa1394_lun_t *lp)
 721 {
 722         sbp2_ses_t              *sp = lp->l_ses;
 723         sbp2_task_t             *task;
 724 
 725         if (sp == NULL) {
 726                 return;
 727         }
 728 
 729         /*
 730          * Process all tasks that received status.
 731          * This algorithm preserves callback order.
 732          */
 733         while ((task = sbp2_ses_remove_first_task_state(sp, SBP2_TASK_COMP)) !=
 734             NULL) {
 735                 sbp2_ses_nudge(sp);
 736 
 737                 ASSERT(task->ts_state == SBP2_TASK_COMP);
 738                 task->ts_state = SBP2_TASK_PROC;
 739                 scsa1394_sbp2_status_proc(lp, TASK2CMD(task),
 740                     (scsa1394_status_t *)&task->ts_status);
 741         }
 742         sbp2_ses_nudge(sp);     /* submit next task */
 743 }
 744 
 745 static void
 746 scsa1394_sbp2_status_proc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd,
 747     scsa1394_status_t *st)
 748 {
 749         sbp2_task_t             *task = CMD2TASK(cmd);
 750         struct scsi_pkt         *pkt = CMD2PKT(cmd);
 751         uint64_t                *p;
 752 
 753         if (cmd->sc_flags & SCSA1394_CMD_READ) {
 754                 (void) ddi_dma_sync(cmd->sc_buf_dma_hdl, 0, 0,
 755                     DDI_DMA_SYNC_FORKERNEL);
 756         }
 757 
 758         if (task->ts_error != SBP2_TASK_ERR_NONE) {
 759                 pkt->pkt_state |= STATE_GOT_BUS;
 760                 switch (task->ts_error) {
 761                 case SBP2_TASK_ERR_ABORT:
 762                         pkt->pkt_state |= STATE_GOT_TARGET;
 763                         pkt->pkt_reason = CMD_ABORTED;
 764                         break;
 765                 case SBP2_TASK_ERR_LUN_RESET:
 766                         pkt->pkt_state |= STATE_GOT_TARGET;
 767                         pkt->pkt_reason = CMD_RESET;
 768                         pkt->pkt_statistics |= STAT_DEV_RESET;
 769                         break;
 770                 case SBP2_TASK_ERR_TGT_RESET:
 771                         pkt->pkt_state |= STATE_GOT_TARGET;
 772                         pkt->pkt_reason = CMD_RESET;
 773                         pkt->pkt_statistics |= STAT_DEV_RESET;
 774                         break;
 775                 case SBP2_TASK_ERR_TIMEOUT:
 776                         (void) scsa1394_sbp2_reset(lp, RESET_TARGET, cmd);
 777                         return;
 778                 case SBP2_TASK_ERR_DEAD:
 779                 case SBP2_TASK_ERR_BUS:
 780                 default:
 781                         pkt->pkt_reason = CMD_TRAN_ERR;
 782                         break;
 783                 }
 784         } else if ((st->st_param & SBP2_ST_RESP) == SBP2_ST_RESP_COMPLETE) {
 785                 /*
 786                  * SBP-2 status block has been received, now look at sbp_status.
 787                  *
 788                  * Note: ANSI NCITS 325-1998 B.2 requires that when status is
 789                  * GOOD, length must be one, but some devices do not comply
 790                  */
 791                 if (st->st_sbp_status == SBP2_ST_SBP_DUMMY_ORB) {
 792                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
 793                         pkt->pkt_reason = CMD_ABORTED;
 794                         pkt->pkt_statistics |= STAT_DEV_RESET;
 795                 } else if ((st->st_status & SCSA1394_ST_STATUS) ==
 796                     STATUS_GOOD) {
 797                         /* request complete */
 798                         *(pkt->pkt_scbp) = STATUS_GOOD;
 799                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
 800                             STATE_SENT_CMD | STATE_XFERRED_DATA |
 801                             STATE_GOT_STATUS);
 802                         pkt->pkt_reason = CMD_CMPLT;
 803                 } else if (scsa1394_sbp2_conv_status(cmd, st) == DDI_SUCCESS) {
 804                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
 805                             STATE_SENT_CMD | STATE_XFERRED_DATA |
 806                             STATE_GOT_STATUS | STATE_ARQ_DONE);
 807                         pkt->pkt_reason = CMD_TRAN_ERR;
 808                 } else {
 809                         pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET |
 810                             STATE_SENT_CMD | STATE_XFERRED_DATA |
 811                             STATE_GOT_STATUS);
 812                         pkt->pkt_reason = CMD_TRAN_ERR;
 813                         lp->l_stat.stat_err_status_conv++;
 814                 }
 815         } else {
 816                 /* transport or serial bus failure */
 817                 pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET);
 818                 pkt->pkt_reason = CMD_TRAN_ERR;
 819                 lp->l_stat.stat_err_status_resp++;
 820         }
 821 
 822         if (pkt->pkt_reason == CMD_TRAN_ERR) {
 823                 lp->l_stat.stat_err_status_tran_err++;
 824 
 825                 /* save the command */
 826                 p = &lp->l_stat.stat_cmd_last_fail[
 827                     lp->l_stat.stat_cmd_last_fail_idx][0];
 828                 bcopy(&pkt->pkt_cdbp[0], p, min(cmd->sc_cdb_len, 16));
 829                 *(clock_t *)&p[2] = ddi_get_lbolt();
 830                 lp->l_stat.stat_cmd_last_fail_idx =
 831                     (lp->l_stat.stat_cmd_last_fail_idx + 1) %
 832                     SCSA1394_STAT_NCMD_LAST;
 833         }
 834 
 835         /* generic HBA status processing */
 836         scsa1394_cmd_status_proc(lp, cmd);
 837 }
 838 
 839 
 840 /*
 841  * Convert SBP-2 status block into SCSA status.
 842  *
 843  * Note: (ref: B.2) "SBP-2 permits the return of a status block between two
 844  *      and quadlets in length. When a truncated status block is stored, the
 845  *      omitted quadlets shall be interpreted as if zero values were stored."
 846  *      We expect the sbp2 layer to do the zeroing for us.
 847  */
 848 static int
 849 scsa1394_sbp2_conv_status(scsa1394_cmd_t *cmd, scsa1394_status_t *st)
 850 {
 851         struct scsi_pkt *pkt = CMD2PKT(cmd);
 852         uint8_t         status = st->st_status;
 853         uint8_t         bits = st->st_sense_bits;
 854         struct scsi_arq_status *arqp = (struct scsi_arq_status *)pkt->pkt_scbp;
 855         struct scsi_extended_sense *esp = &arqp->sts_sensedata;
 856 
 857         *(pkt->pkt_scbp) = (status & SCSA1394_ST_STATUS);
 858         *(uint8_t *)&arqp->sts_rqpkt_status = STATUS_GOOD;
 859         arqp->sts_rqpkt_reason = CMD_CMPLT;
 860         arqp->sts_rqpkt_resid = 0;
 861         arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
 862         arqp->sts_rqpkt_statistics = 0;
 863 
 864         esp->es_valid = (bits & SCSA1394_ST_VALID) >> SCSA1394_ST_VALID_SHIFT;
 865         esp->es_class = CLASS_EXTENDED_SENSE;
 866         esp->es_code = (status & SCSA1394_ST_SFMT) >> SCSA1394_ST_SFMT_SHIFT;
 867 
 868         esp->es_segnum = 0;
 869 
 870         esp->es_filmk = (bits & SCSA1394_ST_MARK) >> SCSA1394_ST_MARK_SHIFT;
 871         esp->es_eom = (bits & SCSA1394_ST_EOM) >> SCSA1394_ST_EOM_SHIFT;
 872         esp->es_ili = (bits & SCSA1394_ST_ILI) >> SCSA1394_ST_ILI_SHIFT;
 873         esp->es_key = (bits & SCSA1394_ST_SENSE_KEY);
 874 
 875         esp->es_info_1 = st->st_info[0];
 876         esp->es_info_2 = st->st_info[1];
 877         esp->es_info_3 = st->st_info[2];
 878         esp->es_info_4 = st->st_info[3];
 879         esp->es_add_len = 4;
 880 
 881         esp->es_cmd_info[0] = st->st_cdb[0];
 882         esp->es_cmd_info[1] = st->st_cdb[1];
 883         esp->es_cmd_info[2] = st->st_cdb[2];
 884         esp->es_cmd_info[3] = st->st_cdb[3];
 885         esp->es_add_code = st->st_sense_code;
 886         esp->es_qual_code = st->st_sense_qual;
 887         esp->es_fru_code = st->st_fru;
 888         esp->es_skey_specific[0] = st->st_sks[0];
 889         esp->es_skey_specific[1] = st->st_sks[1];
 890         esp->es_skey_specific[2] = st->st_sks[2];
 891 
 892         esp->es_add_info[0] = esp->es_add_info[1] = 0;
 893 
 894         return (DDI_SUCCESS);
 895 }
 896 
 897 /*
 898  * Sends appropriate reset command to the target. LUN reset is optional, so it
 899  * can fail, in which case the SCSA target driver will use RESET_TARGET/ALL.
 900  * Target reset support is mandatory in SBP-2, if it fails, it means something's
 901  * terribly wrong with the device - blow away outstanding tasks in that case.
 902  */
 903 int
 904 scsa1394_sbp2_reset(scsa1394_lun_t *lp, int level, scsa1394_cmd_t *cmd)
 905 {
 906         scsa1394_state_t        *sp = lp->l_sp;
 907         sbp2_task_t             *task;
 908         int                     berr;
 909         int                     ret = DDI_FAILURE;
 910 
 911         if (scsa1394_dev_is_online(sp)) {
 912                 switch (level) {
 913                 case RESET_LUN:
 914                         ret = sbp2_lun_reset(lp->l_lun, &berr);
 915                         if (ret != SBP2_SUCCESS) {
 916                                 return (ret);
 917                         }
 918                         break;
 919                 case RESET_TARGET:
 920                 case RESET_ALL:
 921                         ret = sbp2_tgt_reset(sp->s_tgt, &berr);
 922                         break;
 923                 }
 924         }
 925 
 926         if (cmd != NULL) {
 927                 scsa1394_sbp2_reset_proc(lp, level, cmd);
 928         }
 929         if (scsa1394_sbp2_logged_in(lp)) {
 930                 while ((task = sbp2_ses_cancel_first_task(lp->l_ses)) != NULL) {
 931                         ASSERT(task->ts_state < SBP2_TASK_PROC);
 932                         scsa1394_sbp2_reset_proc(lp, level, TASK2CMD(task));
 933                 }
 934         }
 935 
 936         return (ret);
 937 }
 938 
 939 static void
 940 scsa1394_sbp2_reset_proc(scsa1394_lun_t *lp, int level, scsa1394_cmd_t *cmd)
 941 {
 942         sbp2_task_t             *task = CMD2TASK(cmd);
 943         struct scsi_pkt         *pkt = CMD2PKT(cmd);
 944         int                     ts_error;
 945 
 946         pkt->pkt_reason = CMD_RESET;
 947         if (level == RESET_LUN) {
 948                 if (task->ts_state == SBP2_TASK_PEND) {
 949                         pkt->pkt_statistics |= STAT_DEV_RESET;
 950                 } else {
 951                         pkt->pkt_statistics |= STAT_ABORTED;
 952                 }
 953                 ts_error = SBP2_TASK_ERR_LUN_RESET;
 954         } else {
 955                 pkt->pkt_statistics |= STAT_BUS_RESET;
 956                 ts_error = SBP2_TASK_ERR_TGT_RESET;
 957         }
 958         task->ts_error = ts_error;
 959         task->ts_state = SBP2_TASK_PROC;
 960         scsa1394_cmd_status_proc(lp, cmd);
 961 }
 962 
 963 /*
 964  * Cancel commands immediately.
 965  *
 966  * Caller's responsibility to set device state such that no new tasks are added.
 967  */
 968 void
 969 scsa1394_sbp2_flush_cmds(scsa1394_lun_t *lp, int reason, int state,
 970     int statistics)
 971 {
 972         scsa1394_cmd_t  *cmd;
 973         struct scsi_pkt *pkt;
 974         sbp2_ses_t      *sp = lp->l_ses;
 975         sbp2_task_t     *task;
 976 
 977         if (sp == NULL) {
 978                 return;
 979         }
 980 
 981         while ((task = sbp2_ses_cancel_first_task(sp)) != NULL) {
 982                 ASSERT(task->ts_state < SBP2_TASK_PROC);
 983                 cmd = TASK2CMD(task);
 984                 pkt = CMD2PKT(cmd);
 985 
 986                 pkt->pkt_reason = reason;
 987                 pkt->pkt_state |= state;
 988                 pkt->pkt_statistics |= statistics;
 989                 task->ts_state = SBP2_TASK_PROC;
 990                 scsa1394_cmd_status_proc(lp, cmd);
 991         }
 992 
 993         scsa1394_thr_clear_req(&lp->l_worker_thread,
 994             SCSA1394_THREQ_TASK_STATUS | SCSA1394_THREQ_NUDGE);
 995 }
 996 
 997 static boolean_t
 998 scsa1394_sbp2_logged_in(scsa1394_lun_t *lp)
 999 {
1000         return (lp->l_ses != NULL);
1001 }