1507c3241Smlf /* 2507c3241Smlf * CDDL HEADER START 3507c3241Smlf * 4507c3241Smlf * The contents of this file are subject to the terms of the 5507c3241Smlf * Common Development and Distribution License (the "License"). 6507c3241Smlf * You may not use this file except in compliance with the License. 7507c3241Smlf * 8507c3241Smlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9507c3241Smlf * or http://www.opensolaris.org/os/licensing. 10507c3241Smlf * See the License for the specific language governing permissions 11507c3241Smlf * and limitations under the License. 12507c3241Smlf * 13507c3241Smlf * When distributing Covered Code, include this CDDL HEADER in each 14507c3241Smlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15507c3241Smlf * If applicable, add the following below this CDDL HEADER, with the 16507c3241Smlf * fields enclosed by brackets "[]" replaced with your own identifying 17507c3241Smlf * information: Portions Copyright [yyyy] [name of copyright owner] 18507c3241Smlf * 19507c3241Smlf * CDDL HEADER END 20507c3241Smlf */ 21507c3241Smlf 22507c3241Smlf /* 23744947dcSTom Erickson * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 24507c3241Smlf */ 25507c3241Smlf 26507c3241Smlf /* 27507c3241Smlf * Direct Attached Disk 28507c3241Smlf */ 29507c3241Smlf 30507c3241Smlf #include <sys/file.h> 31507c3241Smlf #include <sys/scsi/scsi.h> 32507c3241Smlf #include <sys/var.h> 33507c3241Smlf #include <sys/proc.h> 34507c3241Smlf #include <sys/dktp/cm.h> 35507c3241Smlf #include <sys/vtoc.h> 36507c3241Smlf #include <sys/dkio.h> 370f2c99a4Syt160523 #include <sys/policy.h> 380f2c99a4Syt160523 #include <sys/priv.h> 39507c3241Smlf 40507c3241Smlf #include <sys/dktp/dadev.h> 41507c3241Smlf #include <sys/dktp/fctypes.h> 42507c3241Smlf #include <sys/dktp/flowctrl.h> 43507c3241Smlf #include <sys/dktp/tgcom.h> 44507c3241Smlf #include <sys/dktp/tgdk.h> 45507c3241Smlf #include <sys/dktp/bbh.h> 46507c3241Smlf #include <sys/dktp/dadkio.h> 47507c3241Smlf #include <sys/dktp/dadk.h> 48507c3241Smlf #include <sys/cdio.h> 49507c3241Smlf 50507c3241Smlf /* 51507c3241Smlf * Local Function Prototypes 52507c3241Smlf */ 53507c3241Smlf static void dadk_restart(void *pktp); 54507c3241Smlf static void dadk_pktcb(struct cmpkt *pktp); 55507c3241Smlf static void dadk_iodone(struct buf *bp); 56507c3241Smlf static void dadk_polldone(struct buf *bp); 57507c3241Smlf static void dadk_setcap(struct dadk *dadkp); 584d27faddSmarx static void dadk_create_errstats(struct dadk *dadkp, int instance); 594d27faddSmarx static void dadk_destroy_errstats(struct dadk *dadkp); 60507c3241Smlf 61507c3241Smlf static int dadk_chkerr(struct cmpkt *pktp); 62507c3241Smlf static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp); 63507c3241Smlf static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp); 64507c3241Smlf static int dadk_ioretry(struct cmpkt *pktp, int action); 65507c3241Smlf 66507c3241Smlf static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, 67507c3241Smlf struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t), 68507c3241Smlf caddr_t arg); 69507c3241Smlf 70507c3241Smlf static int dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), 71507c3241Smlf caddr_t arg); 72507c3241Smlf static void dadk_transport(opaque_t com_data, struct buf *bp); 732df1fe9cSrandyf static int dadk_ctl_ioctl(struct dadk *, uint32_t, uintptr_t, int); 74507c3241Smlf 75507c3241Smlf struct tgcom_objops dadk_com_ops = { 76507c3241Smlf nodev, 77507c3241Smlf nodev, 78507c3241Smlf dadk_pkt, 79507c3241Smlf dadk_transport, 80507c3241Smlf 0, 0 81507c3241Smlf }; 82507c3241Smlf 83507c3241Smlf /* 84507c3241Smlf * architecture dependent allocation restrictions for dadk_iob_alloc(). For 85507c3241Smlf * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen 86507c3241Smlf * to dadk_sgl_size during _init(). 87507c3241Smlf */ 88507c3241Smlf #if defined(__sparc) 89507c3241Smlf static ddi_dma_attr_t dadk_alloc_attr = { 90507c3241Smlf DMA_ATTR_V0, /* version number */ 91507c3241Smlf 0x0, /* lowest usable address */ 92507c3241Smlf 0xFFFFFFFFull, /* high DMA address range */ 93507c3241Smlf 0xFFFFFFFFull, /* DMA counter register */ 94507c3241Smlf 1, /* DMA address alignment */ 95507c3241Smlf 1, /* DMA burstsizes */ 96507c3241Smlf 1, /* min effective DMA size */ 97507c3241Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 98507c3241Smlf 0xFFFFFFFFull, /* segment boundary */ 99507c3241Smlf 1, /* s/g list length */ 100507c3241Smlf 512, /* granularity of device */ 101507c3241Smlf 0, /* DMA transfer flags */ 102507c3241Smlf }; 103507c3241Smlf #elif defined(__x86) 104507c3241Smlf static ddi_dma_attr_t dadk_alloc_attr = { 105507c3241Smlf DMA_ATTR_V0, /* version number */ 106507c3241Smlf 0x0, /* lowest usable address */ 107507c3241Smlf 0x0, /* high DMA address range [set in _init()] */ 108507c3241Smlf 0xFFFFull, /* DMA counter register */ 109507c3241Smlf 512, /* DMA address alignment */ 110507c3241Smlf 1, /* DMA burstsizes */ 111507c3241Smlf 1, /* min effective DMA size */ 112507c3241Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 113507c3241Smlf 0xFFFFFFFFull, /* segment boundary */ 114507c3241Smlf 0, /* s/g list length [set in _init()] */ 115507c3241Smlf 512, /* granularity of device */ 116507c3241Smlf 0, /* DMA transfer flags */ 117507c3241Smlf }; 118507c3241Smlf 119507c3241Smlf uint64_t dadk_max_phys_addr = 0xFFFFFFFFull; 120507c3241Smlf int dadk_sgl_size = 0xFF; 121507c3241Smlf #endif 122507c3241Smlf 123507c3241Smlf static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, 124507c3241Smlf int silent); 125507c3241Smlf static void dadk_rmb_iodone(struct buf *bp); 126507c3241Smlf 127507c3241Smlf static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, 128507c3241Smlf dev_t dev, enum uio_seg dataspace, int rw); 129507c3241Smlf static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp, 130507c3241Smlf struct buf *bp); 131507c3241Smlf static void dadkmin(struct buf *bp); 132507c3241Smlf static int dadk_dk_strategy(struct buf *bp); 133507c3241Smlf static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp); 134507c3241Smlf 135507c3241Smlf struct tgdk_objops dadk_ops = { 136507c3241Smlf dadk_init, 137507c3241Smlf dadk_free, 138507c3241Smlf dadk_probe, 139507c3241Smlf dadk_attach, 140507c3241Smlf dadk_open, 141507c3241Smlf dadk_close, 142507c3241Smlf dadk_ioctl, 143507c3241Smlf dadk_strategy, 144507c3241Smlf dadk_setgeom, 145507c3241Smlf dadk_getgeom, 146507c3241Smlf dadk_iob_alloc, 147507c3241Smlf dadk_iob_free, 148507c3241Smlf dadk_iob_htoc, 149507c3241Smlf dadk_iob_xfer, 150507c3241Smlf dadk_dump, 151507c3241Smlf dadk_getphygeom, 152507c3241Smlf dadk_set_bbhobj, 153507c3241Smlf dadk_check_media, 154507c3241Smlf dadk_inquiry, 155507c3241Smlf dadk_cleanup, 156507c3241Smlf 0 157507c3241Smlf }; 158507c3241Smlf 159507c3241Smlf /* 160507c3241Smlf * Local static data 161507c3241Smlf */ 162507c3241Smlf 163507c3241Smlf #ifdef DADK_DEBUG 164507c3241Smlf #define DENT 0x0001 165507c3241Smlf #define DERR 0x0002 166507c3241Smlf #define DIO 0x0004 167507c3241Smlf #define DGEOM 0x0010 168507c3241Smlf #define DSTATE 0x0020 169507c3241Smlf static int dadk_debug = DGEOM; 170507c3241Smlf 171507c3241Smlf #endif /* DADK_DEBUG */ 172507c3241Smlf 173507c3241Smlf static int dadk_check_media_time = 3000000; /* 3 Second State Check */ 174507c3241Smlf static int dadk_dk_maxphys = 0x80000; 175507c3241Smlf 176507c3241Smlf static char *dadk_cmds[] = { 177507c3241Smlf "\000Unknown", /* unknown */ 178507c3241Smlf "\001read sector", /* DCMD_READ 1 */ 179507c3241Smlf "\002write sector", /* DCMD_WRITE 2 */ 180507c3241Smlf "\003format track", /* DCMD_FMTTRK 3 */ 181507c3241Smlf "\004format whole drive", /* DCMD_FMTDRV 4 */ 182507c3241Smlf "\005recalibrate", /* DCMD_RECAL 5 */ 183507c3241Smlf "\006seek sector", /* DCMD_SEEK 6 */ 184507c3241Smlf "\007read verify", /* DCMD_RDVER 7 */ 185507c3241Smlf "\010read defect list", /* DCMD_GETDEF 8 */ 186507c3241Smlf "\011lock door", /* DCMD_LOCK 9 */ 187507c3241Smlf "\012unlock door", /* DCMD_UNLOCK 10 */ 188507c3241Smlf "\013start motor", /* DCMD_START_MOTOR 11 */ 189507c3241Smlf "\014stop motor", /* DCMD_STOP_MOTOR 12 */ 190507c3241Smlf "\015eject", /* DCMD_EJECT 13 */ 191507c3241Smlf "\016update geometry", /* DCMD_UPDATE_GEOM 14 */ 192507c3241Smlf "\017get state", /* DCMD_GET_STATE 15 */ 193507c3241Smlf "\020cdrom pause", /* DCMD_PAUSE 16 */ 194507c3241Smlf "\021cdrom resume", /* DCMD_RESUME 17 */ 195507c3241Smlf "\022cdrom play track index", /* DCMD_PLAYTRKIND 18 */ 196507c3241Smlf "\023cdrom play msf", /* DCMD_PLAYMSF 19 */ 197507c3241Smlf "\024cdrom sub channel", /* DCMD_SUBCHNL 20 */ 198507c3241Smlf "\025cdrom read mode 1", /* DCMD_READMODE1 21 */ 199507c3241Smlf "\026cdrom read toc header", /* DCMD_READTOCHDR 22 */ 200507c3241Smlf "\027cdrom read toc entry", /* DCMD_READTOCENT 23 */ 201507c3241Smlf "\030cdrom read offset", /* DCMD_READOFFSET 24 */ 202507c3241Smlf "\031cdrom read mode 2", /* DCMD_READMODE2 25 */ 203507c3241Smlf "\032cdrom volume control", /* DCMD_VOLCTRL 26 */ 204507c3241Smlf "\033flush cache", /* DCMD_FLUSH_CACHE 27 */ 205507c3241Smlf NULL 206507c3241Smlf }; 207507c3241Smlf 208507c3241Smlf static char *dadk_sense[] = { 209507c3241Smlf "\000Success", /* DERR_SUCCESS */ 210507c3241Smlf "\001address mark not found", /* DERR_AMNF */ 211507c3241Smlf "\002track 0 not found", /* DERR_TKONF */ 212507c3241Smlf "\003aborted command", /* DERR_ABORT */ 213507c3241Smlf "\004write fault", /* DERR_DWF */ 214507c3241Smlf "\005ID not found", /* DERR_IDNF */ 215507c3241Smlf "\006drive busy", /* DERR_BUSY */ 216507c3241Smlf "\007uncorrectable data error", /* DERR_UNC */ 217507c3241Smlf "\010bad block detected", /* DERR_BBK */ 218507c3241Smlf "\011invalid command", /* DERR_INVCDB */ 219507c3241Smlf "\012device hard error", /* DERR_HARD */ 220507c3241Smlf "\013illegal length indicated", /* DERR_ILI */ 221507c3241Smlf "\014end of media", /* DERR_EOM */ 222507c3241Smlf "\015media change requested", /* DERR_MCR */ 223507c3241Smlf "\016recovered from error", /* DERR_RECOVER */ 224507c3241Smlf "\017device not ready", /* DERR_NOTREADY */ 225507c3241Smlf "\020medium error", /* DERR_MEDIUM */ 226507c3241Smlf "\021hardware error", /* DERR_HW */ 227507c3241Smlf "\022illegal request", /* DERR_ILL */ 228507c3241Smlf "\023unit attention", /* DERR_UNIT_ATTN */ 229507c3241Smlf "\024data protection", /* DERR_DATA_PROT */ 230507c3241Smlf "\025miscompare", /* DERR_MISCOMPARE */ 231507c3241Smlf "\026ICRC error during UDMA", /* DERR_ICRC */ 232507c3241Smlf "\027reserved", /* DERR_RESV */ 233507c3241Smlf NULL 234507c3241Smlf }; 235507c3241Smlf 236507c3241Smlf static char *dadk_name = "Disk"; 237507c3241Smlf 238507c3241Smlf /* 239507c3241Smlf * This is the loadable module wrapper 240507c3241Smlf */ 241507c3241Smlf #include <sys/modctl.h> 242507c3241Smlf 243507c3241Smlf extern struct mod_ops mod_miscops; 244507c3241Smlf 245507c3241Smlf static struct modlmisc modlmisc = { 246507c3241Smlf &mod_miscops, /* Type of module */ 2471dc8bc23Szk194757 "Direct Attached Disk" 248507c3241Smlf }; 249507c3241Smlf 250507c3241Smlf static struct modlinkage modlinkage = { 251507c3241Smlf MODREV_1, (void *)&modlmisc, NULL 252507c3241Smlf }; 253507c3241Smlf 254507c3241Smlf int 255507c3241Smlf _init(void) 256507c3241Smlf { 257507c3241Smlf #ifdef DADK_DEBUG 258507c3241Smlf if (dadk_debug & DENT) 259507c3241Smlf PRF("dadk_init: call\n"); 260507c3241Smlf #endif 261507c3241Smlf 262507c3241Smlf #if defined(__x86) 263507c3241Smlf /* set the max physical address for iob allocs on x86 */ 264507c3241Smlf dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr; 265507c3241Smlf 266507c3241Smlf /* 267507c3241Smlf * set the sgllen for iob allocs on x86. If this is set less than 268507c3241Smlf * the number of pages the buffer will take (taking into account 269507c3241Smlf * alignment), it would force the allocator to try and allocate 270507c3241Smlf * contiguous pages. 271507c3241Smlf */ 272507c3241Smlf dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size; 273507c3241Smlf #endif 274507c3241Smlf 275507c3241Smlf return (mod_install(&modlinkage)); 276507c3241Smlf } 277507c3241Smlf 278507c3241Smlf int 279507c3241Smlf _fini(void) 280507c3241Smlf { 281507c3241Smlf #ifdef DADK_DEBUG 282507c3241Smlf if (dadk_debug & DENT) 283507c3241Smlf PRF("dadk_fini: call\n"); 284507c3241Smlf #endif 285507c3241Smlf 286507c3241Smlf return (mod_remove(&modlinkage)); 287507c3241Smlf } 288507c3241Smlf 289507c3241Smlf int 290507c3241Smlf _info(struct modinfo *modinfop) 291507c3241Smlf { 292507c3241Smlf return (mod_info(&modlinkage, modinfop)); 293507c3241Smlf } 294507c3241Smlf 295507c3241Smlf struct tgdk_obj * 296507c3241Smlf dadk_create() 297507c3241Smlf { 298507c3241Smlf struct tgdk_obj *dkobjp; 299507c3241Smlf struct dadk *dadkp; 300507c3241Smlf 301507c3241Smlf dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP); 302507c3241Smlf if (!dkobjp) 303507c3241Smlf return (NULL); 304507c3241Smlf dadkp = (struct dadk *)(dkobjp+1); 305507c3241Smlf 306507c3241Smlf dkobjp->tg_ops = (struct tgdk_objops *)&dadk_ops; 307507c3241Smlf dkobjp->tg_data = (opaque_t)dadkp; 308507c3241Smlf dkobjp->tg_ext = &(dkobjp->tg_extblk); 309507c3241Smlf dadkp->dad_extp = &(dkobjp->tg_extblk); 310507c3241Smlf 311507c3241Smlf #ifdef DADK_DEBUG 312507c3241Smlf if (dadk_debug & DENT) 313507c3241Smlf PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp); 314507c3241Smlf #endif 315507c3241Smlf return (dkobjp); 316507c3241Smlf } 317507c3241Smlf 318507c3241Smlf int 319507c3241Smlf dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp, 320507c3241Smlf opaque_t bbhobjp, void *lkarg) 321507c3241Smlf { 322507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 323507c3241Smlf struct scsi_device *sdevp = (struct scsi_device *)devp; 324507c3241Smlf 325507c3241Smlf dadkp->dad_sd = devp; 326507c3241Smlf dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran; 327507c3241Smlf sdevp->sd_private = (caddr_t)dadkp; 328507c3241Smlf 329507c3241Smlf /* initialize the communication object */ 330507c3241Smlf dadkp->dad_com.com_data = (opaque_t)dadkp; 331507c3241Smlf dadkp->dad_com.com_ops = &dadk_com_ops; 332507c3241Smlf 333507c3241Smlf dadkp->dad_bbhobjp = bbhobjp; 334507c3241Smlf BBH_INIT(bbhobjp); 335507c3241Smlf 336507c3241Smlf dadkp->dad_flcobjp = flcobjp; 3372df1fe9cSrandyf mutex_init(&dadkp->dad_cmd_mutex, NULL, MUTEX_DRIVER, NULL); 3382df1fe9cSrandyf dadkp->dad_cmd_count = 0; 339507c3241Smlf return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg)); 340507c3241Smlf } 341507c3241Smlf 342507c3241Smlf int 343507c3241Smlf dadk_free(struct tgdk_obj *dkobjp) 344507c3241Smlf { 345507c3241Smlf TGDK_CLEANUP(dkobjp); 346507c3241Smlf kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk))); 347507c3241Smlf 348507c3241Smlf return (DDI_SUCCESS); 349507c3241Smlf } 350507c3241Smlf 351507c3241Smlf void 352507c3241Smlf dadk_cleanup(struct tgdk_obj *dkobjp) 353507c3241Smlf { 354507c3241Smlf struct dadk *dadkp; 355507c3241Smlf 356507c3241Smlf dadkp = (struct dadk *)(dkobjp->tg_data); 357507c3241Smlf if (dadkp->dad_sd) 358507c3241Smlf dadkp->dad_sd->sd_private = NULL; 359507c3241Smlf if (dadkp->dad_bbhobjp) { 360507c3241Smlf BBH_FREE(dadkp->dad_bbhobjp); 361507c3241Smlf dadkp->dad_bbhobjp = NULL; 362507c3241Smlf } 363507c3241Smlf if (dadkp->dad_flcobjp) { 364507c3241Smlf FLC_FREE(dadkp->dad_flcobjp); 365507c3241Smlf dadkp->dad_flcobjp = NULL; 366507c3241Smlf } 3672df1fe9cSrandyf mutex_destroy(&dadkp->dad_cmd_mutex); 368507c3241Smlf } 369507c3241Smlf 370507c3241Smlf /* ARGSUSED */ 371507c3241Smlf int 372507c3241Smlf dadk_probe(opaque_t objp, int kmsflg) 373507c3241Smlf { 374507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 375507c3241Smlf struct scsi_device *devp; 376507c3241Smlf char name[80]; 377507c3241Smlf 378507c3241Smlf devp = dadkp->dad_sd; 379507c3241Smlf if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) || 380507c3241Smlf (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) { 381507c3241Smlf return (DDI_PROBE_FAILURE); 382507c3241Smlf } 383507c3241Smlf 384507c3241Smlf switch (devp->sd_inq->inq_dtype) { 385507c3241Smlf case DTYPE_DIRECT: 386507c3241Smlf dadkp->dad_ctype = DKC_DIRECT; 387507c3241Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK; 388507c3241Smlf dadkp->dad_extp->tg_ctype = DKC_DIRECT; 389507c3241Smlf break; 390507c3241Smlf case DTYPE_RODIRECT: /* eg cdrom */ 391507c3241Smlf dadkp->dad_ctype = DKC_CDROM; 392507c3241Smlf dadkp->dad_extp->tg_rdonly = 1; 393507c3241Smlf dadkp->dad_rdonly = 1; 394507c3241Smlf dadkp->dad_cdrom = 1; 395507c3241Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_CD; 396507c3241Smlf dadkp->dad_extp->tg_ctype = DKC_CDROM; 397507c3241Smlf break; 398507c3241Smlf case DTYPE_WORM: 399507c3241Smlf case DTYPE_OPTICAL: 400507c3241Smlf default: 401507c3241Smlf return (DDI_PROBE_FAILURE); 402507c3241Smlf } 403507c3241Smlf 404507c3241Smlf dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb; 405507c3241Smlf 406507c3241Smlf dadkp->dad_secshf = SCTRSHFT; 407507c3241Smlf dadkp->dad_blkshf = 0; 408507c3241Smlf 409507c3241Smlf /* display the device name */ 410507c3241Smlf (void) strcpy(name, "Vendor '"); 411507c3241Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]); 412507c3241Smlf (void) strcat(name, "' Product '"); 413507c3241Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]); 414507c3241Smlf (void) strcat(name, "'"); 415507c3241Smlf gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name); 416507c3241Smlf 417507c3241Smlf return (DDI_PROBE_SUCCESS); 418507c3241Smlf } 419507c3241Smlf 420507c3241Smlf 421507c3241Smlf /* ARGSUSED */ 422507c3241Smlf int 423507c3241Smlf dadk_attach(opaque_t objp) 424507c3241Smlf { 425507c3241Smlf return (DDI_SUCCESS); 426507c3241Smlf } 427507c3241Smlf 428507c3241Smlf int 429507c3241Smlf dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp) 430507c3241Smlf { 431507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 432507c3241Smlf /* free the old bbh object */ 433507c3241Smlf if (dadkp->dad_bbhobjp) 434507c3241Smlf BBH_FREE(dadkp->dad_bbhobjp); 435507c3241Smlf 436507c3241Smlf /* initialize the new bbh object */ 437507c3241Smlf dadkp->dad_bbhobjp = bbhobjp; 438507c3241Smlf BBH_INIT(bbhobjp); 439507c3241Smlf 440507c3241Smlf return (DDI_SUCCESS); 441507c3241Smlf } 442507c3241Smlf 443507c3241Smlf /* ARGSUSED */ 444507c3241Smlf int 445507c3241Smlf dadk_open(opaque_t objp, int flag) 446507c3241Smlf { 447507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 448507c3241Smlf int error; 449507c3241Smlf int wce; 450507c3241Smlf 451507c3241Smlf if (!dadkp->dad_rmb) { 452507c3241Smlf if (dadkp->dad_phyg.g_cap) { 453507c3241Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 454507c3241Smlf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 455507c3241Smlf return (DDI_SUCCESS); 456507c3241Smlf } 457507c3241Smlf } else { 458507c3241Smlf mutex_enter(&dadkp->dad_mutex); 459507c3241Smlf dadkp->dad_iostate = DKIO_NONE; 460507c3241Smlf cv_broadcast(&dadkp->dad_state_cv); 461507c3241Smlf mutex_exit(&dadkp->dad_mutex); 462507c3241Smlf 4632df1fe9cSrandyf if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, 4642df1fe9cSrandyf DADK_SILENT) || 465507c3241Smlf dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) || 4662df1fe9cSrandyf dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, 4672df1fe9cSrandyf DADK_SILENT)) { 468507c3241Smlf return (DDI_FAILURE); 469507c3241Smlf } 470507c3241Smlf 471507c3241Smlf mutex_enter(&dadkp->dad_mutex); 472507c3241Smlf dadkp->dad_iostate = DKIO_INSERTED; 473507c3241Smlf cv_broadcast(&dadkp->dad_state_cv); 474507c3241Smlf mutex_exit(&dadkp->dad_mutex); 475507c3241Smlf } 476507c3241Smlf 477507c3241Smlf /* 478507c3241Smlf * get write cache enable state 479507c3241Smlf * If there is an error, must assume that write cache 480507c3241Smlf * is enabled. 481507c3241Smlf * NOTE: Since there is currently no Solaris mechanism to 482507c3241Smlf * change the state of the Write Cache Enable feature, 483507c3241Smlf * this code just checks the value of the WCE bit 484507c3241Smlf * obtained at device init time. If a mechanism 485507c3241Smlf * is added to the driver to change WCE, dad_wce 486507c3241Smlf * must be updated appropriately. 487507c3241Smlf */ 4882df1fe9cSrandyf error = dadk_ctl_ioctl(dadkp, DIOCTL_GETWCE, 4894d27faddSmarx (uintptr_t)&wce, FKIOCTL | FNATIVE); 490507c3241Smlf mutex_enter(&dadkp->dad_mutex); 491507c3241Smlf dadkp->dad_wce = (error != 0) || (wce != 0); 492507c3241Smlf mutex_exit(&dadkp->dad_mutex); 493507c3241Smlf 494507c3241Smlf /* logical disk geometry */ 4952df1fe9cSrandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETGEOM, 4964d27faddSmarx (uintptr_t)&dadkp->dad_logg, FKIOCTL | FNATIVE); 497507c3241Smlf if (dadkp->dad_logg.g_cap == 0) 498507c3241Smlf return (DDI_FAILURE); 499507c3241Smlf 500507c3241Smlf /* get physical disk geometry */ 5012df1fe9cSrandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETPHYGEOM, 5024d27faddSmarx (uintptr_t)&dadkp->dad_phyg, FKIOCTL | FNATIVE); 503507c3241Smlf if (dadkp->dad_phyg.g_cap == 0) 504507c3241Smlf return (DDI_FAILURE); 505507c3241Smlf 506507c3241Smlf dadk_setcap(dadkp); 507507c3241Smlf 5084d27faddSmarx dadk_create_errstats(dadkp, 5094d27faddSmarx ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 5104d27faddSmarx 511507c3241Smlf /* start profiling */ 512507c3241Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 513507c3241Smlf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 514507c3241Smlf 515507c3241Smlf return (DDI_SUCCESS); 516507c3241Smlf } 517507c3241Smlf 518507c3241Smlf static void 519507c3241Smlf dadk_setcap(struct dadk *dadkp) 520507c3241Smlf { 521507c3241Smlf int totsize; 522507c3241Smlf int i; 523507c3241Smlf 524507c3241Smlf totsize = dadkp->dad_phyg.g_secsiz; 525507c3241Smlf 526507c3241Smlf if (totsize == 0) { 527507c3241Smlf if (dadkp->dad_cdrom) { 528507c3241Smlf totsize = 2048; 529507c3241Smlf } else { 530507c3241Smlf totsize = NBPSCTR; 531507c3241Smlf } 532507c3241Smlf } else { 533507c3241Smlf /* Round down sector size to multiple of 512B */ 534507c3241Smlf totsize &= ~(NBPSCTR-1); 535507c3241Smlf } 536507c3241Smlf dadkp->dad_phyg.g_secsiz = totsize; 537507c3241Smlf 538507c3241Smlf /* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */ 539507c3241Smlf totsize >>= SCTRSHFT; 5402df1fe9cSrandyf for (i = 0; totsize != 1; i++, totsize >>= 1) 5412df1fe9cSrandyf ; 542507c3241Smlf dadkp->dad_blkshf = i; 543507c3241Smlf dadkp->dad_secshf = i + SCTRSHFT; 544507c3241Smlf } 545507c3241Smlf 546507c3241Smlf 5474d27faddSmarx static void 5484d27faddSmarx dadk_create_errstats(struct dadk *dadkp, int instance) 5494d27faddSmarx { 5504d27faddSmarx dadk_errstats_t *dep; 5514d27faddSmarx char kstatname[KSTAT_STRLEN]; 5524d27faddSmarx dadk_ioc_string_t dadk_ioc_string; 5534d27faddSmarx 5544d27faddSmarx if (dadkp->dad_errstats) 5554d27faddSmarx return; 5564d27faddSmarx 5574d27faddSmarx (void) sprintf(kstatname, "cmdk%d,error", instance); 5584d27faddSmarx dadkp->dad_errstats = kstat_create("cmdkerror", instance, 5594d27faddSmarx kstatname, "device_error", KSTAT_TYPE_NAMED, 5604d27faddSmarx sizeof (dadk_errstats_t) / sizeof (kstat_named_t), 5614d27faddSmarx KSTAT_FLAG_PERSISTENT); 5624d27faddSmarx 5634d27faddSmarx if (!dadkp->dad_errstats) 5644d27faddSmarx return; 5654d27faddSmarx 5664d27faddSmarx dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data; 5674d27faddSmarx 5684d27faddSmarx kstat_named_init(&dep->dadk_softerrs, 5694d27faddSmarx "Soft Errors", KSTAT_DATA_UINT32); 5704d27faddSmarx kstat_named_init(&dep->dadk_harderrs, 5714d27faddSmarx "Hard Errors", KSTAT_DATA_UINT32); 5724d27faddSmarx kstat_named_init(&dep->dadk_transerrs, 5734d27faddSmarx "Transport Errors", KSTAT_DATA_UINT32); 5744d27faddSmarx kstat_named_init(&dep->dadk_model, 5754d27faddSmarx "Model", KSTAT_DATA_CHAR); 5764d27faddSmarx kstat_named_init(&dep->dadk_revision, 5774d27faddSmarx "Revision", KSTAT_DATA_CHAR); 5784d27faddSmarx kstat_named_init(&dep->dadk_serial, 5794d27faddSmarx "Serial No", KSTAT_DATA_CHAR); 5804d27faddSmarx kstat_named_init(&dep->dadk_capacity, 5814d27faddSmarx "Size", KSTAT_DATA_ULONGLONG); 5824d27faddSmarx kstat_named_init(&dep->dadk_rq_media_err, 5834d27faddSmarx "Media Error", KSTAT_DATA_UINT32); 5844d27faddSmarx kstat_named_init(&dep->dadk_rq_ntrdy_err, 5854d27faddSmarx "Device Not Ready", KSTAT_DATA_UINT32); 5864d27faddSmarx kstat_named_init(&dep->dadk_rq_nodev_err, 5874d27faddSmarx "No Device", KSTAT_DATA_UINT32); 5884d27faddSmarx kstat_named_init(&dep->dadk_rq_recov_err, 5894d27faddSmarx "Recoverable", KSTAT_DATA_UINT32); 5904d27faddSmarx kstat_named_init(&dep->dadk_rq_illrq_err, 5914d27faddSmarx "Illegal Request", KSTAT_DATA_UINT32); 5924d27faddSmarx 5934d27faddSmarx dadkp->dad_errstats->ks_private = dep; 5944d27faddSmarx dadkp->dad_errstats->ks_update = nulldev; 5954d27faddSmarx kstat_install(dadkp->dad_errstats); 5964d27faddSmarx 5974d27faddSmarx /* get model */ 5984d27faddSmarx dep->dadk_model.value.c[0] = 0; 5994d27faddSmarx dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0]; 6001a5cb58cSmarx dadk_ioc_string.is_size = sizeof (dep->dadk_model.value.c); 6012df1fe9cSrandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETMODEL, 6024d27faddSmarx (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); 6034d27faddSmarx 6044d27faddSmarx /* get serial */ 6054d27faddSmarx dep->dadk_serial.value.c[0] = 0; 6064d27faddSmarx dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0]; 6071a5cb58cSmarx dadk_ioc_string.is_size = sizeof (dep->dadk_serial.value.c); 6082df1fe9cSrandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETSERIAL, 6094d27faddSmarx (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); 6104d27faddSmarx 6114d27faddSmarx /* Get revision */ 6124d27faddSmarx dep->dadk_revision.value.c[0] = 0; 6134d27faddSmarx 6144d27faddSmarx /* Get capacity */ 6154d27faddSmarx 6164d27faddSmarx dep->dadk_capacity.value.ui64 = 6174d27faddSmarx (uint64_t)dadkp->dad_logg.g_cap * 6184d27faddSmarx (uint64_t)dadkp->dad_logg.g_secsiz; 6194d27faddSmarx } 6204d27faddSmarx 6214d27faddSmarx 622507c3241Smlf int 623507c3241Smlf dadk_close(opaque_t objp) 624507c3241Smlf { 625507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 626507c3241Smlf 627507c3241Smlf if (dadkp->dad_rmb) { 628507c3241Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0, 629507c3241Smlf DADK_SILENT); 630507c3241Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT); 631507c3241Smlf } 632507c3241Smlf FLC_STOP_KSTAT(dadkp->dad_flcobjp); 6334d27faddSmarx 6344d27faddSmarx dadk_destroy_errstats(dadkp); 6354d27faddSmarx 636507c3241Smlf return (DDI_SUCCESS); 637507c3241Smlf } 638507c3241Smlf 6394d27faddSmarx static void 6404d27faddSmarx dadk_destroy_errstats(struct dadk *dadkp) 6414d27faddSmarx { 6424d27faddSmarx if (!dadkp->dad_errstats) 6434d27faddSmarx return; 6444d27faddSmarx 6454d27faddSmarx kstat_delete(dadkp->dad_errstats); 6464d27faddSmarx dadkp->dad_errstats = NULL; 6474d27faddSmarx } 6484d27faddSmarx 6494d27faddSmarx 650507c3241Smlf int 651507c3241Smlf dadk_strategy(opaque_t objp, struct buf *bp) 652507c3241Smlf { 653507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 654507c3241Smlf 655507c3241Smlf if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) { 656507c3241Smlf bioerror(bp, EROFS); 657507c3241Smlf return (DDI_FAILURE); 658507c3241Smlf } 659507c3241Smlf 660507c3241Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 661507c3241Smlf bioerror(bp, ENXIO); 662507c3241Smlf return (DDI_FAILURE); 663507c3241Smlf } 664507c3241Smlf 665507c3241Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 6662df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 6672df1fe9cSrandyf dadkp->dad_cmd_count++; 6682df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 669507c3241Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 670507c3241Smlf 671507c3241Smlf return (DDI_SUCCESS); 672507c3241Smlf } 673507c3241Smlf 674507c3241Smlf int 675507c3241Smlf dadk_dump(opaque_t objp, struct buf *bp) 676507c3241Smlf { 677507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 678507c3241Smlf struct cmpkt *pktp; 679507c3241Smlf 680507c3241Smlf if (dadkp->dad_rdonly) { 681507c3241Smlf bioerror(bp, EROFS); 682507c3241Smlf return (DDI_FAILURE); 683507c3241Smlf } 684507c3241Smlf 685507c3241Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 686507c3241Smlf bioerror(bp, ENXIO); 687507c3241Smlf return (DDI_FAILURE); 688507c3241Smlf } 689507c3241Smlf 690507c3241Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 691507c3241Smlf 692507c3241Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL); 693507c3241Smlf if (!pktp) { 694507c3241Smlf cmn_err(CE_WARN, "no resources for dumping"); 695507c3241Smlf bioerror(bp, EIO); 696507c3241Smlf return (DDI_FAILURE); 697507c3241Smlf } 698507c3241Smlf pktp->cp_flags |= CPF_NOINTR; 699507c3241Smlf 700507c3241Smlf (void) dadk_ioprep(dadkp, pktp); 701507c3241Smlf dadk_transport(dadkp, bp); 702507c3241Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 703507c3241Smlf 704507c3241Smlf while (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 705507c3241Smlf (void) dadk_iosetup(dadkp, pktp); 706507c3241Smlf dadk_transport(dadkp, bp); 707507c3241Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 708507c3241Smlf } 709507c3241Smlf 710507c3241Smlf if (pktp->cp_private) 711507c3241Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 712507c3241Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 713507c3241Smlf return (DDI_SUCCESS); 714507c3241Smlf } 715507c3241Smlf 716507c3241Smlf /* ARGSUSED */ 717507c3241Smlf int 718507c3241Smlf dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, 719507c3241Smlf cred_t *cred_p, int *rval_p) 720507c3241Smlf { 721507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 722507c3241Smlf 723507c3241Smlf switch (cmd) { 724507c3241Smlf case DKIOCGETDEF: 725507c3241Smlf { 726507c3241Smlf struct buf *bp; 727507c3241Smlf int err, head; 728507c3241Smlf unsigned char *secbuf; 729507c3241Smlf STRUCT_DECL(defect_header, adh); 730507c3241Smlf 731507c3241Smlf STRUCT_INIT(adh, flag & FMODELS); 732507c3241Smlf 733507c3241Smlf /* 734507c3241Smlf * copyin header .... 735507c3241Smlf * yields head number and buffer address 736507c3241Smlf */ 737507c3241Smlf if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh), 738507c3241Smlf flag)) 739507c3241Smlf return (EFAULT); 740507c3241Smlf head = STRUCT_FGET(adh, head); 741507c3241Smlf if (head < 0 || head >= dadkp->dad_phyg.g_head) 742507c3241Smlf return (ENXIO); 743507c3241Smlf secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP); 744507c3241Smlf if (!secbuf) 745507c3241Smlf return (ENOMEM); 746507c3241Smlf bp = getrbuf(KM_SLEEP); 747507c3241Smlf if (!bp) { 748507c3241Smlf kmem_free(secbuf, NBPSCTR); 749507c3241Smlf return (ENOMEM); 750507c3241Smlf } 751507c3241Smlf 752507c3241Smlf bp->b_edev = dev; 753507c3241Smlf bp->b_dev = cmpdev(dev); 754507c3241Smlf bp->b_flags = B_BUSY; 755507c3241Smlf bp->b_resid = 0; 756507c3241Smlf bp->b_bcount = NBPSCTR; 757507c3241Smlf bp->b_un.b_addr = (caddr_t)secbuf; 758507c3241Smlf bp->b_blkno = head; /* I had to put it somwhere! */ 759507c3241Smlf bp->b_forw = (struct buf *)dadkp; 760507c3241Smlf bp->b_back = (struct buf *)DCMD_GETDEF; 761507c3241Smlf 7622df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 7632df1fe9cSrandyf dadkp->dad_cmd_count++; 7642df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 765507c3241Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 766507c3241Smlf err = biowait(bp); 767507c3241Smlf if (!err) { 768507c3241Smlf if (ddi_copyout((caddr_t)secbuf, 769507c3241Smlf STRUCT_FGETP(adh, buffer), NBPSCTR, flag)) 770507c3241Smlf err = ENXIO; 771507c3241Smlf } 772507c3241Smlf kmem_free(secbuf, NBPSCTR); 773507c3241Smlf freerbuf(bp); 774507c3241Smlf return (err); 775507c3241Smlf } 776507c3241Smlf case DIOCTL_RWCMD: 777507c3241Smlf { 778507c3241Smlf struct dadkio_rwcmd *rwcmdp; 779507c3241Smlf int status, rw; 780507c3241Smlf 781507c3241Smlf /* 782507c3241Smlf * copied in by cmdk and, if necessary, converted to the 783507c3241Smlf * correct datamodel 784507c3241Smlf */ 785507c3241Smlf rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg; 786507c3241Smlf 787507c3241Smlf /* 788507c3241Smlf * handle the complex cases here; we pass these 789507c3241Smlf * through to the driver, which will queue them and 790507c3241Smlf * handle the requests asynchronously. The simpler 791507c3241Smlf * cases ,which can return immediately, fail here, and 792507c3241Smlf * the request reverts to the dadk_ioctl routine, while 793507c3241Smlf * will reroute them directly to the ata driver. 794507c3241Smlf */ 795507c3241Smlf switch (rwcmdp->cmd) { 796507c3241Smlf case DADKIO_RWCMD_READ : 797507c3241Smlf /*FALLTHROUGH*/ 798507c3241Smlf case DADKIO_RWCMD_WRITE: 799507c3241Smlf rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ? 800507c3241Smlf B_WRITE : B_READ); 801507c3241Smlf status = dadk_dk_buf_setup(dadkp, 802507c3241Smlf (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ? 803507c3241Smlf UIO_SYSSPACE : UIO_USERSPACE), rw); 804507c3241Smlf return (status); 805507c3241Smlf default: 806507c3241Smlf return (EINVAL); 807507c3241Smlf } 808507c3241Smlf } 8090f2c99a4Syt160523 case DKIOC_UPDATEFW: 8100f2c99a4Syt160523 8110f2c99a4Syt160523 /* 8120f2c99a4Syt160523 * Require PRIV_ALL privilege to invoke DKIOC_UPDATEFW 8130f2c99a4Syt160523 * to protect the firmware update from malicious use 8140f2c99a4Syt160523 */ 8150f2c99a4Syt160523 if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0) 8160f2c99a4Syt160523 return (EPERM); 8170f2c99a4Syt160523 else 8182df1fe9cSrandyf return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); 8190f2c99a4Syt160523 820507c3241Smlf case DKIOCFLUSHWRITECACHE: 821507c3241Smlf { 822507c3241Smlf struct buf *bp; 823507c3241Smlf int err = 0; 824507c3241Smlf struct dk_callback *dkc = (struct dk_callback *)arg; 825507c3241Smlf struct cmpkt *pktp; 826507c3241Smlf int is_sync = 1; 827507c3241Smlf 828507c3241Smlf mutex_enter(&dadkp->dad_mutex); 829507c3241Smlf if (dadkp->dad_noflush || ! dadkp->dad_wce) { 830507c3241Smlf err = dadkp->dad_noflush ? ENOTSUP : 0; 831507c3241Smlf mutex_exit(&dadkp->dad_mutex); 832507c3241Smlf /* 833507c3241Smlf * If a callback was requested: a 834507c3241Smlf * callback will always be done if the 835507c3241Smlf * caller saw the DKIOCFLUSHWRITECACHE 836507c3241Smlf * ioctl return 0, and never done if the 837507c3241Smlf * caller saw the ioctl return an error. 838507c3241Smlf */ 839507c3241Smlf if ((flag & FKIOCTL) && dkc != NULL && 840507c3241Smlf dkc->dkc_callback != NULL) { 841507c3241Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, 842507c3241Smlf err); 843507c3241Smlf /* 844507c3241Smlf * Did callback and reported error. 845507c3241Smlf * Since we did a callback, ioctl 846507c3241Smlf * should return 0. 847507c3241Smlf */ 848507c3241Smlf err = 0; 849507c3241Smlf } 850507c3241Smlf return (err); 851507c3241Smlf } 852507c3241Smlf mutex_exit(&dadkp->dad_mutex); 853507c3241Smlf 854507c3241Smlf bp = getrbuf(KM_SLEEP); 855507c3241Smlf 856507c3241Smlf bp->b_edev = dev; 857507c3241Smlf bp->b_dev = cmpdev(dev); 858507c3241Smlf bp->b_flags = B_BUSY; 859507c3241Smlf bp->b_resid = 0; 860507c3241Smlf bp->b_bcount = 0; 861507c3241Smlf SET_BP_SEC(bp, 0); 862507c3241Smlf 863507c3241Smlf if ((flag & FKIOCTL) && dkc != NULL && 864507c3241Smlf dkc->dkc_callback != NULL) { 865507c3241Smlf struct dk_callback *dkc2 = 866507c3241Smlf (struct dk_callback *)kmem_zalloc( 867507c3241Smlf sizeof (struct dk_callback), KM_SLEEP); 868507c3241Smlf 869507c3241Smlf bcopy(dkc, dkc2, sizeof (*dkc2)); 870744947dcSTom Erickson bp->b_private = dkc2; 871507c3241Smlf bp->b_iodone = dadk_flushdone; 872507c3241Smlf is_sync = 0; 873507c3241Smlf } 874507c3241Smlf 875507c3241Smlf /* 876507c3241Smlf * Setup command pkt 877507c3241Smlf * dadk_pktprep() can't fail since DDI_DMA_SLEEP set 878507c3241Smlf */ 879507c3241Smlf pktp = dadk_pktprep(dadkp, NULL, bp, 880507c3241Smlf dadk_iodone, DDI_DMA_SLEEP, NULL); 881507c3241Smlf 882507c3241Smlf pktp->cp_time = DADK_FLUSH_CACHE_TIME; 883507c3241Smlf 884507c3241Smlf *((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE; 885507c3241Smlf pktp->cp_byteleft = 0; 886507c3241Smlf pktp->cp_private = NULL; 887507c3241Smlf pktp->cp_secleft = 0; 888507c3241Smlf pktp->cp_srtsec = -1; 889507c3241Smlf pktp->cp_bytexfer = 0; 890507c3241Smlf 891507c3241Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 892507c3241Smlf 8932df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 8942df1fe9cSrandyf dadkp->dad_cmd_count++; 8952df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 896507c3241Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 897507c3241Smlf 898507c3241Smlf if (is_sync) { 899507c3241Smlf err = biowait(bp); 900507c3241Smlf freerbuf(bp); 901507c3241Smlf } 902507c3241Smlf return (err); 903507c3241Smlf } 904507c3241Smlf default: 905507c3241Smlf if (!dadkp->dad_rmb) 9062df1fe9cSrandyf return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); 907507c3241Smlf } 908507c3241Smlf 909507c3241Smlf switch (cmd) { 910507c3241Smlf case CDROMSTOP: 911507c3241Smlf return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 912507c3241Smlf 0, DADK_SILENT)); 913507c3241Smlf case CDROMSTART: 914507c3241Smlf return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 915507c3241Smlf 0, DADK_SILENT)); 916507c3241Smlf case DKIOCLOCK: 917507c3241Smlf return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT)); 918507c3241Smlf case DKIOCUNLOCK: 919507c3241Smlf return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT)); 920507c3241Smlf case DKIOCEJECT: 921507c3241Smlf case CDROMEJECT: 922507c3241Smlf { 923507c3241Smlf int ret; 924507c3241Smlf 925507c3241Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, 926507c3241Smlf DADK_SILENT)) { 927507c3241Smlf return (ret); 928507c3241Smlf } 929507c3241Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0, 930507c3241Smlf DADK_SILENT)) { 931507c3241Smlf return (ret); 932507c3241Smlf } 933507c3241Smlf mutex_enter(&dadkp->dad_mutex); 934507c3241Smlf dadkp->dad_iostate = DKIO_EJECTED; 935507c3241Smlf cv_broadcast(&dadkp->dad_state_cv); 936507c3241Smlf mutex_exit(&dadkp->dad_mutex); 937507c3241Smlf 938507c3241Smlf return (0); 939507c3241Smlf 940507c3241Smlf } 941507c3241Smlf default: 942507c3241Smlf return (ENOTTY); 943507c3241Smlf /* 944507c3241Smlf * cdrom audio commands 945507c3241Smlf */ 946507c3241Smlf case CDROMPAUSE: 947507c3241Smlf cmd = DCMD_PAUSE; 948507c3241Smlf break; 949507c3241Smlf case CDROMRESUME: 950507c3241Smlf cmd = DCMD_RESUME; 951507c3241Smlf break; 952507c3241Smlf case CDROMPLAYMSF: 953507c3241Smlf cmd = DCMD_PLAYMSF; 954507c3241Smlf break; 955507c3241Smlf case CDROMPLAYTRKIND: 956507c3241Smlf cmd = DCMD_PLAYTRKIND; 957507c3241Smlf break; 958507c3241Smlf case CDROMREADTOCHDR: 959507c3241Smlf cmd = DCMD_READTOCHDR; 960507c3241Smlf break; 961507c3241Smlf case CDROMREADTOCENTRY: 962507c3241Smlf cmd = DCMD_READTOCENT; 963507c3241Smlf break; 964507c3241Smlf case CDROMVOLCTRL: 965507c3241Smlf cmd = DCMD_VOLCTRL; 966507c3241Smlf break; 967507c3241Smlf case CDROMSUBCHNL: 968507c3241Smlf cmd = DCMD_SUBCHNL; 969507c3241Smlf break; 970507c3241Smlf case CDROMREADMODE2: 971507c3241Smlf cmd = DCMD_READMODE2; 972507c3241Smlf break; 973507c3241Smlf case CDROMREADMODE1: 974507c3241Smlf cmd = DCMD_READMODE1; 975507c3241Smlf break; 976507c3241Smlf case CDROMREADOFFSET: 977507c3241Smlf cmd = DCMD_READOFFSET; 978507c3241Smlf break; 979507c3241Smlf } 980507c3241Smlf return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0)); 981507c3241Smlf } 982507c3241Smlf 983507c3241Smlf int 984507c3241Smlf dadk_flushdone(struct buf *bp) 985507c3241Smlf { 986744947dcSTom Erickson struct dk_callback *dkc = bp->b_private; 987507c3241Smlf 988507c3241Smlf ASSERT(dkc != NULL && dkc->dkc_callback != NULL); 989507c3241Smlf 990507c3241Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp)); 991507c3241Smlf 992507c3241Smlf kmem_free(dkc, sizeof (*dkc)); 993507c3241Smlf freerbuf(bp); 994507c3241Smlf return (0); 995507c3241Smlf } 996507c3241Smlf 997507c3241Smlf int 998507c3241Smlf dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 999507c3241Smlf { 1000507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1001507c3241Smlf 1002507c3241Smlf bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p, 1003507c3241Smlf sizeof (struct tgdk_geom)); 1004507c3241Smlf return (DDI_SUCCESS); 1005507c3241Smlf } 1006507c3241Smlf 1007507c3241Smlf int 1008507c3241Smlf dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 1009507c3241Smlf { 1010507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1011507c3241Smlf bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p, 1012507c3241Smlf sizeof (struct tgdk_geom)); 1013507c3241Smlf return (DDI_SUCCESS); 1014507c3241Smlf } 1015507c3241Smlf 1016507c3241Smlf int 1017507c3241Smlf dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 1018507c3241Smlf { 1019507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1020507c3241Smlf 1021507c3241Smlf dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl; 1022507c3241Smlf dadkp->dad_logg.g_head = dkgeom_p->g_head; 1023507c3241Smlf dadkp->dad_logg.g_sec = dkgeom_p->g_sec; 1024507c3241Smlf dadkp->dad_logg.g_cap = dkgeom_p->g_cap; 1025507c3241Smlf return (DDI_SUCCESS); 1026507c3241Smlf } 1027507c3241Smlf 1028507c3241Smlf 1029507c3241Smlf tgdk_iob_handle 1030507c3241Smlf dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg) 1031507c3241Smlf { 1032507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1033507c3241Smlf struct buf *bp; 1034507c3241Smlf struct tgdk_iob *iobp; 1035507c3241Smlf size_t rlen; 1036507c3241Smlf 1037507c3241Smlf iobp = kmem_zalloc(sizeof (*iobp), kmsflg); 1038507c3241Smlf if (iobp == NULL) 1039507c3241Smlf return (NULL); 1040507c3241Smlf if ((bp = getrbuf(kmsflg)) == NULL) { 1041507c3241Smlf kmem_free(iobp, sizeof (*iobp)); 1042507c3241Smlf return (NULL); 1043507c3241Smlf } 1044507c3241Smlf 1045507c3241Smlf iobp->b_psec = LBLK2SEC(blkno, dadkp->dad_blkshf); 1046507c3241Smlf iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT; 1047507c3241Smlf iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1) 1048507c3241Smlf >> dadkp->dad_secshf) << dadkp->dad_secshf; 1049507c3241Smlf 1050507c3241Smlf bp->b_un.b_addr = 0; 1051507c3241Smlf /* 1052507c3241Smlf * use i_ddi_mem_alloc() for now until we have an interface to allocate 1053*b89e420aSGarrett D'Amore * memory for DMA which doesn't require a DMA handle. 1054507c3241Smlf */ 1055507c3241Smlf if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr, 1056507c3241Smlf (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL, 1057507c3241Smlf &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) { 1058507c3241Smlf freerbuf(bp); 1059507c3241Smlf kmem_free(iobp, sizeof (*iobp)); 1060507c3241Smlf return (NULL); 1061507c3241Smlf } 1062507c3241Smlf iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC; 1063507c3241Smlf iobp->b_bp = bp; 1064507c3241Smlf iobp->b_lblk = blkno; 1065507c3241Smlf iobp->b_xfer = xfer; 1066507c3241Smlf iobp->b_lblk = blkno; 1067507c3241Smlf iobp->b_xfer = xfer; 1068507c3241Smlf return (iobp); 1069507c3241Smlf } 1070507c3241Smlf 1071507c3241Smlf /* ARGSUSED */ 1072507c3241Smlf int 1073507c3241Smlf dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp) 1074507c3241Smlf { 1075507c3241Smlf struct buf *bp; 1076507c3241Smlf 1077507c3241Smlf if (iobp) { 1078507c3241Smlf if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) { 1079507c3241Smlf bp = iobp->b_bp; 1080507c3241Smlf if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC)) 10817b93957cSeota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 1082507c3241Smlf freerbuf(bp); 1083507c3241Smlf } 1084507c3241Smlf kmem_free(iobp, sizeof (*iobp)); 1085507c3241Smlf } 1086507c3241Smlf return (DDI_SUCCESS); 1087507c3241Smlf } 1088507c3241Smlf 1089507c3241Smlf /* ARGSUSED */ 1090507c3241Smlf caddr_t 1091507c3241Smlf dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp) 1092507c3241Smlf { 1093507c3241Smlf return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff); 1094507c3241Smlf } 1095507c3241Smlf 1096507c3241Smlf 1097507c3241Smlf caddr_t 1098507c3241Smlf dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw) 1099507c3241Smlf { 1100507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1101507c3241Smlf struct buf *bp; 1102507c3241Smlf int err; 1103507c3241Smlf 1104507c3241Smlf bp = iobp->b_bp; 1105507c3241Smlf if (dadkp->dad_rdonly && !(rw & B_READ)) { 1106507c3241Smlf bioerror(bp, EROFS); 1107507c3241Smlf return (NULL); 1108507c3241Smlf } 1109507c3241Smlf 1110507c3241Smlf bp->b_flags |= (B_BUSY | rw); 1111507c3241Smlf bp->b_bcount = iobp->b_pbytecnt; 1112507c3241Smlf SET_BP_SEC(bp, iobp->b_psec); 1113507c3241Smlf bp->av_back = (struct buf *)0; 1114507c3241Smlf bp->b_resid = 0; 1115507c3241Smlf 1116507c3241Smlf /* call flow control */ 11172df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 11182df1fe9cSrandyf dadkp->dad_cmd_count++; 11192df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 1120507c3241Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 1121507c3241Smlf err = biowait(bp); 1122507c3241Smlf 1123507c3241Smlf bp->b_bcount = iobp->b_xfer; 1124507c3241Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 1125507c3241Smlf 1126507c3241Smlf if (err) 1127507c3241Smlf return (NULL); 1128507c3241Smlf 1129507c3241Smlf return (bp->b_un.b_addr+iobp->b_pbyteoff); 1130507c3241Smlf } 1131507c3241Smlf 1132507c3241Smlf static void 1133507c3241Smlf dadk_transport(opaque_t com_data, struct buf *bp) 1134507c3241Smlf { 1135507c3241Smlf struct dadk *dadkp = (struct dadk *)com_data; 1136507c3241Smlf 1137507c3241Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) == 1138507c3241Smlf CTL_SEND_SUCCESS) 1139507c3241Smlf return; 1140507c3241Smlf dadk_restart((void*)GDA_BP_PKT(bp)); 1141507c3241Smlf } 1142507c3241Smlf 1143507c3241Smlf static int 1144507c3241Smlf dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg) 1145507c3241Smlf { 1146507c3241Smlf struct cmpkt *pktp; 1147507c3241Smlf struct dadk *dadkp = (struct dadk *)com_data; 1148507c3241Smlf 1149507c3241Smlf if (GDA_BP_PKT(bp)) 1150507c3241Smlf return (DDI_SUCCESS); 1151507c3241Smlf 1152507c3241Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg); 1153507c3241Smlf if (!pktp) 1154507c3241Smlf return (DDI_FAILURE); 1155507c3241Smlf 1156507c3241Smlf return (dadk_ioprep(dadkp, pktp)); 1157507c3241Smlf } 1158507c3241Smlf 1159507c3241Smlf /* 1160507c3241Smlf * Read, Write preparation 1161507c3241Smlf */ 1162507c3241Smlf static int 1163507c3241Smlf dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp) 1164507c3241Smlf { 1165507c3241Smlf struct buf *bp; 1166507c3241Smlf 1167507c3241Smlf bp = pktp->cp_bp; 1168507c3241Smlf if (bp->b_forw == (struct buf *)dadkp) 1169507c3241Smlf *((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back; 1170507c3241Smlf 1171507c3241Smlf else if (bp->b_flags & B_READ) 1172507c3241Smlf *((char *)(pktp->cp_cdbp)) = DCMD_READ; 1173507c3241Smlf else 1174507c3241Smlf *((char *)(pktp->cp_cdbp)) = DCMD_WRITE; 1175507c3241Smlf pktp->cp_byteleft = bp->b_bcount; 1176507c3241Smlf 1177507c3241Smlf /* setup the bad block list handle */ 1178507c3241Smlf pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp); 1179507c3241Smlf return (dadk_iosetup(dadkp, pktp)); 1180507c3241Smlf } 1181507c3241Smlf 1182507c3241Smlf static int 1183507c3241Smlf dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp) 1184507c3241Smlf { 1185507c3241Smlf struct buf *bp; 1186507c3241Smlf bbh_cookie_t bbhckp; 1187507c3241Smlf int seccnt; 1188507c3241Smlf 1189507c3241Smlf seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf; 1190507c3241Smlf pktp->cp_secleft -= seccnt; 1191507c3241Smlf 1192507c3241Smlf if (pktp->cp_secleft) { 1193507c3241Smlf pktp->cp_srtsec += seccnt; 1194507c3241Smlf } else { 1195507c3241Smlf /* get the first cookie from the bad block list */ 1196507c3241Smlf if (!pktp->cp_private) { 1197507c3241Smlf bp = pktp->cp_bp; 1198507c3241Smlf pktp->cp_srtsec = GET_BP_SEC(bp); 1199507c3241Smlf pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf); 1200507c3241Smlf } else { 1201507c3241Smlf bbhckp = BBH_HTOC(dadkp->dad_bbhobjp, 1202507c3241Smlf pktp->cp_private); 1203507c3241Smlf pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp, 1204507c3241Smlf bbhckp); 1205507c3241Smlf pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp, 1206507c3241Smlf bbhckp); 1207507c3241Smlf } 1208507c3241Smlf } 1209507c3241Smlf 1210507c3241Smlf pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf; 1211507c3241Smlf 1212507c3241Smlf if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) { 1213507c3241Smlf return (DDI_SUCCESS); 1214507c3241Smlf } else { 1215507c3241Smlf return (DDI_FAILURE); 1216507c3241Smlf } 1217507c3241Smlf 1218507c3241Smlf 1219507c3241Smlf 1220507c3241Smlf 1221507c3241Smlf } 1222507c3241Smlf 1223507c3241Smlf static struct cmpkt * 1224507c3241Smlf dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp, 1225507c3241Smlf void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg) 1226507c3241Smlf { 1227507c3241Smlf struct cmpkt *pktp; 1228507c3241Smlf 1229507c3241Smlf pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func, 1230507c3241Smlf arg); 1231507c3241Smlf 1232507c3241Smlf if (pktp) { 1233507c3241Smlf pktp->cp_callback = dadk_pktcb; 1234507c3241Smlf pktp->cp_time = DADK_IO_TIME; 1235507c3241Smlf pktp->cp_flags = 0; 1236507c3241Smlf pktp->cp_iodone = cb_func; 1237507c3241Smlf pktp->cp_dev_private = (opaque_t)dadkp; 1238507c3241Smlf 1239507c3241Smlf } 1240507c3241Smlf 1241507c3241Smlf return (pktp); 1242507c3241Smlf } 1243507c3241Smlf 1244507c3241Smlf 1245507c3241Smlf static void 1246507c3241Smlf dadk_restart(void *vpktp) 1247507c3241Smlf { 1248507c3241Smlf struct cmpkt *pktp = (struct cmpkt *)vpktp; 1249507c3241Smlf 1250507c3241Smlf if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN) 1251507c3241Smlf return; 1252507c3241Smlf pktp->cp_iodone(pktp->cp_bp); 1253507c3241Smlf } 1254507c3241Smlf 1255507c3241Smlf static int 1256507c3241Smlf dadk_ioretry(struct cmpkt *pktp, int action) 1257507c3241Smlf { 1258507c3241Smlf struct buf *bp; 1259507c3241Smlf struct dadk *dadkp = PKT2DADK(pktp); 1260507c3241Smlf 1261507c3241Smlf switch (action) { 1262507c3241Smlf case QUE_COMMAND: 1263507c3241Smlf if (pktp->cp_retry++ < DADK_RETRY_COUNT) { 1264507c3241Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 1265507c3241Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == 1266507c3241Smlf CTL_SEND_SUCCESS) { 1267507c3241Smlf return (JUST_RETURN); 1268507c3241Smlf } 1269507c3241Smlf gda_log(dadkp->dad_sd->sd_dev, dadk_name, 12702df1fe9cSrandyf CE_WARN, "transport of command fails\n"); 1271507c3241Smlf } else 1272507c3241Smlf gda_log(dadkp->dad_sd->sd_dev, 1273507c3241Smlf dadk_name, CE_WARN, 1274507c3241Smlf "exceeds maximum number of retries\n"); 1275507c3241Smlf bioerror(pktp->cp_bp, ENXIO); 1276507c3241Smlf /*FALLTHROUGH*/ 1277507c3241Smlf case COMMAND_DONE_ERROR: 1278507c3241Smlf bp = pktp->cp_bp; 1279507c3241Smlf bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer + 1280507c3241Smlf pktp->cp_resid; 1281507c3241Smlf if (geterror(bp) == 0) { 1282507c3241Smlf if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) && 1283507c3241Smlf (pktp->cp_dev_private == (opaque_t)dadkp) && 1284507c3241Smlf ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) { 1285507c3241Smlf /* 1286507c3241Smlf * Flag "unimplemented" responses for 1287507c3241Smlf * DCMD_FLUSH_CACHE as ENOTSUP 1288507c3241Smlf */ 1289507c3241Smlf bioerror(bp, ENOTSUP); 1290507c3241Smlf mutex_enter(&dadkp->dad_mutex); 1291507c3241Smlf dadkp->dad_noflush = 1; 1292507c3241Smlf mutex_exit(&dadkp->dad_mutex); 1293507c3241Smlf } else { 1294507c3241Smlf bioerror(bp, EIO); 1295507c3241Smlf } 1296507c3241Smlf } 1297507c3241Smlf /*FALLTHROUGH*/ 1298507c3241Smlf case COMMAND_DONE: 1299507c3241Smlf default: 1300507c3241Smlf return (COMMAND_DONE); 1301507c3241Smlf } 1302507c3241Smlf } 1303507c3241Smlf 1304507c3241Smlf 1305507c3241Smlf static void 1306507c3241Smlf dadk_pktcb(struct cmpkt *pktp) 1307507c3241Smlf { 1308507c3241Smlf int action; 1309507c3241Smlf struct dadkio_rwcmd *rwcmdp; 1310507c3241Smlf 1311507c3241Smlf rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru; /* ioctl packet */ 1312507c3241Smlf 1313507c3241Smlf if (pktp->cp_reason == CPS_SUCCESS) { 1314507c3241Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) 1315507c3241Smlf rwcmdp->status.status = DADKIO_STAT_NO_ERROR; 1316507c3241Smlf pktp->cp_iodone(pktp->cp_bp); 1317507c3241Smlf return; 1318507c3241Smlf } 1319507c3241Smlf 1320507c3241Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) { 1321507c3241Smlf if (pktp->cp_reason == CPS_CHKERR) 1322507c3241Smlf dadk_recorderr(pktp, rwcmdp); 1323507c3241Smlf dadk_iodone(pktp->cp_bp); 1324507c3241Smlf return; 1325507c3241Smlf } 1326507c3241Smlf 1327507c3241Smlf if (pktp->cp_reason == CPS_CHKERR) 1328507c3241Smlf action = dadk_chkerr(pktp); 1329507c3241Smlf else 1330507c3241Smlf action = COMMAND_DONE_ERROR; 1331507c3241Smlf 1332507c3241Smlf if (action == JUST_RETURN) 1333507c3241Smlf return; 1334507c3241Smlf 13351dc8bc23Szk194757 /* 13361dc8bc23Szk194757 * If we are panicking don't retry the command 13371dc8bc23Szk194757 * just fail it so we can go down completing all 13381dc8bc23Szk194757 * of the buffers. 13391dc8bc23Szk194757 */ 13401dc8bc23Szk194757 if (ddi_in_panic() && action == QUE_COMMAND) 13411dc8bc23Szk194757 action = COMMAND_DONE_ERROR; 13421dc8bc23Szk194757 1343507c3241Smlf if (action != COMMAND_DONE) { 1344507c3241Smlf if ((dadk_ioretry(pktp, action)) == JUST_RETURN) 1345507c3241Smlf return; 1346507c3241Smlf } 1347507c3241Smlf pktp->cp_iodone(pktp->cp_bp); 1348507c3241Smlf } 1349507c3241Smlf 1350507c3241Smlf 1351507c3241Smlf 1352507c3241Smlf static struct dadkio_derr dadk_errtab[] = { 1353507c3241Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 0 DERR_SUCCESS */ 1354507c3241Smlf {QUE_COMMAND, GDA_FATAL}, /* 1 DERR_AMNF */ 1355507c3241Smlf {QUE_COMMAND, GDA_FATAL}, /* 2 DERR_TKONF */ 1356507c3241Smlf {COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT */ 1357507c3241Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 4 DERR_DWF */ 1358507c3241Smlf {QUE_COMMAND, GDA_FATAL}, /* 5 DERR_IDNF */ 1359507c3241Smlf {JUST_RETURN, GDA_INFORMATIONAL}, /* 6 DERR_BUSY */ 1360507c3241Smlf {QUE_COMMAND, GDA_FATAL}, /* 7 DERR_UNC */ 1361507c3241Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 8 DERR_BBK */ 1362507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 9 DERR_INVCDB */ 1363507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 10 DERR_HARD */ 1364507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 11 DERR_ILI */ 1365507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 12 DERR_EOM */ 1366507c3241Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 13 DERR_MCR */ 1367507c3241Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 14 DERR_RECOVER */ 1368507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 15 DERR_NOTREADY */ 1369507c3241Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 16 DERR_MEDIUM */ 1370507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 17 DERR_HW */ 1371507c3241Smlf {COMMAND_DONE, GDA_FATAL}, /* 18 DERR_ILL */ 1372507c3241Smlf {COMMAND_DONE, GDA_FATAL}, /* 19 DERR_UNIT_ATTN */ 1373507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 20 DERR_DATA_PROT */ 1374507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 21 DERR_MISCOMPARE */ 1375507c3241Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 22 DERR_ICRC */ 1376507c3241Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 23 DERR_RESV */ 1377507c3241Smlf }; 1378507c3241Smlf 1379507c3241Smlf static int 1380507c3241Smlf dadk_chkerr(struct cmpkt *pktp) 1381507c3241Smlf { 1382342440ecSPrasad Singamsetty daddr_t err_blkno; 13834d27faddSmarx struct dadk *dadkp = PKT2DADK(pktp); 13844d27faddSmarx dadk_errstats_t *dep; 13854d27faddSmarx int scb = *(char *)pktp->cp_scbp; 1386507c3241Smlf 13874d27faddSmarx if (scb == DERR_SUCCESS) { 13884d27faddSmarx if (pktp->cp_retry != 0 && dadkp->dad_errstats != NULL) { 13894d27faddSmarx dep = (dadk_errstats_t *) 13904d27faddSmarx dadkp->dad_errstats->ks_data; 13914d27faddSmarx dep->dadk_rq_recov_err.value.ui32++; 13924d27faddSmarx } 1393507c3241Smlf return (COMMAND_DONE); 13944d27faddSmarx } 1395507c3241Smlf 1396507c3241Smlf if (pktp->cp_retry) { 1397507c3241Smlf err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer - 1398507c3241Smlf pktp->cp_resid) >> dadkp->dad_secshf); 1399507c3241Smlf } else 1400507c3241Smlf err_blkno = -1; 1401507c3241Smlf 14024d27faddSmarx if (dadkp->dad_errstats != NULL) { 14034d27faddSmarx dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data; 14044d27faddSmarx 14051a5cb58cSmarx switch (dadk_errtab[scb].d_severity) { 14061a5cb58cSmarx case GDA_RETRYABLE: 14074d27faddSmarx dep->dadk_softerrs.value.ui32++; 14081a5cb58cSmarx break; 14091a5cb58cSmarx 14101a5cb58cSmarx case GDA_FATAL: 14114d27faddSmarx dep->dadk_harderrs.value.ui32++; 14121a5cb58cSmarx break; 14131a5cb58cSmarx 14141a5cb58cSmarx default: 14151a5cb58cSmarx break; 14161a5cb58cSmarx } 14174d27faddSmarx 14184d27faddSmarx switch (scb) { 14194d27faddSmarx case DERR_INVCDB: 14204d27faddSmarx case DERR_ILI: 14214d27faddSmarx case DERR_EOM: 14224d27faddSmarx case DERR_HW: 14234d27faddSmarx case DERR_ICRC: 14244d27faddSmarx dep->dadk_transerrs.value.ui32++; 14254d27faddSmarx break; 14264d27faddSmarx 14274d27faddSmarx case DERR_AMNF: 14284d27faddSmarx case DERR_TKONF: 14294d27faddSmarx case DERR_DWF: 14304d27faddSmarx case DERR_BBK: 14314d27faddSmarx case DERR_UNC: 14324d27faddSmarx case DERR_HARD: 14334d27faddSmarx case DERR_MEDIUM: 14344d27faddSmarx case DERR_DATA_PROT: 14354d27faddSmarx case DERR_MISCOMP: 14364d27faddSmarx dep->dadk_rq_media_err.value.ui32++; 14374d27faddSmarx break; 14384d27faddSmarx 14394d27faddSmarx case DERR_NOTREADY: 14404d27faddSmarx dep->dadk_rq_ntrdy_err.value.ui32++; 14414d27faddSmarx break; 14424d27faddSmarx 14434d27faddSmarx case DERR_IDNF: 14444d27faddSmarx case DERR_UNIT_ATTN: 14454d27faddSmarx dep->dadk_rq_nodev_err.value.ui32++; 14464d27faddSmarx break; 14474d27faddSmarx 14484d27faddSmarx case DERR_ILL: 14494d27faddSmarx case DERR_RESV: 14504d27faddSmarx dep->dadk_rq_illrq_err.value.ui32++; 14514d27faddSmarx break; 14524d27faddSmarx 14534d27faddSmarx default: 14544d27faddSmarx break; 14554d27faddSmarx } 14564d27faddSmarx } 14574d27faddSmarx 1458507c3241Smlf /* if attempting to read a sector from a cdrom audio disk */ 1459507c3241Smlf if ((dadkp->dad_cdrom) && 1460507c3241Smlf (*((char *)(pktp->cp_cdbp)) == DCMD_READ) && 1461507c3241Smlf (scb == DERR_ILL)) { 1462507c3241Smlf return (COMMAND_DONE); 1463507c3241Smlf } 1464507c3241Smlf if (pktp->cp_passthru == NULL) { 1465507c3241Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, 1466507c3241Smlf dadk_errtab[scb].d_severity, pktp->cp_srtsec, 1467507c3241Smlf err_blkno, dadk_cmds, dadk_sense); 1468507c3241Smlf } 1469507c3241Smlf 1470507c3241Smlf if (scb == DERR_BUSY) { 1471507c3241Smlf (void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT); 1472507c3241Smlf } 1473507c3241Smlf 14741a5cb58cSmarx return (dadk_errtab[scb].d_action); 1475507c3241Smlf } 1476507c3241Smlf 1477507c3241Smlf static void 1478507c3241Smlf dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp) 1479507c3241Smlf { 1480507c3241Smlf struct dadk *dadkp; 1481507c3241Smlf int scb; 1482507c3241Smlf 1483507c3241Smlf dadkp = PKT2DADK(pktp); 1484507c3241Smlf scb = (int)(*(char *)pktp->cp_scbp); 1485507c3241Smlf 1486507c3241Smlf 1487507c3241Smlf rwcmdp->status.failed_blk = rwcmdp->blkaddr + 14882df1fe9cSrandyf ((pktp->cp_bytexfer - pktp->cp_resid) >> dadkp->dad_secshf); 1489507c3241Smlf 1490507c3241Smlf rwcmdp->status.resid = pktp->cp_bp->b_resid + 1491507c3241Smlf pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid; 1492507c3241Smlf switch ((int)(* (char *)pktp->cp_scbp)) { 1493507c3241Smlf case DERR_AMNF: 1494507c3241Smlf case DERR_ABORT: 1495507c3241Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST; 1496507c3241Smlf break; 1497507c3241Smlf case DERR_DWF: 1498507c3241Smlf case DERR_IDNF: 1499507c3241Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS; 1500507c3241Smlf break; 1501507c3241Smlf case DERR_TKONF: 1502507c3241Smlf case DERR_UNC: 1503507c3241Smlf case DERR_BBK: 1504507c3241Smlf rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR; 1505507c3241Smlf rwcmdp->status.failed_blk_is_valid = 1; 1506507c3241Smlf rwcmdp->status.resid = 0; 1507507c3241Smlf break; 1508507c3241Smlf case DERR_BUSY: 1509507c3241Smlf rwcmdp->status.status = DADKIO_STAT_NOT_READY; 1510507c3241Smlf break; 1511507c3241Smlf case DERR_INVCDB: 1512507c3241Smlf case DERR_HARD: 1513507c3241Smlf rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR; 1514507c3241Smlf break; 1515507c3241Smlf case DERR_ICRC: 1516507c3241Smlf default: 1517507c3241Smlf rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED; 1518507c3241Smlf } 1519507c3241Smlf 1520507c3241Smlf if (rwcmdp->flags & DADKIO_FLAG_SILENT) 1521507c3241Smlf return; 1522507c3241Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity, 1523507c3241Smlf rwcmdp->blkaddr, rwcmdp->status.failed_blk, 1524507c3241Smlf dadk_cmds, dadk_sense); 1525507c3241Smlf } 1526507c3241Smlf 1527507c3241Smlf /*ARGSUSED*/ 1528507c3241Smlf static void 1529507c3241Smlf dadk_polldone(struct buf *bp) 1530507c3241Smlf { 15312df1fe9cSrandyf struct cmpkt *pktp; 15322df1fe9cSrandyf struct dadk *dadkp; 15332df1fe9cSrandyf 15342df1fe9cSrandyf pktp = GDA_BP_PKT(bp); 15352df1fe9cSrandyf dadkp = PKT2DADK(pktp); 15362df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 15372df1fe9cSrandyf dadkp->dad_cmd_count--; 15382df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 1539507c3241Smlf } 1540507c3241Smlf 1541507c3241Smlf static void 1542507c3241Smlf dadk_iodone(struct buf *bp) 1543507c3241Smlf { 1544507c3241Smlf struct cmpkt *pktp; 1545507c3241Smlf struct dadk *dadkp; 1546507c3241Smlf 1547507c3241Smlf pktp = GDA_BP_PKT(bp); 1548507c3241Smlf dadkp = PKT2DADK(pktp); 1549507c3241Smlf 1550507c3241Smlf /* check for all iodone */ 1551507c3241Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 1552507c3241Smlf if (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 1553507c3241Smlf pktp->cp_retry = 0; 1554507c3241Smlf (void) dadk_iosetup(dadkp, pktp); 1555507c3241Smlf 1556507c3241Smlf 1557507c3241Smlf /* transport the next one */ 1558507c3241Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS) 1559507c3241Smlf return; 1560507c3241Smlf if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN) 1561507c3241Smlf return; 1562507c3241Smlf } 1563507c3241Smlf 1564507c3241Smlf /* start next one */ 1565507c3241Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 1566507c3241Smlf 1567507c3241Smlf /* free pkt */ 1568507c3241Smlf if (pktp->cp_private) 1569507c3241Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 1570507c3241Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 15712df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 15722df1fe9cSrandyf dadkp->dad_cmd_count--; 15732df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 1574507c3241Smlf biodone(bp); 1575507c3241Smlf } 1576507c3241Smlf 1577507c3241Smlf int 1578507c3241Smlf dadk_check_media(opaque_t objp, int *state) 1579507c3241Smlf { 1580507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1581507c3241Smlf 1582507c3241Smlf if (!dadkp->dad_rmb) { 1583507c3241Smlf return (ENXIO); 1584507c3241Smlf } 1585507c3241Smlf #ifdef DADK_DEBUG 1586507c3241Smlf if (dadk_debug & DSTATE) 1587507c3241Smlf PRF("dadk_check_media: user state %x disk state %x\n", 1588507c3241Smlf *state, dadkp->dad_iostate); 1589507c3241Smlf #endif 1590507c3241Smlf /* 1591507c3241Smlf * If state already changed just return 1592507c3241Smlf */ 1593507c3241Smlf if (*state != dadkp->dad_iostate) { 1594507c3241Smlf *state = dadkp->dad_iostate; 1595507c3241Smlf return (0); 1596507c3241Smlf } 1597507c3241Smlf 1598507c3241Smlf /* 1599507c3241Smlf * Startup polling on thread state 1600507c3241Smlf */ 1601507c3241Smlf mutex_enter(&dadkp->dad_mutex); 1602507c3241Smlf if (dadkp->dad_thread_cnt == 0) { 1603507c3241Smlf /* 1604507c3241Smlf * One thread per removable dadk device 1605507c3241Smlf */ 1606507c3241Smlf (void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0, 1607507c3241Smlf TS_RUN, v.v_maxsyspri - 2); 1608507c3241Smlf } 1609507c3241Smlf dadkp->dad_thread_cnt++; 1610507c3241Smlf 1611507c3241Smlf /* 1612507c3241Smlf * Wait for state to change 1613507c3241Smlf */ 1614507c3241Smlf do { 1615507c3241Smlf if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) { 1616507c3241Smlf dadkp->dad_thread_cnt--; 1617507c3241Smlf mutex_exit(&dadkp->dad_mutex); 1618507c3241Smlf return (EINTR); 1619507c3241Smlf } 1620507c3241Smlf } while (*state == dadkp->dad_iostate); 1621507c3241Smlf *state = dadkp->dad_iostate; 1622507c3241Smlf dadkp->dad_thread_cnt--; 1623507c3241Smlf mutex_exit(&dadkp->dad_mutex); 1624507c3241Smlf return (0); 1625507c3241Smlf } 1626507c3241Smlf 1627507c3241Smlf 1628507c3241Smlf #define MEDIA_ACCESS_DELAY 2000000 1629507c3241Smlf 1630507c3241Smlf static void 1631507c3241Smlf dadk_watch_thread(struct dadk *dadkp) 1632507c3241Smlf { 1633507c3241Smlf enum dkio_state state; 1634507c3241Smlf int interval; 1635507c3241Smlf 1636507c3241Smlf interval = drv_usectohz(dadk_check_media_time); 1637507c3241Smlf 1638507c3241Smlf do { 1639507c3241Smlf if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0, 1640507c3241Smlf DADK_SILENT)) { 1641507c3241Smlf /* 1642507c3241Smlf * Assume state remained the same 1643507c3241Smlf */ 1644507c3241Smlf state = dadkp->dad_iostate; 1645507c3241Smlf } 1646507c3241Smlf 1647507c3241Smlf /* 1648507c3241Smlf * now signal the waiting thread if this is *not* the 1649507c3241Smlf * specified state; 1650507c3241Smlf * delay the signal if the state is DKIO_INSERTED 1651507c3241Smlf * to allow the target to recover 1652507c3241Smlf */ 1653507c3241Smlf if (state != dadkp->dad_iostate) { 1654507c3241Smlf 1655507c3241Smlf dadkp->dad_iostate = state; 1656507c3241Smlf if (state == DKIO_INSERTED) { 1657507c3241Smlf /* 1658507c3241Smlf * delay the signal to give the drive a chance 1659507c3241Smlf * to do what it apparently needs to do 1660507c3241Smlf */ 1661507c3241Smlf (void) timeout((void(*)(void *))cv_broadcast, 1662507c3241Smlf (void *)&dadkp->dad_state_cv, 1663507c3241Smlf drv_usectohz((clock_t)MEDIA_ACCESS_DELAY)); 1664507c3241Smlf } else { 1665507c3241Smlf cv_broadcast(&dadkp->dad_state_cv); 1666507c3241Smlf } 1667507c3241Smlf } 1668507c3241Smlf delay(interval); 1669507c3241Smlf } while (dadkp->dad_thread_cnt); 1670507c3241Smlf } 1671507c3241Smlf 1672507c3241Smlf int 1673507c3241Smlf dadk_inquiry(opaque_t objp, opaque_t *inqpp) 1674507c3241Smlf { 1675507c3241Smlf struct dadk *dadkp = (struct dadk *)objp; 1676507c3241Smlf struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp; 1677507c3241Smlf 1678507c3241Smlf if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) { 1679507c3241Smlf *sinqpp = dadkp->dad_sd->sd_inq; 1680507c3241Smlf return (DDI_SUCCESS); 1681507c3241Smlf } 1682507c3241Smlf 1683507c3241Smlf return (DDI_FAILURE); 1684507c3241Smlf } 1685507c3241Smlf 1686507c3241Smlf static int 1687507c3241Smlf dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent) 1688507c3241Smlf 1689507c3241Smlf { 1690507c3241Smlf struct buf *bp; 1691507c3241Smlf int err; 1692507c3241Smlf struct cmpkt *pktp; 1693507c3241Smlf 1694507c3241Smlf if ((bp = getrbuf(KM_SLEEP)) == NULL) { 1695507c3241Smlf return (ENOMEM); 1696507c3241Smlf } 1697507c3241Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL); 1698507c3241Smlf if (!pktp) { 1699507c3241Smlf freerbuf(bp); 1700507c3241Smlf return (ENOMEM); 1701507c3241Smlf } 1702507c3241Smlf bp->b_back = (struct buf *)arg; 1703507c3241Smlf bp->b_forw = (struct buf *)dadkp->dad_flcobjp; 1704507c3241Smlf pktp->cp_passthru = (opaque_t)(intptr_t)silent; 1705507c3241Smlf 17062df1fe9cSrandyf err = dadk_ctl_ioctl(dadkp, cmd, (uintptr_t)pktp, flags); 1707507c3241Smlf freerbuf(bp); 1708507c3241Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 1709507c3241Smlf return (err); 1710507c3241Smlf 1711507c3241Smlf 1712507c3241Smlf } 1713507c3241Smlf 1714507c3241Smlf static void 1715507c3241Smlf dadk_rmb_iodone(struct buf *bp) 1716507c3241Smlf { 1717507c3241Smlf struct cmpkt *pktp; 1718507c3241Smlf struct dadk *dadkp; 1719507c3241Smlf 1720507c3241Smlf pktp = GDA_BP_PKT(bp); 1721507c3241Smlf dadkp = PKT2DADK(pktp); 1722507c3241Smlf 1723507c3241Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 1724507c3241Smlf 1725507c3241Smlf /* Start next one */ 1726507c3241Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 1727507c3241Smlf 17282df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 17292df1fe9cSrandyf dadkp->dad_cmd_count--; 17302df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 1731507c3241Smlf biodone(bp); 1732507c3241Smlf } 1733507c3241Smlf 1734507c3241Smlf static int 1735507c3241Smlf dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev, 1736507c3241Smlf enum uio_seg dataspace, int rw) 1737507c3241Smlf { 1738507c3241Smlf struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp; 1739507c3241Smlf struct buf *bp; 1740507c3241Smlf struct iovec aiov; 1741507c3241Smlf struct uio auio; 1742507c3241Smlf struct uio *uio = &auio; 1743507c3241Smlf int status; 1744507c3241Smlf 1745507c3241Smlf bp = getrbuf(KM_SLEEP); 1746507c3241Smlf 1747507c3241Smlf bp->av_forw = bp->b_forw = (struct buf *)dadkp; 1748507c3241Smlf bp->b_back = (struct buf *)rwcmdp; /* ioctl packet */ 1749507c3241Smlf 1750507c3241Smlf bzero((caddr_t)&auio, sizeof (struct uio)); 1751507c3241Smlf bzero((caddr_t)&aiov, sizeof (struct iovec)); 1752507c3241Smlf aiov.iov_base = rwcmdp->bufaddr; 1753507c3241Smlf aiov.iov_len = rwcmdp->buflen; 1754507c3241Smlf uio->uio_iov = &aiov; 1755507c3241Smlf 1756507c3241Smlf uio->uio_iovcnt = 1; 1757507c3241Smlf uio->uio_resid = rwcmdp->buflen; 1758507c3241Smlf uio->uio_segflg = dataspace; 1759507c3241Smlf 1760507c3241Smlf /* Let physio do the rest... */ 1761507c3241Smlf status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio); 1762507c3241Smlf 1763507c3241Smlf freerbuf(bp); 1764507c3241Smlf return (status); 1765507c3241Smlf 1766507c3241Smlf } 1767507c3241Smlf 1768507c3241Smlf /* Do not let a user gendisk request get too big or */ 1769507c3241Smlf /* else we could use to many resources. */ 1770507c3241Smlf 1771507c3241Smlf static void 1772507c3241Smlf dadkmin(struct buf *bp) 1773507c3241Smlf { 1774507c3241Smlf if (bp->b_bcount > dadk_dk_maxphys) 1775507c3241Smlf bp->b_bcount = dadk_dk_maxphys; 1776507c3241Smlf } 1777507c3241Smlf 1778507c3241Smlf static int 1779507c3241Smlf dadk_dk_strategy(struct buf *bp) 1780507c3241Smlf { 1781507c3241Smlf dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back, 1782507c3241Smlf bp); 1783507c3241Smlf return (0); 1784507c3241Smlf } 1785507c3241Smlf 1786507c3241Smlf static void 1787507c3241Smlf dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp) 1788507c3241Smlf { 1789507c3241Smlf struct cmpkt *pktp; 1790507c3241Smlf 1791507c3241Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL); 1792507c3241Smlf if (!pktp) { 1793507c3241Smlf bioerror(bp, ENOMEM); 1794507c3241Smlf biodone(bp); 1795507c3241Smlf return; 1796507c3241Smlf } 1797507c3241Smlf 1798507c3241Smlf pktp->cp_passthru = rwcmdp; 1799507c3241Smlf 1800507c3241Smlf (void) dadk_ioprep(dadkp, pktp); 1801507c3241Smlf 18022df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 18032df1fe9cSrandyf dadkp->dad_cmd_count++; 18042df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 1805507c3241Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 1806507c3241Smlf } 18072df1fe9cSrandyf 18082df1fe9cSrandyf /* 18092df1fe9cSrandyf * There is no existing way to notify cmdk module 18102df1fe9cSrandyf * when the command completed, so add this function 18112df1fe9cSrandyf * to calculate how many on-going commands. 18122df1fe9cSrandyf */ 18132df1fe9cSrandyf int 18142df1fe9cSrandyf dadk_getcmds(opaque_t objp) 18152df1fe9cSrandyf { 18162df1fe9cSrandyf struct dadk *dadkp = (struct dadk *)objp; 18172df1fe9cSrandyf int count; 18182df1fe9cSrandyf 18192df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 18202df1fe9cSrandyf count = dadkp->dad_cmd_count; 18212df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 18222df1fe9cSrandyf return (count); 18232df1fe9cSrandyf } 18242df1fe9cSrandyf 18252df1fe9cSrandyf /* 18262df1fe9cSrandyf * this function was used to calc the cmd for CTL_IOCTL 18272df1fe9cSrandyf */ 18282df1fe9cSrandyf static int 18292df1fe9cSrandyf dadk_ctl_ioctl(struct dadk *dadkp, uint32_t cmd, uintptr_t arg, int flag) 18302df1fe9cSrandyf { 18312df1fe9cSrandyf int error; 18322df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 18332df1fe9cSrandyf dadkp->dad_cmd_count++; 18342df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 18352df1fe9cSrandyf error = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag); 18362df1fe9cSrandyf mutex_enter(&dadkp->dad_cmd_mutex); 18372df1fe9cSrandyf dadkp->dad_cmd_count--; 18382df1fe9cSrandyf mutex_exit(&dadkp->dad_cmd_mutex); 18392df1fe9cSrandyf return (error); 18402df1fe9cSrandyf } 1841