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 /*
23 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /*
27 * Direct Attached Disk
28 */
29
30 #include <sys/file.h>
31 #include <sys/scsi/scsi.h>
32 #include <sys/var.h>
33 #include <sys/proc.h>
34 #include <sys/dktp/cm.h>
35 #include <sys/vtoc.h>
36 #include <sys/dkio.h>
37 #include <sys/policy.h>
38 #include <sys/priv.h>
39
40 #include <sys/dktp/dadev.h>
41 #include <sys/dktp/fctypes.h>
42 #include <sys/dktp/flowctrl.h>
43 #include <sys/dktp/tgcom.h>
44 #include <sys/dktp/tgdk.h>
45 #include <sys/dktp/bbh.h>
46 #include <sys/dktp/dadkio.h>
47 #include <sys/dktp/dadk.h>
48 #include <sys/cdio.h>
49
50 /*
51 * Local Function Prototypes
52 */
53 static void dadk_restart(void *pktp);
54 static void dadk_pktcb(struct cmpkt *pktp);
55 static void dadk_iodone(struct buf *bp);
56 static void dadk_polldone(struct buf *bp);
57 static void dadk_setcap(struct dadk *dadkp);
58 static void dadk_create_errstats(struct dadk *dadkp, int instance);
59 static void dadk_destroy_errstats(struct dadk *dadkp);
60
61 static int dadk_chkerr(struct cmpkt *pktp);
62 static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp);
63 static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp);
64 static int dadk_ioretry(struct cmpkt *pktp, int action);
65
66 static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp,
67 struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t),
68 caddr_t arg);
69
70 static int dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t),
71 caddr_t arg);
72 static void dadk_transport(opaque_t com_data, struct buf *bp);
73 static int dadk_ctl_ioctl(struct dadk *, uint32_t, uintptr_t, int);
74
75 struct tgcom_objops dadk_com_ops = {
76 nodev,
77 nodev,
78 dadk_pkt,
79 dadk_transport,
80 0, 0
81 };
82
83 /*
84 * architecture dependent allocation restrictions for dadk_iob_alloc(). For
85 * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen
86 * to dadk_sgl_size during _init().
87 */
88 #if defined(__sparc)
89 static ddi_dma_attr_t dadk_alloc_attr = {
90 DMA_ATTR_V0, /* version number */
91 0x0, /* lowest usable address */
92 0xFFFFFFFFull, /* high DMA address range */
93 0xFFFFFFFFull, /* DMA counter register */
94 1, /* DMA address alignment */
95 1, /* DMA burstsizes */
96 1, /* min effective DMA size */
97 0xFFFFFFFFull, /* max DMA xfer size */
98 0xFFFFFFFFull, /* segment boundary */
99 1, /* s/g list length */
100 512, /* granularity of device */
101 0, /* DMA transfer flags */
102 };
103 #elif defined(__x86)
104 static ddi_dma_attr_t dadk_alloc_attr = {
105 DMA_ATTR_V0, /* version number */
106 0x0, /* lowest usable address */
107 0x0, /* high DMA address range [set in _init()] */
108 0xFFFFull, /* DMA counter register */
109 512, /* DMA address alignment */
110 1, /* DMA burstsizes */
111 1, /* min effective DMA size */
112 0xFFFFFFFFull, /* max DMA xfer size */
113 0xFFFFFFFFull, /* segment boundary */
114 0, /* s/g list length [set in _init()] */
115 512, /* granularity of device */
116 0, /* DMA transfer flags */
117 };
118
119 uint64_t dadk_max_phys_addr = 0xFFFFFFFFull;
120 int dadk_sgl_size = 0xFF;
121 #endif
122
123 static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags,
124 int silent);
125 static void dadk_rmb_iodone(struct buf *bp);
126
127 static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp,
128 dev_t dev, enum uio_seg dataspace, int rw);
129 static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp,
130 struct buf *bp);
131 static void dadkmin(struct buf *bp);
132 static int dadk_dk_strategy(struct buf *bp);
133 static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp);
134
135 struct tgdk_objops dadk_ops = {
136 dadk_init,
137 dadk_free,
138 dadk_probe,
139 dadk_attach,
140 dadk_open,
141 dadk_close,
142 dadk_ioctl,
143 dadk_strategy,
144 dadk_setgeom,
145 dadk_getgeom,
146 dadk_iob_alloc,
147 dadk_iob_free,
148 dadk_iob_htoc,
149 dadk_iob_xfer,
150 dadk_dump,
151 dadk_getphygeom,
152 dadk_set_bbhobj,
153 dadk_check_media,
154 dadk_inquiry,
155 dadk_cleanup,
156 0
157 };
158
159 /*
160 * Local static data
161 */
162
163 #ifdef DADK_DEBUG
164 #define DENT 0x0001
165 #define DERR 0x0002
166 #define DIO 0x0004
167 #define DGEOM 0x0010
168 #define DSTATE 0x0020
169 static int dadk_debug = DGEOM;
170
171 #endif /* DADK_DEBUG */
172
173 static int dadk_check_media_time = 3000000; /* 3 Second State Check */
174 static int dadk_dk_maxphys = 0x80000;
175
176 static char *dadk_cmds[] = {
177 "\000Unknown", /* unknown */
178 "\001read sector", /* DCMD_READ 1 */
179 "\002write sector", /* DCMD_WRITE 2 */
180 "\003format track", /* DCMD_FMTTRK 3 */
181 "\004format whole drive", /* DCMD_FMTDRV 4 */
182 "\005recalibrate", /* DCMD_RECAL 5 */
183 "\006seek sector", /* DCMD_SEEK 6 */
184 "\007read verify", /* DCMD_RDVER 7 */
185 "\010read defect list", /* DCMD_GETDEF 8 */
186 "\011lock door", /* DCMD_LOCK 9 */
187 "\012unlock door", /* DCMD_UNLOCK 10 */
188 "\013start motor", /* DCMD_START_MOTOR 11 */
189 "\014stop motor", /* DCMD_STOP_MOTOR 12 */
190 "\015eject", /* DCMD_EJECT 13 */
191 "\016update geometry", /* DCMD_UPDATE_GEOM 14 */
192 "\017get state", /* DCMD_GET_STATE 15 */
193 "\020cdrom pause", /* DCMD_PAUSE 16 */
194 "\021cdrom resume", /* DCMD_RESUME 17 */
195 "\022cdrom play track index", /* DCMD_PLAYTRKIND 18 */
196 "\023cdrom play msf", /* DCMD_PLAYMSF 19 */
197 "\024cdrom sub channel", /* DCMD_SUBCHNL 20 */
198 "\025cdrom read mode 1", /* DCMD_READMODE1 21 */
199 "\026cdrom read toc header", /* DCMD_READTOCHDR 22 */
200 "\027cdrom read toc entry", /* DCMD_READTOCENT 23 */
201 "\030cdrom read offset", /* DCMD_READOFFSET 24 */
202 "\031cdrom read mode 2", /* DCMD_READMODE2 25 */
203 "\032cdrom volume control", /* DCMD_VOLCTRL 26 */
204 "\033flush cache", /* DCMD_FLUSH_CACHE 27 */
205 NULL
206 };
207
208 static char *dadk_sense[] = {
209 "\000Success", /* DERR_SUCCESS */
210 "\001address mark not found", /* DERR_AMNF */
211 "\002track 0 not found", /* DERR_TKONF */
212 "\003aborted command", /* DERR_ABORT */
213 "\004write fault", /* DERR_DWF */
214 "\005ID not found", /* DERR_IDNF */
215 "\006drive busy", /* DERR_BUSY */
216 "\007uncorrectable data error", /* DERR_UNC */
217 "\010bad block detected", /* DERR_BBK */
218 "\011invalid command", /* DERR_INVCDB */
219 "\012device hard error", /* DERR_HARD */
220 "\013illegal length indicated", /* DERR_ILI */
221 "\014end of media", /* DERR_EOM */
222 "\015media change requested", /* DERR_MCR */
223 "\016recovered from error", /* DERR_RECOVER */
224 "\017device not ready", /* DERR_NOTREADY */
225 "\020medium error", /* DERR_MEDIUM */
226 "\021hardware error", /* DERR_HW */
227 "\022illegal request", /* DERR_ILL */
228 "\023unit attention", /* DERR_UNIT_ATTN */
229 "\024data protection", /* DERR_DATA_PROT */
230 "\025miscompare", /* DERR_MISCOMPARE */
231 "\026ICRC error during UDMA", /* DERR_ICRC */
232 "\027reserved", /* DERR_RESV */
233 NULL
234 };
235
236 static char *dadk_name = "Disk";
237
238 /*
239 * This is the loadable module wrapper
240 */
241 #include <sys/modctl.h>
242
243 extern struct mod_ops mod_miscops;
244
245 static struct modlmisc modlmisc = {
246 &mod_miscops, /* Type of module */
247 "Direct Attached Disk"
248 };
249
250 static struct modlinkage modlinkage = {
251 MODREV_1, (void *)&modlmisc, NULL
252 };
253
254 int
_init(void)255 _init(void)
256 {
257 #ifdef DADK_DEBUG
258 if (dadk_debug & DENT)
259 PRF("dadk_init: call\n");
260 #endif
261
262 #if defined(__x86)
263 /* set the max physical address for iob allocs on x86 */
264 dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr;
265
266 /*
267 * set the sgllen for iob allocs on x86. If this is set less than
268 * the number of pages the buffer will take (taking into account
269 * alignment), it would force the allocator to try and allocate
270 * contiguous pages.
271 */
272 dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size;
273 #endif
274
275 return (mod_install(&modlinkage));
276 }
277
278 int
_fini(void)279 _fini(void)
280 {
281 #ifdef DADK_DEBUG
282 if (dadk_debug & DENT)
283 PRF("dadk_fini: call\n");
284 #endif
285
286 return (mod_remove(&modlinkage));
287 }
288
289 int
_info(struct modinfo * modinfop)290 _info(struct modinfo *modinfop)
291 {
292 return (mod_info(&modlinkage, modinfop));
293 }
294
295 struct tgdk_obj *
dadk_create()296 dadk_create()
297 {
298 struct tgdk_obj *dkobjp;
299 struct dadk *dadkp;
300
301 dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP);
302 if (!dkobjp)
303 return (NULL);
304 dadkp = (struct dadk *)(dkobjp+1);
305
306 dkobjp->tg_ops = (struct tgdk_objops *)&dadk_ops;
307 dkobjp->tg_data = (opaque_t)dadkp;
308 dkobjp->tg_ext = &(dkobjp->tg_extblk);
309 dadkp->dad_extp = &(dkobjp->tg_extblk);
310
311 #ifdef DADK_DEBUG
312 if (dadk_debug & DENT)
313 PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp);
314 #endif
315 return (dkobjp);
316 }
317
318 int
dadk_init(opaque_t objp,opaque_t devp,opaque_t flcobjp,opaque_t queobjp,opaque_t bbhobjp,void * lkarg)319 dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp,
320 opaque_t bbhobjp, void *lkarg)
321 {
322 struct dadk *dadkp = (struct dadk *)objp;
323 struct scsi_device *sdevp = (struct scsi_device *)devp;
324
325 dadkp->dad_sd = devp;
326 dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran;
327 sdevp->sd_private = (caddr_t)dadkp;
328
329 /* initialize the communication object */
330 dadkp->dad_com.com_data = (opaque_t)dadkp;
331 dadkp->dad_com.com_ops = &dadk_com_ops;
332
333 dadkp->dad_bbhobjp = bbhobjp;
334 BBH_INIT(bbhobjp);
335
336 dadkp->dad_flcobjp = flcobjp;
337 mutex_init(&dadkp->dad_cmd_mutex, NULL, MUTEX_DRIVER, NULL);
338 dadkp->dad_cmd_count = 0;
339 return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg));
340 }
341
342 int
dadk_free(struct tgdk_obj * dkobjp)343 dadk_free(struct tgdk_obj *dkobjp)
344 {
345 TGDK_CLEANUP(dkobjp);
346 kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk)));
347
348 return (DDI_SUCCESS);
349 }
350
351 void
dadk_cleanup(struct tgdk_obj * dkobjp)352 dadk_cleanup(struct tgdk_obj *dkobjp)
353 {
354 struct dadk *dadkp;
355
356 dadkp = (struct dadk *)(dkobjp->tg_data);
357 if (dadkp->dad_sd)
358 dadkp->dad_sd->sd_private = NULL;
359 if (dadkp->dad_bbhobjp) {
360 BBH_FREE(dadkp->dad_bbhobjp);
361 dadkp->dad_bbhobjp = NULL;
362 }
363 if (dadkp->dad_flcobjp) {
364 FLC_FREE(dadkp->dad_flcobjp);
365 dadkp->dad_flcobjp = NULL;
366 }
367 mutex_destroy(&dadkp->dad_cmd_mutex);
368 }
369
370 /* ARGSUSED */
371 int
dadk_probe(opaque_t objp,int kmsflg)372 dadk_probe(opaque_t objp, int kmsflg)
373 {
374 struct dadk *dadkp = (struct dadk *)objp;
375 struct scsi_device *devp;
376 char name[80];
377
378 devp = dadkp->dad_sd;
379 if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) ||
380 (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) {
381 return (DDI_PROBE_FAILURE);
382 }
383
384 switch (devp->sd_inq->inq_dtype) {
385 case DTYPE_DIRECT:
386 dadkp->dad_ctype = DKC_DIRECT;
387 dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK;
388 dadkp->dad_extp->tg_ctype = DKC_DIRECT;
389 break;
390 case DTYPE_RODIRECT: /* eg cdrom */
391 dadkp->dad_ctype = DKC_CDROM;
392 dadkp->dad_extp->tg_rdonly = 1;
393 dadkp->dad_rdonly = 1;
394 dadkp->dad_cdrom = 1;
395 dadkp->dad_extp->tg_nodetype = DDI_NT_CD;
396 dadkp->dad_extp->tg_ctype = DKC_CDROM;
397 break;
398 case DTYPE_WORM:
399 case DTYPE_OPTICAL:
400 default:
401 return (DDI_PROBE_FAILURE);
402 }
403
404 dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb;
405
406 dadkp->dad_secshf = SCTRSHFT;
407 dadkp->dad_blkshf = 0;
408
409 /* display the device name */
410 (void) strcpy(name, "Vendor '");
411 gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]);
412 (void) strcat(name, "' Product '");
413 gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]);
414 (void) strcat(name, "'");
415 gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name);
416
417 return (DDI_PROBE_SUCCESS);
418 }
419
420
421 /* ARGSUSED */
422 int
dadk_attach(opaque_t objp)423 dadk_attach(opaque_t objp)
424 {
425 return (DDI_SUCCESS);
426 }
427
428 int
dadk_set_bbhobj(opaque_t objp,opaque_t bbhobjp)429 dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp)
430 {
431 struct dadk *dadkp = (struct dadk *)objp;
432 /* free the old bbh object */
433 if (dadkp->dad_bbhobjp)
434 BBH_FREE(dadkp->dad_bbhobjp);
435
436 /* initialize the new bbh object */
437 dadkp->dad_bbhobjp = bbhobjp;
438 BBH_INIT(bbhobjp);
439
440 return (DDI_SUCCESS);
441 }
442
443 /* ARGSUSED */
444 int
dadk_open(opaque_t objp,int flag)445 dadk_open(opaque_t objp, int flag)
446 {
447 struct dadk *dadkp = (struct dadk *)objp;
448 int error;
449 int wce;
450
451 if (!dadkp->dad_rmb) {
452 if (dadkp->dad_phyg.g_cap) {
453 FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
454 ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
455 return (DDI_SUCCESS);
456 }
457 } else {
458 mutex_enter(&dadkp->dad_mutex);
459 dadkp->dad_iostate = DKIO_NONE;
460 cv_broadcast(&dadkp->dad_state_cv);
461 mutex_exit(&dadkp->dad_mutex);
462
463 if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0,
464 DADK_SILENT) ||
465 dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) ||
466 dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0,
467 DADK_SILENT)) {
468 return (DDI_FAILURE);
469 }
470
471 mutex_enter(&dadkp->dad_mutex);
472 dadkp->dad_iostate = DKIO_INSERTED;
473 cv_broadcast(&dadkp->dad_state_cv);
474 mutex_exit(&dadkp->dad_mutex);
475 }
476
477 /*
478 * get write cache enable state
479 * If there is an error, must assume that write cache
480 * is enabled.
481 * NOTE: Since there is currently no Solaris mechanism to
482 * change the state of the Write Cache Enable feature,
483 * this code just checks the value of the WCE bit
484 * obtained at device init time. If a mechanism
485 * is added to the driver to change WCE, dad_wce
486 * must be updated appropriately.
487 */
488 error = dadk_ctl_ioctl(dadkp, DIOCTL_GETWCE,
489 (uintptr_t)&wce, FKIOCTL | FNATIVE);
490 mutex_enter(&dadkp->dad_mutex);
491 dadkp->dad_wce = (error != 0) || (wce != 0);
492 mutex_exit(&dadkp->dad_mutex);
493
494 /* logical disk geometry */
495 (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETGEOM,
496 (uintptr_t)&dadkp->dad_logg, FKIOCTL | FNATIVE);
497 if (dadkp->dad_logg.g_cap == 0)
498 return (DDI_FAILURE);
499
500 /* get physical disk geometry */
501 (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETPHYGEOM,
502 (uintptr_t)&dadkp->dad_phyg, FKIOCTL | FNATIVE);
503 if (dadkp->dad_phyg.g_cap == 0)
504 return (DDI_FAILURE);
505
506 dadk_setcap(dadkp);
507
508 dadk_create_errstats(dadkp,
509 ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
510
511 /* start profiling */
512 FLC_START_KSTAT(dadkp->dad_flcobjp, "disk",
513 ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp)));
514
515 return (DDI_SUCCESS);
516 }
517
518 static void
dadk_setcap(struct dadk * dadkp)519 dadk_setcap(struct dadk *dadkp)
520 {
521 int totsize;
522 int i;
523
524 totsize = dadkp->dad_phyg.g_secsiz;
525
526 if (totsize == 0) {
527 if (dadkp->dad_cdrom) {
528 totsize = 2048;
529 } else {
530 totsize = NBPSCTR;
531 }
532 } else {
533 /* Round down sector size to multiple of 512B */
534 totsize &= ~(NBPSCTR-1);
535 }
536 dadkp->dad_phyg.g_secsiz = totsize;
537
538 /* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */
539 totsize >>= SCTRSHFT;
540 for (i = 0; totsize != 1; i++, totsize >>= 1)
541 ;
542 dadkp->dad_blkshf = i;
543 dadkp->dad_secshf = i + SCTRSHFT;
544 }
545
546
547 static void
dadk_create_errstats(struct dadk * dadkp,int instance)548 dadk_create_errstats(struct dadk *dadkp, int instance)
549 {
550 dadk_errstats_t *dep;
551 char kstatname[KSTAT_STRLEN];
552 dadk_ioc_string_t dadk_ioc_string;
553
554 if (dadkp->dad_errstats)
555 return;
556
557 (void) sprintf(kstatname, "cmdk%d,error", instance);
558 dadkp->dad_errstats = kstat_create("cmdkerror", instance,
559 kstatname, "device_error", KSTAT_TYPE_NAMED,
560 sizeof (dadk_errstats_t) / sizeof (kstat_named_t),
561 KSTAT_FLAG_PERSISTENT);
562
563 if (!dadkp->dad_errstats)
564 return;
565
566 dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data;
567
568 kstat_named_init(&dep->dadk_softerrs,
569 "Soft Errors", KSTAT_DATA_UINT32);
570 kstat_named_init(&dep->dadk_harderrs,
571 "Hard Errors", KSTAT_DATA_UINT32);
572 kstat_named_init(&dep->dadk_transerrs,
573 "Transport Errors", KSTAT_DATA_UINT32);
574 kstat_named_init(&dep->dadk_model,
575 "Model", KSTAT_DATA_CHAR);
576 kstat_named_init(&dep->dadk_revision,
577 "Revision", KSTAT_DATA_CHAR);
578 kstat_named_init(&dep->dadk_serial,
579 "Serial No", KSTAT_DATA_CHAR);
580 kstat_named_init(&dep->dadk_capacity,
581 "Size", KSTAT_DATA_ULONGLONG);
582 kstat_named_init(&dep->dadk_rq_media_err,
583 "Media Error", KSTAT_DATA_UINT32);
584 kstat_named_init(&dep->dadk_rq_ntrdy_err,
585 "Device Not Ready", KSTAT_DATA_UINT32);
586 kstat_named_init(&dep->dadk_rq_nodev_err,
587 "No Device", KSTAT_DATA_UINT32);
588 kstat_named_init(&dep->dadk_rq_recov_err,
589 "Recoverable", KSTAT_DATA_UINT32);
590 kstat_named_init(&dep->dadk_rq_illrq_err,
591 "Illegal Request", KSTAT_DATA_UINT32);
592
593 dadkp->dad_errstats->ks_private = dep;
594 dadkp->dad_errstats->ks_update = nulldev;
595 kstat_install(dadkp->dad_errstats);
596
597 /* get model */
598 dep->dadk_model.value.c[0] = 0;
599 dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0];
600 dadk_ioc_string.is_size = sizeof (dep->dadk_model.value.c);
601 (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETMODEL,
602 (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE);
603
604 /* get serial */
605 dep->dadk_serial.value.c[0] = 0;
606 dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0];
607 dadk_ioc_string.is_size = sizeof (dep->dadk_serial.value.c);
608 (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETSERIAL,
609 (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE);
610
611 /* Get revision */
612 dep->dadk_revision.value.c[0] = 0;
613
614 /* Get capacity */
615
616 dep->dadk_capacity.value.ui64 =
617 (uint64_t)dadkp->dad_logg.g_cap *
618 (uint64_t)dadkp->dad_logg.g_secsiz;
619 }
620
621
622 int
dadk_close(opaque_t objp)623 dadk_close(opaque_t objp)
624 {
625 struct dadk *dadkp = (struct dadk *)objp;
626
627 if (dadkp->dad_rmb) {
628 (void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0,
629 DADK_SILENT);
630 (void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT);
631 }
632 FLC_STOP_KSTAT(dadkp->dad_flcobjp);
633
634 dadk_destroy_errstats(dadkp);
635
636 return (DDI_SUCCESS);
637 }
638
639 static void
dadk_destroy_errstats(struct dadk * dadkp)640 dadk_destroy_errstats(struct dadk *dadkp)
641 {
642 if (!dadkp->dad_errstats)
643 return;
644
645 kstat_delete(dadkp->dad_errstats);
646 dadkp->dad_errstats = NULL;
647 }
648
649
650 int
dadk_strategy(opaque_t objp,struct buf * bp)651 dadk_strategy(opaque_t objp, struct buf *bp)
652 {
653 struct dadk *dadkp = (struct dadk *)objp;
654
655 if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) {
656 bioerror(bp, EROFS);
657 return (DDI_FAILURE);
658 }
659
660 if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
661 bioerror(bp, ENXIO);
662 return (DDI_FAILURE);
663 }
664
665 SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
666 mutex_enter(&dadkp->dad_cmd_mutex);
667 dadkp->dad_cmd_count++;
668 mutex_exit(&dadkp->dad_cmd_mutex);
669 FLC_ENQUE(dadkp->dad_flcobjp, bp);
670
671 return (DDI_SUCCESS);
672 }
673
674 int
dadk_dump(opaque_t objp,struct buf * bp)675 dadk_dump(opaque_t objp, struct buf *bp)
676 {
677 struct dadk *dadkp = (struct dadk *)objp;
678 struct cmpkt *pktp;
679
680 if (dadkp->dad_rdonly) {
681 bioerror(bp, EROFS);
682 return (DDI_FAILURE);
683 }
684
685 if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) {
686 bioerror(bp, ENXIO);
687 return (DDI_FAILURE);
688 }
689
690 SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf)));
691
692 pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL);
693 if (!pktp) {
694 cmn_err(CE_WARN, "no resources for dumping");
695 bioerror(bp, EIO);
696 return (DDI_FAILURE);
697 }
698 pktp->cp_flags |= CPF_NOINTR;
699
700 (void) dadk_ioprep(dadkp, pktp);
701 dadk_transport(dadkp, bp);
702 pktp->cp_byteleft -= pktp->cp_bytexfer;
703
704 while (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
705 (void) dadk_iosetup(dadkp, pktp);
706 dadk_transport(dadkp, bp);
707 pktp->cp_byteleft -= pktp->cp_bytexfer;
708 }
709
710 if (pktp->cp_private)
711 BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
712 gda_free(dadkp->dad_ctlobjp, pktp, NULL);
713 return (DDI_SUCCESS);
714 }
715
716 /* ARGSUSED */
717 int
dadk_ioctl(opaque_t objp,dev_t dev,int cmd,intptr_t arg,int flag,cred_t * cred_p,int * rval_p)718 dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag,
719 cred_t *cred_p, int *rval_p)
720 {
721 struct dadk *dadkp = (struct dadk *)objp;
722
723 switch (cmd) {
724 case DKIOCGETDEF:
725 {
726 struct buf *bp;
727 int err, head;
728 unsigned char *secbuf;
729 STRUCT_DECL(defect_header, adh);
730
731 STRUCT_INIT(adh, flag & FMODELS);
732
733 /*
734 * copyin header ....
735 * yields head number and buffer address
736 */
737 if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh),
738 flag))
739 return (EFAULT);
740 head = STRUCT_FGET(adh, head);
741 if (head < 0 || head >= dadkp->dad_phyg.g_head)
742 return (ENXIO);
743 secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP);
744 if (!secbuf)
745 return (ENOMEM);
746 bp = getrbuf(KM_SLEEP);
747 if (!bp) {
748 kmem_free(secbuf, NBPSCTR);
749 return (ENOMEM);
750 }
751
752 bp->b_edev = dev;
753 bp->b_dev = cmpdev(dev);
754 bp->b_flags = B_BUSY;
755 bp->b_resid = 0;
756 bp->b_bcount = NBPSCTR;
757 bp->b_un.b_addr = (caddr_t)secbuf;
758 bp->b_blkno = head; /* I had to put it somwhere! */
759 bp->b_forw = (struct buf *)dadkp;
760 bp->b_back = (struct buf *)DCMD_GETDEF;
761
762 mutex_enter(&dadkp->dad_cmd_mutex);
763 dadkp->dad_cmd_count++;
764 mutex_exit(&dadkp->dad_cmd_mutex);
765 FLC_ENQUE(dadkp->dad_flcobjp, bp);
766 err = biowait(bp);
767 if (!err) {
768 if (ddi_copyout((caddr_t)secbuf,
769 STRUCT_FGETP(adh, buffer), NBPSCTR, flag))
770 err = ENXIO;
771 }
772 kmem_free(secbuf, NBPSCTR);
773 freerbuf(bp);
774 return (err);
775 }
776 case DIOCTL_RWCMD:
777 {
778 struct dadkio_rwcmd *rwcmdp;
779 int status, rw;
780
781 /*
782 * copied in by cmdk and, if necessary, converted to the
783 * correct datamodel
784 */
785 rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg;
786
787 /*
788 * handle the complex cases here; we pass these
789 * through to the driver, which will queue them and
790 * handle the requests asynchronously. The simpler
791 * cases ,which can return immediately, fail here, and
792 * the request reverts to the dadk_ioctl routine, while
793 * will reroute them directly to the ata driver.
794 */
795 switch (rwcmdp->cmd) {
796 case DADKIO_RWCMD_READ :
797 /*FALLTHROUGH*/
798 case DADKIO_RWCMD_WRITE:
799 rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ?
800 B_WRITE : B_READ);
801 status = dadk_dk_buf_setup(dadkp,
802 (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ?
803 UIO_SYSSPACE : UIO_USERSPACE), rw);
804 return (status);
805 default:
806 return (EINVAL);
807 }
808 }
809 case DKIOC_UPDATEFW:
810
811 /*
812 * Require PRIV_ALL privilege to invoke DKIOC_UPDATEFW
813 * to protect the firmware update from malicious use
814 */
815 if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0)
816 return (EPERM);
817 else
818 return (dadk_ctl_ioctl(dadkp, cmd, arg, flag));
819
820 case DKIOCFLUSHWRITECACHE:
821 {
822 struct buf *bp;
823 int err = 0;
824 struct dk_callback *dkc = (struct dk_callback *)arg;
825 struct cmpkt *pktp;
826 int is_sync = 1;
827
828 mutex_enter(&dadkp->dad_mutex);
829 if (dadkp->dad_noflush || ! dadkp->dad_wce) {
830 err = dadkp->dad_noflush ? ENOTSUP : 0;
831 mutex_exit(&dadkp->dad_mutex);
832 /*
833 * If a callback was requested: a
834 * callback will always be done if the
835 * caller saw the DKIOCFLUSHWRITECACHE
836 * ioctl return 0, and never done if the
837 * caller saw the ioctl return an error.
838 */
839 if ((flag & FKIOCTL) && dkc != NULL &&
840 dkc->dkc_callback != NULL) {
841 (*dkc->dkc_callback)(dkc->dkc_cookie,
842 err);
843 /*
844 * Did callback and reported error.
845 * Since we did a callback, ioctl
846 * should return 0.
847 */
848 err = 0;
849 }
850 return (err);
851 }
852 mutex_exit(&dadkp->dad_mutex);
853
854 bp = getrbuf(KM_SLEEP);
855
856 bp->b_edev = dev;
857 bp->b_dev = cmpdev(dev);
858 bp->b_flags = B_BUSY;
859 bp->b_resid = 0;
860 bp->b_bcount = 0;
861 SET_BP_SEC(bp, 0);
862
863 if ((flag & FKIOCTL) && dkc != NULL &&
864 dkc->dkc_callback != NULL) {
865 struct dk_callback *dkc2 =
866 (struct dk_callback *)kmem_zalloc(
867 sizeof (struct dk_callback), KM_SLEEP);
868
869 bcopy(dkc, dkc2, sizeof (*dkc2));
870 bp->b_private = dkc2;
871 bp->b_iodone = dadk_flushdone;
872 is_sync = 0;
873 }
874
875 /*
876 * Setup command pkt
877 * dadk_pktprep() can't fail since DDI_DMA_SLEEP set
878 */
879 pktp = dadk_pktprep(dadkp, NULL, bp,
880 dadk_iodone, DDI_DMA_SLEEP, NULL);
881
882 pktp->cp_time = DADK_FLUSH_CACHE_TIME;
883
884 *((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE;
885 pktp->cp_byteleft = 0;
886 pktp->cp_private = NULL;
887 pktp->cp_secleft = 0;
888 pktp->cp_srtsec = -1;
889 pktp->cp_bytexfer = 0;
890
891 CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
892
893 mutex_enter(&dadkp->dad_cmd_mutex);
894 dadkp->dad_cmd_count++;
895 mutex_exit(&dadkp->dad_cmd_mutex);
896 FLC_ENQUE(dadkp->dad_flcobjp, bp);
897
898 if (is_sync) {
899 err = biowait(bp);
900 freerbuf(bp);
901 }
902 return (err);
903 }
904 default:
905 if (!dadkp->dad_rmb)
906 return (dadk_ctl_ioctl(dadkp, cmd, arg, flag));
907 }
908
909 switch (cmd) {
910 case CDROMSTOP:
911 return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0,
912 0, DADK_SILENT));
913 case CDROMSTART:
914 return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0,
915 0, DADK_SILENT));
916 case DKIOCLOCK:
917 return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT));
918 case DKIOCUNLOCK:
919 return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT));
920 case DKIOCEJECT:
921 case CDROMEJECT:
922 {
923 int ret;
924
925 if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0,
926 DADK_SILENT)) {
927 return (ret);
928 }
929 if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0,
930 DADK_SILENT)) {
931 return (ret);
932 }
933 mutex_enter(&dadkp->dad_mutex);
934 dadkp->dad_iostate = DKIO_EJECTED;
935 cv_broadcast(&dadkp->dad_state_cv);
936 mutex_exit(&dadkp->dad_mutex);
937
938 return (0);
939
940 }
941 default:
942 return (ENOTTY);
943 /*
944 * cdrom audio commands
945 */
946 case CDROMPAUSE:
947 cmd = DCMD_PAUSE;
948 break;
949 case CDROMRESUME:
950 cmd = DCMD_RESUME;
951 break;
952 case CDROMPLAYMSF:
953 cmd = DCMD_PLAYMSF;
954 break;
955 case CDROMPLAYTRKIND:
956 cmd = DCMD_PLAYTRKIND;
957 break;
958 case CDROMREADTOCHDR:
959 cmd = DCMD_READTOCHDR;
960 break;
961 case CDROMREADTOCENTRY:
962 cmd = DCMD_READTOCENT;
963 break;
964 case CDROMVOLCTRL:
965 cmd = DCMD_VOLCTRL;
966 break;
967 case CDROMSUBCHNL:
968 cmd = DCMD_SUBCHNL;
969 break;
970 case CDROMREADMODE2:
971 cmd = DCMD_READMODE2;
972 break;
973 case CDROMREADMODE1:
974 cmd = DCMD_READMODE1;
975 break;
976 case CDROMREADOFFSET:
977 cmd = DCMD_READOFFSET;
978 break;
979 }
980 return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0));
981 }
982
983 int
dadk_flushdone(struct buf * bp)984 dadk_flushdone(struct buf *bp)
985 {
986 struct dk_callback *dkc = bp->b_private;
987
988 ASSERT(dkc != NULL && dkc->dkc_callback != NULL);
989
990 (*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp));
991
992 kmem_free(dkc, sizeof (*dkc));
993 freerbuf(bp);
994 return (0);
995 }
996
997 int
dadk_getphygeom(opaque_t objp,struct tgdk_geom * dkgeom_p)998 dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
999 {
1000 struct dadk *dadkp = (struct dadk *)objp;
1001
1002 bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p,
1003 sizeof (struct tgdk_geom));
1004 return (DDI_SUCCESS);
1005 }
1006
1007 int
dadk_getgeom(opaque_t objp,struct tgdk_geom * dkgeom_p)1008 dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
1009 {
1010 struct dadk *dadkp = (struct dadk *)objp;
1011 bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p,
1012 sizeof (struct tgdk_geom));
1013 return (DDI_SUCCESS);
1014 }
1015
1016 int
dadk_setgeom(opaque_t objp,struct tgdk_geom * dkgeom_p)1017 dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p)
1018 {
1019 struct dadk *dadkp = (struct dadk *)objp;
1020
1021 dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl;
1022 dadkp->dad_logg.g_head = dkgeom_p->g_head;
1023 dadkp->dad_logg.g_sec = dkgeom_p->g_sec;
1024 dadkp->dad_logg.g_cap = dkgeom_p->g_cap;
1025 return (DDI_SUCCESS);
1026 }
1027
1028
1029 tgdk_iob_handle
dadk_iob_alloc(opaque_t objp,daddr_t blkno,ssize_t xfer,int kmsflg)1030 dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg)
1031 {
1032 struct dadk *dadkp = (struct dadk *)objp;
1033 struct buf *bp;
1034 struct tgdk_iob *iobp;
1035 size_t rlen;
1036
1037 iobp = kmem_zalloc(sizeof (*iobp), kmsflg);
1038 if (iobp == NULL)
1039 return (NULL);
1040 if ((bp = getrbuf(kmsflg)) == NULL) {
1041 kmem_free(iobp, sizeof (*iobp));
1042 return (NULL);
1043 }
1044
1045 iobp->b_psec = LBLK2SEC(blkno, dadkp->dad_blkshf);
1046 iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT;
1047 iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1)
1048 >> dadkp->dad_secshf) << dadkp->dad_secshf;
1049
1050 bp->b_un.b_addr = 0;
1051 /*
1052 * use i_ddi_mem_alloc() for now until we have an interface to allocate
1053 * memory for DMA which doesn't require a DMA handle. ddi_iopb_alloc()
1054 * is obsolete and we want more flexibility in controlling the DMA
1055 * address constraints..
1056 */
1057 if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr,
1058 (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL,
1059 &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) {
1060 freerbuf(bp);
1061 kmem_free(iobp, sizeof (*iobp));
1062 return (NULL);
1063 }
1064 iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC;
1065 iobp->b_bp = bp;
1066 iobp->b_lblk = blkno;
1067 iobp->b_xfer = xfer;
1068 iobp->b_lblk = blkno;
1069 iobp->b_xfer = xfer;
1070 return (iobp);
1071 }
1072
1073 /* ARGSUSED */
1074 int
dadk_iob_free(opaque_t objp,struct tgdk_iob * iobp)1075 dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp)
1076 {
1077 struct buf *bp;
1078
1079 if (iobp) {
1080 if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) {
1081 bp = iobp->b_bp;
1082 if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC))
1083 i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL);
1084 freerbuf(bp);
1085 }
1086 kmem_free(iobp, sizeof (*iobp));
1087 }
1088 return (DDI_SUCCESS);
1089 }
1090
1091 /* ARGSUSED */
1092 caddr_t
dadk_iob_htoc(opaque_t objp,struct tgdk_iob * iobp)1093 dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp)
1094 {
1095 return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff);
1096 }
1097
1098
1099 caddr_t
dadk_iob_xfer(opaque_t objp,struct tgdk_iob * iobp,int rw)1100 dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw)
1101 {
1102 struct dadk *dadkp = (struct dadk *)objp;
1103 struct buf *bp;
1104 int err;
1105
1106 bp = iobp->b_bp;
1107 if (dadkp->dad_rdonly && !(rw & B_READ)) {
1108 bioerror(bp, EROFS);
1109 return (NULL);
1110 }
1111
1112 bp->b_flags |= (B_BUSY | rw);
1113 bp->b_bcount = iobp->b_pbytecnt;
1114 SET_BP_SEC(bp, iobp->b_psec);
1115 bp->av_back = (struct buf *)0;
1116 bp->b_resid = 0;
1117
1118 /* call flow control */
1119 mutex_enter(&dadkp->dad_cmd_mutex);
1120 dadkp->dad_cmd_count++;
1121 mutex_exit(&dadkp->dad_cmd_mutex);
1122 FLC_ENQUE(dadkp->dad_flcobjp, bp);
1123 err = biowait(bp);
1124
1125 bp->b_bcount = iobp->b_xfer;
1126 bp->b_flags &= ~(B_DONE|B_BUSY);
1127
1128 if (err)
1129 return (NULL);
1130
1131 return (bp->b_un.b_addr+iobp->b_pbyteoff);
1132 }
1133
1134 static void
dadk_transport(opaque_t com_data,struct buf * bp)1135 dadk_transport(opaque_t com_data, struct buf *bp)
1136 {
1137 struct dadk *dadkp = (struct dadk *)com_data;
1138
1139 if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) ==
1140 CTL_SEND_SUCCESS)
1141 return;
1142 dadk_restart((void*)GDA_BP_PKT(bp));
1143 }
1144
1145 static int
dadk_pkt(opaque_t com_data,struct buf * bp,int (* func)(caddr_t),caddr_t arg)1146 dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg)
1147 {
1148 struct cmpkt *pktp;
1149 struct dadk *dadkp = (struct dadk *)com_data;
1150
1151 if (GDA_BP_PKT(bp))
1152 return (DDI_SUCCESS);
1153
1154 pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg);
1155 if (!pktp)
1156 return (DDI_FAILURE);
1157
1158 return (dadk_ioprep(dadkp, pktp));
1159 }
1160
1161 /*
1162 * Read, Write preparation
1163 */
1164 static int
dadk_ioprep(struct dadk * dadkp,struct cmpkt * pktp)1165 dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp)
1166 {
1167 struct buf *bp;
1168
1169 bp = pktp->cp_bp;
1170 if (bp->b_forw == (struct buf *)dadkp)
1171 *((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back;
1172
1173 else if (bp->b_flags & B_READ)
1174 *((char *)(pktp->cp_cdbp)) = DCMD_READ;
1175 else
1176 *((char *)(pktp->cp_cdbp)) = DCMD_WRITE;
1177 pktp->cp_byteleft = bp->b_bcount;
1178
1179 /* setup the bad block list handle */
1180 pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp);
1181 return (dadk_iosetup(dadkp, pktp));
1182 }
1183
1184 static int
dadk_iosetup(struct dadk * dadkp,struct cmpkt * pktp)1185 dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp)
1186 {
1187 struct buf *bp;
1188 bbh_cookie_t bbhckp;
1189 int seccnt;
1190
1191 seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf;
1192 pktp->cp_secleft -= seccnt;
1193
1194 if (pktp->cp_secleft) {
1195 pktp->cp_srtsec += seccnt;
1196 } else {
1197 /* get the first cookie from the bad block list */
1198 if (!pktp->cp_private) {
1199 bp = pktp->cp_bp;
1200 pktp->cp_srtsec = GET_BP_SEC(bp);
1201 pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf);
1202 } else {
1203 bbhckp = BBH_HTOC(dadkp->dad_bbhobjp,
1204 pktp->cp_private);
1205 pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp,
1206 bbhckp);
1207 pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp,
1208 bbhckp);
1209 }
1210 }
1211
1212 pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf;
1213
1214 if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) {
1215 return (DDI_SUCCESS);
1216 } else {
1217 return (DDI_FAILURE);
1218 }
1219
1220
1221
1222
1223 }
1224
1225 static struct cmpkt *
dadk_pktprep(struct dadk * dadkp,struct cmpkt * in_pktp,struct buf * bp,void (* cb_func)(struct buf *),int (* func)(caddr_t),caddr_t arg)1226 dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp,
1227 void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg)
1228 {
1229 struct cmpkt *pktp;
1230
1231 pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func,
1232 arg);
1233
1234 if (pktp) {
1235 pktp->cp_callback = dadk_pktcb;
1236 pktp->cp_time = DADK_IO_TIME;
1237 pktp->cp_flags = 0;
1238 pktp->cp_iodone = cb_func;
1239 pktp->cp_dev_private = (opaque_t)dadkp;
1240
1241 }
1242
1243 return (pktp);
1244 }
1245
1246
1247 static void
dadk_restart(void * vpktp)1248 dadk_restart(void *vpktp)
1249 {
1250 struct cmpkt *pktp = (struct cmpkt *)vpktp;
1251
1252 if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN)
1253 return;
1254 pktp->cp_iodone(pktp->cp_bp);
1255 }
1256
1257 static int
dadk_ioretry(struct cmpkt * pktp,int action)1258 dadk_ioretry(struct cmpkt *pktp, int action)
1259 {
1260 struct buf *bp;
1261 struct dadk *dadkp = PKT2DADK(pktp);
1262
1263 switch (action) {
1264 case QUE_COMMAND:
1265 if (pktp->cp_retry++ < DADK_RETRY_COUNT) {
1266 CTL_IOSETUP(dadkp->dad_ctlobjp, pktp);
1267 if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) ==
1268 CTL_SEND_SUCCESS) {
1269 return (JUST_RETURN);
1270 }
1271 gda_log(dadkp->dad_sd->sd_dev, dadk_name,
1272 CE_WARN, "transport of command fails\n");
1273 } else
1274 gda_log(dadkp->dad_sd->sd_dev,
1275 dadk_name, CE_WARN,
1276 "exceeds maximum number of retries\n");
1277 bioerror(pktp->cp_bp, ENXIO);
1278 /*FALLTHROUGH*/
1279 case COMMAND_DONE_ERROR:
1280 bp = pktp->cp_bp;
1281 bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer +
1282 pktp->cp_resid;
1283 if (geterror(bp) == 0) {
1284 if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) &&
1285 (pktp->cp_dev_private == (opaque_t)dadkp) &&
1286 ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) {
1287 /*
1288 * Flag "unimplemented" responses for
1289 * DCMD_FLUSH_CACHE as ENOTSUP
1290 */
1291 bioerror(bp, ENOTSUP);
1292 mutex_enter(&dadkp->dad_mutex);
1293 dadkp->dad_noflush = 1;
1294 mutex_exit(&dadkp->dad_mutex);
1295 } else {
1296 bioerror(bp, EIO);
1297 }
1298 }
1299 /*FALLTHROUGH*/
1300 case COMMAND_DONE:
1301 default:
1302 return (COMMAND_DONE);
1303 }
1304 }
1305
1306
1307 static void
dadk_pktcb(struct cmpkt * pktp)1308 dadk_pktcb(struct cmpkt *pktp)
1309 {
1310 int action;
1311 struct dadkio_rwcmd *rwcmdp;
1312
1313 rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru; /* ioctl packet */
1314
1315 if (pktp->cp_reason == CPS_SUCCESS) {
1316 if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT))
1317 rwcmdp->status.status = DADKIO_STAT_NO_ERROR;
1318 pktp->cp_iodone(pktp->cp_bp);
1319 return;
1320 }
1321
1322 if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) {
1323 if (pktp->cp_reason == CPS_CHKERR)
1324 dadk_recorderr(pktp, rwcmdp);
1325 dadk_iodone(pktp->cp_bp);
1326 return;
1327 }
1328
1329 if (pktp->cp_reason == CPS_CHKERR)
1330 action = dadk_chkerr(pktp);
1331 else
1332 action = COMMAND_DONE_ERROR;
1333
1334 if (action == JUST_RETURN)
1335 return;
1336
1337 /*
1338 * If we are panicking don't retry the command
1339 * just fail it so we can go down completing all
1340 * of the buffers.
1341 */
1342 if (ddi_in_panic() && action == QUE_COMMAND)
1343 action = COMMAND_DONE_ERROR;
1344
1345 if (action != COMMAND_DONE) {
1346 if ((dadk_ioretry(pktp, action)) == JUST_RETURN)
1347 return;
1348 }
1349 pktp->cp_iodone(pktp->cp_bp);
1350 }
1351
1352
1353
1354 static struct dadkio_derr dadk_errtab[] = {
1355 {COMMAND_DONE, GDA_INFORMATIONAL}, /* 0 DERR_SUCCESS */
1356 {QUE_COMMAND, GDA_FATAL}, /* 1 DERR_AMNF */
1357 {QUE_COMMAND, GDA_FATAL}, /* 2 DERR_TKONF */
1358 {COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT */
1359 {QUE_COMMAND, GDA_RETRYABLE}, /* 4 DERR_DWF */
1360 {QUE_COMMAND, GDA_FATAL}, /* 5 DERR_IDNF */
1361 {JUST_RETURN, GDA_INFORMATIONAL}, /* 6 DERR_BUSY */
1362 {QUE_COMMAND, GDA_FATAL}, /* 7 DERR_UNC */
1363 {QUE_COMMAND, GDA_RETRYABLE}, /* 8 DERR_BBK */
1364 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 9 DERR_INVCDB */
1365 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 10 DERR_HARD */
1366 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 11 DERR_ILI */
1367 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 12 DERR_EOM */
1368 {COMMAND_DONE, GDA_INFORMATIONAL}, /* 13 DERR_MCR */
1369 {COMMAND_DONE, GDA_INFORMATIONAL}, /* 14 DERR_RECOVER */
1370 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 15 DERR_NOTREADY */
1371 {QUE_COMMAND, GDA_RETRYABLE}, /* 16 DERR_MEDIUM */
1372 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 17 DERR_HW */
1373 {COMMAND_DONE, GDA_FATAL}, /* 18 DERR_ILL */
1374 {COMMAND_DONE, GDA_FATAL}, /* 19 DERR_UNIT_ATTN */
1375 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 20 DERR_DATA_PROT */
1376 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 21 DERR_MISCOMPARE */
1377 {QUE_COMMAND, GDA_RETRYABLE}, /* 22 DERR_ICRC */
1378 {COMMAND_DONE_ERROR, GDA_FATAL}, /* 23 DERR_RESV */
1379 };
1380
1381 static int
dadk_chkerr(struct cmpkt * pktp)1382 dadk_chkerr(struct cmpkt *pktp)
1383 {
1384 daddr_t err_blkno;
1385 struct dadk *dadkp = PKT2DADK(pktp);
1386 dadk_errstats_t *dep;
1387 int scb = *(char *)pktp->cp_scbp;
1388
1389 if (scb == DERR_SUCCESS) {
1390 if (pktp->cp_retry != 0 && dadkp->dad_errstats != NULL) {
1391 dep = (dadk_errstats_t *)
1392 dadkp->dad_errstats->ks_data;
1393 dep->dadk_rq_recov_err.value.ui32++;
1394 }
1395 return (COMMAND_DONE);
1396 }
1397
1398 if (pktp->cp_retry) {
1399 err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer -
1400 pktp->cp_resid) >> dadkp->dad_secshf);
1401 } else
1402 err_blkno = -1;
1403
1404 if (dadkp->dad_errstats != NULL) {
1405 dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data;
1406
1407 switch (dadk_errtab[scb].d_severity) {
1408 case GDA_RETRYABLE:
1409 dep->dadk_softerrs.value.ui32++;
1410 break;
1411
1412 case GDA_FATAL:
1413 dep->dadk_harderrs.value.ui32++;
1414 break;
1415
1416 default:
1417 break;
1418 }
1419
1420 switch (scb) {
1421 case DERR_INVCDB:
1422 case DERR_ILI:
1423 case DERR_EOM:
1424 case DERR_HW:
1425 case DERR_ICRC:
1426 dep->dadk_transerrs.value.ui32++;
1427 break;
1428
1429 case DERR_AMNF:
1430 case DERR_TKONF:
1431 case DERR_DWF:
1432 case DERR_BBK:
1433 case DERR_UNC:
1434 case DERR_HARD:
1435 case DERR_MEDIUM:
1436 case DERR_DATA_PROT:
1437 case DERR_MISCOMP:
1438 dep->dadk_rq_media_err.value.ui32++;
1439 break;
1440
1441 case DERR_NOTREADY:
1442 dep->dadk_rq_ntrdy_err.value.ui32++;
1443 break;
1444
1445 case DERR_IDNF:
1446 case DERR_UNIT_ATTN:
1447 dep->dadk_rq_nodev_err.value.ui32++;
1448 break;
1449
1450 case DERR_ILL:
1451 case DERR_RESV:
1452 dep->dadk_rq_illrq_err.value.ui32++;
1453 break;
1454
1455 default:
1456 break;
1457 }
1458 }
1459
1460 /* if attempting to read a sector from a cdrom audio disk */
1461 if ((dadkp->dad_cdrom) &&
1462 (*((char *)(pktp->cp_cdbp)) == DCMD_READ) &&
1463 (scb == DERR_ILL)) {
1464 return (COMMAND_DONE);
1465 }
1466 if (pktp->cp_passthru == NULL) {
1467 gda_errmsg(dadkp->dad_sd, pktp, dadk_name,
1468 dadk_errtab[scb].d_severity, pktp->cp_srtsec,
1469 err_blkno, dadk_cmds, dadk_sense);
1470 }
1471
1472 if (scb == DERR_BUSY) {
1473 (void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT);
1474 }
1475
1476 return (dadk_errtab[scb].d_action);
1477 }
1478
1479 static void
dadk_recorderr(struct cmpkt * pktp,struct dadkio_rwcmd * rwcmdp)1480 dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp)
1481 {
1482 struct dadk *dadkp;
1483 int scb;
1484
1485 dadkp = PKT2DADK(pktp);
1486 scb = (int)(*(char *)pktp->cp_scbp);
1487
1488
1489 rwcmdp->status.failed_blk = rwcmdp->blkaddr +
1490 ((pktp->cp_bytexfer - pktp->cp_resid) >> dadkp->dad_secshf);
1491
1492 rwcmdp->status.resid = pktp->cp_bp->b_resid +
1493 pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid;
1494 switch ((int)(* (char *)pktp->cp_scbp)) {
1495 case DERR_AMNF:
1496 case DERR_ABORT:
1497 rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST;
1498 break;
1499 case DERR_DWF:
1500 case DERR_IDNF:
1501 rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS;
1502 break;
1503 case DERR_TKONF:
1504 case DERR_UNC:
1505 case DERR_BBK:
1506 rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR;
1507 rwcmdp->status.failed_blk_is_valid = 1;
1508 rwcmdp->status.resid = 0;
1509 break;
1510 case DERR_BUSY:
1511 rwcmdp->status.status = DADKIO_STAT_NOT_READY;
1512 break;
1513 case DERR_INVCDB:
1514 case DERR_HARD:
1515 rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR;
1516 break;
1517 case DERR_ICRC:
1518 default:
1519 rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED;
1520 }
1521
1522 if (rwcmdp->flags & DADKIO_FLAG_SILENT)
1523 return;
1524 gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity,
1525 rwcmdp->blkaddr, rwcmdp->status.failed_blk,
1526 dadk_cmds, dadk_sense);
1527 }
1528
1529 /*ARGSUSED*/
1530 static void
dadk_polldone(struct buf * bp)1531 dadk_polldone(struct buf *bp)
1532 {
1533 struct cmpkt *pktp;
1534 struct dadk *dadkp;
1535
1536 pktp = GDA_BP_PKT(bp);
1537 dadkp = PKT2DADK(pktp);
1538 mutex_enter(&dadkp->dad_cmd_mutex);
1539 dadkp->dad_cmd_count--;
1540 mutex_exit(&dadkp->dad_cmd_mutex);
1541 }
1542
1543 static void
dadk_iodone(struct buf * bp)1544 dadk_iodone(struct buf *bp)
1545 {
1546 struct cmpkt *pktp;
1547 struct dadk *dadkp;
1548
1549 pktp = GDA_BP_PKT(bp);
1550 dadkp = PKT2DADK(pktp);
1551
1552 /* check for all iodone */
1553 pktp->cp_byteleft -= pktp->cp_bytexfer;
1554 if (geterror(bp) == 0 && pktp->cp_byteleft != 0) {
1555 pktp->cp_retry = 0;
1556 (void) dadk_iosetup(dadkp, pktp);
1557
1558
1559 /* transport the next one */
1560 if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS)
1561 return;
1562 if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN)
1563 return;
1564 }
1565
1566 /* start next one */
1567 FLC_DEQUE(dadkp->dad_flcobjp, bp);
1568
1569 /* free pkt */
1570 if (pktp->cp_private)
1571 BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private);
1572 gda_free(dadkp->dad_ctlobjp, pktp, NULL);
1573 mutex_enter(&dadkp->dad_cmd_mutex);
1574 dadkp->dad_cmd_count--;
1575 mutex_exit(&dadkp->dad_cmd_mutex);
1576 biodone(bp);
1577 }
1578
1579 int
dadk_check_media(opaque_t objp,int * state)1580 dadk_check_media(opaque_t objp, int *state)
1581 {
1582 struct dadk *dadkp = (struct dadk *)objp;
1583
1584 if (!dadkp->dad_rmb) {
1585 return (ENXIO);
1586 }
1587 #ifdef DADK_DEBUG
1588 if (dadk_debug & DSTATE)
1589 PRF("dadk_check_media: user state %x disk state %x\n",
1590 *state, dadkp->dad_iostate);
1591 #endif
1592 /*
1593 * If state already changed just return
1594 */
1595 if (*state != dadkp->dad_iostate) {
1596 *state = dadkp->dad_iostate;
1597 return (0);
1598 }
1599
1600 /*
1601 * Startup polling on thread state
1602 */
1603 mutex_enter(&dadkp->dad_mutex);
1604 if (dadkp->dad_thread_cnt == 0) {
1605 /*
1606 * One thread per removable dadk device
1607 */
1608 (void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0,
1609 TS_RUN, v.v_maxsyspri - 2);
1610 }
1611 dadkp->dad_thread_cnt++;
1612
1613 /*
1614 * Wait for state to change
1615 */
1616 do {
1617 if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) {
1618 dadkp->dad_thread_cnt--;
1619 mutex_exit(&dadkp->dad_mutex);
1620 return (EINTR);
1621 }
1622 } while (*state == dadkp->dad_iostate);
1623 *state = dadkp->dad_iostate;
1624 dadkp->dad_thread_cnt--;
1625 mutex_exit(&dadkp->dad_mutex);
1626 return (0);
1627 }
1628
1629
1630 #define MEDIA_ACCESS_DELAY 2000000
1631
1632 static void
dadk_watch_thread(struct dadk * dadkp)1633 dadk_watch_thread(struct dadk *dadkp)
1634 {
1635 enum dkio_state state;
1636 int interval;
1637
1638 interval = drv_usectohz(dadk_check_media_time);
1639
1640 do {
1641 if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0,
1642 DADK_SILENT)) {
1643 /*
1644 * Assume state remained the same
1645 */
1646 state = dadkp->dad_iostate;
1647 }
1648
1649 /*
1650 * now signal the waiting thread if this is *not* the
1651 * specified state;
1652 * delay the signal if the state is DKIO_INSERTED
1653 * to allow the target to recover
1654 */
1655 if (state != dadkp->dad_iostate) {
1656
1657 dadkp->dad_iostate = state;
1658 if (state == DKIO_INSERTED) {
1659 /*
1660 * delay the signal to give the drive a chance
1661 * to do what it apparently needs to do
1662 */
1663 (void) timeout((void(*)(void *))cv_broadcast,
1664 (void *)&dadkp->dad_state_cv,
1665 drv_usectohz((clock_t)MEDIA_ACCESS_DELAY));
1666 } else {
1667 cv_broadcast(&dadkp->dad_state_cv);
1668 }
1669 }
1670 delay(interval);
1671 } while (dadkp->dad_thread_cnt);
1672 }
1673
1674 int
dadk_inquiry(opaque_t objp,opaque_t * inqpp)1675 dadk_inquiry(opaque_t objp, opaque_t *inqpp)
1676 {
1677 struct dadk *dadkp = (struct dadk *)objp;
1678 struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp;
1679
1680 if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) {
1681 *sinqpp = dadkp->dad_sd->sd_inq;
1682 return (DDI_SUCCESS);
1683 }
1684
1685 return (DDI_FAILURE);
1686 }
1687
1688 static int
dadk_rmb_ioctl(struct dadk * dadkp,int cmd,intptr_t arg,int flags,int silent)1689 dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent)
1690
1691 {
1692 struct buf *bp;
1693 int err;
1694 struct cmpkt *pktp;
1695
1696 if ((bp = getrbuf(KM_SLEEP)) == NULL) {
1697 return (ENOMEM);
1698 }
1699 pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL);
1700 if (!pktp) {
1701 freerbuf(bp);
1702 return (ENOMEM);
1703 }
1704 bp->b_back = (struct buf *)arg;
1705 bp->b_forw = (struct buf *)dadkp->dad_flcobjp;
1706 pktp->cp_passthru = (opaque_t)(intptr_t)silent;
1707
1708 err = dadk_ctl_ioctl(dadkp, cmd, (uintptr_t)pktp, flags);
1709 freerbuf(bp);
1710 gda_free(dadkp->dad_ctlobjp, pktp, NULL);
1711 return (err);
1712
1713
1714 }
1715
1716 static void
dadk_rmb_iodone(struct buf * bp)1717 dadk_rmb_iodone(struct buf *bp)
1718 {
1719 struct cmpkt *pktp;
1720 struct dadk *dadkp;
1721
1722 pktp = GDA_BP_PKT(bp);
1723 dadkp = PKT2DADK(pktp);
1724
1725 bp->b_flags &= ~(B_DONE|B_BUSY);
1726
1727 /* Start next one */
1728 FLC_DEQUE(dadkp->dad_flcobjp, bp);
1729
1730 mutex_enter(&dadkp->dad_cmd_mutex);
1731 dadkp->dad_cmd_count--;
1732 mutex_exit(&dadkp->dad_cmd_mutex);
1733 biodone(bp);
1734 }
1735
1736 static int
dadk_dk_buf_setup(struct dadk * dadkp,opaque_t * cmdp,dev_t dev,enum uio_seg dataspace,int rw)1737 dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev,
1738 enum uio_seg dataspace, int rw)
1739 {
1740 struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp;
1741 struct buf *bp;
1742 struct iovec aiov;
1743 struct uio auio;
1744 struct uio *uio = &auio;
1745 int status;
1746
1747 bp = getrbuf(KM_SLEEP);
1748
1749 bp->av_forw = bp->b_forw = (struct buf *)dadkp;
1750 bp->b_back = (struct buf *)rwcmdp; /* ioctl packet */
1751
1752 bzero((caddr_t)&auio, sizeof (struct uio));
1753 bzero((caddr_t)&aiov, sizeof (struct iovec));
1754 aiov.iov_base = rwcmdp->bufaddr;
1755 aiov.iov_len = rwcmdp->buflen;
1756 uio->uio_iov = &aiov;
1757
1758 uio->uio_iovcnt = 1;
1759 uio->uio_resid = rwcmdp->buflen;
1760 uio->uio_segflg = dataspace;
1761
1762 /* Let physio do the rest... */
1763 status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio);
1764
1765 freerbuf(bp);
1766 return (status);
1767
1768 }
1769
1770 /* Do not let a user gendisk request get too big or */
1771 /* else we could use to many resources. */
1772
1773 static void
dadkmin(struct buf * bp)1774 dadkmin(struct buf *bp)
1775 {
1776 if (bp->b_bcount > dadk_dk_maxphys)
1777 bp->b_bcount = dadk_dk_maxphys;
1778 }
1779
1780 static int
dadk_dk_strategy(struct buf * bp)1781 dadk_dk_strategy(struct buf *bp)
1782 {
1783 dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back,
1784 bp);
1785 return (0);
1786 }
1787
1788 static void
dadk_dk(struct dadk * dadkp,struct dadkio_rwcmd * rwcmdp,struct buf * bp)1789 dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp)
1790 {
1791 struct cmpkt *pktp;
1792
1793 pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL);
1794 if (!pktp) {
1795 bioerror(bp, ENOMEM);
1796 biodone(bp);
1797 return;
1798 }
1799
1800 pktp->cp_passthru = rwcmdp;
1801
1802 (void) dadk_ioprep(dadkp, pktp);
1803
1804 mutex_enter(&dadkp->dad_cmd_mutex);
1805 dadkp->dad_cmd_count++;
1806 mutex_exit(&dadkp->dad_cmd_mutex);
1807 FLC_ENQUE(dadkp->dad_flcobjp, bp);
1808 }
1809
1810 /*
1811 * There is no existing way to notify cmdk module
1812 * when the command completed, so add this function
1813 * to calculate how many on-going commands.
1814 */
1815 int
dadk_getcmds(opaque_t objp)1816 dadk_getcmds(opaque_t objp)
1817 {
1818 struct dadk *dadkp = (struct dadk *)objp;
1819 int count;
1820
1821 mutex_enter(&dadkp->dad_cmd_mutex);
1822 count = dadkp->dad_cmd_count;
1823 mutex_exit(&dadkp->dad_cmd_mutex);
1824 return (count);
1825 }
1826
1827 /*
1828 * this function was used to calc the cmd for CTL_IOCTL
1829 */
1830 static int
dadk_ctl_ioctl(struct dadk * dadkp,uint32_t cmd,uintptr_t arg,int flag)1831 dadk_ctl_ioctl(struct dadk *dadkp, uint32_t cmd, uintptr_t arg, int flag)
1832 {
1833 int error;
1834 mutex_enter(&dadkp->dad_cmd_mutex);
1835 dadkp->dad_cmd_count++;
1836 mutex_exit(&dadkp->dad_cmd_mutex);
1837 error = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag);
1838 mutex_enter(&dadkp->dad_cmd_mutex);
1839 dadkp->dad_cmd_count--;
1840 mutex_exit(&dadkp->dad_cmd_mutex);
1841 return (error);
1842 }
1843