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*7239Szk194757 * Copyright 2008 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> 403652Syt160523 #include <sys/policy.h> 413652Syt160523 #include <sys/priv.h> 421709Smlf 431709Smlf #include <sys/dktp/dadev.h> 441709Smlf #include <sys/dktp/fctypes.h> 451709Smlf #include <sys/dktp/flowctrl.h> 461709Smlf #include <sys/dktp/tgcom.h> 471709Smlf #include <sys/dktp/tgdk.h> 481709Smlf #include <sys/dktp/bbh.h> 491709Smlf #include <sys/dktp/dadkio.h> 501709Smlf #include <sys/dktp/dadk.h> 511709Smlf #include <sys/cdio.h> 521709Smlf 531709Smlf /* 541709Smlf * Local Function Prototypes 551709Smlf */ 561709Smlf static void dadk_restart(void *pktp); 571709Smlf static void dadk_pktcb(struct cmpkt *pktp); 581709Smlf static void dadk_iodone(struct buf *bp); 591709Smlf static void dadk_polldone(struct buf *bp); 601709Smlf static void dadk_setcap(struct dadk *dadkp); 612799Smarx static void dadk_create_errstats(struct dadk *dadkp, int instance); 622799Smarx static void dadk_destroy_errstats(struct dadk *dadkp); 631709Smlf 641709Smlf static int dadk_chkerr(struct cmpkt *pktp); 651709Smlf static int dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp); 661709Smlf static int dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp); 671709Smlf static int dadk_ioretry(struct cmpkt *pktp, int action); 681709Smlf 691709Smlf static struct cmpkt *dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, 701709Smlf struct buf *bp, void (*cb_func)(struct buf *), int (*func)(caddr_t), 711709Smlf caddr_t arg); 721709Smlf 731709Smlf static int dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), 741709Smlf caddr_t arg); 751709Smlf static void dadk_transport(opaque_t com_data, struct buf *bp); 765295Srandyf static int dadk_ctl_ioctl(struct dadk *, uint32_t, uintptr_t, int); 771709Smlf 781709Smlf struct tgcom_objops dadk_com_ops = { 791709Smlf nodev, 801709Smlf nodev, 811709Smlf dadk_pkt, 821709Smlf dadk_transport, 831709Smlf 0, 0 841709Smlf }; 851709Smlf 861709Smlf /* 871709Smlf * architecture dependent allocation restrictions for dadk_iob_alloc(). For 881709Smlf * x86, we'll set dma_attr_addr_hi to dadk_max_phys_addr and dma_attr_sgllen 891709Smlf * to dadk_sgl_size during _init(). 901709Smlf */ 911709Smlf #if defined(__sparc) 921709Smlf static ddi_dma_attr_t dadk_alloc_attr = { 931709Smlf DMA_ATTR_V0, /* version number */ 941709Smlf 0x0, /* lowest usable address */ 951709Smlf 0xFFFFFFFFull, /* high DMA address range */ 961709Smlf 0xFFFFFFFFull, /* DMA counter register */ 971709Smlf 1, /* DMA address alignment */ 981709Smlf 1, /* DMA burstsizes */ 991709Smlf 1, /* min effective DMA size */ 1001709Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 1011709Smlf 0xFFFFFFFFull, /* segment boundary */ 1021709Smlf 1, /* s/g list length */ 1031709Smlf 512, /* granularity of device */ 1041709Smlf 0, /* DMA transfer flags */ 1051709Smlf }; 1061709Smlf #elif defined(__x86) 1071709Smlf static ddi_dma_attr_t dadk_alloc_attr = { 1081709Smlf DMA_ATTR_V0, /* version number */ 1091709Smlf 0x0, /* lowest usable address */ 1101709Smlf 0x0, /* high DMA address range [set in _init()] */ 1111709Smlf 0xFFFFull, /* DMA counter register */ 1121709Smlf 512, /* DMA address alignment */ 1131709Smlf 1, /* DMA burstsizes */ 1141709Smlf 1, /* min effective DMA size */ 1151709Smlf 0xFFFFFFFFull, /* max DMA xfer size */ 1161709Smlf 0xFFFFFFFFull, /* segment boundary */ 1171709Smlf 0, /* s/g list length [set in _init()] */ 1181709Smlf 512, /* granularity of device */ 1191709Smlf 0, /* DMA transfer flags */ 1201709Smlf }; 1211709Smlf 1221709Smlf uint64_t dadk_max_phys_addr = 0xFFFFFFFFull; 1231709Smlf int dadk_sgl_size = 0xFF; 1241709Smlf #endif 1251709Smlf 1261709Smlf static int dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, 1271709Smlf int silent); 1281709Smlf static void dadk_rmb_iodone(struct buf *bp); 1291709Smlf 1301709Smlf static int dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, 1311709Smlf dev_t dev, enum uio_seg dataspace, int rw); 1321709Smlf static void dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *scmdp, 1331709Smlf struct buf *bp); 1341709Smlf static void dadkmin(struct buf *bp); 1351709Smlf static int dadk_dk_strategy(struct buf *bp); 1361709Smlf static void dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp); 1371709Smlf 1381709Smlf struct tgdk_objops dadk_ops = { 1391709Smlf dadk_init, 1401709Smlf dadk_free, 1411709Smlf dadk_probe, 1421709Smlf dadk_attach, 1431709Smlf dadk_open, 1441709Smlf dadk_close, 1451709Smlf dadk_ioctl, 1461709Smlf dadk_strategy, 1471709Smlf dadk_setgeom, 1481709Smlf dadk_getgeom, 1491709Smlf dadk_iob_alloc, 1501709Smlf dadk_iob_free, 1511709Smlf dadk_iob_htoc, 1521709Smlf dadk_iob_xfer, 1531709Smlf dadk_dump, 1541709Smlf dadk_getphygeom, 1551709Smlf dadk_set_bbhobj, 1561709Smlf dadk_check_media, 1571709Smlf dadk_inquiry, 1581709Smlf dadk_cleanup, 1591709Smlf 0 1601709Smlf }; 1611709Smlf 1621709Smlf /* 1631709Smlf * Local static data 1641709Smlf */ 1651709Smlf 1661709Smlf #ifdef DADK_DEBUG 1671709Smlf #define DENT 0x0001 1681709Smlf #define DERR 0x0002 1691709Smlf #define DIO 0x0004 1701709Smlf #define DGEOM 0x0010 1711709Smlf #define DSTATE 0x0020 1721709Smlf static int dadk_debug = DGEOM; 1731709Smlf 1741709Smlf #endif /* DADK_DEBUG */ 1751709Smlf 1761709Smlf static int dadk_check_media_time = 3000000; /* 3 Second State Check */ 1771709Smlf static int dadk_dk_maxphys = 0x80000; 1781709Smlf 1791709Smlf static char *dadk_cmds[] = { 1801709Smlf "\000Unknown", /* unknown */ 1811709Smlf "\001read sector", /* DCMD_READ 1 */ 1821709Smlf "\002write sector", /* DCMD_WRITE 2 */ 1831709Smlf "\003format track", /* DCMD_FMTTRK 3 */ 1841709Smlf "\004format whole drive", /* DCMD_FMTDRV 4 */ 1851709Smlf "\005recalibrate", /* DCMD_RECAL 5 */ 1861709Smlf "\006seek sector", /* DCMD_SEEK 6 */ 1871709Smlf "\007read verify", /* DCMD_RDVER 7 */ 1881709Smlf "\010read defect list", /* DCMD_GETDEF 8 */ 1891709Smlf "\011lock door", /* DCMD_LOCK 9 */ 1901709Smlf "\012unlock door", /* DCMD_UNLOCK 10 */ 1911709Smlf "\013start motor", /* DCMD_START_MOTOR 11 */ 1921709Smlf "\014stop motor", /* DCMD_STOP_MOTOR 12 */ 1931709Smlf "\015eject", /* DCMD_EJECT 13 */ 1941709Smlf "\016update geometry", /* DCMD_UPDATE_GEOM 14 */ 1951709Smlf "\017get state", /* DCMD_GET_STATE 15 */ 1961709Smlf "\020cdrom pause", /* DCMD_PAUSE 16 */ 1971709Smlf "\021cdrom resume", /* DCMD_RESUME 17 */ 1981709Smlf "\022cdrom play track index", /* DCMD_PLAYTRKIND 18 */ 1991709Smlf "\023cdrom play msf", /* DCMD_PLAYMSF 19 */ 2001709Smlf "\024cdrom sub channel", /* DCMD_SUBCHNL 20 */ 2011709Smlf "\025cdrom read mode 1", /* DCMD_READMODE1 21 */ 2021709Smlf "\026cdrom read toc header", /* DCMD_READTOCHDR 22 */ 2031709Smlf "\027cdrom read toc entry", /* DCMD_READTOCENT 23 */ 2041709Smlf "\030cdrom read offset", /* DCMD_READOFFSET 24 */ 2051709Smlf "\031cdrom read mode 2", /* DCMD_READMODE2 25 */ 2061709Smlf "\032cdrom volume control", /* DCMD_VOLCTRL 26 */ 2071709Smlf "\033flush cache", /* DCMD_FLUSH_CACHE 27 */ 2081709Smlf NULL 2091709Smlf }; 2101709Smlf 2111709Smlf static char *dadk_sense[] = { 2121709Smlf "\000Success", /* DERR_SUCCESS */ 2131709Smlf "\001address mark not found", /* DERR_AMNF */ 2141709Smlf "\002track 0 not found", /* DERR_TKONF */ 2151709Smlf "\003aborted command", /* DERR_ABORT */ 2161709Smlf "\004write fault", /* DERR_DWF */ 2171709Smlf "\005ID not found", /* DERR_IDNF */ 2181709Smlf "\006drive busy", /* DERR_BUSY */ 2191709Smlf "\007uncorrectable data error", /* DERR_UNC */ 2201709Smlf "\010bad block detected", /* DERR_BBK */ 2211709Smlf "\011invalid command", /* DERR_INVCDB */ 2221709Smlf "\012device hard error", /* DERR_HARD */ 2231709Smlf "\013illegal length indicated", /* DERR_ILI */ 2241709Smlf "\014end of media", /* DERR_EOM */ 2251709Smlf "\015media change requested", /* DERR_MCR */ 2261709Smlf "\016recovered from error", /* DERR_RECOVER */ 2271709Smlf "\017device not ready", /* DERR_NOTREADY */ 2281709Smlf "\020medium error", /* DERR_MEDIUM */ 2291709Smlf "\021hardware error", /* DERR_HW */ 2301709Smlf "\022illegal request", /* DERR_ILL */ 2311709Smlf "\023unit attention", /* DERR_UNIT_ATTN */ 2321709Smlf "\024data protection", /* DERR_DATA_PROT */ 2331709Smlf "\025miscompare", /* DERR_MISCOMPARE */ 2341709Smlf "\026ICRC error during UDMA", /* DERR_ICRC */ 2351709Smlf "\027reserved", /* DERR_RESV */ 2361709Smlf NULL 2371709Smlf }; 2381709Smlf 2391709Smlf static char *dadk_name = "Disk"; 2401709Smlf 2411709Smlf /* 2421709Smlf * This is the loadable module wrapper 2431709Smlf */ 2441709Smlf #include <sys/modctl.h> 2451709Smlf 2461709Smlf extern struct mod_ops mod_miscops; 2471709Smlf 2481709Smlf static struct modlmisc modlmisc = { 2491709Smlf &mod_miscops, /* Type of module */ 250*7239Szk194757 "Direct Attached Disk" 2511709Smlf }; 2521709Smlf 2531709Smlf static struct modlinkage modlinkage = { 2541709Smlf MODREV_1, (void *)&modlmisc, NULL 2551709Smlf }; 2561709Smlf 2571709Smlf int 2581709Smlf _init(void) 2591709Smlf { 2601709Smlf #ifdef DADK_DEBUG 2611709Smlf if (dadk_debug & DENT) 2621709Smlf PRF("dadk_init: call\n"); 2631709Smlf #endif 2641709Smlf 2651709Smlf #if defined(__x86) 2661709Smlf /* set the max physical address for iob allocs on x86 */ 2671709Smlf dadk_alloc_attr.dma_attr_addr_hi = dadk_max_phys_addr; 2681709Smlf 2691709Smlf /* 2701709Smlf * set the sgllen for iob allocs on x86. If this is set less than 2711709Smlf * the number of pages the buffer will take (taking into account 2721709Smlf * alignment), it would force the allocator to try and allocate 2731709Smlf * contiguous pages. 2741709Smlf */ 2751709Smlf dadk_alloc_attr.dma_attr_sgllen = dadk_sgl_size; 2761709Smlf #endif 2771709Smlf 2781709Smlf return (mod_install(&modlinkage)); 2791709Smlf } 2801709Smlf 2811709Smlf int 2821709Smlf _fini(void) 2831709Smlf { 2841709Smlf #ifdef DADK_DEBUG 2851709Smlf if (dadk_debug & DENT) 2861709Smlf PRF("dadk_fini: call\n"); 2871709Smlf #endif 2881709Smlf 2891709Smlf return (mod_remove(&modlinkage)); 2901709Smlf } 2911709Smlf 2921709Smlf int 2931709Smlf _info(struct modinfo *modinfop) 2941709Smlf { 2951709Smlf return (mod_info(&modlinkage, modinfop)); 2961709Smlf } 2971709Smlf 2981709Smlf struct tgdk_obj * 2991709Smlf dadk_create() 3001709Smlf { 3011709Smlf struct tgdk_obj *dkobjp; 3021709Smlf struct dadk *dadkp; 3031709Smlf 3041709Smlf dkobjp = kmem_zalloc((sizeof (*dkobjp) + sizeof (*dadkp)), KM_NOSLEEP); 3051709Smlf if (!dkobjp) 3061709Smlf return (NULL); 3071709Smlf dadkp = (struct dadk *)(dkobjp+1); 3081709Smlf 3091709Smlf dkobjp->tg_ops = (struct tgdk_objops *)&dadk_ops; 3101709Smlf dkobjp->tg_data = (opaque_t)dadkp; 3111709Smlf dkobjp->tg_ext = &(dkobjp->tg_extblk); 3121709Smlf dadkp->dad_extp = &(dkobjp->tg_extblk); 3131709Smlf 3141709Smlf #ifdef DADK_DEBUG 3151709Smlf if (dadk_debug & DENT) 3161709Smlf PRF("dadk_create: tgdkobjp= 0x%x dadkp= 0x%x\n", dkobjp, dadkp); 3171709Smlf #endif 3181709Smlf return (dkobjp); 3191709Smlf } 3201709Smlf 3211709Smlf int 3221709Smlf dadk_init(opaque_t objp, opaque_t devp, opaque_t flcobjp, opaque_t queobjp, 3231709Smlf opaque_t bbhobjp, void *lkarg) 3241709Smlf { 3251709Smlf struct dadk *dadkp = (struct dadk *)objp; 3261709Smlf struct scsi_device *sdevp = (struct scsi_device *)devp; 3271709Smlf 3281709Smlf dadkp->dad_sd = devp; 3291709Smlf dadkp->dad_ctlobjp = (opaque_t)sdevp->sd_address.a_hba_tran; 3301709Smlf sdevp->sd_private = (caddr_t)dadkp; 3311709Smlf 3321709Smlf /* initialize the communication object */ 3331709Smlf dadkp->dad_com.com_data = (opaque_t)dadkp; 3341709Smlf dadkp->dad_com.com_ops = &dadk_com_ops; 3351709Smlf 3361709Smlf dadkp->dad_bbhobjp = bbhobjp; 3371709Smlf BBH_INIT(bbhobjp); 3381709Smlf 3391709Smlf dadkp->dad_flcobjp = flcobjp; 3405295Srandyf mutex_init(&dadkp->dad_cmd_mutex, NULL, MUTEX_DRIVER, NULL); 3415295Srandyf dadkp->dad_cmd_count = 0; 3421709Smlf return (FLC_INIT(flcobjp, &(dadkp->dad_com), queobjp, lkarg)); 3431709Smlf } 3441709Smlf 3451709Smlf int 3461709Smlf dadk_free(struct tgdk_obj *dkobjp) 3471709Smlf { 3481709Smlf TGDK_CLEANUP(dkobjp); 3491709Smlf kmem_free(dkobjp, (sizeof (*dkobjp) + sizeof (struct dadk))); 3501709Smlf 3511709Smlf return (DDI_SUCCESS); 3521709Smlf } 3531709Smlf 3541709Smlf void 3551709Smlf dadk_cleanup(struct tgdk_obj *dkobjp) 3561709Smlf { 3571709Smlf struct dadk *dadkp; 3581709Smlf 3591709Smlf dadkp = (struct dadk *)(dkobjp->tg_data); 3601709Smlf if (dadkp->dad_sd) 3611709Smlf dadkp->dad_sd->sd_private = NULL; 3621709Smlf if (dadkp->dad_bbhobjp) { 3631709Smlf BBH_FREE(dadkp->dad_bbhobjp); 3641709Smlf dadkp->dad_bbhobjp = NULL; 3651709Smlf } 3661709Smlf if (dadkp->dad_flcobjp) { 3671709Smlf FLC_FREE(dadkp->dad_flcobjp); 3681709Smlf dadkp->dad_flcobjp = NULL; 3691709Smlf } 3705295Srandyf mutex_destroy(&dadkp->dad_cmd_mutex); 3711709Smlf } 3721709Smlf 3731709Smlf /* ARGSUSED */ 3741709Smlf int 3751709Smlf dadk_probe(opaque_t objp, int kmsflg) 3761709Smlf { 3771709Smlf struct dadk *dadkp = (struct dadk *)objp; 3781709Smlf struct scsi_device *devp; 3791709Smlf char name[80]; 3801709Smlf 3811709Smlf devp = dadkp->dad_sd; 3821709Smlf if (!devp->sd_inq || (devp->sd_inq->inq_dtype == DTYPE_NOTPRESENT) || 3835295Srandyf (devp->sd_inq->inq_dtype == DTYPE_UNKNOWN)) { 3841709Smlf return (DDI_PROBE_FAILURE); 3851709Smlf } 3861709Smlf 3871709Smlf switch (devp->sd_inq->inq_dtype) { 3881709Smlf case DTYPE_DIRECT: 3891709Smlf dadkp->dad_ctype = DKC_DIRECT; 3901709Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_BLOCK; 3911709Smlf dadkp->dad_extp->tg_ctype = DKC_DIRECT; 3921709Smlf break; 3931709Smlf case DTYPE_RODIRECT: /* eg cdrom */ 3941709Smlf dadkp->dad_ctype = DKC_CDROM; 3951709Smlf dadkp->dad_extp->tg_rdonly = 1; 3961709Smlf dadkp->dad_rdonly = 1; 3971709Smlf dadkp->dad_cdrom = 1; 3981709Smlf dadkp->dad_extp->tg_nodetype = DDI_NT_CD; 3991709Smlf dadkp->dad_extp->tg_ctype = DKC_CDROM; 4001709Smlf break; 4011709Smlf case DTYPE_WORM: 4021709Smlf case DTYPE_OPTICAL: 4031709Smlf default: 4041709Smlf return (DDI_PROBE_FAILURE); 4051709Smlf } 4061709Smlf 4071709Smlf dadkp->dad_extp->tg_rmb = dadkp->dad_rmb = devp->sd_inq->inq_rmb; 4081709Smlf 4091709Smlf dadkp->dad_secshf = SCTRSHFT; 4101709Smlf dadkp->dad_blkshf = 0; 4111709Smlf 4121709Smlf /* display the device name */ 4131709Smlf (void) strcpy(name, "Vendor '"); 4141709Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_vid, 8, &name[strlen(name)]); 4151709Smlf (void) strcat(name, "' Product '"); 4161709Smlf gda_inqfill((caddr_t)devp->sd_inq->inq_pid, 16, &name[strlen(name)]); 4171709Smlf (void) strcat(name, "'"); 4181709Smlf gda_log(devp->sd_dev, dadk_name, CE_NOTE, "!<%s>\n", name); 4191709Smlf 4201709Smlf return (DDI_PROBE_SUCCESS); 4211709Smlf } 4221709Smlf 4231709Smlf 4241709Smlf /* ARGSUSED */ 4251709Smlf int 4261709Smlf dadk_attach(opaque_t objp) 4271709Smlf { 4281709Smlf return (DDI_SUCCESS); 4291709Smlf } 4301709Smlf 4311709Smlf int 4321709Smlf dadk_set_bbhobj(opaque_t objp, opaque_t bbhobjp) 4331709Smlf { 4341709Smlf struct dadk *dadkp = (struct dadk *)objp; 4351709Smlf /* free the old bbh object */ 4361709Smlf if (dadkp->dad_bbhobjp) 4371709Smlf BBH_FREE(dadkp->dad_bbhobjp); 4381709Smlf 4391709Smlf /* initialize the new bbh object */ 4401709Smlf dadkp->dad_bbhobjp = bbhobjp; 4411709Smlf BBH_INIT(bbhobjp); 4421709Smlf 4431709Smlf return (DDI_SUCCESS); 4441709Smlf } 4451709Smlf 4461709Smlf /* ARGSUSED */ 4471709Smlf int 4481709Smlf dadk_open(opaque_t objp, int flag) 4491709Smlf { 4501709Smlf struct dadk *dadkp = (struct dadk *)objp; 4511709Smlf int error; 4521709Smlf int wce; 4531709Smlf 4541709Smlf if (!dadkp->dad_rmb) { 4551709Smlf if (dadkp->dad_phyg.g_cap) { 4561709Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 4571709Smlf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 4581709Smlf return (DDI_SUCCESS); 4591709Smlf } 4601709Smlf } else { 4615295Srandyf mutex_enter(&dadkp->dad_mutex); 4625295Srandyf dadkp->dad_iostate = DKIO_NONE; 4635295Srandyf cv_broadcast(&dadkp->dad_state_cv); 4645295Srandyf mutex_exit(&dadkp->dad_mutex); 4651709Smlf 4665295Srandyf if (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 0, 4675295Srandyf DADK_SILENT) || 4685295Srandyf dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT) || 4695295Srandyf dadk_rmb_ioctl(dadkp, DCMD_UPDATE_GEOM, 0, 0, 4705295Srandyf DADK_SILENT)) { 4715295Srandyf return (DDI_FAILURE); 4725295Srandyf } 4731709Smlf 4745295Srandyf mutex_enter(&dadkp->dad_mutex); 4755295Srandyf dadkp->dad_iostate = DKIO_INSERTED; 4765295Srandyf cv_broadcast(&dadkp->dad_state_cv); 4775295Srandyf mutex_exit(&dadkp->dad_mutex); 4781709Smlf } 4791709Smlf 4801709Smlf /* 4811709Smlf * get write cache enable state 4821709Smlf * If there is an error, must assume that write cache 4831709Smlf * is enabled. 4841709Smlf * NOTE: Since there is currently no Solaris mechanism to 4851709Smlf * change the state of the Write Cache Enable feature, 4861709Smlf * this code just checks the value of the WCE bit 4871709Smlf * obtained at device init time. If a mechanism 4881709Smlf * is added to the driver to change WCE, dad_wce 4891709Smlf * must be updated appropriately. 4901709Smlf */ 4915295Srandyf error = dadk_ctl_ioctl(dadkp, DIOCTL_GETWCE, 4922799Smarx (uintptr_t)&wce, FKIOCTL | FNATIVE); 4931709Smlf mutex_enter(&dadkp->dad_mutex); 4941709Smlf dadkp->dad_wce = (error != 0) || (wce != 0); 4951709Smlf mutex_exit(&dadkp->dad_mutex); 4961709Smlf 4971709Smlf /* logical disk geometry */ 4985295Srandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETGEOM, 4992799Smarx (uintptr_t)&dadkp->dad_logg, FKIOCTL | FNATIVE); 5001709Smlf if (dadkp->dad_logg.g_cap == 0) 5011709Smlf return (DDI_FAILURE); 5021709Smlf 5031709Smlf /* get physical disk geometry */ 5045295Srandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETPHYGEOM, 5052799Smarx (uintptr_t)&dadkp->dad_phyg, FKIOCTL | FNATIVE); 5061709Smlf if (dadkp->dad_phyg.g_cap == 0) 5071709Smlf return (DDI_FAILURE); 5081709Smlf 5091709Smlf dadk_setcap(dadkp); 5101709Smlf 5112799Smarx dadk_create_errstats(dadkp, 5122799Smarx ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 5132799Smarx 5141709Smlf /* start profiling */ 5151709Smlf FLC_START_KSTAT(dadkp->dad_flcobjp, "disk", 5165295Srandyf ddi_get_instance(CTL_DIP_DEV(dadkp->dad_ctlobjp))); 5171709Smlf 5181709Smlf return (DDI_SUCCESS); 5191709Smlf } 5201709Smlf 5211709Smlf static void 5221709Smlf dadk_setcap(struct dadk *dadkp) 5231709Smlf { 5241709Smlf int totsize; 5251709Smlf int i; 5261709Smlf 5271709Smlf totsize = dadkp->dad_phyg.g_secsiz; 5281709Smlf 5291709Smlf if (totsize == 0) { 5301709Smlf if (dadkp->dad_cdrom) { 5311709Smlf totsize = 2048; 5321709Smlf } else { 5331709Smlf totsize = NBPSCTR; 5341709Smlf } 5351709Smlf } else { 5361709Smlf /* Round down sector size to multiple of 512B */ 5371709Smlf totsize &= ~(NBPSCTR-1); 5381709Smlf } 5391709Smlf dadkp->dad_phyg.g_secsiz = totsize; 5401709Smlf 5411709Smlf /* set sec,block shift factor - (512->0, 1024->1, 2048->2, etc.) */ 5421709Smlf totsize >>= SCTRSHFT; 5435295Srandyf for (i = 0; totsize != 1; i++, totsize >>= 1) 5445295Srandyf ; 5451709Smlf dadkp->dad_blkshf = i; 5461709Smlf dadkp->dad_secshf = i + SCTRSHFT; 5471709Smlf } 5481709Smlf 5491709Smlf 5502799Smarx static void 5512799Smarx dadk_create_errstats(struct dadk *dadkp, int instance) 5522799Smarx { 5532799Smarx dadk_errstats_t *dep; 5542799Smarx char kstatname[KSTAT_STRLEN]; 5552799Smarx dadk_ioc_string_t dadk_ioc_string; 5562799Smarx 5572799Smarx if (dadkp->dad_errstats) 5582799Smarx return; 5592799Smarx 5602799Smarx (void) sprintf(kstatname, "cmdk%d,error", instance); 5612799Smarx dadkp->dad_errstats = kstat_create("cmdkerror", instance, 5622799Smarx kstatname, "device_error", KSTAT_TYPE_NAMED, 5632799Smarx sizeof (dadk_errstats_t) / sizeof (kstat_named_t), 5642799Smarx KSTAT_FLAG_PERSISTENT); 5652799Smarx 5662799Smarx if (!dadkp->dad_errstats) 5672799Smarx return; 5682799Smarx 5692799Smarx dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data; 5702799Smarx 5712799Smarx kstat_named_init(&dep->dadk_softerrs, 5722799Smarx "Soft Errors", KSTAT_DATA_UINT32); 5732799Smarx kstat_named_init(&dep->dadk_harderrs, 5742799Smarx "Hard Errors", KSTAT_DATA_UINT32); 5752799Smarx kstat_named_init(&dep->dadk_transerrs, 5762799Smarx "Transport Errors", KSTAT_DATA_UINT32); 5772799Smarx kstat_named_init(&dep->dadk_model, 5782799Smarx "Model", KSTAT_DATA_CHAR); 5792799Smarx kstat_named_init(&dep->dadk_revision, 5802799Smarx "Revision", KSTAT_DATA_CHAR); 5812799Smarx kstat_named_init(&dep->dadk_serial, 5822799Smarx "Serial No", KSTAT_DATA_CHAR); 5832799Smarx kstat_named_init(&dep->dadk_capacity, 5842799Smarx "Size", KSTAT_DATA_ULONGLONG); 5852799Smarx kstat_named_init(&dep->dadk_rq_media_err, 5862799Smarx "Media Error", KSTAT_DATA_UINT32); 5872799Smarx kstat_named_init(&dep->dadk_rq_ntrdy_err, 5882799Smarx "Device Not Ready", KSTAT_DATA_UINT32); 5892799Smarx kstat_named_init(&dep->dadk_rq_nodev_err, 5902799Smarx "No Device", KSTAT_DATA_UINT32); 5912799Smarx kstat_named_init(&dep->dadk_rq_recov_err, 5922799Smarx "Recoverable", KSTAT_DATA_UINT32); 5932799Smarx kstat_named_init(&dep->dadk_rq_illrq_err, 5942799Smarx "Illegal Request", KSTAT_DATA_UINT32); 5952799Smarx 5962799Smarx dadkp->dad_errstats->ks_private = dep; 5972799Smarx dadkp->dad_errstats->ks_update = nulldev; 5982799Smarx kstat_install(dadkp->dad_errstats); 5992799Smarx 6002799Smarx /* get model */ 6012799Smarx dep->dadk_model.value.c[0] = 0; 6022799Smarx dadk_ioc_string.is_buf = &dep->dadk_model.value.c[0]; 6033399Smarx dadk_ioc_string.is_size = sizeof (dep->dadk_model.value.c); 6045295Srandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETMODEL, 6052799Smarx (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); 6062799Smarx 6072799Smarx /* get serial */ 6082799Smarx dep->dadk_serial.value.c[0] = 0; 6092799Smarx dadk_ioc_string.is_buf = &dep->dadk_serial.value.c[0]; 6103399Smarx dadk_ioc_string.is_size = sizeof (dep->dadk_serial.value.c); 6115295Srandyf (void) dadk_ctl_ioctl(dadkp, DIOCTL_GETSERIAL, 6122799Smarx (uintptr_t)&dadk_ioc_string, FKIOCTL | FNATIVE); 6132799Smarx 6142799Smarx /* Get revision */ 6152799Smarx dep->dadk_revision.value.c[0] = 0; 6162799Smarx 6172799Smarx /* Get capacity */ 6182799Smarx 6192799Smarx dep->dadk_capacity.value.ui64 = 6202799Smarx (uint64_t)dadkp->dad_logg.g_cap * 6212799Smarx (uint64_t)dadkp->dad_logg.g_secsiz; 6222799Smarx } 6232799Smarx 6242799Smarx 6251709Smlf int 6261709Smlf dadk_close(opaque_t objp) 6271709Smlf { 6281709Smlf struct dadk *dadkp = (struct dadk *)objp; 6291709Smlf 6301709Smlf if (dadkp->dad_rmb) { 6311709Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 0, 6321709Smlf DADK_SILENT); 6331709Smlf (void) dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT); 6341709Smlf } 6351709Smlf FLC_STOP_KSTAT(dadkp->dad_flcobjp); 6362799Smarx 6372799Smarx dadk_destroy_errstats(dadkp); 6382799Smarx 6391709Smlf return (DDI_SUCCESS); 6401709Smlf } 6411709Smlf 6422799Smarx static void 6432799Smarx dadk_destroy_errstats(struct dadk *dadkp) 6442799Smarx { 6452799Smarx if (!dadkp->dad_errstats) 6462799Smarx return; 6472799Smarx 6482799Smarx kstat_delete(dadkp->dad_errstats); 6492799Smarx dadkp->dad_errstats = NULL; 6502799Smarx } 6512799Smarx 6522799Smarx 6531709Smlf int 6541709Smlf dadk_strategy(opaque_t objp, struct buf *bp) 6551709Smlf { 6561709Smlf struct dadk *dadkp = (struct dadk *)objp; 6571709Smlf 6581709Smlf if (dadkp->dad_rdonly && !(bp->b_flags & B_READ)) { 6591709Smlf bioerror(bp, EROFS); 6601709Smlf return (DDI_FAILURE); 6611709Smlf } 6621709Smlf 6631709Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 6641709Smlf bioerror(bp, ENXIO); 6651709Smlf return (DDI_FAILURE); 6661709Smlf } 6671709Smlf 6681709Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 6695295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 6705295Srandyf dadkp->dad_cmd_count++; 6715295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 6721709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 6731709Smlf 6741709Smlf return (DDI_SUCCESS); 6751709Smlf } 6761709Smlf 6771709Smlf int 6781709Smlf dadk_dump(opaque_t objp, struct buf *bp) 6791709Smlf { 6801709Smlf struct dadk *dadkp = (struct dadk *)objp; 6811709Smlf struct cmpkt *pktp; 6821709Smlf 6831709Smlf if (dadkp->dad_rdonly) { 6841709Smlf bioerror(bp, EROFS); 6851709Smlf return (DDI_FAILURE); 6861709Smlf } 6871709Smlf 6881709Smlf if (bp->b_bcount & (dadkp->DAD_SECSIZ-1)) { 6891709Smlf bioerror(bp, ENXIO); 6901709Smlf return (DDI_FAILURE); 6911709Smlf } 6921709Smlf 6931709Smlf SET_BP_SEC(bp, (LBLK2SEC(GET_BP_SEC(bp), dadkp->dad_blkshf))); 6941709Smlf 6951709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_polldone, NULL, NULL); 6961709Smlf if (!pktp) { 6971709Smlf cmn_err(CE_WARN, "no resources for dumping"); 6981709Smlf bioerror(bp, EIO); 6991709Smlf return (DDI_FAILURE); 7001709Smlf } 7011709Smlf pktp->cp_flags |= CPF_NOINTR; 7021709Smlf 7031709Smlf (void) dadk_ioprep(dadkp, pktp); 7041709Smlf dadk_transport(dadkp, bp); 7051709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 7061709Smlf 7071709Smlf while (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 7081709Smlf (void) dadk_iosetup(dadkp, pktp); 7091709Smlf dadk_transport(dadkp, bp); 7101709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 7111709Smlf } 7121709Smlf 7131709Smlf if (pktp->cp_private) 7141709Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 7151709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 7161709Smlf return (DDI_SUCCESS); 7171709Smlf } 7181709Smlf 7191709Smlf /* ARGSUSED */ 7201709Smlf int 7211709Smlf dadk_ioctl(opaque_t objp, dev_t dev, int cmd, intptr_t arg, int flag, 7221709Smlf cred_t *cred_p, int *rval_p) 7231709Smlf { 7241709Smlf struct dadk *dadkp = (struct dadk *)objp; 7251709Smlf 7261709Smlf switch (cmd) { 7271709Smlf case DKIOCGETDEF: 7285295Srandyf { 7291709Smlf struct buf *bp; 7301709Smlf int err, head; 7311709Smlf unsigned char *secbuf; 7321709Smlf STRUCT_DECL(defect_header, adh); 7331709Smlf 7341709Smlf STRUCT_INIT(adh, flag & FMODELS); 7351709Smlf 7361709Smlf /* 7371709Smlf * copyin header .... 7381709Smlf * yields head number and buffer address 7391709Smlf */ 7401709Smlf if (ddi_copyin((caddr_t)arg, STRUCT_BUF(adh), STRUCT_SIZE(adh), 7411709Smlf flag)) 7421709Smlf return (EFAULT); 7431709Smlf head = STRUCT_FGET(adh, head); 7441709Smlf if (head < 0 || head >= dadkp->dad_phyg.g_head) 7451709Smlf return (ENXIO); 7461709Smlf secbuf = kmem_zalloc(NBPSCTR, KM_SLEEP); 7471709Smlf if (!secbuf) 7481709Smlf return (ENOMEM); 7491709Smlf bp = getrbuf(KM_SLEEP); 7501709Smlf if (!bp) { 7511709Smlf kmem_free(secbuf, NBPSCTR); 7521709Smlf return (ENOMEM); 7531709Smlf } 7541709Smlf 7551709Smlf bp->b_edev = dev; 7561709Smlf bp->b_dev = cmpdev(dev); 7571709Smlf bp->b_flags = B_BUSY; 7581709Smlf bp->b_resid = 0; 7591709Smlf bp->b_bcount = NBPSCTR; 7601709Smlf bp->b_un.b_addr = (caddr_t)secbuf; 7611709Smlf bp->b_blkno = head; /* I had to put it somwhere! */ 7621709Smlf bp->b_forw = (struct buf *)dadkp; 7631709Smlf bp->b_back = (struct buf *)DCMD_GETDEF; 7641709Smlf 7655295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 7665295Srandyf dadkp->dad_cmd_count++; 7675295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 7681709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 7691709Smlf err = biowait(bp); 7701709Smlf if (!err) { 7711709Smlf if (ddi_copyout((caddr_t)secbuf, 7721709Smlf STRUCT_FGETP(adh, buffer), NBPSCTR, flag)) 7731709Smlf err = ENXIO; 7741709Smlf } 7751709Smlf kmem_free(secbuf, NBPSCTR); 7761709Smlf freerbuf(bp); 7771709Smlf return (err); 7785295Srandyf } 7791709Smlf case DIOCTL_RWCMD: 7805295Srandyf { 7811709Smlf struct dadkio_rwcmd *rwcmdp; 7821709Smlf int status, rw; 7831709Smlf 7841709Smlf /* 7851709Smlf * copied in by cmdk and, if necessary, converted to the 7861709Smlf * correct datamodel 7871709Smlf */ 7881709Smlf rwcmdp = (struct dadkio_rwcmd *)(intptr_t)arg; 7891709Smlf 7901709Smlf /* 7911709Smlf * handle the complex cases here; we pass these 7921709Smlf * through to the driver, which will queue them and 7931709Smlf * handle the requests asynchronously. The simpler 7941709Smlf * cases ,which can return immediately, fail here, and 7951709Smlf * the request reverts to the dadk_ioctl routine, while 7961709Smlf * will reroute them directly to the ata driver. 7971709Smlf */ 7981709Smlf switch (rwcmdp->cmd) { 7991709Smlf case DADKIO_RWCMD_READ : 8001709Smlf /*FALLTHROUGH*/ 8011709Smlf case DADKIO_RWCMD_WRITE: 8021709Smlf rw = ((rwcmdp->cmd == DADKIO_RWCMD_WRITE) ? 8031709Smlf B_WRITE : B_READ); 8041709Smlf status = dadk_dk_buf_setup(dadkp, 8051709Smlf (opaque_t)rwcmdp, dev, ((flag &FKIOCTL) ? 8061709Smlf UIO_SYSSPACE : UIO_USERSPACE), rw); 8071709Smlf return (status); 8081709Smlf default: 8091709Smlf return (EINVAL); 8105295Srandyf } 8111709Smlf } 8123652Syt160523 case DKIOC_UPDATEFW: 8133652Syt160523 8143652Syt160523 /* 8153652Syt160523 * Require PRIV_ALL privilege to invoke DKIOC_UPDATEFW 8163652Syt160523 * to protect the firmware update from malicious use 8173652Syt160523 */ 8183652Syt160523 if (PRIV_POLICY(cred_p, PRIV_ALL, B_FALSE, EPERM, NULL) != 0) 8193652Syt160523 return (EPERM); 8203652Syt160523 else 8215295Srandyf return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); 8223652Syt160523 8231709Smlf case DKIOCFLUSHWRITECACHE: 8241709Smlf { 8251709Smlf struct buf *bp; 8261709Smlf int err = 0; 8271709Smlf struct dk_callback *dkc = (struct dk_callback *)arg; 8281709Smlf struct cmpkt *pktp; 8291709Smlf int is_sync = 1; 8301709Smlf 8311709Smlf mutex_enter(&dadkp->dad_mutex); 8321709Smlf if (dadkp->dad_noflush || ! dadkp->dad_wce) { 8331709Smlf err = dadkp->dad_noflush ? ENOTSUP : 0; 8341709Smlf mutex_exit(&dadkp->dad_mutex); 8351709Smlf /* 8361709Smlf * If a callback was requested: a 8371709Smlf * callback will always be done if the 8381709Smlf * caller saw the DKIOCFLUSHWRITECACHE 8391709Smlf * ioctl return 0, and never done if the 8401709Smlf * caller saw the ioctl return an error. 8411709Smlf */ 8421709Smlf if ((flag & FKIOCTL) && dkc != NULL && 8431709Smlf dkc->dkc_callback != NULL) { 8441709Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, 8451709Smlf err); 8461709Smlf /* 8471709Smlf * Did callback and reported error. 8481709Smlf * Since we did a callback, ioctl 8491709Smlf * should return 0. 8501709Smlf */ 8511709Smlf err = 0; 8521709Smlf } 8531709Smlf return (err); 8541709Smlf } 8551709Smlf mutex_exit(&dadkp->dad_mutex); 8561709Smlf 8571709Smlf bp = getrbuf(KM_SLEEP); 8581709Smlf 8591709Smlf bp->b_edev = dev; 8601709Smlf bp->b_dev = cmpdev(dev); 8611709Smlf bp->b_flags = B_BUSY; 8621709Smlf bp->b_resid = 0; 8631709Smlf bp->b_bcount = 0; 8641709Smlf SET_BP_SEC(bp, 0); 8651709Smlf 8661709Smlf if ((flag & FKIOCTL) && dkc != NULL && 8671709Smlf dkc->dkc_callback != NULL) { 8681709Smlf struct dk_callback *dkc2 = 8691709Smlf (struct dk_callback *)kmem_zalloc( 8701709Smlf sizeof (struct dk_callback), KM_SLEEP); 8711709Smlf 8721709Smlf bcopy(dkc, dkc2, sizeof (*dkc2)); 8731709Smlf /* 8741709Smlf * Borrow b_list to carry private data 8751709Smlf * to the b_iodone func. 8761709Smlf */ 8771709Smlf bp->b_list = (struct buf *)dkc2; 8781709Smlf bp->b_iodone = dadk_flushdone; 8791709Smlf is_sync = 0; 8801709Smlf } 8811709Smlf 8821709Smlf /* 8831709Smlf * Setup command pkt 8841709Smlf * dadk_pktprep() can't fail since DDI_DMA_SLEEP set 8851709Smlf */ 8861709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, 8871709Smlf dadk_iodone, DDI_DMA_SLEEP, NULL); 8881709Smlf 8891709Smlf pktp->cp_time = DADK_FLUSH_CACHE_TIME; 8901709Smlf 8911709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_FLUSH_CACHE; 8921709Smlf pktp->cp_byteleft = 0; 8931709Smlf pktp->cp_private = NULL; 8941709Smlf pktp->cp_secleft = 0; 8951709Smlf pktp->cp_srtsec = -1; 8961709Smlf pktp->cp_bytexfer = 0; 8971709Smlf 8981709Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 8991709Smlf 9005295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 9015295Srandyf dadkp->dad_cmd_count++; 9025295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 9031709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 9041709Smlf 9051709Smlf if (is_sync) { 9061709Smlf err = biowait(bp); 9071709Smlf freerbuf(bp); 9081709Smlf } 9091709Smlf return (err); 9101709Smlf } 9111709Smlf default: 9121709Smlf if (!dadkp->dad_rmb) 9135295Srandyf return (dadk_ctl_ioctl(dadkp, cmd, arg, flag)); 9141709Smlf } 9151709Smlf 9161709Smlf switch (cmd) { 9171709Smlf case CDROMSTOP: 9181709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_STOP_MOTOR, 0, 9195295Srandyf 0, DADK_SILENT)); 9201709Smlf case CDROMSTART: 9211709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_START_MOTOR, 0, 9225295Srandyf 0, DADK_SILENT)); 9231709Smlf case DKIOCLOCK: 9241709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_LOCK, 0, 0, DADK_SILENT)); 9251709Smlf case DKIOCUNLOCK: 9261709Smlf return (dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, DADK_SILENT)); 9271709Smlf case DKIOCEJECT: 9281709Smlf case CDROMEJECT: 9291709Smlf { 9301709Smlf int ret; 9311709Smlf 9321709Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_UNLOCK, 0, 0, 9335295Srandyf DADK_SILENT)) { 9341709Smlf return (ret); 9351709Smlf } 9361709Smlf if (ret = dadk_rmb_ioctl(dadkp, DCMD_EJECT, 0, 0, 9375295Srandyf DADK_SILENT)) { 9381709Smlf return (ret); 9391709Smlf } 9401709Smlf mutex_enter(&dadkp->dad_mutex); 9411709Smlf dadkp->dad_iostate = DKIO_EJECTED; 9421709Smlf cv_broadcast(&dadkp->dad_state_cv); 9431709Smlf mutex_exit(&dadkp->dad_mutex); 9441709Smlf 9451709Smlf return (0); 9461709Smlf 9471709Smlf } 9481709Smlf default: 9491709Smlf return (ENOTTY); 9501709Smlf /* 9511709Smlf * cdrom audio commands 9521709Smlf */ 9531709Smlf case CDROMPAUSE: 9541709Smlf cmd = DCMD_PAUSE; 9551709Smlf break; 9561709Smlf case CDROMRESUME: 9571709Smlf cmd = DCMD_RESUME; 9581709Smlf break; 9591709Smlf case CDROMPLAYMSF: 9601709Smlf cmd = DCMD_PLAYMSF; 9611709Smlf break; 9621709Smlf case CDROMPLAYTRKIND: 9631709Smlf cmd = DCMD_PLAYTRKIND; 9641709Smlf break; 9651709Smlf case CDROMREADTOCHDR: 9661709Smlf cmd = DCMD_READTOCHDR; 9671709Smlf break; 9681709Smlf case CDROMREADTOCENTRY: 9691709Smlf cmd = DCMD_READTOCENT; 9701709Smlf break; 9711709Smlf case CDROMVOLCTRL: 9721709Smlf cmd = DCMD_VOLCTRL; 9731709Smlf break; 9741709Smlf case CDROMSUBCHNL: 9751709Smlf cmd = DCMD_SUBCHNL; 9761709Smlf break; 9771709Smlf case CDROMREADMODE2: 9781709Smlf cmd = DCMD_READMODE2; 9791709Smlf break; 9801709Smlf case CDROMREADMODE1: 9811709Smlf cmd = DCMD_READMODE1; 9821709Smlf break; 9831709Smlf case CDROMREADOFFSET: 9841709Smlf cmd = DCMD_READOFFSET; 9851709Smlf break; 9861709Smlf } 9871709Smlf return (dadk_rmb_ioctl(dadkp, cmd, arg, flag, 0)); 9881709Smlf } 9891709Smlf 9901709Smlf int 9911709Smlf dadk_flushdone(struct buf *bp) 9921709Smlf { 9931709Smlf struct dk_callback *dkc = (struct dk_callback *)bp->b_list; 9941709Smlf 9951709Smlf ASSERT(dkc != NULL && dkc->dkc_callback != NULL); 9961709Smlf 9971709Smlf (*dkc->dkc_callback)(dkc->dkc_cookie, geterror(bp)); 9981709Smlf 9991709Smlf kmem_free(dkc, sizeof (*dkc)); 10001709Smlf freerbuf(bp); 10011709Smlf return (0); 10021709Smlf } 10031709Smlf 10041709Smlf int 10051709Smlf dadk_getphygeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 10061709Smlf { 10071709Smlf struct dadk *dadkp = (struct dadk *)objp; 10081709Smlf 10091709Smlf bcopy((caddr_t)&dadkp->dad_phyg, (caddr_t)dkgeom_p, 10101709Smlf sizeof (struct tgdk_geom)); 10111709Smlf return (DDI_SUCCESS); 10121709Smlf } 10131709Smlf 10141709Smlf int 10151709Smlf dadk_getgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 10161709Smlf { 10171709Smlf struct dadk *dadkp = (struct dadk *)objp; 10181709Smlf bcopy((caddr_t)&dadkp->dad_logg, (caddr_t)dkgeom_p, 10191709Smlf sizeof (struct tgdk_geom)); 10201709Smlf return (DDI_SUCCESS); 10211709Smlf } 10221709Smlf 10231709Smlf int 10241709Smlf dadk_setgeom(opaque_t objp, struct tgdk_geom *dkgeom_p) 10251709Smlf { 10261709Smlf struct dadk *dadkp = (struct dadk *)objp; 10271709Smlf 10281709Smlf dadkp->dad_logg.g_cyl = dkgeom_p->g_cyl; 10291709Smlf dadkp->dad_logg.g_head = dkgeom_p->g_head; 10301709Smlf dadkp->dad_logg.g_sec = dkgeom_p->g_sec; 10311709Smlf dadkp->dad_logg.g_cap = dkgeom_p->g_cap; 10321709Smlf return (DDI_SUCCESS); 10331709Smlf } 10341709Smlf 10351709Smlf 10361709Smlf tgdk_iob_handle 10371709Smlf dadk_iob_alloc(opaque_t objp, daddr_t blkno, ssize_t xfer, int kmsflg) 10381709Smlf { 10391709Smlf struct dadk *dadkp = (struct dadk *)objp; 10401709Smlf struct buf *bp; 10411709Smlf struct tgdk_iob *iobp; 10421709Smlf size_t rlen; 10431709Smlf 10441709Smlf iobp = kmem_zalloc(sizeof (*iobp), kmsflg); 10451709Smlf if (iobp == NULL) 10461709Smlf return (NULL); 10471709Smlf if ((bp = getrbuf(kmsflg)) == NULL) { 10481709Smlf kmem_free(iobp, sizeof (*iobp)); 10491709Smlf return (NULL); 10501709Smlf } 10511709Smlf 10521709Smlf iobp->b_psec = LBLK2SEC(blkno, dadkp->dad_blkshf); 10531709Smlf iobp->b_pbyteoff = (blkno & ((1<<dadkp->dad_blkshf) - 1)) << SCTRSHFT; 10541709Smlf iobp->b_pbytecnt = ((iobp->b_pbyteoff + xfer + dadkp->DAD_SECSIZ - 1) 10555295Srandyf >> dadkp->dad_secshf) << dadkp->dad_secshf; 10561709Smlf 10571709Smlf bp->b_un.b_addr = 0; 10581709Smlf /* 10591709Smlf * use i_ddi_mem_alloc() for now until we have an interface to allocate 10601709Smlf * memory for DMA which doesn't require a DMA handle. ddi_iopb_alloc() 10611709Smlf * is obsolete and we want more flexibility in controlling the DMA 10621709Smlf * address constraints.. 10631709Smlf */ 10641709Smlf if (i_ddi_mem_alloc((dadkp->dad_sd)->sd_dev, &dadk_alloc_attr, 10651709Smlf (size_t)iobp->b_pbytecnt, ((kmsflg == KM_SLEEP) ? 1 : 0), 0, NULL, 10661709Smlf &bp->b_un.b_addr, &rlen, NULL) != DDI_SUCCESS) { 10671709Smlf freerbuf(bp); 10681709Smlf kmem_free(iobp, sizeof (*iobp)); 10691709Smlf return (NULL); 10701709Smlf } 10711709Smlf iobp->b_flag |= IOB_BPALLOC | IOB_BPBUFALLOC; 10721709Smlf iobp->b_bp = bp; 10731709Smlf iobp->b_lblk = blkno; 10741709Smlf iobp->b_xfer = xfer; 10751709Smlf iobp->b_lblk = blkno; 10761709Smlf iobp->b_xfer = xfer; 10771709Smlf return (iobp); 10781709Smlf } 10791709Smlf 10801709Smlf /* ARGSUSED */ 10811709Smlf int 10821709Smlf dadk_iob_free(opaque_t objp, struct tgdk_iob *iobp) 10831709Smlf { 10841709Smlf struct buf *bp; 10851709Smlf 10861709Smlf if (iobp) { 10871709Smlf if (iobp->b_bp && (iobp->b_flag & IOB_BPALLOC)) { 10881709Smlf bp = iobp->b_bp; 10891709Smlf if (bp->b_un.b_addr && (iobp->b_flag & IOB_BPBUFALLOC)) 10901900Seota i_ddi_mem_free((caddr_t)bp->b_un.b_addr, NULL); 10911709Smlf freerbuf(bp); 10921709Smlf } 10931709Smlf kmem_free(iobp, sizeof (*iobp)); 10941709Smlf } 10951709Smlf return (DDI_SUCCESS); 10961709Smlf } 10971709Smlf 10981709Smlf /* ARGSUSED */ 10991709Smlf caddr_t 11001709Smlf dadk_iob_htoc(opaque_t objp, struct tgdk_iob *iobp) 11011709Smlf { 11021709Smlf return (iobp->b_bp->b_un.b_addr+iobp->b_pbyteoff); 11031709Smlf } 11041709Smlf 11051709Smlf 11061709Smlf caddr_t 11071709Smlf dadk_iob_xfer(opaque_t objp, struct tgdk_iob *iobp, int rw) 11081709Smlf { 11091709Smlf struct dadk *dadkp = (struct dadk *)objp; 11101709Smlf struct buf *bp; 11111709Smlf int err; 11121709Smlf 11131709Smlf bp = iobp->b_bp; 11141709Smlf if (dadkp->dad_rdonly && !(rw & B_READ)) { 11151709Smlf bioerror(bp, EROFS); 11161709Smlf return (NULL); 11171709Smlf } 11181709Smlf 11191709Smlf bp->b_flags |= (B_BUSY | rw); 11201709Smlf bp->b_bcount = iobp->b_pbytecnt; 11211709Smlf SET_BP_SEC(bp, iobp->b_psec); 11221709Smlf bp->av_back = (struct buf *)0; 11231709Smlf bp->b_resid = 0; 11241709Smlf 11251709Smlf /* call flow control */ 11265295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 11275295Srandyf dadkp->dad_cmd_count++; 11285295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 11291709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 11301709Smlf err = biowait(bp); 11311709Smlf 11321709Smlf bp->b_bcount = iobp->b_xfer; 11331709Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 11341709Smlf 11351709Smlf if (err) 11361709Smlf return (NULL); 11371709Smlf 11381709Smlf return (bp->b_un.b_addr+iobp->b_pbyteoff); 11391709Smlf } 11401709Smlf 11411709Smlf static void 11421709Smlf dadk_transport(opaque_t com_data, struct buf *bp) 11431709Smlf { 11441709Smlf struct dadk *dadkp = (struct dadk *)com_data; 11451709Smlf 11461709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, GDA_BP_PKT(bp)) == 11471709Smlf CTL_SEND_SUCCESS) 11481709Smlf return; 11491709Smlf dadk_restart((void*)GDA_BP_PKT(bp)); 11501709Smlf } 11511709Smlf 11521709Smlf static int 11531709Smlf dadk_pkt(opaque_t com_data, struct buf *bp, int (*func)(caddr_t), caddr_t arg) 11541709Smlf { 11551709Smlf struct cmpkt *pktp; 11561709Smlf struct dadk *dadkp = (struct dadk *)com_data; 11571709Smlf 11581709Smlf if (GDA_BP_PKT(bp)) 11591709Smlf return (DDI_SUCCESS); 11601709Smlf 11611709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, func, arg); 11621709Smlf if (!pktp) 11631709Smlf return (DDI_FAILURE); 11641709Smlf 11651709Smlf return (dadk_ioprep(dadkp, pktp)); 11661709Smlf } 11671709Smlf 11681709Smlf /* 11691709Smlf * Read, Write preparation 11701709Smlf */ 11711709Smlf static int 11721709Smlf dadk_ioprep(struct dadk *dadkp, struct cmpkt *pktp) 11731709Smlf { 11741709Smlf struct buf *bp; 11751709Smlf 11761709Smlf bp = pktp->cp_bp; 11771709Smlf if (bp->b_forw == (struct buf *)dadkp) 11781709Smlf *((char *)(pktp->cp_cdbp)) = (char)(intptr_t)bp->b_back; 11791709Smlf 11801709Smlf else if (bp->b_flags & B_READ) 11811709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_READ; 11821709Smlf else 11831709Smlf *((char *)(pktp->cp_cdbp)) = DCMD_WRITE; 11841709Smlf pktp->cp_byteleft = bp->b_bcount; 11851709Smlf 11861709Smlf /* setup the bad block list handle */ 11871709Smlf pktp->cp_private = BBH_GETHANDLE(dadkp->dad_bbhobjp, bp); 11881709Smlf return (dadk_iosetup(dadkp, pktp)); 11891709Smlf } 11901709Smlf 11911709Smlf static int 11921709Smlf dadk_iosetup(struct dadk *dadkp, struct cmpkt *pktp) 11931709Smlf { 11941709Smlf struct buf *bp; 11951709Smlf bbh_cookie_t bbhckp; 11961709Smlf int seccnt; 11971709Smlf 11981709Smlf seccnt = pktp->cp_bytexfer >> dadkp->dad_secshf; 11991709Smlf pktp->cp_secleft -= seccnt; 12001709Smlf 12011709Smlf if (pktp->cp_secleft) { 12021709Smlf pktp->cp_srtsec += seccnt; 12031709Smlf } else { 12041709Smlf /* get the first cookie from the bad block list */ 12051709Smlf if (!pktp->cp_private) { 12061709Smlf bp = pktp->cp_bp; 12071709Smlf pktp->cp_srtsec = GET_BP_SEC(bp); 12081709Smlf pktp->cp_secleft = (bp->b_bcount >> dadkp->dad_secshf); 12091709Smlf } else { 12101709Smlf bbhckp = BBH_HTOC(dadkp->dad_bbhobjp, 12111709Smlf pktp->cp_private); 12121709Smlf pktp->cp_srtsec = BBH_GETCK_SECTOR(dadkp->dad_bbhobjp, 12131709Smlf bbhckp); 12141709Smlf pktp->cp_secleft = BBH_GETCK_SECLEN(dadkp->dad_bbhobjp, 12151709Smlf bbhckp); 12161709Smlf } 12171709Smlf } 12181709Smlf 12191709Smlf pktp->cp_bytexfer = pktp->cp_secleft << dadkp->dad_secshf; 12201709Smlf 12211709Smlf if (CTL_IOSETUP(dadkp->dad_ctlobjp, pktp)) { 12221709Smlf return (DDI_SUCCESS); 12231709Smlf } else { 12241709Smlf return (DDI_FAILURE); 12251709Smlf } 12261709Smlf 12271709Smlf 12281709Smlf 12291709Smlf 12301709Smlf } 12311709Smlf 12321709Smlf static struct cmpkt * 12331709Smlf dadk_pktprep(struct dadk *dadkp, struct cmpkt *in_pktp, struct buf *bp, 12341709Smlf void (*cb_func)(struct buf *), int (*func)(caddr_t), caddr_t arg) 12351709Smlf { 12361709Smlf struct cmpkt *pktp; 12371709Smlf 12381709Smlf pktp = gda_pktprep(dadkp->dad_ctlobjp, in_pktp, (opaque_t)bp, func, 12391709Smlf arg); 12401709Smlf 12411709Smlf if (pktp) { 12421709Smlf pktp->cp_callback = dadk_pktcb; 12431709Smlf pktp->cp_time = DADK_IO_TIME; 12441709Smlf pktp->cp_flags = 0; 12451709Smlf pktp->cp_iodone = cb_func; 12461709Smlf pktp->cp_dev_private = (opaque_t)dadkp; 12471709Smlf 12481709Smlf } 12491709Smlf 12501709Smlf return (pktp); 12511709Smlf } 12521709Smlf 12531709Smlf 12541709Smlf static void 12551709Smlf dadk_restart(void *vpktp) 12561709Smlf { 12571709Smlf struct cmpkt *pktp = (struct cmpkt *)vpktp; 12581709Smlf 12591709Smlf if (dadk_ioretry(pktp, QUE_COMMAND) == JUST_RETURN) 12601709Smlf return; 12611709Smlf pktp->cp_iodone(pktp->cp_bp); 12621709Smlf } 12631709Smlf 12641709Smlf static int 12651709Smlf dadk_ioretry(struct cmpkt *pktp, int action) 12661709Smlf { 12671709Smlf struct buf *bp; 12681709Smlf struct dadk *dadkp = PKT2DADK(pktp); 12691709Smlf 12701709Smlf switch (action) { 12711709Smlf case QUE_COMMAND: 12721709Smlf if (pktp->cp_retry++ < DADK_RETRY_COUNT) { 12731709Smlf CTL_IOSETUP(dadkp->dad_ctlobjp, pktp); 12741709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == 12755295Srandyf CTL_SEND_SUCCESS) { 12761709Smlf return (JUST_RETURN); 12771709Smlf } 12781709Smlf gda_log(dadkp->dad_sd->sd_dev, dadk_name, 12795295Srandyf CE_WARN, "transport of command fails\n"); 12801709Smlf } else 12811709Smlf gda_log(dadkp->dad_sd->sd_dev, 12825295Srandyf dadk_name, CE_WARN, 12835295Srandyf "exceeds maximum number of retries\n"); 12841709Smlf bioerror(pktp->cp_bp, ENXIO); 12851709Smlf /*FALLTHROUGH*/ 12861709Smlf case COMMAND_DONE_ERROR: 12871709Smlf bp = pktp->cp_bp; 12881709Smlf bp->b_resid += pktp->cp_byteleft - pktp->cp_bytexfer + 12891709Smlf pktp->cp_resid; 12901709Smlf if (geterror(bp) == 0) { 12911709Smlf if ((*((char *)(pktp->cp_cdbp)) == DCMD_FLUSH_CACHE) && 12921709Smlf (pktp->cp_dev_private == (opaque_t)dadkp) && 12931709Smlf ((int)(*(char *)pktp->cp_scbp) == DERR_ABORT)) { 12941709Smlf /* 12951709Smlf * Flag "unimplemented" responses for 12961709Smlf * DCMD_FLUSH_CACHE as ENOTSUP 12971709Smlf */ 12981709Smlf bioerror(bp, ENOTSUP); 12991709Smlf mutex_enter(&dadkp->dad_mutex); 13001709Smlf dadkp->dad_noflush = 1; 13011709Smlf mutex_exit(&dadkp->dad_mutex); 13021709Smlf } else { 13031709Smlf bioerror(bp, EIO); 13041709Smlf } 13051709Smlf } 13061709Smlf /*FALLTHROUGH*/ 13071709Smlf case COMMAND_DONE: 13081709Smlf default: 13091709Smlf return (COMMAND_DONE); 13101709Smlf } 13111709Smlf } 13121709Smlf 13131709Smlf 13141709Smlf static void 13151709Smlf dadk_pktcb(struct cmpkt *pktp) 13161709Smlf { 13171709Smlf int action; 13181709Smlf struct dadkio_rwcmd *rwcmdp; 13191709Smlf 13201709Smlf rwcmdp = (struct dadkio_rwcmd *)pktp->cp_passthru; /* ioctl packet */ 13211709Smlf 13221709Smlf if (pktp->cp_reason == CPS_SUCCESS) { 13231709Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) 13241709Smlf rwcmdp->status.status = DADKIO_STAT_NO_ERROR; 13251709Smlf pktp->cp_iodone(pktp->cp_bp); 13261709Smlf return; 13271709Smlf } 13281709Smlf 13291709Smlf if (rwcmdp && (rwcmdp != (opaque_t)DADK_SILENT)) { 13301709Smlf if (pktp->cp_reason == CPS_CHKERR) 13311709Smlf dadk_recorderr(pktp, rwcmdp); 13321709Smlf dadk_iodone(pktp->cp_bp); 13331709Smlf return; 13341709Smlf } 13351709Smlf 13361709Smlf if (pktp->cp_reason == CPS_CHKERR) 13371709Smlf action = dadk_chkerr(pktp); 13381709Smlf else 13391709Smlf action = COMMAND_DONE_ERROR; 13401709Smlf 13411709Smlf if (action == JUST_RETURN) 13421709Smlf return; 13431709Smlf 1344*7239Szk194757 /* 1345*7239Szk194757 * If we are panicking don't retry the command 1346*7239Szk194757 * just fail it so we can go down completing all 1347*7239Szk194757 * of the buffers. 1348*7239Szk194757 */ 1349*7239Szk194757 if (ddi_in_panic() && action == QUE_COMMAND) 1350*7239Szk194757 action = COMMAND_DONE_ERROR; 1351*7239Szk194757 13521709Smlf if (action != COMMAND_DONE) { 13531709Smlf if ((dadk_ioretry(pktp, action)) == JUST_RETURN) 13541709Smlf return; 13551709Smlf } 13561709Smlf pktp->cp_iodone(pktp->cp_bp); 13571709Smlf } 13581709Smlf 13591709Smlf 13601709Smlf 13611709Smlf static struct dadkio_derr dadk_errtab[] = { 13621709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 0 DERR_SUCCESS */ 13631709Smlf {QUE_COMMAND, GDA_FATAL}, /* 1 DERR_AMNF */ 13641709Smlf {QUE_COMMAND, GDA_FATAL}, /* 2 DERR_TKONF */ 13651709Smlf {COMMAND_DONE_ERROR, GDA_INFORMATIONAL}, /* 3 DERR_ABORT */ 13661709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 4 DERR_DWF */ 13671709Smlf {QUE_COMMAND, GDA_FATAL}, /* 5 DERR_IDNF */ 13681709Smlf {JUST_RETURN, GDA_INFORMATIONAL}, /* 6 DERR_BUSY */ 13691709Smlf {QUE_COMMAND, GDA_FATAL}, /* 7 DERR_UNC */ 13701709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 8 DERR_BBK */ 13711709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 9 DERR_INVCDB */ 13721709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 10 DERR_HARD */ 13731709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 11 DERR_ILI */ 13741709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 12 DERR_EOM */ 13751709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 13 DERR_MCR */ 13761709Smlf {COMMAND_DONE, GDA_INFORMATIONAL}, /* 14 DERR_RECOVER */ 13771709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 15 DERR_NOTREADY */ 13781709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 16 DERR_MEDIUM */ 13791709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 17 DERR_HW */ 13801709Smlf {COMMAND_DONE, GDA_FATAL}, /* 18 DERR_ILL */ 13811709Smlf {COMMAND_DONE, GDA_FATAL}, /* 19 DERR_UNIT_ATTN */ 13821709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 20 DERR_DATA_PROT */ 13831709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 21 DERR_MISCOMPARE */ 13841709Smlf {QUE_COMMAND, GDA_RETRYABLE}, /* 22 DERR_ICRC */ 13851709Smlf {COMMAND_DONE_ERROR, GDA_FATAL}, /* 23 DERR_RESV */ 13861709Smlf }; 13871709Smlf 13881709Smlf static int 13891709Smlf dadk_chkerr(struct cmpkt *pktp) 13901709Smlf { 13911709Smlf int err_blkno; 13922799Smarx struct dadk *dadkp = PKT2DADK(pktp); 13932799Smarx dadk_errstats_t *dep; 13942799Smarx int scb = *(char *)pktp->cp_scbp; 13951709Smlf 13962799Smarx if (scb == DERR_SUCCESS) { 13972799Smarx if (pktp->cp_retry != 0 && dadkp->dad_errstats != NULL) { 13982799Smarx dep = (dadk_errstats_t *) 13992799Smarx dadkp->dad_errstats->ks_data; 14002799Smarx dep->dadk_rq_recov_err.value.ui32++; 14012799Smarx } 14021709Smlf return (COMMAND_DONE); 14032799Smarx } 14041709Smlf 14051709Smlf if (pktp->cp_retry) { 14061709Smlf err_blkno = pktp->cp_srtsec + ((pktp->cp_bytexfer - 14075295Srandyf pktp->cp_resid) >> dadkp->dad_secshf); 14081709Smlf } else 14091709Smlf err_blkno = -1; 14101709Smlf 14112799Smarx if (dadkp->dad_errstats != NULL) { 14122799Smarx dep = (dadk_errstats_t *)dadkp->dad_errstats->ks_data; 14132799Smarx 14143399Smarx switch (dadk_errtab[scb].d_severity) { 14153399Smarx case GDA_RETRYABLE: 14163399Smarx dep->dadk_softerrs.value.ui32++; 14173399Smarx break; 14183399Smarx 14193399Smarx case GDA_FATAL: 14203399Smarx dep->dadk_harderrs.value.ui32++; 14213399Smarx break; 14223399Smarx 14233399Smarx default: 14243399Smarx break; 14253399Smarx } 14262799Smarx 14272799Smarx switch (scb) { 14282799Smarx case DERR_INVCDB: 14292799Smarx case DERR_ILI: 14302799Smarx case DERR_EOM: 14312799Smarx case DERR_HW: 14322799Smarx case DERR_ICRC: 14332799Smarx dep->dadk_transerrs.value.ui32++; 14342799Smarx break; 14352799Smarx 14362799Smarx case DERR_AMNF: 14372799Smarx case DERR_TKONF: 14382799Smarx case DERR_DWF: 14392799Smarx case DERR_BBK: 14402799Smarx case DERR_UNC: 14412799Smarx case DERR_HARD: 14422799Smarx case DERR_MEDIUM: 14432799Smarx case DERR_DATA_PROT: 14442799Smarx case DERR_MISCOMP: 14452799Smarx dep->dadk_rq_media_err.value.ui32++; 14462799Smarx break; 14472799Smarx 14482799Smarx case DERR_NOTREADY: 14492799Smarx dep->dadk_rq_ntrdy_err.value.ui32++; 14502799Smarx break; 14512799Smarx 14522799Smarx case DERR_IDNF: 14532799Smarx case DERR_UNIT_ATTN: 14542799Smarx dep->dadk_rq_nodev_err.value.ui32++; 14552799Smarx break; 14562799Smarx 14572799Smarx case DERR_ILL: 14582799Smarx case DERR_RESV: 14592799Smarx dep->dadk_rq_illrq_err.value.ui32++; 14602799Smarx break; 14612799Smarx 14622799Smarx default: 14632799Smarx break; 14642799Smarx } 14652799Smarx } 14662799Smarx 14671709Smlf /* if attempting to read a sector from a cdrom audio disk */ 14681709Smlf if ((dadkp->dad_cdrom) && 14691709Smlf (*((char *)(pktp->cp_cdbp)) == DCMD_READ) && 14701709Smlf (scb == DERR_ILL)) { 14711709Smlf return (COMMAND_DONE); 14721709Smlf } 14731709Smlf if (pktp->cp_passthru == NULL) { 14741709Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, 14751709Smlf dadk_errtab[scb].d_severity, pktp->cp_srtsec, 14761709Smlf err_blkno, dadk_cmds, dadk_sense); 14771709Smlf } 14781709Smlf 14791709Smlf if (scb == DERR_BUSY) { 14801709Smlf (void) timeout(dadk_restart, (void *)pktp, DADK_BSY_TIMEOUT); 14811709Smlf } 14821709Smlf 14833399Smarx return (dadk_errtab[scb].d_action); 14841709Smlf } 14851709Smlf 14861709Smlf static void 14871709Smlf dadk_recorderr(struct cmpkt *pktp, struct dadkio_rwcmd *rwcmdp) 14881709Smlf { 14891709Smlf struct dadk *dadkp; 14901709Smlf int scb; 14911709Smlf 14921709Smlf dadkp = PKT2DADK(pktp); 14931709Smlf scb = (int)(*(char *)pktp->cp_scbp); 14941709Smlf 14951709Smlf 14961709Smlf rwcmdp->status.failed_blk = rwcmdp->blkaddr + 14975295Srandyf ((pktp->cp_bytexfer - pktp->cp_resid) >> dadkp->dad_secshf); 14981709Smlf 14991709Smlf rwcmdp->status.resid = pktp->cp_bp->b_resid + 15005295Srandyf pktp->cp_byteleft - pktp->cp_bytexfer + pktp->cp_resid; 15011709Smlf switch ((int)(* (char *)pktp->cp_scbp)) { 15021709Smlf case DERR_AMNF: 15031709Smlf case DERR_ABORT: 15041709Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_REQUEST; 15051709Smlf break; 15061709Smlf case DERR_DWF: 15071709Smlf case DERR_IDNF: 15081709Smlf rwcmdp->status.status = DADKIO_STAT_ILLEGAL_ADDRESS; 15091709Smlf break; 15101709Smlf case DERR_TKONF: 15111709Smlf case DERR_UNC: 15121709Smlf case DERR_BBK: 15131709Smlf rwcmdp->status.status = DADKIO_STAT_MEDIUM_ERROR; 15141709Smlf rwcmdp->status.failed_blk_is_valid = 1; 15151709Smlf rwcmdp->status.resid = 0; 15161709Smlf break; 15171709Smlf case DERR_BUSY: 15181709Smlf rwcmdp->status.status = DADKIO_STAT_NOT_READY; 15191709Smlf break; 15201709Smlf case DERR_INVCDB: 15211709Smlf case DERR_HARD: 15221709Smlf rwcmdp->status.status = DADKIO_STAT_HARDWARE_ERROR; 15231709Smlf break; 15241709Smlf case DERR_ICRC: 15251709Smlf default: 15261709Smlf rwcmdp->status.status = DADKIO_STAT_NOT_SUPPORTED; 15271709Smlf } 15281709Smlf 15291709Smlf if (rwcmdp->flags & DADKIO_FLAG_SILENT) 15301709Smlf return; 15311709Smlf gda_errmsg(dadkp->dad_sd, pktp, dadk_name, dadk_errtab[scb].d_severity, 15325295Srandyf rwcmdp->blkaddr, rwcmdp->status.failed_blk, 15335295Srandyf dadk_cmds, dadk_sense); 15341709Smlf } 15351709Smlf 15361709Smlf /*ARGSUSED*/ 15371709Smlf static void 15381709Smlf dadk_polldone(struct buf *bp) 15391709Smlf { 15405295Srandyf struct cmpkt *pktp; 15415295Srandyf struct dadk *dadkp; 15425295Srandyf 15435295Srandyf pktp = GDA_BP_PKT(bp); 15445295Srandyf dadkp = PKT2DADK(pktp); 15455295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 15465295Srandyf dadkp->dad_cmd_count--; 15475295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 15481709Smlf } 15491709Smlf 15501709Smlf static void 15511709Smlf dadk_iodone(struct buf *bp) 15521709Smlf { 15531709Smlf struct cmpkt *pktp; 15541709Smlf struct dadk *dadkp; 15551709Smlf 15561709Smlf pktp = GDA_BP_PKT(bp); 15571709Smlf dadkp = PKT2DADK(pktp); 15581709Smlf 15591709Smlf /* check for all iodone */ 15601709Smlf pktp->cp_byteleft -= pktp->cp_bytexfer; 15611709Smlf if (geterror(bp) == 0 && pktp->cp_byteleft != 0) { 15621709Smlf pktp->cp_retry = 0; 15631709Smlf (void) dadk_iosetup(dadkp, pktp); 15641709Smlf 15651709Smlf 15661709Smlf /* transport the next one */ 15671709Smlf if (CTL_TRANSPORT(dadkp->dad_ctlobjp, pktp) == CTL_SEND_SUCCESS) 15681709Smlf return; 15691709Smlf if ((dadk_ioretry(pktp, QUE_COMMAND)) == JUST_RETURN) 15701709Smlf return; 15711709Smlf } 15721709Smlf 15731709Smlf /* start next one */ 15741709Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 15751709Smlf 15761709Smlf /* free pkt */ 15771709Smlf if (pktp->cp_private) 15781709Smlf BBH_FREEHANDLE(dadkp->dad_bbhobjp, pktp->cp_private); 15791709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 15805295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 15815295Srandyf dadkp->dad_cmd_count--; 15825295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 15831709Smlf biodone(bp); 15841709Smlf } 15851709Smlf 15861709Smlf int 15871709Smlf dadk_check_media(opaque_t objp, int *state) 15881709Smlf { 15891709Smlf struct dadk *dadkp = (struct dadk *)objp; 15901709Smlf 15911709Smlf if (!dadkp->dad_rmb) { 15921709Smlf return (ENXIO); 15931709Smlf } 15941709Smlf #ifdef DADK_DEBUG 15951709Smlf if (dadk_debug & DSTATE) 15961709Smlf PRF("dadk_check_media: user state %x disk state %x\n", 15975295Srandyf *state, dadkp->dad_iostate); 15981709Smlf #endif 15991709Smlf /* 16001709Smlf * If state already changed just return 16011709Smlf */ 16021709Smlf if (*state != dadkp->dad_iostate) { 16031709Smlf *state = dadkp->dad_iostate; 16041709Smlf return (0); 16051709Smlf } 16061709Smlf 16071709Smlf /* 16081709Smlf * Startup polling on thread state 16091709Smlf */ 16101709Smlf mutex_enter(&dadkp->dad_mutex); 16111709Smlf if (dadkp->dad_thread_cnt == 0) { 16121709Smlf /* 16131709Smlf * One thread per removable dadk device 16141709Smlf */ 16151709Smlf (void) thread_create(NULL, 0, dadk_watch_thread, dadkp, 0, &p0, 16161709Smlf TS_RUN, v.v_maxsyspri - 2); 16171709Smlf } 16181709Smlf dadkp->dad_thread_cnt++; 16191709Smlf 16201709Smlf /* 16211709Smlf * Wait for state to change 16221709Smlf */ 16231709Smlf do { 16241709Smlf if (cv_wait_sig(&dadkp->dad_state_cv, &dadkp->dad_mutex) == 0) { 16251709Smlf dadkp->dad_thread_cnt--; 16261709Smlf mutex_exit(&dadkp->dad_mutex); 16271709Smlf return (EINTR); 16281709Smlf } 16291709Smlf } while (*state == dadkp->dad_iostate); 16301709Smlf *state = dadkp->dad_iostate; 16311709Smlf dadkp->dad_thread_cnt--; 16321709Smlf mutex_exit(&dadkp->dad_mutex); 16331709Smlf return (0); 16341709Smlf } 16351709Smlf 16361709Smlf 16371709Smlf #define MEDIA_ACCESS_DELAY 2000000 16381709Smlf 16391709Smlf static void 16401709Smlf dadk_watch_thread(struct dadk *dadkp) 16411709Smlf { 16421709Smlf enum dkio_state state; 16431709Smlf int interval; 16441709Smlf 16451709Smlf interval = drv_usectohz(dadk_check_media_time); 16461709Smlf 16471709Smlf do { 16481709Smlf if (dadk_rmb_ioctl(dadkp, DCMD_GET_STATE, (intptr_t)&state, 0, 16491709Smlf DADK_SILENT)) { 16501709Smlf /* 16511709Smlf * Assume state remained the same 16521709Smlf */ 16531709Smlf state = dadkp->dad_iostate; 16541709Smlf } 16551709Smlf 16561709Smlf /* 16571709Smlf * now signal the waiting thread if this is *not* the 16581709Smlf * specified state; 16591709Smlf * delay the signal if the state is DKIO_INSERTED 16601709Smlf * to allow the target to recover 16611709Smlf */ 16621709Smlf if (state != dadkp->dad_iostate) { 16631709Smlf 16641709Smlf dadkp->dad_iostate = state; 16651709Smlf if (state == DKIO_INSERTED) { 16661709Smlf /* 16671709Smlf * delay the signal to give the drive a chance 16681709Smlf * to do what it apparently needs to do 16691709Smlf */ 16701709Smlf (void) timeout((void(*)(void *))cv_broadcast, 16711709Smlf (void *)&dadkp->dad_state_cv, 16721709Smlf drv_usectohz((clock_t)MEDIA_ACCESS_DELAY)); 16731709Smlf } else { 16741709Smlf cv_broadcast(&dadkp->dad_state_cv); 16751709Smlf } 16761709Smlf } 16771709Smlf delay(interval); 16781709Smlf } while (dadkp->dad_thread_cnt); 16791709Smlf } 16801709Smlf 16811709Smlf int 16821709Smlf dadk_inquiry(opaque_t objp, opaque_t *inqpp) 16831709Smlf { 16841709Smlf struct dadk *dadkp = (struct dadk *)objp; 16851709Smlf struct scsi_inquiry **sinqpp = (struct scsi_inquiry **)inqpp; 16861709Smlf 16871709Smlf if (dadkp && dadkp->dad_sd && dadkp->dad_sd->sd_inq) { 16881709Smlf *sinqpp = dadkp->dad_sd->sd_inq; 16891709Smlf return (DDI_SUCCESS); 16901709Smlf } 16911709Smlf 16921709Smlf return (DDI_FAILURE); 16931709Smlf } 16941709Smlf 16951709Smlf static int 16961709Smlf dadk_rmb_ioctl(struct dadk *dadkp, int cmd, intptr_t arg, int flags, int silent) 16971709Smlf 16981709Smlf { 16991709Smlf struct buf *bp; 17001709Smlf int err; 17011709Smlf struct cmpkt *pktp; 17021709Smlf 17031709Smlf if ((bp = getrbuf(KM_SLEEP)) == NULL) { 17041709Smlf return (ENOMEM); 17051709Smlf } 17061709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_rmb_iodone, NULL, NULL); 17071709Smlf if (!pktp) { 17081709Smlf freerbuf(bp); 17091709Smlf return (ENOMEM); 17101709Smlf } 17111709Smlf bp->b_back = (struct buf *)arg; 17121709Smlf bp->b_forw = (struct buf *)dadkp->dad_flcobjp; 17131709Smlf pktp->cp_passthru = (opaque_t)(intptr_t)silent; 17141709Smlf 17155295Srandyf err = dadk_ctl_ioctl(dadkp, cmd, (uintptr_t)pktp, flags); 17161709Smlf freerbuf(bp); 17171709Smlf gda_free(dadkp->dad_ctlobjp, pktp, NULL); 17181709Smlf return (err); 17191709Smlf 17201709Smlf 17211709Smlf } 17221709Smlf 17231709Smlf static void 17241709Smlf dadk_rmb_iodone(struct buf *bp) 17251709Smlf { 17261709Smlf struct cmpkt *pktp; 17271709Smlf struct dadk *dadkp; 17281709Smlf 17291709Smlf pktp = GDA_BP_PKT(bp); 17301709Smlf dadkp = PKT2DADK(pktp); 17311709Smlf 17321709Smlf bp->b_flags &= ~(B_DONE|B_BUSY); 17331709Smlf 17341709Smlf /* Start next one */ 17351709Smlf FLC_DEQUE(dadkp->dad_flcobjp, bp); 17361709Smlf 17375295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 17385295Srandyf dadkp->dad_cmd_count--; 17395295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 17401709Smlf biodone(bp); 17411709Smlf } 17421709Smlf 17431709Smlf static int 17441709Smlf dadk_dk_buf_setup(struct dadk *dadkp, opaque_t *cmdp, dev_t dev, 17451709Smlf enum uio_seg dataspace, int rw) 17461709Smlf { 17471709Smlf struct dadkio_rwcmd *rwcmdp = (struct dadkio_rwcmd *)cmdp; 17481709Smlf struct buf *bp; 17491709Smlf struct iovec aiov; 17501709Smlf struct uio auio; 17511709Smlf struct uio *uio = &auio; 17521709Smlf int status; 17531709Smlf 17541709Smlf bp = getrbuf(KM_SLEEP); 17551709Smlf 17561709Smlf bp->av_forw = bp->b_forw = (struct buf *)dadkp; 17571709Smlf bp->b_back = (struct buf *)rwcmdp; /* ioctl packet */ 17581709Smlf 17591709Smlf bzero((caddr_t)&auio, sizeof (struct uio)); 17601709Smlf bzero((caddr_t)&aiov, sizeof (struct iovec)); 17611709Smlf aiov.iov_base = rwcmdp->bufaddr; 17621709Smlf aiov.iov_len = rwcmdp->buflen; 17631709Smlf uio->uio_iov = &aiov; 17641709Smlf 17651709Smlf uio->uio_iovcnt = 1; 17661709Smlf uio->uio_resid = rwcmdp->buflen; 17671709Smlf uio->uio_segflg = dataspace; 17681709Smlf 17691709Smlf /* Let physio do the rest... */ 17701709Smlf status = physio(dadk_dk_strategy, bp, dev, rw, dadkmin, uio); 17711709Smlf 17721709Smlf freerbuf(bp); 17731709Smlf return (status); 17741709Smlf 17751709Smlf } 17761709Smlf 17771709Smlf /* Do not let a user gendisk request get too big or */ 17781709Smlf /* else we could use to many resources. */ 17791709Smlf 17801709Smlf static void 17811709Smlf dadkmin(struct buf *bp) 17821709Smlf { 17831709Smlf if (bp->b_bcount > dadk_dk_maxphys) 17841709Smlf bp->b_bcount = dadk_dk_maxphys; 17851709Smlf } 17861709Smlf 17871709Smlf static int 17881709Smlf dadk_dk_strategy(struct buf *bp) 17891709Smlf { 17901709Smlf dadk_dk((struct dadk *)bp->av_forw, (struct dadkio_rwcmd *)bp->b_back, 17911709Smlf bp); 17921709Smlf return (0); 17931709Smlf } 17941709Smlf 17951709Smlf static void 17961709Smlf dadk_dk(struct dadk *dadkp, struct dadkio_rwcmd *rwcmdp, struct buf *bp) 17971709Smlf { 17981709Smlf struct cmpkt *pktp; 17991709Smlf 18001709Smlf pktp = dadk_pktprep(dadkp, NULL, bp, dadk_iodone, NULL, NULL); 18011709Smlf if (!pktp) { 18021709Smlf bioerror(bp, ENOMEM); 18031709Smlf biodone(bp); 18041709Smlf return; 18051709Smlf } 18061709Smlf 18071709Smlf pktp->cp_passthru = rwcmdp; 18081709Smlf 18091709Smlf (void) dadk_ioprep(dadkp, pktp); 18101709Smlf 18115295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 18125295Srandyf dadkp->dad_cmd_count++; 18135295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 18141709Smlf FLC_ENQUE(dadkp->dad_flcobjp, bp); 18151709Smlf } 18165295Srandyf 18175295Srandyf /* 18185295Srandyf * There is no existing way to notify cmdk module 18195295Srandyf * when the command completed, so add this function 18205295Srandyf * to calculate how many on-going commands. 18215295Srandyf */ 18225295Srandyf int 18235295Srandyf dadk_getcmds(opaque_t objp) 18245295Srandyf { 18255295Srandyf struct dadk *dadkp = (struct dadk *)objp; 18265295Srandyf int count; 18275295Srandyf 18285295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 18295295Srandyf count = dadkp->dad_cmd_count; 18305295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 18315295Srandyf return (count); 18325295Srandyf } 18335295Srandyf 18345295Srandyf /* 18355295Srandyf * this function was used to calc the cmd for CTL_IOCTL 18365295Srandyf */ 18375295Srandyf static int 18385295Srandyf dadk_ctl_ioctl(struct dadk *dadkp, uint32_t cmd, uintptr_t arg, int flag) 18395295Srandyf { 18405295Srandyf int error; 18415295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 18425295Srandyf dadkp->dad_cmd_count++; 18435295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 18445295Srandyf error = CTL_IOCTL(dadkp->dad_ctlobjp, cmd, arg, flag); 18455295Srandyf mutex_enter(&dadkp->dad_cmd_mutex); 18465295Srandyf dadkp->dad_cmd_count--; 18475295Srandyf mutex_exit(&dadkp->dad_cmd_mutex); 18485295Srandyf return (error); 18495295Srandyf } 1850