Annotation of src/sys/dev/ccd.c, Revision 1.4
1.4 ! mycroft 1: /* $NetBSD: ccd.c,v 1.3 1994/07/02 06:03:47 hpeyerl Exp $ */
1.2 cgd 2:
1.1 hpeyerl 3: /*
4: * Copyright (c) 1988 University of Utah.
1.3 hpeyerl 5: * Copyright (c) 1990, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 hpeyerl 7: *
8: * This code is derived from software contributed to Berkeley by
9: * the Systems Programming Group of the University of Utah Computer
10: * Science Department.
11: *
12: * Redistribution and use in source and binary forms, with or without
13: * modification, are permitted provided that the following conditions
14: * are met:
15: * 1. Redistributions of source code must retain the above copyright
16: * notice, this list of conditions and the following disclaimer.
17: * 2. Redistributions in binary form must reproduce the above copyright
18: * notice, this list of conditions and the following disclaimer in the
19: * documentation and/or other materials provided with the distribution.
20: * 3. All advertising materials mentioning features or use of this software
21: * must display the following acknowledgement:
22: * This product includes software developed by the University of
23: * California, Berkeley and its contributors.
24: * 4. Neither the name of the University nor the names of its contributors
25: * may be used to endorse or promote products derived from this software
26: * without specific prior written permission.
27: *
28: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38: * SUCH DAMAGE.
39: *
1.2 cgd 40: * from: Utah $Hdr: cd.c 1.6 90/11/28$
41: *
1.3 hpeyerl 42: * @(#)cd.c 8.2 (Berkeley) 11/16/93
1.1 hpeyerl 43: */
44:
45: /*
46: * "Concatenated" disk driver.
47: */
48: #include "ccd.h"
49: #if NCCD > 0
50:
51: #include <sys/param.h>
52: #include <sys/systm.h>
1.3 hpeyerl 53: #include <sys/proc.h>
1.1 hpeyerl 54: #include <sys/errno.h>
55: #include <sys/dkstat.h>
56: #include <sys/buf.h>
57: #include <sys/malloc.h>
58: #include <sys/conf.h>
1.3 hpeyerl 59: #include <sys/stat.h>
60: #ifdef COMPAT_NOLABEL
61: #include <sys/ioctl.h>
62: #include <sys/disklabel.h>
63: #include <sys/fcntl.h>
64: #endif
1.1 hpeyerl 65:
66: #include <dev/ccdvar.h>
67:
68: #ifdef DEBUG
69: int ccddebug = 0x00;
1.3 hpeyerl 70: #define CCDB_FOLLOW 0x01
71: #define CCDB_INIT 0x02
72: #define CCDB_IO 0x04
1.1 hpeyerl 73: #endif
74:
75: struct buf *ccdbuffer();
76: char *ccddevtostr();
1.3 hpeyerl 77: void ccdiodone();
1.1 hpeyerl 78:
1.3 hpeyerl 79: #define ccdunit(x) ((minor(x) >> 3) & 0xf) /* for consistency */
1.1 hpeyerl 80:
81: #define getcbuf() \
82: ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
83: #define putcbuf(bp) \
84: free((caddr_t)(bp), M_DEVBUF)
85:
86: struct ccd_softc {
87: int sc_flags; /* flags */
88: size_t sc_size; /* size of ccd */
89: int sc_ileave; /* interleave */
90: int sc_nccdisks; /* number of components */
91: struct ccdcinfo sc_cinfo[NCCDISKS]; /* component info */
92: struct ccdiinfo *sc_itable; /* interleave table */
93: int sc_usecnt; /* number of requests active */
94: int sc_dk; /* disk index */
1.3 hpeyerl 95: };
1.1 hpeyerl 96:
97: /* sc_flags */
1.3 hpeyerl 98: #define CCDF_ALIVE 0x01
99: #define CCDF_INITED 0x02
100:
101: struct ccd_softc *ccd_softc;
102: int numccd;
1.1 hpeyerl 103:
1.3 hpeyerl 104: /*
105: * Since this is called after auto-configuration of devices,
106: * we can handle the initialization here.
107: *
108: * XXX this will not work if you want to use a ccd as your primary
109: * swap device since swapconf() has been called before now.
1.1 hpeyerl 110: */
111: void
1.3 hpeyerl 112: ccdattach(num)
113: int num;
114: {
115: char *mem;
116: register u_long size;
117: register struct ccddevice *ccd;
118: extern int dkn;
119:
120: if (num <= 0)
121: return;
122: size = num * sizeof(struct ccd_softc);
123: mem = malloc(size, M_DEVBUF, M_NOWAIT);
124: if (mem == NULL) {
125: printf("WARNING: no memory for concatonated disks\n");
126: return;
127: }
128: bzero(mem, size);
129: ccd_softc = (struct ccd_softc *)mem;
130: numccd = num;
131: for (ccd = ccddevice; ccd->ccd_unit >= 0; ccd++) {
132: /*
133: * XXX
134: * Assign disk index first so that init routine
135: * can use it (saves having the driver drag around
136: * the ccddevice pointer just to set up the dk_*
137: * info in the open routine).
138: */
139: if (dkn < DK_NDRIVE)
140: ccd->ccd_dk = dkn++;
141: else
142: ccd->ccd_dk = -1;
143: if (ccdinit(ccd))
144: printf("ccd%d configured\n", ccd->ccd_unit);
145: else if (ccd->ccd_dk >= 0) {
146: ccd->ccd_dk = -1;
147: dkn--;
148: }
149: }
1.1 hpeyerl 150: }
151:
152: ccdinit(ccd)
153: struct ccddevice *ccd;
154: {
155: register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
156: register struct ccdcinfo *ci;
157: register size_t size;
158: register int ix;
159: size_t minsize;
160: dev_t dev;
1.3 hpeyerl 161: struct bdevsw *bsw;
162: int error;
163: struct proc *p = curproc; /* XXX */
1.1 hpeyerl 164:
165: #ifdef DEBUG
1.3 hpeyerl 166: if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.1 hpeyerl 167: printf("ccdinit: unit %d\n", ccd->ccd_unit);
168: #endif
169: cs->sc_dk = ccd->ccd_dk;
170: cs->sc_size = 0;
171: cs->sc_ileave = ccd->ccd_interleave;
172: cs->sc_nccdisks = 0;
173: /*
174: * Verify that each component piece exists and record
175: * relevant information about it.
176: */
177: minsize = 0;
178: for (ix = 0; ix < NCCDISKS; ix++) {
179: if ((dev = ccd->ccd_dev[ix]) == NODEV)
180: break;
181: ci = &cs->sc_cinfo[ix];
182: ci->ci_dev = dev;
1.3 hpeyerl 183: bsw = &bdevsw[major(dev)];
184: /*
185: * Open the partition
186: */
187: if (bsw->d_open &&
188: (error = (*bsw->d_open)(dev, 0, S_IFBLK, p))) {
189: printf("ccd%d: component %s open failed, error = %d\n",
190: ccd->ccd_unit, ccddevtostr(dev), error);
191: return(0);
192: }
1.1 hpeyerl 193: /*
194: * Calculate size (truncated to interleave boundary
195: * if necessary.
196: */
1.3 hpeyerl 197: if (bsw->d_psize) {
198: size = (size_t) (*bsw->d_psize)(dev);
1.1 hpeyerl 199: if ((int)size < 0)
200: size = 0;
201: } else
202: size = 0;
203: if (cs->sc_ileave > 1)
204: size -= size % cs->sc_ileave;
205: if (size == 0) {
206: printf("ccd%d: not configured (component %s missing)\n",
1.3 hpeyerl 207: ccd->ccd_unit, ccddevtostr(dev));
1.1 hpeyerl 208: return(0);
209: }
1.3 hpeyerl 210: #ifdef COMPAT_NOLABEL
211: /*
212: * XXX if this is a 'c' partition then we need to mark the
213: * label area writeable since there cannot be a label.
214: */
215: if ((minor(dev) & 7) == 2 && bsw->d_open) {
216: int i, flag;
217:
218: for (i = 0; i < nchrdev; i++)
1.4 ! mycroft 219: if (cdevsw[i].d_open == bsw->d_open)
1.3 hpeyerl 220: break;
1.4 ! mycroft 221: if (i != nchrdev && cdevsw[i].d_ioctl) {
1.3 hpeyerl 222: flag = 1;
1.4 ! mycroft 223: (void)(*cdevsw[i].d_ioctl)(dev, DIOCWLABEL,
1.3 hpeyerl 224: (caddr_t)&flag, FWRITE, p);
225: }
226: }
227: #endif
1.1 hpeyerl 228: if (minsize == 0 || size < minsize)
229: minsize = size;
230: ci->ci_size = size;
231: cs->sc_size += size;
232: cs->sc_nccdisks++;
233: }
234: /*
235: * If uniform interleave is desired set all sizes to that of
236: * the smallest component.
237: */
1.3 hpeyerl 238: if (ccd->ccd_flags & CCDF_UNIFORM) {
1.1 hpeyerl 239: for (ci = cs->sc_cinfo;
240: ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
241: ci->ci_size = minsize;
242: cs->sc_size = cs->sc_nccdisks * minsize;
243: }
244: /*
245: * Construct the interleave table
246: */
247: if (!ccdinterleave(cs))
248: return(0);
249: if (ccd->ccd_dk >= 0)
250: dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */
251: printf("ccd%d: %d components ", ccd->ccd_unit, cs->sc_nccdisks);
252: for (ix = 0; ix < cs->sc_nccdisks; ix++)
253: printf("%c%s%c",
254: ix == 0 ? '(' : ' ',
255: ccddevtostr(cs->sc_cinfo[ix].ci_dev),
256: ix == cs->sc_nccdisks - 1 ? ')' : ',');
257: printf(", %d blocks ", cs->sc_size);
258: if (cs->sc_ileave)
259: printf("interleaved at %d blocks\n", cs->sc_ileave);
260: else
261: printf("concatenated\n");
1.3 hpeyerl 262: cs->sc_flags = CCDF_ALIVE | CCDF_INITED;
1.1 hpeyerl 263: return(1);
264: }
265:
266: /*
267: * XXX not really ccd specific.
1.3 hpeyerl 268: * Could be called something like bdevtostr in machine/conf.c.
1.1 hpeyerl 269: */
270: char *
271: ccddevtostr(dev)
272: dev_t dev;
273: {
274: static char dbuf[5];
275:
276: switch (major(dev)) {
1.3 hpeyerl 277: #ifdef hp300
1.1 hpeyerl 278: case 2:
1.3 hpeyerl 279: dbuf[0] = 'r'; dbuf[1] = 'd';
1.1 hpeyerl 280: break;
281: case 4:
1.3 hpeyerl 282: dbuf[0] = 's'; dbuf[1] = 'd';
1.1 hpeyerl 283: break;
284: case 5:
1.3 hpeyerl 285: dbuf[0] = 'c'; dbuf[1] = 'd';
286: break;
287: case 6:
288: dbuf[0] = 'v'; dbuf[1] = 'n';
1.1 hpeyerl 289: break;
1.3 hpeyerl 290: #endif
1.1 hpeyerl 291: default:
292: dbuf[0] = dbuf[1] = '?';
293: break;
294: }
295: dbuf[2] = (minor(dev) >> 3) + '0';
296: dbuf[3] = (minor(dev) & 7) + 'a';
297: dbuf[4] = '\0';
298: return (dbuf);
299: }
300:
301: ccdinterleave(cs)
302: register struct ccd_softc *cs;
303: {
304: register struct ccdcinfo *ci, *smallci;
305: register struct ccdiinfo *ii;
306: register daddr_t bn, lbn;
307: register int ix;
308: u_long size;
309:
310: #ifdef DEBUG
1.3 hpeyerl 311: if (ccddebug & CCDB_INIT)
1.1 hpeyerl 312: printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
313: #endif
314: /*
315: * Allocate an interleave table.
316: * Chances are this is too big, but we don't care.
317: */
318: size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
319: cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
320: bzero((caddr_t)cs->sc_itable, size);
321: /*
322: * Trivial case: no interleave (actually interleave of disk size).
323: * Each table entry represent a single component in its entirety.
324: */
325: if (cs->sc_ileave == 0) {
326: bn = 0;
327: ii = cs->sc_itable;
328: for (ix = 0; ix < cs->sc_nccdisks; ix++) {
329: ii->ii_ndisk = 1;
330: ii->ii_startblk = bn;
331: ii->ii_startoff = 0;
332: ii->ii_index[0] = ix;
333: bn += cs->sc_cinfo[ix].ci_size;
334: ii++;
335: }
336: ii->ii_ndisk = 0;
337: #ifdef DEBUG
1.3 hpeyerl 338: if (ccddebug & CCDB_INIT)
1.1 hpeyerl 339: printiinfo(cs->sc_itable);
340: #endif
341: return(1);
342: }
343: /*
344: * The following isn't fast or pretty; it doesn't have to be.
345: */
346: size = 0;
347: bn = lbn = 0;
348: for (ii = cs->sc_itable; ; ii++) {
349: /*
350: * Locate the smallest of the remaining components
351: */
352: smallci = NULL;
353: for (ci = cs->sc_cinfo;
354: ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
355: if (ci->ci_size > size &&
356: (smallci == NULL ||
357: ci->ci_size < smallci->ci_size))
358: smallci = ci;
359: /*
360: * Nobody left, all done
361: */
362: if (smallci == NULL) {
363: ii->ii_ndisk = 0;
364: break;
365: }
366: /*
367: * Record starting logical block and component offset
368: */
369: ii->ii_startblk = bn / cs->sc_ileave;
370: ii->ii_startoff = lbn;
371: /*
372: * Determine how many disks take part in this interleave
373: * and record their indices.
374: */
375: ix = 0;
376: for (ci = cs->sc_cinfo;
377: ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
378: if (ci->ci_size >= smallci->ci_size)
379: ii->ii_index[ix++] = ci - cs->sc_cinfo;
380: ii->ii_ndisk = ix;
381: bn += ix * (smallci->ci_size - size);
382: lbn = smallci->ci_size / cs->sc_ileave;
383: size = smallci->ci_size;
384: }
385: #ifdef DEBUG
1.3 hpeyerl 386: if (ccddebug & CCDB_INIT)
1.1 hpeyerl 387: printiinfo(cs->sc_itable);
388: #endif
389: return(1);
390: }
391:
392: #ifdef DEBUG
393: printiinfo(ii)
394: struct ccdiinfo *ii;
395: {
396: register int ix, i;
397:
398: for (ix = 0; ii->ii_ndisk; ix++, ii++) {
399: printf(" itab[%d]: #dk %d sblk %d soff %d",
400: ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
401: for (i = 0; i < ii->ii_ndisk; i++)
402: printf(" %d", ii->ii_index[i]);
403: printf("\n");
404: }
405: }
406: #endif
407:
408: ccdopen(dev, flags)
409: dev_t dev;
410: {
411: int unit = ccdunit(dev);
412: register struct ccd_softc *cs = &ccd_softc[unit];
413:
414: #ifdef DEBUG
1.3 hpeyerl 415: if (ccddebug & CCDB_FOLLOW)
1.1 hpeyerl 416: printf("ccdopen(%x, %x)\n", dev, flags);
417: #endif
1.3 hpeyerl 418: if (unit >= numccd || (cs->sc_flags & CCDF_ALIVE) == 0)
1.1 hpeyerl 419: return(ENXIO);
420: return(0);
421: }
422:
423: ccdstrategy(bp)
424: register struct buf *bp;
425: {
426: register int unit = ccdunit(bp->b_dev);
427: register struct ccd_softc *cs = &ccd_softc[unit];
428: register daddr_t bn;
429: register int sz, s;
430:
431: #ifdef DEBUG
1.3 hpeyerl 432: if (ccddebug & CCDB_FOLLOW)
1.1 hpeyerl 433: printf("ccdstrategy(%x): unit %d\n", bp, unit);
434: #endif
1.3 hpeyerl 435: if ((cs->sc_flags & CCDF_INITED) == 0) {
1.1 hpeyerl 436: bp->b_error = ENXIO;
437: bp->b_flags |= B_ERROR;
438: goto done;
439: }
440: bn = bp->b_blkno;
441: sz = howmany(bp->b_bcount, DEV_BSIZE);
442: if (bn < 0 || bn + sz > cs->sc_size) {
443: sz = cs->sc_size - bn;
444: if (sz == 0) {
445: bp->b_resid = bp->b_bcount;
446: goto done;
447: }
448: if (sz < 0) {
449: bp->b_error = EINVAL;
450: bp->b_flags |= B_ERROR;
451: goto done;
452: }
453: bp->b_bcount = dbtob(sz);
454: }
455: bp->b_resid = bp->b_bcount;
456: /*
457: * "Start" the unit.
458: */
459: s = splbio();
1.3 hpeyerl 460: ccdstart(cs, bp);
1.1 hpeyerl 461: splx(s);
462: return;
463: done:
464: biodone(bp);
465: }
466:
1.3 hpeyerl 467: ccdstart(cs, bp)
468: register struct ccd_softc *cs;
469: register struct buf *bp;
1.1 hpeyerl 470: {
471: register long bcount, rcount;
472: struct buf *cbp;
473: caddr_t addr;
474: daddr_t bn;
475:
476: #ifdef DEBUG
1.3 hpeyerl 477: if (ccddebug & CCDB_FOLLOW)
478: printf("ccdstart(%x, %x)\n", cs, bp);
1.1 hpeyerl 479: #endif
480: /*
481: * Instumentation (not real meaningful)
482: */
483: cs->sc_usecnt++;
484: if (cs->sc_dk >= 0) {
485: dk_busy |= 1 << cs->sc_dk;
486: dk_xfer[cs->sc_dk]++;
487: dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
488: }
489: /*
490: * Allocate component buffers and fire off the requests
491: */
492: bn = bp->b_blkno;
1.3 hpeyerl 493: addr = bp->b_data;
1.1 hpeyerl 494: for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
495: cbp = ccdbuffer(cs, bp, bn, addr, bcount);
496: rcount = cbp->b_bcount;
497: (*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
498: bn += btodb(rcount);
499: addr += rcount;
500: }
501: }
502:
503: /*
504: * Build a component buffer header.
505: */
506: struct buf *
507: ccdbuffer(cs, bp, bn, addr, bcount)
508: register struct ccd_softc *cs;
509: struct buf *bp;
510: daddr_t bn;
511: caddr_t addr;
512: long bcount;
513: {
514: register struct ccdcinfo *ci;
515: register struct buf *cbp;
516: register daddr_t cbn, cboff;
517:
518: #ifdef DEBUG
1.3 hpeyerl 519: if (ccddebug & CCDB_IO)
1.1 hpeyerl 520: printf("ccdbuffer(%x, %x, %d, %x, %d)\n",
521: cs, bp, bn, addr, bcount);
522: #endif
523: /*
524: * Determine which component bn falls in.
525: */
526: cbn = bn;
527: cboff = 0;
528: /*
529: * Serially concatenated
530: */
531: if (cs->sc_ileave == 0) {
532: register daddr_t sblk;
533:
534: sblk = 0;
535: for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
536: sblk += ci->ci_size;
537: cbn -= sblk;
538: }
539: /*
540: * Interleaved
541: */
542: else {
543: register struct ccdiinfo *ii;
544: int ccdisk, off;
545:
546: cboff = cbn % cs->sc_ileave;
547: cbn /= cs->sc_ileave;
548: for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
549: if (ii->ii_startblk > cbn)
550: break;
551: ii--;
552: off = cbn - ii->ii_startblk;
553: if (ii->ii_ndisk == 1) {
554: ccdisk = ii->ii_index[0];
555: cbn = ii->ii_startoff + off;
556: } else {
557: ccdisk = ii->ii_index[off % ii->ii_ndisk];
558: cbn = ii->ii_startoff + off / ii->ii_ndisk;
559: }
560: cbn *= cs->sc_ileave;
561: ci = &cs->sc_cinfo[ccdisk];
562: }
563: /*
564: * Fill in the component buf structure.
565: */
566: cbp = getcbuf();
567: cbp->b_flags = bp->b_flags | B_CALL;
568: cbp->b_iodone = ccdiodone;
569: cbp->b_proc = bp->b_proc;
570: cbp->b_dev = ci->ci_dev;
571: cbp->b_blkno = cbn + cboff;
1.3 hpeyerl 572: cbp->b_data = addr;
1.1 hpeyerl 573: cbp->b_vp = 0;
574: if (cs->sc_ileave == 0)
575: cbp->b_bcount = dbtob(ci->ci_size - cbn);
576: else
577: cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
578: if (cbp->b_bcount > bcount)
579: cbp->b_bcount = bcount;
580: /*
1.3 hpeyerl 581: * XXX context for ccdiodone
1.1 hpeyerl 582: */
583: cbp->b_saveaddr = (caddr_t)bp;
584: cbp->b_pfcent = ((cs - ccd_softc) << 16) | (ci - cs->sc_cinfo);
585: #ifdef DEBUG
1.3 hpeyerl 586: if (ccddebug & CCDB_IO)
1.1 hpeyerl 587: printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
588: ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
1.3 hpeyerl 589: cbp->b_data, cbp->b_bcount);
1.1 hpeyerl 590: #endif
591: return(cbp);
592: }
593:
1.3 hpeyerl 594: ccdintr(cs, bp)
595: register struct ccd_softc *cs;
596: register struct buf *bp;
1.1 hpeyerl 597: {
598:
599: #ifdef DEBUG
1.3 hpeyerl 600: if (ccddebug & CCDB_FOLLOW)
601: printf("ccdintr(%x, %x)\n", cs, bp);
1.1 hpeyerl 602: #endif
603: /*
604: * Request is done for better or worse, wakeup the top half.
605: */
606: if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
607: dk_busy &= ~(1 << cs->sc_dk);
608: if (bp->b_flags & B_ERROR)
609: bp->b_resid = bp->b_bcount;
610: biodone(bp);
611: }
612:
613: /*
614: * Called by biodone at interrupt time.
615: * Mark the component as done and if all components are done,
616: * take a ccd interrupt.
617: */
1.3 hpeyerl 618: void
1.1 hpeyerl 619: ccdiodone(cbp)
620: register struct buf *cbp;
621: {
622: register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */
623: register int unit = (cbp->b_pfcent >> 16) & 0xFFFF; /* XXX */
624: int count, s;
625:
626: s = splbio();
627: #ifdef DEBUG
1.3 hpeyerl 628: if (ccddebug & CCDB_FOLLOW)
1.1 hpeyerl 629: printf("ccdiodone(%x)\n", cbp);
1.3 hpeyerl 630: if (ccddebug & CCDB_IO) {
1.1 hpeyerl 631: printf("ccdiodone: bp %x bcount %d resid %d\n",
632: bp, bp->b_bcount, bp->b_resid);
633: printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
634: cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
1.3 hpeyerl 635: cbp->b_blkno, cbp->b_data, cbp->b_bcount);
1.1 hpeyerl 636: }
637: #endif
638:
639: if (cbp->b_flags & B_ERROR) {
640: bp->b_flags |= B_ERROR;
641: bp->b_error = biowait(cbp);
642: #ifdef DEBUG
643: printf("ccd%d: error %d on component %d\n",
644: unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
645: #endif
646: }
647: count = cbp->b_bcount;
648: putcbuf(cbp);
649:
650: /*
651: * If all done, "interrupt".
652: */
653: bp->b_resid -= count;
654: if (bp->b_resid < 0)
655: panic("ccdiodone: count");
1.3 hpeyerl 656: if (bp->b_resid == 0)
657: ccdintr(&ccd_softc[unit], bp);
1.1 hpeyerl 658: splx(s);
659: }
660:
1.3 hpeyerl 661: ccdread(dev, uio)
662: dev_t dev;
663: struct uio *uio;
664: {
665: register int unit = ccdunit(dev);
666:
667: #ifdef DEBUG
668: if (ccddebug & CCDB_FOLLOW)
669: printf("ccdread(%x, %x)\n", dev, uio);
670: #endif
671: return(physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
672: }
673:
674: ccdwrite(dev, uio)
675: dev_t dev;
676: struct uio *uio;
677: {
678: register int unit = ccdunit(dev);
679:
680: #ifdef DEBUG
681: if (ccddebug & CCDB_FOLLOW)
682: printf("ccdwrite(%x, %x)\n", dev, uio);
683: #endif
684: return(physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
685: }
686:
687: ccdioctl(dev, cmd, data, flag)
1.1 hpeyerl 688: dev_t dev;
689: int cmd;
690: caddr_t data;
691: int flag;
692: {
693: return(EINVAL);
694: }
695:
696: ccdsize(dev)
697: dev_t dev;
698: {
699: int unit = ccdunit(dev);
700: register struct ccd_softc *cs = &ccd_softc[unit];
701:
1.3 hpeyerl 702: if (unit >= numccd || (cs->sc_flags & CCDF_INITED) == 0)
1.1 hpeyerl 703: return(-1);
704: return(cs->sc_size);
705: }
706:
707: ccddump(dev)
708: {
709: return(ENXIO);
710: }
711: #endif
CVSweb <webmaster@jp.NetBSD.org>