xref: /csrg-svn/sys/luna68k/dev/sd.c (revision 56519)
154007Sfujita /*
254007Sfujita  * Copyright (c) 1992 OMRON Corporation.
354007Sfujita  * Copyright (c) 1992 The Regents of the University of California.
454007Sfujita  * All rights reserved.
554007Sfujita  *
654007Sfujita  * This code is derived from software contributed to Berkeley by
754007Sfujita  * OMRON Corporation.
854007Sfujita  *
954007Sfujita  * %sccs.include.redist.c%
1054007Sfujita  *
11*56519Sbostic  *	@(#)sd.c	7.4 (Berkeley) 10/11/92
1254007Sfujita  */
1354007Sfujita 
1454007Sfujita /*
1554007Sfujita  * sd.c -- SCSI Disk Device Driver
1654007Sfujita  * remaked by A.Fujita, MAR-22-1992
1754007Sfujita  */
1854007Sfujita 
1954007Sfujita /*
2054007Sfujita  * SCSI CCS (Command Command Set) disk driver.
2154007Sfujita  */
2254007Sfujita #include "sd.h"
2354007Sfujita #if NSD > 0
2454007Sfujita 
25*56519Sbostic #include <sys/param.h>
26*56519Sbostic #include <sys/systm.h>
27*56519Sbostic #include <sys/buf.h>
28*56519Sbostic #include <sys/dkstat.h>
29*56519Sbostic #include <sys/proc.h>
30*56519Sbostic #include <sys/disklabel.h>
3154007Sfujita 
32*56519Sbostic #include <luna68k/dev/device.h>
33*56519Sbostic #include <luna68k/dev/scsireg.h>
34*56519Sbostic #include <luna68k/dev/scsivar.h>
3554007Sfujita 
3654007Sfujita int	sdinit(), sdstrategy(), sdstart(), sdintr();
3754007Sfujita 
3854007Sfujita struct	driver sddriver = {
3954007Sfujita 	sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0
4054007Sfujita };
4154007Sfujita 
4254007Sfujita struct	disklabel sdlabel[NSD];
4354007Sfujita 
4454007Sfujita struct	sd_softc {
4554007Sfujita 	struct	hp_device *sc_hd;
4654007Sfujita 	struct	scsi_queue sc_dq;
4754007Sfujita 	short	sc_flags;
4854007Sfujita 	short	sc_type;	/* drive type */
4954007Sfujita 	short	sc_punit;	/* physical unit (scsi lun) */
5054007Sfujita 	u_int	sc_blks;	/* number of blocks on device */
5154007Sfujita 	int	sc_blksize;	/* device block size in bytes */
5254007Sfujita 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
5354007Sfujita } sd_softc[NSD];
5454007Sfujita 
5554007Sfujita /* sc_flags values */
5654007Sfujita #define	SDF_ALIVE	0x1
5754007Sfujita 
5854007Sfujita struct	buf sdtab[NSD];
5954007Sfujita struct	scsi_fmt_sense sdsense[NSD];
6054007Sfujita 
6154007Sfujita static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
6254007Sfujita static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
6354007Sfujita 
6454007Sfujita #define	sdunit(x)	((minor(x) >> 3) & 0x7)
6554007Sfujita #define sdpart(x)	(minor(x) & 0x7)
6654007Sfujita #define	sdpunit(x)	((x) & 7)
6754007Sfujita #define sdminor(unit, part)	(((unit) << 3) | (part))
6854007Sfujita 
6954007Sfujita #define	b_lba		b_resid
7054007Sfujita 
7154007Sfujita #define	SDRETRY		3	/* IO retry count */
7254007Sfujita 
7354007Sfujita struct sd_iostat {
7454007Sfujita 	int imax;
7554007Sfujita 	int imin;
7654007Sfujita 	int omax;
7754007Sfujita 	int omin;
7854007Sfujita };
7954007Sfujita 
8054007Sfujita struct sd_iostat sd_iostat[NSD] = {
8154007Sfujita 	{ 14000, -1, 100, -1 },
8254007Sfujita };
8354007Sfujita 
8454007Sfujita /*
8554007Sfujita  * Initialize
8654007Sfujita  */
8754007Sfujita 
8854007Sfujita int
8954007Sfujita sdinit(hd)
9054007Sfujita 	register struct hp_device *hd;
9154007Sfujita {
9254007Sfujita 	register struct sd_softc *sc = &sd_softc[hd->hp_unit];
9354007Sfujita 	register struct disklabel *lp;
9454007Sfujita 	char *msg, *sdreadlabel();
9554007Sfujita 
9654007Sfujita 	sc->sc_hd = hd;
9754007Sfujita 	sc->sc_punit = sdpunit(hd->hp_flags);
9854007Sfujita 	sc->sc_type = sdident(sc, hd);
9954007Sfujita 	if (sc->sc_type < 0)
10054007Sfujita 		return(0);
10154007Sfujita 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
10254007Sfujita 	sc->sc_dq.dq_unit = hd->hp_unit;
10354007Sfujita 	sc->sc_dq.dq_slave = hd->hp_slave;
10454007Sfujita 	sc->sc_dq.dq_driver = &sddriver;
10554007Sfujita 
10654007Sfujita 	/*
10754007Sfujita 	 * Use the default sizes until we've read the label,
10854007Sfujita 	 * or longer if there isn't one there.
10954007Sfujita 	 */
11054007Sfujita 	lp = &sdlabel[hd->hp_unit];
11154007Sfujita 
11254007Sfujita 	if (lp->d_secpercyl == 0) {
11354007Sfujita 		lp->d_secsize = DEV_BSIZE;
11454007Sfujita 		lp->d_nsectors = 32;
11554007Sfujita 		lp->d_ntracks = 20;
11654007Sfujita 		lp->d_secpercyl = 32*20;
11754007Sfujita 		lp->d_npartitions = 1;
11854007Sfujita 		lp->d_partitions[0].p_offset = 0;
11954007Sfujita 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
12054007Sfujita 	}
12154007Sfujita 
12254007Sfujita 	/*
12354007Sfujita 	 * read disklabel
12454007Sfujita 	 */
12554007Sfujita 	if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) {
12654007Sfujita 		if (msg != NULL) {
12754007Sfujita 			printf("sd%d: %s\n", hd->hp_unit, msg);
12854007Sfujita 			return(0);
12954007Sfujita 		}
13054007Sfujita 	}
13154007Sfujita 
13254007Sfujita 	sc->sc_flags = SDF_ALIVE;
13354007Sfujita 	return(1);
13454007Sfujita }
13554007Sfujita 
13654007Sfujita static struct scsi_inquiry inqbuf;
13754007Sfujita static struct scsi_fmt_cdb inq = {
13854007Sfujita 	6,
13954007Sfujita 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
14054007Sfujita };
14154007Sfujita 
14254007Sfujita static u_long capbuf[2];
14354007Sfujita struct scsi_fmt_cdb cap = {
14454007Sfujita 	10,
14554007Sfujita 	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
14654007Sfujita };
14754007Sfujita 
14854007Sfujita int
14954007Sfujita sdident(sc, hd)
15054007Sfujita 	struct sd_softc *sc;
15154007Sfujita 	struct hp_device *hd;
15254007Sfujita {
15354007Sfujita 	char idstr[32];
15454007Sfujita 	int unit;
15554007Sfujita 	register int ctlr, slave;
15654007Sfujita 	register int i;
15754007Sfujita 	register int tries = 10;
15854007Sfujita 
15954007Sfujita 	ctlr = hd->hp_ctlr;
16054007Sfujita 	slave = hd->hp_slave;
16154007Sfujita 	unit = sc->sc_punit;
16254007Sfujita 
16354007Sfujita 	/*
16454007Sfujita 	 * See if unit exists and is a disk then read block size & nblocks.
16554007Sfujita 	 */
16654007Sfujita 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
16754007Sfujita 		if (i < 0 || --tries < 0)
16854007Sfujita 			return (-1);
16954007Sfujita 		if (i == STS_CHECKCOND) {
17054007Sfujita 			u_char sensebuf[8];
17154007Sfujita 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
17254007Sfujita 
17354007Sfujita 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
17454007Sfujita 			if (sp->class == 7 && sp->key == 6)
17554007Sfujita 				/* drive doing an RTZ -- give it a while */
17654007Sfujita 				DELAY(1000000);
17754007Sfujita 		}
17854007Sfujita 		DELAY(1000);
17954007Sfujita 	}
18054007Sfujita 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
18154007Sfujita 			       sizeof(inqbuf)) ||
18254007Sfujita 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
18354007Sfujita 			       sizeof(capbuf)))
18454007Sfujita 		/* doesn't exist or not a CCS device */
18554007Sfujita 		return (-1);
18654007Sfujita 
18754007Sfujita 	switch (inqbuf.type) {
18854007Sfujita 	case 0:		/* disk */
18954007Sfujita 	case 4:		/* WORM */
19054007Sfujita 	case 5:		/* CD-ROM */
19154007Sfujita 	case 7:		/* Magneto-optical */
19254007Sfujita 		break;
19354007Sfujita 	default:	/* not a disk */
19454007Sfujita 		return (-1);
19554007Sfujita 	}
19654007Sfujita 	sc->sc_blks    = capbuf[0];
19754007Sfujita 	sc->sc_blksize = capbuf[1];
19854007Sfujita 
19954007Sfujita 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
20054007Sfujita 	for (i = 27; i > 23; --i)
20154007Sfujita 		if (idstr[i] != ' ')
20254007Sfujita 			break;
20354007Sfujita 	idstr[i+1] = 0;
20454007Sfujita 	for (i = 23; i > 7; --i)
20554007Sfujita 		if (idstr[i] != ' ')
20654007Sfujita 			break;
20754007Sfujita 	idstr[i+1] = 0;
20854007Sfujita 	for (i = 7; i >= 0; --i)
20954007Sfujita 		if (idstr[i] != ' ')
21054007Sfujita 			break;
21154007Sfujita 	idstr[i+1] = 0;
21254007Sfujita 	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
21354007Sfujita 	       &idstr[24]);
21454007Sfujita 
21554007Sfujita 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
21654007Sfujita 	if (sc->sc_blksize != DEV_BSIZE) {
21754007Sfujita 		printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE);
21854007Sfujita 		return(1);
21954007Sfujita 	}
22054007Sfujita 
22154007Sfujita 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
22254007Sfujita 	return(inqbuf.type);
22354007Sfujita }
22454007Sfujita 
22554007Sfujita 
22654007Sfujita /*
22754007Sfujita  * Open
22854007Sfujita  */
22954007Sfujita 
23054007Sfujita int
23154007Sfujita sdopen(dev, flags, mode, p)
23254007Sfujita 	dev_t dev;
23354007Sfujita 	int flags, mode;
23454007Sfujita 	struct proc *p;
23554007Sfujita {
23654007Sfujita 	register int unit = sdunit(dev);
23754007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
23854007Sfujita 
23954007Sfujita 	if (unit >= NSD)
24054007Sfujita 		return(ENXIO);
24154007Sfujita 	if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
24254007Sfujita 		return(ENXIO);
24354007Sfujita 
24454007Sfujita 	if (sc->sc_hd->hp_dk >= 0)
24554007Sfujita 		dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
24654007Sfujita 	return(0);
24754007Sfujita }
24854007Sfujita 
24954007Sfujita 
25054007Sfujita /*
25154007Sfujita  * Strategy
25254007Sfujita  */
25354007Sfujita 
25454007Sfujita int
25554007Sfujita sdstrategy(bp)
25654007Sfujita 	register struct buf *bp;
25754007Sfujita {
25854007Sfujita 	register int unit = sdunit(bp->b_dev);
25954007Sfujita 	register int part = sdpart(bp->b_dev);
26054007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
26154007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
26254007Sfujita 	register struct partition *pp = &(lp->d_partitions[part]);
26354007Sfujita 	register struct buf *dp = &sdtab[unit];
26454007Sfujita 	register daddr_t bn;
26554007Sfujita 	register int sz, s;
26654007Sfujita 
26754007Sfujita #ifdef DEBUG
26854007Sfujita 	printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n",
26954007Sfujita 	       bp->b_blkno, bp->b_bcount);
27054007Sfujita #endif
27154007Sfujita 	bn = bp->b_blkno;
27254007Sfujita 	sz = howmany(bp->b_bcount, DEV_BSIZE);
27354007Sfujita 
27454007Sfujita 	/* check that tracsfer is within a drive's partition */
27554007Sfujita 
27654007Sfujita 	if (bn < 0 || (bn + sz) > pp->p_size) {
27754007Sfujita 		sz = pp->p_size - bn;
27854007Sfujita 		if (sz == 0) {
27954007Sfujita 			bp->b_resid = bp->b_bcount;
28054007Sfujita 			goto done;
28154007Sfujita 		}
28254007Sfujita 		if (sz < 0) {
28354007Sfujita 			bp->b_error = EINVAL;
28454007Sfujita 			bp->b_flags |= B_ERROR;
28554007Sfujita 			goto done;
28654007Sfujita 		}
28754007Sfujita 		bp->b_bcount = dbtob(sz);
28854007Sfujita 	}
28954007Sfujita 
29054007Sfujita 	/* calculate LBA for transfer */
29154007Sfujita 
29254007Sfujita 	bp->b_lba = bn + pp->p_offset;
29354007Sfujita 
29454007Sfujita 	/* raise priority to block sdintr */
29554007Sfujita 
29654007Sfujita 	s = splbio();
29754007Sfujita 
29854007Sfujita 	/* call disksort to sort request into drive queue */
29954007Sfujita 
30054007Sfujita 	disksort(dp, bp);
30154007Sfujita 
30254007Sfujita #ifdef DEBUG
30354007Sfujita 	printf("sdstrategy: dp->b_active = %d\n", dp->b_active);
30454007Sfujita #endif
30554007Sfujita 	if (dp->b_active == 0) {			/*  */
30654007Sfujita 		dp->b_active = 1;
30754007Sfujita 		sdustart(unit);
30854007Sfujita 	}
30954007Sfujita 
31054007Sfujita 	/* lower priority */
31154007Sfujita 
31254007Sfujita 	splx(s);
31354007Sfujita 
31454007Sfujita 	return;
31554007Sfujita 
31654007Sfujita done:
31754007Sfujita 	biodone(bp);
31854007Sfujita }
31954007Sfujita 
32054007Sfujita int
32154007Sfujita sdustart(unit)
32254007Sfujita 	register int unit;
32354007Sfujita {
32454007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
32554007Sfujita 	register struct hp_device *hp = sc->sc_hd;
32654007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
32754007Sfujita 	register struct buf *bp = sdtab[unit].b_actf;
32854007Sfujita 	register struct scsi_fmt_cdb *cmd;
32954007Sfujita 
33054007Sfujita 	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
33154007Sfujita 	*(int *)(&cmd->cdb[2]) = bp->b_lba;
33254007Sfujita 	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);
33354007Sfujita 
33454007Sfujita 	dq->dq_cdb   = cmd;
33554007Sfujita 	dq->dq_bp    = bp;
33654007Sfujita 	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */
33754007Sfujita 
33854007Sfujita 	if (screq(dq))
33954007Sfujita 		sdstart(unit);
34054007Sfujita }
34154007Sfujita 
34254007Sfujita int
34354007Sfujita sdstart(unit)
34454007Sfujita 	register int unit;
34554007Sfujita {
34654007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
34754007Sfujita 	register struct hp_device *hp = sc->sc_hd;
34854007Sfujita 
34954007Sfujita 	if (hp->hp_dk >= 0) {
35054007Sfujita 		dk_busy |= 1 << hp->hp_dk;
35154007Sfujita 	}
35254007Sfujita 
35354007Sfujita 	scstart(hp->hp_ctlr);
35454007Sfujita }
35554007Sfujita 
35654007Sfujita 
35754007Sfujita /*
35854007Sfujita  * Return:
35954007Sfujita  *	0	if not really an error
36054007Sfujita  *	<0	if we should do a retry
36154007Sfujita  *	>0	if a fatal error
36254007Sfujita  */
36354007Sfujita static int
36454007Sfujita sderror(unit, sc, hp, stat)
36554007Sfujita 	int unit, stat;
36654007Sfujita 	register struct sd_softc *sc;
36754007Sfujita 	register struct hp_device *hp;
36854007Sfujita {
36954007Sfujita 	int cond = 1;
37054007Sfujita 
37154007Sfujita 	sdsense[unit].status = stat;
37254007Sfujita 	if (stat & STS_CHECKCOND) {
37354007Sfujita 		struct scsi_xsense *sp;
37454007Sfujita 
37554007Sfujita 		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
37654007Sfujita 				   sc->sc_punit, sdsense[unit].sense,
37754007Sfujita 				   sizeof(sdsense[unit].sense));
37854007Sfujita 		sp = (struct scsi_xsense *)sdsense[unit].sense;
37954007Sfujita 		printf("sd%d: scsi sense class %d, code %d", unit,
38054007Sfujita 			sp->class, sp->code);
38154007Sfujita 		if (sp->class == 7) {
38254007Sfujita 			printf(", key %d", sp->key);
38354007Sfujita 			if (sp->valid)
38454007Sfujita 				printf(", blk %d", *(int *)&sp->info1);
38554007Sfujita 			switch (sp->key) {
38654007Sfujita 			/* no sense, try again */
38754007Sfujita 			case 0:
38854007Sfujita 				cond = -1;
38954007Sfujita 				break;
39054007Sfujita 			/* recovered error, not a problem */
39154007Sfujita 			case 1:
39254007Sfujita 				cond = 0;
39354007Sfujita 				break;
39454007Sfujita 			}
39554007Sfujita 		}
39654007Sfujita 		printf("\n");
39754007Sfujita 	}
39854007Sfujita 	return(cond);
39954007Sfujita }
40054007Sfujita 
40154007Sfujita /*
40254007Sfujita  * Interrupt
40354007Sfujita  */
40454007Sfujita 
40554007Sfujita int
40654007Sfujita sdintr(unit, stat)
40754007Sfujita 	register int unit;
40854007Sfujita 	int stat;
40954007Sfujita {
41054007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
41154007Sfujita 	register struct hp_device *hp = sc->sc_hd;
41254007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
41354007Sfujita 	register struct buf *bp = dq->dq_bp;
41454007Sfujita 	int cond;
41554007Sfujita 
41654007Sfujita #ifdef DEBUG
41754007Sfujita 	printf("sdintr(unit = %d, stat = %d)\n", unit, stat);
41854007Sfujita #endif
41954007Sfujita 
42054007Sfujita 	if (stat == SC_IO_TIMEOUT) {
42154007Sfujita 		printf("sdintr: sd%d timeout error\n", unit, stat);
42254007Sfujita 	}
42354007Sfujita 
42454007Sfujita 	if (hp->hp_dk >= 0) {
42554007Sfujita 		dk_busy &=~ (1 << hp->hp_dk);
42654007Sfujita 		if (stat == 0) {
42754007Sfujita 			++dk_seek[hp->hp_dk];
42854007Sfujita 			++dk_xfer[hp->hp_dk];
42954007Sfujita 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
43054007Sfujita 		}
43154007Sfujita 	}
43254007Sfujita 
43354007Sfujita 	if (bp->b_flags & B_READ) {
43455176Saki 		sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin);
43554007Sfujita 		if (dq->dq_imax > sd_iostat[unit].imax) {
43654007Sfujita 			sd_iostat[unit].imax = dq->dq_imax;
43754007Sfujita #ifdef SD_IOSTAT
43854007Sfujita 			printf("sdintr: sd%d  INPUT	MAX = %d, MIN = %d\n",
43954007Sfujita 			       unit, sd_iostat[unit].imax, sd_iostat[unit].imin);
44054007Sfujita #endif
44154007Sfujita 		}
44254007Sfujita 	} else {
44355176Saki 		sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin);
44454007Sfujita 		if (dq->dq_omax > sd_iostat[unit].omax) {
44554007Sfujita 			sd_iostat[unit].omax = dq->dq_omax;
44654007Sfujita #ifdef SD_IOSTAT
44754007Sfujita 			printf("sdintr: sd%d  OUTPUT	MAX = %d, MIN = %d\n",
44854007Sfujita 			       unit, sd_iostat[unit].omax, sd_iostat[unit].omin);
44954007Sfujita #endif
45054007Sfujita 		}
45154007Sfujita 	}
45254007Sfujita 
45354007Sfujita 	if (stat != 0) {
45454007Sfujita 		if (stat > 0) {
45554007Sfujita #ifdef DEBUGPRINT
45654007Sfujita 			dbgprintall();
45754007Sfujita 			printf("\n");
45854007Sfujita #endif
45954007Sfujita 			cond = sderror(unit, sc, hp, stat);
46054007Sfujita 			if (cond) {
46154007Sfujita 				if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
46254007Sfujita 					sdstart(unit);
46354007Sfujita 					return;
46454007Sfujita 				}
46554007Sfujita 			}
46654007Sfujita 		} else {
46754007Sfujita 			if (sdtab[unit].b_errcnt++ < SDRETRY) {
46854007Sfujita 				printf("sdintr: sd%d restart IO request\n", unit);
46954007Sfujita 				sdstart(unit);
47054007Sfujita 				return;
47154007Sfujita 			}
47254007Sfujita 		}
47354007Sfujita 		bp->b_flags |= B_ERROR;
47454007Sfujita 		bp->b_error = EIO;
47554007Sfujita 	}
47654007Sfujita 
47754007Sfujita 	sdtab[unit].b_errcnt = 0;
47854007Sfujita 	sdtab[unit].b_actf = bp->b_actf;
47954007Sfujita 
48054007Sfujita 	bp->b_resid = 0;
48154007Sfujita 
48254007Sfujita 	biodone(bp);
48354007Sfujita 
48454007Sfujita 	scfree(dq);
48554007Sfujita 
48654007Sfujita 	if (sdtab[unit].b_actf) {
48754007Sfujita 		sdustart(unit);
48854007Sfujita 	} else {
48954007Sfujita 		sdtab[unit].b_active = 0;
49054007Sfujita 	}
49154007Sfujita }
49254007Sfujita 
49354007Sfujita 
49454007Sfujita /*
49554007Sfujita  * RAW Device Routines
49654007Sfujita  */
49754007Sfujita 
49854007Sfujita int
49954007Sfujita sdread(dev, uio, flags)
50054007Sfujita 	dev_t dev;
50154007Sfujita 	struct uio *uio;
50254007Sfujita 	int flags;
50354007Sfujita {
50454007Sfujita 	register int unit = sdunit(dev);
50554007Sfujita 
50654007Sfujita 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
50754007Sfujita }
50854007Sfujita 
50954007Sfujita int
51054007Sfujita sdwrite(dev, uio, flags)
51154007Sfujita 	dev_t dev;
51254007Sfujita 	struct uio *uio;
51354007Sfujita 	int flags;
51454007Sfujita {
51554007Sfujita 	register int unit = sdunit(dev);
51654007Sfujita 
51754007Sfujita 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
51854007Sfujita }
51954007Sfujita 
52054007Sfujita int
52154007Sfujita sdioctl(dev, cmd, data, flag, p)
52254007Sfujita 	dev_t dev;
52354007Sfujita 	int cmd;
52454007Sfujita 	caddr_t data;
52554007Sfujita 	int flag;
52654007Sfujita 	struct proc *p;
52754007Sfujita {
52854007Sfujita 	int unit = sdunit(dev);
52954007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
53054007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
53154007Sfujita 	int error = 0;
53254007Sfujita 
53354007Sfujita 	switch (cmd) {
53454007Sfujita 
53554007Sfujita 	case DIOCGDINFO:
53654007Sfujita 		*(struct disklabel *)data = *lp;
53754007Sfujita 		break;
53854007Sfujita 
53954007Sfujita 	case DIOCGPART:
54054007Sfujita 		((struct partinfo *)data)->disklab = lp;
54154007Sfujita 		((struct partinfo *)data)->part =
54254007Sfujita 		    &lp->d_partitions[sdpart(dev)];
54354007Sfujita 		break;
54454007Sfujita 
54554007Sfujita 	default:
54654007Sfujita 		error = ENOTTY;
54754007Sfujita 		break;
54854007Sfujita 	}
54954007Sfujita 	return (error);
55054007Sfujita }
55154007Sfujita 
55254007Sfujita 
55354007Sfujita /*
55454007Sfujita  * Size
55554007Sfujita  */
55654007Sfujita 
55754007Sfujita int
55854007Sfujita sdsize(dev)
55954007Sfujita 	dev_t dev;
56054007Sfujita {
56154007Sfujita 	register int unit = sdunit(dev);
56254007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
56354007Sfujita 
56454007Sfujita 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
56554007Sfujita 		return(-1);
56654007Sfujita 
56754007Sfujita 	return(sdlabel[unit].d_partitions[sdpart(dev)].p_size);
56854007Sfujita }
56954007Sfujita 
57054007Sfujita 
57154007Sfujita /*
57254007Sfujita  * Dump
57354007Sfujita  */
57454007Sfujita 
57554007Sfujita int
57654007Sfujita sddump(dev)
57754007Sfujita 	dev_t dev;
57854007Sfujita {
57954007Sfujita }
58054007Sfujita 
58154007Sfujita /*
58254007Sfujita  * Disk Subs
58354007Sfujita  */
58454007Sfujita 
58554007Sfujita /*
58654007Sfujita  * Attempt to read a disk label from a device
58754007Sfujita  * using the indicated stategy routine.
58854007Sfujita  * The label must be partly set up before this:
58954007Sfujita  * secpercyl and anything required in the strategy routine
59054007Sfujita  * (e.g., sector size) must be filled in before calling us.
59154007Sfujita  * Returns null on success and an error string on failure.
59254007Sfujita  */
59354007Sfujita char *
59454007Sfujita sdreadlabel(dev, strat, lp)
59554007Sfujita 	dev_t dev;
59654007Sfujita 	int (*strat)();
59754007Sfujita 	register struct disklabel *lp;
59854007Sfujita {
59954007Sfujita 	register struct buf *bp;
60054007Sfujita 	struct disklabel *dlp;
60154007Sfujita 	char *msg = NULL;
60254007Sfujita 
60354007Sfujita 	if (lp->d_secperunit == 0)
60454007Sfujita 		lp->d_secperunit = 0x1fffffff;
60554007Sfujita 	lp->d_npartitions = 1;
60654007Sfujita 	if (lp->d_partitions[0].p_size == 0)
60754007Sfujita 		lp->d_partitions[0].p_size = 0x1fffffff;
60854007Sfujita 	lp->d_partitions[0].p_offset = 0;
60954007Sfujita 
61054007Sfujita 	bp = geteblk((int)lp->d_secsize);
61154007Sfujita 	bp->b_dev = dev;
61254007Sfujita 	bp->b_blkno = LABELSECTOR;
61354007Sfujita 	bp->b_bcount = lp->d_secsize;
61454007Sfujita 	bp->b_flags = B_BUSY | B_READ;
61554007Sfujita 	(*strat)(bp);
61654007Sfujita 	if (biowait(bp)) {
61754007Sfujita 		msg = "I/O error";
61854007Sfujita 	} else {
61954007Sfujita 		for (dlp = (struct disklabel *)bp->b_un.b_addr;
62054007Sfujita 		     dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
62154007Sfujita 		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
62254007Sfujita 			if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
62354007Sfujita 				if (msg == NULL)
62454007Sfujita 					msg = "no disk label";
62554007Sfujita 			} else if (dlp->d_npartitions > MAXPARTITIONS ||
62654007Sfujita 				   dkcksum(dlp) != 0)
62754007Sfujita 				msg = "disk label corrupted";
62854007Sfujita 			else {
62954007Sfujita 				*lp = *dlp;
63054007Sfujita 				msg = NULL;
63154007Sfujita 				break;
63254007Sfujita 			}
63354007Sfujita 		}
63454007Sfujita 	}
63554007Sfujita 	bp->b_flags = B_INVAL | B_AGE;
63654007Sfujita 	brelse(bp);
63754007Sfujita 	return (msg);
63854007Sfujita }
63954007Sfujita 
64054007Sfujita #ifdef notyet
64154007Sfujita 
64254007Sfujita /*
64354007Sfujita  * Checksum routine for OMRON native disklabel
64454007Sfujita  */
64554007Sfujita 
64654007Sfujita #define	OMRON_LBLSIZE	512
64754007Sfujita 
64854007Sfujita u_short
64954007Sfujita omcksum(omp)
65054007Sfujita 	register char *omp;
65154007Sfujita {
65254007Sfujita 	register u_short *start, *end;
65354007Sfujita 	register u_short sum = 0;
65454007Sfujita 
65554007Sfujita 	start = (u_short *) omp;
65654007Sfujita 	end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)];
65754007Sfujita 	while (start < end)
65854007Sfujita 		sum ^= *start++;
65954007Sfujita 
66054007Sfujita 	printf("omcksum: saved  ... 0x%s\n", hexstr(*end, 4));
66154007Sfujita 	printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4));
66254007Sfujita 
66354007Sfujita 	return (sum);
66454007Sfujita }
66554007Sfujita 
66654007Sfujita /*
66754007Sfujita  * Write disk label back to device after modification.
66854007Sfujita  */
66954007Sfujita sdwritelabel(dev, strat, lp)
67054007Sfujita 	dev_t dev;
67154007Sfujita 	int (*strat)();
67254007Sfujita 	register struct disklabel *lp;
67354007Sfujita {
67454007Sfujita 	struct buf *bp;
67554007Sfujita 	struct disklabel *dlp;
67654007Sfujita 	int labelpart;
67754007Sfujita 	int error = 0;
67854007Sfujita 
67954007Sfujita 	labelpart = sdpart(dev);
68054007Sfujita 	if (lp->d_partitions[labelpart].p_offset != 0) {
68154007Sfujita 		if (lp->d_partitions[0].p_offset != 0)
68254007Sfujita 			return (EXDEV);			/* not quite right */
68354007Sfujita 		labelpart = 0;
68454007Sfujita 	}
68554007Sfujita 
68654007Sfujita 	bp = geteblk((int)lp->d_secsize);
68754007Sfujita 	bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart));
68854007Sfujita 	bp->b_blkno = LABELSECTOR;
68954007Sfujita 	bp->b_bcount = lp->d_secsize;
69054007Sfujita 	bp->b_flags = B_READ;
69154007Sfujita 	(*strat)(bp);
69254007Sfujita 	if (error = biowait(bp))
69354007Sfujita 		goto done;
69454007Sfujita 
69554007Sfujita 	for (dlp = (struct disklabel *)bp->b_un.b_addr;
69654007Sfujita 	    dlp <= (struct disklabel *)
69754007Sfujita 	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
69854007Sfujita 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
69954007Sfujita 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
70054007Sfujita 		    dkcksum(dlp) == 0) {
70154007Sfujita 			omcksum(bp->b_un.b_addr);
70254007Sfujita /*
70354007Sfujita 			*dlp = *lp;
70454007Sfujita 			bp->b_flags = B_WRITE;
70554007Sfujita 			(*strat)(bp);
70654007Sfujita 			error = biowait(bp);
70754007Sfujita 			goto done;
70854007Sfujita  */
70954007Sfujita 		}
71054007Sfujita 	}
71154007Sfujita 	error = ESRCH;
71254007Sfujita done:
71354007Sfujita 	brelse(bp);
71454007Sfujita 	return (error);
71554007Sfujita }
71654007Sfujita #endif
71754007Sfujita 
71854007Sfujita #endif
719