home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / hp300 / dev / cd.c next >
Encoding:
C/C++ Source or Header  |  1991-05-08  |  14.3 KB  |  625 lines

  1. /*
  2.  * Copyright (c) 1988 University of Utah.
  3.  * Copyright (c) 1990 The Regents of the University of California.
  4.  * All rights reserved.
  5.  *
  6.  * This code is derived from software contributed to Berkeley by
  7.  * the Systems Programming Group of the University of Utah Computer
  8.  * Science Department.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  *
  38.  * from: Utah $Hdr: cd.c 1.6 90/11/28$
  39.  *
  40.  *    @(#)cd.c    7.4 (Berkeley) 5/7/91
  41.  */
  42.  
  43. /*
  44.  * "Concatenated" disk driver.
  45.  */
  46. #include "cd.h"
  47. #if NCD > 0
  48.  
  49. #include "sys/param.h"
  50. #include "sys/systm.h"
  51. #include "sys/errno.h"
  52. #include "sys/dkstat.h"
  53. #include "sys/buf.h"
  54. #include "sys/malloc.h"
  55. #include "sys/conf.h"
  56.  
  57. #include "cdvar.h"
  58.  
  59. #ifdef DEBUG
  60. int cddebug = 0x00;
  61. #define CDB_FOLLOW    0x01
  62. #define CDB_INIT    0x02
  63. #define CDB_IO        0x04
  64. #endif
  65.  
  66. struct    buf cdbuf[NCD];
  67. struct    buf *cdbuffer();
  68. char    *cddevtostr();
  69. int    cdiodone();
  70.  
  71. #define    cdunit(x)    ((minor(x) >> 3) & 0x7)    /* for consistency */
  72.  
  73. #define    getcbuf()    \
  74.     ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
  75. #define putcbuf(bp)    \
  76.     free((caddr_t)(bp), M_DEVBUF)
  77.  
  78. struct cd_softc {
  79.     int         sc_flags;        /* flags */
  80.     size_t         sc_size;        /* size of cd */
  81.     int         sc_ileave;        /* interleave */
  82.     int         sc_ncdisks;        /* number of components */
  83.     struct cdcinfo     sc_cinfo[NCDISKS];    /* component info */
  84.     struct cdiinfo     *sc_itable;        /* interleave table */
  85.     int         sc_usecnt;        /* number of requests active */
  86.     struct buf     *sc_bp;        /* "current" request */
  87.     int         sc_dk;            /* disk index */
  88. } cd_softc[NCD];
  89.  
  90. /* sc_flags */
  91. #define    CDF_ALIVE    0x01
  92. #define CDF_INITED    0x02
  93.  
  94. cdinit(cd)
  95.     struct cddevice *cd;
  96. {
  97.     register struct cd_softc *cs = &cd_softc[cd->cd_unit];
  98.     register struct cdcinfo *ci;
  99.     register size_t size;
  100.     register int ix;
  101.     size_t minsize;
  102.     dev_t dev;
  103.  
  104. #ifdef DEBUG
  105.     if (cddebug & (CDB_FOLLOW|CDB_INIT))
  106.         printf("cdinit: unit %d\n", cd->cd_unit);
  107. #endif
  108.     cs->sc_dk = cd->cd_dk;
  109.     cs->sc_size = 0;
  110.     cs->sc_ileave = cd->cd_interleave;
  111.     cs->sc_ncdisks = 0;
  112.     /*
  113.      * Verify that each component piece exists and record
  114.      * relevant information about it.
  115.      */
  116.     minsize = 0;
  117.     for (ix = 0; ix < NCDISKS; ix++) {
  118.         if ((dev = cd->cd_dev[ix]) == NODEV)
  119.             break;
  120.         ci = &cs->sc_cinfo[ix];
  121.         ci->ci_dev = dev;
  122.         /*
  123.          * Calculate size (truncated to interleave boundary
  124.          * if necessary.
  125.          */
  126.         if (bdevsw[major(dev)].d_psize) {
  127.             size = (size_t) (*bdevsw[major(dev)].d_psize)(dev);
  128.             if ((int)size < 0)
  129.                 size = 0;
  130.         } else
  131.             size = 0;
  132.         if (cs->sc_ileave > 1)
  133.             size -= size % cs->sc_ileave;
  134.         if (size == 0) {
  135.             printf("cd%d: not configured (component %s missing)\n",
  136.                    cd->cd_unit, cddevtostr(ci->ci_dev));
  137.             return(0);
  138.         }
  139.         if (minsize == 0 || size < minsize)
  140.             minsize = size;
  141.         ci->ci_size = size;
  142.         cs->sc_size += size;
  143.         cs->sc_ncdisks++;
  144.     }
  145.     /*
  146.      * If uniform interleave is desired set all sizes to that of
  147.      * the smallest component.
  148.      */
  149.     if (cd->cd_flags & CDF_UNIFORM) {
  150.         for (ci = cs->sc_cinfo;
  151.              ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
  152.             ci->ci_size = minsize;
  153.         cs->sc_size = cs->sc_ncdisks * minsize;
  154.     }
  155.     /*
  156.      * Construct the interleave table
  157.      */
  158.     if (!cdinterleave(cs))
  159.         return(0);
  160.     if (cd->cd_dk >= 0)
  161.         dk_wpms[cd->cd_dk] = 32 * (60 * DEV_BSIZE / 2);    /* XXX */
  162.     printf("cd%d: %d components ", cd->cd_unit, cs->sc_ncdisks);
  163.     for (ix = 0; ix < cs->sc_ncdisks; ix++)
  164.         printf("%c%s%c",
  165.                ix == 0 ? '(' : ' ',
  166.                cddevtostr(cs->sc_cinfo[ix].ci_dev),
  167.                ix == cs->sc_ncdisks - 1 ? ')' : ',');
  168.     printf(", %d blocks ", cs->sc_size);
  169.     if (cs->sc_ileave)
  170.         printf("interleaved at %d blocks\n", cs->sc_ileave);
  171.     else
  172.         printf("concatenated\n");
  173.     cs->sc_flags = CDF_ALIVE | CDF_INITED;
  174.     return(1);
  175. }
  176.  
  177. /*
  178.  * XXX not really cd specific.
  179.  */
  180. char *
  181. cddevtostr(dev)
  182.     dev_t dev;
  183. {
  184.     static char dbuf[5];
  185.  
  186.     dbuf[1] = 'd';
  187.     switch (major(dev)) {
  188.     case 2:
  189.         dbuf[0] = 'r';
  190.         break;
  191.     case 4:
  192.         dbuf[0] = 's';
  193.         break;
  194.     case 5:
  195.         dbuf[0] = 'c';
  196.         break;
  197.     default:
  198.         dbuf[0] = dbuf[1] = '?';
  199.         break;
  200.     }
  201.     dbuf[2] = (minor(dev) >> 3) + '0';
  202.     dbuf[3] = (minor(dev) & 7) + 'a';
  203.     dbuf[4] = '\0';
  204.     return (dbuf);
  205. }
  206.  
  207. cdinterleave(cs)
  208.     register struct cd_softc *cs;
  209. {
  210.     register struct cdcinfo *ci, *smallci;
  211.     register struct cdiinfo *ii;
  212.     register daddr_t bn, lbn;
  213.     register int ix;
  214.     u_long size;
  215.  
  216. #ifdef DEBUG
  217.     if (cddebug & CDB_INIT)
  218.         printf("cdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
  219. #endif
  220.     /*
  221.      * Allocate an interleave table.
  222.      * Chances are this is too big, but we don't care.
  223.      */
  224.     size = (cs->sc_ncdisks + 1) * sizeof(struct cdiinfo);
  225.     cs->sc_itable = (struct cdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
  226.     bzero((caddr_t)cs->sc_itable, size);
  227.     /*
  228.      * Trivial case: no interleave (actually interleave of disk size).
  229.      * Each table entry represent a single component in its entirety.
  230.      */
  231.     if (cs->sc_ileave == 0) {
  232.         bn = 0;
  233.         ii = cs->sc_itable;
  234.         for (ix = 0; ix < cs->sc_ncdisks; ix++) {
  235.             ii->ii_ndisk = 1;
  236.             ii->ii_startblk = bn;
  237.             ii->ii_startoff = 0;
  238.             ii->ii_index[0] = ix;
  239.             bn += cs->sc_cinfo[ix].ci_size;
  240.             ii++;
  241.         }
  242.         ii->ii_ndisk = 0;
  243. #ifdef DEBUG
  244.         if (cddebug & CDB_INIT)
  245.             printiinfo(cs->sc_itable);
  246. #endif
  247.         return(1);
  248.     }
  249.     /*
  250.      * The following isn't fast or pretty; it doesn't have to be.
  251.      */
  252.     size = 0;
  253.     bn = lbn = 0;
  254.     for (ii = cs->sc_itable; ; ii++) {
  255.         /*
  256.          * Locate the smallest of the remaining components
  257.          */
  258.         smallci = NULL;
  259.         for (ci = cs->sc_cinfo;
  260.              ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
  261.             if (ci->ci_size > size &&
  262.                 (smallci == NULL ||
  263.                  ci->ci_size < smallci->ci_size))
  264.                 smallci = ci;
  265.         /*
  266.          * Nobody left, all done
  267.          */
  268.         if (smallci == NULL) {
  269.             ii->ii_ndisk = 0;
  270.             break;
  271.         }
  272.         /*
  273.          * Record starting logical block and component offset
  274.          */
  275.         ii->ii_startblk = bn / cs->sc_ileave;
  276.         ii->ii_startoff = lbn;
  277.         /*
  278.          * Determine how many disks take part in this interleave
  279.          * and record their indices.
  280.          */
  281.         ix = 0;
  282.         for (ci = cs->sc_cinfo;
  283.              ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
  284.             if (ci->ci_size >= smallci->ci_size)
  285.                 ii->ii_index[ix++] = ci - cs->sc_cinfo;
  286.         ii->ii_ndisk = ix;
  287.         bn += ix * (smallci->ci_size - size);
  288.         lbn = smallci->ci_size / cs->sc_ileave;
  289.         size = smallci->ci_size;
  290.     }
  291. #ifdef DEBUG
  292.     if (cddebug & CDB_INIT)
  293.         printiinfo(cs->sc_itable);
  294. #endif
  295.     return(1);
  296. }
  297.  
  298. #ifdef DEBUG
  299. printiinfo(ii)
  300.     struct cdiinfo *ii;
  301. {
  302.     register int ix, i;
  303.  
  304.     for (ix = 0; ii->ii_ndisk; ix++, ii++) {
  305.         printf(" itab[%d]: #dk %d sblk %d soff %d",
  306.                ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
  307.         for (i = 0; i < ii->ii_ndisk; i++)
  308.             printf(" %d", ii->ii_index[i]);
  309.         printf("\n");
  310.     }
  311. }
  312. #endif
  313.  
  314. cdopen(dev, flags)
  315.     dev_t dev;
  316. {
  317.     int unit = cdunit(dev);
  318.     register struct cd_softc *cs = &cd_softc[unit];
  319.  
  320. #ifdef DEBUG
  321.     if (cddebug & CDB_FOLLOW)
  322.         printf("cdopen(%x, %x)\n", dev, flags);
  323. #endif
  324.     if (unit >= NCD || (cs->sc_flags & CDF_ALIVE) == 0)
  325.         return(ENXIO);
  326.     return(0);
  327. }
  328.  
  329. cdstrategy(bp)
  330.     register struct buf *bp;
  331. {
  332.     register int unit = cdunit(bp->b_dev);
  333.     register struct cd_softc *cs = &cd_softc[unit];
  334.     register daddr_t bn;
  335.     register int sz, s;
  336.  
  337. #ifdef DEBUG
  338.     if (cddebug & CDB_FOLLOW)
  339.         printf("cdstrategy(%x): unit %d\n", bp, unit);
  340. #endif
  341.     if ((cs->sc_flags & CDF_INITED) == 0) {
  342.         bp->b_error = ENXIO;
  343.         bp->b_flags |= B_ERROR;
  344.         goto done;
  345.     }
  346.     bn = bp->b_blkno;
  347.     sz = howmany(bp->b_bcount, DEV_BSIZE);
  348.     if (bn < 0 || bn + sz > cs->sc_size) {
  349.         sz = cs->sc_size - bn;
  350.         if (sz == 0) {
  351.             bp->b_resid = bp->b_bcount;
  352.             goto done;
  353.         }
  354.         if (sz < 0) {
  355.             bp->b_error = EINVAL;
  356.             bp->b_flags |= B_ERROR;
  357.             goto done;
  358.         }
  359.         bp->b_bcount = dbtob(sz);
  360.     }
  361.     bp->b_resid = bp->b_bcount;
  362.     /*
  363.      * "Start" the unit.
  364.      * XXX: the use of sc_bp is just to retain the "traditional"
  365.      * interface to the start routine.
  366.      */
  367.     s = splbio();
  368.     cs->sc_bp = bp;
  369.     cdstart(unit);
  370.     splx(s);
  371.     return;
  372. done:
  373.     biodone(bp);
  374. }
  375.  
  376. cdstart(unit)
  377.     int unit;
  378. {
  379.     register struct cd_softc *cs = &cd_softc[unit];
  380.     register struct buf *bp = cs->sc_bp;
  381.     register long bcount, rcount;
  382.     struct buf *cbp;
  383.     caddr_t addr;
  384.     daddr_t bn;
  385.  
  386. #ifdef DEBUG
  387.     if (cddebug & CDB_FOLLOW)
  388.         printf("cdstart(%d)\n", unit);
  389. #endif
  390.     /*
  391.      * Instumentation (not real meaningful)
  392.      */
  393.     cs->sc_usecnt++;
  394.     if (cs->sc_dk >= 0) {
  395.         dk_busy |= 1 << cs->sc_dk;
  396.         dk_xfer[cs->sc_dk]++;
  397.         dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
  398.     }
  399.     /*
  400.      * Allocate component buffers and fire off the requests
  401.      */
  402.     bn = bp->b_blkno;
  403.     addr = bp->b_un.b_addr;
  404.     for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
  405.         cbp = cdbuffer(cs, bp, bn, addr, bcount);
  406.         rcount = cbp->b_bcount;
  407.         (*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
  408.         bn += btodb(rcount);
  409.         addr += rcount;
  410.     }
  411. }
  412.  
  413. /*
  414.  * Build a component buffer header.
  415.  */
  416. struct buf *
  417. cdbuffer(cs, bp, bn, addr, bcount)
  418.     register struct cd_softc *cs;
  419.     struct buf *bp;
  420.     daddr_t bn;
  421.     caddr_t addr;
  422.     long bcount;
  423. {
  424.     register struct cdcinfo *ci;
  425.     register struct buf *cbp;
  426.     register daddr_t cbn, cboff;
  427.  
  428. #ifdef DEBUG
  429.     if (cddebug & CDB_IO)
  430.         printf("cdbuffer(%x, %x, %d, %x, %d)\n",
  431.                cs, bp, bn, addr, bcount);
  432. #endif
  433.     /*
  434.      * Determine which component bn falls in.
  435.      */
  436.     cbn = bn;
  437.     cboff = 0;
  438.     /*
  439.      * Serially concatenated
  440.      */
  441.     if (cs->sc_ileave == 0) {
  442.         register daddr_t sblk;
  443.  
  444.         sblk = 0;
  445.         for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
  446.             sblk += ci->ci_size;
  447.         cbn -= sblk;
  448.     }
  449.     /*
  450.      * Interleaved
  451.      */
  452.     else {
  453.         register struct cdiinfo *ii;
  454.         int cdisk, off;
  455.  
  456.         cboff = cbn % cs->sc_ileave;
  457.         cbn /= cs->sc_ileave;
  458.         for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
  459.             if (ii->ii_startblk > cbn)
  460.                 break;
  461.         ii--;
  462.         off = cbn - ii->ii_startblk;
  463.         if (ii->ii_ndisk == 1) {
  464.             cdisk = ii->ii_index[0];
  465.             cbn = ii->ii_startoff + off;
  466.         } else {
  467.             cdisk = ii->ii_index[off % ii->ii_ndisk];
  468.             cbn = ii->ii_startoff + off / ii->ii_ndisk;
  469.         }
  470.         cbn *= cs->sc_ileave;
  471.         ci = &cs->sc_cinfo[cdisk];
  472.     }
  473.     /*
  474.      * Fill in the component buf structure.
  475.      */
  476.     cbp = getcbuf();
  477.     cbp->b_flags = bp->b_flags | B_CALL;
  478.     cbp->b_iodone = cdiodone;
  479.     cbp->b_proc = bp->b_proc;
  480.     cbp->b_dev = ci->ci_dev;
  481.     cbp->b_blkno = cbn + cboff;
  482.     cbp->b_un.b_addr = addr;
  483.     cbp->b_vp = 0;
  484.     if (cs->sc_ileave == 0)
  485.         cbp->b_bcount = dbtob(ci->ci_size - cbn);
  486.     else
  487.         cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
  488.     if (cbp->b_bcount > bcount)
  489.         cbp->b_bcount = bcount;
  490.     /*
  491.      * XXX: context for cdiodone
  492.      */
  493.     cbp->b_saveaddr = (caddr_t)bp;
  494.     cbp->b_pfcent = ((cs - cd_softc) << 16) | (ci - cs->sc_cinfo);
  495. #ifdef DEBUG
  496.     if (cddebug & CDB_IO)
  497.         printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
  498.                ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
  499.                cbp->b_un.b_addr, cbp->b_bcount);
  500. #endif
  501.     return(cbp);
  502. }
  503.  
  504. cdintr(unit)
  505.     int unit;
  506. {
  507.     register struct cd_softc *cs = &cd_softc[unit];
  508.     register struct buf *bp = cs->sc_bp;
  509.  
  510. #ifdef DEBUG
  511.     if (cddebug & CDB_FOLLOW)
  512.         printf("cdintr(%d): bp %x\n", unit, bp);
  513. #endif
  514.     /*
  515.      * Request is done for better or worse, wakeup the top half.
  516.      */
  517.     if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
  518.         dk_busy &= ~(1 << cs->sc_dk);
  519.     if (bp->b_flags & B_ERROR)
  520.         bp->b_resid = bp->b_bcount;
  521.     biodone(bp);
  522. }
  523.  
  524. /*
  525.  * Called by biodone at interrupt time.
  526.  * Mark the component as done and if all components are done,
  527.  * take a cd interrupt.
  528.  */
  529. cdiodone(cbp)
  530.     register struct buf *cbp;
  531. {
  532.     register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */
  533.     register int unit = (cbp->b_pfcent >> 16) & 0xFFFF;    /* XXX */
  534.     int count, s;
  535.  
  536.     s = splbio();
  537. #ifdef DEBUG
  538.     if (cddebug & CDB_FOLLOW)
  539.         printf("cdiodone(%x)\n", cbp);
  540.     if (cddebug & CDB_IO) {
  541.         printf("cdiodone: bp %x bcount %d resid %d\n",
  542.                bp, bp->b_bcount, bp->b_resid);
  543.         printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
  544.                cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
  545.                cbp->b_blkno, cbp->b_un.b_addr, cbp->b_bcount);
  546.     }
  547. #endif
  548.  
  549.     if (cbp->b_flags & B_ERROR) {
  550.         bp->b_flags |= B_ERROR;
  551.         bp->b_error = biowait(cbp);
  552. #ifdef DEBUG
  553.         printf("cd%d: error %d on component %d\n",
  554.                unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
  555. #endif
  556.     }
  557.     count = cbp->b_bcount;
  558.     putcbuf(cbp);
  559.  
  560.     /*
  561.      * If all done, "interrupt".
  562.      * Again, sc_bp is only used to preserve the traditional interface.
  563.      */
  564.     bp->b_resid -= count;
  565.     if (bp->b_resid < 0)
  566.         panic("cdiodone: count");
  567.     if (bp->b_resid == 0) {
  568.         cd_softc[unit].sc_bp = bp;
  569.         cdintr(unit);
  570.     }
  571.     splx(s);
  572. }
  573.  
  574. cdread(dev, uio)
  575.     dev_t dev;
  576.     struct uio *uio;
  577. {
  578.     register int unit = cdunit(dev);
  579.  
  580. #ifdef DEBUG
  581.     if (cddebug & CDB_FOLLOW)
  582.         printf("cdread(%x, %x)\n", dev, uio);
  583. #endif
  584.     return(physio(cdstrategy, &cdbuf[unit], dev, B_READ, minphys, uio));
  585. }
  586.  
  587. cdwrite(dev, uio)
  588.     dev_t dev;
  589.     struct uio *uio;
  590. {
  591.     register int unit = cdunit(dev);
  592.  
  593. #ifdef DEBUG
  594.     if (cddebug & CDB_FOLLOW)
  595.         printf("cdwrite(%x, %x)\n", dev, uio);
  596. #endif
  597.     return(physio(cdstrategy, &cdbuf[unit], dev, B_WRITE, minphys, uio));
  598. }
  599.  
  600. cdioctl(dev, cmd, data, flag)
  601.     dev_t dev;
  602.     int cmd;
  603.     caddr_t data;
  604.     int flag;
  605. {
  606.     return(EINVAL);
  607. }
  608.  
  609. cdsize(dev)
  610.     dev_t dev;
  611. {
  612.     int unit = cdunit(dev);
  613.     register struct cd_softc *cs = &cd_softc[unit];
  614.  
  615.     if (unit >= NCD || (cs->sc_flags & CDF_INITED) == 0)
  616.         return(-1);
  617.     return(cs->sc_size);
  618. }
  619.  
  620. cddump(dev)
  621. {
  622.     return(ENXIO);
  623. }
  624. #endif
  625.