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 * 12*49302Shibler * from: Utah $Hdr: cd.c 1.6 90/11/28$ 1341480Smckusick * 14*49302Shibler * @(#)cd.c 7.4 (Berkeley) 05/07/91 1541480Smckusick */ 1641480Smckusick 1741480Smckusick /* 1841480Smckusick * "Concatenated" disk driver. 1941480Smckusick */ 2041480Smckusick #include "cd.h" 2141480Smckusick #if NCD > 0 2241480Smckusick 2345788Sbostic #include "sys/param.h" 2445788Sbostic #include "sys/systm.h" 2545788Sbostic #include "sys/errno.h" 2645788Sbostic #include "sys/dkstat.h" 2745788Sbostic #include "sys/buf.h" 2845788Sbostic #include "sys/malloc.h" 2945788Sbostic #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(); 42*49302Shibler char *cddevtostr(); 4341480Smckusick int cdiodone(); 4441480Smckusick 4541480Smckusick #define cdunit(x) ((minor(x) >> 3) & 0x7) /* for consistency */ 4641480Smckusick 4741480Smckusick #define getcbuf() \ 4841480Smckusick ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK)) 4941480Smckusick #define putcbuf(bp) \ 5041480Smckusick free((caddr_t)(bp), M_DEVBUF) 5141480Smckusick 5241480Smckusick struct cd_softc { 5341480Smckusick int sc_flags; /* flags */ 5441480Smckusick size_t sc_size; /* size of cd */ 5541480Smckusick int sc_ileave; /* interleave */ 5641480Smckusick int sc_ncdisks; /* number of components */ 5741480Smckusick struct cdcinfo sc_cinfo[NCDISKS]; /* component info */ 5841480Smckusick struct cdiinfo *sc_itable; /* interleave table */ 5941480Smckusick int sc_usecnt; /* number of requests active */ 6041480Smckusick struct buf *sc_bp; /* "current" request */ 6141480Smckusick int sc_dk; /* disk index */ 6241480Smckusick } cd_softc[NCD]; 6341480Smckusick 6441480Smckusick /* sc_flags */ 6541480Smckusick #define CDF_ALIVE 0x01 6641480Smckusick #define CDF_INITED 0x02 6741480Smckusick 6841480Smckusick cdinit(cd) 6941480Smckusick struct cddevice *cd; 7041480Smckusick { 7141480Smckusick register struct cd_softc *cs = &cd_softc[cd->cd_unit]; 7241480Smckusick register struct cdcinfo *ci; 7341480Smckusick register size_t size; 7441480Smckusick register int ix; 7541480Smckusick size_t minsize; 7641480Smckusick dev_t dev; 7741480Smckusick 7841480Smckusick #ifdef DEBUG 7941480Smckusick if (cddebug & (CDB_FOLLOW|CDB_INIT)) 8041480Smckusick printf("cdinit: unit %d\n", cd->cd_unit); 8141480Smckusick #endif 8241480Smckusick cs->sc_dk = cd->cd_dk; 8341480Smckusick cs->sc_size = 0; 8441480Smckusick cs->sc_ileave = cd->cd_interleave; 8541480Smckusick cs->sc_ncdisks = 0; 8641480Smckusick /* 8741480Smckusick * Verify that each component piece exists and record 8841480Smckusick * relevant information about it. 8941480Smckusick */ 9041480Smckusick minsize = 0; 9141480Smckusick for (ix = 0; ix < NCDISKS; ix++) { 9241480Smckusick if ((dev = cd->cd_dev[ix]) == NODEV) 9341480Smckusick break; 9441480Smckusick ci = &cs->sc_cinfo[ix]; 9541480Smckusick ci->ci_dev = dev; 9641480Smckusick /* 9741480Smckusick * Calculate size (truncated to interleave boundary 9841480Smckusick * if necessary. 9941480Smckusick */ 10041480Smckusick if (bdevsw[major(dev)].d_psize) { 101*49302Shibler size = (size_t) (*bdevsw[major(dev)].d_psize)(dev); 102*49302Shibler if ((int)size < 0) 10341480Smckusick size = 0; 10441480Smckusick } else 10541480Smckusick size = 0; 10641480Smckusick if (cs->sc_ileave > 1) 10741480Smckusick size -= size % cs->sc_ileave; 108*49302Shibler if (size == 0) { 109*49302Shibler printf("cd%d: not configured (component %s missing)\n", 110*49302Shibler cd->cd_unit, cddevtostr(ci->ci_dev)); 11141480Smckusick return(0); 112*49302Shibler } 11341480Smckusick if (minsize == 0 || size < minsize) 11441480Smckusick minsize = size; 11541480Smckusick ci->ci_size = size; 11641480Smckusick cs->sc_size += size; 11741480Smckusick cs->sc_ncdisks++; 11841480Smckusick } 11941480Smckusick /* 12041480Smckusick * If uniform interleave is desired set all sizes to that of 12141480Smckusick * the smallest component. 12241480Smckusick */ 12341480Smckusick if (cd->cd_flags & CDF_UNIFORM) { 12441480Smckusick for (ci = cs->sc_cinfo; 12541480Smckusick ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++) 12641480Smckusick ci->ci_size = minsize; 12741480Smckusick cs->sc_size = cs->sc_ncdisks * minsize; 12841480Smckusick } 12941480Smckusick /* 13041480Smckusick * Construct the interleave table 13141480Smckusick */ 13241480Smckusick if (!cdinterleave(cs)) 13341480Smckusick return(0); 13441480Smckusick if (cd->cd_dk >= 0) 13541480Smckusick dk_wpms[cd->cd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 136*49302Shibler printf("cd%d: %d components ", cd->cd_unit, cs->sc_ncdisks); 137*49302Shibler for (ix = 0; ix < cs->sc_ncdisks; ix++) 138*49302Shibler printf("%c%s%c", 139*49302Shibler ix == 0 ? '(' : ' ', 140*49302Shibler cddevtostr(cs->sc_cinfo[ix].ci_dev), 141*49302Shibler ix == cs->sc_ncdisks - 1 ? ')' : ','); 142*49302Shibler printf(", %d blocks ", cs->sc_size); 14341480Smckusick if (cs->sc_ileave) 144*49302Shibler printf("interleaved at %d blocks\n", cs->sc_ileave); 14541480Smckusick else 146*49302Shibler printf("concatenated\n"); 14741480Smckusick cs->sc_flags = CDF_ALIVE | CDF_INITED; 14841480Smckusick return(1); 14941480Smckusick } 15041480Smckusick 151*49302Shibler /* 152*49302Shibler * XXX not really cd specific. 153*49302Shibler */ 154*49302Shibler char * 155*49302Shibler cddevtostr(dev) 156*49302Shibler dev_t dev; 157*49302Shibler { 158*49302Shibler static char dbuf[5]; 159*49302Shibler 160*49302Shibler dbuf[1] = 'd'; 161*49302Shibler switch (major(dev)) { 162*49302Shibler case 2: 163*49302Shibler dbuf[0] = 'r'; 164*49302Shibler break; 165*49302Shibler case 4: 166*49302Shibler dbuf[0] = 's'; 167*49302Shibler break; 168*49302Shibler case 5: 169*49302Shibler dbuf[0] = 'c'; 170*49302Shibler break; 171*49302Shibler default: 172*49302Shibler dbuf[0] = dbuf[1] = '?'; 173*49302Shibler break; 174*49302Shibler } 175*49302Shibler dbuf[2] = (minor(dev) >> 3) + '0'; 176*49302Shibler dbuf[3] = (minor(dev) & 7) + 'a'; 177*49302Shibler dbuf[4] = '\0'; 178*49302Shibler return (dbuf); 179*49302Shibler } 180*49302Shibler 18141480Smckusick cdinterleave(cs) 18241480Smckusick register struct cd_softc *cs; 18341480Smckusick { 18441480Smckusick register struct cdcinfo *ci, *smallci; 18541480Smckusick register struct cdiinfo *ii; 18641480Smckusick register daddr_t bn, lbn; 18741480Smckusick register int ix; 18841480Smckusick u_long size; 18941480Smckusick 19041480Smckusick #ifdef DEBUG 19141480Smckusick if (cddebug & CDB_INIT) 19241480Smckusick printf("cdinterleave(%x): ileave %d\n", cs, cs->sc_ileave); 19341480Smckusick #endif 19441480Smckusick /* 19541480Smckusick * Allocate an interleave table. 19641480Smckusick * Chances are this is too big, but we don't care. 19741480Smckusick */ 19841480Smckusick size = (cs->sc_ncdisks + 1) * sizeof(struct cdiinfo); 19941480Smckusick cs->sc_itable = (struct cdiinfo *)malloc(size, M_DEVBUF, M_WAITOK); 20041480Smckusick bzero((caddr_t)cs->sc_itable, size); 20141480Smckusick /* 20241480Smckusick * Trivial case: no interleave (actually interleave of disk size). 20341480Smckusick * Each table entry represent a single component in its entirety. 20441480Smckusick */ 20541480Smckusick if (cs->sc_ileave == 0) { 20641480Smckusick bn = 0; 20741480Smckusick ii = cs->sc_itable; 20841480Smckusick for (ix = 0; ix < cs->sc_ncdisks; ix++) { 20941480Smckusick ii->ii_ndisk = 1; 21041480Smckusick ii->ii_startblk = bn; 21141480Smckusick ii->ii_startoff = 0; 21241480Smckusick ii->ii_index[0] = ix; 21341480Smckusick bn += cs->sc_cinfo[ix].ci_size; 21441480Smckusick ii++; 21541480Smckusick } 21641480Smckusick ii->ii_ndisk = 0; 21741480Smckusick #ifdef DEBUG 21841480Smckusick if (cddebug & CDB_INIT) 21941480Smckusick printiinfo(cs->sc_itable); 22041480Smckusick #endif 22141480Smckusick return(1); 22241480Smckusick } 22341480Smckusick /* 22441480Smckusick * The following isn't fast or pretty; it doesn't have to be. 22541480Smckusick */ 22641480Smckusick size = 0; 22741480Smckusick bn = lbn = 0; 22841480Smckusick for (ii = cs->sc_itable; ; ii++) { 22941480Smckusick /* 23041480Smckusick * Locate the smallest of the remaining components 23141480Smckusick */ 23241480Smckusick smallci = NULL; 23341480Smckusick for (ci = cs->sc_cinfo; 23441480Smckusick ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++) 23541480Smckusick if (ci->ci_size > size && 23641480Smckusick (smallci == NULL || 23741480Smckusick ci->ci_size < smallci->ci_size)) 23841480Smckusick smallci = ci; 23941480Smckusick /* 24041480Smckusick * Nobody left, all done 24141480Smckusick */ 24241480Smckusick if (smallci == NULL) { 24341480Smckusick ii->ii_ndisk = 0; 24441480Smckusick break; 24541480Smckusick } 24641480Smckusick /* 24741480Smckusick * Record starting logical block and component offset 24841480Smckusick */ 24941480Smckusick ii->ii_startblk = bn / cs->sc_ileave; 25041480Smckusick ii->ii_startoff = lbn; 25141480Smckusick /* 25241480Smckusick * Determine how many disks take part in this interleave 25341480Smckusick * and record their indices. 25441480Smckusick */ 25541480Smckusick ix = 0; 25641480Smckusick for (ci = cs->sc_cinfo; 25741480Smckusick ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++) 25841480Smckusick if (ci->ci_size >= smallci->ci_size) 25941480Smckusick ii->ii_index[ix++] = ci - cs->sc_cinfo; 26041480Smckusick ii->ii_ndisk = ix; 26141480Smckusick bn += ix * (smallci->ci_size - size); 26241480Smckusick lbn = smallci->ci_size / cs->sc_ileave; 26341480Smckusick size = smallci->ci_size; 26441480Smckusick } 26541480Smckusick #ifdef DEBUG 26641480Smckusick if (cddebug & CDB_INIT) 26741480Smckusick printiinfo(cs->sc_itable); 26841480Smckusick #endif 26941480Smckusick return(1); 27041480Smckusick } 27141480Smckusick 27241480Smckusick #ifdef DEBUG 27341480Smckusick printiinfo(ii) 27441480Smckusick struct cdiinfo *ii; 27541480Smckusick { 27641480Smckusick register int ix, i; 27741480Smckusick 27841480Smckusick for (ix = 0; ii->ii_ndisk; ix++, ii++) { 27941480Smckusick printf(" itab[%d]: #dk %d sblk %d soff %d", 28041480Smckusick ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); 28141480Smckusick for (i = 0; i < ii->ii_ndisk; i++) 28241480Smckusick printf(" %d", ii->ii_index[i]); 28341480Smckusick printf("\n"); 28441480Smckusick } 28541480Smckusick } 28641480Smckusick #endif 28741480Smckusick 28841480Smckusick cdopen(dev, flags) 28941480Smckusick dev_t dev; 29041480Smckusick { 29141480Smckusick int unit = cdunit(dev); 29241480Smckusick register struct cd_softc *cs = &cd_softc[unit]; 29341480Smckusick 29441480Smckusick #ifdef DEBUG 29541480Smckusick if (cddebug & CDB_FOLLOW) 29641480Smckusick printf("cdopen(%x, %x)\n", dev, flags); 29741480Smckusick #endif 29841480Smckusick if (unit >= NCD || (cs->sc_flags & CDF_ALIVE) == 0) 29941480Smckusick return(ENXIO); 30041480Smckusick return(0); 30141480Smckusick } 30241480Smckusick 30341480Smckusick cdstrategy(bp) 30441480Smckusick register struct buf *bp; 30541480Smckusick { 30641480Smckusick register int unit = cdunit(bp->b_dev); 30741480Smckusick register struct cd_softc *cs = &cd_softc[unit]; 30845480Smckusick register daddr_t bn; 30945480Smckusick register int sz, s; 31041480Smckusick 31141480Smckusick #ifdef DEBUG 31241480Smckusick if (cddebug & CDB_FOLLOW) 31341480Smckusick printf("cdstrategy(%x): unit %d\n", bp, unit); 31441480Smckusick #endif 31541480Smckusick if ((cs->sc_flags & CDF_INITED) == 0) { 31641480Smckusick bp->b_error = ENXIO; 31745480Smckusick bp->b_flags |= B_ERROR; 31845480Smckusick goto done; 31941480Smckusick } 32041480Smckusick bn = bp->b_blkno; 32145480Smckusick sz = howmany(bp->b_bcount, DEV_BSIZE); 32241480Smckusick if (bn < 0 || bn + sz > cs->sc_size) { 32345480Smckusick sz = cs->sc_size - bn; 32445480Smckusick if (sz == 0) { 32545480Smckusick bp->b_resid = bp->b_bcount; 32641480Smckusick goto done; 32745480Smckusick } 32845480Smckusick if (sz < 0) { 32945480Smckusick bp->b_error = EINVAL; 33045480Smckusick bp->b_flags |= B_ERROR; 33145480Smckusick goto done; 33245480Smckusick } 33345480Smckusick bp->b_bcount = dbtob(sz); 33441480Smckusick } 33545480Smckusick bp->b_resid = bp->b_bcount; 33641480Smckusick /* 33741480Smckusick * "Start" the unit. 33841480Smckusick * XXX: the use of sc_bp is just to retain the "traditional" 33941480Smckusick * interface to the start routine. 34041480Smckusick */ 34141480Smckusick s = splbio(); 34241480Smckusick cs->sc_bp = bp; 34341480Smckusick cdstart(unit); 34441480Smckusick splx(s); 34541480Smckusick return; 34641480Smckusick done: 34745480Smckusick biodone(bp); 34841480Smckusick } 34941480Smckusick 35041480Smckusick cdstart(unit) 35141480Smckusick int unit; 35241480Smckusick { 35341480Smckusick register struct cd_softc *cs = &cd_softc[unit]; 35441480Smckusick register struct buf *bp = cs->sc_bp; 35541480Smckusick register long bcount, rcount; 35641480Smckusick struct buf *cbp; 35741480Smckusick caddr_t addr; 35841480Smckusick daddr_t bn; 35941480Smckusick 36041480Smckusick #ifdef DEBUG 36141480Smckusick if (cddebug & CDB_FOLLOW) 36241480Smckusick printf("cdstart(%d)\n", unit); 36341480Smckusick #endif 36441480Smckusick /* 36541480Smckusick * Instumentation (not real meaningful) 36641480Smckusick */ 36741480Smckusick cs->sc_usecnt++; 36841480Smckusick if (cs->sc_dk >= 0) { 36941480Smckusick dk_busy |= 1 << cs->sc_dk; 37041480Smckusick dk_xfer[cs->sc_dk]++; 37141480Smckusick dk_wds[cs->sc_dk] += bp->b_bcount >> 6; 37241480Smckusick } 37341480Smckusick /* 37441480Smckusick * Allocate component buffers and fire off the requests 37541480Smckusick */ 37641480Smckusick bn = bp->b_blkno; 37741480Smckusick addr = bp->b_un.b_addr; 37841480Smckusick for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 37941480Smckusick cbp = cdbuffer(cs, bp, bn, addr, bcount); 38041480Smckusick rcount = cbp->b_bcount; 38141480Smckusick (*bdevsw[major(cbp->b_dev)].d_strategy)(cbp); 38241480Smckusick bn += btodb(rcount); 38341480Smckusick addr += rcount; 38441480Smckusick } 38541480Smckusick } 38641480Smckusick 38741480Smckusick /* 38841480Smckusick * Build a component buffer header. 38941480Smckusick */ 39041480Smckusick struct buf * 39141480Smckusick cdbuffer(cs, bp, bn, addr, bcount) 39241480Smckusick register struct cd_softc *cs; 39341480Smckusick struct buf *bp; 39441480Smckusick daddr_t bn; 39541480Smckusick caddr_t addr; 39641480Smckusick long bcount; 39741480Smckusick { 39841480Smckusick register struct cdcinfo *ci; 39941480Smckusick register struct buf *cbp; 40041480Smckusick register daddr_t cbn, cboff; 40141480Smckusick 40241480Smckusick #ifdef DEBUG 40341480Smckusick if (cddebug & CDB_IO) 40441480Smckusick printf("cdbuffer(%x, %x, %d, %x, %d)\n", 40541480Smckusick cs, bp, bn, addr, bcount); 40641480Smckusick #endif 40741480Smckusick /* 40841480Smckusick * Determine which component bn falls in. 40941480Smckusick */ 41041480Smckusick cbn = bn; 41141480Smckusick cboff = 0; 41241480Smckusick /* 41341480Smckusick * Serially concatenated 41441480Smckusick */ 41541480Smckusick if (cs->sc_ileave == 0) { 41641480Smckusick register daddr_t sblk; 41741480Smckusick 41841480Smckusick sblk = 0; 41941480Smckusick for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) 42041480Smckusick sblk += ci->ci_size; 42141480Smckusick cbn -= sblk; 42241480Smckusick } 42341480Smckusick /* 42441480Smckusick * Interleaved 42541480Smckusick */ 42641480Smckusick else { 42741480Smckusick register struct cdiinfo *ii; 42841480Smckusick int cdisk, off; 42941480Smckusick 43041480Smckusick cboff = cbn % cs->sc_ileave; 43141480Smckusick cbn /= cs->sc_ileave; 43241480Smckusick for (ii = cs->sc_itable; ii->ii_ndisk; ii++) 43341480Smckusick if (ii->ii_startblk > cbn) 43441480Smckusick break; 43541480Smckusick ii--; 43641480Smckusick off = cbn - ii->ii_startblk; 43741480Smckusick if (ii->ii_ndisk == 1) { 43841480Smckusick cdisk = ii->ii_index[0]; 43941480Smckusick cbn = ii->ii_startoff + off; 44041480Smckusick } else { 44141480Smckusick cdisk = ii->ii_index[off % ii->ii_ndisk]; 44241480Smckusick cbn = ii->ii_startoff + off / ii->ii_ndisk; 44341480Smckusick } 44441480Smckusick cbn *= cs->sc_ileave; 44541480Smckusick ci = &cs->sc_cinfo[cdisk]; 44641480Smckusick } 44741480Smckusick /* 44841480Smckusick * Fill in the component buf structure. 44941480Smckusick */ 45041480Smckusick cbp = getcbuf(); 45141480Smckusick cbp->b_flags = bp->b_flags | B_CALL; 45241480Smckusick cbp->b_iodone = cdiodone; 45341480Smckusick cbp->b_proc = bp->b_proc; 45441480Smckusick cbp->b_dev = ci->ci_dev; 45541480Smckusick cbp->b_blkno = cbn + cboff; 45641480Smckusick cbp->b_un.b_addr = addr; 45745480Smckusick cbp->b_vp = 0; 45841480Smckusick if (cs->sc_ileave == 0) 45941480Smckusick cbp->b_bcount = dbtob(ci->ci_size - cbn); 46041480Smckusick else 46141480Smckusick cbp->b_bcount = dbtob(cs->sc_ileave - cboff); 46241480Smckusick if (cbp->b_bcount > bcount) 46341480Smckusick cbp->b_bcount = bcount; 46441480Smckusick /* 46541480Smckusick * XXX: context for cdiodone 46641480Smckusick */ 46745480Smckusick cbp->b_saveaddr = (caddr_t)bp; 46841480Smckusick cbp->b_pfcent = ((cs - cd_softc) << 16) | (ci - cs->sc_cinfo); 46941480Smckusick #ifdef DEBUG 47041480Smckusick if (cddebug & CDB_IO) 47141480Smckusick printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n", 47241480Smckusick ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno, 47341480Smckusick cbp->b_un.b_addr, cbp->b_bcount); 47441480Smckusick #endif 47541480Smckusick return(cbp); 47641480Smckusick } 47741480Smckusick 47841480Smckusick cdintr(unit) 47941480Smckusick int unit; 48041480Smckusick { 48141480Smckusick register struct cd_softc *cs = &cd_softc[unit]; 48241480Smckusick register struct buf *bp = cs->sc_bp; 48341480Smckusick 48441480Smckusick #ifdef DEBUG 48541480Smckusick if (cddebug & CDB_FOLLOW) 48645480Smckusick printf("cdintr(%d): bp %x\n", unit, bp); 48741480Smckusick #endif 48841480Smckusick /* 48941480Smckusick * Request is done for better or worse, wakeup the top half. 49041480Smckusick */ 49141480Smckusick if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0) 49241480Smckusick dk_busy &= ~(1 << cs->sc_dk); 49341480Smckusick if (bp->b_flags & B_ERROR) 49441480Smckusick bp->b_resid = bp->b_bcount; 49545480Smckusick biodone(bp); 49641480Smckusick } 49741480Smckusick 49841480Smckusick /* 49945480Smckusick * Called by biodone at interrupt time. 50041480Smckusick * Mark the component as done and if all components are done, 50141480Smckusick * take a cd interrupt. 50241480Smckusick */ 50341480Smckusick cdiodone(cbp) 50441480Smckusick register struct buf *cbp; 50541480Smckusick { 50645480Smckusick register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */ 50741480Smckusick register int unit = (cbp->b_pfcent >> 16) & 0xFFFF; /* XXX */ 50841480Smckusick int count, s; 50941480Smckusick 51041480Smckusick s = splbio(); 51141480Smckusick #ifdef DEBUG 51241480Smckusick if (cddebug & CDB_FOLLOW) 51341480Smckusick printf("cdiodone(%x)\n", cbp); 51441480Smckusick if (cddebug & CDB_IO) { 51541480Smckusick printf("cdiodone: bp %x bcount %d resid %d\n", 51641480Smckusick bp, bp->b_bcount, bp->b_resid); 51741480Smckusick printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n", 51841480Smckusick cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp, 51941480Smckusick cbp->b_blkno, cbp->b_un.b_addr, cbp->b_bcount); 52041480Smckusick } 52141480Smckusick #endif 52241480Smckusick 52341480Smckusick if (cbp->b_flags & B_ERROR) { 52441480Smckusick bp->b_flags |= B_ERROR; 52545480Smckusick bp->b_error = biowait(cbp); 52641480Smckusick #ifdef DEBUG 52741480Smckusick printf("cd%d: error %d on component %d\n", 52841480Smckusick unit, bp->b_error, cbp->b_pfcent & 0xFFFF); 52941480Smckusick #endif 53041480Smckusick } 53141480Smckusick count = cbp->b_bcount; 53241480Smckusick putcbuf(cbp); 53341480Smckusick 53441480Smckusick /* 53541480Smckusick * If all done, "interrupt". 53641480Smckusick * Again, sc_bp is only used to preserve the traditional interface. 53741480Smckusick */ 53841480Smckusick bp->b_resid -= count; 53941480Smckusick if (bp->b_resid < 0) 54041480Smckusick panic("cdiodone: count"); 54141480Smckusick if (bp->b_resid == 0) { 54241480Smckusick cd_softc[unit].sc_bp = bp; 54341480Smckusick cdintr(unit); 54441480Smckusick } 54541480Smckusick splx(s); 54641480Smckusick } 54741480Smckusick 54841480Smckusick cdread(dev, uio) 54941480Smckusick dev_t dev; 55041480Smckusick struct uio *uio; 55141480Smckusick { 55241480Smckusick register int unit = cdunit(dev); 55341480Smckusick 55441480Smckusick #ifdef DEBUG 55541480Smckusick if (cddebug & CDB_FOLLOW) 55641480Smckusick printf("cdread(%x, %x)\n", dev, uio); 55741480Smckusick #endif 55841480Smckusick return(physio(cdstrategy, &cdbuf[unit], dev, B_READ, minphys, uio)); 55941480Smckusick } 56041480Smckusick 56141480Smckusick cdwrite(dev, uio) 56241480Smckusick dev_t dev; 56341480Smckusick struct uio *uio; 56441480Smckusick { 56541480Smckusick register int unit = cdunit(dev); 56641480Smckusick 56741480Smckusick #ifdef DEBUG 56841480Smckusick if (cddebug & CDB_FOLLOW) 56941480Smckusick printf("cdwrite(%x, %x)\n", dev, uio); 57041480Smckusick #endif 57141480Smckusick return(physio(cdstrategy, &cdbuf[unit], dev, B_WRITE, minphys, uio)); 57241480Smckusick } 57341480Smckusick 57441480Smckusick cdioctl(dev, cmd, data, flag) 57541480Smckusick dev_t dev; 57641480Smckusick int cmd; 57741480Smckusick caddr_t data; 57841480Smckusick int flag; 57941480Smckusick { 58041480Smckusick return(EINVAL); 58141480Smckusick } 58241480Smckusick 58341480Smckusick cdsize(dev) 58441480Smckusick dev_t dev; 58541480Smckusick { 58641480Smckusick int unit = cdunit(dev); 58741480Smckusick register struct cd_softc *cs = &cd_softc[unit]; 58841480Smckusick 58941480Smckusick if (unit >= NCD || (cs->sc_flags & CDF_INITED) == 0) 59041480Smckusick return(-1); 59141480Smckusick return(cs->sc_size); 59241480Smckusick } 59341480Smckusick 59441480Smckusick cddump(dev) 59541480Smckusick { 59641480Smckusick return(ENXIO); 59741480Smckusick } 59841480Smckusick #endif 599