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