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