xref: /illumos-gate/usr/src/uts/common/io/1394/targets/scsa1394/sbp2_driver.c (revision 8c067cfd3aea0c49a166f9fb38114b56a9160ac6)
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
scsa1394_sbp2_attach(scsa1394_state_t * sp)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
scsa1394_sbp2_detach(scsa1394_state_t * sp)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
scsa1394_sbp2_detect_symbios(scsa1394_state_t * sp)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
bcopy_swap32(uint32_t * from,uint32_t * to,int count)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
scsa1394_sbp2_fake_inquiry(scsa1394_state_t * sp,struct scsi_inquiry * inq)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
scsa1394_sbp2_threads_init(scsa1394_state_t * sp)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
scsa1394_sbp2_threads_fini(scsa1394_state_t * sp)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
scsa1394_sbp2_get_lun_type(scsa1394_lun_t * lp)296 scsa1394_sbp2_get_lun_type(scsa1394_lun_t *lp)
297 {
298 	return (lp->l_lun->l_type);
299 }
300 
301 int
scsa1394_sbp2_login(scsa1394_state_t * sp,int lun)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
scsa1394_sbp2_logout(scsa1394_state_t * sp,int lun,boolean_t phys)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
scsa1394_sbp2_req(scsa1394_state_t * sp,int lun,int req)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
scsa1394_sbp2_req_bus_reset(scsa1394_lun_t * lp)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
scsa1394_sbp2_req_reconnect(scsa1394_lun_t * lp)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
scsa1394_sbp2_disconnect(scsa1394_state_t * sp)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
scsa1394_sbp2_seg2pt(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_seg2pt_default(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_seg2pt_symbios(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_cmd2orb(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_start(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_status_cb(void * arg,sbp2_task_t * task)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
scsa1394_sbp2_nudge(scsa1394_lun_t * lp)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
scsa1394_sbp2_worker_thread(void * arg)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
scsa1394_sbp2_req_status(scsa1394_lun_t * lp)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
scsa1394_sbp2_status_proc(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd,scsa1394_status_t * st)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
scsa1394_sbp2_conv_status(scsa1394_cmd_t * cmd,scsa1394_status_t * st)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
scsa1394_sbp2_reset(scsa1394_lun_t * lp,int level,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_reset_proc(scsa1394_lun_t * lp,int level,scsa1394_cmd_t * cmd)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
scsa1394_sbp2_flush_cmds(scsa1394_lun_t * lp,int reason,int state,int statistics)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
scsa1394_sbp2_logged_in(scsa1394_lun_t * lp)998 scsa1394_sbp2_logged_in(scsa1394_lun_t *lp)
999 {
1000 	return (lp->l_ses != NULL);
1001 }
1002