154881Storek /* 254881Storek * Copyright (c) 1990, 1992 The Regents of the University of California. 354881Storek * All rights reserved. 454881Storek * 554881Storek * This software was developed by the Computer Systems Engineering group 654881Storek * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 754881Storek * contributed to Berkeley. 854881Storek * 955559Storek * All advertising materials mentioning features or use of this software 1055559Storek * must display the following acknowledgement: 1155559Storek * This product includes software developed by the University of 12*56900Storek * California, Lawrence Berkeley Laboratory. 1355559Storek * 1454881Storek * %sccs.include.redist.c% 1554881Storek * 16*56900Storek * @(#)sd.c 5.4 (Berkeley) 11/18/92 1754881Storek * 18*56900Storek * from: $Header: sd.c,v 1.24 92/11/19 04:37:33 torek Exp $ 1954881Storek */ 2054881Storek 2154881Storek /* 2254881Storek * SCSI CCS (Command Command Set) disk driver. 2354881Storek * 2454881Storek * MACHINE INDEPENDENT (do not put machine dependent goo in here!) 2554881Storek * 2654881Storek * (from sd.c,v 1.7 90/12/15 14:11:26 van Exp) 2754881Storek */ 2854881Storek 2955559Storek #include <sys/param.h> 3055559Storek #include <sys/systm.h> 3155559Storek #include <sys/proc.h> 3255559Storek #include <sys/buf.h> 3355559Storek #include <sys/errno.h> 3455559Storek #include <sys/device.h> 3555559Storek #include <sys/disklabel.h> 3655559Storek #include <sys/dkstat.h> 3755559Storek #include <sys/disk.h> 3855559Storek #include <sys/ioctl.h> 3955559Storek #include <sys/malloc.h> 4054881Storek 41*56900Storek #include <dev/scsi/scsi.h> 42*56900Storek #include <dev/scsi/disk.h> 43*56900Storek #include <dev/scsi/scsivar.h> 44*56900Storek #include <dev/scsi/scsi_ioctl.h> 45*56900Storek 4655559Storek #include <machine/cpu.h> 4754881Storek 48*56900Storek #include <dev/scsi/sdtrace.h> 4954881Storek 5055559Storek #ifdef sparc /* XXX */ 5155559Storek #define SUN_LABEL_HACK /* XXX */ 5255559Storek #endif /* XXX */ 5354881Storek 5454881Storek #ifdef SUN_LABEL_HACK 5555559Storek #include <sparc/sunos/sun_disklabel.h> 5654881Storek #endif 5754881Storek 5854881Storek /* 5954881Storek * Per-disk variables. 6054881Storek * 6154881Storek * sd_dk contains all the `disk' specific stuff (label/partitions, 6254881Storek * transfer rate, etc). We need only things that are special to 6354881Storek * scsi disks. Note that our blocks are in terms of DEV_BSIZE blocks. 6454881Storek */ 6554881Storek struct sd_softc { 6654881Storek struct dkdevice sc_dk; /* base disk device, must be first */ 6754881Storek struct unit sc_unit; /* scsi unit */ 6854881Storek pid_t sc_format_pid; /* process using "format" mode */ 6954881Storek u_char sc_type; /* drive type */ 7054881Storek u_char sc_bshift; /* convert device blocks to DEV_BSIZE blks */ 7154881Storek short sc_flags; /* see below */ 7254881Storek u_int sc_blks; /* number of blocks on device */ 7354881Storek int sc_blksize; /* device block size in bytes */ 7454881Storek 7554881Storek /* should be in dkdevice?? */ 7654881Storek struct buf sc_tab; /* transfer queue */ 7754881Storek 7854881Storek /* statistics */ 7954881Storek long sc_resets; /* number of times reset */ 8054881Storek long sc_transfers; /* count of total transfers */ 8154881Storek long sc_partials; /* count of `partial' transfers */ 8254881Storek 8354881Storek /* for user formatting */ 8454881Storek struct scsi_cdb sc_cmd; 8554881Storek struct scsi_fmt_sense sc_sense; 8654881Storek }; 8754881Storek 8854881Storek #define SDF_ALIVE 1 /* drive OK for regular kernel use */ 8954881Storek 9054881Storek /* definition of the autoconfig driver */ 9154881Storek int sdmatch __P((struct device *, struct cfdata *, void *)); 9254881Storek void sdattach __P((struct device *, struct device *, void *)); 9354881Storek 9454881Storek struct cfdriver sdcd = 9554881Storek { NULL, "sd", sdmatch, sdattach, DV_DISK, sizeof(struct sd_softc) }; 9654881Storek 9754881Storek /* definition of the unit driver, for hba */ 9854881Storek void sdigo __P((struct device *, struct scsi_cdb *)); 9954881Storek void sdgo __P((struct device *, struct scsi_cdb *)); 10054881Storek void sdintr __P((struct device *, int, int)); 10154881Storek void sdreset __P((struct unit *)); 10254881Storek 10354881Storek static struct unitdriver sdunitdriver = { /*sdgo, sdintr*/ sdreset }; 10454881Storek 10554881Storek /* definition of the disk driver, for kernel */ 10654881Storek void sdstrategy __P((struct buf *)); 10754881Storek 108*56900Storek static struct dkdriver sddkdriver = { sdstrategy }; 10954881Storek 11054881Storek #ifdef DEBUG 11154881Storek int sddebug = 1; 11254881Storek #define SDB_ERROR 0x01 11354881Storek #define SDB_PARTIAL 0x02 11454881Storek #endif 11554881Storek 11654881Storek #define sdunit(x) (minor(x) >> 3) 11754881Storek #define sdpart(x) (minor(x) & 0x7) 11854881Storek 11954881Storek #define b_cylin b_resid 12054881Storek 12154881Storek #define SDRETRY 2 12254881Storek 12354881Storek /* 12454881Storek * Table of scsi commands users are allowed to access via `format' 12554881Storek * mode. 0 means not legal. 1 means `immediate' (doesn't need dma). 12654881Storek * -1 means needs dma and/or wait for intr (i.e., `slow'). 12754881Storek */ 12854881Storek static char legal_cmds[256] = { 12954881Storek /***** 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 13054881Storek /*00*/ 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13154881Storek /*10*/ 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 13254881Storek /*20*/ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13354881Storek /*30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13454881Storek /*40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13554881Storek /*50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13654881Storek /*60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13754881Storek /*70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13854881Storek /*80*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13954881Storek /*90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14054881Storek /*a0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14154881Storek /*b0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14254881Storek /*c0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14354881Storek /*d0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14454881Storek /*e0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14554881Storek /*f0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14654881Storek }; 14754881Storek 14854881Storek int 14954881Storek sdmatch(parent, cf, aux) 15054881Storek struct device *parent; 15154881Storek register struct cfdata *cf; 15254881Storek void *aux; 15354881Storek { 15454881Storek register struct scsi_attach_args *sa = aux; 15554881Storek #ifdef DEBUG 15654881Storek char *whynot; 15754881Storek #endif 15854881Storek 15954881Storek /* 16054881Storek * unit number must match, or be given as `any' 16154881Storek */ 16254881Storek if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != sa->sa_unit) 16354881Storek return (0); 16454881Storek /* 16554881Storek * drive must be a disk, and of a kind we recognize 16654881Storek */ 16754881Storek if ((sa->sa_inq_status & STS_MASK) != STS_GOOD) { 16854881Storek #ifdef DEBUG 16954881Storek whynot = "INQUIRY failed"; 17054881Storek #endif 17154881Storek goto notdisk; 17254881Storek } 17354881Storek 17454881Storek switch (sa->sa_si.si_type & TYPE_TYPE_MASK) { 17554881Storek 17654881Storek case TYPE_DAD: /* disk */ 17754881Storek case TYPE_WORM: /* WORM */ 17854881Storek case TYPE_ROM: /* CD-ROM */ 17954881Storek case TYPE_MO: /* Magneto-optical */ 18054881Storek case TYPE_JUKEBOX: /* medium changer */ 18154881Storek break; 18254881Storek 18354881Storek default: 18454881Storek notdisk: 18554881Storek #ifdef DEBUG 18654881Storek whynot = "not a disk"; 18754881Storek printf("[not matching `sd' at unit %d: %s]\n", 18854881Storek sa->sa_unit, whynot); 18954881Storek #endif 19054881Storek return (0); 19154881Storek } 19254881Storek 19354881Storek /* 19454881Storek * It is a disk of some kind; take it. We will figure out 19554881Storek * the rest in the attach routine. 19654881Storek */ 19754881Storek return (1); 19854881Storek } 19954881Storek 20054881Storek /* 20154881Storek * Attach a disk (called after sdmatch returns true). 20254881Storek * Note that this routine is never reentered (so we can use statics). 20354881Storek */ 20454881Storek void 20554881Storek sdattach(parent, self, aux) 20654881Storek struct device *parent, *self; 20754881Storek void *aux; 20854881Storek { 20954881Storek register struct sd_softc *sc = (struct sd_softc *)self; 21054881Storek register struct scsi_attach_args *sa = aux; 21154881Storek register int i; 21254881Storek char vendor[10], drive[17], rev[5]; 21354881Storek static u_char capbuf[8]; 21454881Storek static struct scsi_cdb cap = { CMD_READ_CAPACITY }; 21554881Storek #ifdef SUN_LABEL_HACK 21654881Storek static struct scsi_cdb rd0 = { CMD_READ10, 0, 0, 0, 0, 0, 0, 0, 1, 0 }; 21754881Storek caddr_t sector; 21854881Storek #endif 21954881Storek 22054881Storek /* 22154881Storek * Declare our existence. 22254881Storek */ 22354881Storek sc->sc_unit.u_driver = &sdunitdriver; 22454881Storek scsi_establish(&sc->sc_unit, &sc->sc_dk.dk_dev, sa->sa_unit); 22554881Storek 22654881Storek /* 22754881Storek * Figure out what kind of disk this is. 22854881Storek * We only accepted it if the inquiry succeeded, so 22954881Storek * we can inspect those fields. 23054881Storek */ 23154881Storek i = (sa->sa_si.si_version >> VER_ANSI_SHIFT) & VER_ANSI_MASK; 23254881Storek if (i == 1 || i == 2) { 23354881Storek scsi_inq_ansi((struct scsi_inq_ansi *)&sa->sa_si, 23454881Storek vendor, drive, rev); 23554881Storek printf(": %s %s", vendor, drive); 23654881Storek /* XXX should we even ever bother printing this? */ 23754881Storek if (rev[0]) 23854881Storek printf(" %s", rev); 23954881Storek } else { 24054881Storek /* bleah */ 24154881Storek bcopy("<unknown>", vendor, 10); 24254881Storek bcopy("<unknown>", drive, 10); 24354881Storek printf(": type 0x%x, qual 0x%x, ver %d", 24454881Storek sa->sa_si.si_type, sa->sa_si.si_qual, 24554881Storek sa->sa_si.si_version); 24654881Storek } 24754881Storek 24854881Storek CDB10(&cap)->cdb_lun_rel = sc->sc_unit.u_unit << 5; 24954881Storek i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba, 25054881Storek sc->sc_unit.u_targ, &cap, (char *)capbuf, sizeof capbuf, B_READ); 25154881Storek i &= STS_MASK; 25254881Storek if (i == STS_GOOD) { 25354881Storek #define NUMBER(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3]) 25454881Storek sc->sc_blks = NUMBER(&capbuf[0]); 25554881Storek sc->sc_blksize = NUMBER(&capbuf[4]); 25654881Storek } else if (i == STS_CHECKCOND && 25754881Storek (strcmp(vendor, "HP") == 0 && strcmp(drive, "S6300.650A") == 0)) { 25854881Storek /* XXX unformatted or nonexistent MO medium: fake it */ 25954881Storek sc->sc_blks = 318664; 26054881Storek sc->sc_blksize = 1024; 26154881Storek } else { 262*56900Storek /* XXX shouldn't bail for removable media */ 26354881Storek printf(": unable to determine drive capacity [sts=%x]\n", i); 26454881Storek return; 26554881Storek } 26654881Storek /* return value from read capacity is last valid block, not nblocks */ 26754881Storek sc->sc_blks++; 26854881Storek printf(", %u %d byte blocks\n", sc->sc_blks, sc->sc_blksize); 26954881Storek if (sc->sc_blksize != DEV_BSIZE) { 27054881Storek for (i = sc->sc_blksize; i > DEV_BSIZE; i >>= 1) 27154881Storek ++sc->sc_bshift; 27254881Storek if (i != DEV_BSIZE) { 27354881Storek printf("%s: blksize not multiple of %d: cannot use\n", 27454881Storek sc->sc_dk.dk_dev.dv_xname, DEV_BSIZE); 27554881Storek return; 27654881Storek } 27754881Storek sc->sc_blks <<= sc->sc_bshift; 27854881Storek } 27954881Storek sc->sc_type = sa->sa_si.si_type; /* sufficient? */ 28054881Storek 281*56900Storek sc->sc_dk.dk_driver = &sddkdriver; 282*56900Storek #ifdef notyet 283*56900Storek dk_establish(&sc->sc_dk); 284*56900Storek /* READ DISK LABEL HERE, UNLESS REMOVABLE MEDIUM... NEEDS THOUGHT */ 285*56900Storek #else 28654881Storek sc->sc_dk.dk_label.d_secsize = 512; /* XXX */ 287*56900Storek sc->sc_dk.dk_bps = (3600/60) * 32 * 512;/* XXX */ 28854881Storek 28954881Storek #ifdef SUN_LABEL_HACK 29054881Storek sector = (caddr_t)malloc(sc->sc_blksize, M_DEVBUF, M_NOWAIT); 29154881Storek CDB10(&rd0)->cdb_lun_rel = sc->sc_unit.u_unit << 5; 29254881Storek i = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba, 29354881Storek sc->sc_unit.u_targ, &rd0, sector, sc->sc_blksize, B_READ); 29454881Storek if (i == STS_GOOD) { 29554881Storek printf("%s: <%s>\n", sc->sc_dk.dk_dev.dv_xname, 29654881Storek ((struct sun_disklabel *)sector)->sl_text); 29754881Storek if (sun_disklabel(sector, &sc->sc_dk.dk_label)) 29854881Storek sc->sc_flags |= SDF_ALIVE; 29954881Storek else 30054881Storek printf("%s: sun_disklabel fails\n", 30154881Storek sc->sc_dk.dk_dev.dv_xname); 30254881Storek } else 30354881Storek printf("%s: could not read sector 0 for disk label\n", 30454881Storek sc->sc_dk.dk_dev.dv_xname); 30554881Storek free(sector, M_DEVBUF); 30654881Storek #endif 307*56900Storek #endif /* notyet */ 30854881Storek } 30954881Storek 31054881Storek /* 31154881Storek * Reset a disk, after a SCSI bus reset. 31254881Storek * 31354881Storek * XXX untested and probably incomplete/incorrect 31454881Storek */ 31554881Storek void 31654881Storek sdreset(u) 31754881Storek register struct unit *u; 31854881Storek { 31954881Storek register struct sd_softc *sc = (struct sd_softc *)u->u_dev; 32054881Storek 32154881Storek printf(" %s", sc->sc_dk.dk_dev.dv_xname); 32254881Storek sc->sc_resets++; 32354881Storek } 32454881Storek 32554881Storek /* dev_t is short, must use prototype syntax */ 32654881Storek int 32754881Storek sdopen(dev_t dev, int flags, int ifmt, struct proc *p) 32854881Storek { 32954881Storek register int unit = sdunit(dev); 33054881Storek register struct sd_softc *sc; 33154881Storek 33254881Storek if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL) 33354881Storek return (ENXIO); 33454881Storek if ((sc->sc_flags & SDF_ALIVE) == 0 && 33554881Storek !suser(p->p_ucred, &p->p_acflag)) 33654881Storek return (ENXIO); 33754881Storek return (0); 33854881Storek } 33954881Storek 34054881Storek int 34154881Storek sdclose(dev_t dev, int flags, int ifmt, struct proc *p) 34254881Storek { 34354881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)]; 34454881Storek 34554881Storek sc->sc_format_pid = 0; 34654881Storek return (0); 34754881Storek } 34854881Storek 34954881Storek /* 35054881Storek * This routine is called for partial block transfers and non-aligned 35154881Storek * transfers (the latter only being possible on devices with a block size 35254881Storek * larger than DEV_BSIZE). The operation is performed in three steps 35354881Storek * using a locally allocated buffer: 35454881Storek * 1. transfer any initial partial block 35554881Storek * 2. transfer full blocks 35654881Storek * 3. transfer any final partial block 35754881Storek */ 35854881Storek static void 35954881Storek sdlblkstrat(bp, bsize) 36054881Storek register struct buf *bp; 36154881Storek register int bsize; 36254881Storek { 36354881Storek register int bn, resid, boff, count; 36454881Storek register caddr_t addr, cbuf; 365*56900Storek struct buf *tbp; 36654881Storek 367*56900Storek /* should probably use geteblk() here, but I fear consequences */ 36854881Storek cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK); 369*56900Storek tbp = (struct buf *)malloc(sizeof *tbp, M_DEVBUF, M_WAITOK); 370*56900Storek bzero((caddr_t)tbp, sizeof *tbp); 371*56900Storek tbp->b_proc = curproc; 372*56900Storek tbp->b_dev = bp->b_dev; 37354881Storek bn = bp->b_blkno; 37454881Storek resid = bp->b_bcount; 37554881Storek addr = bp->b_un.b_addr; 37654881Storek #ifdef DEBUG 37754881Storek if (sddebug & SDB_PARTIAL) 37854881Storek printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n", 37954881Storek bp, bp->b_flags, bn, resid, addr); 38054881Storek #endif 38154881Storek 38254881Storek while (resid > 0) { 38354881Storek boff = dbtob(bn) & (bsize - 1); 38454881Storek if (boff || resid < bsize) { 38554881Storek struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)]; 38654881Storek sc->sc_partials++; 38755161Spendry count = min(resid, bsize - boff); 388*56900Storek tbp->b_flags = B_BUSY | B_READ; 389*56900Storek tbp->b_blkno = bn - btodb(boff); 390*56900Storek tbp->b_un.b_addr = cbuf; 391*56900Storek tbp->b_bcount = bsize; 39254881Storek #ifdef DEBUG 39354881Storek if (sddebug & SDB_PARTIAL) 39454881Storek printf(" readahead: bn %x cnt %x off %x addr %x\n", 395*56900Storek tbp->b_blkno, count, boff, addr); 39654881Storek #endif 397*56900Storek sdstrategy(tbp); 398*56900Storek biowait(tbp); 399*56900Storek if (tbp->b_flags & B_ERROR) { 40054881Storek bp->b_flags |= B_ERROR; 401*56900Storek bp->b_error = tbp->b_error; 40254881Storek break; 40354881Storek } 40454881Storek if (bp->b_flags & B_READ) { 40554881Storek bcopy(&cbuf[boff], addr, count); 40654881Storek goto done; 40754881Storek } 40854881Storek bcopy(addr, &cbuf[boff], count); 40954881Storek #ifdef DEBUG 41054881Storek if (sddebug & SDB_PARTIAL) 41154881Storek printf(" writeback: bn %x cnt %x off %x addr %x\n", 412*56900Storek tbp->b_blkno, count, boff, addr); 41354881Storek #endif 41454881Storek } else { 41554881Storek count = resid & ~(bsize - 1); 416*56900Storek tbp->b_blkno = bn; 417*56900Storek tbp->b_un.b_addr = addr; 418*56900Storek tbp->b_bcount = count; 41954881Storek #ifdef DEBUG 42054881Storek if (sddebug & SDB_PARTIAL) 42154881Storek printf(" fulltrans: bn %x cnt %x addr %x\n", 422*56900Storek tbp->b_blkno, count, addr); 42354881Storek #endif 42454881Storek } 425*56900Storek tbp->b_flags = B_BUSY | (bp->b_flags & B_READ); 426*56900Storek sdstrategy(tbp); 427*56900Storek biowait(tbp); 428*56900Storek if (tbp->b_flags & B_ERROR) { 42954881Storek bp->b_flags |= B_ERROR; 430*56900Storek bp->b_error = tbp->b_error; 43154881Storek break; 43254881Storek } 43354881Storek done: 43454881Storek bn += btodb(count); 43554881Storek resid -= count; 43654881Storek addr += count; 43754881Storek #ifdef DEBUG 43854881Storek if (sddebug & SDB_PARTIAL) 43954881Storek printf(" done: bn %x resid %x addr %x\n", 44054881Storek bn, resid, addr); 44154881Storek #endif 44254881Storek } 44354881Storek free(cbuf, M_DEVBUF); 444*56900Storek free((caddr_t)tbp, M_DEVBUF); 44554881Storek biodone(bp); 44654881Storek } 44754881Storek 44854881Storek /* 44954881Storek * Start a transfer on sc as described by bp 45054881Storek * (i.e., call hba or target start). 45154881Storek * If in format mode, we may not need dma. 45254881Storek */ 45354881Storek #define sdstart(sc, bp) { \ 45454881Storek SD_TRACE(T_START, sc, bp); \ 45554881Storek if ((sc)->sc_format_pid && legal_cmds[(sc)->sc_cmd.cdb_bytes[0]] > 0) \ 45654881Storek (*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \ 45754881Storek &(sc)->sc_unit.u_forw, (struct buf *)NULL, \ 45854881Storek sdigo, &(sc)->sc_dk.dk_dev); \ 45954881Storek else \ 46054881Storek (*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \ 46154881Storek &(sc)->sc_unit.u_forw, bp, sdgo, &(sc)->sc_dk.dk_dev); \ 46254881Storek } 46354881Storek 46454881Storek void 46554881Storek sdstrategy(bp) 46654881Storek register struct buf *bp; 46754881Storek { 46854881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)]; 46954881Storek register int s; 47054881Storek 47154881Storek if (sc->sc_format_pid) { 47254881Storek /* XXXXXXXXX SHOULD NOT COMPARE curproc IN HERE!?! */ 47354881Storek /* 47454881Storek * In format mode, only allow the owner to mess 47554881Storek * with the drive. Skip all the partition checks. 47654881Storek */ 47754881Storek if (sc->sc_format_pid != curproc->p_pid) { 47854881Storek bp->b_error = EPERM; 47954881Storek bp->b_flags |= B_ERROR; 48054881Storek biodone(bp); 48154881Storek return; 48254881Storek } 48354881Storek bp->b_cylin = 0; 48454881Storek } else { 48554881Storek register daddr_t bn = bp->b_blkno; 48654881Storek register int sz = howmany(bp->b_bcount, DEV_BSIZE); 48754881Storek register struct partition *p; 48854881Storek 48954881Storek /* 49054881Storek * Make sure transfer is within partition. 49154881Storek * If it starts at the end, return EOF; if 49254881Storek * it extends past the end, truncate it. 49354881Storek */ 49454881Storek p = &sc->sc_dk.dk_label.d_partitions[sdpart(bp->b_dev)]; 49554881Storek if ((unsigned)bn >= p->p_size) { 49654881Storek if ((unsigned)bn > p->p_size) { 49754881Storek bp->b_error = EINVAL; 49854881Storek bp->b_flags |= B_ERROR; 49954881Storek } else 50054881Storek bp->b_resid = bp->b_bcount; 50154881Storek biodone(bp); 50254881Storek return; 50354881Storek } 50454881Storek if (bn + sz > p->p_size) { 50554881Storek sz = p->p_size - bn; 50654881Storek bp->b_bcount = dbtob(sz); 50754881Storek } 50854881Storek /* 50954881Storek * Non-aligned or partial-block transfers handled specially. 51054881Storek * SHOULD THIS BE AT A HIGHER LEVEL? 51154881Storek */ 51254881Storek s = sc->sc_blksize - 1; 51354881Storek if ((dbtob(bn) & s) || (bp->b_bcount & s)) { 51454881Storek sdlblkstrat(bp, sc->sc_blksize); 51554881Storek return; 51654881Storek } 51754881Storek bp->b_cylin = (bn + p->p_offset) >> sc->sc_bshift; 51854881Storek } 51954881Storek 52054881Storek /* 52154881Storek * Transfer valid, or format mode. Queue the request 52254881Storek * on the drive, and maybe try to start it. 52354881Storek */ 52454881Storek s = splbio(); 52554881Storek disksort(&sc->sc_tab, bp); 52654881Storek if (sc->sc_tab.b_active == 0) { 52754881Storek sc->sc_tab.b_active = 1; 52854881Storek sdstart(sc, bp); 52954881Storek } 53054881Storek splx(s); 53154881Storek } 53254881Storek 53354881Storek int 53454881Storek sderror(sc, stat) 53554881Storek register struct sd_softc *sc; 53654881Storek register int stat; 53754881Storek { 53854881Storek register struct scsi_sense *sn; 53954881Storek int retry = 0; 54054881Storek 54154881Storek sc->sc_sense.status = stat; 54254881Storek if ((stat & STS_MASK) == STS_CHECKCOND) { 54354881Storek sn = (struct scsi_sense *)sc->sc_sense.sense; 54454881Storek stat = scsi_request_sense(sc->sc_unit.u_hba, 54554881Storek sc->sc_unit.u_targ, sc->sc_unit.u_unit, 54654881Storek (caddr_t)sn, sizeof sc->sc_sense.sense); 54754881Storek sc->sc_sense.status = stat; /* ??? */ 54854881Storek if ((stat & STS_MASK) != STS_GOOD) { 54954881Storek printf("%s: sense failed, status %x\n", 55054881Storek sc->sc_dk.dk_dev.dv_xname, stat); 55154881Storek return (0); 55254881Storek } 55354881Storek printf("%s: scsi sense class %d, code %d", 55454881Storek sc->sc_dk.dk_dev.dv_xname, 55554881Storek SENSE_ECLASS(sn), SENSE_ECODE(sn)); 55654881Storek if (SENSE_ISXSENSE(sn) && XSENSE_ISSTD(sn)) { 55754881Storek int key; 55854881Storek 55954881Storek /* 56054881Storek * Standard extended sense: can examine sense key 56154881Storek * and (if valid) info. 56254881Storek */ 56354881Storek key = XSENSE_KEY(sn); 56454881Storek printf(", key %d", key); 56554881Storek if (XSENSE_IVALID(sn)) 56654881Storek printf(", blk %d", XSENSE_INFO(sn)); 56754881Storek /* no sense or recovered error, try again */ 56854881Storek if (key == 0 || key == 1) 56954881Storek retry = 1; 57054881Storek } 57154881Storek printf("\n"); 57254881Storek } 57354881Storek return (retry); 57454881Storek } 57554881Storek 57654881Storek /* 57754881Storek * sdigo is called from the hba driver when it has got the scsi bus 57854881Storek * for us, and we were doing a format op that did not need dma. 57954881Storek */ 58054881Storek void 58154881Storek sdigo(sc0, cdb) 58254881Storek struct device *sc0; 58354881Storek struct scsi_cdb *cdb; 58454881Storek { 58554881Storek register struct sd_softc *sc = (struct sd_softc *)sc0; 58654881Storek register struct buf *bp = sc->sc_tab.b_actf; 58754881Storek register int stat; 58854881Storek 58954881Storek stat = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba, 59054881Storek sc->sc_unit.u_targ, &sc->sc_cmd, bp->b_un.b_addr, bp->b_bcount, 59154881Storek bp->b_flags & B_READ); 59254881Storek sc->sc_sense.status = stat; 59354881Storek if (stat & 0xfe) { /* XXX */ 59454881Storek (void) sderror(sc, stat); 59554881Storek bp->b_flags |= B_ERROR; 59654881Storek bp->b_error = EIO; 59754881Storek } 59854881Storek /* 59954881Storek * Done with SCSI bus, before we `ought' to be. Release it. 60054881Storek */ 60154881Storek (*sc->sc_unit.u_rel)(sc->sc_unit.u_updev); 60254881Storek bp->b_resid = 0; 60354881Storek sc->sc_tab.b_errcnt = 0; 60454881Storek sc->sc_tab.b_actf = bp->b_actf; 60554881Storek biodone(bp); 60654881Storek if ((bp = sc->sc_tab.b_actf) == NULL) 60754881Storek sc->sc_tab.b_active = 0; 60854881Storek else 60954881Storek sdstart(sc, bp); 61054881Storek } 61154881Storek 61254881Storek /* 61354881Storek * sdgo is called from the hba driver or target code when it has 61454881Storek * allocated the scsi bus and DMA resources and target datapath for us. 61554881Storek */ 61654881Storek void 61754881Storek sdgo(sc0, cdb) 61854881Storek struct device *sc0; 61954881Storek register struct scsi_cdb *cdb; 62054881Storek { 62154881Storek register struct sd_softc *sc = (struct sd_softc *)sc0; 62254881Storek register struct buf *bp = sc->sc_tab.b_actf; 62354881Storek register int n; 62454881Storek register unsigned int u; 62554881Storek 62654881Storek SD_TRACE(T_MKCDB, sc, bp); 62754881Storek if (sc->sc_format_pid) { 62854881Storek *cdb = sc->sc_cmd; 62954881Storek n = 0; 63054881Storek } else { 63154881Storek CDB10(cdb)->cdb_cmd = bp->b_flags & B_READ ? CMD_READ10 : 63254881Storek CMD_WRITE10; 63354881Storek CDB10(cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5; 63454881Storek u = bp->b_cylin; 63554881Storek CDB10(cdb)->cdb_lbah = u >> 24; 63654881Storek CDB10(cdb)->cdb_lbahm = u >> 16; 63754881Storek CDB10(cdb)->cdb_lbalm = u >> 8; 63854881Storek CDB10(cdb)->cdb_lbal = u; 63954881Storek CDB10(cdb)->cdb_xxx = 0; 64054881Storek n = sc->sc_blksize - 1; 64154881Storek u = (bp->b_bcount + n) >> (DEV_BSHIFT + sc->sc_bshift); 64254881Storek CDB10(cdb)->cdb_lenh = u >> 8; 64354881Storek CDB10(cdb)->cdb_lenl = u; 64454881Storek CDB10(cdb)->cdb_ctrl = 0; 64554881Storek n = (bp->b_bcount & n) != 0; 64654881Storek #ifdef DEBUG 64754881Storek if (n) 64854881Storek printf("%s: partial block xfer -- %x bytes\n", 64954881Storek sc->sc_dk.dk_dev.dv_xname, bp->b_bcount); 65054881Storek #endif 65154881Storek sc->sc_transfers++; 65254881Storek } 65354881Storek if ((*sc->sc_unit.u_go)(sc->sc_unit.u_updev, sc->sc_unit.u_targ, 65454881Storek sdintr, (void *)sc, bp, n) == 0) { 65554881Storek #ifdef notyet 65654881Storek sc->sc_dk.dk_busy = 1; 65754881Storek sc->sc_dk.dk_seek++; /* XXX */ 65854881Storek sc->sc_dk.dk_xfer++; 65954881Storek sc->sc_dk.dk_wds += bp->b_bcount >> 6; 66054881Storek #endif 66154881Storek return; 66254881Storek } 66354881Storek /* 66454881Storek * Some sort of nasty unrecoverable error: clobber the 66554881Storek * transfer. Call the bus release function first, though. 66654881Storek */ 66754881Storek (*sc->sc_unit.u_rel)(sc->sc_unit.u_updev); 66854881Storek #ifdef DEBUG 66954881Storek if (sddebug & SDB_ERROR) 67054881Storek printf("%s: sdgo: %s adr %d blk %d len %d ecnt %d\n", 67154881Storek sc->sc_dk.dk_dev.dv_xname, 67254881Storek bp->b_flags & B_READ? "read" : "write", 67354881Storek bp->b_un.b_addr, bp->b_cylin, bp->b_bcount, 67454881Storek sc->sc_tab.b_errcnt); 67554881Storek #endif 67654881Storek bp->b_flags |= B_ERROR; 67754881Storek bp->b_error = EIO; 67854881Storek bp->b_resid = 0; 67954881Storek sc->sc_tab.b_errcnt = 0; 68054881Storek sc->sc_tab.b_actf = bp->b_actf; 68154881Storek biodone(bp); 68254881Storek if ((bp = sc->sc_tab.b_actf) == NULL) 68354881Storek sc->sc_tab.b_active = 0; 68454881Storek else 68554881Storek sdstart(sc, bp); 68654881Storek } 68754881Storek 68854881Storek /* 68954881Storek * A transfer finished (or, someday, disconnected). 69054881Storek * We are already off the target/hba queues. 69154881Storek * Restart this one for error recovery, or start the next, as appropriate. 69254881Storek */ 69354881Storek void 69454881Storek sdintr(sc0, stat, resid) 69554881Storek struct device *sc0; 69654881Storek int stat, resid; 69754881Storek { 69854881Storek register struct sd_softc *sc = (struct sd_softc *)sc0; 69954881Storek register struct buf *bp = sc->sc_tab.b_actf; 70054881Storek int retry; 70154881Storek 70254881Storek if (bp == NULL) 70354881Storek panic("sdintr"); 70454881Storek SD_TRACE(T_INTR, sc, bp); 70554881Storek #ifdef notyet 70654881Storek sc->sc_dk.dk_busy = 0; 70754881Storek #endif 70854881Storek if ((stat & STS_MASK) != STS_GOOD) { 70954881Storek #ifdef DEBUG 71054881Storek if (sddebug & SDB_ERROR) 71154881Storek printf("%s: sdintr scsi status 0x%x resid %d\n", 71254881Storek sc->sc_dk.dk_dev.dv_xname, stat, resid); 71354881Storek #endif 71454881Storek retry = sderror(sc, stat); 71554881Storek if (retry && ++sc->sc_tab.b_errcnt <= SDRETRY) { 71654881Storek printf("%s: retry %d\n", 71754881Storek sc->sc_dk.dk_dev.dv_xname, sc->sc_tab.b_errcnt); 71854881Storek goto restart; 71954881Storek } 72054881Storek bp->b_flags |= B_ERROR; 72154881Storek bp->b_error = EIO; 72254881Storek } 72354881Storek bp->b_resid = resid; 72454881Storek sc->sc_tab.b_errcnt = 0; 72554881Storek sc->sc_tab.b_actf = bp->b_actf; 72654881Storek biodone(bp); 72754881Storek if ((bp = sc->sc_tab.b_actf) == NULL) 72854881Storek sc->sc_tab.b_active = 0; 72954881Storek else { 73054881Storek restart: 73154881Storek sdstart(sc, bp); 73254881Storek } 73354881Storek } 73454881Storek 73554881Storek int 73654881Storek sdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p) 73754881Storek { 73854881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)]; 73954881Storek #ifdef COMPAT_SUNOS 74054881Storek int error; 74154881Storek 74254881Storek error = sun_dkioctl(&sc->sc_dk, cmd, data, sdpart(dev)); 74354881Storek if (error >= 0) 74454881Storek return (error); 74554881Storek #endif 74654881Storek switch (cmd) { 74754881Storek 74854881Storek case SDIOCSFORMAT: 74954881Storek /* take this device into or out of "format" mode */ 75054881Storek if (!suser(p->p_ucred, &p->p_acflag)) 75154881Storek return (EPERM); 75254881Storek if (*(int *)data) { 75354881Storek if (sc->sc_format_pid) 75454881Storek return (EPERM); 75554881Storek sc->sc_format_pid = p->p_pid; 75654881Storek } else 75754881Storek sc->sc_format_pid = 0; 75854881Storek break; 75954881Storek 76054881Storek case SDIOCGFORMAT: 76154881Storek /* find out who has the device in format mode */ 76254881Storek *(int *)data = sc->sc_format_pid; 76354881Storek break; 76454881Storek 76554881Storek case SDIOCSCSICOMMAND: 76654881Storek #define cdb ((struct scsi_cdb *)data) 76754881Storek /* 76854881Storek * Save what user gave us as SCSI cdb to use with next 769*56900Storek * read or write to the char device. Be sure to replace 770*56900Storek * the lun field with the actual unit number. 77154881Storek */ 77254881Storek if (sc->sc_format_pid != p->p_pid) 77354881Storek return (EPERM); 77454881Storek if (legal_cmds[cdb->cdb_bytes[0]] == 0) 77554881Storek return (EINVAL); 77654881Storek sc->sc_cmd = *cdb; 777*56900Storek sc->sc_cmd.cdb_bytes[1] = 778*56900Storek (sc->sc_cmd.cdb_bytes[1] & ~(7 << 5)) | 779*56900Storek (sc->sc_unit.u_unit << 5); 78054881Storek #undef cdb 78154881Storek break; 78254881Storek 78354881Storek case SDIOCSENSE: 78454881Storek /* 78554881Storek * return the SCSI sense data saved after the last 78654881Storek * operation that completed with "check condition" status. 78754881Storek */ 78854881Storek sc->sc_sense = *(struct scsi_fmt_sense *)data; 78954881Storek break; 79054881Storek 79154881Storek default: 79254881Storek return (ENOTTY); 79354881Storek } 79454881Storek return (0); 79554881Storek } 79654881Storek 79754881Storek int 79854881Storek sdsize(dev_t dev) 79954881Storek { 80054881Storek register int unit = sdunit(dev); 80154881Storek register struct sd_softc *sc; 80254881Storek 80354881Storek if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL || 80454881Storek (sc->sc_flags & SDF_ALIVE) == 0) 80554881Storek return (-1); 80654881Storek return (sc->sc_dk.dk_label.d_partitions[sdpart(dev)].p_size); 80754881Storek } 80854881Storek 80954881Storek /* 81054881Storek * Write `len' bytes from address `addr' to drive and partition in `dev', 81154881Storek * at block blkoff from the beginning of the partition. The address is 81254881Storek * either kernel virtual or physical (some machines may never use one or 81354881Storek * the other, but we need it in the protocol to stay machine-independent). 81454881Storek */ 81554881Storek int 81654881Storek sddump(dev_t dev, daddr_t blkoff, caddr_t addr, int len) 81754881Storek { 81854881Storek register struct sd_softc *sc; 81954881Storek register struct partition *p; 82054881Storek register daddr_t bn, n, nblks; 82154881Storek register struct hba_softc *hba; 82254881Storek register int stat, unit; 82354881Storek struct scsi_cdb cdb; 82454881Storek 82554881Storek /* drive ok? */ 82654881Storek unit = sdunit(dev); 82754881Storek if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL || 82854881Storek (sc->sc_flags & SDF_ALIVE) == 0) 82954881Storek return (ENXIO); 83054881Storek 83154881Storek /* blocks in range? */ 83254881Storek p = &sc->sc_dk.dk_label.d_partitions[sdpart(dev)]; 83354881Storek n = (len + sc->sc_blksize - 1) >> DEV_BSHIFT; 83454881Storek if (blkoff < 0 || blkoff >= p->p_size || blkoff + n > p->p_size) 83554881Storek return (EINVAL); 83654881Storek bn = blkoff + p->p_offset; 83754881Storek bn >>= sc->sc_bshift; 83854881Storek 83954881Storek /* scsi bus idle? */ 84054881Storek hba = sc->sc_unit.u_hba; 84154881Storek if (hba->hba_head) { 84254881Storek (*hba->hba_driver->hd_reset)(hba, 0); 84354881Storek printf("[reset %s] ", sc->sc_dk.dk_dev.dv_xname); 84454881Storek } 84554881Storek 84654881Storek CDB10(&cdb)->cdb_cmd = CMD_WRITE10; 84754881Storek CDB10(&cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5; 84854881Storek CDB10(&cdb)->cdb_xxx = 0; 84954881Storek CDB10(&cdb)->cdb_ctrl = 0; 85054881Storek 85154881Storek #define DUMP_MAX (32 * 1024) /* no more than 32k per write */ 85254881Storek for (;;) { 85354881Storek if ((n = len) > DUMP_MAX) 85454881Storek n = DUMP_MAX; 85554881Storek CDB10(&cdb)->cdb_lbah = bn >> 24; 85654881Storek CDB10(&cdb)->cdb_lbahm = bn >> 16; 85754881Storek CDB10(&cdb)->cdb_lbalm = bn >> 8; 85854881Storek CDB10(&cdb)->cdb_lbal = bn; 85954881Storek nblks = n >> (DEV_BSHIFT + sc->sc_bshift); 86054881Storek CDB10(&cdb)->cdb_lenh = nblks >> 8; 86154881Storek CDB10(&cdb)->cdb_lenl = nblks; 86254881Storek stat = hba->hba_driver->hd_dump(hba, sc->sc_unit.u_targ, 86354881Storek &cdb, addr, n); 86454881Storek if ((stat & STS_MASK) != STS_GOOD) { 86554881Storek printf("%s: scsi write error 0x%x\ndump ", 86654881Storek sc->sc_dk.dk_dev.dv_xname, stat); 86754881Storek return (EIO); 86854881Storek } 86954881Storek if ((len -= n) == 0) 87054881Storek return (0); 87154881Storek addr += n; 87254881Storek bn += nblks; 87354881Storek } 87454881Storek } 875