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  * Copyright 2023 Oxide Computer Company
28  */
29 
30 /*
31  * 1394 mass storage HBA driver
32  */
33 
34 #include <sys/param.h>
35 #include <sys/errno.h>
36 #include <sys/cred.h>
37 #include <sys/conf.h>
38 #include <sys/modctl.h>
39 #include <sys/stat.h>
40 #include <sys/byteorder.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 
44 #include <sys/1394/targets/scsa1394/impl.h>
45 #include <sys/1394/targets/scsa1394/cmd.h>
46 
47 /* DDI/DKI entry points */
48 static int	scsa1394_attach(dev_info_t *, ddi_attach_cmd_t);
49 static int	scsa1394_detach(dev_info_t *, ddi_detach_cmd_t);
50 static int	scsa1394_power(dev_info_t *, int, int);
51 static int	scsa1394_cpr_suspend(dev_info_t *);
52 static void	scsa1394_cpr_resume(dev_info_t *);
53 
54 /* configuration routines */
55 static void	scsa1394_cleanup(scsa1394_state_t *, int);
56 static int	scsa1394_attach_1394(scsa1394_state_t *);
57 static void	scsa1394_detach_1394(scsa1394_state_t *);
58 static int	scsa1394_attach_threads(scsa1394_state_t *);
59 static void	scsa1394_detach_threads(scsa1394_state_t *);
60 static int	scsa1394_attach_scsa(scsa1394_state_t *);
61 static void	scsa1394_detach_scsa(scsa1394_state_t *);
62 static int	scsa1394_create_cmd_cache(scsa1394_state_t *);
63 static void	scsa1394_destroy_cmd_cache(scsa1394_state_t *);
64 static int	scsa1394_add_events(scsa1394_state_t *);
65 static void	scsa1394_remove_events(scsa1394_state_t *);
66 
67 /* device configuration */
68 static int	scsa1394_scsi_bus_config(dev_info_t *, uint_t,
69 		ddi_bus_config_op_t, void *, dev_info_t **);
70 static int	scsa1394_scsi_bus_unconfig(dev_info_t *, uint_t,
71 		ddi_bus_config_op_t, void *);
72 static void	scsa1394_create_children(scsa1394_state_t *);
73 static void	scsa1394_bus_reset(dev_info_t *, ddi_eventcookie_t, void *,
74 		void *);
75 static void	scsa1394_disconnect(dev_info_t *, ddi_eventcookie_t, void *,
76 		void *);
77 static void	scsa1394_reconnect(dev_info_t *, ddi_eventcookie_t, void *,
78 		void *);
79 
80 /* SCSA HBA entry points */
81 static int	scsa1394_scsi_tgt_init(dev_info_t *, dev_info_t *,
82 		scsi_hba_tran_t *, struct scsi_device *);
83 static void	scsa1394_scsi_tgt_free(dev_info_t *, dev_info_t *,
84 		scsi_hba_tran_t *, struct scsi_device *);
85 static int	scsa1394_scsi_tgt_probe(struct scsi_device *, int (*)());
86 static int	scsa1394_probe_g0_nodata(struct scsi_device *, int (*)(),
87 		uchar_t, uint_t, uint_t);
88 static int	scsa1394_probe_tran(struct scsi_pkt *);
89 static struct scsi_pkt *scsa1394_scsi_init_pkt(struct scsi_address *,
90 		struct scsi_pkt *, struct buf *, int, int, int, int,
91 		int (*)(), caddr_t arg);
92 static void	scsa1394_scsi_destroy_pkt(struct scsi_address *,
93 		struct scsi_pkt *);
94 static int	scsa1394_scsi_start(struct scsi_address *, struct scsi_pkt *);
95 static int	scsa1394_scsi_abort(struct scsi_address *, struct scsi_pkt *);
96 static int	scsa1394_scsi_reset(struct scsi_address *, int);
97 static int	scsa1394_scsi_getcap(struct scsi_address *, char *, int);
98 static int	scsa1394_scsi_setcap(struct scsi_address *, char *, int, int);
99 static void	scsa1394_scsi_dmafree(struct scsi_address *, struct scsi_pkt *);
100 static void	scsa1394_scsi_sync_pkt(struct scsi_address *,
101 		struct scsi_pkt *);
102 
103 /* pkt resource allocation routines */
104 static int	scsa1394_cmd_cache_constructor(void *, void *, int);
105 static void	scsa1394_cmd_cache_destructor(void *, void *);
106 static int	scsa1394_cmd_ext_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
107 		int);
108 static void	scsa1394_cmd_ext_free(scsa1394_state_t *, scsa1394_cmd_t *);
109 static int	scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
110 		int, int (*)(), caddr_t);
111 static void	scsa1394_cmd_cdb_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
112 static int	scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
113 		int, int (*)(), caddr_t, struct buf *);
114 static void	scsa1394_cmd_buf_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
115 static int	scsa1394_cmd_dmac2seg(scsa1394_state_t *, scsa1394_cmd_t *,
116 		ddi_dma_cookie_t *, uint_t, int);
117 static void	scsa1394_cmd_seg_free(scsa1394_state_t *, scsa1394_cmd_t *);
118 static int	scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *, scsa1394_cmd_t *,
119 		int (*)(), caddr_t, int);
120 static void	scsa1394_cmd_pt_dma_free(scsa1394_state_t *, scsa1394_cmd_t *);
121 static int	scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *,
122 		scsa1394_cmd_t *);
123 static void	scsa1394_cmd_buf_addr_free(scsa1394_state_t *,
124 		scsa1394_cmd_t *);
125 static int	scsa1394_cmd_buf_dma_move(scsa1394_state_t *, scsa1394_cmd_t *);
126 
127 
128 /* pkt and data transfer routines */
129 static void	scsa1394_prepare_pkt(scsa1394_state_t *, struct scsi_pkt *);
130 static void	scsa1394_cmd_fill_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
131 static void	scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *, scsa1394_cmd_t *);
132 static void	scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *, scsa1394_cmd_t *);
133 static void	scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *, int);
134 static void	scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *, int);
135 static void	scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *, int);
136 static void	scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *, int);
137 static int	scsa1394_cmd_read_cd_blk_size(uchar_t);
138 static int	scsa1394_cmd_fake_mode_sense(scsa1394_state_t *,
139 		scsa1394_cmd_t *);
140 static int	scsa1394_cmd_fake_inquiry(scsa1394_state_t *, scsa1394_cmd_t *);
141 static int	scsa1394_cmd_fake_comp(scsa1394_state_t *, scsa1394_cmd_t *);
142 static int	scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *,
143 		scsa1394_cmd_t *);
144 static void	scsa1394_cmd_adjust_cdb(scsa1394_lun_t *, scsa1394_cmd_t *);
145 static void	scsa1394_cmd_status_wrka(scsa1394_lun_t *, scsa1394_cmd_t *);
146 
147 /* other routines */
148 static boolean_t scsa1394_is_my_child(dev_info_t *);
149 static void *	scsa1394_kmem_realloc(void *, int, int, size_t, int);
150 
151 static void	*scsa1394_statep;
152 #define	SCSA1394_INST2STATE(inst) (ddi_get_soft_state(scsa1394_statep, inst))
153 
154 static struct cb_ops scsa1394_cb_ops = {
155 	nodev,			/* open */
156 	nodev,			/* close */
157 	nodev,			/* strategy */
158 	nodev,			/* print */
159 	nodev,			/* dump */
160 	nodev,			/* read */
161 	nodev,			/* write */
162 	NULL,			/* ioctl */
163 	nodev,			/* devmap */
164 	nodev,			/* mmap */
165 	nodev,			/* segmap */
166 	nochpoll,		/* poll */
167 	ddi_prop_op,		/* prop_op */
168 	NULL,			/* stream */
169 	D_MP,			/* cb_flag */
170 	CB_REV,			/* rev */
171 	nodev,			/* aread */
172 	nodev			/* awrite */
173 };
174 
175 static struct dev_ops scsa1394_ops = {
176 	DEVO_REV,		/* devo_rev, */
177 	0,			/* refcnt  */
178 	ddi_no_info,		/* info */
179 	nulldev,		/* identify */
180 	nulldev,		/* probe */
181 	scsa1394_attach,	/* attach */
182 	scsa1394_detach,	/* detach */
183 	nodev,			/* reset */
184 	&scsa1394_cb_ops,	/* driver operations */
185 	NULL,			/* bus operations */
186 	scsa1394_power,		/* power */
187 	ddi_quiesce_not_supported,	/* devo_quiesce */
188 };
189 
190 static struct modldrv scsa1394_modldrv = {
191 	&mod_driverops,			/* module type */
192 	"1394 Mass Storage HBA Driver", /* name of the module */
193 	&scsa1394_ops,			/* driver ops */
194 };
195 
196 static struct modlinkage scsa1394_modlinkage = {
197 	MODREV_1, (void *)&scsa1394_modldrv, NULL
198 };
199 
200 /* tunables */
201 int scsa1394_bus_config_debug = 0;
202 int scsa1394_start_stop_fail_max = SCSA1394_START_STOP_FAIL_MAX;
203 int scsa1394_mode_sense_fail_max = SCSA1394_MODE_SENSE_FAIL_MAX;
204 int scsa1394_start_stop_timeout_max = SCSA1394_START_STOP_TIMEOUT_MAX;
205 
206 /* workarounds */
207 int scsa1394_wrka_rbc2direct = 1;
208 int scsa1394_wrka_fake_rmb = 0;
209 int scsa1394_wrka_fake_prin = 1;
210 
211 int scsa1394_wrka_symbios = 1;
212 int scsa1394_symbios_page_size = 4 * 1024;	/* must be <= _pagesize */
213 int scsa1394_symbios_size_max = 512 * 248;	/* multiple of page size */
214 
215 /*
216  *
217  * --- DDI/DKI entry points
218  *
219  */
220 int
_init(void)221 _init(void)
222 {
223 	int	ret;
224 
225 	if (((ret = ddi_soft_state_init(&scsa1394_statep,
226 	    sizeof (scsa1394_state_t), 1)) != 0)) {
227 		return (ret);
228 	}
229 
230 	if ((ret = scsi_hba_init(&scsa1394_modlinkage)) != 0) {
231 		ddi_soft_state_fini(&scsa1394_statep);
232 		return (ret);
233 	}
234 
235 	if ((ret = mod_install(&scsa1394_modlinkage)) != 0) {
236 		scsi_hba_fini(&scsa1394_modlinkage);
237 		ddi_soft_state_fini(&scsa1394_statep);
238 		return (ret);
239 	}
240 
241 	return (ret);
242 }
243 
244 int
_fini(void)245 _fini(void)
246 {
247 	int	ret;
248 
249 	if ((ret = mod_remove(&scsa1394_modlinkage)) == 0) {
250 		scsi_hba_fini(&scsa1394_modlinkage);
251 		ddi_soft_state_fini(&scsa1394_statep);
252 	}
253 
254 	return (ret);
255 }
256 
257 int
_info(struct modinfo * modinfop)258 _info(struct modinfo *modinfop)
259 {
260 	return (mod_info(&scsa1394_modlinkage, modinfop));
261 }
262 
263 static int
scsa1394_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)264 scsa1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
265 {
266 	int		instance = ddi_get_instance(dip);
267 	scsa1394_state_t *sp;
268 
269 	switch (cmd) {
270 	case DDI_ATTACH:
271 		break;
272 	case DDI_RESUME:
273 		scsa1394_cpr_resume(dip);
274 		return (DDI_SUCCESS);
275 	default:
276 		return (DDI_FAILURE);
277 	}
278 
279 	if (ddi_soft_state_zalloc(scsa1394_statep, instance) != 0) {
280 		return (DDI_FAILURE);
281 	}
282 	sp = SCSA1394_INST2STATE(instance);
283 
284 #ifndef __lock_lint
285 	sp->s_dip = dip;
286 	sp->s_instance = instance;
287 #endif
288 	mutex_init(&sp->s_mutex, NULL, MUTEX_DRIVER,
289 	    sp->s_attachinfo.iblock_cookie);
290 	cv_init(&sp->s_event_cv, NULL, CV_DRIVER, NULL);
291 
292 	if (scsa1394_attach_1394(sp) != DDI_SUCCESS) {
293 		scsa1394_cleanup(sp, 1);
294 		return (DDI_FAILURE);
295 	}
296 
297 	if (scsa1394_sbp2_attach(sp) != DDI_SUCCESS) {
298 		scsa1394_cleanup(sp, 2);
299 		return (DDI_FAILURE);
300 	}
301 
302 	if (scsa1394_attach_threads(sp) != DDI_SUCCESS) {
303 		scsa1394_cleanup(sp, 3);
304 		return (DDI_FAILURE);
305 	}
306 
307 	if (scsa1394_attach_scsa(sp) != DDI_SUCCESS) {
308 		scsa1394_cleanup(sp, 4);
309 		return (DDI_FAILURE);
310 	}
311 
312 	if (scsa1394_create_cmd_cache(sp) != DDI_SUCCESS) {
313 		scsa1394_cleanup(sp, 5);
314 		return (DDI_FAILURE);
315 	}
316 
317 	if (scsa1394_add_events(sp) != DDI_SUCCESS) {
318 		scsa1394_cleanup(sp, 6);
319 		return (DDI_FAILURE);
320 	}
321 
322 	/* prevent async PM changes until we are done */
323 	(void) pm_busy_component(dip, 0);
324 
325 	/* Set power to full on */
326 	(void) pm_raise_power(dip, 0, PM_LEVEL_D0);
327 
328 	/* we are done */
329 	(void) pm_idle_component(dip, 0);
330 
331 #ifndef __lock_lint
332 	sp->s_dev_state = SCSA1394_DEV_ONLINE;
333 #endif
334 
335 	ddi_report_dev(dip);
336 
337 	return (DDI_SUCCESS);
338 }
339 
340 static int
scsa1394_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)341 scsa1394_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
342 {
343 	int		instance = ddi_get_instance(dip);
344 	scsa1394_state_t *sp;
345 
346 	if ((sp = SCSA1394_INST2STATE(instance)) == NULL) {
347 		return (DDI_FAILURE);
348 	}
349 
350 	switch (cmd) {
351 	case DDI_DETACH:
352 		/* Cycle power state to off and idle  where done/gone */
353 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
354 
355 		scsa1394_cleanup(sp, SCSA1394_CLEANUP_LEVEL_MAX);
356 		return (DDI_SUCCESS);
357 	case DDI_SUSPEND:
358 		return (scsa1394_cpr_suspend(dip));
359 	default:
360 		return (DDI_FAILURE);
361 	}
362 }
363 
364 /*ARGSUSED*/
365 static int
scsa1394_power(dev_info_t * dip,int comp,int level)366 scsa1394_power(dev_info_t *dip, int comp, int level)
367 {
368 	return (DDI_SUCCESS);
369 }
370 
371 /*
372  * scsa1394_cpr_suspend
373  *	determine if the device's state can be changed to SUSPENDED
374  */
375 /* ARGSUSED */
376 static int
scsa1394_cpr_suspend(dev_info_t * dip)377 scsa1394_cpr_suspend(dev_info_t *dip)
378 {
379 	int		instance = ddi_get_instance(dip);
380 	scsa1394_state_t *sp;
381 	int		rval = DDI_FAILURE;
382 
383 	sp = SCSA1394_INST2STATE(instance);
384 
385 	ASSERT(sp != NULL);
386 
387 
388 	mutex_enter(&sp->s_mutex);
389 	switch (sp->s_dev_state) {
390 	case SCSA1394_DEV_ONLINE:
391 	case SCSA1394_DEV_PWRED_DOWN:
392 	case SCSA1394_DEV_DISCONNECTED:
393 		sp->s_dev_state = SCSA1394_DEV_SUSPENDED;
394 
395 		/*  Power down and make device idle */
396 		(void) pm_lower_power(dip, 0, PM_LEVEL_D3);
397 
398 		rval = DDI_SUCCESS;
399 		break;
400 	case SCSA1394_DEV_SUSPENDED:
401 	default:
402 		if (scsa1394_bus_config_debug)
403 			cmn_err(CE_WARN,
404 			    "scsa1304_cpr_suspend: Illegal dev state: %d",
405 			    sp->s_dev_state);
406 
407 		rval = DDI_SUCCESS;
408 		break;
409 	}
410 	mutex_exit(&sp->s_mutex);
411 
412 	return (rval);
413 }
414 
415 /*
416  * scsa2usb_cpr_resume:
417  *	restore device's state
418  */
419 static void
scsa1394_cpr_resume(dev_info_t * dip)420 scsa1394_cpr_resume(dev_info_t *dip)
421 {
422 	int		instance = ddi_get_instance(dip);
423 	scsa1394_state_t *sp;
424 	int		i;
425 	scsa1394_lun_t	*lp;
426 
427 	sp = SCSA1394_INST2STATE(instance);
428 
429 	ASSERT(sp != NULL);
430 
431 	if (sp->s_dev_state != SCSA1394_DEV_SUSPENDED)
432 		return;
433 
434 	/*
435 	 * Go through each lun and reset it to force a reconnect.
436 	 */
437 	for (i = 0; i < sp->s_nluns; i++) {
438 		lp = &sp->s_lun[i];
439 		if (lp->l_ses != NULL) {  /* Are we loged in? */
440 			scsa1394_sbp2_req_bus_reset(lp);
441 			scsa1394_sbp2_req_reconnect(lp);
442 		}
443 	}
444 
445 	/* we are down so let the power get managed */
446 	(void) pm_idle_component(dip, 0);
447 }
448 
449 
450 
451 /*
452  *
453  * --- configuration routines
454  *
455  */
456 static void
scsa1394_cleanup(scsa1394_state_t * sp,int level)457 scsa1394_cleanup(scsa1394_state_t *sp, int level)
458 {
459 	ASSERT((level > 0) && (level <= SCSA1394_CLEANUP_LEVEL_MAX));
460 
461 	switch (level) {
462 	default:
463 		scsa1394_remove_events(sp);
464 		/* FALLTHRU */
465 	case 6:
466 		scsa1394_detach_scsa(sp);
467 		/* FALLTHRU */
468 	case 5:
469 		scsa1394_destroy_cmd_cache(sp);
470 		/* FALLTHRU */
471 	case 4:
472 		scsa1394_detach_threads(sp);
473 		/* FALLTHRU */
474 	case 3:
475 		scsa1394_sbp2_detach(sp);
476 		/* FALLTHRU */
477 	case 2:
478 		scsa1394_detach_1394(sp);
479 		/* FALLTHRU */
480 	case 1:
481 		cv_destroy(&sp->s_event_cv);
482 		mutex_destroy(&sp->s_mutex);
483 		ddi_soft_state_free(scsa1394_statep, sp->s_instance);
484 	}
485 }
486 
487 static int
scsa1394_attach_1394(scsa1394_state_t * sp)488 scsa1394_attach_1394(scsa1394_state_t *sp)
489 {
490 	int	ret;
491 
492 	if ((ret = t1394_attach(sp->s_dip, T1394_VERSION_V1, 0,
493 	    &sp->s_attachinfo, &sp->s_t1394_hdl)) != DDI_SUCCESS) {
494 		return (ret);
495 	}
496 
497 	/* DMA attributes for data buffers */
498 	sp->s_buf_dma_attr = sp->s_attachinfo.dma_attr;
499 
500 	/* DMA attributes for page tables */
501 	sp->s_pt_dma_attr = sp->s_attachinfo.dma_attr;
502 	sp->s_pt_dma_attr.dma_attr_sgllen = 1;	/* pt must be contiguous */
503 
504 	if ((ret = t1394_get_targetinfo(sp->s_t1394_hdl, SCSA1394_BUSGEN(sp), 0,
505 	    &sp->s_targetinfo)) != DDI_SUCCESS) {
506 		(void) t1394_detach(&sp->s_t1394_hdl, 0);
507 		return (ret);
508 	}
509 
510 	return (DDI_SUCCESS);
511 }
512 
513 static void
scsa1394_detach_1394(scsa1394_state_t * sp)514 scsa1394_detach_1394(scsa1394_state_t *sp)
515 {
516 	(void) t1394_detach(&sp->s_t1394_hdl, 0);
517 }
518 
519 static int
scsa1394_attach_threads(scsa1394_state_t * sp)520 scsa1394_attach_threads(scsa1394_state_t *sp)
521 {
522 	char		name[16];
523 	int		nthr;
524 
525 	nthr = sp->s_nluns;
526 	(void) snprintf(name, sizeof (name), "scsa1394%d", sp->s_instance);
527 	if ((sp->s_taskq = ddi_taskq_create(sp->s_dip, name, nthr,
528 	    TASKQ_DEFAULTPRI, 0)) == NULL) {
529 		return (DDI_FAILURE);
530 	}
531 
532 	if (scsa1394_sbp2_threads_init(sp) != DDI_SUCCESS) {
533 		ddi_taskq_destroy(sp->s_taskq);
534 		return (DDI_FAILURE);
535 	}
536 
537 	return (DDI_SUCCESS);
538 }
539 
540 static void
scsa1394_detach_threads(scsa1394_state_t * sp)541 scsa1394_detach_threads(scsa1394_state_t *sp)
542 {
543 	scsa1394_sbp2_threads_fini(sp);
544 	ddi_taskq_destroy(sp->s_taskq);
545 }
546 
547 static int
scsa1394_attach_scsa(scsa1394_state_t * sp)548 scsa1394_attach_scsa(scsa1394_state_t *sp)
549 {
550 	scsi_hba_tran_t	*tran;
551 	int		ret;
552 
553 	sp->s_tran = tran = scsi_hba_tran_alloc(sp->s_dip, SCSI_HBA_CANSLEEP);
554 
555 	tran->tran_hba_private	= sp;
556 	tran->tran_tgt_private	= NULL;
557 	tran->tran_tgt_init	= scsa1394_scsi_tgt_init;
558 	tran->tran_tgt_probe	= scsa1394_scsi_tgt_probe;
559 	tran->tran_tgt_free	= scsa1394_scsi_tgt_free;
560 	tran->tran_start	= scsa1394_scsi_start;
561 	tran->tran_abort	= scsa1394_scsi_abort;
562 	tran->tran_reset	= scsa1394_scsi_reset;
563 	tran->tran_getcap	= scsa1394_scsi_getcap;
564 	tran->tran_setcap	= scsa1394_scsi_setcap;
565 	tran->tran_init_pkt	= scsa1394_scsi_init_pkt;
566 	tran->tran_destroy_pkt	= scsa1394_scsi_destroy_pkt;
567 	tran->tran_dmafree	= scsa1394_scsi_dmafree;
568 	tran->tran_sync_pkt	= scsa1394_scsi_sync_pkt;
569 	tran->tran_reset_notify	= NULL;
570 	tran->tran_get_bus_addr	= NULL;
571 	tran->tran_get_name	= NULL;
572 	tran->tran_bus_reset	= NULL;
573 	tran->tran_quiesce	= NULL;
574 	tran->tran_unquiesce	= NULL;
575 	tran->tran_get_eventcookie = NULL;
576 	tran->tran_add_eventcall = NULL;
577 	tran->tran_remove_eventcall = NULL;
578 	tran->tran_post_event	= NULL;
579 	tran->tran_bus_config	= scsa1394_scsi_bus_config;
580 	tran->tran_bus_unconfig	= scsa1394_scsi_bus_unconfig;
581 
582 	if ((ret = scsi_hba_attach_setup(sp->s_dip, &sp->s_attachinfo.dma_attr,
583 	    tran, 0)) != DDI_SUCCESS) {
584 		scsi_hba_tran_free(tran);
585 		return (ret);
586 	}
587 
588 	return (DDI_SUCCESS);
589 }
590 
591 static void
scsa1394_detach_scsa(scsa1394_state_t * sp)592 scsa1394_detach_scsa(scsa1394_state_t *sp)
593 {
594 	int	ret;
595 
596 	ret = scsi_hba_detach(sp->s_dip);
597 	ASSERT(ret == DDI_SUCCESS);
598 
599 	scsi_hba_tran_free(sp->s_tran);
600 }
601 
602 static int
scsa1394_create_cmd_cache(scsa1394_state_t * sp)603 scsa1394_create_cmd_cache(scsa1394_state_t *sp)
604 {
605 	char	name[64];
606 
607 	(void) sprintf(name, "scsa1394%d_cache", sp->s_instance);
608 	sp->s_cmd_cache = kmem_cache_create(name,
609 	    SCSA1394_CMD_SIZE, sizeof (void *),
610 	    scsa1394_cmd_cache_constructor, scsa1394_cmd_cache_destructor,
611 	    NULL, (void *)sp, NULL, 0);
612 
613 	return ((sp->s_cmd_cache == NULL) ? DDI_FAILURE : DDI_SUCCESS);
614 }
615 
616 static void
scsa1394_destroy_cmd_cache(scsa1394_state_t * sp)617 scsa1394_destroy_cmd_cache(scsa1394_state_t *sp)
618 {
619 	kmem_cache_destroy(sp->s_cmd_cache);
620 }
621 
622 static int
scsa1394_add_events(scsa1394_state_t * sp)623 scsa1394_add_events(scsa1394_state_t *sp)
624 {
625 	ddi_eventcookie_t	br_evc, rem_evc, ins_evc;
626 
627 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
628 	    &br_evc) != DDI_SUCCESS) {
629 		return (DDI_FAILURE);
630 	}
631 	if (ddi_add_event_handler(sp->s_dip, br_evc, scsa1394_bus_reset,
632 	    sp, &sp->s_reset_cb_id) != DDI_SUCCESS) {
633 		return (DDI_FAILURE);
634 	}
635 
636 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
637 	    &rem_evc) != DDI_SUCCESS) {
638 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
639 		return (DDI_FAILURE);
640 	}
641 	if (ddi_add_event_handler(sp->s_dip, rem_evc, scsa1394_disconnect,
642 	    sp, &sp->s_remove_cb_id) != DDI_SUCCESS) {
643 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
644 		return (DDI_FAILURE);
645 	}
646 
647 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
648 	    &ins_evc) != DDI_SUCCESS) {
649 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
650 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
651 		return (DDI_FAILURE);
652 	}
653 	if (ddi_add_event_handler(sp->s_dip, ins_evc, scsa1394_reconnect,
654 	    sp, &sp->s_insert_cb_id) != DDI_SUCCESS) {
655 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
656 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
657 		return (DDI_FAILURE);
658 	}
659 
660 	return (DDI_SUCCESS);
661 }
662 
663 static void
scsa1394_remove_events(scsa1394_state_t * sp)664 scsa1394_remove_events(scsa1394_state_t *sp)
665 {
666 	ddi_eventcookie_t	evc;
667 
668 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_INSERT_EVENT,
669 	    &evc) == DDI_SUCCESS) {
670 		(void) ddi_remove_event_handler(sp->s_insert_cb_id);
671 	}
672 
673 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_REMOVE_EVENT,
674 	    &evc) == DDI_SUCCESS) {
675 		(void) ddi_remove_event_handler(sp->s_remove_cb_id);
676 	}
677 
678 	if (ddi_get_eventcookie(sp->s_dip, DDI_DEVI_BUS_RESET_EVENT,
679 	    &evc) == DDI_SUCCESS) {
680 		(void) ddi_remove_event_handler(sp->s_reset_cb_id);
681 	}
682 }
683 
684 /*
685  *
686  * --- device configuration
687  *
688  */
689 static int
scsa1394_scsi_bus_config(dev_info_t * dip,uint_t flag,ddi_bus_config_op_t op,void * arg,dev_info_t ** child)690 scsa1394_scsi_bus_config(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
691     void *arg, dev_info_t **child)
692 {
693 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
694 	int		ret;
695 
696 	if (scsa1394_bus_config_debug) {
697 		flag |= NDI_DEVI_DEBUG;
698 	}
699 
700 	ndi_devi_enter(dip);
701 	if (DEVI(dip)->devi_child == NULL) {
702 		scsa1394_create_children(sp);
703 	}
704 	ret = ndi_busop_bus_config(dip, flag, op, arg, child, 0);
705 	ndi_devi_exit(dip);
706 
707 	return (ret);
708 }
709 
710 static int
scsa1394_scsi_bus_unconfig(dev_info_t * dip,uint_t flag,ddi_bus_config_op_t op,void * arg)711 scsa1394_scsi_bus_unconfig(dev_info_t *dip, uint_t flag, ddi_bus_config_op_t op,
712     void *arg)
713 {
714 	scsa1394_state_t *sp = SCSA1394_INST2STATE(ddi_get_instance(dip));
715 	int		ret;
716 	uint_t		saved_flag = flag;
717 
718 	if (scsa1394_bus_config_debug) {
719 		flag |= NDI_DEVI_DEBUG;
720 	}
721 
722 	/*
723 	 * First offline and if offlining successful, then remove children.
724 	 */
725 	if (op == BUS_UNCONFIG_ALL) {
726 		flag &= ~(NDI_DEVI_REMOVE | NDI_UNCONFIG);
727 	}
728 
729 	ndi_devi_enter(dip);
730 
731 	ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
732 
733 	/*
734 	 * If previous step was successful and not part of modunload daemon,
735 	 * attempt to remove children.
736 	 */
737 	if ((op == BUS_UNCONFIG_ALL) && (ret == NDI_SUCCESS) &&
738 	    ((flag & NDI_AUTODETACH) == 0)) {
739 		flag |= NDI_DEVI_REMOVE;
740 		ret = ndi_busop_bus_unconfig(dip, flag, op, arg);
741 	}
742 	ndi_devi_exit(dip);
743 
744 	if ((ret != NDI_SUCCESS) && (op == BUS_UNCONFIG_ALL) &&
745 	    ((saved_flag & NDI_DEVI_REMOVE) != 0)) {
746 		mutex_enter(&sp->s_mutex);
747 		if (!sp->s_disconnect_warned) {
748 			cmn_err(CE_WARN, "scsa1394(%d): "
749 			    "Disconnected device was busy, please reconnect.\n",
750 			    sp->s_instance);
751 			sp->s_disconnect_warned = B_TRUE;
752 		}
753 		mutex_exit(&sp->s_mutex);
754 	}
755 
756 	return (ret);
757 }
758 
759 void
scsa1394_dtype2name(int dtype,char ** node_name,char ** driver_name)760 scsa1394_dtype2name(int dtype, char **node_name, char **driver_name)
761 {
762 	static struct {
763 		char	*node_name;
764 		char	*driver_name;
765 	} dtype2name[] = {
766 		{ "disk",	"sd" },		/* DTYPE_DIRECT		0x00 */
767 		{ "tape",	"st" },		/* DTYPE_SEQUENTIAL	0x01 */
768 		{ "printer",	NULL },		/* DTYPE_PRINTER	0x02 */
769 		{ "processor",	NULL },		/* DTYPE_PROCESSOR	0x03 */
770 		{ "worm",	NULL },		/* DTYPE_WORM		0x04 */
771 		{ "disk",	"sd" },		/* DTYPE_RODIRECT	0x05 */
772 		{ "scanner",	NULL },		/* DTYPE_SCANNER	0x06 */
773 		{ "disk",	"sd" },		/* DTYPE_OPTICAL	0x07 */
774 		{ "changer",	NULL },		/* DTYPE_CHANGER	0x08 */
775 		{ "comm",	NULL },		/* DTYPE_COMM		0x09 */
776 		{ "generic",	NULL },		/* DTYPE_???		0x0A */
777 		{ "generic",	NULL },		/* DTYPE_???		0x0B */
778 		{ "array_ctrl",	NULL },		/* DTYPE_ARRAY_CTRL	0x0C */
779 		{ "esi",	"ses" },	/* DTYPE_ESI		0x0D */
780 		{ "disk",	"sd" }		/* DTYPE_RBC		0x0E */
781 	};
782 
783 	if (dtype < NELEM(dtype2name)) {
784 		*node_name = dtype2name[dtype].node_name;
785 		*driver_name = dtype2name[dtype].driver_name;
786 	} else {
787 		*node_name = "generic";
788 		*driver_name = NULL;
789 	}
790 }
791 
792 static void
scsa1394_create_children(scsa1394_state_t * sp)793 scsa1394_create_children(scsa1394_state_t *sp)
794 {
795 	char		name[SCSA1394_COMPAT_MAX][16];
796 	char		*compatible[SCSA1394_COMPAT_MAX];
797 	dev_info_t	*cdip;
798 	int		i;
799 	int		dtype;
800 	char		*node_name;
801 	char		*driver_name;
802 	int		ret;
803 
804 	bzero(name, sizeof (name));
805 	(void) strcpy(name[0], "sd");
806 	for (i = 0; i < SCSA1394_COMPAT_MAX; i++) {
807 		compatible[i] = name[i];
808 	}
809 
810 	for (i = 0; i < sp->s_nluns; i++) {
811 		dtype = scsa1394_sbp2_get_lun_type(&sp->s_lun[i]);
812 		scsa1394_dtype2name(dtype, &node_name, &driver_name);
813 
814 		ndi_devi_alloc_sleep(sp->s_dip, node_name,
815 		    (pnode_t)DEVI_SID_NODEID, &cdip);
816 
817 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
818 		    SCSI_ADDR_PROP_TARGET, 0);
819 		if (ret != DDI_PROP_SUCCESS) {
820 			(void) ndi_devi_free(cdip);
821 			continue;
822 		}
823 
824 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
825 		    SCSI_ADDR_PROP_LUN, i);
826 		if (ret != DDI_PROP_SUCCESS) {
827 			ddi_prop_remove_all(cdip);
828 			(void) ndi_devi_free(cdip);
829 			continue;
830 		}
831 
832 		/*
833 		 * Some devices don't support LOG SENSE, so tell
834 		 * sd driver not to send this command.
835 		 */
836 		ret = ndi_prop_update_int(DDI_DEV_T_NONE, cdip,
837 		    "pm-capable", 1);
838 		if (ret != DDI_PROP_SUCCESS) {
839 			ddi_prop_remove_all(cdip);
840 			(void) ndi_devi_free(cdip);
841 			continue;
842 		}
843 
844 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
845 		    "hotpluggable");
846 		if (ret != DDI_PROP_SUCCESS) {
847 			ddi_prop_remove_all(cdip);
848 			(void) ndi_devi_free(cdip);
849 			continue;
850 		}
851 
852 		if (driver_name) {
853 			compatible[0] = driver_name;
854 			ret = ndi_prop_update_string_array(DDI_DEV_T_NONE, cdip,
855 			    "compatible", (char **)compatible,
856 			    SCSA1394_COMPAT_MAX);
857 			if (ret != DDI_PROP_SUCCESS) {
858 				ddi_prop_remove_all(cdip);
859 				(void) ndi_devi_free(cdip);
860 				continue;
861 			}
862 		}
863 
864 		/*
865 		 * add property "scsa1394" to distinguish from others' children
866 		 */
867 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
868 		if (ret != DDI_PROP_SUCCESS) {
869 			ddi_prop_remove_all(cdip);
870 			(void) ndi_devi_free(cdip);
871 			continue;
872 		}
873 
874 		(void) ddi_initchild(sp->s_dip, cdip);
875 	}
876 }
877 
878 /*ARGSUSED*/
879 static void
scsa1394_bus_reset(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)880 scsa1394_bus_reset(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
881     void *data)
882 {
883 	scsa1394_state_t	*sp = arg;
884 
885 	if (sp != NULL) {
886 		mutex_enter(&sp->s_mutex);
887 		if (sp->s_dev_state == SCSA1394_DEV_DISCONNECTED) {
888 			mutex_exit(&sp->s_mutex);
889 			return;
890 		}
891 		sp->s_stat.stat_bus_reset_cnt++;
892 		sp->s_dev_state = SCSA1394_DEV_BUS_RESET;
893 		sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
894 		mutex_exit(&sp->s_mutex);
895 
896 		scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_BUS_RESET);
897 	}
898 }
899 
900 /*ARGSUSED*/
901 static void
scsa1394_disconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)902 scsa1394_disconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
903     void *data)
904 {
905 	scsa1394_state_t	*sp = arg;
906 	dev_info_t		*cdip, *cdip_next;
907 
908 	if (sp == NULL) {
909 		return;
910 	}
911 
912 	mutex_enter(&sp->s_mutex);
913 	sp->s_stat.stat_disconnect_cnt++;
914 	sp->s_dev_state = SCSA1394_DEV_DISCONNECTED;
915 	mutex_exit(&sp->s_mutex);
916 
917 	scsa1394_sbp2_disconnect(sp);
918 
919 	ndi_devi_enter(dip);
920 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
921 		cdip_next = ddi_get_next_sibling(cdip);
922 
923 		mutex_enter(&DEVI(cdip)->devi_lock);
924 		DEVI_SET_DEVICE_REMOVED(cdip);
925 		mutex_exit(&DEVI(cdip)->devi_lock);
926 	}
927 	ndi_devi_exit(dip);
928 }
929 
930 /*ARGSUSED*/
931 static void
scsa1394_reconnect(dev_info_t * dip,ddi_eventcookie_t evc,void * arg,void * data)932 scsa1394_reconnect(dev_info_t *dip, ddi_eventcookie_t evc, void *arg,
933     void *data)
934 {
935 	scsa1394_state_t	*sp = arg;
936 	dev_info_t		*cdip, *cdip_next;
937 
938 	if (sp == NULL) {
939 		return;
940 	}
941 
942 	mutex_enter(&sp->s_mutex);
943 	sp->s_stat.stat_reconnect_cnt++;
944 	sp->s_attachinfo.localinfo = *(t1394_localinfo_t *)data;
945 	sp->s_disconnect_warned = B_FALSE;
946 	mutex_exit(&sp->s_mutex);
947 
948 	ndi_devi_enter(dip);
949 	for (cdip = ddi_get_child(dip); cdip != NULL; cdip = cdip_next) {
950 		cdip_next = ddi_get_next_sibling(cdip);
951 
952 		mutex_enter(&DEVI(cdip)->devi_lock);
953 		DEVI_SET_DEVICE_REINSERTED(cdip);
954 		mutex_exit(&DEVI(cdip)->devi_lock);
955 	}
956 	ndi_devi_exit(dip);
957 
958 	scsa1394_sbp2_req(sp, 0, SCSA1394_THREQ_RECONNECT);
959 }
960 
961 /*
962  *
963  * --- SCSA entry points
964  *
965  */
966 /*ARGSUSED*/
967 static int
scsa1394_scsi_tgt_init(dev_info_t * dip,dev_info_t * cdip,scsi_hba_tran_t * tran,struct scsi_device * sd)968 scsa1394_scsi_tgt_init(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
969     struct scsi_device *sd)
970 {
971 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
972 	int		lun;
973 	int		plen = sizeof (int);
974 	int		ret = DDI_FAILURE;
975 
976 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
977 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
978 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
979 		return (DDI_FAILURE);
980 	}
981 
982 	if (!scsa1394_is_my_child(cdip)) {
983 		/*
984 		 * add property "scsa1394" to distinguish from others' children
985 		 */
986 		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip, "scsa1394");
987 		if (ret != DDI_PROP_SUCCESS) {
988 			return (DDI_FAILURE);
989 		}
990 
991 		if (scsa1394_dev_is_online(sp)) {
992 			return (scsa1394_sbp2_login(sp, lun));
993 		} else {
994 			return (DDI_FAILURE);
995 		}
996 	}
997 
998 	if ((lun >= sp->s_nluns) || (sp->s_lun[lun].l_cdip != NULL) ||
999 	    !scsa1394_dev_is_online(sp)) {
1000 		return (DDI_FAILURE);
1001 	}
1002 
1003 	if ((ret = scsa1394_sbp2_login(sp, lun)) == DDI_SUCCESS) {
1004 		sp->s_lun[lun].l_cdip = cdip;
1005 	}
1006 	return (ret);
1007 }
1008 
1009 /*ARGSUSED*/
1010 static void
scsa1394_scsi_tgt_free(dev_info_t * dip,dev_info_t * cdip,scsi_hba_tran_t * tran,struct scsi_device * sd)1011 scsa1394_scsi_tgt_free(dev_info_t *dip, dev_info_t *cdip, scsi_hba_tran_t *tran,
1012     struct scsi_device *sd)
1013 {
1014 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
1015 	int		lun;
1016 	int		plen = sizeof (int);
1017 
1018 	if (!scsa1394_is_my_child(cdip)) {
1019 		return;
1020 	}
1021 
1022 	if (ddi_prop_op(DDI_DEV_T_ANY, cdip, PROP_LEN_AND_VAL_BUF,
1023 	    DDI_PROP_DONTPASS | DDI_PROP_CANSLEEP, SCSI_ADDR_PROP_LUN,
1024 	    (caddr_t)&lun, &plen) != DDI_PROP_SUCCESS) {
1025 		return;
1026 	}
1027 
1028 	if ((lun < sp->s_nluns) && (sp->s_lun[lun].l_cdip == cdip)) {
1029 		if (scsa1394_dev_is_online(sp)) {
1030 			scsa1394_sbp2_logout(sp, lun, B_TRUE);
1031 		}
1032 		sp->s_lun[lun].l_cdip = NULL;
1033 	}
1034 }
1035 
1036 static int
scsa1394_scsi_tgt_probe(struct scsi_device * sd,int (* waitfunc)())1037 scsa1394_scsi_tgt_probe(struct scsi_device *sd, int (*waitfunc)())
1038 {
1039 	dev_info_t	*dip = ddi_get_parent(sd->sd_dev);
1040 	scsi_hba_tran_t	*tran = (scsi_hba_tran_t *)ddi_get_driver_private(dip);
1041 	scsa1394_state_t *sp = (scsa1394_state_t *)tran->tran_hba_private;
1042 	scsa1394_lun_t	*lp;
1043 
1044 	if (!scsa1394_dev_is_online(sp)) {
1045 		return (SCSIPROBE_FAILURE);
1046 	}
1047 	lp = &sp->s_lun[sd->sd_address.a_lun];
1048 
1049 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
1050 	    SCMD_TEST_UNIT_READY, 0, 0) != SCSIPROBE_EXISTS) {
1051 		lp->l_nosup_tur = B_TRUE;
1052 		(void) scsa1394_sbp2_reset(lp, RESET_LUN, NULL);
1053 	}
1054 	if (scsa1394_probe_g0_nodata(sd, waitfunc,
1055 	    SCMD_START_STOP, 0, 1) != SCSIPROBE_EXISTS) {
1056 		lp->l_nosup_start_stop = B_TRUE;
1057 	}
1058 
1059 	/* standard probe issues INQUIRY, which some devices may not support */
1060 	if (scsi_hba_probe(sd, waitfunc) != SCSIPROBE_EXISTS) {
1061 		lp->l_nosup_inquiry = B_TRUE;
1062 		scsa1394_sbp2_fake_inquiry(sp, &lp->l_fake_inq);
1063 		bcopy(&lp->l_fake_inq, sd->sd_inq, SUN_INQSIZE);
1064 #ifndef __lock_lint
1065 		lp->l_rmb_orig = 1;
1066 #endif
1067 	}
1068 
1069 	if (scsa1394_wrka_fake_rmb) {
1070 		sd->sd_inq->inq_rmb = 1;
1071 	}
1072 
1073 	return (SCSIPROBE_EXISTS);
1074 }
1075 
1076 static int
scsa1394_probe_g0_nodata(struct scsi_device * sd,int (* waitfunc)(),uchar_t cmd,uint_t addr,uint_t cnt)1077 scsa1394_probe_g0_nodata(struct scsi_device *sd, int (*waitfunc)(),
1078     uchar_t cmd, uint_t addr, uint_t cnt)
1079 {
1080 	struct scsi_pkt	*pkt;
1081 	int		ret = SCSIPROBE_EXISTS;
1082 
1083 	pkt = scsi_init_pkt(&sd->sd_address, NULL, NULL, CDB_GROUP0,
1084 	    sizeof (struct scsi_arq_status), 0, PKT_CONSISTENT, waitfunc, NULL);
1085 
1086 	if (pkt == NULL) {
1087 		return (SCSIPROBE_NOMEM);
1088 	}
1089 
1090 	(void) scsi_setup_cdb((union scsi_cdb *)pkt->pkt_cdbp, cmd, addr, cnt,
1091 	    0);
1092 	((union scsi_cdb *)(pkt)->pkt_cdbp)->scc_lun = sd->sd_address.a_lun;
1093 	pkt->pkt_flags = FLAG_NOINTR;
1094 
1095 	if (scsa1394_probe_tran(pkt) < 0) {
1096 		if (pkt->pkt_reason == CMD_INCOMPLETE) {
1097 			ret = SCSIPROBE_NORESP;
1098 		} else if ((pkt->pkt_reason == CMD_TRAN_ERR) &&
1099 		    ((*(pkt->pkt_scbp) & STATUS_MASK) == STATUS_CHECK) &&
1100 		    (pkt->pkt_state & STATE_ARQ_DONE)) {
1101 			ret = SCSIPROBE_EXISTS;
1102 		} else {
1103 			ret = SCSIPROBE_FAILURE;
1104 		}
1105 	}
1106 
1107 	scsi_destroy_pkt(pkt);
1108 
1109 	return (ret);
1110 }
1111 
1112 static int
scsa1394_probe_tran(struct scsi_pkt * pkt)1113 scsa1394_probe_tran(struct scsi_pkt *pkt)
1114 {
1115 	pkt->pkt_time = SCSA1394_PROBE_TIMEOUT;
1116 
1117 	if (scsi_transport(pkt) != TRAN_ACCEPT) {
1118 		return (-1);
1119 	} else if ((pkt->pkt_reason == CMD_INCOMPLETE) &&
1120 	    (pkt->pkt_state == 0)) {
1121 		return (-1);
1122 	} else if (pkt->pkt_reason != CMD_CMPLT) {
1123 		return (-1);
1124 	} else if (((*pkt->pkt_scbp) & STATUS_MASK) == STATUS_BUSY) {
1125 		return (0);
1126 	}
1127 	return (0);
1128 }
1129 
1130 /*ARGSUSED*/
1131 static int
scsa1394_scsi_abort(struct scsi_address * ap,struct scsi_pkt * pkt)1132 scsa1394_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt)
1133 {
1134 	return (0);
1135 }
1136 
1137 static int
scsa1394_scsi_reset(struct scsi_address * ap,int level)1138 scsa1394_scsi_reset(struct scsi_address *ap, int level)
1139 {
1140 	scsa1394_state_t *sp = ADDR2STATE(ap);
1141 	scsa1394_lun_t	*lp;
1142 	int		ret;
1143 
1144 	switch (level) {
1145 	case RESET_ALL:
1146 	case RESET_TARGET:
1147 		lp = &sp->s_lun[0];
1148 		break;
1149 	case RESET_LUN:
1150 		lp = &sp->s_lun[ap->a_lun];
1151 		break;
1152 	default:
1153 		return (DDI_FAILURE);
1154 	}
1155 
1156 	ret = scsa1394_sbp2_reset(lp, level, NULL);
1157 
1158 	return ((ret == SBP2_SUCCESS) ? 1 : 0);
1159 }
1160 
1161 /*ARGSUSED*/
1162 static int
scsa1394_scsi_getcap(struct scsi_address * ap,char * cap,int whom)1163 scsa1394_scsi_getcap(struct scsi_address *ap, char *cap, int whom)
1164 {
1165 	scsa1394_state_t *sp = ADDR2STATE(ap);
1166 	size_t		dev_bsize_cap;
1167 	int		ret = -1;
1168 
1169 	if (!scsa1394_dev_is_online(sp)) {
1170 		return (-1);
1171 	}
1172 
1173 	if (cap == NULL) {
1174 		return (-1);
1175 	}
1176 
1177 	switch (scsi_hba_lookup_capstr(cap)) {
1178 	case SCSI_CAP_DMA_MAX:
1179 		ret = sp->s_attachinfo.dma_attr.dma_attr_maxxfer;
1180 		break;
1181 	case SCSI_CAP_SCSI_VERSION:
1182 		ret = SCSI_VERSION_2;
1183 		break;
1184 	case SCSI_CAP_ARQ:
1185 		ret = 1;
1186 		break;
1187 	case SCSI_CAP_UNTAGGED_QING:
1188 		ret = 1;
1189 		break;
1190 	case SCSI_CAP_GEOMETRY:
1191 		dev_bsize_cap = sp->s_totalsec;
1192 
1193 		if (sp->s_secsz > DEV_BSIZE) {
1194 			dev_bsize_cap *= sp->s_secsz / DEV_BSIZE;
1195 		} else if (sp->s_secsz < DEV_BSIZE) {
1196 			dev_bsize_cap /= DEV_BSIZE / sp->s_secsz;
1197 		}
1198 
1199 		if (dev_bsize_cap < 65536 * 2 * 18) {		/* < ~1GB */
1200 			/* unlabeled floppy, 18k per cylinder */
1201 			ret = ((2 << 16) | 18);
1202 		} else if (dev_bsize_cap < 65536 * 64 * 32) {	/* < 64GB */
1203 			/* 1024k per cylinder */
1204 			ret = ((64 << 16) | 32);
1205 		} else if (dev_bsize_cap < 65536 * 255 * 63) {	/* < ~500GB */
1206 			/* ~8m per cylinder */
1207 			ret = ((255 << 16) | 63);
1208 		} else {					/* .. 8TB */
1209 			/* 64m per cylinder */
1210 			ret = ((512 << 16) | 256);
1211 		}
1212 		break;
1213 	default:
1214 		break;
1215 	}
1216 
1217 	return (ret);
1218 }
1219 
1220 /*ARGSUSED*/
1221 static int
scsa1394_scsi_setcap(struct scsi_address * ap,char * cap,int value,int whom)1222 scsa1394_scsi_setcap(struct scsi_address *ap, char *cap, int value, int whom)
1223 {
1224 	scsa1394_state_t *sp = ADDR2STATE(ap);
1225 	int		ret = -1;
1226 
1227 	if (!scsa1394_dev_is_online(sp)) {
1228 		return (-1);
1229 	}
1230 
1231 	switch (scsi_hba_lookup_capstr(cap)) {
1232 	case SCSI_CAP_ARQ:
1233 		ret = 1;
1234 		break;
1235 	case SCSI_CAP_DMA_MAX:
1236 	case SCSI_CAP_SCSI_VERSION:
1237 	case SCSI_CAP_UNTAGGED_QING:
1238 		/* supported but not settable */
1239 		ret = 0;
1240 		break;
1241 	case SCSI_CAP_SECTOR_SIZE:
1242 		if (value) {
1243 			sp->s_secsz = value;
1244 		}
1245 		break;
1246 	case SCSI_CAP_TOTAL_SECTORS:
1247 		if (value) {
1248 			sp->s_totalsec = value;
1249 		}
1250 		break;
1251 	default:
1252 		break;
1253 	}
1254 
1255 	return (ret);
1256 }
1257 
1258 /*ARGSUSED*/
1259 static void
scsa1394_scsi_sync_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)1260 scsa1394_scsi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1261 {
1262 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1263 
1264 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1265 		(void) ddi_dma_sync(cmd->sc_buf_dma_hdl, 0, 0,
1266 		    (cmd->sc_flags & SCSA1394_CMD_READ) ?
1267 		    DDI_DMA_SYNC_FORCPU : DDI_DMA_SYNC_FORDEV);
1268 	}
1269 }
1270 
1271 /*
1272  *
1273  * --- pkt resource allocation routines
1274  *
1275  */
1276 static struct scsi_pkt *
scsa1394_scsi_init_pkt(struct scsi_address * ap,struct scsi_pkt * pkt,struct buf * bp,int cmdlen,int statuslen,int tgtlen,int flags,int (* callback)(),caddr_t arg)1277 scsa1394_scsi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt,
1278     struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags,
1279     int (*callback)(), caddr_t arg)
1280 {
1281 	scsa1394_state_t *sp = ADDR2STATE(ap);
1282 	scsa1394_lun_t	*lp;
1283 	scsa1394_cmd_t	*cmd;
1284 	boolean_t	is_new;	/* new cmd is being allocated */
1285 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1286 
1287 	if (ap->a_lun >= sp->s_nluns) {
1288 		return (NULL);
1289 	}
1290 	lp = &sp->s_lun[ap->a_lun];
1291 
1292 	/*
1293 	 * allocate cmd space
1294 	 */
1295 	if (pkt == NULL) {
1296 		is_new = B_TRUE;
1297 		if ((cmd = kmem_cache_alloc(sp->s_cmd_cache, kf)) == NULL) {
1298 			return (NULL);
1299 		}
1300 
1301 		/* initialize cmd */
1302 		pkt = &cmd->sc_scsi_pkt;
1303 		pkt->pkt_ha_private	= cmd;
1304 		pkt->pkt_address	= *ap;
1305 		pkt->pkt_private	= cmd->sc_priv;
1306 		pkt->pkt_scbp		= (uchar_t *)&cmd->sc_scb;
1307 		pkt->pkt_cdbp		= (uchar_t *)&cmd->sc_pkt_cdb;
1308 		pkt->pkt_resid		= 0;
1309 
1310 		cmd->sc_lun		= lp;
1311 		cmd->sc_pkt		= pkt;
1312 		cmd->sc_cdb_len		= cmdlen;
1313 		cmd->sc_scb_len		= statuslen;
1314 		cmd->sc_priv_len	= tgtlen;
1315 
1316 		/* need external space? */
1317 		if ((cmdlen > sizeof (cmd->sc_pkt_cdb)) ||
1318 		    (statuslen > sizeof (cmd->sc_scb)) ||
1319 		    (tgtlen > sizeof (cmd->sc_priv))) {
1320 			if (scsa1394_cmd_ext_alloc(sp, cmd, kf) !=
1321 			    DDI_SUCCESS) {
1322 				kmem_cache_free(sp->s_cmd_cache, cmd);
1323 				lp->l_stat.stat_err_pkt_kmem_alloc++;
1324 				return (NULL);
1325 			}
1326 		}
1327 
1328 		/* allocate DMA resources for CDB */
1329 		if (scsa1394_cmd_cdb_dma_alloc(sp, cmd, flags, callback, arg) !=
1330 		    DDI_SUCCESS) {
1331 			scsa1394_scsi_destroy_pkt(ap, pkt);
1332 			return (NULL);
1333 		}
1334 	} else {
1335 		is_new = B_FALSE;
1336 		cmd = PKT2CMD(pkt);
1337 	}
1338 
1339 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1340 
1341 	/* allocate/move DMA resources for data buffer */
1342 	if ((bp != NULL) && (bp->b_bcount > 0)) {
1343 		if ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) == 0) {
1344 			if (scsa1394_cmd_buf_dma_alloc(sp, cmd, flags, callback,
1345 			    arg, bp) != DDI_SUCCESS) {
1346 				if (is_new) {
1347 					scsa1394_scsi_destroy_pkt(ap, pkt);
1348 				}
1349 				return (NULL);
1350 			}
1351 		} else {
1352 			if (scsa1394_cmd_buf_dma_move(sp, cmd) != DDI_SUCCESS) {
1353 				return (NULL);
1354 			}
1355 		}
1356 
1357 		ASSERT(cmd->sc_win_len > 0);
1358 		pkt->pkt_resid = bp->b_bcount - cmd->sc_win_len;
1359 	}
1360 
1361 	/*
1362 	 * kernel virtual address may be required for certain workarounds
1363 	 * and in case of B_PHYS or B_PAGEIO, bp_mapin() will get it for us
1364 	 */
1365 	if ((bp != NULL) && ((bp->b_flags & (B_PAGEIO | B_PHYS)) != 0) &&
1366 	    (bp->b_bcount < SCSA1394_MAPIN_SIZE_MAX) &&
1367 	    ((cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) == 0)) {
1368 		bp_mapin(bp);
1369 		cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_MAPIN;
1370 	}
1371 
1372 	return (pkt);
1373 }
1374 
1375 static void
scsa1394_scsi_destroy_pkt(struct scsi_address * ap,struct scsi_pkt * pkt)1376 scsa1394_scsi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt)
1377 {
1378 	scsa1394_state_t *sp = ADDR2STATE(ap);
1379 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1380 
1381 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1382 		scsa1394_cmd_buf_dma_free(sp, cmd);
1383 	}
1384 	if (cmd->sc_flags & SCSA1394_CMD_DMA_CDB_VALID) {
1385 		scsa1394_cmd_cdb_dma_free(sp, cmd);
1386 	}
1387 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1388 		bp_mapout(cmd->sc_bp);
1389 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1390 	}
1391 	if (cmd->sc_flags & SCSA1394_CMD_EXT) {
1392 		scsa1394_cmd_ext_free(sp, cmd);
1393 	}
1394 
1395 	kmem_cache_free(sp->s_cmd_cache, cmd);
1396 }
1397 
1398 static void
scsa1394_scsi_dmafree(struct scsi_address * ap,struct scsi_pkt * pkt)1399 scsa1394_scsi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt)
1400 {
1401 	scsa1394_state_t *sp = ADDR2STATE(ap);
1402 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1403 
1404 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_VALID) {
1405 		scsa1394_cmd_buf_dma_free(sp, cmd);
1406 	}
1407 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_MAPIN) {
1408 		bp_mapout(cmd->sc_bp);
1409 		cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_MAPIN;
1410 	}
1411 }
1412 
1413 /*ARGSUSED*/
1414 static int
scsa1394_cmd_cache_constructor(void * buf,void * cdrarg,int kf)1415 scsa1394_cmd_cache_constructor(void *buf, void *cdrarg, int kf)
1416 {
1417 	scsa1394_cmd_t	*cmd = buf;
1418 
1419 	bzero(buf, SCSA1394_CMD_SIZE);
1420 	cmd->sc_task.ts_drv_priv = cmd;
1421 
1422 	return (0);
1423 }
1424 
1425 /*ARGSUSED*/
1426 static void
scsa1394_cmd_cache_destructor(void * buf,void * cdrarg)1427 scsa1394_cmd_cache_destructor(void *buf, void *cdrarg)
1428 {
1429 }
1430 
1431 /*
1432  * allocate and deallocate external cmd space (ie. not part of scsa1394_cmd_t)
1433  * for non-standard length cdb, pkt_private, status areas
1434  */
1435 static int
scsa1394_cmd_ext_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int kf)1436 scsa1394_cmd_ext_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd, int kf)
1437 {
1438 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1439 	void		*buf;
1440 
1441 	if (cmd->sc_cdb_len > sizeof (cmd->sc_pkt_cdb)) {
1442 		if ((buf = kmem_zalloc(cmd->sc_cdb_len, kf)) == NULL) {
1443 			return (DDI_FAILURE);
1444 		}
1445 		pkt->pkt_cdbp = buf;
1446 		cmd->sc_flags |= SCSA1394_CMD_CDB_EXT;
1447 	}
1448 
1449 	if (cmd->sc_scb_len > sizeof (cmd->sc_scb)) {
1450 		if ((buf = kmem_zalloc(cmd->sc_scb_len, kf)) == NULL) {
1451 			scsa1394_cmd_ext_free(sp, cmd);
1452 			return (DDI_FAILURE);
1453 		}
1454 		pkt->pkt_scbp = buf;
1455 		cmd->sc_flags |= SCSA1394_CMD_SCB_EXT;
1456 	}
1457 
1458 	if (cmd->sc_priv_len > sizeof (cmd->sc_priv)) {
1459 		if ((buf = kmem_zalloc(cmd->sc_priv_len, kf)) == NULL) {
1460 			scsa1394_cmd_ext_free(sp, cmd);
1461 			return (DDI_FAILURE);
1462 		}
1463 		pkt->pkt_private = buf;
1464 		cmd->sc_flags |= SCSA1394_CMD_PRIV_EXT;
1465 	}
1466 
1467 	return (DDI_SUCCESS);
1468 }
1469 
1470 /*ARGSUSED*/
1471 static void
scsa1394_cmd_ext_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1472 scsa1394_cmd_ext_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1473 {
1474 	struct scsi_pkt	*pkt = cmd->sc_pkt;
1475 
1476 	if (cmd->sc_flags & SCSA1394_CMD_CDB_EXT) {
1477 		kmem_free(pkt->pkt_cdbp, cmd->sc_cdb_len);
1478 	}
1479 	if (cmd->sc_flags & SCSA1394_CMD_SCB_EXT) {
1480 		kmem_free(pkt->pkt_scbp, cmd->sc_scb_len);
1481 	}
1482 	if (cmd->sc_flags & SCSA1394_CMD_PRIV_EXT) {
1483 		kmem_free(pkt->pkt_private, cmd->sc_priv_len);
1484 	}
1485 	cmd->sc_flags &= ~SCSA1394_CMD_EXT;
1486 }
1487 
1488 /*ARGSUSED*/
1489 static int
scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int flags,int (* callback)(),caddr_t arg)1490 scsa1394_cmd_cdb_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1491     int flags, int (*callback)(), caddr_t arg)
1492 {
1493 	if (sbp2_task_orb_alloc(cmd->sc_lun->l_lun, &cmd->sc_task,
1494 	    sizeof (scsa1394_cmd_orb_t)) != SBP2_SUCCESS) {
1495 		return (DDI_FAILURE);
1496 	}
1497 
1498 	cmd->sc_flags |= SCSA1394_CMD_DMA_CDB_VALID;
1499 	return (DDI_SUCCESS);
1500 }
1501 
1502 /*ARGSUSED*/
1503 static void
scsa1394_cmd_cdb_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1504 scsa1394_cmd_cdb_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1505 {
1506 	sbp2_task_orb_free(cmd->sc_lun->l_lun, &cmd->sc_task);
1507 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_CDB_VALID;
1508 }
1509 
1510 /*
1511  * buffer resources
1512  */
1513 static int
scsa1394_cmd_buf_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int flags,int (* callback)(),caddr_t arg,struct buf * bp)1514 scsa1394_cmd_buf_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1515     int flags, int (*callback)(), caddr_t arg, struct buf *bp)
1516 {
1517 	scsa1394_lun_t	*lp = cmd->sc_lun;
1518 	int		kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP;
1519 	int		dma_flags;
1520 	ddi_dma_cookie_t dmac;
1521 	uint_t		ccount;
1522 	int		error;
1523 	int		ret;
1524 
1525 	cmd->sc_bp = bp;
1526 
1527 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_buf_dma_attr, callback,
1528 	    NULL, &cmd->sc_buf_dma_hdl)) != DDI_SUCCESS) {
1529 		bioerror(bp, 0);
1530 		return (DDI_FAILURE);
1531 	}
1532 
1533 	cmd->sc_flags &= ~SCSA1394_CMD_RDWR;
1534 	if (bp->b_flags & B_READ) {
1535 		dma_flags = DDI_DMA_READ;
1536 		cmd->sc_flags |= SCSA1394_CMD_READ;
1537 	} else {
1538 		dma_flags = DDI_DMA_WRITE;
1539 		cmd->sc_flags |= SCSA1394_CMD_WRITE;
1540 	}
1541 	if (flags & PKT_CONSISTENT) {
1542 		dma_flags |= DDI_DMA_CONSISTENT;
1543 	}
1544 	if (flags & PKT_DMA_PARTIAL) {
1545 		dma_flags |= DDI_DMA_PARTIAL;
1546 	}
1547 
1548 	ret = ddi_dma_buf_bind_handle(cmd->sc_buf_dma_hdl, bp, dma_flags,
1549 	    callback, arg, &dmac, &ccount);
1550 
1551 	switch (ret) {
1552 	case DDI_DMA_MAPPED:
1553 		cmd->sc_nwin = 1;
1554 		cmd->sc_curwin = 0;
1555 		cmd->sc_win_offset = 0;
1556 		cmd->sc_win_len = bp->b_bcount;
1557 		break;
1558 
1559 	case DDI_DMA_PARTIAL_MAP:
1560 		/* retrieve number of windows and first window cookie */
1561 		cmd->sc_curwin = 0;
1562 		if ((ddi_dma_numwin(cmd->sc_buf_dma_hdl, &cmd->sc_nwin) !=
1563 		    DDI_SUCCESS) ||
1564 		    (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1565 		    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1566 		    DDI_SUCCESS)) {
1567 			(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1568 			ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1569 			return (DDI_FAILURE);
1570 		}
1571 		lp->l_stat.stat_cmd_buf_dma_partial++;
1572 		break;
1573 
1574 	case DDI_DMA_NORESOURCES:
1575 		error = 0;
1576 		goto map_error;
1577 
1578 	case DDI_DMA_BADATTR:
1579 	case DDI_DMA_NOMAPPING:
1580 		error = EFAULT;
1581 		goto map_error;
1582 
1583 	default:
1584 		error = EINVAL;
1585 
1586 	map_error:
1587 		bioerror(bp, error);
1588 		lp->l_stat.stat_err_cmd_buf_dbind++;
1589 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1590 		return (DDI_FAILURE);
1591 	}
1592 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_BIND_VALID;
1593 
1594 	/*
1595 	 * setup page table if needed
1596 	 */
1597 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1598 	    (!sp->s_symbios ||
1599 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1600 		cmd->sc_buf_nsegs = 1;
1601 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1602 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1603 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1604 	} else {
1605 		/* break window into segments */
1606 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, kf) !=
1607 		    DDI_SUCCESS) {
1608 			scsa1394_cmd_buf_dma_free(sp, cmd);
1609 			bioerror(bp, 0);
1610 			return (DDI_FAILURE);
1611 		}
1612 
1613 		/* allocate DMA resources for page table */
1614 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, callback, arg,
1615 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1616 			scsa1394_cmd_buf_dma_free(sp, cmd);
1617 			bioerror(bp, 0);
1618 			return (DDI_FAILURE);
1619 		}
1620 	}
1621 
1622 	/* allocate 1394 addresses for segments */
1623 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1624 		scsa1394_cmd_buf_dma_free(sp, cmd);
1625 		bioerror(bp, 0);
1626 		return (DDI_FAILURE);
1627 	}
1628 
1629 	return (DDI_SUCCESS);
1630 }
1631 
1632 static void
scsa1394_cmd_buf_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1633 scsa1394_cmd_buf_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1634 {
1635 	scsa1394_cmd_buf_addr_free(sp, cmd);
1636 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1637 		scsa1394_cmd_pt_dma_free(sp, cmd);
1638 	}
1639 	scsa1394_cmd_seg_free(sp, cmd);
1640 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_BIND_VALID) {
1641 		(void) ddi_dma_unbind_handle(cmd->sc_buf_dma_hdl);
1642 		ddi_dma_free_handle(&cmd->sc_buf_dma_hdl);
1643 	}
1644 	cmd->sc_flags &= ~(SCSA1394_CMD_DMA_BUF_VALID | SCSA1394_CMD_RDWR);
1645 }
1646 
1647 /*
1648  * Break a set DMA cookies into segments suitable for SBP-2 page table.
1649  * This routine can reuse/reallocate segment array from previous calls.
1650  */
1651 static int
scsa1394_cmd_dmac2seg(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,ddi_dma_cookie_t * dmac,uint_t ccount,int kf)1652 scsa1394_cmd_dmac2seg(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1653     ddi_dma_cookie_t *dmac, uint_t ccount, int kf)
1654 {
1655 	scsa1394_lun_t	*lp = cmd->sc_lun;
1656 	int		i;
1657 	int		nsegs;
1658 	size_t		segsize_max;
1659 	size_t		dmac_resid;
1660 	uint32_t	dmac_addr;
1661 	scsa1394_cmd_seg_t *seg;
1662 
1663 	if (!sp->s_symbios) {
1664 		/*
1665 		 * Number of segments is unknown at this point. Start with
1666 		 * a reasonable estimate and grow it later if needed.
1667 		 */
1668 		nsegs = max(ccount, cmd->sc_win_len / SBP2_PT_SEGSIZE_MAX) * 2;
1669 		segsize_max = SBP2_PT_SEGSIZE_MAX;
1670 	} else {
1671 		/*
1672 		 * For Symbios workaround we know exactly the number of segments
1673 		 * Additional segment may be needed if buffer is not aligned.
1674 		 */
1675 		nsegs =
1676 		    howmany(cmd->sc_win_len, scsa1394_symbios_page_size) + 1;
1677 		segsize_max = scsa1394_symbios_page_size;
1678 	}
1679 
1680 	if (nsegs > cmd->sc_buf_nsegs_alloc) {
1681 		if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(cmd->sc_buf_seg,
1682 		    cmd->sc_buf_nsegs_alloc, nsegs,
1683 		    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1684 			cmd->sc_buf_nsegs_alloc = 0;
1685 			return (DDI_FAILURE);
1686 		}
1687 		cmd->sc_buf_nsegs_alloc = nsegs;
1688 	}
1689 
1690 	/* each cookie maps into one or more segments */
1691 	cmd->sc_buf_nsegs = 0;
1692 	i = ccount;
1693 	for (;;) {
1694 		dmac_resid = dmac->dmac_size;
1695 		dmac_addr = dmac->dmac_address;
1696 		while (dmac_resid > 0) {
1697 			/* grow array if needed */
1698 			if (cmd->sc_buf_nsegs >= cmd->sc_buf_nsegs_alloc) {
1699 				if ((cmd->sc_buf_seg = scsa1394_kmem_realloc(
1700 				    cmd->sc_buf_seg,
1701 				    cmd->sc_buf_nsegs_alloc,
1702 				    cmd->sc_buf_nsegs_alloc + ccount,
1703 				    sizeof (scsa1394_cmd_seg_t), kf)) == NULL) {
1704 					return (DDI_FAILURE);
1705 				}
1706 				cmd->sc_buf_nsegs_alloc += ccount;
1707 			}
1708 
1709 			seg = &cmd->sc_buf_seg[cmd->sc_buf_nsegs];
1710 			seg->ss_len = min(dmac_resid, segsize_max);
1711 			seg->ss_daddr = (uint64_t)dmac_addr;
1712 			dmac_addr += seg->ss_len;
1713 			dmac_resid -= seg->ss_len;
1714 			cmd->sc_buf_nsegs++;
1715 		}
1716 		ASSERT(dmac_resid == 0);
1717 
1718 		/* grab next cookie */
1719 		if (--i <= 0) {
1720 			break;
1721 		}
1722 		ddi_dma_nextcookie(cmd->sc_buf_dma_hdl, dmac);
1723 	}
1724 
1725 	if (cmd->sc_buf_nsegs > lp->l_stat.stat_cmd_buf_max_nsegs) {
1726 		lp->l_stat.stat_cmd_buf_max_nsegs = cmd->sc_buf_nsegs;
1727 	}
1728 
1729 	return (DDI_SUCCESS);
1730 }
1731 
1732 /*ARGSUSED*/
1733 static void
scsa1394_cmd_seg_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1734 scsa1394_cmd_seg_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1735 {
1736 	if (cmd->sc_buf_nsegs_alloc > 0) {
1737 		kmem_free(cmd->sc_buf_seg, cmd->sc_buf_nsegs_alloc *
1738 		    sizeof (scsa1394_cmd_seg_t));
1739 	}
1740 	cmd->sc_buf_seg = NULL;
1741 	cmd->sc_buf_nsegs = 0;
1742 	cmd->sc_buf_nsegs_alloc = 0;
1743 }
1744 
1745 static int
scsa1394_cmd_pt_dma_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd,int (* callback)(),caddr_t arg,int cnt)1746 scsa1394_cmd_pt_dma_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd,
1747     int (*callback)(), caddr_t arg, int cnt)
1748 {
1749 	scsa1394_lun_t	*lp = cmd->sc_lun;
1750 	size_t		len, rlen;
1751 	uint_t		ccount;
1752 	t1394_alloc_addr_t aa;
1753 	int		result;
1754 
1755 	/* allocate DMA memory for page table */
1756 	if ((ddi_dma_alloc_handle(sp->s_dip, &sp->s_pt_dma_attr,
1757 	    callback, NULL, &cmd->sc_pt_dma_hdl)) != DDI_SUCCESS) {
1758 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1759 		return (DDI_FAILURE);
1760 	}
1761 
1762 	cmd->sc_pt_ent_alloc = cnt;
1763 	len = cmd->sc_pt_ent_alloc * SBP2_PT_ENT_SIZE;
1764 	if (ddi_dma_mem_alloc(cmd->sc_pt_dma_hdl, len,
1765 	    &sp->s_attachinfo.acc_attr, DDI_DMA_CONSISTENT, callback, arg,
1766 	    &cmd->sc_pt_kaddr, &rlen, &cmd->sc_pt_acc_hdl) != DDI_SUCCESS) {
1767 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1768 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1769 		return (DDI_FAILURE);
1770 	}
1771 
1772 	if (ddi_dma_addr_bind_handle(cmd->sc_pt_dma_hdl, NULL,
1773 	    cmd->sc_pt_kaddr, len, DDI_DMA_READ | DDI_DMA_CONSISTENT,
1774 	    callback, arg, &cmd->sc_pt_dmac, &ccount) != DDI_DMA_MAPPED) {
1775 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1776 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1777 		lp->l_stat.stat_err_cmd_pt_dmem_alloc++;
1778 		return (DDI_FAILURE);
1779 	}
1780 	ASSERT(ccount == 1);	/* because dma_attr_sgllen is 1 */
1781 
1782 	/* allocate 1394 address for page table */
1783 	aa.aa_type = T1394_ADDR_FIXED;
1784 	aa.aa_length = len;
1785 	aa.aa_address = cmd->sc_pt_dmac.dmac_address;
1786 	aa.aa_evts.recv_read_request = NULL;
1787 	aa.aa_evts.recv_write_request = NULL;
1788 	aa.aa_evts.recv_lock_request = NULL;
1789 	aa.aa_arg = NULL;
1790 	aa.aa_kmem_bufp = NULL;
1791 	aa.aa_enable = T1394_ADDR_RDENBL;
1792 	if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) != DDI_SUCCESS) {
1793 		(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1794 		ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1795 		ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1796 		lp->l_stat.stat_err_cmd_pt_addr_alloc++;
1797 		return (DDI_FAILURE);
1798 	}
1799 	ASSERT(aa.aa_address != 0);
1800 	cmd->sc_pt_baddr = aa.aa_address;
1801 	cmd->sc_pt_addr_hdl = aa.aa_hdl;
1802 
1803 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_PT_VALID;
1804 
1805 	return (DDI_SUCCESS);
1806 }
1807 
1808 static void
scsa1394_cmd_pt_dma_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1809 scsa1394_cmd_pt_dma_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1810 {
1811 	(void) ddi_dma_unbind_handle(cmd->sc_pt_dma_hdl);
1812 	ddi_dma_mem_free(&cmd->sc_pt_acc_hdl);
1813 	ddi_dma_free_handle(&cmd->sc_pt_dma_hdl);
1814 	(void) t1394_free_addr(sp->s_t1394_hdl, &cmd->sc_pt_addr_hdl, 0);
1815 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_PT_VALID;
1816 }
1817 
1818 /*
1819  * allocate 1394 addresses for all buffer segments
1820  */
1821 static int
scsa1394_cmd_buf_addr_alloc(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1822 scsa1394_cmd_buf_addr_alloc(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1823 {
1824 	scsa1394_lun_t	*lp = cmd->sc_lun;
1825 	t1394_alloc_addr_t aa;
1826 	scsa1394_cmd_seg_t *seg;
1827 	int		result;
1828 	int		i;
1829 
1830 	aa.aa_type = T1394_ADDR_FIXED;
1831 	aa.aa_evts.recv_read_request = NULL;
1832 	aa.aa_evts.recv_write_request = NULL;
1833 	aa.aa_evts.recv_lock_request = NULL;
1834 	aa.aa_arg = NULL;
1835 	aa.aa_kmem_bufp = NULL;
1836 	if (cmd->sc_flags & SCSA1394_CMD_READ) {
1837 		aa.aa_enable = T1394_ADDR_RDENBL;
1838 	} else {
1839 		aa.aa_enable = T1394_ADDR_WRENBL;
1840 	}
1841 
1842 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1843 		seg = &cmd->sc_buf_seg[i];
1844 
1845 		/* segment bus address */
1846 		aa.aa_length = seg->ss_len;
1847 		aa.aa_address = seg->ss_daddr;
1848 
1849 		if (t1394_alloc_addr(sp->s_t1394_hdl, &aa, 0, &result) !=
1850 		    DDI_SUCCESS) {
1851 			lp->l_stat.stat_err_cmd_buf_addr_alloc++;
1852 			return (DDI_FAILURE);
1853 		}
1854 		ASSERT(aa.aa_address != 0);
1855 		seg->ss_baddr = aa.aa_address;
1856 		seg->ss_addr_hdl = aa.aa_hdl;
1857 	}
1858 
1859 	cmd->sc_flags |= SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1860 
1861 	return (DDI_SUCCESS);
1862 }
1863 
1864 static void
scsa1394_cmd_buf_addr_free(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1865 scsa1394_cmd_buf_addr_free(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1866 {
1867 	int		i;
1868 
1869 	for (i = 0; i < cmd->sc_buf_nsegs; i++) {
1870 		if (cmd->sc_buf_seg[i].ss_addr_hdl) {
1871 			(void) t1394_free_addr(sp->s_t1394_hdl,
1872 			    &cmd->sc_buf_seg[i].ss_addr_hdl, 0);
1873 		}
1874 	}
1875 	cmd->sc_flags &= ~SCSA1394_CMD_DMA_BUF_ADDR_VALID;
1876 }
1877 
1878 /*
1879  * move to next DMA window
1880  */
1881 static int
scsa1394_cmd_buf_dma_move(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)1882 scsa1394_cmd_buf_dma_move(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
1883 {
1884 	/* scsa1394_lun_t	*lp = cmd->sc_lun; */
1885 	ddi_dma_cookie_t dmac;
1886 	uint_t		ccount;
1887 
1888 	/* for small pkts, leave things where they are (says WDD) */
1889 	if ((cmd->sc_curwin == cmd->sc_nwin) && (cmd->sc_nwin == 1)) {
1890 		return (DDI_SUCCESS);
1891 	}
1892 	if (++cmd->sc_curwin >= cmd->sc_nwin) {
1893 		return (DDI_FAILURE);
1894 	}
1895 	if (ddi_dma_getwin(cmd->sc_buf_dma_hdl, cmd->sc_curwin,
1896 	    &cmd->sc_win_offset, &cmd->sc_win_len, &dmac, &ccount) !=
1897 	    DDI_SUCCESS) {
1898 		return (DDI_FAILURE);
1899 	}
1900 
1901 	scsa1394_cmd_buf_addr_free(sp, cmd);
1902 
1903 	/*
1904 	 * setup page table if needed
1905 	 */
1906 	if ((ccount == 1) && (dmac.dmac_size <= SBP2_PT_SEGSIZE_MAX) &&
1907 	    (!sp->s_symbios ||
1908 	    (dmac.dmac_size <= scsa1394_symbios_page_size))) {
1909 		/* but first, free old resources */
1910 		if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1911 			scsa1394_cmd_pt_dma_free(sp, cmd);
1912 		}
1913 		scsa1394_cmd_seg_free(sp, cmd);
1914 
1915 		cmd->sc_buf_nsegs = 1;
1916 		cmd->sc_buf_seg_mem.ss_len = dmac.dmac_size;
1917 		cmd->sc_buf_seg_mem.ss_daddr = dmac.dmac_address;
1918 		cmd->sc_buf_seg = &cmd->sc_buf_seg_mem;
1919 	} else {
1920 		/* break window into segments */
1921 		if (scsa1394_cmd_dmac2seg(sp, cmd, &dmac, ccount, KM_NOSLEEP) !=
1922 		    DDI_SUCCESS) {
1923 			return (DDI_FAILURE);
1924 		}
1925 
1926 		/* allocate DMA resources */
1927 		if (scsa1394_cmd_pt_dma_alloc(sp, cmd, NULL_FUNC, NULL,
1928 		    cmd->sc_buf_nsegs) != DDI_SUCCESS) {
1929 			return (DDI_FAILURE);
1930 		}
1931 	}
1932 
1933 	/* allocate 1394 addresses for segments */
1934 	if (scsa1394_cmd_buf_addr_alloc(sp, cmd) != DDI_SUCCESS) {
1935 		return (DDI_FAILURE);
1936 	}
1937 
1938 	return (DDI_SUCCESS);
1939 }
1940 
1941 /*
1942  *
1943  * --- pkt and data transfer routines
1944  *
1945  */
1946 static int
scsa1394_scsi_start(struct scsi_address * ap,struct scsi_pkt * pkt)1947 scsa1394_scsi_start(struct scsi_address *ap, struct scsi_pkt *pkt)
1948 {
1949 	scsa1394_state_t *sp = ADDR2STATE(ap);
1950 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
1951 	scsa1394_lun_t	*lp = cmd->sc_lun;
1952 	int		ret;
1953 
1954 	/*
1955 	 * since we don't support polled I/O, just accept the packet
1956 	 * so the rest of the file systems get synced properly
1957 	 */
1958 	if (ddi_in_panic()) {
1959 		scsa1394_prepare_pkt(sp, pkt);
1960 		return (TRAN_ACCEPT);
1961 	}
1962 
1963 	/* polling not supported yet */
1964 	if (pkt->pkt_flags & FLAG_NOINTR) {
1965 		return (TRAN_BADPKT);
1966 	}
1967 
1968 	mutex_enter(&sp->s_mutex);
1969 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
1970 		/*
1971 		 * If device is temporarily gone due to bus reset,
1972 		 * return busy to prevent prevent scary console messages.
1973 		 * If permanently gone, leave it to scsa1394_cmd_fake_comp().
1974 		 */
1975 		if (sp->s_dev_state == SCSA1394_DEV_BUS_RESET) {
1976 			mutex_exit(&sp->s_mutex);
1977 			return (TRAN_BUSY);
1978 		}
1979 	}
1980 	mutex_exit(&sp->s_mutex);
1981 
1982 	if ((ap->a_lun >= sp->s_nluns) ||
1983 	    (ap->a_lun != pkt->pkt_address.a_lun)) {
1984 		return (TRAN_BADPKT);
1985 	}
1986 
1987 	scsa1394_prepare_pkt(sp, pkt);
1988 
1989 	/* some commands may require fake completion */
1990 	if ((ret = scsa1394_cmd_fake_comp(sp, cmd)) == DDI_SUCCESS) {
1991 		return (TRAN_ACCEPT);
1992 	}
1993 
1994 	scsa1394_cmd_fill_cdb(lp, cmd);
1995 
1996 	if (cmd->sc_flags & SCSA1394_CMD_DMA_BUF_PT_VALID) {
1997 		scsa1394_sbp2_seg2pt(lp, cmd);
1998 	}
1999 
2000 	scsa1394_sbp2_cmd2orb(lp, cmd);		/* convert into ORB */
2001 
2002 	if ((ret = scsa1394_sbp2_start(lp, cmd)) != TRAN_BUSY) {
2003 		scsa1394_sbp2_nudge(lp);
2004 	}
2005 
2006 	return (ret);
2007 }
2008 
2009 /*ARGSUSED*/
2010 static void
scsa1394_prepare_pkt(scsa1394_state_t * sp,struct scsi_pkt * pkt)2011 scsa1394_prepare_pkt(scsa1394_state_t *sp, struct scsi_pkt *pkt)
2012 {
2013 	scsa1394_cmd_t	*cmd = PKT2CMD(pkt);
2014 
2015 	pkt->pkt_reason = CMD_CMPLT;
2016 	pkt->pkt_state = 0;
2017 	pkt->pkt_statistics = 0;
2018 	*(pkt->pkt_scbp) = STATUS_GOOD;
2019 
2020 	if (cmd) {
2021 		cmd->sc_timeout = pkt->pkt_time;
2022 
2023 		/* workarounds */
2024 		switch (pkt->pkt_cdbp[0]) {
2025 		/*
2026 		 * sd does START_STOP_UNIT during attach with a 200 sec timeout.
2027 		 * at this time devi_lock is held, prtconf will be stuck.
2028 		 * reduce timeout for the time being.
2029 		 */
2030 		case SCMD_START_STOP:
2031 			cmd->sc_timeout = min(cmd->sc_timeout,
2032 			    scsa1394_start_stop_timeout_max);
2033 			break;
2034 		default:
2035 			break;
2036 		}
2037 	}
2038 }
2039 
2040 static void
scsa1394_cmd_fill_cdb(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2041 scsa1394_cmd_fill_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2042 {
2043 	cmd->sc_cdb_actual_len = cmd->sc_cdb_len;
2044 
2045 	mutex_enter(&lp->l_mutex);
2046 
2047 	switch (lp->l_dtype_orig) {
2048 	case DTYPE_DIRECT:
2049 	case DTYPE_RODIRECT:
2050 	case DTYPE_OPTICAL:
2051 	case SCSA1394_DTYPE_RBC:
2052 		scsa1394_cmd_fill_cdb_rbc(lp, cmd);
2053 		break;
2054 	default:
2055 		scsa1394_cmd_fill_cdb_other(lp, cmd);
2056 		break;
2057 	}
2058 
2059 	mutex_exit(&lp->l_mutex);
2060 }
2061 
2062 static void
scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2063 scsa1394_cmd_fill_cdb_rbc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2064 {
2065 	scsa1394_state_t *sp = lp->l_sp;
2066 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2067 	int		lba, opcode;
2068 	struct buf	*bp = cmd->sc_bp;
2069 	size_t		len;
2070 	size_t		blk_size;
2071 	int		sz;
2072 
2073 	opcode = pkt->pkt_cdbp[0];
2074 	blk_size  = lp->l_lba_size;
2075 
2076 	switch (opcode) {
2077 	case SCMD_READ:
2078 		/* RBC only supports 10-byte read/write */
2079 		lba = SCSA1394_LBA_6BYTE(pkt);
2080 		len = SCSA1394_LEN_6BYTE(pkt);
2081 		opcode = SCMD_READ_G1;
2082 		cmd->sc_cdb_actual_len = CDB_GROUP1;
2083 		break;
2084 	case SCMD_WRITE:
2085 		lba = SCSA1394_LBA_6BYTE(pkt);
2086 		len = SCSA1394_LEN_6BYTE(pkt);
2087 		opcode = SCMD_WRITE_G1;
2088 		cmd->sc_cdb_actual_len = CDB_GROUP1;
2089 		break;
2090 	case SCMD_READ_G1:
2091 	case SCMD_READ_LONG:
2092 		lba = SCSA1394_LBA_10BYTE(pkt);
2093 		len = SCSA1394_LEN_10BYTE(pkt);
2094 		break;
2095 	case SCMD_WRITE_G1:
2096 	case SCMD_WRITE_LONG:
2097 		lba = SCSA1394_LBA_10BYTE(pkt);
2098 		len = SCSA1394_LEN_10BYTE(pkt);
2099 		if ((lp->l_dtype_orig == DTYPE_RODIRECT) &&
2100 		    (bp != NULL) && (len != 0)) {
2101 			sz = SCSA1394_CDRW_BLKSZ(bp->b_bcount, len);
2102 			if (SCSA1394_VALID_CDRW_BLKSZ(sz)) {
2103 				blk_size = sz;
2104 			}
2105 		}
2106 		break;
2107 	case SCMD_READ_CD:
2108 		lba = SCSA1394_LBA_10BYTE(pkt);
2109 		len = SCSA1394_LEN_READ_CD(pkt);
2110 		blk_size = scsa1394_cmd_read_cd_blk_size(pkt->pkt_cdbp[1] >> 2);
2111 		break;
2112 	case SCMD_READ_G5:
2113 		lba = SCSA1394_LBA_12BYTE(pkt);
2114 		len = SCSA1394_LEN_12BYTE(pkt);
2115 		break;
2116 	case SCMD_WRITE_G5:
2117 		lba = SCSA1394_LBA_12BYTE(pkt);
2118 		len = SCSA1394_LEN_12BYTE(pkt);
2119 		break;
2120 	default:
2121 		/* no special mapping for other commands */
2122 		scsa1394_cmd_fill_cdb_other(lp, cmd);
2123 		return;
2124 	}
2125 	cmd->sc_blk_size = blk_size;
2126 
2127 	/* limit xfer length for Symbios workaround */
2128 	if (sp->s_symbios && (len * blk_size > scsa1394_symbios_size_max)) {
2129 		cmd->sc_flags |= SCSA1394_CMD_SYMBIOS_BREAKUP;
2130 
2131 		cmd->sc_total_blks = cmd->sc_resid_blks = len;
2132 
2133 		len = scsa1394_symbios_size_max / blk_size;
2134 	}
2135 	cmd->sc_xfer_blks = len;
2136 	cmd->sc_xfer_bytes = len * blk_size;
2137 
2138 	/* finalize new CDB */
2139 	switch (pkt->pkt_cdbp[0]) {
2140 	case SCMD_READ:
2141 	case SCMD_WRITE:
2142 		/*
2143 		 * We rewrite READ/WRITE G0 commands as READ/WRITE G1.
2144 		 * Build new cdb from scatch.
2145 		 * The lba and length fields is updated below.
2146 		 */
2147 		bzero(cmd->sc_cdb, cmd->sc_cdb_actual_len);
2148 		break;
2149 	default:
2150 		/*
2151 		 * Copy the non lba/len fields.
2152 		 * The lba and length fields is updated below.
2153 		 */
2154 		bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_actual_len);
2155 		break;
2156 	}
2157 
2158 	cmd->sc_cdb[0] = (uchar_t)opcode;
2159 	scsa1394_cmd_fill_cdb_lba(cmd, lba);
2160 	switch (opcode) {
2161 	case SCMD_READ_CD:
2162 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2163 		break;
2164 	case SCMD_WRITE_G5:
2165 	case SCMD_READ_G5:
2166 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2167 		break;
2168 	default:
2169 		scsa1394_cmd_fill_cdb_len(cmd, len);
2170 		break;
2171 	}
2172 }
2173 
2174 /*ARGSUSED*/
2175 static void
scsa1394_cmd_fill_cdb_other(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2176 scsa1394_cmd_fill_cdb_other(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2177 {
2178 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2179 
2180 	cmd->sc_xfer_bytes = cmd->sc_win_len;
2181 	cmd->sc_xfer_blks = cmd->sc_xfer_bytes / lp->l_lba_size;
2182 	cmd->sc_total_blks = cmd->sc_xfer_blks;
2183 	cmd->sc_lba = 0;
2184 
2185 	bcopy(pkt->pkt_cdbp, cmd->sc_cdb, cmd->sc_cdb_len);
2186 }
2187 
2188 /*
2189  * fill up parts of CDB
2190  */
2191 static void
scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t * cmd,int len)2192 scsa1394_cmd_fill_cdb_len(scsa1394_cmd_t *cmd, int len)
2193 {
2194 	cmd->sc_cdb[7] = len >> 8;
2195 	cmd->sc_cdb[8] = (uchar_t)len;
2196 }
2197 
2198 static void
scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t * cmd,int lba)2199 scsa1394_cmd_fill_cdb_lba(scsa1394_cmd_t *cmd, int lba)
2200 {
2201 	cmd->sc_cdb[2] = lba >> 24;
2202 	cmd->sc_cdb[3] = lba >> 16;
2203 	cmd->sc_cdb[4] = lba >> 8;
2204 	cmd->sc_cdb[5] = (uchar_t)lba;
2205 	cmd->sc_lba = lba;
2206 }
2207 
2208 static void
scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t * cmd,int len)2209 scsa1394_cmd_fill_12byte_cdb_len(scsa1394_cmd_t *cmd, int len)
2210 {
2211 	cmd->sc_cdb[6] = len >> 24;
2212 	cmd->sc_cdb[7] = len >> 16;
2213 	cmd->sc_cdb[8] = len >> 8;
2214 	cmd->sc_cdb[9] = (uchar_t)len;
2215 }
2216 
2217 static void
scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t * cmd,int len)2218 scsa1394_cmd_fill_read_cd_cdb_len(scsa1394_cmd_t *cmd, int len)
2219 {
2220 	cmd->sc_cdb[6] = len >> 16;
2221 	cmd->sc_cdb[7] = len >> 8;
2222 	cmd->sc_cdb[8] = (uchar_t)len;
2223 }
2224 
2225 /*
2226  * For SCMD_READ_CD, figure out the block size based on expected sector type.
2227  * See MMC SCSI Specs section 6.1.15
2228  */
2229 static int
scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)2230 scsa1394_cmd_read_cd_blk_size(uchar_t expected_sector_type)
2231 {
2232 	int blk_size;
2233 
2234 	switch (expected_sector_type) {
2235 	case READ_CD_EST_CDDA:
2236 		blk_size = CDROM_BLK_2352;
2237 		break;
2238 	case READ_CD_EST_MODE2:
2239 		blk_size = CDROM_BLK_2336;
2240 		break;
2241 	case READ_CD_EST_MODE2FORM2:
2242 		blk_size = CDROM_BLK_2324;
2243 		break;
2244 	case READ_CD_EST_MODE2FORM1:
2245 	case READ_CD_EST_ALLTYPE:
2246 	case READ_CD_EST_MODE1:
2247 	default:
2248 		blk_size = CDROM_BLK_2048;
2249 	}
2250 
2251 	return (blk_size);
2252 }
2253 
2254 /*ARGSUSED*/
2255 static int
scsa1394_cmd_fake_mode_sense(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)2256 scsa1394_cmd_fake_mode_sense(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2257 {
2258 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2259 	struct scsi_arq_status *arqp = (struct scsi_arq_status *)pkt->pkt_scbp;
2260 	struct scsi_extended_sense *esp = &arqp->sts_sensedata;
2261 
2262 	*(pkt->pkt_scbp) = STATUS_CHECK;
2263 	*(uint8_t *)&arqp->sts_rqpkt_status = STATUS_GOOD;
2264 	arqp->sts_rqpkt_reason = CMD_CMPLT;
2265 	arqp->sts_rqpkt_resid = 0;
2266 	arqp->sts_rqpkt_state |= STATE_XFERRED_DATA;
2267 	arqp->sts_rqpkt_statistics = 0;
2268 
2269 	bzero(esp, sizeof (struct scsi_extended_sense));
2270 
2271 	esp->es_class = CLASS_EXTENDED_SENSE;
2272 
2273 	esp->es_key = KEY_ILLEGAL_REQUEST;
2274 
2275 	pkt->pkt_reason = CMD_CMPLT;
2276 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2277 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2278 
2279 	if (pkt->pkt_comp) {
2280 		(*pkt->pkt_comp)(pkt);
2281 	}
2282 	return (DDI_SUCCESS);
2283 }
2284 
2285 /*ARGSUSED*/
2286 static int
scsa1394_cmd_fake_inquiry(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)2287 scsa1394_cmd_fake_inquiry(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2288 {
2289 	scsa1394_lun_t	*lp = cmd->sc_lun;
2290 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2291 	struct scsi_inquiry *inq;
2292 
2293 	/* copy fabricated inquiry data */
2294 	inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2295 	bcopy(&lp->l_fake_inq, inq, sizeof (struct scsi_inquiry));
2296 
2297 	pkt->pkt_resid -= sizeof (struct scsi_inquiry);
2298 	pkt->pkt_reason = CMD_CMPLT;
2299 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2300 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2301 
2302 	if (pkt->pkt_comp) {
2303 		(*pkt->pkt_comp)(pkt);
2304 	}
2305 	return (DDI_SUCCESS);
2306 }
2307 
2308 /*
2309  * If command allows fake completion (without actually being transported),
2310  * call completion callback and return DDI_SUCCESS.
2311  * Otherwise return DDI_FAILURE.
2312  */
2313 static int
scsa1394_cmd_fake_comp(scsa1394_state_t * sp,scsa1394_cmd_t * cmd)2314 scsa1394_cmd_fake_comp(scsa1394_state_t *sp, scsa1394_cmd_t *cmd)
2315 {
2316 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2317 	scsa1394_lun_t	*lp = cmd->sc_lun;
2318 	int		ret = DDI_SUCCESS;
2319 
2320 	/*
2321 	 * agreement with sd in case of device hot removal
2322 	 * is to fake completion with CMD_DEV_GONE
2323 	 */
2324 	mutex_enter(&sp->s_mutex);
2325 	if (sp->s_dev_state != SCSA1394_DEV_ONLINE) {
2326 		mutex_exit(&sp->s_mutex);
2327 		pkt->pkt_reason = CMD_DEV_GONE;
2328 		if (pkt->pkt_comp) {
2329 			(*pkt->pkt_comp)(pkt);
2330 		}
2331 		return (DDI_SUCCESS);
2332 	}
2333 	mutex_exit(&sp->s_mutex);
2334 
2335 	mutex_enter(&lp->l_mutex);
2336 
2337 	switch (pkt->pkt_cdbp[0]) {
2338 	/*
2339 	 * RBC support for PRIN/PROUT is optional
2340 	 */
2341 	case SCMD_PRIN:
2342 	case SCMD_PROUT:
2343 		if (!scsa1394_wrka_fake_prin) {
2344 			ret = DDI_FAILURE;
2345 		}
2346 		break;
2347 	/*
2348 	 * Some fixed disks don't like doorlock cmd. And they don't need it.
2349 	 */
2350 	case SCMD_DOORLOCK:
2351 		if (lp->l_rmb_orig != 0) {
2352 			ret = DDI_FAILURE;
2353 		}
2354 		break;
2355 	case SCMD_TEST_UNIT_READY:
2356 		if (!lp->l_nosup_tur) {
2357 			ret = DDI_FAILURE;
2358 		}
2359 		break;
2360 	case SCMD_START_STOP:
2361 		if (!lp->l_nosup_start_stop) {
2362 			ret = DDI_FAILURE;
2363 		}
2364 		break;
2365 	case SCMD_INQUIRY:
2366 		if (!lp->l_nosup_inquiry) {
2367 			ret = DDI_FAILURE;
2368 		} else {
2369 			mutex_exit(&lp->l_mutex);
2370 			return (scsa1394_cmd_fake_inquiry(sp, cmd));
2371 		}
2372 		break;
2373 	case SCMD_MODE_SENSE:
2374 		if (!lp->l_mode_sense_fake) {
2375 			ret = DDI_FAILURE;
2376 		} else {
2377 			mutex_exit(&lp->l_mutex);
2378 			return (scsa1394_cmd_fake_mode_sense(sp, cmd));
2379 		}
2380 		break;
2381 	default:
2382 		ret = DDI_FAILURE;
2383 	}
2384 
2385 	mutex_exit(&lp->l_mutex);
2386 
2387 	if (ret != DDI_SUCCESS) {
2388 		return (ret);
2389 	}
2390 
2391 	ASSERT(*(pkt->pkt_scbp) == STATUS_GOOD);
2392 	ASSERT(pkt->pkt_reason == CMD_CMPLT);
2393 	pkt->pkt_state |= (STATE_GOT_BUS | STATE_GOT_TARGET | STATE_SENT_CMD |
2394 	    STATE_XFERRED_DATA | STATE_GOT_STATUS);
2395 
2396 	if (pkt->pkt_comp) {
2397 		(*pkt->pkt_comp)(pkt);
2398 	}
2399 	return (DDI_SUCCESS);
2400 }
2401 
2402 /*
2403  * Returns DDI_SUCCESS if next xfer setup successfully, DDI_FAILURE otherwise.
2404  */
2405 static int
scsa1394_cmd_setup_next_xfer(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2406 scsa1394_cmd_setup_next_xfer(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2407 {
2408 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2409 
2410 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2411 
2412 	cmd->sc_resid_blks -= cmd->sc_xfer_blks;
2413 	if (cmd->sc_resid_blks <= 0) {
2414 		pkt->pkt_resid = 0;
2415 		return (DDI_FAILURE);
2416 	}
2417 
2418 	scsa1394_cmd_adjust_cdb(lp, cmd);
2419 
2420 	scsa1394_sbp2_seg2pt(lp, cmd);
2421 
2422 	scsa1394_sbp2_cmd2orb(lp, cmd);
2423 
2424 	if (scsa1394_sbp2_start(lp, cmd) != TRAN_ACCEPT) {
2425 		pkt->pkt_resid = cmd->sc_resid_blks * cmd->sc_blk_size;
2426 		return (DDI_FAILURE);
2427 	}
2428 
2429 	return (DDI_SUCCESS);
2430 }
2431 
2432 /*
2433  * new lba = current lba + previous xfer len
2434  */
2435 /*ARGSUSED*/
2436 static void
scsa1394_cmd_adjust_cdb(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2437 scsa1394_cmd_adjust_cdb(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2438 {
2439 	int		len;
2440 
2441 	ASSERT(cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP);
2442 
2443 	cmd->sc_lba += cmd->sc_xfer_blks;
2444 	len = cmd->sc_resid_blks;
2445 
2446 	/* limit xfer length for Symbios workaround */
2447 	if (len * cmd->sc_blk_size > scsa1394_symbios_size_max) {
2448 		len = scsa1394_symbios_size_max / cmd->sc_blk_size;
2449 	}
2450 
2451 	switch (cmd->sc_cdb[0]) {
2452 	case SCMD_READ_CD:
2453 		scsa1394_cmd_fill_read_cd_cdb_len(cmd, len);
2454 		break;
2455 	case SCMD_WRITE_G5:
2456 	case SCMD_READ_G5:
2457 		scsa1394_cmd_fill_12byte_cdb_len(cmd, len);
2458 		break;
2459 	case SCMD_WRITE_G1:
2460 	case SCMD_WRITE_LONG:
2461 	default:
2462 		scsa1394_cmd_fill_cdb_len(cmd, len);
2463 	}
2464 
2465 	scsa1394_cmd_fill_cdb_lba(cmd, cmd->sc_lba);
2466 
2467 	cmd->sc_xfer_blks = len;
2468 	cmd->sc_xfer_bytes = len * cmd->sc_blk_size;
2469 }
2470 
2471 void
scsa1394_cmd_status_proc(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2472 scsa1394_cmd_status_proc(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2473 {
2474 	struct scsi_pkt		*pkt = CMD2PKT(cmd);
2475 
2476 	/* next iteration of partial xfer? */
2477 	if ((pkt->pkt_reason == CMD_CMPLT) &&
2478 	    (cmd->sc_flags & SCSA1394_CMD_SYMBIOS_BREAKUP)) {
2479 		if (scsa1394_cmd_setup_next_xfer(lp, cmd) == DDI_SUCCESS) {
2480 			return;
2481 		}
2482 	}
2483 	cmd->sc_flags &= ~SCSA1394_CMD_SYMBIOS_BREAKUP;
2484 
2485 	/* apply workarounds */
2486 	if (pkt->pkt_reason == CMD_CMPLT) {
2487 		scsa1394_cmd_status_wrka(lp, cmd);
2488 	}
2489 
2490 	mutex_enter(&lp->l_mutex);
2491 
2492 	/* mode sense workaround */
2493 	if (pkt->pkt_cdbp[0] == SCMD_MODE_SENSE) {
2494 		if (pkt->pkt_reason == CMD_CMPLT) {
2495 			lp->l_mode_sense_fail_cnt = 0;
2496 		} else if (++lp->l_mode_sense_fail_cnt >=
2497 		    scsa1394_mode_sense_fail_max) {
2498 			lp->l_mode_sense_fake = B_TRUE;
2499 		}
2500 	} else {
2501 		lp->l_mode_sense_fail_cnt = 0;
2502 	}
2503 
2504 	mutex_exit(&lp->l_mutex);
2505 
2506 	if (pkt->pkt_comp) {
2507 		(*pkt->pkt_comp)(pkt);
2508 	}
2509 }
2510 
2511 static void
scsa1394_cmd_status_wrka(scsa1394_lun_t * lp,scsa1394_cmd_t * cmd)2512 scsa1394_cmd_status_wrka(scsa1394_lun_t *lp, scsa1394_cmd_t *cmd)
2513 {
2514 	struct scsi_pkt	*pkt = CMD2PKT(cmd);
2515 
2516 	mutex_enter(&lp->l_mutex);
2517 
2518 	switch (pkt->pkt_cdbp[0]) {
2519 	case SCMD_INQUIRY: {
2520 		struct scsi_inquiry *inq;
2521 
2522 		inq = (struct scsi_inquiry *)cmd->sc_bp->b_un.b_addr;
2523 
2524 		/* change dtype RBC to DIRECT, sd doesn't support RBC */
2525 		lp->l_dtype_orig = inq->inq_dtype;
2526 		if ((inq->inq_dtype == SCSA1394_DTYPE_RBC) &&
2527 		    scsa1394_wrka_rbc2direct) {
2528 			inq->inq_dtype = DTYPE_DIRECT;
2529 		}
2530 
2531 		/* force RMB to 1 */
2532 		lp->l_rmb_orig = inq->inq_rmb;
2533 		if (scsa1394_wrka_fake_rmb) {
2534 			inq->inq_rmb = 1;
2535 		}
2536 		break;
2537 	}
2538 	case SCMD_READ_CAPACITY: {
2539 		uint32_t	*capacity_buf;
2540 
2541 		capacity_buf = (uint32_t *)cmd->sc_bp->b_un.b_addr;
2542 
2543 		if (lp->l_dtype_orig != DTYPE_RODIRECT) {
2544 			lp->l_lba_size = min(BE_32(capacity_buf[1]), DEV_BSIZE);
2545 			if (lp->l_lba_size == 0) {
2546 				cmn_err(CE_WARN, "zero LBA size reported, "
2547 				    "possibly broken device");
2548 				lp->l_lba_size = DEV_BSIZE;
2549 			}
2550 		} else {
2551 			lp->l_lba_size = 2048;
2552 		}
2553 	}
2554 	default:
2555 		break;
2556 	}
2557 
2558 	mutex_exit(&lp->l_mutex);
2559 }
2560 
2561 /*
2562  * --- thread management
2563  *
2564  * dispatch a thread
2565  */
2566 int
scsa1394_thr_dispatch(scsa1394_thread_t * thr)2567 scsa1394_thr_dispatch(scsa1394_thread_t *thr)
2568 {
2569 	scsa1394_lun_t		*lp = thr->thr_lun;
2570 	scsa1394_state_t	*sp = lp->l_sp;
2571 	int			ret;
2572 
2573 	ASSERT(mutex_owned(&lp->l_mutex));
2574 	ASSERT(thr->thr_state == SCSA1394_THR_INIT);
2575 
2576 	thr->thr_state = SCSA1394_THR_RUN;
2577 
2578 	ret = ddi_taskq_dispatch(sp->s_taskq, thr->thr_func, thr->thr_arg,
2579 	    KM_SLEEP);
2580 	return (ret);
2581 }
2582 
2583 /*
2584  * cancel thread
2585  */
2586 void
scsa1394_thr_cancel(scsa1394_thread_t * thr)2587 scsa1394_thr_cancel(scsa1394_thread_t *thr)
2588 {
2589 	scsa1394_lun_t		*lp = thr->thr_lun;
2590 
2591 	ASSERT(mutex_owned(&lp->l_mutex));
2592 
2593 	thr->thr_req |= SCSA1394_THREQ_EXIT;
2594 	cv_signal(&thr->thr_cv);
2595 
2596 	/* wait until the thread actually exits */
2597 	do {
2598 		if (cv_wait_sig(&thr->thr_cv, &lp->l_mutex) == 0) {
2599 			break;
2600 		}
2601 	} while (thr->thr_state != SCSA1394_THR_EXIT);
2602 }
2603 
2604 /*
2605  * wake thread
2606  */
2607 void
scsa1394_thr_wake(scsa1394_thread_t * thr,int req)2608 scsa1394_thr_wake(scsa1394_thread_t *thr, int req)
2609 {
2610 	scsa1394_lun_t		*lp = thr->thr_lun;
2611 
2612 	ASSERT(mutex_owned(&lp->l_mutex));
2613 
2614 	thr->thr_req |= req;
2615 	cv_signal(&thr->thr_cv);
2616 }
2617 
2618 void
scsa1394_thr_clear_req(scsa1394_thread_t * thr,int mask)2619 scsa1394_thr_clear_req(scsa1394_thread_t *thr, int mask)
2620 {
2621 	scsa1394_lun_t		*lp = thr->thr_lun;
2622 
2623 	mutex_enter(&lp->l_mutex);
2624 	thr->thr_req &= ~mask;
2625 	mutex_exit(&lp->l_mutex);
2626 }
2627 
2628 /*
2629  *
2630  * --- other routines
2631  *
2632  */
2633 static boolean_t
scsa1394_is_my_child(dev_info_t * dip)2634 scsa1394_is_my_child(dev_info_t *dip)
2635 {
2636 	return ((dip != NULL) && (ddi_prop_exists(DDI_DEV_T_ANY, dip,
2637 	    DDI_PROP_DONTPASS, "scsa1394") == 1));
2638 }
2639 
2640 boolean_t
scsa1394_dev_is_online(scsa1394_state_t * sp)2641 scsa1394_dev_is_online(scsa1394_state_t *sp)
2642 {
2643 	boolean_t	ret;
2644 
2645 	mutex_enter(&sp->s_mutex);
2646 	ret = (sp->s_dev_state == SCSA1394_DEV_ONLINE);
2647 	mutex_exit(&sp->s_mutex);
2648 
2649 	return (ret);
2650 }
2651 
2652 static void *
scsa1394_kmem_realloc(void * old_buf,int old_size,int new_size,size_t elsize,int kf)2653 scsa1394_kmem_realloc(void *old_buf, int old_size, int new_size, size_t elsize,
2654     int kf)
2655 {
2656 	void	*new_buf;
2657 
2658 	new_buf = kmem_zalloc(new_size * elsize, kf);
2659 
2660 	if (old_size > 0) {
2661 		if (new_buf != NULL) {
2662 			bcopy(old_buf, new_buf, old_size * elsize);
2663 		}
2664 		kmem_free(old_buf, old_size * elsize);
2665 	}
2666 
2667 	return (new_buf);
2668 }
2669