xref: /csrg-svn/sys/luna68k/dev/sd.c (revision 65044)
154007Sfujita /*
254007Sfujita  * Copyright (c) 1992 OMRON Corporation.
363192Sbostic  * Copyright (c) 1992, 1993
463192Sbostic  *	The Regents of the University of California.  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*65044Sakito  *	@(#)sd.c	8.3 (Berkeley) 12/07/93
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 
2556519Sbostic #include <sys/param.h>
2656519Sbostic #include <sys/systm.h>
2756519Sbostic #include <sys/buf.h>
2856519Sbostic #include <sys/dkstat.h>
2956519Sbostic #include <sys/proc.h>
3056519Sbostic #include <sys/disklabel.h>
3154007Sfujita 
3256519Sbostic #include <luna68k/dev/device.h>
3365035Sakito #include <luna68k/dev/screg.h>
3465035Sakito #include <luna68k/dev/scvar.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
sdinit(hd)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
sdident(sc,hd)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 	 */
16665035Sakito 	while ((i = sc_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 
17365035Sakito 			sc_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
sdopen(dev,flags,mode,p)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 /*
25158693Sakito  * Close
25258693Sakito  */
25358693Sakito 
25458693Sakito int
sdclose(dev,flag,mode,p)25558693Sakito sdclose(dev, flag, mode, p)
25658693Sakito 	dev_t dev;
25758693Sakito 	int flag, mode;
25858693Sakito 	struct proc *p;
25958693Sakito {
260*65044Sakito 	return(0);
26158693Sakito }
26258693Sakito 
26358693Sakito /*
26454007Sfujita  * Strategy
26554007Sfujita  */
26654007Sfujita 
26754007Sfujita int
sdstrategy(bp)26854007Sfujita sdstrategy(bp)
26954007Sfujita 	register struct buf *bp;
27054007Sfujita {
27154007Sfujita 	register int unit = sdunit(bp->b_dev);
27254007Sfujita 	register int part = sdpart(bp->b_dev);
27354007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
27454007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
27554007Sfujita 	register struct partition *pp = &(lp->d_partitions[part]);
27654007Sfujita 	register struct buf *dp = &sdtab[unit];
27754007Sfujita 	register daddr_t bn;
27854007Sfujita 	register int sz, s;
27954007Sfujita 
28054007Sfujita 	bn = bp->b_blkno;
28154007Sfujita 	sz = howmany(bp->b_bcount, DEV_BSIZE);
28254007Sfujita 
28354007Sfujita 	/* check that tracsfer is within a drive's partition */
28454007Sfujita 
28554007Sfujita 	if (bn < 0 || (bn + sz) > pp->p_size) {
28654007Sfujita 		sz = pp->p_size - bn;
28754007Sfujita 		if (sz == 0) {
28854007Sfujita 			bp->b_resid = bp->b_bcount;
28954007Sfujita 			goto done;
29054007Sfujita 		}
29154007Sfujita 		if (sz < 0) {
29254007Sfujita 			bp->b_error = EINVAL;
29354007Sfujita 			bp->b_flags |= B_ERROR;
29454007Sfujita 			goto done;
29554007Sfujita 		}
29654007Sfujita 		bp->b_bcount = dbtob(sz);
29754007Sfujita 	}
29854007Sfujita 
29954007Sfujita 	/* calculate LBA for transfer */
30054007Sfujita 
30154007Sfujita 	bp->b_lba = bn + pp->p_offset;
30254007Sfujita 
30354007Sfujita 	/* raise priority to block sdintr */
30454007Sfujita 
30554007Sfujita 	s = splbio();
30654007Sfujita 
30754007Sfujita 	/* call disksort to sort request into drive queue */
30854007Sfujita 
30954007Sfujita 	disksort(dp, bp);
31054007Sfujita 
31154007Sfujita 	if (dp->b_active == 0) {			/*  */
31254007Sfujita 		dp->b_active = 1;
31354007Sfujita 		sdustart(unit);
31454007Sfujita 	}
31554007Sfujita 
31654007Sfujita 	/* lower priority */
31754007Sfujita 
31854007Sfujita 	splx(s);
31954007Sfujita 
32054007Sfujita 	return;
32154007Sfujita 
32254007Sfujita done:
32354007Sfujita 	biodone(bp);
32454007Sfujita }
32554007Sfujita 
32654007Sfujita int
sdustart(unit)32754007Sfujita sdustart(unit)
32854007Sfujita 	register int unit;
32954007Sfujita {
33054007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
33154007Sfujita 	register struct hp_device *hp = sc->sc_hd;
33254007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
33354007Sfujita 	register struct buf *bp = sdtab[unit].b_actf;
33454007Sfujita 	register struct scsi_fmt_cdb *cmd;
33554007Sfujita 
33654007Sfujita 	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
33754007Sfujita 	*(int *)(&cmd->cdb[2]) = bp->b_lba;
33854007Sfujita 	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);
33954007Sfujita 
34054007Sfujita 	dq->dq_cdb   = cmd;
34154007Sfujita 	dq->dq_bp    = bp;
34254007Sfujita 	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */
34354007Sfujita 
34454007Sfujita 	if (screq(dq))
34554007Sfujita 		sdstart(unit);
34654007Sfujita }
34754007Sfujita 
34854007Sfujita int
sdstart(unit)34954007Sfujita sdstart(unit)
35054007Sfujita 	register int unit;
35154007Sfujita {
35254007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
35354007Sfujita 	register struct hp_device *hp = sc->sc_hd;
35454007Sfujita 
35554007Sfujita 	if (hp->hp_dk >= 0) {
35654007Sfujita 		dk_busy |= 1 << hp->hp_dk;
35754007Sfujita 	}
35854007Sfujita 
35954007Sfujita 	scstart(hp->hp_ctlr);
36054007Sfujita }
36154007Sfujita 
36254007Sfujita 
36354007Sfujita /*
36454007Sfujita  * Return:
36554007Sfujita  *	0	if not really an error
36654007Sfujita  *	<0	if we should do a retry
36754007Sfujita  *	>0	if a fatal error
36854007Sfujita  */
36954007Sfujita static int
sderror(unit,sc,hp,stat)37054007Sfujita sderror(unit, sc, hp, stat)
37154007Sfujita 	int unit, stat;
37254007Sfujita 	register struct sd_softc *sc;
37354007Sfujita 	register struct hp_device *hp;
37454007Sfujita {
37554007Sfujita 	int cond = 1;
37654007Sfujita 
37754007Sfujita 	sdsense[unit].status = stat;
37854007Sfujita 	if (stat & STS_CHECKCOND) {
37954007Sfujita 		struct scsi_xsense *sp;
38054007Sfujita 
38165035Sakito 		sc_request_sense(hp->hp_ctlr, hp->hp_slave,
38254007Sfujita 				   sc->sc_punit, sdsense[unit].sense,
38354007Sfujita 				   sizeof(sdsense[unit].sense));
38454007Sfujita 		sp = (struct scsi_xsense *)sdsense[unit].sense;
38554007Sfujita 		printf("sd%d: scsi sense class %d, code %d", unit,
38654007Sfujita 			sp->class, sp->code);
38754007Sfujita 		if (sp->class == 7) {
38854007Sfujita 			printf(", key %d", sp->key);
38954007Sfujita 			if (sp->valid)
39054007Sfujita 				printf(", blk %d", *(int *)&sp->info1);
39154007Sfujita 			switch (sp->key) {
39254007Sfujita 			/* no sense, try again */
39354007Sfujita 			case 0:
39454007Sfujita 				cond = -1;
39554007Sfujita 				break;
39654007Sfujita 			/* recovered error, not a problem */
39754007Sfujita 			case 1:
39854007Sfujita 				cond = 0;
39954007Sfujita 				break;
40054007Sfujita 			}
40154007Sfujita 		}
40254007Sfujita 		printf("\n");
40354007Sfujita 	}
40454007Sfujita 	return(cond);
40554007Sfujita }
40654007Sfujita 
40754007Sfujita /*
40854007Sfujita  * Interrupt
40954007Sfujita  */
41054007Sfujita 
41154007Sfujita int
sdintr(unit,stat)41254007Sfujita sdintr(unit, stat)
41354007Sfujita 	register int unit;
41454007Sfujita 	int stat;
41554007Sfujita {
41654007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
41754007Sfujita 	register struct hp_device *hp = sc->sc_hd;
41854007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
41954007Sfujita 	register struct buf *bp = dq->dq_bp;
42054007Sfujita 	int cond;
42154007Sfujita 
42254007Sfujita 	if (stat == SC_IO_TIMEOUT) {
42354007Sfujita 		printf("sdintr: sd%d timeout error\n", unit, stat);
42454007Sfujita 	}
42554007Sfujita 
42654007Sfujita 	if (hp->hp_dk >= 0) {
42754007Sfujita 		dk_busy &=~ (1 << hp->hp_dk);
42854007Sfujita 		if (stat == 0) {
42954007Sfujita 			++dk_seek[hp->hp_dk];
43054007Sfujita 			++dk_xfer[hp->hp_dk];
43154007Sfujita 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
43254007Sfujita 		}
43354007Sfujita 	}
43454007Sfujita 
43554007Sfujita 	if (bp->b_flags & B_READ) {
43655176Saki 		sd_iostat[unit].imin = min(dq->dq_imin, sd_iostat[unit].imin);
43754007Sfujita 		if (dq->dq_imax > sd_iostat[unit].imax) {
43854007Sfujita 			sd_iostat[unit].imax = dq->dq_imax;
43954007Sfujita #ifdef SD_IOSTAT
44054007Sfujita 			printf("sdintr: sd%d  INPUT	MAX = %d, MIN = %d\n",
44154007Sfujita 			       unit, sd_iostat[unit].imax, sd_iostat[unit].imin);
44254007Sfujita #endif
44354007Sfujita 		}
44454007Sfujita 	} else {
44555176Saki 		sd_iostat[unit].omin = min(dq->dq_omin, sd_iostat[unit].omin);
44654007Sfujita 		if (dq->dq_omax > sd_iostat[unit].omax) {
44754007Sfujita 			sd_iostat[unit].omax = dq->dq_omax;
44854007Sfujita #ifdef SD_IOSTAT
44954007Sfujita 			printf("sdintr: sd%d  OUTPUT	MAX = %d, MIN = %d\n",
45054007Sfujita 			       unit, sd_iostat[unit].omax, sd_iostat[unit].omin);
45154007Sfujita #endif
45254007Sfujita 		}
45354007Sfujita 	}
45454007Sfujita 
45554007Sfujita 	if (stat != 0) {
45654007Sfujita 		if (stat > 0) {
45754007Sfujita #ifdef DEBUGPRINT
45854007Sfujita 			dbgprintall();
45954007Sfujita 			printf("\n");
46054007Sfujita #endif
46154007Sfujita 			cond = sderror(unit, sc, hp, stat);
46254007Sfujita 			if (cond) {
46354007Sfujita 				if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
46454007Sfujita 					sdstart(unit);
46554007Sfujita 					return;
46654007Sfujita 				}
46754007Sfujita 			}
46854007Sfujita 		} else {
46954007Sfujita 			if (sdtab[unit].b_errcnt++ < SDRETRY) {
47054007Sfujita 				printf("sdintr: sd%d restart IO request\n", unit);
47154007Sfujita 				sdstart(unit);
47254007Sfujita 				return;
47354007Sfujita 			}
47454007Sfujita 		}
47554007Sfujita 		bp->b_flags |= B_ERROR;
47654007Sfujita 		bp->b_error = EIO;
47754007Sfujita 	}
47854007Sfujita 
47954007Sfujita 	sdtab[unit].b_errcnt = 0;
48054007Sfujita 	sdtab[unit].b_actf = bp->b_actf;
48154007Sfujita 
48254007Sfujita 	bp->b_resid = 0;
48354007Sfujita 
48454007Sfujita 	biodone(bp);
48554007Sfujita 
48654007Sfujita 	scfree(dq);
48754007Sfujita 
48854007Sfujita 	if (sdtab[unit].b_actf) {
48954007Sfujita 		sdustart(unit);
49054007Sfujita 	} else {
49154007Sfujita 		sdtab[unit].b_active = 0;
49254007Sfujita 	}
49354007Sfujita }
49454007Sfujita 
49554007Sfujita 
49654007Sfujita /*
49754007Sfujita  * RAW Device Routines
49854007Sfujita  */
49954007Sfujita 
50054007Sfujita int
sdread(dev,uio,flags)50154007Sfujita sdread(dev, uio, flags)
50254007Sfujita 	dev_t dev;
50354007Sfujita 	struct uio *uio;
50454007Sfujita 	int flags;
50554007Sfujita {
50654007Sfujita 	register int unit = sdunit(dev);
50754007Sfujita 
50854007Sfujita 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
50954007Sfujita }
51054007Sfujita 
51154007Sfujita int
sdwrite(dev,uio,flags)51254007Sfujita sdwrite(dev, uio, flags)
51354007Sfujita 	dev_t dev;
51454007Sfujita 	struct uio *uio;
51554007Sfujita 	int flags;
51654007Sfujita {
51754007Sfujita 	register int unit = sdunit(dev);
51854007Sfujita 
51954007Sfujita 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
52054007Sfujita }
52154007Sfujita 
52254007Sfujita int
sdioctl(dev,cmd,data,flag,p)52354007Sfujita sdioctl(dev, cmd, data, flag, p)
52454007Sfujita 	dev_t dev;
52554007Sfujita 	int cmd;
52654007Sfujita 	caddr_t data;
52754007Sfujita 	int flag;
52854007Sfujita 	struct proc *p;
52954007Sfujita {
53054007Sfujita 	int unit = sdunit(dev);
53154007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
53254007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
53354007Sfujita 	int error = 0;
53454007Sfujita 
53554007Sfujita 	switch (cmd) {
53654007Sfujita 
53754007Sfujita 	case DIOCGDINFO:
53854007Sfujita 		*(struct disklabel *)data = *lp;
53954007Sfujita 		break;
54054007Sfujita 
54154007Sfujita 	case DIOCGPART:
54254007Sfujita 		((struct partinfo *)data)->disklab = lp;
54354007Sfujita 		((struct partinfo *)data)->part =
54454007Sfujita 		    &lp->d_partitions[sdpart(dev)];
54554007Sfujita 		break;
54654007Sfujita 
54757378Sakito         case DIOCWLABEL:
54857378Sakito         case DIOCSDINFO:
54957378Sakito         case DIOCWDINFO:
55057378Sakito 		break;
55157378Sakito 
55254007Sfujita 	default:
55354007Sfujita 		error = ENOTTY;
55454007Sfujita 		break;
55554007Sfujita 	}
55654007Sfujita 	return (error);
55754007Sfujita }
55854007Sfujita 
55954007Sfujita 
56054007Sfujita /*
56154007Sfujita  * Size
56254007Sfujita  */
56354007Sfujita 
56454007Sfujita int
sdsize(dev)56554007Sfujita sdsize(dev)
56654007Sfujita 	dev_t dev;
56754007Sfujita {
56854007Sfujita 	register int unit = sdunit(dev);
56954007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
57054007Sfujita 
57154007Sfujita 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
57254007Sfujita 		return(-1);
57354007Sfujita 
57454007Sfujita 	return(sdlabel[unit].d_partitions[sdpart(dev)].p_size);
57554007Sfujita }
57654007Sfujita 
57754007Sfujita 
57854007Sfujita /*
57954007Sfujita  * Dump
58054007Sfujita  */
58154007Sfujita 
58254007Sfujita int
sddump(dev)58354007Sfujita sddump(dev)
58454007Sfujita 	dev_t dev;
58554007Sfujita {
58654007Sfujita }
58754007Sfujita 
58854007Sfujita /*
58954007Sfujita  * Disk Subs
59054007Sfujita  */
59154007Sfujita 
59254007Sfujita /*
59354007Sfujita  * Attempt to read a disk label from a device
59454007Sfujita  * using the indicated stategy routine.
59554007Sfujita  * The label must be partly set up before this:
59654007Sfujita  * secpercyl and anything required in the strategy routine
59754007Sfujita  * (e.g., sector size) must be filled in before calling us.
59854007Sfujita  * Returns null on success and an error string on failure.
59954007Sfujita  */
60054007Sfujita char *
sdreadlabel(dev,strat,lp)60154007Sfujita sdreadlabel(dev, strat, lp)
60254007Sfujita 	dev_t dev;
60354007Sfujita 	int (*strat)();
60454007Sfujita 	register struct disklabel *lp;
60554007Sfujita {
60654007Sfujita 	register struct buf *bp;
60754007Sfujita 	struct disklabel *dlp;
60854007Sfujita 	char *msg = NULL;
60954007Sfujita 
61054007Sfujita 	if (lp->d_secperunit == 0)
61154007Sfujita 		lp->d_secperunit = 0x1fffffff;
61254007Sfujita 	lp->d_npartitions = 1;
61354007Sfujita 	if (lp->d_partitions[0].p_size == 0)
61454007Sfujita 		lp->d_partitions[0].p_size = 0x1fffffff;
61554007Sfujita 	lp->d_partitions[0].p_offset = 0;
61654007Sfujita 
61754007Sfujita 	bp = geteblk((int)lp->d_secsize);
61854007Sfujita 	bp->b_dev = dev;
61954007Sfujita 	bp->b_blkno = LABELSECTOR;
62054007Sfujita 	bp->b_bcount = lp->d_secsize;
62154007Sfujita 	bp->b_flags = B_BUSY | B_READ;
62254007Sfujita 	(*strat)(bp);
62354007Sfujita 	if (biowait(bp)) {
62454007Sfujita 		msg = "I/O error";
62554007Sfujita 	} else {
62654007Sfujita 		for (dlp = (struct disklabel *)bp->b_un.b_addr;
62754007Sfujita 		     dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
62854007Sfujita 		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
62954007Sfujita 			if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
63054007Sfujita 				if (msg == NULL)
63154007Sfujita 					msg = "no disk label";
63254007Sfujita 			} else if (dlp->d_npartitions > MAXPARTITIONS ||
63354007Sfujita 				   dkcksum(dlp) != 0)
63454007Sfujita 				msg = "disk label corrupted";
63554007Sfujita 			else {
63654007Sfujita 				*lp = *dlp;
63754007Sfujita 				msg = NULL;
63854007Sfujita 				break;
63954007Sfujita 			}
64054007Sfujita 		}
64154007Sfujita 	}
64254007Sfujita 	bp->b_flags = B_INVAL | B_AGE;
64354007Sfujita 	brelse(bp);
64454007Sfujita 	return (msg);
64554007Sfujita }
64654007Sfujita 
64754007Sfujita #ifdef notyet
64854007Sfujita 
64954007Sfujita /*
65054007Sfujita  * Checksum routine for OMRON native disklabel
65154007Sfujita  */
65254007Sfujita 
65354007Sfujita #define	OMRON_LBLSIZE	512
65454007Sfujita 
65554007Sfujita u_short
omcksum(omp)65654007Sfujita omcksum(omp)
65754007Sfujita 	register char *omp;
65854007Sfujita {
65954007Sfujita 	register u_short *start, *end;
66054007Sfujita 	register u_short sum = 0;
66154007Sfujita 
66254007Sfujita 	start = (u_short *) omp;
66354007Sfujita 	end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)];
66454007Sfujita 	while (start < end)
66554007Sfujita 		sum ^= *start++;
66654007Sfujita 
66754007Sfujita 	printf("omcksum: saved  ... 0x%s\n", hexstr(*end, 4));
66854007Sfujita 	printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4));
66954007Sfujita 
67054007Sfujita 	return (sum);
67154007Sfujita }
67254007Sfujita 
67354007Sfujita /*
67454007Sfujita  * Write disk label back to device after modification.
67554007Sfujita  */
sdwritelabel(dev,strat,lp)67654007Sfujita sdwritelabel(dev, strat, lp)
67754007Sfujita 	dev_t dev;
67854007Sfujita 	int (*strat)();
67954007Sfujita 	register struct disklabel *lp;
68054007Sfujita {
68154007Sfujita 	struct buf *bp;
68254007Sfujita 	struct disklabel *dlp;
68354007Sfujita 	int labelpart;
68454007Sfujita 	int error = 0;
68554007Sfujita 
68654007Sfujita 	labelpart = sdpart(dev);
68754007Sfujita 	if (lp->d_partitions[labelpart].p_offset != 0) {
68854007Sfujita 		if (lp->d_partitions[0].p_offset != 0)
68954007Sfujita 			return (EXDEV);			/* not quite right */
69054007Sfujita 		labelpart = 0;
69154007Sfujita 	}
69254007Sfujita 
69354007Sfujita 	bp = geteblk((int)lp->d_secsize);
69454007Sfujita 	bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart));
69554007Sfujita 	bp->b_blkno = LABELSECTOR;
69654007Sfujita 	bp->b_bcount = lp->d_secsize;
69754007Sfujita 	bp->b_flags = B_READ;
69854007Sfujita 	(*strat)(bp);
69954007Sfujita 	if (error = biowait(bp))
70054007Sfujita 		goto done;
70154007Sfujita 
70254007Sfujita 	for (dlp = (struct disklabel *)bp->b_un.b_addr;
70354007Sfujita 	    dlp <= (struct disklabel *)
70454007Sfujita 	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
70554007Sfujita 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
70654007Sfujita 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
70754007Sfujita 		    dkcksum(dlp) == 0) {
70854007Sfujita 			omcksum(bp->b_un.b_addr);
70954007Sfujita /*
71054007Sfujita 			*dlp = *lp;
71154007Sfujita 			bp->b_flags = B_WRITE;
71254007Sfujita 			(*strat)(bp);
71354007Sfujita 			error = biowait(bp);
71454007Sfujita 			goto done;
71554007Sfujita  */
71654007Sfujita 		}
71754007Sfujita 	}
71854007Sfujita 	error = ESRCH;
71954007Sfujita done:
72054007Sfujita 	brelse(bp);
72154007Sfujita 	return (error);
72254007Sfujita }
72354007Sfujita #endif
72454007Sfujita 
72554007Sfujita #endif
726