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