xref: /csrg-svn/sys/dev/cd.c (revision 45788)
141480Smckusick /*
241480Smckusick  * Copyright (c) 1988 University of Utah.
341480Smckusick  * Copyright (c) 1990 The Regents of the University of California.
441480Smckusick  * All rights reserved.
541480Smckusick  *
641480Smckusick  * This code is derived from software contributed to Berkeley by
741480Smckusick  * the Systems Programming Group of the University of Utah Computer
841480Smckusick  * Science Department.
941480Smckusick  *
1041480Smckusick  * %sccs.include.redist.c%
1141480Smckusick  *
1245480Smckusick  * from: Utah $Hdr: cd.c 1.1 90/07/09$
1341480Smckusick  *
14*45788Sbostic  *	@(#)cd.c	7.3 (Berkeley) 12/16/90
1541480Smckusick  */
1641480Smckusick 
1741480Smckusick /*
1841480Smckusick  * "Concatenated" disk driver.
1941480Smckusick  */
2041480Smckusick #include "cd.h"
2141480Smckusick #if NCD > 0
2241480Smckusick 
23*45788Sbostic #include "sys/param.h"
24*45788Sbostic #include "sys/systm.h"
25*45788Sbostic #include "sys/errno.h"
26*45788Sbostic #include "sys/dkstat.h"
27*45788Sbostic #include "sys/buf.h"
28*45788Sbostic #include "sys/malloc.h"
29*45788Sbostic #include "sys/conf.h"
3041480Smckusick 
3141480Smckusick #include "cdvar.h"
3241480Smckusick 
3341480Smckusick #ifdef DEBUG
3441480Smckusick int cddebug = 0x00;
3541480Smckusick #define CDB_FOLLOW	0x01
3641480Smckusick #define CDB_INIT	0x02
3741480Smckusick #define CDB_IO		0x04
3841480Smckusick #endif
3941480Smckusick 
4041480Smckusick struct	buf cdbuf[NCD];
4141480Smckusick struct	buf *cdbuffer();
4241480Smckusick int	cdiodone();
4341480Smckusick 
4441480Smckusick #define	cdunit(x)	((minor(x) >> 3) & 0x7)	/* for consistency */
4541480Smckusick 
4641480Smckusick #define	getcbuf()	\
4741480Smckusick 	((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
4841480Smckusick #define putcbuf(bp)	\
4941480Smckusick 	free((caddr_t)(bp), M_DEVBUF)
5041480Smckusick 
5141480Smckusick struct cd_softc {
5241480Smckusick 	int		 sc_flags;		/* flags */
5341480Smckusick 	size_t		 sc_size;		/* size of cd */
5441480Smckusick 	int		 sc_ileave;		/* interleave */
5541480Smckusick 	int		 sc_ncdisks;		/* number of components */
5641480Smckusick 	struct cdcinfo	 sc_cinfo[NCDISKS];	/* component info */
5741480Smckusick 	struct cdiinfo	 *sc_itable;		/* interleave table */
5841480Smckusick 	int		 sc_usecnt;		/* number of requests active */
5941480Smckusick 	struct buf	 *sc_bp;		/* "current" request */
6041480Smckusick 	int		 sc_dk;			/* disk index */
6141480Smckusick } cd_softc[NCD];
6241480Smckusick 
6341480Smckusick /* sc_flags */
6441480Smckusick #define	CDF_ALIVE	0x01
6541480Smckusick #define CDF_INITED	0x02
6641480Smckusick 
6741480Smckusick cdinit(cd)
6841480Smckusick 	struct cddevice *cd;
6941480Smckusick {
7041480Smckusick 	register struct cd_softc *cs = &cd_softc[cd->cd_unit];
7141480Smckusick 	register struct cdcinfo *ci;
7241480Smckusick 	register size_t size;
7341480Smckusick 	register int ix;
7441480Smckusick 	size_t minsize;
7541480Smckusick 	dev_t dev;
7641480Smckusick 
7741480Smckusick #ifdef DEBUG
7841480Smckusick 	if (cddebug & (CDB_FOLLOW|CDB_INIT))
7941480Smckusick 		printf("cdinit: unit %d\n", cd->cd_unit);
8041480Smckusick #endif
8141480Smckusick 	cs->sc_dk = cd->cd_dk;
8241480Smckusick 	cs->sc_size = 0;
8341480Smckusick 	cs->sc_ileave = cd->cd_interleave;
8441480Smckusick 	cs->sc_ncdisks = 0;
8541480Smckusick 	/*
8641480Smckusick 	 * Verify that each component piece exists and record
8741480Smckusick 	 * relevant information about it.
8841480Smckusick 	 */
8941480Smckusick 	minsize = 0;
9041480Smckusick 	for (ix = 0; ix < NCDISKS; ix++) {
9141480Smckusick 		if ((dev = cd->cd_dev[ix]) == NODEV)
9241480Smckusick 			break;
9341480Smckusick 		ci = &cs->sc_cinfo[ix];
9441480Smckusick 		ci->ci_dev = dev;
9541480Smckusick 		/*
9641480Smckusick 		 * Calculate size (truncated to interleave boundary
9741480Smckusick 		 * if necessary.
9841480Smckusick 		 */
9941480Smckusick 		if (bdevsw[major(dev)].d_psize) {
10041480Smckusick 			size = (*bdevsw[major(dev)].d_psize)(dev);
10141480Smckusick 			if (size <= 0)
10241480Smckusick 				size = 0;
10341480Smckusick 		} else
10441480Smckusick 			size = 0;
10541480Smckusick 		if (cs->sc_ileave > 1)
10641480Smckusick 			size -= size % cs->sc_ileave;
10741480Smckusick 		if (size == 0)
10841480Smckusick 			return(0);
10941480Smckusick 		if (minsize == 0 || size < minsize)
11041480Smckusick 			minsize = size;
11141480Smckusick 		ci->ci_size = size;
11241480Smckusick 		cs->sc_size += size;
11341480Smckusick 		cs->sc_ncdisks++;
11441480Smckusick 	}
11541480Smckusick 	/*
11641480Smckusick 	 * If uniform interleave is desired set all sizes to that of
11741480Smckusick 	 * the smallest component.
11841480Smckusick 	 */
11941480Smckusick 	if (cd->cd_flags & CDF_UNIFORM) {
12041480Smckusick 		for (ci = cs->sc_cinfo;
12141480Smckusick 		     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
12241480Smckusick 			ci->ci_size = minsize;
12341480Smckusick 		cs->sc_size = cs->sc_ncdisks * minsize;
12441480Smckusick 	}
12541480Smckusick 	/*
12641480Smckusick 	 * Construct the interleave table
12741480Smckusick 	 */
12841480Smckusick 	if (!cdinterleave(cs))
12941480Smckusick 		return(0);
13041480Smckusick 	if (cd->cd_dk >= 0)
13141480Smckusick 		dk_wpms[cd->cd_dk] = 32 * (60 * DEV_BSIZE / 2);	/* XXX */
13241480Smckusick 	printf("cd%d: %d components (%d blocks) concatenated",
13341480Smckusick 	       cd->cd_unit, cs->sc_ncdisks, cs->sc_size);
13441480Smckusick 	if (cs->sc_ileave)
13541480Smckusick 		printf(", %d block interleave\n", cs->sc_ileave);
13641480Smckusick 	else
13741480Smckusick 		printf(" serially\n");
13841480Smckusick 	cs->sc_flags = CDF_ALIVE | CDF_INITED;
13941480Smckusick 	return(1);
14041480Smckusick }
14141480Smckusick 
14241480Smckusick cdinterleave(cs)
14341480Smckusick 	register struct cd_softc *cs;
14441480Smckusick {
14541480Smckusick 	register struct cdcinfo *ci, *smallci;
14641480Smckusick 	register struct cdiinfo *ii;
14741480Smckusick 	register daddr_t bn, lbn;
14841480Smckusick 	register int ix;
14941480Smckusick 	u_long size;
15041480Smckusick 
15141480Smckusick #ifdef DEBUG
15241480Smckusick 	if (cddebug & CDB_INIT)
15341480Smckusick 		printf("cdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
15441480Smckusick #endif
15541480Smckusick 	/*
15641480Smckusick 	 * Allocate an interleave table.
15741480Smckusick 	 * Chances are this is too big, but we don't care.
15841480Smckusick 	 */
15941480Smckusick 	size = (cs->sc_ncdisks + 1) * sizeof(struct cdiinfo);
16041480Smckusick 	cs->sc_itable = (struct cdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
16141480Smckusick 	bzero((caddr_t)cs->sc_itable, size);
16241480Smckusick 	/*
16341480Smckusick 	 * Trivial case: no interleave (actually interleave of disk size).
16441480Smckusick 	 * Each table entry represent a single component in its entirety.
16541480Smckusick 	 */
16641480Smckusick 	if (cs->sc_ileave == 0) {
16741480Smckusick 		bn = 0;
16841480Smckusick 		ii = cs->sc_itable;
16941480Smckusick 		for (ix = 0; ix < cs->sc_ncdisks; ix++) {
17041480Smckusick 			ii->ii_ndisk = 1;
17141480Smckusick 			ii->ii_startblk = bn;
17241480Smckusick 			ii->ii_startoff = 0;
17341480Smckusick 			ii->ii_index[0] = ix;
17441480Smckusick 			bn += cs->sc_cinfo[ix].ci_size;
17541480Smckusick 			ii++;
17641480Smckusick 		}
17741480Smckusick 		ii->ii_ndisk = 0;
17841480Smckusick #ifdef DEBUG
17941480Smckusick 		if (cddebug & CDB_INIT)
18041480Smckusick 			printiinfo(cs->sc_itable);
18141480Smckusick #endif
18241480Smckusick 		return(1);
18341480Smckusick 	}
18441480Smckusick 	/*
18541480Smckusick 	 * The following isn't fast or pretty; it doesn't have to be.
18641480Smckusick 	 */
18741480Smckusick 	size = 0;
18841480Smckusick 	bn = lbn = 0;
18941480Smckusick 	for (ii = cs->sc_itable; ; ii++) {
19041480Smckusick 		/*
19141480Smckusick 		 * Locate the smallest of the remaining components
19241480Smckusick 		 */
19341480Smckusick 		smallci = NULL;
19441480Smckusick 		for (ci = cs->sc_cinfo;
19541480Smckusick 		     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
19641480Smckusick 			if (ci->ci_size > size &&
19741480Smckusick 			    (smallci == NULL ||
19841480Smckusick 			     ci->ci_size < smallci->ci_size))
19941480Smckusick 				smallci = ci;
20041480Smckusick 		/*
20141480Smckusick 		 * Nobody left, all done
20241480Smckusick 		 */
20341480Smckusick 		if (smallci == NULL) {
20441480Smckusick 			ii->ii_ndisk = 0;
20541480Smckusick 			break;
20641480Smckusick 		}
20741480Smckusick 		/*
20841480Smckusick 		 * Record starting logical block and component offset
20941480Smckusick 		 */
21041480Smckusick 		ii->ii_startblk = bn / cs->sc_ileave;
21141480Smckusick 		ii->ii_startoff = lbn;
21241480Smckusick 		/*
21341480Smckusick 		 * Determine how many disks take part in this interleave
21441480Smckusick 		 * and record their indices.
21541480Smckusick 		 */
21641480Smckusick 		ix = 0;
21741480Smckusick 		for (ci = cs->sc_cinfo;
21841480Smckusick 		     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
21941480Smckusick 			if (ci->ci_size >= smallci->ci_size)
22041480Smckusick 				ii->ii_index[ix++] = ci - cs->sc_cinfo;
22141480Smckusick 		ii->ii_ndisk = ix;
22241480Smckusick 		bn += ix * (smallci->ci_size - size);
22341480Smckusick 		lbn = smallci->ci_size / cs->sc_ileave;
22441480Smckusick 		size = smallci->ci_size;
22541480Smckusick 	}
22641480Smckusick #ifdef DEBUG
22741480Smckusick 	if (cddebug & CDB_INIT)
22841480Smckusick 		printiinfo(cs->sc_itable);
22941480Smckusick #endif
23041480Smckusick 	return(1);
23141480Smckusick }
23241480Smckusick 
23341480Smckusick #ifdef DEBUG
23441480Smckusick printiinfo(ii)
23541480Smckusick 	struct cdiinfo *ii;
23641480Smckusick {
23741480Smckusick 	register int ix, i;
23841480Smckusick 
23941480Smckusick 	for (ix = 0; ii->ii_ndisk; ix++, ii++) {
24041480Smckusick 		printf(" itab[%d]: #dk %d sblk %d soff %d",
24141480Smckusick 		       ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
24241480Smckusick 		for (i = 0; i < ii->ii_ndisk; i++)
24341480Smckusick 			printf(" %d", ii->ii_index[i]);
24441480Smckusick 		printf("\n");
24541480Smckusick 	}
24641480Smckusick }
24741480Smckusick #endif
24841480Smckusick 
24941480Smckusick cdopen(dev, flags)
25041480Smckusick 	dev_t dev;
25141480Smckusick {
25241480Smckusick 	int unit = cdunit(dev);
25341480Smckusick 	register struct cd_softc *cs = &cd_softc[unit];
25441480Smckusick 
25541480Smckusick #ifdef DEBUG
25641480Smckusick 	if (cddebug & CDB_FOLLOW)
25741480Smckusick 		printf("cdopen(%x, %x)\n", dev, flags);
25841480Smckusick #endif
25941480Smckusick 	if (unit >= NCD || (cs->sc_flags & CDF_ALIVE) == 0)
26041480Smckusick 		return(ENXIO);
26141480Smckusick 	return(0);
26241480Smckusick }
26341480Smckusick 
26441480Smckusick cdstrategy(bp)
26541480Smckusick 	register struct buf *bp;
26641480Smckusick {
26741480Smckusick 	register int unit = cdunit(bp->b_dev);
26841480Smckusick 	register struct cd_softc *cs = &cd_softc[unit];
26945480Smckusick 	register daddr_t bn;
27045480Smckusick 	register int sz, s;
27141480Smckusick 
27241480Smckusick #ifdef DEBUG
27341480Smckusick 	if (cddebug & CDB_FOLLOW)
27441480Smckusick 		printf("cdstrategy(%x): unit %d\n", bp, unit);
27541480Smckusick #endif
27641480Smckusick 	if ((cs->sc_flags & CDF_INITED) == 0) {
27741480Smckusick 		bp->b_error = ENXIO;
27845480Smckusick 		bp->b_flags |= B_ERROR;
27945480Smckusick 		goto done;
28041480Smckusick 	}
28141480Smckusick 	bn = bp->b_blkno;
28245480Smckusick 	sz = howmany(bp->b_bcount, DEV_BSIZE);
28341480Smckusick 	if (bn < 0 || bn + sz > cs->sc_size) {
28445480Smckusick 		sz = cs->sc_size - bn;
28545480Smckusick 		if (sz == 0) {
28645480Smckusick 			bp->b_resid = bp->b_bcount;
28741480Smckusick 			goto done;
28845480Smckusick 		}
28945480Smckusick 		if (sz < 0) {
29045480Smckusick 			bp->b_error = EINVAL;
29145480Smckusick 			bp->b_flags |= B_ERROR;
29245480Smckusick 			goto done;
29345480Smckusick 		}
29445480Smckusick 		bp->b_bcount = dbtob(sz);
29541480Smckusick 	}
29645480Smckusick 	bp->b_resid = bp->b_bcount;
29741480Smckusick 	/*
29841480Smckusick 	 * "Start" the unit.
29941480Smckusick 	 * XXX: the use of sc_bp is just to retain the "traditional"
30041480Smckusick 	 * interface to the start routine.
30141480Smckusick 	 */
30241480Smckusick 	s = splbio();
30341480Smckusick 	cs->sc_bp = bp;
30441480Smckusick 	cdstart(unit);
30541480Smckusick 	splx(s);
30641480Smckusick 	return;
30741480Smckusick done:
30845480Smckusick 	biodone(bp);
30941480Smckusick }
31041480Smckusick 
31141480Smckusick cdstart(unit)
31241480Smckusick 	int unit;
31341480Smckusick {
31441480Smckusick 	register struct cd_softc *cs = &cd_softc[unit];
31541480Smckusick 	register struct buf *bp = cs->sc_bp;
31641480Smckusick 	register long bcount, rcount;
31741480Smckusick 	struct buf *cbp;
31841480Smckusick 	caddr_t addr;
31941480Smckusick 	daddr_t bn;
32041480Smckusick 
32141480Smckusick #ifdef DEBUG
32241480Smckusick 	if (cddebug & CDB_FOLLOW)
32341480Smckusick 		printf("cdstart(%d)\n", unit);
32441480Smckusick #endif
32541480Smckusick 	/*
32641480Smckusick 	 * Instumentation (not real meaningful)
32741480Smckusick 	 */
32841480Smckusick 	cs->sc_usecnt++;
32941480Smckusick 	if (cs->sc_dk >= 0) {
33041480Smckusick 		dk_busy |= 1 << cs->sc_dk;
33141480Smckusick 		dk_xfer[cs->sc_dk]++;
33241480Smckusick 		dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
33341480Smckusick 	}
33441480Smckusick 	/*
33541480Smckusick 	 * Allocate component buffers and fire off the requests
33641480Smckusick 	 */
33741480Smckusick 	bn = bp->b_blkno;
33841480Smckusick 	addr = bp->b_un.b_addr;
33941480Smckusick 	for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
34041480Smckusick 		cbp = cdbuffer(cs, bp, bn, addr, bcount);
34141480Smckusick 		rcount = cbp->b_bcount;
34241480Smckusick 		(*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
34341480Smckusick 		bn += btodb(rcount);
34441480Smckusick 		addr += rcount;
34541480Smckusick 	}
34641480Smckusick }
34741480Smckusick 
34841480Smckusick /*
34941480Smckusick  * Build a component buffer header.
35041480Smckusick  */
35141480Smckusick struct buf *
35241480Smckusick cdbuffer(cs, bp, bn, addr, bcount)
35341480Smckusick 	register struct cd_softc *cs;
35441480Smckusick 	struct buf *bp;
35541480Smckusick 	daddr_t bn;
35641480Smckusick 	caddr_t addr;
35741480Smckusick 	long bcount;
35841480Smckusick {
35941480Smckusick 	register struct cdcinfo *ci;
36041480Smckusick 	register struct buf *cbp;
36141480Smckusick 	register daddr_t cbn, cboff;
36241480Smckusick 
36341480Smckusick #ifdef DEBUG
36441480Smckusick 	if (cddebug & CDB_IO)
36541480Smckusick 		printf("cdbuffer(%x, %x, %d, %x, %d)\n",
36641480Smckusick 		       cs, bp, bn, addr, bcount);
36741480Smckusick #endif
36841480Smckusick 	/*
36941480Smckusick 	 * Determine which component bn falls in.
37041480Smckusick 	 */
37141480Smckusick 	cbn = bn;
37241480Smckusick 	cboff = 0;
37341480Smckusick 	/*
37441480Smckusick 	 * Serially concatenated
37541480Smckusick 	 */
37641480Smckusick 	if (cs->sc_ileave == 0) {
37741480Smckusick 		register daddr_t sblk;
37841480Smckusick 
37941480Smckusick 		sblk = 0;
38041480Smckusick 		for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
38141480Smckusick 			sblk += ci->ci_size;
38241480Smckusick 		cbn -= sblk;
38341480Smckusick 	}
38441480Smckusick 	/*
38541480Smckusick 	 * Interleaved
38641480Smckusick 	 */
38741480Smckusick 	else {
38841480Smckusick 		register struct cdiinfo *ii;
38941480Smckusick 		int cdisk, off;
39041480Smckusick 
39141480Smckusick 		cboff = cbn % cs->sc_ileave;
39241480Smckusick 		cbn /= cs->sc_ileave;
39341480Smckusick 		for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
39441480Smckusick 			if (ii->ii_startblk > cbn)
39541480Smckusick 				break;
39641480Smckusick 		ii--;
39741480Smckusick 		off = cbn - ii->ii_startblk;
39841480Smckusick 		if (ii->ii_ndisk == 1) {
39941480Smckusick 			cdisk = ii->ii_index[0];
40041480Smckusick 			cbn = ii->ii_startoff + off;
40141480Smckusick 		} else {
40241480Smckusick 			cdisk = ii->ii_index[off % ii->ii_ndisk];
40341480Smckusick 			cbn = ii->ii_startoff + off / ii->ii_ndisk;
40441480Smckusick 		}
40541480Smckusick 		cbn *= cs->sc_ileave;
40641480Smckusick 		ci = &cs->sc_cinfo[cdisk];
40741480Smckusick 	}
40841480Smckusick 	/*
40941480Smckusick 	 * Fill in the component buf structure.
41041480Smckusick 	 */
41141480Smckusick 	cbp = getcbuf();
41241480Smckusick 	cbp->b_flags = bp->b_flags | B_CALL;
41341480Smckusick 	cbp->b_iodone = cdiodone;
41441480Smckusick 	cbp->b_proc = bp->b_proc;
41541480Smckusick 	cbp->b_dev = ci->ci_dev;
41641480Smckusick 	cbp->b_blkno = cbn + cboff;
41741480Smckusick 	cbp->b_un.b_addr = addr;
41845480Smckusick 	cbp->b_vp = 0;
41941480Smckusick 	if (cs->sc_ileave == 0)
42041480Smckusick 		cbp->b_bcount = dbtob(ci->ci_size - cbn);
42141480Smckusick 	else
42241480Smckusick 		cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
42341480Smckusick 	if (cbp->b_bcount > bcount)
42441480Smckusick 		cbp->b_bcount = bcount;
42541480Smckusick 	/*
42641480Smckusick 	 * XXX: context for cdiodone
42741480Smckusick 	 */
42845480Smckusick 	cbp->b_saveaddr = (caddr_t)bp;
42941480Smckusick 	cbp->b_pfcent = ((cs - cd_softc) << 16) | (ci - cs->sc_cinfo);
43041480Smckusick #ifdef DEBUG
43141480Smckusick 	if (cddebug & CDB_IO)
43241480Smckusick 		printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
43341480Smckusick 		       ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
43441480Smckusick 		       cbp->b_un.b_addr, cbp->b_bcount);
43541480Smckusick #endif
43641480Smckusick 	return(cbp);
43741480Smckusick }
43841480Smckusick 
43941480Smckusick cdintr(unit)
44041480Smckusick 	int unit;
44141480Smckusick {
44241480Smckusick 	register struct cd_softc *cs = &cd_softc[unit];
44341480Smckusick 	register struct buf *bp = cs->sc_bp;
44441480Smckusick 
44541480Smckusick #ifdef DEBUG
44641480Smckusick 	if (cddebug & CDB_FOLLOW)
44745480Smckusick 		printf("cdintr(%d): bp %x\n", unit, bp);
44841480Smckusick #endif
44941480Smckusick 	/*
45041480Smckusick 	 * Request is done for better or worse, wakeup the top half.
45141480Smckusick 	 */
45241480Smckusick 	if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
45341480Smckusick 		dk_busy &= ~(1 << cs->sc_dk);
45441480Smckusick 	if (bp->b_flags & B_ERROR)
45541480Smckusick 		bp->b_resid = bp->b_bcount;
45645480Smckusick 	biodone(bp);
45741480Smckusick }
45841480Smckusick 
45941480Smckusick /*
46045480Smckusick  * Called by biodone at interrupt time.
46141480Smckusick  * Mark the component as done and if all components are done,
46241480Smckusick  * take a cd interrupt.
46341480Smckusick  */
46441480Smckusick cdiodone(cbp)
46541480Smckusick 	register struct buf *cbp;
46641480Smckusick {
46745480Smckusick 	register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */
46841480Smckusick 	register int unit = (cbp->b_pfcent >> 16) & 0xFFFF;	/* XXX */
46941480Smckusick 	int count, s;
47041480Smckusick 
47141480Smckusick 	s = splbio();
47241480Smckusick #ifdef DEBUG
47341480Smckusick 	if (cddebug & CDB_FOLLOW)
47441480Smckusick 		printf("cdiodone(%x)\n", cbp);
47541480Smckusick 	if (cddebug & CDB_IO) {
47641480Smckusick 		printf("cdiodone: bp %x bcount %d resid %d\n",
47741480Smckusick 		       bp, bp->b_bcount, bp->b_resid);
47841480Smckusick 		printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
47941480Smckusick 		       cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
48041480Smckusick 		       cbp->b_blkno, cbp->b_un.b_addr, cbp->b_bcount);
48141480Smckusick 	}
48241480Smckusick #endif
48341480Smckusick 
48441480Smckusick 	if (cbp->b_flags & B_ERROR) {
48541480Smckusick 		bp->b_flags |= B_ERROR;
48645480Smckusick 		bp->b_error = biowait(cbp);
48741480Smckusick #ifdef DEBUG
48841480Smckusick 		printf("cd%d: error %d on component %d\n",
48941480Smckusick 		       unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
49041480Smckusick #endif
49141480Smckusick 	}
49241480Smckusick 	count = cbp->b_bcount;
49341480Smckusick 	putcbuf(cbp);
49441480Smckusick 
49541480Smckusick 	/*
49641480Smckusick 	 * If all done, "interrupt".
49741480Smckusick 	 * Again, sc_bp is only used to preserve the traditional interface.
49841480Smckusick 	 */
49941480Smckusick 	bp->b_resid -= count;
50041480Smckusick 	if (bp->b_resid < 0)
50141480Smckusick 		panic("cdiodone: count");
50241480Smckusick 	if (bp->b_resid == 0) {
50341480Smckusick 		cd_softc[unit].sc_bp = bp;
50441480Smckusick 		cdintr(unit);
50541480Smckusick 	}
50641480Smckusick 	splx(s);
50741480Smckusick }
50841480Smckusick 
50941480Smckusick cdread(dev, uio)
51041480Smckusick 	dev_t dev;
51141480Smckusick 	struct uio *uio;
51241480Smckusick {
51341480Smckusick 	register int unit = cdunit(dev);
51441480Smckusick 
51541480Smckusick #ifdef DEBUG
51641480Smckusick 	if (cddebug & CDB_FOLLOW)
51741480Smckusick 		printf("cdread(%x, %x)\n", dev, uio);
51841480Smckusick #endif
51941480Smckusick 	return(physio(cdstrategy, &cdbuf[unit], dev, B_READ, minphys, uio));
52041480Smckusick }
52141480Smckusick 
52241480Smckusick cdwrite(dev, uio)
52341480Smckusick 	dev_t dev;
52441480Smckusick 	struct uio *uio;
52541480Smckusick {
52641480Smckusick 	register int unit = cdunit(dev);
52741480Smckusick 
52841480Smckusick #ifdef DEBUG
52941480Smckusick 	if (cddebug & CDB_FOLLOW)
53041480Smckusick 		printf("cdwrite(%x, %x)\n", dev, uio);
53141480Smckusick #endif
53241480Smckusick 	return(physio(cdstrategy, &cdbuf[unit], dev, B_WRITE, minphys, uio));
53341480Smckusick }
53441480Smckusick 
53541480Smckusick cdioctl(dev, cmd, data, flag)
53641480Smckusick 	dev_t dev;
53741480Smckusick 	int cmd;
53841480Smckusick 	caddr_t data;
53941480Smckusick 	int flag;
54041480Smckusick {
54141480Smckusick 	return(EINVAL);
54241480Smckusick }
54341480Smckusick 
54441480Smckusick cdsize(dev)
54541480Smckusick 	dev_t dev;
54641480Smckusick {
54741480Smckusick 	int unit = cdunit(dev);
54841480Smckusick 	register struct cd_softc *cs = &cd_softc[unit];
54941480Smckusick 
55041480Smckusick 	if (unit >= NCD || (cs->sc_flags & CDF_INITED) == 0)
55141480Smckusick 		return(-1);
55241480Smckusick 	return(cs->sc_size);
55341480Smckusick }
55441480Smckusick 
55541480Smckusick cddump(dev)
55641480Smckusick {
55741480Smckusick 	return(ENXIO);
55841480Smckusick }
55941480Smckusick #endif
560