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