xref: /csrg-svn/sys/luna68k/dev/sd.c (revision 54007)
1*54007Sfujita /*
2*54007Sfujita  * Copyright (c) 1992 OMRON Corporation.
3*54007Sfujita  * Copyright (c) 1992 The Regents of the University of California.
4*54007Sfujita  * All rights reserved.
5*54007Sfujita  *
6*54007Sfujita  * This code is derived from software contributed to Berkeley by
7*54007Sfujita  * OMRON Corporation.
8*54007Sfujita  *
9*54007Sfujita  * %sccs.include.redist.c%
10*54007Sfujita  *
11*54007Sfujita  *	@(#)sd.c	7.1 (Berkeley) 06/15/92
12*54007Sfujita  */
13*54007Sfujita 
14*54007Sfujita /*
15*54007Sfujita  * sd.c -- SCSI Disk Device Driver
16*54007Sfujita  * remaked by A.Fujita, MAR-22-1992
17*54007Sfujita  */
18*54007Sfujita 
19*54007Sfujita /*
20*54007Sfujita  * SCSI CCS (Command Command Set) disk driver.
21*54007Sfujita  */
22*54007Sfujita #include "sd.h"
23*54007Sfujita #if NSD > 0
24*54007Sfujita 
25*54007Sfujita #include "sys/param.h"
26*54007Sfujita #include "sys/buf.h"
27*54007Sfujita #include "sys/dkstat.h"
28*54007Sfujita #include "sys/proc.h"
29*54007Sfujita #include "sys/disklabel.h"
30*54007Sfujita 
31*54007Sfujita #include "device.h"
32*54007Sfujita #include "scsireg.h"
33*54007Sfujita #include "scsivar.h"
34*54007Sfujita 
35*54007Sfujita int	sdinit(), sdstrategy(), sdstart(), sdintr();
36*54007Sfujita 
37*54007Sfujita struct	driver sddriver = {
38*54007Sfujita 	sdinit, "sd", sdstart, (int (*)()) 0, sdintr, (int (*)()) 0
39*54007Sfujita };
40*54007Sfujita 
41*54007Sfujita struct	disklabel sdlabel[NSD];
42*54007Sfujita 
43*54007Sfujita struct	sd_softc {
44*54007Sfujita 	struct	hp_device *sc_hd;
45*54007Sfujita 	struct	scsi_queue sc_dq;
46*54007Sfujita 	short	sc_flags;
47*54007Sfujita 	short	sc_type;	/* drive type */
48*54007Sfujita 	short	sc_punit;	/* physical unit (scsi lun) */
49*54007Sfujita 	u_int	sc_blks;	/* number of blocks on device */
50*54007Sfujita 	int	sc_blksize;	/* device block size in bytes */
51*54007Sfujita 	u_int	sc_wpms;	/* average xfer rate in 16 bit wds/sec. */
52*54007Sfujita } sd_softc[NSD];
53*54007Sfujita 
54*54007Sfujita /* sc_flags values */
55*54007Sfujita #define	SDF_ALIVE	0x1
56*54007Sfujita 
57*54007Sfujita struct	buf sdtab[NSD];
58*54007Sfujita struct	scsi_fmt_sense sdsense[NSD];
59*54007Sfujita 
60*54007Sfujita static struct scsi_fmt_cdb sd_read_cmd = { 10, CMD_READ_EXT };
61*54007Sfujita static struct scsi_fmt_cdb sd_write_cmd = { 10, CMD_WRITE_EXT };
62*54007Sfujita 
63*54007Sfujita #define	sdunit(x)	((minor(x) >> 3) & 0x7)
64*54007Sfujita #define sdpart(x)	(minor(x) & 0x7)
65*54007Sfujita #define	sdpunit(x)	((x) & 7)
66*54007Sfujita #define sdminor(unit, part)	(((unit) << 3) | (part))
67*54007Sfujita 
68*54007Sfujita #define	b_lba		b_resid
69*54007Sfujita 
70*54007Sfujita #define	SDRETRY		3	/* IO retry count */
71*54007Sfujita 
72*54007Sfujita struct sd_iostat {
73*54007Sfujita 	int imax;
74*54007Sfujita 	int imin;
75*54007Sfujita 	int omax;
76*54007Sfujita 	int omin;
77*54007Sfujita };
78*54007Sfujita 
79*54007Sfujita struct sd_iostat sd_iostat[NSD] = {
80*54007Sfujita 	{ 14000, -1, 100, -1 },
81*54007Sfujita };
82*54007Sfujita 
83*54007Sfujita /*
84*54007Sfujita  * Initialize
85*54007Sfujita  */
86*54007Sfujita 
87*54007Sfujita int
88*54007Sfujita sdinit(hd)
89*54007Sfujita 	register struct hp_device *hd;
90*54007Sfujita {
91*54007Sfujita 	register struct sd_softc *sc = &sd_softc[hd->hp_unit];
92*54007Sfujita 	register struct disklabel *lp;
93*54007Sfujita 	char *msg, *sdreadlabel();
94*54007Sfujita 
95*54007Sfujita 	sc->sc_hd = hd;
96*54007Sfujita 	sc->sc_punit = sdpunit(hd->hp_flags);
97*54007Sfujita 	sc->sc_type = sdident(sc, hd);
98*54007Sfujita 	if (sc->sc_type < 0)
99*54007Sfujita 		return(0);
100*54007Sfujita 	sc->sc_dq.dq_ctlr = hd->hp_ctlr;
101*54007Sfujita 	sc->sc_dq.dq_unit = hd->hp_unit;
102*54007Sfujita 	sc->sc_dq.dq_slave = hd->hp_slave;
103*54007Sfujita 	sc->sc_dq.dq_driver = &sddriver;
104*54007Sfujita 
105*54007Sfujita 	/*
106*54007Sfujita 	 * Use the default sizes until we've read the label,
107*54007Sfujita 	 * or longer if there isn't one there.
108*54007Sfujita 	 */
109*54007Sfujita 	lp = &sdlabel[hd->hp_unit];
110*54007Sfujita 
111*54007Sfujita 	if (lp->d_secpercyl == 0) {
112*54007Sfujita 		lp->d_secsize = DEV_BSIZE;
113*54007Sfujita 		lp->d_nsectors = 32;
114*54007Sfujita 		lp->d_ntracks = 20;
115*54007Sfujita 		lp->d_secpercyl = 32*20;
116*54007Sfujita 		lp->d_npartitions = 1;
117*54007Sfujita 		lp->d_partitions[0].p_offset = 0;
118*54007Sfujita 		lp->d_partitions[0].p_size = LABELSECTOR + 1;
119*54007Sfujita 	}
120*54007Sfujita 
121*54007Sfujita 	/*
122*54007Sfujita 	 * read disklabel
123*54007Sfujita 	 */
124*54007Sfujita 	if (msg = sdreadlabel(makedev(4, (hd->hp_unit<<3)), sdstrategy, lp)) {
125*54007Sfujita 		if (msg != NULL) {
126*54007Sfujita 			printf("sd%d: %s\n", hd->hp_unit, msg);
127*54007Sfujita 			return(0);
128*54007Sfujita 		}
129*54007Sfujita 	}
130*54007Sfujita 
131*54007Sfujita 	sc->sc_flags = SDF_ALIVE;
132*54007Sfujita 	return(1);
133*54007Sfujita }
134*54007Sfujita 
135*54007Sfujita static struct scsi_inquiry inqbuf;
136*54007Sfujita static struct scsi_fmt_cdb inq = {
137*54007Sfujita 	6,
138*54007Sfujita 	CMD_INQUIRY, 0, 0, 0, sizeof(inqbuf), 0
139*54007Sfujita };
140*54007Sfujita 
141*54007Sfujita static u_long capbuf[2];
142*54007Sfujita struct scsi_fmt_cdb cap = {
143*54007Sfujita 	10,
144*54007Sfujita 	CMD_READ_CAPACITY, 0, 0, 0, 0, 0, 0, 0, 0, 0
145*54007Sfujita };
146*54007Sfujita 
147*54007Sfujita int
148*54007Sfujita sdident(sc, hd)
149*54007Sfujita 	struct sd_softc *sc;
150*54007Sfujita 	struct hp_device *hd;
151*54007Sfujita {
152*54007Sfujita 	char idstr[32];
153*54007Sfujita 	int unit;
154*54007Sfujita 	register int ctlr, slave;
155*54007Sfujita 	register int i;
156*54007Sfujita 	register int tries = 10;
157*54007Sfujita 
158*54007Sfujita 	ctlr = hd->hp_ctlr;
159*54007Sfujita 	slave = hd->hp_slave;
160*54007Sfujita 	unit = sc->sc_punit;
161*54007Sfujita 
162*54007Sfujita 	/*
163*54007Sfujita 	 * See if unit exists and is a disk then read block size & nblocks.
164*54007Sfujita 	 */
165*54007Sfujita 	while ((i = scsi_test_unit_rdy(ctlr, slave, unit)) != 0) {
166*54007Sfujita 		if (i < 0 || --tries < 0)
167*54007Sfujita 			return (-1);
168*54007Sfujita 		if (i == STS_CHECKCOND) {
169*54007Sfujita 			u_char sensebuf[8];
170*54007Sfujita 			struct scsi_xsense *sp = (struct scsi_xsense *)sensebuf;
171*54007Sfujita 
172*54007Sfujita 			scsi_request_sense(ctlr, slave, unit, sensebuf, 8);
173*54007Sfujita 			if (sp->class == 7 && sp->key == 6)
174*54007Sfujita 				/* drive doing an RTZ -- give it a while */
175*54007Sfujita 				DELAY(1000000);
176*54007Sfujita 		}
177*54007Sfujita 		DELAY(1000);
178*54007Sfujita 	}
179*54007Sfujita 	if (scsi_immed_command(ctlr, slave, unit, &inq, (u_char *)&inqbuf,
180*54007Sfujita 			       sizeof(inqbuf)) ||
181*54007Sfujita 	    scsi_immed_command(ctlr, slave, unit, &cap, (u_char *)&capbuf,
182*54007Sfujita 			       sizeof(capbuf)))
183*54007Sfujita 		/* doesn't exist or not a CCS device */
184*54007Sfujita 		return (-1);
185*54007Sfujita 
186*54007Sfujita 	switch (inqbuf.type) {
187*54007Sfujita 	case 0:		/* disk */
188*54007Sfujita 	case 4:		/* WORM */
189*54007Sfujita 	case 5:		/* CD-ROM */
190*54007Sfujita 	case 7:		/* Magneto-optical */
191*54007Sfujita 		break;
192*54007Sfujita 	default:	/* not a disk */
193*54007Sfujita 		return (-1);
194*54007Sfujita 	}
195*54007Sfujita 	sc->sc_blks    = capbuf[0];
196*54007Sfujita 	sc->sc_blksize = capbuf[1];
197*54007Sfujita 
198*54007Sfujita 	bcopy((caddr_t)&inqbuf.vendor_id, (caddr_t)idstr, 28);
199*54007Sfujita 	for (i = 27; i > 23; --i)
200*54007Sfujita 		if (idstr[i] != ' ')
201*54007Sfujita 			break;
202*54007Sfujita 	idstr[i+1] = 0;
203*54007Sfujita 	for (i = 23; i > 7; --i)
204*54007Sfujita 		if (idstr[i] != ' ')
205*54007Sfujita 			break;
206*54007Sfujita 	idstr[i+1] = 0;
207*54007Sfujita 	for (i = 7; i >= 0; --i)
208*54007Sfujita 		if (idstr[i] != ' ')
209*54007Sfujita 			break;
210*54007Sfujita 	idstr[i+1] = 0;
211*54007Sfujita 	printf("sd%d: %s %s rev %s", hd->hp_unit, idstr, &idstr[8],
212*54007Sfujita 	       &idstr[24]);
213*54007Sfujita 
214*54007Sfujita 	printf(", %d %d byte blocks\n", sc->sc_blks, sc->sc_blksize);
215*54007Sfujita 	if (sc->sc_blksize != DEV_BSIZE) {
216*54007Sfujita 		printf("sd%d: need %d byte blocks - drive ignored\n", unit, DEV_BSIZE);
217*54007Sfujita 		return(1);
218*54007Sfujita 	}
219*54007Sfujita 
220*54007Sfujita 	sc->sc_wpms = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
221*54007Sfujita 	return(inqbuf.type);
222*54007Sfujita }
223*54007Sfujita 
224*54007Sfujita 
225*54007Sfujita /*
226*54007Sfujita  * Open
227*54007Sfujita  */
228*54007Sfujita 
229*54007Sfujita int
230*54007Sfujita sdopen(dev, flags, mode, p)
231*54007Sfujita 	dev_t dev;
232*54007Sfujita 	int flags, mode;
233*54007Sfujita 	struct proc *p;
234*54007Sfujita {
235*54007Sfujita 	register int unit = sdunit(dev);
236*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
237*54007Sfujita 
238*54007Sfujita 	if (unit >= NSD)
239*54007Sfujita 		return(ENXIO);
240*54007Sfujita 	if ((sc->sc_flags & SDF_ALIVE) == 0 && suser(p->p_ucred, &p->p_acflag))
241*54007Sfujita 		return(ENXIO);
242*54007Sfujita 
243*54007Sfujita 	if (sc->sc_hd->hp_dk >= 0)
244*54007Sfujita 		dk_wpms[sc->sc_hd->hp_dk] = sc->sc_wpms;
245*54007Sfujita 	return(0);
246*54007Sfujita }
247*54007Sfujita 
248*54007Sfujita 
249*54007Sfujita /*
250*54007Sfujita  * Strategy
251*54007Sfujita  */
252*54007Sfujita 
253*54007Sfujita int
254*54007Sfujita sdstrategy(bp)
255*54007Sfujita 	register struct buf *bp;
256*54007Sfujita {
257*54007Sfujita 	register int unit = sdunit(bp->b_dev);
258*54007Sfujita 	register int part = sdpart(bp->b_dev);
259*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
260*54007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
261*54007Sfujita 	register struct partition *pp = &(lp->d_partitions[part]);
262*54007Sfujita 	register struct buf *dp = &sdtab[unit];
263*54007Sfujita 	register daddr_t bn;
264*54007Sfujita 	register int sz, s;
265*54007Sfujita 
266*54007Sfujita #ifdef DEBUG
267*54007Sfujita 	printf("sdstrategy: bp->b_blkno = %d, bp->bcount = %d\n",
268*54007Sfujita 	       bp->b_blkno, bp->b_bcount);
269*54007Sfujita #endif
270*54007Sfujita 	bn = bp->b_blkno;
271*54007Sfujita 	sz = howmany(bp->b_bcount, DEV_BSIZE);
272*54007Sfujita 
273*54007Sfujita 	/* check that tracsfer is within a drive's partition */
274*54007Sfujita 
275*54007Sfujita 	if (bn < 0 || (bn + sz) > pp->p_size) {
276*54007Sfujita 		sz = pp->p_size - bn;
277*54007Sfujita 		if (sz == 0) {
278*54007Sfujita 			bp->b_resid = bp->b_bcount;
279*54007Sfujita 			goto done;
280*54007Sfujita 		}
281*54007Sfujita 		if (sz < 0) {
282*54007Sfujita 			bp->b_error = EINVAL;
283*54007Sfujita 			bp->b_flags |= B_ERROR;
284*54007Sfujita 			goto done;
285*54007Sfujita 		}
286*54007Sfujita 		bp->b_bcount = dbtob(sz);
287*54007Sfujita 	}
288*54007Sfujita 
289*54007Sfujita 	/* calculate LBA for transfer */
290*54007Sfujita 
291*54007Sfujita 	bp->b_lba = bn + pp->p_offset;
292*54007Sfujita 
293*54007Sfujita 	/* raise priority to block sdintr */
294*54007Sfujita 
295*54007Sfujita 	s = splbio();
296*54007Sfujita 
297*54007Sfujita 	/* call disksort to sort request into drive queue */
298*54007Sfujita 
299*54007Sfujita 	disksort(dp, bp);
300*54007Sfujita 
301*54007Sfujita #ifdef DEBUG
302*54007Sfujita 	printf("sdstrategy: dp->b_active = %d\n", dp->b_active);
303*54007Sfujita #endif
304*54007Sfujita 	if (dp->b_active == 0) {			/*  */
305*54007Sfujita 		dp->b_active = 1;
306*54007Sfujita 		sdustart(unit);
307*54007Sfujita 	}
308*54007Sfujita 
309*54007Sfujita 	/* lower priority */
310*54007Sfujita 
311*54007Sfujita 	splx(s);
312*54007Sfujita 
313*54007Sfujita 	return;
314*54007Sfujita 
315*54007Sfujita done:
316*54007Sfujita 	biodone(bp);
317*54007Sfujita }
318*54007Sfujita 
319*54007Sfujita int
320*54007Sfujita sdustart(unit)
321*54007Sfujita 	register int unit;
322*54007Sfujita {
323*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
324*54007Sfujita 	register struct hp_device *hp = sc->sc_hd;
325*54007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
326*54007Sfujita 	register struct buf *bp = sdtab[unit].b_actf;
327*54007Sfujita 	register struct scsi_fmt_cdb *cmd;
328*54007Sfujita 
329*54007Sfujita 	cmd = bp->b_flags & B_READ? &sd_read_cmd : &sd_write_cmd;
330*54007Sfujita 	*(int *)(&cmd->cdb[2]) = bp->b_lba;
331*54007Sfujita 	*(u_short *)(&cmd->cdb[7]) = howmany(bp->b_bcount, DEV_BSIZE);
332*54007Sfujita 
333*54007Sfujita 	dq->dq_cdb   = cmd;
334*54007Sfujita 	dq->dq_bp    = bp;
335*54007Sfujita 	dq->dq_flags = DQ_DISCONNECT;	/* SCSI Disconnect */
336*54007Sfujita 
337*54007Sfujita 	if (screq(dq))
338*54007Sfujita 		sdstart(unit);
339*54007Sfujita }
340*54007Sfujita 
341*54007Sfujita int
342*54007Sfujita sdstart(unit)
343*54007Sfujita 	register int unit;
344*54007Sfujita {
345*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
346*54007Sfujita 	register struct hp_device *hp = sc->sc_hd;
347*54007Sfujita 
348*54007Sfujita 	if (hp->hp_dk >= 0) {
349*54007Sfujita 		dk_busy |= 1 << hp->hp_dk;
350*54007Sfujita 	}
351*54007Sfujita 
352*54007Sfujita 	scstart(hp->hp_ctlr);
353*54007Sfujita }
354*54007Sfujita 
355*54007Sfujita 
356*54007Sfujita /*
357*54007Sfujita  * Return:
358*54007Sfujita  *	0	if not really an error
359*54007Sfujita  *	<0	if we should do a retry
360*54007Sfujita  *	>0	if a fatal error
361*54007Sfujita  */
362*54007Sfujita static int
363*54007Sfujita sderror(unit, sc, hp, stat)
364*54007Sfujita 	int unit, stat;
365*54007Sfujita 	register struct sd_softc *sc;
366*54007Sfujita 	register struct hp_device *hp;
367*54007Sfujita {
368*54007Sfujita 	int cond = 1;
369*54007Sfujita 
370*54007Sfujita 	sdsense[unit].status = stat;
371*54007Sfujita 	if (stat & STS_CHECKCOND) {
372*54007Sfujita 		struct scsi_xsense *sp;
373*54007Sfujita 
374*54007Sfujita 		scsi_request_sense(hp->hp_ctlr, hp->hp_slave,
375*54007Sfujita 				   sc->sc_punit, sdsense[unit].sense,
376*54007Sfujita 				   sizeof(sdsense[unit].sense));
377*54007Sfujita 		sp = (struct scsi_xsense *)sdsense[unit].sense;
378*54007Sfujita 		printf("sd%d: scsi sense class %d, code %d", unit,
379*54007Sfujita 			sp->class, sp->code);
380*54007Sfujita 		if (sp->class == 7) {
381*54007Sfujita 			printf(", key %d", sp->key);
382*54007Sfujita 			if (sp->valid)
383*54007Sfujita 				printf(", blk %d", *(int *)&sp->info1);
384*54007Sfujita 			switch (sp->key) {
385*54007Sfujita 			/* no sense, try again */
386*54007Sfujita 			case 0:
387*54007Sfujita 				cond = -1;
388*54007Sfujita 				break;
389*54007Sfujita 			/* recovered error, not a problem */
390*54007Sfujita 			case 1:
391*54007Sfujita 				cond = 0;
392*54007Sfujita 				break;
393*54007Sfujita 			}
394*54007Sfujita 		}
395*54007Sfujita 		printf("\n");
396*54007Sfujita 	}
397*54007Sfujita 	return(cond);
398*54007Sfujita }
399*54007Sfujita 
400*54007Sfujita /*
401*54007Sfujita  * Interrupt
402*54007Sfujita  */
403*54007Sfujita 
404*54007Sfujita int
405*54007Sfujita sdintr(unit, stat)
406*54007Sfujita 	register int unit;
407*54007Sfujita 	int stat;
408*54007Sfujita {
409*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
410*54007Sfujita 	register struct hp_device *hp = sc->sc_hd;
411*54007Sfujita 	register struct scsi_queue *dq = &sc->sc_dq;
412*54007Sfujita 	register struct buf *bp = dq->dq_bp;
413*54007Sfujita 	int cond;
414*54007Sfujita 
415*54007Sfujita #ifdef DEBUG
416*54007Sfujita 	printf("sdintr(unit = %d, stat = %d)\n", unit, stat);
417*54007Sfujita #endif
418*54007Sfujita 
419*54007Sfujita 	if (stat == SC_IO_TIMEOUT) {
420*54007Sfujita 		printf("sdintr: sd%d timeout error\n", unit, stat);
421*54007Sfujita 	}
422*54007Sfujita 
423*54007Sfujita 	if (hp->hp_dk >= 0) {
424*54007Sfujita 		dk_busy &=~ (1 << hp->hp_dk);
425*54007Sfujita 		if (stat == 0) {
426*54007Sfujita 			++dk_seek[hp->hp_dk];
427*54007Sfujita 			++dk_xfer[hp->hp_dk];
428*54007Sfujita 			dk_wds[hp->hp_dk] += bp->b_bcount >> 6;
429*54007Sfujita 		}
430*54007Sfujita 	}
431*54007Sfujita 
432*54007Sfujita 	if (bp->b_flags & B_READ) {
433*54007Sfujita 		sd_iostat[unit].imin = MIN(dq->dq_imin, sd_iostat[unit].imin);
434*54007Sfujita 		if (dq->dq_imax > sd_iostat[unit].imax) {
435*54007Sfujita 			sd_iostat[unit].imax = dq->dq_imax;
436*54007Sfujita #ifdef SD_IOSTAT
437*54007Sfujita 			printf("sdintr: sd%d  INPUT	MAX = %d, MIN = %d\n",
438*54007Sfujita 			       unit, sd_iostat[unit].imax, sd_iostat[unit].imin);
439*54007Sfujita #endif
440*54007Sfujita 		}
441*54007Sfujita 	} else {
442*54007Sfujita 		sd_iostat[unit].omin = MIN(dq->dq_omin, sd_iostat[unit].omin);
443*54007Sfujita 		if (dq->dq_omax > sd_iostat[unit].omax) {
444*54007Sfujita 			sd_iostat[unit].omax = dq->dq_omax;
445*54007Sfujita #ifdef SD_IOSTAT
446*54007Sfujita 			printf("sdintr: sd%d  OUTPUT	MAX = %d, MIN = %d\n",
447*54007Sfujita 			       unit, sd_iostat[unit].omax, sd_iostat[unit].omin);
448*54007Sfujita #endif
449*54007Sfujita 		}
450*54007Sfujita 	}
451*54007Sfujita 
452*54007Sfujita 	if (stat != 0) {
453*54007Sfujita 		if (stat > 0) {
454*54007Sfujita #ifdef DEBUGPRINT
455*54007Sfujita 			dbgprintall();
456*54007Sfujita 			printf("\n");
457*54007Sfujita #endif
458*54007Sfujita 			cond = sderror(unit, sc, hp, stat);
459*54007Sfujita 			if (cond) {
460*54007Sfujita 				if (cond < 0 && sdtab[unit].b_errcnt++ < SDRETRY) {
461*54007Sfujita 					sdstart(unit);
462*54007Sfujita 					return;
463*54007Sfujita 				}
464*54007Sfujita 			}
465*54007Sfujita 		} else {
466*54007Sfujita 			if (sdtab[unit].b_errcnt++ < SDRETRY) {
467*54007Sfujita 				printf("sdintr: sd%d restart IO request\n", unit);
468*54007Sfujita 				sdstart(unit);
469*54007Sfujita 				return;
470*54007Sfujita 			}
471*54007Sfujita 		}
472*54007Sfujita 		bp->b_flags |= B_ERROR;
473*54007Sfujita 		bp->b_error = EIO;
474*54007Sfujita 	}
475*54007Sfujita 
476*54007Sfujita 	sdtab[unit].b_errcnt = 0;
477*54007Sfujita 	sdtab[unit].b_actf = bp->b_actf;
478*54007Sfujita 
479*54007Sfujita 	bp->b_resid = 0;
480*54007Sfujita 
481*54007Sfujita 	biodone(bp);
482*54007Sfujita 
483*54007Sfujita 	scfree(dq);
484*54007Sfujita 
485*54007Sfujita 	if (sdtab[unit].b_actf) {
486*54007Sfujita 		sdustart(unit);
487*54007Sfujita 	} else {
488*54007Sfujita 		sdtab[unit].b_active = 0;
489*54007Sfujita 	}
490*54007Sfujita }
491*54007Sfujita 
492*54007Sfujita 
493*54007Sfujita /*
494*54007Sfujita  * RAW Device Routines
495*54007Sfujita  */
496*54007Sfujita 
497*54007Sfujita int
498*54007Sfujita sdread(dev, uio, flags)
499*54007Sfujita 	dev_t dev;
500*54007Sfujita 	struct uio *uio;
501*54007Sfujita 	int flags;
502*54007Sfujita {
503*54007Sfujita 	register int unit = sdunit(dev);
504*54007Sfujita 
505*54007Sfujita 	return (physio(sdstrategy, NULL, dev, B_READ, minphys, uio));
506*54007Sfujita }
507*54007Sfujita 
508*54007Sfujita int
509*54007Sfujita sdwrite(dev, uio, flags)
510*54007Sfujita 	dev_t dev;
511*54007Sfujita 	struct uio *uio;
512*54007Sfujita 	int flags;
513*54007Sfujita {
514*54007Sfujita 	register int unit = sdunit(dev);
515*54007Sfujita 
516*54007Sfujita 	return (physio(sdstrategy, NULL, dev, B_WRITE, minphys, uio));
517*54007Sfujita }
518*54007Sfujita 
519*54007Sfujita int
520*54007Sfujita sdioctl(dev, cmd, data, flag, p)
521*54007Sfujita 	dev_t dev;
522*54007Sfujita 	int cmd;
523*54007Sfujita 	caddr_t data;
524*54007Sfujita 	int flag;
525*54007Sfujita 	struct proc *p;
526*54007Sfujita {
527*54007Sfujita 	int unit = sdunit(dev);
528*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
529*54007Sfujita 	register struct disklabel *lp = &sdlabel[unit];
530*54007Sfujita 	int error = 0;
531*54007Sfujita 
532*54007Sfujita 	switch (cmd) {
533*54007Sfujita 
534*54007Sfujita 	case DIOCGDINFO:
535*54007Sfujita 		*(struct disklabel *)data = *lp;
536*54007Sfujita 		break;
537*54007Sfujita 
538*54007Sfujita 	case DIOCGPART:
539*54007Sfujita 		((struct partinfo *)data)->disklab = lp;
540*54007Sfujita 		((struct partinfo *)data)->part =
541*54007Sfujita 		    &lp->d_partitions[sdpart(dev)];
542*54007Sfujita 		break;
543*54007Sfujita 
544*54007Sfujita 	default:
545*54007Sfujita 		error = ENOTTY;
546*54007Sfujita 		break;
547*54007Sfujita 	}
548*54007Sfujita 	return (error);
549*54007Sfujita }
550*54007Sfujita 
551*54007Sfujita 
552*54007Sfujita /*
553*54007Sfujita  * Size
554*54007Sfujita  */
555*54007Sfujita 
556*54007Sfujita int
557*54007Sfujita sdsize(dev)
558*54007Sfujita 	dev_t dev;
559*54007Sfujita {
560*54007Sfujita 	register int unit = sdunit(dev);
561*54007Sfujita 	register struct sd_softc *sc = &sd_softc[unit];
562*54007Sfujita 
563*54007Sfujita 	if (unit >= NSD || (sc->sc_flags & SDF_ALIVE) == 0)
564*54007Sfujita 		return(-1);
565*54007Sfujita 
566*54007Sfujita 	return(sdlabel[unit].d_partitions[sdpart(dev)].p_size);
567*54007Sfujita }
568*54007Sfujita 
569*54007Sfujita 
570*54007Sfujita /*
571*54007Sfujita  * Dump
572*54007Sfujita  */
573*54007Sfujita 
574*54007Sfujita int
575*54007Sfujita sddump(dev)
576*54007Sfujita 	dev_t dev;
577*54007Sfujita {
578*54007Sfujita }
579*54007Sfujita 
580*54007Sfujita /*
581*54007Sfujita  * Disk Subs
582*54007Sfujita  */
583*54007Sfujita 
584*54007Sfujita /*
585*54007Sfujita  * Attempt to read a disk label from a device
586*54007Sfujita  * using the indicated stategy routine.
587*54007Sfujita  * The label must be partly set up before this:
588*54007Sfujita  * secpercyl and anything required in the strategy routine
589*54007Sfujita  * (e.g., sector size) must be filled in before calling us.
590*54007Sfujita  * Returns null on success and an error string on failure.
591*54007Sfujita  */
592*54007Sfujita char *
593*54007Sfujita sdreadlabel(dev, strat, lp)
594*54007Sfujita 	dev_t dev;
595*54007Sfujita 	int (*strat)();
596*54007Sfujita 	register struct disklabel *lp;
597*54007Sfujita {
598*54007Sfujita 	register struct buf *bp;
599*54007Sfujita 	struct disklabel *dlp;
600*54007Sfujita 	char *msg = NULL;
601*54007Sfujita 
602*54007Sfujita 	if (lp->d_secperunit == 0)
603*54007Sfujita 		lp->d_secperunit = 0x1fffffff;
604*54007Sfujita 	lp->d_npartitions = 1;
605*54007Sfujita 	if (lp->d_partitions[0].p_size == 0)
606*54007Sfujita 		lp->d_partitions[0].p_size = 0x1fffffff;
607*54007Sfujita 	lp->d_partitions[0].p_offset = 0;
608*54007Sfujita 
609*54007Sfujita 	bp = geteblk((int)lp->d_secsize);
610*54007Sfujita 	bp->b_dev = dev;
611*54007Sfujita 	bp->b_blkno = LABELSECTOR;
612*54007Sfujita 	bp->b_bcount = lp->d_secsize;
613*54007Sfujita 	bp->b_flags = B_BUSY | B_READ;
614*54007Sfujita 	(*strat)(bp);
615*54007Sfujita 	if (biowait(bp)) {
616*54007Sfujita 		msg = "I/O error";
617*54007Sfujita 	} else {
618*54007Sfujita 		for (dlp = (struct disklabel *)bp->b_un.b_addr;
619*54007Sfujita 		     dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
620*54007Sfujita 		     dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
621*54007Sfujita 			if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
622*54007Sfujita 				if (msg == NULL)
623*54007Sfujita 					msg = "no disk label";
624*54007Sfujita 			} else if (dlp->d_npartitions > MAXPARTITIONS ||
625*54007Sfujita 				   dkcksum(dlp) != 0)
626*54007Sfujita 				msg = "disk label corrupted";
627*54007Sfujita 			else {
628*54007Sfujita 				*lp = *dlp;
629*54007Sfujita 				msg = NULL;
630*54007Sfujita 				break;
631*54007Sfujita 			}
632*54007Sfujita 		}
633*54007Sfujita 	}
634*54007Sfujita 	bp->b_flags = B_INVAL | B_AGE;
635*54007Sfujita 	brelse(bp);
636*54007Sfujita 	return (msg);
637*54007Sfujita }
638*54007Sfujita 
639*54007Sfujita #ifdef notyet
640*54007Sfujita 
641*54007Sfujita /*
642*54007Sfujita  * Checksum routine for OMRON native disklabel
643*54007Sfujita  */
644*54007Sfujita 
645*54007Sfujita #define	OMRON_LBLSIZE	512
646*54007Sfujita 
647*54007Sfujita u_short
648*54007Sfujita omcksum(omp)
649*54007Sfujita 	register char *omp;
650*54007Sfujita {
651*54007Sfujita 	register u_short *start, *end;
652*54007Sfujita 	register u_short sum = 0;
653*54007Sfujita 
654*54007Sfujita 	start = (u_short *) omp;
655*54007Sfujita 	end = (u_short *) &start[(OMRON_LBLSIZE/sizeof(u_short) - 1)];
656*54007Sfujita 	while (start < end)
657*54007Sfujita 		sum ^= *start++;
658*54007Sfujita 
659*54007Sfujita 	printf("omcksum: saved  ... 0x%s\n", hexstr(*end, 4));
660*54007Sfujita 	printf("omcksum: calced ... 0x%s\n", hexstr(sum, 4));
661*54007Sfujita 
662*54007Sfujita 	return (sum);
663*54007Sfujita }
664*54007Sfujita 
665*54007Sfujita /*
666*54007Sfujita  * Write disk label back to device after modification.
667*54007Sfujita  */
668*54007Sfujita sdwritelabel(dev, strat, lp)
669*54007Sfujita 	dev_t dev;
670*54007Sfujita 	int (*strat)();
671*54007Sfujita 	register struct disklabel *lp;
672*54007Sfujita {
673*54007Sfujita 	struct buf *bp;
674*54007Sfujita 	struct disklabel *dlp;
675*54007Sfujita 	int labelpart;
676*54007Sfujita 	int error = 0;
677*54007Sfujita 
678*54007Sfujita 	labelpart = sdpart(dev);
679*54007Sfujita 	if (lp->d_partitions[labelpart].p_offset != 0) {
680*54007Sfujita 		if (lp->d_partitions[0].p_offset != 0)
681*54007Sfujita 			return (EXDEV);			/* not quite right */
682*54007Sfujita 		labelpart = 0;
683*54007Sfujita 	}
684*54007Sfujita 
685*54007Sfujita 	bp = geteblk((int)lp->d_secsize);
686*54007Sfujita 	bp->b_dev = makedev(major(dev), sdminor(sdunit(dev), labelpart));
687*54007Sfujita 	bp->b_blkno = LABELSECTOR;
688*54007Sfujita 	bp->b_bcount = lp->d_secsize;
689*54007Sfujita 	bp->b_flags = B_READ;
690*54007Sfujita 	(*strat)(bp);
691*54007Sfujita 	if (error = biowait(bp))
692*54007Sfujita 		goto done;
693*54007Sfujita 
694*54007Sfujita 	for (dlp = (struct disklabel *)bp->b_un.b_addr;
695*54007Sfujita 	    dlp <= (struct disklabel *)
696*54007Sfujita 	      (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
697*54007Sfujita 	    dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
698*54007Sfujita 		if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
699*54007Sfujita 		    dkcksum(dlp) == 0) {
700*54007Sfujita 			omcksum(bp->b_un.b_addr);
701*54007Sfujita /*
702*54007Sfujita 			*dlp = *lp;
703*54007Sfujita 			bp->b_flags = B_WRITE;
704*54007Sfujita 			(*strat)(bp);
705*54007Sfujita 			error = biowait(bp);
706*54007Sfujita 			goto done;
707*54007Sfujita  */
708*54007Sfujita 		}
709*54007Sfujita 	}
710*54007Sfujita 	error = ESRCH;
711*54007Sfujita done:
712*54007Sfujita 	brelse(bp);
713*54007Sfujita 	return (error);
714*54007Sfujita }
715*54007Sfujita #endif
716*54007Sfujita 
717*54007Sfujita #endif
718