154881Storek /*
2*63144Sbostic * Copyright (c) 1990, 1992, 1993
3*63144Sbostic * The Regents of the University of California. 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
1256900Storek * California, Lawrence Berkeley Laboratory.
1355559Storek *
1454881Storek * %sccs.include.redist.c%
1554881Storek *
16*63144Sbostic * @(#)sd.c 8.1 (Berkeley) 06/10/93
1754881Storek *
1859479Storek * from: $Header: sd.c,v 1.27 93/04/29 01:22:19 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
4156900Storek #include <dev/scsi/scsi.h>
4256900Storek #include <dev/scsi/disk.h>
4356900Storek #include <dev/scsi/scsivar.h>
4456900Storek #include <dev/scsi/scsi_ioctl.h>
4556900Storek
4655559Storek #include <machine/cpu.h>
4754881Storek
4856900Storek #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
10856900Storek 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
sdmatch(parent,cf,aux)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
sdattach(parent,self,aux)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 {
26256900Storek /* 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
28156900Storek sc->sc_dk.dk_driver = &sddkdriver;
28256900Storek #ifdef notyet
28356900Storek dk_establish(&sc->sc_dk);
28456900Storek /* READ DISK LABEL HERE, UNLESS REMOVABLE MEDIUM... NEEDS THOUGHT */
28556900Storek #else
28654881Storek sc->sc_dk.dk_label.d_secsize = 512; /* XXX */
28756900Storek 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
30756900Storek #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
sdreset(u)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
sdopen(dev_t dev,int flags,int ifmt,struct proc * p)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);
33459479Storek if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
33554881Storek return (ENXIO);
33654881Storek return (0);
33754881Storek }
33854881Storek
33954881Storek int
sdclose(dev_t dev,int flags,int ifmt,struct proc * p)34054881Storek sdclose(dev_t dev, int flags, int ifmt, struct proc *p)
34154881Storek {
34254881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
34354881Storek
34454881Storek sc->sc_format_pid = 0;
34554881Storek return (0);
34654881Storek }
34754881Storek
34854881Storek /*
34954881Storek * This routine is called for partial block transfers and non-aligned
35054881Storek * transfers (the latter only being possible on devices with a block size
35154881Storek * larger than DEV_BSIZE). The operation is performed in three steps
35254881Storek * using a locally allocated buffer:
35354881Storek * 1. transfer any initial partial block
35454881Storek * 2. transfer full blocks
35554881Storek * 3. transfer any final partial block
35654881Storek */
35754881Storek static void
sdlblkstrat(bp,bsize)35854881Storek sdlblkstrat(bp, bsize)
35954881Storek register struct buf *bp;
36054881Storek register int bsize;
36154881Storek {
36254881Storek register int bn, resid, boff, count;
36354881Storek register caddr_t addr, cbuf;
36456900Storek struct buf *tbp;
36554881Storek
36656900Storek /* should probably use geteblk() here, but I fear consequences */
36754881Storek cbuf = (caddr_t)malloc(bsize, M_DEVBUF, M_WAITOK);
36856900Storek tbp = (struct buf *)malloc(sizeof *tbp, M_DEVBUF, M_WAITOK);
36956900Storek bzero((caddr_t)tbp, sizeof *tbp);
37056900Storek tbp->b_proc = curproc;
37156900Storek tbp->b_dev = bp->b_dev;
37254881Storek bn = bp->b_blkno;
37354881Storek resid = bp->b_bcount;
37454881Storek addr = bp->b_un.b_addr;
37554881Storek #ifdef DEBUG
37654881Storek if (sddebug & SDB_PARTIAL)
37754881Storek printf("sdlblkstrat: bp %x flags %x bn %x resid %x addr %x\n",
37854881Storek bp, bp->b_flags, bn, resid, addr);
37954881Storek #endif
38054881Storek
38154881Storek while (resid > 0) {
38254881Storek boff = dbtob(bn) & (bsize - 1);
38354881Storek if (boff || resid < bsize) {
38454881Storek struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
38554881Storek sc->sc_partials++;
38655161Spendry count = min(resid, bsize - boff);
38756900Storek tbp->b_flags = B_BUSY | B_READ;
38856900Storek tbp->b_blkno = bn - btodb(boff);
38956900Storek tbp->b_un.b_addr = cbuf;
39056900Storek tbp->b_bcount = bsize;
39154881Storek #ifdef DEBUG
39254881Storek if (sddebug & SDB_PARTIAL)
39354881Storek printf(" readahead: bn %x cnt %x off %x addr %x\n",
39456900Storek tbp->b_blkno, count, boff, addr);
39554881Storek #endif
39656900Storek sdstrategy(tbp);
39756900Storek biowait(tbp);
39856900Storek if (tbp->b_flags & B_ERROR) {
39954881Storek bp->b_flags |= B_ERROR;
40056900Storek bp->b_error = tbp->b_error;
40154881Storek break;
40254881Storek }
40354881Storek if (bp->b_flags & B_READ) {
40454881Storek bcopy(&cbuf[boff], addr, count);
40554881Storek goto done;
40654881Storek }
40754881Storek bcopy(addr, &cbuf[boff], count);
40854881Storek #ifdef DEBUG
40954881Storek if (sddebug & SDB_PARTIAL)
41054881Storek printf(" writeback: bn %x cnt %x off %x addr %x\n",
41156900Storek tbp->b_blkno, count, boff, addr);
41254881Storek #endif
41354881Storek } else {
41454881Storek count = resid & ~(bsize - 1);
41556900Storek tbp->b_blkno = bn;
41656900Storek tbp->b_un.b_addr = addr;
41756900Storek tbp->b_bcount = count;
41854881Storek #ifdef DEBUG
41954881Storek if (sddebug & SDB_PARTIAL)
42054881Storek printf(" fulltrans: bn %x cnt %x addr %x\n",
42156900Storek tbp->b_blkno, count, addr);
42254881Storek #endif
42354881Storek }
42456900Storek tbp->b_flags = B_BUSY | (bp->b_flags & B_READ);
42556900Storek sdstrategy(tbp);
42656900Storek biowait(tbp);
42756900Storek if (tbp->b_flags & B_ERROR) {
42854881Storek bp->b_flags |= B_ERROR;
42956900Storek bp->b_error = tbp->b_error;
43054881Storek break;
43154881Storek }
43254881Storek done:
43354881Storek bn += btodb(count);
43454881Storek resid -= count;
43554881Storek addr += count;
43654881Storek #ifdef DEBUG
43754881Storek if (sddebug & SDB_PARTIAL)
43854881Storek printf(" done: bn %x resid %x addr %x\n",
43954881Storek bn, resid, addr);
44054881Storek #endif
44154881Storek }
44254881Storek free(cbuf, M_DEVBUF);
44356900Storek free((caddr_t)tbp, M_DEVBUF);
44454881Storek biodone(bp);
44554881Storek }
44654881Storek
44754881Storek /*
44854881Storek * Start a transfer on sc as described by bp
44954881Storek * (i.e., call hba or target start).
45054881Storek * If in format mode, we may not need dma.
45154881Storek */
45254881Storek #define sdstart(sc, bp) { \
45354881Storek SD_TRACE(T_START, sc, bp); \
45454881Storek if ((sc)->sc_format_pid && legal_cmds[(sc)->sc_cmd.cdb_bytes[0]] > 0) \
45554881Storek (*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
45654881Storek &(sc)->sc_unit.u_forw, (struct buf *)NULL, \
45754881Storek sdigo, &(sc)->sc_dk.dk_dev); \
45854881Storek else \
45954881Storek (*(sc)->sc_unit.u_start)((sc)->sc_unit.u_updev, \
46054881Storek &(sc)->sc_unit.u_forw, bp, sdgo, &(sc)->sc_dk.dk_dev); \
46154881Storek }
46254881Storek
46354881Storek void
sdstrategy(bp)46454881Storek sdstrategy(bp)
46554881Storek register struct buf *bp;
46654881Storek {
46754881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(bp->b_dev)];
46854881Storek register int s;
46954881Storek
47054881Storek if (sc->sc_format_pid) {
47154881Storek /* XXXXXXXXX SHOULD NOT COMPARE curproc IN HERE!?! */
47254881Storek /*
47354881Storek * In format mode, only allow the owner to mess
47454881Storek * with the drive. Skip all the partition checks.
47554881Storek */
47654881Storek if (sc->sc_format_pid != curproc->p_pid) {
47754881Storek bp->b_error = EPERM;
47854881Storek bp->b_flags |= B_ERROR;
47954881Storek biodone(bp);
48054881Storek return;
48154881Storek }
48254881Storek bp->b_cylin = 0;
48354881Storek } else {
48454881Storek register daddr_t bn = bp->b_blkno;
48554881Storek register int sz = howmany(bp->b_bcount, DEV_BSIZE);
48654881Storek register struct partition *p;
48754881Storek
48854881Storek /*
48954881Storek * Make sure transfer is within partition.
49054881Storek * If it starts at the end, return EOF; if
49154881Storek * it extends past the end, truncate it.
49254881Storek */
49354881Storek p = &sc->sc_dk.dk_label.d_partitions[sdpart(bp->b_dev)];
49454881Storek if ((unsigned)bn >= p->p_size) {
49554881Storek if ((unsigned)bn > p->p_size) {
49654881Storek bp->b_error = EINVAL;
49754881Storek bp->b_flags |= B_ERROR;
49854881Storek } else
49954881Storek bp->b_resid = bp->b_bcount;
50054881Storek biodone(bp);
50154881Storek return;
50254881Storek }
50354881Storek if (bn + sz > p->p_size) {
50454881Storek sz = p->p_size - bn;
50554881Storek bp->b_bcount = dbtob(sz);
50654881Storek }
50754881Storek /*
50854881Storek * Non-aligned or partial-block transfers handled specially.
50954881Storek * SHOULD THIS BE AT A HIGHER LEVEL?
51054881Storek */
51154881Storek s = sc->sc_blksize - 1;
51254881Storek if ((dbtob(bn) & s) || (bp->b_bcount & s)) {
51354881Storek sdlblkstrat(bp, sc->sc_blksize);
51454881Storek return;
51554881Storek }
51654881Storek bp->b_cylin = (bn + p->p_offset) >> sc->sc_bshift;
51754881Storek }
51854881Storek
51954881Storek /*
52054881Storek * Transfer valid, or format mode. Queue the request
52154881Storek * on the drive, and maybe try to start it.
52254881Storek */
52354881Storek s = splbio();
52454881Storek disksort(&sc->sc_tab, bp);
52554881Storek if (sc->sc_tab.b_active == 0) {
52654881Storek sc->sc_tab.b_active = 1;
52754881Storek sdstart(sc, bp);
52854881Storek }
52954881Storek splx(s);
53054881Storek }
53154881Storek
53254881Storek int
sderror(sc,stat)53354881Storek sderror(sc, stat)
53454881Storek register struct sd_softc *sc;
53554881Storek register int stat;
53654881Storek {
53754881Storek register struct scsi_sense *sn;
53854881Storek int retry = 0;
53954881Storek
54054881Storek sc->sc_sense.status = stat;
54154881Storek if ((stat & STS_MASK) == STS_CHECKCOND) {
54254881Storek sn = (struct scsi_sense *)sc->sc_sense.sense;
54354881Storek stat = scsi_request_sense(sc->sc_unit.u_hba,
54454881Storek sc->sc_unit.u_targ, sc->sc_unit.u_unit,
54554881Storek (caddr_t)sn, sizeof sc->sc_sense.sense);
54654881Storek sc->sc_sense.status = stat; /* ??? */
54754881Storek if ((stat & STS_MASK) != STS_GOOD) {
54854881Storek printf("%s: sense failed, status %x\n",
54954881Storek sc->sc_dk.dk_dev.dv_xname, stat);
55054881Storek return (0);
55154881Storek }
55254881Storek printf("%s: scsi sense class %d, code %d",
55354881Storek sc->sc_dk.dk_dev.dv_xname,
55454881Storek SENSE_ECLASS(sn), SENSE_ECODE(sn));
55554881Storek if (SENSE_ISXSENSE(sn) && XSENSE_ISSTD(sn)) {
55654881Storek int key;
55754881Storek
55854881Storek /*
55954881Storek * Standard extended sense: can examine sense key
56054881Storek * and (if valid) info.
56154881Storek */
56254881Storek key = XSENSE_KEY(sn);
56354881Storek printf(", key %d", key);
56454881Storek if (XSENSE_IVALID(sn))
56554881Storek printf(", blk %d", XSENSE_INFO(sn));
56654881Storek /* no sense or recovered error, try again */
56754881Storek if (key == 0 || key == 1)
56854881Storek retry = 1;
56954881Storek }
57054881Storek printf("\n");
57154881Storek }
57254881Storek return (retry);
57354881Storek }
57454881Storek
57554881Storek /*
57654881Storek * sdigo is called from the hba driver when it has got the scsi bus
57754881Storek * for us, and we were doing a format op that did not need dma.
57854881Storek */
57954881Storek void
sdigo(sc0,cdb)58054881Storek sdigo(sc0, cdb)
58154881Storek struct device *sc0;
58254881Storek struct scsi_cdb *cdb;
58354881Storek {
58454881Storek register struct sd_softc *sc = (struct sd_softc *)sc0;
58554881Storek register struct buf *bp = sc->sc_tab.b_actf;
58654881Storek register int stat;
58754881Storek
58854881Storek stat = (*sc->sc_unit.u_hbd->hd_icmd)(sc->sc_unit.u_hba,
58954881Storek sc->sc_unit.u_targ, &sc->sc_cmd, bp->b_un.b_addr, bp->b_bcount,
59054881Storek bp->b_flags & B_READ);
59154881Storek sc->sc_sense.status = stat;
59254881Storek if (stat & 0xfe) { /* XXX */
59354881Storek (void) sderror(sc, stat);
59454881Storek bp->b_flags |= B_ERROR;
59554881Storek bp->b_error = EIO;
59654881Storek }
59754881Storek /*
59854881Storek * Done with SCSI bus, before we `ought' to be. Release it.
59954881Storek */
60054881Storek (*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
60154881Storek bp->b_resid = 0;
60254881Storek sc->sc_tab.b_errcnt = 0;
60354881Storek sc->sc_tab.b_actf = bp->b_actf;
60454881Storek biodone(bp);
60554881Storek if ((bp = sc->sc_tab.b_actf) == NULL)
60654881Storek sc->sc_tab.b_active = 0;
60754881Storek else
60854881Storek sdstart(sc, bp);
60954881Storek }
61054881Storek
61154881Storek /*
61254881Storek * sdgo is called from the hba driver or target code when it has
61354881Storek * allocated the scsi bus and DMA resources and target datapath for us.
61454881Storek */
61554881Storek void
sdgo(sc0,cdb)61654881Storek sdgo(sc0, cdb)
61754881Storek struct device *sc0;
61854881Storek register struct scsi_cdb *cdb;
61954881Storek {
62054881Storek register struct sd_softc *sc = (struct sd_softc *)sc0;
62154881Storek register struct buf *bp = sc->sc_tab.b_actf;
62254881Storek register int n;
62354881Storek register unsigned int u;
62454881Storek
62554881Storek SD_TRACE(T_MKCDB, sc, bp);
62654881Storek if (sc->sc_format_pid) {
62754881Storek *cdb = sc->sc_cmd;
62854881Storek n = 0;
62954881Storek } else {
63054881Storek CDB10(cdb)->cdb_cmd = bp->b_flags & B_READ ? CMD_READ10 :
63154881Storek CMD_WRITE10;
63254881Storek CDB10(cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
63354881Storek u = bp->b_cylin;
63454881Storek CDB10(cdb)->cdb_lbah = u >> 24;
63554881Storek CDB10(cdb)->cdb_lbahm = u >> 16;
63654881Storek CDB10(cdb)->cdb_lbalm = u >> 8;
63754881Storek CDB10(cdb)->cdb_lbal = u;
63854881Storek CDB10(cdb)->cdb_xxx = 0;
63954881Storek n = sc->sc_blksize - 1;
64054881Storek u = (bp->b_bcount + n) >> (DEV_BSHIFT + sc->sc_bshift);
64154881Storek CDB10(cdb)->cdb_lenh = u >> 8;
64254881Storek CDB10(cdb)->cdb_lenl = u;
64354881Storek CDB10(cdb)->cdb_ctrl = 0;
64454881Storek n = (bp->b_bcount & n) != 0;
64554881Storek #ifdef DEBUG
64654881Storek if (n)
64754881Storek printf("%s: partial block xfer -- %x bytes\n",
64854881Storek sc->sc_dk.dk_dev.dv_xname, bp->b_bcount);
64954881Storek #endif
65054881Storek sc->sc_transfers++;
65154881Storek }
65254881Storek if ((*sc->sc_unit.u_go)(sc->sc_unit.u_updev, sc->sc_unit.u_targ,
65354881Storek sdintr, (void *)sc, bp, n) == 0) {
65454881Storek #ifdef notyet
65554881Storek sc->sc_dk.dk_busy = 1;
65654881Storek sc->sc_dk.dk_seek++; /* XXX */
65754881Storek sc->sc_dk.dk_xfer++;
65854881Storek sc->sc_dk.dk_wds += bp->b_bcount >> 6;
65954881Storek #endif
66054881Storek return;
66154881Storek }
66254881Storek /*
66354881Storek * Some sort of nasty unrecoverable error: clobber the
66454881Storek * transfer. Call the bus release function first, though.
66554881Storek */
66654881Storek (*sc->sc_unit.u_rel)(sc->sc_unit.u_updev);
66754881Storek #ifdef DEBUG
66854881Storek if (sddebug & SDB_ERROR)
66954881Storek printf("%s: sdgo: %s adr %d blk %d len %d ecnt %d\n",
67054881Storek sc->sc_dk.dk_dev.dv_xname,
67154881Storek bp->b_flags & B_READ? "read" : "write",
67254881Storek bp->b_un.b_addr, bp->b_cylin, bp->b_bcount,
67354881Storek sc->sc_tab.b_errcnt);
67454881Storek #endif
67554881Storek bp->b_flags |= B_ERROR;
67654881Storek bp->b_error = EIO;
67754881Storek bp->b_resid = 0;
67854881Storek sc->sc_tab.b_errcnt = 0;
67954881Storek sc->sc_tab.b_actf = bp->b_actf;
68054881Storek biodone(bp);
68154881Storek if ((bp = sc->sc_tab.b_actf) == NULL)
68254881Storek sc->sc_tab.b_active = 0;
68354881Storek else
68454881Storek sdstart(sc, bp);
68554881Storek }
68654881Storek
68754881Storek /*
68854881Storek * A transfer finished (or, someday, disconnected).
68954881Storek * We are already off the target/hba queues.
69054881Storek * Restart this one for error recovery, or start the next, as appropriate.
69154881Storek */
69254881Storek void
sdintr(sc0,stat,resid)69354881Storek sdintr(sc0, stat, resid)
69454881Storek struct device *sc0;
69554881Storek int stat, resid;
69654881Storek {
69754881Storek register struct sd_softc *sc = (struct sd_softc *)sc0;
69854881Storek register struct buf *bp = sc->sc_tab.b_actf;
69954881Storek int retry;
70054881Storek
70154881Storek if (bp == NULL)
70254881Storek panic("sdintr");
70354881Storek SD_TRACE(T_INTR, sc, bp);
70454881Storek #ifdef notyet
70554881Storek sc->sc_dk.dk_busy = 0;
70654881Storek #endif
70754881Storek if ((stat & STS_MASK) != STS_GOOD) {
70854881Storek #ifdef DEBUG
70954881Storek if (sddebug & SDB_ERROR)
71054881Storek printf("%s: sdintr scsi status 0x%x resid %d\n",
71154881Storek sc->sc_dk.dk_dev.dv_xname, stat, resid);
71254881Storek #endif
71354881Storek retry = sderror(sc, stat);
71454881Storek if (retry && ++sc->sc_tab.b_errcnt <= SDRETRY) {
71554881Storek printf("%s: retry %d\n",
71654881Storek sc->sc_dk.dk_dev.dv_xname, sc->sc_tab.b_errcnt);
71754881Storek goto restart;
71854881Storek }
71954881Storek bp->b_flags |= B_ERROR;
72054881Storek bp->b_error = EIO;
72154881Storek }
72254881Storek bp->b_resid = resid;
72354881Storek sc->sc_tab.b_errcnt = 0;
72454881Storek sc->sc_tab.b_actf = bp->b_actf;
72554881Storek biodone(bp);
72654881Storek if ((bp = sc->sc_tab.b_actf) == NULL)
72754881Storek sc->sc_tab.b_active = 0;
72854881Storek else {
72954881Storek restart:
73054881Storek sdstart(sc, bp);
73154881Storek }
73254881Storek }
73354881Storek
73454881Storek int
sdioctl(dev_t dev,int cmd,register caddr_t data,int flag,struct proc * p)73554881Storek sdioctl(dev_t dev, int cmd, register caddr_t data, int flag, struct proc *p)
73654881Storek {
73754881Storek register struct sd_softc *sc = sdcd.cd_devs[sdunit(dev)];
73854881Storek #ifdef COMPAT_SUNOS
73954881Storek int error;
74054881Storek
74154881Storek error = sun_dkioctl(&sc->sc_dk, cmd, data, sdpart(dev));
74254881Storek if (error >= 0)
74354881Storek return (error);
74454881Storek #endif
74554881Storek switch (cmd) {
74654881Storek
74754881Storek case SDIOCSFORMAT:
74854881Storek /* take this device into or out of "format" mode */
74959479Storek if (suser(p->p_ucred, &p->p_acflag))
75054881Storek return (EPERM);
75154881Storek if (*(int *)data) {
75254881Storek if (sc->sc_format_pid)
75354881Storek return (EPERM);
75454881Storek sc->sc_format_pid = p->p_pid;
75554881Storek } else
75654881Storek sc->sc_format_pid = 0;
75754881Storek break;
75854881Storek
75954881Storek case SDIOCGFORMAT:
76054881Storek /* find out who has the device in format mode */
76154881Storek *(int *)data = sc->sc_format_pid;
76254881Storek break;
76354881Storek
76454881Storek case SDIOCSCSICOMMAND:
76554881Storek #define cdb ((struct scsi_cdb *)data)
76654881Storek /*
76754881Storek * Save what user gave us as SCSI cdb to use with next
76856900Storek * read or write to the char device. Be sure to replace
76956900Storek * the lun field with the actual unit number.
77054881Storek */
77154881Storek if (sc->sc_format_pid != p->p_pid)
77254881Storek return (EPERM);
77354881Storek if (legal_cmds[cdb->cdb_bytes[0]] == 0)
77454881Storek return (EINVAL);
77554881Storek sc->sc_cmd = *cdb;
77656900Storek sc->sc_cmd.cdb_bytes[1] =
77756900Storek (sc->sc_cmd.cdb_bytes[1] & ~(7 << 5)) |
77856900Storek (sc->sc_unit.u_unit << 5);
77954881Storek #undef cdb
78054881Storek break;
78154881Storek
78254881Storek case SDIOCSENSE:
78354881Storek /*
78454881Storek * return the SCSI sense data saved after the last
78554881Storek * operation that completed with "check condition" status.
78654881Storek */
78754881Storek sc->sc_sense = *(struct scsi_fmt_sense *)data;
78854881Storek break;
78954881Storek
79059305Storek case DIOCGDINFO:
79159305Storek *(struct disklabel *)data = sc->sc_dk.dk_label;
79259305Storek break;
79359305Storek
79459305Storek case DIOCGPART:
79559305Storek ((struct partinfo *)data)->disklab = &sc->sc_dk.dk_label;
79659305Storek ((struct partinfo *)data)->part =
79759305Storek &sc->sc_dk.dk_label.d_partitions[sdpart(dev)];
79859305Storek break;
79959305Storek
80054881Storek default:
80154881Storek return (ENOTTY);
80254881Storek }
80354881Storek return (0);
80454881Storek }
80554881Storek
80654881Storek int
sdsize(dev_t dev)80754881Storek sdsize(dev_t dev)
80854881Storek {
80954881Storek register int unit = sdunit(dev);
81054881Storek register struct sd_softc *sc;
81154881Storek
81254881Storek if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
81354881Storek (sc->sc_flags & SDF_ALIVE) == 0)
81454881Storek return (-1);
81554881Storek return (sc->sc_dk.dk_label.d_partitions[sdpart(dev)].p_size);
81654881Storek }
81754881Storek
81854881Storek /*
81954881Storek * Write `len' bytes from address `addr' to drive and partition in `dev',
82054881Storek * at block blkoff from the beginning of the partition. The address is
82154881Storek * either kernel virtual or physical (some machines may never use one or
82254881Storek * the other, but we need it in the protocol to stay machine-independent).
82354881Storek */
82454881Storek int
sddump(dev_t dev,daddr_t blkoff,caddr_t addr,int len)82554881Storek sddump(dev_t dev, daddr_t blkoff, caddr_t addr, int len)
82654881Storek {
82754881Storek register struct sd_softc *sc;
82854881Storek register struct partition *p;
82954881Storek register daddr_t bn, n, nblks;
83054881Storek register struct hba_softc *hba;
83154881Storek register int stat, unit;
83254881Storek struct scsi_cdb cdb;
83354881Storek
83454881Storek /* drive ok? */
83554881Storek unit = sdunit(dev);
83654881Storek if (unit >= sdcd.cd_ndevs || (sc = sdcd.cd_devs[unit]) == NULL ||
83754881Storek (sc->sc_flags & SDF_ALIVE) == 0)
83854881Storek return (ENXIO);
83954881Storek
84054881Storek /* blocks in range? */
84154881Storek p = &sc->sc_dk.dk_label.d_partitions[sdpart(dev)];
84254881Storek n = (len + sc->sc_blksize - 1) >> DEV_BSHIFT;
84354881Storek if (blkoff < 0 || blkoff >= p->p_size || blkoff + n > p->p_size)
84454881Storek return (EINVAL);
84554881Storek bn = blkoff + p->p_offset;
84654881Storek bn >>= sc->sc_bshift;
84754881Storek
84854881Storek /* scsi bus idle? */
84954881Storek hba = sc->sc_unit.u_hba;
85054881Storek if (hba->hba_head) {
85154881Storek (*hba->hba_driver->hd_reset)(hba, 0);
85254881Storek printf("[reset %s] ", sc->sc_dk.dk_dev.dv_xname);
85354881Storek }
85454881Storek
85554881Storek CDB10(&cdb)->cdb_cmd = CMD_WRITE10;
85654881Storek CDB10(&cdb)->cdb_lun_rel = sc->sc_unit.u_unit << 5;
85754881Storek CDB10(&cdb)->cdb_xxx = 0;
85854881Storek CDB10(&cdb)->cdb_ctrl = 0;
85954881Storek
86054881Storek #define DUMP_MAX (32 * 1024) /* no more than 32k per write */
86154881Storek for (;;) {
86254881Storek if ((n = len) > DUMP_MAX)
86354881Storek n = DUMP_MAX;
86454881Storek CDB10(&cdb)->cdb_lbah = bn >> 24;
86554881Storek CDB10(&cdb)->cdb_lbahm = bn >> 16;
86654881Storek CDB10(&cdb)->cdb_lbalm = bn >> 8;
86754881Storek CDB10(&cdb)->cdb_lbal = bn;
86854881Storek nblks = n >> (DEV_BSHIFT + sc->sc_bshift);
86954881Storek CDB10(&cdb)->cdb_lenh = nblks >> 8;
87054881Storek CDB10(&cdb)->cdb_lenl = nblks;
87154881Storek stat = hba->hba_driver->hd_dump(hba, sc->sc_unit.u_targ,
87254881Storek &cdb, addr, n);
87354881Storek if ((stat & STS_MASK) != STS_GOOD) {
87454881Storek printf("%s: scsi write error 0x%x\ndump ",
87554881Storek sc->sc_dk.dk_dev.dv_xname, stat);
87654881Storek return (EIO);
87754881Storek }
87854881Storek if ((len -= n) == 0)
87954881Storek return (0);
88054881Storek addr += n;
88154881Storek bn += nblks;
88254881Storek }
88354881Storek }
884