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