|
|
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.