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