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