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