11709Smlf /* 21709Smlf * CDDL HEADER START 31709Smlf * 41709Smlf * The contents of this file are subject to the terms of the 51709Smlf * Common Development and Distribution License (the "License"). 61709Smlf * You may not use this file except in compliance with the License. 71709Smlf * 81709Smlf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 91709Smlf * or http://www.opensolaris.org/os/licensing. 101709Smlf * See the License for the specific language governing permissions 111709Smlf * and limitations under the License. 121709Smlf * 131709Smlf * When distributing Covered Code, include this CDDL HEADER in each 141709Smlf * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 151709Smlf * If applicable, add the following below this CDDL HEADER, with the 161709Smlf * fields enclosed by brackets "[]" replaced with your own identifying 171709Smlf * information: Portions Copyright [yyyy] [name of copyright owner] 181709Smlf * 191709Smlf * CDDL HEADER END 201709Smlf */ 211709Smlf 221709Smlf /* 23*1900Seota * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 241709Smlf * Use is subject to license terms. 251709Smlf */ 261709Smlf 271709Smlf #pragma ident "%Z%%M% %I% %E% SMI" 281709Smlf 291709Smlf /* 301709Smlf * Direct Attached Disk 311709Smlf */ 321709Smlf 331709Smlf #include <sys/file.h> 341709Smlf #include <sys/scsi/scsi.h> 351709Smlf #include <sys/var.h> 361709Smlf #include <sys/proc.h> 371709Smlf #include <sys/dktp/cm.h> 381709Smlf #include <sys/vtoc.h> 391709Smlf #include <sys/dkio.h> 401709Smlf 411709Smlf #include <sys/dktp/dadev.h> 421709Smlf #include <sys/dktp/fctypes.h> 431709Smlf #include <sys/dktp/flowctrl.h> 441709Smlf #include <sys/dktp/tgcom.h> 451709Smlf #include <sys/dktp/tgdk.h> 461709Smlf #include <sys/dktp/bbh.h> 471709Smlf #include <sys/dktp/dadkio.h> 481709Smlf #include <sys/dktp/dadk.h> 491709Smlf #include <sys/cdio.h> 501709Smlf 511709Smlf /* 521709Smlf * Local Function Prototypes 531709Smlf */ 541709Smlf static void dadk_restart(void *pktp); 551709Smlf static void dadk_pktcb(struct cmpkt *pktp); 561709Smlf static void dadk_iodone(struct buf *bp); 571709Smlf static void dadk_polldone(struct buf *bp); 581709Smlf static void dadk_setcap(struct dadk *dadkp); 591709Smlf 601709Smlf static int dadk_chkerr(struct cmpkt *pktp); 611709Smlf static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp); 621709Smlf static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp); 631709Smlf static int dadk_ioretry(struct cmpkt *pktp, int action); 641709Smlf 651709Smlf static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, 661709Smlf struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t), 671709Smlf caddr_t arg); 681709Smlf 691709Smlf static int dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), 701709Smlf caddr_t arg); 711709Smlf static void dadk_transport(opaque_t com_data, struct buf *bp); 721709Smlf 731709Smlf struct tgcom_objops dadk_com_ops = { 741709Smlf nodev, 751709Smlf nodev, 761709Smlf dadk_pkt, 771709Smlf dadk_transport, 781709Smlf 0, 0 791709Smlf }; 801709Smlf 811709Smlf /* 821709Smlf * architecture dependent allocation restrictions for dadk_iob_alloc(). For 831709Smlf * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen 841709Smlf * to dadk_sgl_size during _init(). 851709Smlf */ 861709Smlf #if defined(__sparc) 871709Smlf static ddi_dma_attr_t dadk_alloc_attr = { 881709Smlf DMA_ATTR_V0, /* version number */ 891709Smlf 0x0, /* lowest usable address */ 901709Smlf 0xFFFFFFFFull, /* high DMA address range */ 911709Smlf 0xFFFFFFFFull, /* DMA counter register */ 921709Smlf 1, /* DMA address alignment */ 931709Smlf 1, /* DMA burstsizes */ 941709Smlf 1, /* min effective DMA size */ 951709Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 961709Smlf 0xFFFFFFFFull, /* segment boundary */ 971709Smlf 1, /* s/g list length */ 981709Smlf 512, /* granularity of device */ 991709Smlf 0, /* DMA transfer flags */ 1001709Smlf }; 1011709Smlf #elif defined(__x86) 1021709Smlf static ddi_dma_attr_t dadk_alloc_attr = { 1031709Smlf DMA_ATTR_V0, /* version number */ 1041709Smlf 0x0, /* lowest usable address */ 1051709Smlf 0x0, /* high DMA address range [set in _init()] */ 1061709Smlf 0xFFFFull, /* DMA counter register */ 1071709Smlf 512, /* DMA address alignment */ 1081709Smlf 1, /* DMA burstsizes */ 1091709Smlf 1, /* min effective DMA size */ 1101709Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 1111709Smlf 0xFFFFFFFFull, /* segment boundary */ 1121709Smlf 0, /* s/g list length [set in _init()] */ 1131709Smlf 512, /* granularity of device */ 1141709Smlf 0, /* DMA transfer flags */ 1151709Smlf }; 1161709Smlf 1171709Smlf uint64_t dadk_max_phys_addr = 0xFFFFFFFFull; 1181709Smlf int dadk_sgl_size = 0xFF; 1191709Smlf #endif 1201709Smlf 1211709Smlf static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, 1221709Smlf int silent); 1231709Smlf static void dadk_rmb_iodone(struct buf *bp); 1241709Smlf 1251709Smlf static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, 1261709Smlf dev_t dev, enum uio_seg dataspace, int rw); 1271709Smlf static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp, 1281709Smlf struct buf *bp); 1291709Smlf static void dadkmin(struct buf *bp); 1301709Smlf static int dadk_dk_strategy(struct buf *bp); 1311709Smlf static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp); 1321709Smlf 1331709Smlf struct tgdk_objops dadk_ops = { 1341709Smlf dadk_init, 1351709Smlf dadk_free, 1361709Smlf dadk_probe, 1371709Smlf dadk_attach, 1381709Smlf dadk_open, 1391709Smlf dadk_close, 1401709Smlf dadk_ioctl, 1411709Smlf dadk_strategy, 1421709Smlf dadk_setgeom, 1431709Smlf dadk_getgeom, 1441709Smlf dadk_iob_alloc, 1451709Smlf dadk_iob_free, 1461709Smlf dadk_iob_htoc, 1471709Smlf dadk_iob_xfer, 1481709Smlf dadk_dump, 1491709Smlf dadk_getphygeom, 1501709Smlf dadk_set_bbhobj, 1511709Smlf dadk_check_media, 1521709Smlf dadk_inquiry, 1531709Smlf dadk_cleanup, 1541709Smlf 0 1551709Smlf }; 1561709Smlf 1571709Smlf /* 1581709Smlf * Local static data 1591709Smlf */ 1601709Smlf 1611709Smlf #ifdef DADK_DEBUG 1621709Smlf #define DENT 0x0001 1631709Smlf #define DERR 0x0002 1641709Smlf #define DIO 0x0004 1651709Smlf #define DGEOM 0x0010 1661709Smlf #define DSTATE 0x0020 1671709Smlf static int dadk_debug = DGEOM; 1681709Smlf 1691709Smlf #endif /* DADK_DEBUG */ 1701709Smlf 1711709Smlf static int dadk_check_media_time = 3000000; /* 3 Second State Check */ 1721709Smlf static int dadk_dk_maxphys = 0x80000; 1731709Smlf 1741709Smlf static char *dadk_cmds[] = { 1751709Smlf "\000Unknown", /* unknown */ 1761709Smlf "\001read sector", /* DCMD_READ 1 */ 1771709Smlf "\002write sector", /* DCMD_WRITE 2 */ 1781709Smlf "\003format track", /* DCMD_FMTTRK 3 */ 1791709Smlf "\004format whole drive", /* DCMD_FMTDRV 4 */ 1801709Smlf "\005recalibrate", /* DCMD_RECAL 5 */ 1811709Smlf "\006seek sector", /* DCMD_SEEK 6 */ 1821709Smlf "\007read verify", /* DCMD_RDVER 7 */ 1831709Smlf "\010read defect list", /* DCMD_GETDEF 8 */ 1841709Smlf "\011lock door", /* DCMD_LOCK 9 */ 1851709Smlf "\012unlock door", /* DCMD_UNLOCK 10 */ 1861709Smlf "\013start motor", /* DCMD_START_MOTOR 11 */ 1871709Smlf "\014stop motor", /* DCMD_STOP_MOTOR 12 */ 1881709Smlf "\015eject", /* DCMD_EJECT 13 */ 1891709Smlf "\016update geometry", /* DCMD_UPDATE_GEOM 14 */ 1901709Smlf "\017get state", /* DCMD_GET_STATE 15 */ 1911709Smlf "\020cdrom pause", /* DCMD_PAUSE 16 */ 1921709Smlf "\021cdrom resume", /* DCMD_RESUME 17 */ 1931709Smlf "\022cdrom play track index", /* DCMD_PLAYTRKIND 18 */ 1941709Smlf "\023cdrom play msf", /* DCMD_PLAYMSF 19 */ 1951709Smlf "\024cdrom sub channel", /* DCMD_SUBCHNL 20 */ 1961709Smlf "\025cdrom read mode 1", /* DCMD_READMODE1 21 */ 1971709Smlf "\026cdrom read toc header", /* DCMD_READTOCHDR 22 */ 1981709Smlf "\027cdrom read toc entry", /* DCMD_READTOCENT 23 */ 1991709Smlf "\030cdrom read offset", /* DCMD_READOFFSET 24 */ 2001709Smlf "\031cdrom read mode 2", /* DCMD_READMODE2 25 */ 2011709Smlf "\032cdrom volume control", /* DCMD_VOLCTRL 26 */ 2021709Smlf "\033flush cache", /* DCMD_FLUSH_CACHE 27 */ 2031709Smlf NULL 2041709Smlf }; 2051709Smlf 2061709Smlf static char *dadk_sense[] = { 2071709Smlf "\000Success", /* DERR_SUCCESS */ 2081709Smlf "\001address mark not found", /* DERR_AMNF */ 2091709Smlf "\002track 0 not found", /* DERR_TKONF */ 2101709Smlf "\003aborted command", /* DERR_ABORT */ 2111709Smlf "\004write fault", /* DERR_DWF */ 2121709Smlf "\005ID not found", /* DERR_IDNF */ 2131709Smlf "\006drive busy", /* DERR_BUSY */ 2141709Smlf "\007uncorrectable data error", /* DERR_UNC */ 2151709Smlf "\010bad block detected", /* DERR_BBK */ 2161709Smlf "\011invalid command", /* DERR_INVCDB */ 2171709Smlf "\012device hard error", /* DERR_HARD */ 2181709Smlf "\013illegal length indicated", /* DERR_ILI */ 2191709Smlf "\014end of media", /* DERR_EOM */ 2201709Smlf "\015media change requested", /* DERR_MCR */ 2211709Smlf "\016recovered from error", /* DERR_RECOVER */ 2221709Smlf "\017device not ready", /* DERR_NOTREADY */ 2231709Smlf "\020medium error", /* DERR_MEDIUM */ 2241709Smlf "\021hardware error", /* DERR_HW */ 2251709Smlf "\022illegal request", /* DERR_ILL */ 2261709Smlf "\023unit attention", /* DERR_UNIT_ATTN */ 2271709Smlf "\024data protection", /* DERR_DATA_PROT */ 2281709Smlf "\025miscompare", /* DERR_MISCOMPARE */ 2291709Smlf "\026ICRC error during UDMA", /* DERR_ICRC */ 2301709Smlf "\027reserved", /* DERR_RESV */ 2311709Smlf NULL 2321709Smlf }; 2331709Smlf 2341709Smlf static char *dadk_name = "Disk"; 2351709Smlf 2361709Smlf /* 2371709Smlf * This is the loadable module wrapper 2381709Smlf */ 2391709Smlf #include <sys/modctl.h> 2401709Smlf 2411709Smlf extern struct mod_ops mod_miscops; 2421709Smlf 2431709Smlf static struct modlmisc modlmisc = { 2441709Smlf &mod_miscops, /* Type of module */ 2451709Smlf "Direct Attached Disk %I%" 2461709Smlf }; 2471709Smlf 2481709Smlf static struct modlinkage modlinkage = { 2491709Smlf MODREV_1, (void *)&modlmisc, NULL 2501709Smlf }; 2511709Smlf 2521709Smlf int 2531709Smlf _init(void) 2541709Smlf { 2551709Smlf #ifdef DADK_DEBUG 2561709Smlf if (dadk_debug & DENT) 2571709Smlf PRF("dadk_init: call\n"); 2581709Smlf #endif 2591709Smlf 2601709Smlf #if defined(__x86) 2611709Smlf /* set the max physical address for iob allocs on x86 */ 2621709Smlf dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr; 2631709Smlf 2641709Smlf /* 2651709Smlf * set the sgllen for iob allocs on x86. If this is set less than 2661709Smlf * the number of pages the buffer will take (taking into account 2671709Smlf * alignment), it would force the allocator to try and allocate 2681709Smlf * contiguous pages. 2691709Smlf */ 2701709Smlf dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size; 2711709Smlf #endif 2721709Smlf 2731709Smlf return (mod_install(&modlinkage)); 2741709Smlf } 2751709Smlf 2761709Smlf int 2771709Smlf _fini(void) 2781709Smlf { 2791709Smlf #ifdef DADK_DEBUG 2801709Smlf if (dadk_debug & DENT) 2811709Smlf PRF("dadk_fini: call\n"); 2821709Smlf #endif 2831709Smlf 2841709Smlf return (mod_remove(&modlinkage)); 2851709Smlf } 2861709Smlf 2871709Smlf int 2881709Smlf _info(struct modinfo *modinfop) 2891709Smlf { 2901709Smlf return (mod_info(&modlinkage, modinfop)); 2911709Smlf } 2921709Smlf 2931709Smlf struct tgdk_obj * 2941709Smlf dadk_create() 2951709Smlf { 2961709Smlf struct tgdk_obj *dkobjp; 2971709Smlf struct dadk *dadkp; 2981709Smlf 2991709Smlf dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP); 3001709Smlf if (!dkobjp) 3011709Smlf return (NULL); 3021709Smlf dadkp = (struct dadk *)(dkobjp+1); 3031709Smlf 3041709Smlf dkobjp->tg_ops = (struct tgdk_objops *)&dadk_ops; 3051709Smlf dkobjp->tg_data = (opaque_t)dadkp; 3061709Smlf dkobjp->tg_ext = &(dkobjp->tg_extblk); 3071709Smlf dadkp->dad_extp = &(dkobjp->tg_extblk); 3081709Smlf 3091709Smlf #ifdef DADK_DEBUG 3101709Smlf if (dadk_debug & DENT) 3111709Smlf PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp); 3121709Smlf #endif 3131709Smlf return (dkobjp); 3141709Smlf } 3151709Smlf 3161709Smlf int 3171709Smlf dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp, 3181709Smlf opaque_t bbhobjp, void *lkarg) 3191709Smlf { 3201709Smlf struct dadk *dadkp = (struct dadk *)objp; 3211709Smlf struct scsi_device *sdevp = (struct scsi_device *)devp; 3221709Smlf 3231709Smlf dadkp->dad_sd = devp; 3241709Smlf dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran; 3251709Smlf sdevp->sd_private = (caddr_t)dadkp; 3261709Smlf 3271709Smlf /* initialize the communication object */ 3281709Smlf dadkp->dad_com.com_data = (opaque_t)dadkp; 3291709Smlf dadkp->dad_com.com_ops = &dadk_com_ops; 3301709Smlf 3311709Smlf dadkp->dad_bbhobjp = bbhobjp; 3321709Smlf BBH_INIT(bbhobjp); 3331709Smlf 3341709Smlf dadkp->dad_flcobjp = flcobjp; 3351709Smlf return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg)); 3361709Smlf } 3371709Smlf 3381709Smlf int 3391709Smlf dadk_free(struct tgdk_obj *dkobjp) 3401709Smlf { 3411709Smlf TGDK_CLEANUP(dkobjp); 3421709Smlf kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk))); 3431709Smlf 3441709Smlf return (DDI_SUCCESS); 3451709Smlf } 3461709Smlf 3471709Smlf void 3481709Smlf dadk_cleanup(struct tgdk_obj *dkobjp) 3491709Smlf { 3501709Smlf struct dadk *dadkp; 3511709Smlf 3521709Smlf dadkp = (struct dadk *)(dkobjp->tg_data); 3531709Smlf if (dadkp->dad_sd) 3541709Smlf dadkp->dad_sd->sd_private = NULL; 3551709Smlf if (dadkp->dad_bbhobjp) { 3561709Smlf BBH_FREE(dadkp->dad_bbhobjp); 3571709Smlf dadkp->dad_bbhobjp = NULL; 3581709Smlf } 3591709Smlf if (dadkp->dad_flcobjp) { 3601709Smlf FLC_FREE(dadkp->dad_flcobjp); 3611709Smlf dadkp->dad_flcobjp = NULL; 3621709Smlf } 3631709Smlf } 3641709Smlf 3651709Smlf /* ARGSUSED */ 3661709Smlf int 3671709Smlf dadk_probe(opaque_t objp, int kmsflg) 3681709Smlf { 3691709Smlf struct dadk *dadkp = (struct dadk *)objp; 3701709Smlf struct scsi_device *devp; 3711709Smlf char name[80]; 3721709Smlf 3731709Smlf devp = dadkp->dad_sd; 3741709Smlf if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) || 3751709Smlf (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) { 3761709Smlf return (DDI_PROBE_FAILURE); 3771709Smlf } 3781709Smlf 3791709Smlf switch (devp->sd_inq->inq_dtype) { 3801709Smlf case DTYPE_DIRECT: 3811709Smlf dadkp->dad_ctype = DKC_DIRECT; 3821709Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK; 3831709Smlf dadkp->dad_extp->tg_ctype = DKC_DIRECT; 3841709Smlf break; 3851709Smlf case DTYPE_RODIRECT: /* eg cdrom */ 3861709Smlf dadkp->dad_ctype = DKC_CDROM; 3871709Smlf dadkp->dad_extp->tg_rdonly = 1; 3881709Smlf dadkp->dad_rdonly = 1; 3891709Smlf dadkp->dad_cdrom = 1; 3901709Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_CD; 3911709Smlf dadkp->dad_extp->tg_ctype = DKC_CDROM; 3921709Smlf break; 3931709Smlf case DTYPE_WORM: 3941709Smlf case DTYPE_OPTICAL: 3951709Smlf default: 3961709Smlf return (DDI_PROBE_FAILURE); 3971709Smlf } 3981709Smlf 3991709Smlf dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb; 4001709Smlf 4011709Smlf dadkp->dad_secshf = SCTRSHFT; 4021709Smlf dadkp->dad_blkshf = 0; 4031709Smlf 4041709Smlf /* display the device name */ 4051709Smlf (void) strcpy(name, "Vendor '"); 4061709Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]); 4071709Smlf (void) strcat(name, "' Product '"); 4081709Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]); 4091709Smlf (void) strcat(name, "'"); 4101709Smlf gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name); 4111709Smlf 4121709Smlf return (DDI_PROBE_SUCCESS); 4131709Smlf } 4141709Smlf 4151709Smlf 4161709Smlf /* ARGSUSED */ 4171709Smlf int 4181709Smlf dadk_attach(opaque_t objp) 4191709Smlf { 4201709Smlf return (DDI_SUCCESS); 4211709Smlf } 4221709Smlf 4231709Smlf int 4241709Smlf dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp) 4251709Smlf { 4261709Smlf struct dadk *dadkp = (struct dadk *)objp; 4271709Smlf /* free the old bbh object */ 4281709Smlf if (dadkp->dad_bbhobjp) 4291709Smlf BBH_FREE(dadkp->dad_bbhobjp); 4301709Smlf 4311709Smlf /* initialize the new bbh object */ 4321709Smlf dadkp->dad_bbhobjp = bbhobjp; 4331709Smlf BBH_INIT(bbhobjp); 4341709Smlf 4351709Smlf return (DDI_SUCCESS); 4361709Smlf } 4371709Smlf 4381709Smlf /* ARGSUSED */ 4391709Smlf int 4401709Smlf dadk_open(opaque_t objp, int flag) 4411709Smlf { 4421709Smlf struct dadk *dadkp = (struct dadk *)objp; 4431709Smlf int error; 4441709Smlf int wce; 4451709Smlf 4461709Smlf if (!dadkp->dad_rmb) { 4471709Smlf if (dadkp->dad_phyg.g_cap) { 4481709Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 4491709Smlf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 4501709Smlf return (DDI_SUCCESS); 4511709Smlf } 4521709Smlf } else { 4531709Smlf mutex_enter(&dadkp->dad_mutex); 4541709Smlf dadkp->dad_iostate = DKIO_NONE; 4551709Smlf cv_broadcast(&dadkp->dad_state_cv); 4561709Smlf mutex_exit(&dadkp->dad_mutex); 4571709Smlf 4581709Smlf if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, DADK_SILENT) || 4591709Smlf dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) || 4601709Smlf dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, DADK_SILENT)) { 4611709Smlf return (DDI_FAILURE); 4621709Smlf } 4631709Smlf 4641709Smlf mutex_enter(&dadkp->dad_mutex); 4651709Smlf dadkp->dad_iostate = DKIO_INSERTED; 4661709Smlf cv_broadcast(&dadkp->dad_state_cv); 4671709Smlf mutex_exit(&dadkp->dad_mutex); 4681709Smlf } 4691709Smlf 4701709Smlf /* 4711709Smlf * get write cache enable state 4721709Smlf * If there is an error, must assume that write cache 4731709Smlf * is enabled. 4741709Smlf * NOTE: Since there is currently no Solaris mechanism to 4751709Smlf * change the state of the Write Cache Enable feature, 4761709Smlf * this code just checks the value of the WCE bit 4771709Smlf * obtained at device init time. If a mechanism 4781709Smlf * is added to the driver to change WCE, dad_wce 4791709Smlf * must be updated appropriately. 4801709Smlf */ 4811709Smlf error = CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETWCE, 4821709Smlf (uintptr_t)&wce, 0); 4831709Smlf mutex_enter(&dadkp->dad_mutex); 4841709Smlf dadkp->dad_wce = (error != 0) || (wce != 0); 4851709Smlf mutex_exit(&dadkp->dad_mutex); 4861709Smlf 4871709Smlf /* logical disk geometry */ 4881709Smlf CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETGEOM, 4891709Smlf (uintptr_t)&dadkp->dad_logg, 0); 4901709Smlf if (dadkp->dad_logg.g_cap == 0) 4911709Smlf return (DDI_FAILURE); 4921709Smlf 4931709Smlf /* get physical disk geometry */ 4941709Smlf CTL_IOCTL(dadkp->dad_ctlobjp, DIOCTL_GETPHYGEOM, 4951709Smlf (uintptr_t)&dadkp->dad_phyg, 0); 4961709Smlf if (dadkp->dad_phyg.g_cap == 0) 4971709Smlf return (DDI_FAILURE); 4981709Smlf 4991709Smlf dadk_setcap(dadkp); 5001709Smlf 5011709Smlf /* start profiling */ 5021709Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 5031709Smlf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 5041709Smlf 5051709Smlf return (DDI_SUCCESS); 5061709Smlf } 5071709Smlf 5081709Smlf static void 5091709Smlf dadk_setcap(struct dadk *dadkp) 5101709Smlf { 5111709Smlf int totsize; 5121709Smlf int i; 5131709Smlf 5141709Smlf totsize = dadkp->dad_phyg.g_secsiz; 5151709Smlf 5161709Smlf if (totsize == 0) { 5171709Smlf if (dadkp->dad_cdrom) { 5181709Smlf totsize = 2048; 5191709Smlf } else { 5201709Smlf totsize = NBPSCTR; 5211709Smlf } 5221709Smlf } else { 5231709Smlf /* Round down sector size to multiple of 512B */ 5241709Smlf totsize &= ~(NBPSCTR-1); 5251709Smlf } 5261709Smlf dadkp->dad_phyg.g_secsiz = totsize; 5271709Smlf 5281709Smlf /* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */ 5291709Smlf totsize >>= SCTRSHFT; 5301709Smlf for (i = 0; totsize != 1; i++, totsize >>= 1); 5311709Smlf dadkp->dad_blkshf = i; 5321709Smlf dadkp->dad_secshf = i + SCTRSHFT; 5331709Smlf } 5341709Smlf 5351709Smlf 5361709Smlf int 5371709Smlf dadk_close(opaque_t objp) 5381709Smlf { 5391709Smlf struct dadk *dadkp = (struct dadk *)objp; 5401709Smlf 5411709Smlf if (dadkp->dad_rmb) { 5421709Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0, 5431709Smlf DADK_SILENT); 5441709Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT); 5451709Smlf } 5461709Smlf FLC_STOP_KSTAT(dadkp->dad_flcobjp); 5471709Smlf return (DDI_SUCCESS); 5481709Smlf } 5491709Smlf 5501709Smlf int 5511709Smlf dadk_strategy(opaque_t objp, struct buf *bp) 5521709Smlf { 5531709Smlf struct dadk *dadkp = (struct dadk *)objp; 5541709Smlf 5551709Smlf if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) { 5561709Smlf bioerror(bp, EROFS); 5571709Smlf return (DDI_FAILURE); 5581709Smlf } 5591709Smlf 5601709Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 5611709Smlf bioerror(bp, ENXIO); 5621709Smlf return (DDI_FAILURE); 5631709Smlf } 5641709Smlf 5651709Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 5661709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 5671709Smlf 5681709Smlf return (DDI_SUCCESS); 5691709Smlf } 5701709Smlf 5711709Smlf int 5721709Smlf dadk_dump(opaque_t objp, struct buf *bp) 5731709Smlf { 5741709Smlf struct dadk *dadkp = (struct dadk *)objp; 5751709Smlf struct cmpkt *pktp; 5761709Smlf 5771709Smlf if (dadkp->dad_rdonly) { 5781709Smlf bioerror(bp, EROFS); 5791709Smlf return (DDI_FAILURE); 5801709Smlf } 5811709Smlf 5821709Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 5831709Smlf bioerror(bp, ENXIO); 5841709Smlf return (DDI_FAILURE); 5851709Smlf } 5861709Smlf 5871709Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 5881709Smlf 5891709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL); 5901709Smlf if (!pktp) { 5911709Smlf cmn_err(CE_WARN, "no resources for dumping"); 5921709Smlf bioerror(bp, EIO); 5931709Smlf return (DDI_FAILURE); 5941709Smlf } 5951709Smlf pktp->cp_flags |= CPF_NOINTR; 5961709Smlf 5971709Smlf (void) dadk_ioprep(dadkp, pktp); 5981709Smlf dadk_transport(dadkp, bp); 5991709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 6001709Smlf 6011709Smlf while (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 6021709Smlf (void) dadk_iosetup(dadkp, pktp); 6031709Smlf dadk_transport(dadkp, bp); 6041709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 6051709Smlf } 6061709Smlf 6071709Smlf if (pktp->cp_private) 6081709Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 6091709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 6101709Smlf return (DDI_SUCCESS); 6111709Smlf } 6121709Smlf 6131709Smlf /* ARGSUSED */ 6141709Smlf int 6151709Smlf dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, 6161709Smlf cred_t *cred_p, int *rval_p) 6171709Smlf { 6181709Smlf struct dadk *dadkp = (struct dadk *)objp; 6191709Smlf 6201709Smlf switch (cmd) { 6211709Smlf case DKIOCGETDEF: 6221709Smlf { 6231709Smlf struct buf *bp; 6241709Smlf int err, head; 6251709Smlf unsigned char *secbuf; 6261709Smlf STRUCT_DECL(defect_header, adh); 6271709Smlf 6281709Smlf STRUCT_INIT(adh, flag & FMODELS); 6291709Smlf 6301709Smlf /* 6311709Smlf * copyin header .... 6321709Smlf * yields head number and buffer address 6331709Smlf */ 6341709Smlf if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh), 6351709Smlf flag)) 6361709Smlf return (EFAULT); 6371709Smlf head = STRUCT_FGET(adh, head); 6381709Smlf if (head < 0 || head >= dadkp->dad_phyg.g_head) 6391709Smlf return (ENXIO); 6401709Smlf secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP); 6411709Smlf if (!secbuf) 6421709Smlf return (ENOMEM); 6431709Smlf bp = getrbuf(KM_SLEEP); 6441709Smlf if (!bp) { 6451709Smlf kmem_free(secbuf, NBPSCTR); 6461709Smlf return (ENOMEM); 6471709Smlf } 6481709Smlf 6491709Smlf bp->b_edev = dev; 6501709Smlf bp->b_dev = cmpdev(dev); 6511709Smlf bp->b_flags = B_BUSY; 6521709Smlf bp->b_resid = 0; 6531709Smlf bp->b_bcount = NBPSCTR; 6541709Smlf bp->b_un.b_addr = (caddr_t)secbuf; 6551709Smlf bp->b_blkno = head; /* I had to put it somwhere! */ 6561709Smlf bp->b_forw = (struct buf *)dadkp; 6571709Smlf bp->b_back = (struct buf *)DCMD_GETDEF; 6581709Smlf 6591709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 6601709Smlf err = biowait(bp); 6611709Smlf if (!err) { 6621709Smlf if (ddi_copyout((caddr_t)secbuf, 6631709Smlf STRUCT_FGETP(adh, buffer), NBPSCTR, flag)) 6641709Smlf err = ENXIO; 6651709Smlf } 6661709Smlf kmem_free(secbuf, NBPSCTR); 6671709Smlf freerbuf(bp); 6681709Smlf return (err); 6691709Smlf } 6701709Smlf case DIOCTL_RWCMD: 6711709Smlf { 6721709Smlf struct dadkio_rwcmd *rwcmdp; 6731709Smlf int status, rw; 6741709Smlf 6751709Smlf /* 6761709Smlf * copied in by cmdk and, if necessary, converted to the 6771709Smlf * correct datamodel 6781709Smlf */ 6791709Smlf rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg; 6801709Smlf 6811709Smlf /* 6821709Smlf * handle the complex cases here; we pass these 6831709Smlf * through to the driver, which will queue them and 6841709Smlf * handle the requests asynchronously. The simpler 6851709Smlf * cases ,which can return immediately, fail here, and 6861709Smlf * the request reverts to the dadk_ioctl routine, while 6871709Smlf * will reroute them directly to the ata driver. 6881709Smlf */ 6891709Smlf switch (rwcmdp->cmd) { 6901709Smlf case DADKIO_RWCMD_READ : 6911709Smlf /*FALLTHROUGH*/ 6921709Smlf case DADKIO_RWCMD_WRITE: 6931709Smlf rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ? 6941709Smlf B_WRITE : B_READ); 6951709Smlf status = dadk_dk_buf_setup(dadkp, 6961709Smlf (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ? 6971709Smlf UIO_SYSSPACE : UIO_USERSPACE), rw); 6981709Smlf return (status); 6991709Smlf default: 7001709Smlf return (EINVAL); 7011709Smlf } 7021709Smlf } 7031709Smlf case DKIOCFLUSHWRITECACHE: 7041709Smlf { 7051709Smlf struct buf *bp; 7061709Smlf int err = 0; 7071709Smlf struct dk_callback *dkc = (struct dk_callback *)arg; 7081709Smlf struct cmpkt *pktp; 7091709Smlf int is_sync = 1; 7101709Smlf 7111709Smlf mutex_enter(&dadkp->dad_mutex); 7121709Smlf if (dadkp->dad_noflush || ! dadkp->dad_wce) { 7131709Smlf err = dadkp->dad_noflush ? ENOTSUP : 0; 7141709Smlf mutex_exit(&dadkp->dad_mutex); 7151709Smlf /* 7161709Smlf * If a callback was requested: a 7171709Smlf * callback will always be done if the 7181709Smlf * caller saw the DKIOCFLUSHWRITECACHE 7191709Smlf * ioctl return 0, and never done if the 7201709Smlf * caller saw the ioctl return an error. 7211709Smlf */ 7221709Smlf if ((flag & FKIOCTL) && dkc != NULL && 7231709Smlf dkc->dkc_callback != NULL) { 7241709Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, 7251709Smlf err); 7261709Smlf /* 7271709Smlf * Did callback and reported error. 7281709Smlf * Since we did a callback, ioctl 7291709Smlf * should return 0. 7301709Smlf */ 7311709Smlf err = 0; 7321709Smlf } 7331709Smlf return (err); 7341709Smlf } 7351709Smlf mutex_exit(&dadkp->dad_mutex); 7361709Smlf 7371709Smlf bp = getrbuf(KM_SLEEP); 7381709Smlf 7391709Smlf bp->b_edev = dev; 7401709Smlf bp->b_dev = cmpdev(dev); 7411709Smlf bp->b_flags = B_BUSY; 7421709Smlf bp->b_resid = 0; 7431709Smlf bp->b_bcount = 0; 7441709Smlf SET_BP_SEC(bp, 0); 7451709Smlf 7461709Smlf if ((flag & FKIOCTL) && dkc != NULL && 7471709Smlf dkc->dkc_callback != NULL) { 7481709Smlf struct dk_callback *dkc2 = 7491709Smlf (struct dk_callback *)kmem_zalloc( 7501709Smlf sizeof (struct dk_callback), KM_SLEEP); 7511709Smlf 7521709Smlf bcopy(dkc, dkc2, sizeof (*dkc2)); 7531709Smlf /* 7541709Smlf * Borrow b_list to carry private data 7551709Smlf * to the b_iodone func. 7561709Smlf */ 7571709Smlf bp->b_list = (struct buf *)dkc2; 7581709Smlf bp->b_iodone = dadk_flushdone; 7591709Smlf is_sync = 0; 7601709Smlf } 7611709Smlf 7621709Smlf /* 7631709Smlf * Setup command pkt 7641709Smlf * dadk_pktprep() can't fail since DDI_DMA_SLEEP set 7651709Smlf */ 7661709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, 7671709Smlf dadk_iodone, DDI_DMA_SLEEP, NULL); 7681709Smlf 7691709Smlf pktp->cp_time = DADK_FLUSH_CACHE_TIME; 7701709Smlf 7711709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE; 7721709Smlf pktp->cp_byteleft = 0; 7731709Smlf pktp->cp_private = NULL; 7741709Smlf pktp->cp_secleft = 0; 7751709Smlf pktp->cp_srtsec = -1; 7761709Smlf pktp->cp_bytexfer = 0; 7771709Smlf 7781709Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 7791709Smlf 7801709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 7811709Smlf 7821709Smlf if (is_sync) { 7831709Smlf err = biowait(bp); 7841709Smlf freerbuf(bp); 7851709Smlf } 7861709Smlf return (err); 7871709Smlf } 7881709Smlf default: 7891709Smlf if (!dadkp->dad_rmb) 7901709Smlf return (CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag)); 7911709Smlf } 7921709Smlf 7931709Smlf switch (cmd) { 7941709Smlf case CDROMSTOP: 7951709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 7961709Smlf 0, DADK_SILENT)); 7971709Smlf case CDROMSTART: 7981709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 7991709Smlf 0, DADK_SILENT)); 8001709Smlf case DKIOCLOCK: 8011709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT)); 8021709Smlf case DKIOCUNLOCK: 8031709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT)); 8041709Smlf case DKIOCEJECT: 8051709Smlf case CDROMEJECT: 8061709Smlf { 8071709Smlf int ret; 8081709Smlf 8091709Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, 8101709Smlf DADK_SILENT)) { 8111709Smlf return (ret); 8121709Smlf } 8131709Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0, 8141709Smlf DADK_SILENT)) { 8151709Smlf return (ret); 8161709Smlf } 8171709Smlf mutex_enter(&dadkp->dad_mutex); 8181709Smlf dadkp->dad_iostate = DKIO_EJECTED; 8191709Smlf cv_broadcast(&dadkp->dad_state_cv); 8201709Smlf mutex_exit(&dadkp->dad_mutex); 8211709Smlf 8221709Smlf return (0); 8231709Smlf 8241709Smlf } 8251709Smlf default: 8261709Smlf return (ENOTTY); 8271709Smlf /* 8281709Smlf * cdrom audio commands 8291709Smlf */ 8301709Smlf case CDROMPAUSE: 8311709Smlf cmd = DCMD_PAUSE; 8321709Smlf break; 8331709Smlf case CDROMRESUME: 8341709Smlf cmd = DCMD_RESUME; 8351709Smlf break; 8361709Smlf case CDROMPLAYMSF: 8371709Smlf cmd = DCMD_PLAYMSF; 8381709Smlf break; 8391709Smlf case CDROMPLAYTRKIND: 8401709Smlf cmd = DCMD_PLAYTRKIND; 8411709Smlf break; 8421709Smlf case CDROMREADTOCHDR: 8431709Smlf cmd = DCMD_READTOCHDR; 8441709Smlf break; 8451709Smlf case CDROMREADTOCENTRY: 8461709Smlf cmd = DCMD_READTOCENT; 8471709Smlf break; 8481709Smlf case CDROMVOLCTRL: 8491709Smlf cmd = DCMD_VOLCTRL; 8501709Smlf break; 8511709Smlf case CDROMSUBCHNL: 8521709Smlf cmd = DCMD_SUBCHNL; 8531709Smlf break; 8541709Smlf case CDROMREADMODE2: 8551709Smlf cmd = DCMD_READMODE2; 8561709Smlf break; 8571709Smlf case CDROMREADMODE1: 8581709Smlf cmd = DCMD_READMODE1; 8591709Smlf break; 8601709Smlf case CDROMREADOFFSET: 8611709Smlf cmd = DCMD_READOFFSET; 8621709Smlf break; 8631709Smlf } 8641709Smlf return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0)); 8651709Smlf } 8661709Smlf 8671709Smlf int 8681709Smlf dadk_flushdone(struct buf *bp) 8691709Smlf { 8701709Smlf struct dk_callback *dkc = (struct dk_callback *)bp->b_list; 8711709Smlf 8721709Smlf ASSERT(dkc != NULL && dkc->dkc_callback != NULL); 8731709Smlf 8741709Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp)); 8751709Smlf 8761709Smlf kmem_free(dkc, sizeof (*dkc)); 8771709Smlf freerbuf(bp); 8781709Smlf return (0); 8791709Smlf } 8801709Smlf 8811709Smlf int 8821709Smlf dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 8831709Smlf { 8841709Smlf struct dadk *dadkp = (struct dadk *)objp; 8851709Smlf 8861709Smlf bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p, 8871709Smlf sizeof (struct tgdk_geom)); 8881709Smlf return (DDI_SUCCESS); 8891709Smlf } 8901709Smlf 8911709Smlf int 8921709Smlf dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 8931709Smlf { 8941709Smlf struct dadk *dadkp = (struct dadk *)objp; 8951709Smlf bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p, 8961709Smlf sizeof (struct tgdk_geom)); 8971709Smlf return (DDI_SUCCESS); 8981709Smlf } 8991709Smlf 9001709Smlf int 9011709Smlf dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 9021709Smlf { 9031709Smlf struct dadk *dadkp = (struct dadk *)objp; 9041709Smlf 9051709Smlf dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl; 9061709Smlf dadkp->dad_logg.g_head = dkgeom_p->g_head; 9071709Smlf dadkp->dad_logg.g_sec = dkgeom_p->g_sec; 9081709Smlf dadkp->dad_logg.g_cap = dkgeom_p->g_cap; 9091709Smlf return (DDI_SUCCESS); 9101709Smlf } 9111709Smlf 9121709Smlf 9131709Smlf tgdk_iob_handle 9141709Smlf dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg) 9151709Smlf { 9161709Smlf struct dadk *dadkp = (struct dadk *)objp; 9171709Smlf struct buf *bp; 9181709Smlf struct tgdk_iob *iobp; 9191709Smlf size_t rlen; 9201709Smlf 9211709Smlf iobp = kmem_zalloc(sizeof (*iobp), kmsflg); 9221709Smlf if (iobp == NULL) 9231709Smlf return (NULL); 9241709Smlf if ((bp = getrbuf(kmsflg)) == NULL) { 9251709Smlf kmem_free(iobp, sizeof (*iobp)); 9261709Smlf return (NULL); 9271709Smlf } 9281709Smlf 9291709Smlf iobp->b_psec = LBLK2SEC(blkno, dadkp->dad_blkshf); 9301709Smlf iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT; 9311709Smlf iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1) 9321709Smlf >> dadkp->dad_secshf) << dadkp->dad_secshf; 9331709Smlf 9341709Smlf bp->b_un.b_addr = 0; 9351709Smlf /* 9361709Smlf * use i_ddi_mem_alloc() for now until we have an interface to allocate 9371709Smlf * memory for DMA which doesn't require a DMA handle. ddi_iopb_alloc() 9381709Smlf * is obsolete and we want more flexibility in controlling the DMA 9391709Smlf * address constraints.. 9401709Smlf */ 9411709Smlf if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr, 9421709Smlf (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL, 9431709Smlf &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) { 9441709Smlf freerbuf(bp); 9451709Smlf kmem_free(iobp, sizeof (*iobp)); 9461709Smlf return (NULL); 9471709Smlf } 9481709Smlf iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC; 9491709Smlf iobp->b_bp = bp; 9501709Smlf iobp->b_lblk = blkno; 9511709Smlf iobp->b_xfer = xfer; 9521709Smlf iobp->b_lblk = blkno; 9531709Smlf iobp->b_xfer = xfer; 9541709Smlf return (iobp); 9551709Smlf } 9561709Smlf 9571709Smlf /* ARGSUSED */ 9581709Smlf int 9591709Smlf dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp) 9601709Smlf { 9611709Smlf struct buf *bp; 9621709Smlf 9631709Smlf if (iobp) { 9641709Smlf if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) { 9651709Smlf bp = iobp->b_bp; 9661709Smlf if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC)) 967*1900Seota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 9681709Smlf freerbuf(bp); 9691709Smlf } 9701709Smlf kmem_free(iobp, sizeof (*iobp)); 9711709Smlf } 9721709Smlf return (DDI_SUCCESS); 9731709Smlf } 9741709Smlf 9751709Smlf /* ARGSUSED */ 9761709Smlf caddr_t 9771709Smlf dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp) 9781709Smlf { 9791709Smlf return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff); 9801709Smlf } 9811709Smlf 9821709Smlf 9831709Smlf caddr_t 9841709Smlf dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw) 9851709Smlf { 9861709Smlf struct dadk *dadkp = (struct dadk *)objp; 9871709Smlf struct buf *bp; 9881709Smlf int err; 9891709Smlf 9901709Smlf bp = iobp->b_bp; 9911709Smlf if (dadkp->dad_rdonly && !(rw & B_READ)) { 9921709Smlf bioerror(bp, EROFS); 9931709Smlf return (NULL); 9941709Smlf } 9951709Smlf 9961709Smlf bp->b_flags |= (B_BUSY | rw); 9971709Smlf bp->b_bcount = iobp->b_pbytecnt; 9981709Smlf SET_BP_SEC(bp, iobp->b_psec); 9991709Smlf bp->av_back = (struct buf *)0; 10001709Smlf bp->b_resid = 0; 10011709Smlf 10021709Smlf /* call flow control */ 10031709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 10041709Smlf err = biowait(bp); 10051709Smlf 10061709Smlf bp->b_bcount = iobp->b_xfer; 10071709Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 10081709Smlf 10091709Smlf if (err) 10101709Smlf return (NULL); 10111709Smlf 10121709Smlf return (bp->b_un.b_addr+iobp->b_pbyteoff); 10131709Smlf } 10141709Smlf 10151709Smlf static void 10161709Smlf dadk_transport(opaque_t com_data, struct buf *bp) 10171709Smlf { 10181709Smlf struct dadk *dadkp = (struct dadk *)com_data; 10191709Smlf 10201709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) == 10211709Smlf CTL_SEND_SUCCESS) 10221709Smlf return; 10231709Smlf dadk_restart((void*)GDA_BP_PKT(bp)); 10241709Smlf } 10251709Smlf 10261709Smlf static int 10271709Smlf dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg) 10281709Smlf { 10291709Smlf struct cmpkt *pktp; 10301709Smlf struct dadk *dadkp = (struct dadk *)com_data; 10311709Smlf 10321709Smlf if (GDA_BP_PKT(bp)) 10331709Smlf return (DDI_SUCCESS); 10341709Smlf 10351709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg); 10361709Smlf if (!pktp) 10371709Smlf return (DDI_FAILURE); 10381709Smlf 10391709Smlf return (dadk_ioprep(dadkp, pktp)); 10401709Smlf } 10411709Smlf 10421709Smlf /* 10431709Smlf * Read, Write preparation 10441709Smlf */ 10451709Smlf static int 10461709Smlf dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp) 10471709Smlf { 10481709Smlf struct buf *bp; 10491709Smlf 10501709Smlf bp = pktp->cp_bp; 10511709Smlf if (bp->b_forw == (struct buf *)dadkp) 10521709Smlf *((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back; 10531709Smlf 10541709Smlf else if (bp->b_flags & B_READ) 10551709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_READ; 10561709Smlf else 10571709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_WRITE; 10581709Smlf pktp->cp_byteleft = bp->b_bcount; 10591709Smlf 10601709Smlf /* setup the bad block list handle */ 10611709Smlf pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp); 10621709Smlf return (dadk_iosetup(dadkp, pktp)); 10631709Smlf } 10641709Smlf 10651709Smlf static int 10661709Smlf dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp) 10671709Smlf { 10681709Smlf struct buf *bp; 10691709Smlf bbh_cookie_t bbhckp; 10701709Smlf int seccnt; 10711709Smlf 10721709Smlf seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf; 10731709Smlf pktp->cp_secleft -= seccnt; 10741709Smlf 10751709Smlf if (pktp->cp_secleft) { 10761709Smlf pktp->cp_srtsec += seccnt; 10771709Smlf } else { 10781709Smlf /* get the first cookie from the bad block list */ 10791709Smlf if (!pktp->cp_private) { 10801709Smlf bp = pktp->cp_bp; 10811709Smlf pktp->cp_srtsec = GET_BP_SEC(bp); 10821709Smlf pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf); 10831709Smlf } else { 10841709Smlf bbhckp = BBH_HTOC(dadkp->dad_bbhobjp, 10851709Smlf pktp->cp_private); 10861709Smlf pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp, 10871709Smlf bbhckp); 10881709Smlf pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp, 10891709Smlf bbhckp); 10901709Smlf } 10911709Smlf } 10921709Smlf 10931709Smlf pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf; 10941709Smlf 10951709Smlf if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) { 10961709Smlf return (DDI_SUCCESS); 10971709Smlf } else { 10981709Smlf return (DDI_FAILURE); 10991709Smlf } 11001709Smlf 11011709Smlf 11021709Smlf 11031709Smlf 11041709Smlf } 11051709Smlf 11061709Smlf static struct cmpkt * 11071709Smlf dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp, 11081709Smlf void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg) 11091709Smlf { 11101709Smlf struct cmpkt *pktp; 11111709Smlf 11121709Smlf pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func, 11131709Smlf arg); 11141709Smlf 11151709Smlf if (pktp) { 11161709Smlf pktp->cp_callback = dadk_pktcb; 11171709Smlf pktp->cp_time = DADK_IO_TIME; 11181709Smlf pktp->cp_flags = 0; 11191709Smlf pktp->cp_iodone = cb_func; 11201709Smlf pktp->cp_dev_private = (opaque_t)dadkp; 11211709Smlf 11221709Smlf } 11231709Smlf 11241709Smlf return (pktp); 11251709Smlf } 11261709Smlf 11271709Smlf 11281709Smlf static void 11291709Smlf dadk_restart(void *vpktp) 11301709Smlf { 11311709Smlf struct cmpkt *pktp = (struct cmpkt *)vpktp; 11321709Smlf 11331709Smlf if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN) 11341709Smlf return; 11351709Smlf pktp->cp_iodone(pktp->cp_bp); 11361709Smlf } 11371709Smlf 11381709Smlf static int 11391709Smlf dadk_ioretry(struct cmpkt *pktp, int action) 11401709Smlf { 11411709Smlf struct buf *bp; 11421709Smlf struct dadk *dadkp = PKT2DADK(pktp); 11431709Smlf 11441709Smlf switch (action) { 11451709Smlf case QUE_COMMAND: 11461709Smlf if (pktp->cp_retry++ < DADK_RETRY_COUNT) { 11471709Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 11481709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == 11491709Smlf CTL_SEND_SUCCESS) { 11501709Smlf return (JUST_RETURN); 11511709Smlf } 11521709Smlf gda_log(dadkp->dad_sd->sd_dev, dadk_name, 11531709Smlf CE_WARN, 11541709Smlf "transport of command fails\n"); 11551709Smlf } else 11561709Smlf gda_log(dadkp->dad_sd->sd_dev, 11571709Smlf dadk_name, CE_WARN, 11581709Smlf "exceeds maximum number of retries\n"); 11591709Smlf bioerror(pktp->cp_bp, ENXIO); 11601709Smlf /*FALLTHROUGH*/ 11611709Smlf case COMMAND_DONE_ERROR: 11621709Smlf bp = pktp->cp_bp; 11631709Smlf bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer + 11641709Smlf pktp->cp_resid; 11651709Smlf if (geterror(bp) == 0) { 11661709Smlf if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) && 11671709Smlf (pktp->cp_dev_private == (opaque_t)dadkp) && 11681709Smlf ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) { 11691709Smlf /* 11701709Smlf * Flag "unimplemented" responses for 11711709Smlf * DCMD_FLUSH_CACHE as ENOTSUP 11721709Smlf */ 11731709Smlf bioerror(bp, ENOTSUP); 11741709Smlf mutex_enter(&dadkp->dad_mutex); 11751709Smlf dadkp->dad_noflush = 1; 11761709Smlf mutex_exit(&dadkp->dad_mutex); 11771709Smlf } else { 11781709Smlf bioerror(bp, EIO); 11791709Smlf } 11801709Smlf } 11811709Smlf /*FALLTHROUGH*/ 11821709Smlf case COMMAND_DONE: 11831709Smlf default: 11841709Smlf return (COMMAND_DONE); 11851709Smlf } 11861709Smlf } 11871709Smlf 11881709Smlf 11891709Smlf static void 11901709Smlf dadk_pktcb(struct cmpkt *pktp) 11911709Smlf { 11921709Smlf int action; 11931709Smlf struct dadkio_rwcmd *rwcmdp; 11941709Smlf 11951709Smlf rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru; /* ioctl packet */ 11961709Smlf 11971709Smlf if (pktp->cp_reason == CPS_SUCCESS) { 11981709Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) 11991709Smlf rwcmdp->status.status = DADKIO_STAT_NO_ERROR; 12001709Smlf pktp->cp_iodone(pktp->cp_bp); 12011709Smlf return; 12021709Smlf } 12031709Smlf 12041709Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) { 12051709Smlf if (pktp->cp_reason == CPS_CHKERR) 12061709Smlf dadk_recorderr(pktp, rwcmdp); 12071709Smlf dadk_iodone(pktp->cp_bp); 12081709Smlf return; 12091709Smlf } 12101709Smlf 12111709Smlf if (pktp->cp_reason == CPS_CHKERR) 12121709Smlf action = dadk_chkerr(pktp); 12131709Smlf else 12141709Smlf action = COMMAND_DONE_ERROR; 12151709Smlf 12161709Smlf if (action == JUST_RETURN) 12171709Smlf return; 12181709Smlf 12191709Smlf if (action != COMMAND_DONE) { 12201709Smlf if ((dadk_ioretry(pktp, action)) == JUST_RETURN) 12211709Smlf return; 12221709Smlf } 12231709Smlf pktp->cp_iodone(pktp->cp_bp); 12241709Smlf } 12251709Smlf 12261709Smlf 12271709Smlf 12281709Smlf static struct dadkio_derr dadk_errtab[] = { 12291709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 0 DERR_SUCCESS */ 12301709Smlf {QUE_COMMAND, GDA_FATAL}, /* 1 DERR_AMNF */ 12311709Smlf {QUE_COMMAND, GDA_FATAL}, /* 2 DERR_TKONF */ 12321709Smlf {COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT */ 12331709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 4 DERR_DWF */ 12341709Smlf {QUE_COMMAND, GDA_FATAL}, /* 5 DERR_IDNF */ 12351709Smlf {JUST_RETURN, GDA_INFORMATIONAL}, /* 6 DERR_BUSY */ 12361709Smlf {QUE_COMMAND, GDA_FATAL}, /* 7 DERR_UNC */ 12371709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 8 DERR_BBK */ 12381709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 9 DERR_INVCDB */ 12391709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 10 DERR_HARD */ 12401709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 11 DERR_ILI */ 12411709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 12 DERR_EOM */ 12421709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 13 DERR_MCR */ 12431709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 14 DERR_RECOVER */ 12441709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 15 DERR_NOTREADY */ 12451709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 16 DERR_MEDIUM */ 12461709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 17 DERR_HW */ 12471709Smlf {COMMAND_DONE, GDA_FATAL}, /* 18 DERR_ILL */ 12481709Smlf {COMMAND_DONE, GDA_FATAL}, /* 19 DERR_UNIT_ATTN */ 12491709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 20 DERR_DATA_PROT */ 12501709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 21 DERR_MISCOMPARE */ 12511709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 22 DERR_ICRC */ 12521709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 23 DERR_RESV */ 12531709Smlf }; 12541709Smlf 12551709Smlf static int 12561709Smlf dadk_chkerr(struct cmpkt *pktp) 12571709Smlf { 12581709Smlf int err_blkno; 12591709Smlf struct dadk *dadkp; 12601709Smlf int scb; 12611709Smlf 12621709Smlf if (*(char *)pktp->cp_scbp == DERR_SUCCESS) 12631709Smlf return (COMMAND_DONE); 12641709Smlf 12651709Smlf /* check error code table */ 12661709Smlf dadkp = PKT2DADK(pktp); 12671709Smlf scb = (int)(*(char *)pktp->cp_scbp); 12681709Smlf if (pktp->cp_retry) { 12691709Smlf err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer - 12701709Smlf pktp->cp_resid) >> dadkp->dad_secshf); 12711709Smlf } else 12721709Smlf err_blkno = -1; 12731709Smlf 12741709Smlf /* if attempting to read a sector from a cdrom audio disk */ 12751709Smlf if ((dadkp->dad_cdrom) && 12761709Smlf (*((char *)(pktp->cp_cdbp)) == DCMD_READ) && 12771709Smlf (scb == DERR_ILL)) { 12781709Smlf return (COMMAND_DONE); 12791709Smlf } 12801709Smlf if (pktp->cp_passthru == NULL) { 12811709Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, 12821709Smlf dadk_errtab[scb].d_severity, pktp->cp_srtsec, 12831709Smlf err_blkno, dadk_cmds, dadk_sense); 12841709Smlf } 12851709Smlf 12861709Smlf if (scb == DERR_BUSY) { 12871709Smlf (void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT); 12881709Smlf } 12891709Smlf 12901709Smlf return (dadk_errtab[scb].d_action); 12911709Smlf } 12921709Smlf 12931709Smlf static void 12941709Smlf dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp) 12951709Smlf { 12961709Smlf struct dadk *dadkp; 12971709Smlf int scb; 12981709Smlf 12991709Smlf dadkp = PKT2DADK(pktp); 13001709Smlf scb = (int)(*(char *)pktp->cp_scbp); 13011709Smlf 13021709Smlf 13031709Smlf rwcmdp->status.failed_blk = rwcmdp->blkaddr + 13041709Smlf ((pktp->cp_bytexfer - 13051709Smlf pktp->cp_resid) >> dadkp->dad_secshf); 13061709Smlf 13071709Smlf rwcmdp->status.resid = pktp->cp_bp->b_resid + 13081709Smlf pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid; 13091709Smlf switch ((int)(* (char *)pktp->cp_scbp)) { 13101709Smlf case DERR_AMNF: 13111709Smlf case DERR_ABORT: 13121709Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST; 13131709Smlf break; 13141709Smlf case DERR_DWF: 13151709Smlf case DERR_IDNF: 13161709Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS; 13171709Smlf break; 13181709Smlf case DERR_TKONF: 13191709Smlf case DERR_UNC: 13201709Smlf case DERR_BBK: 13211709Smlf rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR; 13221709Smlf rwcmdp->status.failed_blk_is_valid = 1; 13231709Smlf rwcmdp->status.resid = 0; 13241709Smlf break; 13251709Smlf case DERR_BUSY: 13261709Smlf rwcmdp->status.status = DADKIO_STAT_NOT_READY; 13271709Smlf break; 13281709Smlf case DERR_INVCDB: 13291709Smlf case DERR_HARD: 13301709Smlf rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR; 13311709Smlf break; 13321709Smlf case DERR_ICRC: 13331709Smlf default: 13341709Smlf rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED; 13351709Smlf } 13361709Smlf 13371709Smlf if (rwcmdp->flags & DADKIO_FLAG_SILENT) 13381709Smlf return; 13391709Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity, 13401709Smlf rwcmdp->blkaddr, rwcmdp->status.failed_blk, 13411709Smlf dadk_cmds, dadk_sense); 13421709Smlf } 13431709Smlf 13441709Smlf /*ARGSUSED*/ 13451709Smlf static void 13461709Smlf dadk_polldone(struct buf *bp) 13471709Smlf { 13481709Smlf } 13491709Smlf 13501709Smlf static void 13511709Smlf dadk_iodone(struct buf *bp) 13521709Smlf { 13531709Smlf struct cmpkt *pktp; 13541709Smlf struct dadk *dadkp; 13551709Smlf 13561709Smlf pktp = GDA_BP_PKT(bp); 13571709Smlf dadkp = PKT2DADK(pktp); 13581709Smlf 13591709Smlf /* check for all iodone */ 13601709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 13611709Smlf if (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 13621709Smlf pktp->cp_retry = 0; 13631709Smlf (void) dadk_iosetup(dadkp, pktp); 13641709Smlf 13651709Smlf 13661709Smlf /* transport the next one */ 13671709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS) 13681709Smlf return; 13691709Smlf if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN) 13701709Smlf return; 13711709Smlf } 13721709Smlf 13731709Smlf /* start next one */ 13741709Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 13751709Smlf 13761709Smlf /* free pkt */ 13771709Smlf if (pktp->cp_private) 13781709Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 13791709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 13801709Smlf biodone(bp); 13811709Smlf } 13821709Smlf 13831709Smlf int 13841709Smlf dadk_check_media(opaque_t objp, int *state) 13851709Smlf { 13861709Smlf struct dadk *dadkp = (struct dadk *)objp; 13871709Smlf 13881709Smlf if (!dadkp->dad_rmb) { 13891709Smlf return (ENXIO); 13901709Smlf } 13911709Smlf #ifdef DADK_DEBUG 13921709Smlf if (dadk_debug & DSTATE) 13931709Smlf PRF("dadk_check_media: user state %x disk state %x\n", 13941709Smlf *state, dadkp->dad_iostate); 13951709Smlf #endif 13961709Smlf /* 13971709Smlf * If state already changed just return 13981709Smlf */ 13991709Smlf if (*state != dadkp->dad_iostate) { 14001709Smlf *state = dadkp->dad_iostate; 14011709Smlf return (0); 14021709Smlf } 14031709Smlf 14041709Smlf /* 14051709Smlf * Startup polling on thread state 14061709Smlf */ 14071709Smlf mutex_enter(&dadkp->dad_mutex); 14081709Smlf if (dadkp->dad_thread_cnt == 0) { 14091709Smlf /* 14101709Smlf * One thread per removable dadk device 14111709Smlf */ 14121709Smlf (void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0, 14131709Smlf TS_RUN, v.v_maxsyspri - 2); 14141709Smlf } 14151709Smlf dadkp->dad_thread_cnt++; 14161709Smlf 14171709Smlf /* 14181709Smlf * Wait for state to change 14191709Smlf */ 14201709Smlf do { 14211709Smlf if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) { 14221709Smlf dadkp->dad_thread_cnt--; 14231709Smlf mutex_exit(&dadkp->dad_mutex); 14241709Smlf return (EINTR); 14251709Smlf } 14261709Smlf } while (*state == dadkp->dad_iostate); 14271709Smlf *state = dadkp->dad_iostate; 14281709Smlf dadkp->dad_thread_cnt--; 14291709Smlf mutex_exit(&dadkp->dad_mutex); 14301709Smlf return (0); 14311709Smlf } 14321709Smlf 14331709Smlf 14341709Smlf #define MEDIA_ACCESS_DELAY 2000000 14351709Smlf 14361709Smlf static void 14371709Smlf dadk_watch_thread(struct dadk *dadkp) 14381709Smlf { 14391709Smlf enum dkio_state state; 14401709Smlf int interval; 14411709Smlf 14421709Smlf interval = drv_usectohz(dadk_check_media_time); 14431709Smlf 14441709Smlf do { 14451709Smlf if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0, 14461709Smlf DADK_SILENT)) { 14471709Smlf /* 14481709Smlf * Assume state remained the same 14491709Smlf */ 14501709Smlf state = dadkp->dad_iostate; 14511709Smlf } 14521709Smlf 14531709Smlf /* 14541709Smlf * now signal the waiting thread if this is *not* the 14551709Smlf * specified state; 14561709Smlf * delay the signal if the state is DKIO_INSERTED 14571709Smlf * to allow the target to recover 14581709Smlf */ 14591709Smlf if (state != dadkp->dad_iostate) { 14601709Smlf 14611709Smlf dadkp->dad_iostate = state; 14621709Smlf if (state == DKIO_INSERTED) { 14631709Smlf /* 14641709Smlf * delay the signal to give the drive a chance 14651709Smlf * to do what it apparently needs to do 14661709Smlf */ 14671709Smlf (void) timeout((void(*)(void *))cv_broadcast, 14681709Smlf (void *)&dadkp->dad_state_cv, 14691709Smlf drv_usectohz((clock_t)MEDIA_ACCESS_DELAY)); 14701709Smlf } else { 14711709Smlf cv_broadcast(&dadkp->dad_state_cv); 14721709Smlf } 14731709Smlf } 14741709Smlf delay(interval); 14751709Smlf } while (dadkp->dad_thread_cnt); 14761709Smlf } 14771709Smlf 14781709Smlf int 14791709Smlf dadk_inquiry(opaque_t objp, opaque_t *inqpp) 14801709Smlf { 14811709Smlf struct dadk *dadkp = (struct dadk *)objp; 14821709Smlf struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp; 14831709Smlf 14841709Smlf if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) { 14851709Smlf *sinqpp = dadkp->dad_sd->sd_inq; 14861709Smlf return (DDI_SUCCESS); 14871709Smlf } 14881709Smlf 14891709Smlf return (DDI_FAILURE); 14901709Smlf } 14911709Smlf 14921709Smlf static int 14931709Smlf dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent) 14941709Smlf 14951709Smlf { 14961709Smlf struct buf *bp; 14971709Smlf int err; 14981709Smlf struct cmpkt *pktp; 14991709Smlf 15001709Smlf if ((bp = getrbuf(KM_SLEEP)) == NULL) { 15011709Smlf return (ENOMEM); 15021709Smlf } 15031709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL); 15041709Smlf if (!pktp) { 15051709Smlf freerbuf(bp); 15061709Smlf return (ENOMEM); 15071709Smlf } 15081709Smlf bp->b_back = (struct buf *)arg; 15091709Smlf bp->b_forw = (struct buf *)dadkp->dad_flcobjp; 15101709Smlf pktp->cp_passthru = (opaque_t)(intptr_t)silent; 15111709Smlf 15121709Smlf err = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, (uintptr_t)pktp, flags); 15131709Smlf freerbuf(bp); 15141709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 15151709Smlf return (err); 15161709Smlf 15171709Smlf 15181709Smlf } 15191709Smlf 15201709Smlf static void 15211709Smlf dadk_rmb_iodone(struct buf *bp) 15221709Smlf { 15231709Smlf struct cmpkt *pktp; 15241709Smlf struct dadk *dadkp; 15251709Smlf 15261709Smlf pktp = GDA_BP_PKT(bp); 15271709Smlf dadkp = PKT2DADK(pktp); 15281709Smlf 15291709Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 15301709Smlf 15311709Smlf /* Start next one */ 15321709Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 15331709Smlf 15341709Smlf biodone(bp); 15351709Smlf } 15361709Smlf 15371709Smlf static int 15381709Smlf dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev, 15391709Smlf enum uio_seg dataspace, int rw) 15401709Smlf { 15411709Smlf struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp; 15421709Smlf struct buf *bp; 15431709Smlf struct iovec aiov; 15441709Smlf struct uio auio; 15451709Smlf struct uio *uio = &auio; 15461709Smlf int status; 15471709Smlf 15481709Smlf bp = getrbuf(KM_SLEEP); 15491709Smlf 15501709Smlf bp->av_forw = bp->b_forw = (struct buf *)dadkp; 15511709Smlf bp->b_back = (struct buf *)rwcmdp; /* ioctl packet */ 15521709Smlf 15531709Smlf bzero((caddr_t)&auio, sizeof (struct uio)); 15541709Smlf bzero((caddr_t)&aiov, sizeof (struct iovec)); 15551709Smlf aiov.iov_base = rwcmdp->bufaddr; 15561709Smlf aiov.iov_len = rwcmdp->buflen; 15571709Smlf uio->uio_iov = &aiov; 15581709Smlf 15591709Smlf uio->uio_iovcnt = 1; 15601709Smlf uio->uio_resid = rwcmdp->buflen; 15611709Smlf uio->uio_segflg = dataspace; 15621709Smlf 15631709Smlf /* Let physio do the rest... */ 15641709Smlf status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio); 15651709Smlf 15661709Smlf freerbuf(bp); 15671709Smlf return (status); 15681709Smlf 15691709Smlf } 15701709Smlf 15711709Smlf /* Do not let a user gendisk request get too big or */ 15721709Smlf /* else we could use to many resources. */ 15731709Smlf 15741709Smlf static void 15751709Smlf dadkmin(struct buf *bp) 15761709Smlf { 15771709Smlf if (bp->b_bcount > dadk_dk_maxphys) 15781709Smlf bp->b_bcount = dadk_dk_maxphys; 15791709Smlf } 15801709Smlf 15811709Smlf static int 15821709Smlf dadk_dk_strategy(struct buf *bp) 15831709Smlf { 15841709Smlf dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back, 15851709Smlf bp); 15861709Smlf return (0); 15871709Smlf } 15881709Smlf 15891709Smlf static void 15901709Smlf dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp) 15911709Smlf { 15921709Smlf struct cmpkt *pktp; 15931709Smlf 15941709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL); 15951709Smlf if (!pktp) { 15961709Smlf bioerror(bp, ENOMEM); 15971709Smlf biodone(bp); 15981709Smlf return; 15991709Smlf } 16001709Smlf 16011709Smlf pktp->cp_passthru = rwcmdp; 16021709Smlf 16031709Smlf (void) dadk_ioprep(dadkp, pktp); 16041709Smlf 16051709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 16061709Smlf } 1607