|
|
1.1 ! root 1: /* $Header: /kernel/kersrc/coh.386/RCS/bio.c,v 1.2 92/08/04 12:30:18 bin Exp Locker: bin $ */ ! 2: /* (lgl- ! 3: * The information contained herein is a trade secret of Mark Williams ! 4: * Company, and is confidential information. It is provided under a ! 5: * license agreement, and may be copied or disclosed only under the ! 6: * terms of that agreement. Any reproduction or disclosure of this ! 7: * material without the express written authorization of Mark Williams ! 8: * Company or persuant to the license agreement is unlawful. ! 9: * ! 10: * COHERENT Version 2.3.37 ! 11: * Copyright (c) 1982, 1983, 1984. ! 12: * An unpublished work by Mark Williams Company, Chicago. ! 13: * All rights reserved. ! 14: -lgl) */ ! 15: /* ! 16: * Coherent. ! 17: * Buffered I/O. ! 18: * ! 19: * $Log: bio.c,v $ ! 20: * Revision 1.2 92/08/04 12:30:18 bin ! 21: * changed for kernel 59 ! 22: * ! 23: * Revision 1.2 92/01/06 11:58:35 hal ! 24: * Compile with cc.mwc. ! 25: * ! 26: * Revision 1.1 88/03/24 16:13:29 src ! 27: * Initial revision ! 28: * ! 29: * 87/11/05 Allan Cornish /usr/src/sys/coh/bio.c ! 30: * New seg struct now used to allow extended addressing. ! 31: * ! 32: * 87/01/05 Allan Cornish /usr/src/sys/coh/bio.c ! 33: * ioreq() now only wakes &stimer if the swap timer is active. ! 34: * ! 35: * 86/12/12 Allan Cornish /usr/src/sys/coh/bio.c ! 36: * Added 3rd arg to dpoll() to specify blocking poll if non-zero. ! 37: * ! 38: * 86/11/19 Allan Cornish /usr/src/sys/coh/bio.c ! 39: * Added dpoll() routine to perform device polls [System V.3 compatible]. ! 40: * ! 41: * 86/07/24 Allan Cornish /usr/src/sys/coh/bio.c ! 42: * Added check in devinit() for null dp->d_conp->c_load function pointer. ! 43: */ ! 44: #include <sys/coherent.h> ! 45: #include <sys/buf.h> ! 46: #include <sys/con.h> ! 47: #include <errno.h> ! 48: #include <sys/io.h> ! 49: #include <sys/proc.h> ! 50: #include <sys/sched.h> ! 51: #include <sys/seg.h> ! 52: #include <sys/stat.h> ! 53: ! 54: static BUF **hasharray; /* pointer to hash buckets */ ! 55: static BUF *firstbuf; /* pointer to first in LRU chain */ ! 56: static BUF *lastbuf; /* pointer to last in LRU chain */ ! 57: ! 58: /* ! 59: * The following hashing algorithm is used by bclaim(). ! 60: */ ! 61: #define HASH(device, blockno) ((device * 257) + blockno) ! 62: ! 63: #if BDEBUG ! 64: #include <sys/bufdebug.h> ! 65: ! 66: static BUFDEBUG bufdebug; /* actual counters used in profiling */ ! 67: ! 68: /* ! 69: * Perform buffer cache debugging ioctl's. ! 70: * These will not stay in the production release! ! 71: */ ! 72: bufioctl(cmd, vec) ! 73: BUFDEBUG *vec; ! 74: { ! 75: switch (cmd) { ! 76: case BDINIT: /* clear (init) all counters */ ! 77: kclear(&bufdebug, sizeof(bufdebug)); ! 78: bufdebug.nbuf = NBUF; ! 79: bufdebug.version = BDVERSION; ! 80: break; ! 81: case BDGETVAL: /* return current counters to user */ ! 82: kucopy(&bufdebug, vec, sizeof(bufdebug)); ! 83: break; ! 84: default: ! 85: SET_U_ERROR(EINVAL, "bufioctl()"); ! 86: } ! 87: } ! 88: #endif ! 89: ! 90: /* ! 91: * Allocate and initialize buffer headers. ! 92: */ ! 93: bufinit() ! 94: { ! 95: register BUF *bp; ! 96: paddr_t p; ! 97: vaddr_t v; ! 98: int i; ! 99: ! 100: p = MAPIO(blockp.sr_segp->s_vmem, 0); ! 101: v = blockp.sr_base; ! 102: ! 103: if (NBUF < 32) ! 104: panic("NBUF not set correctly"); ! 105: if (NHASH < 32) ! 106: panic("NHASH not set correctly"); ! 107: ! 108: bufl = kalloc(NBUF * sizeof(BUF)); ! 109: hasharray = kalloc(NHASH * sizeof(BUF *)); ! 110: if (bufl == BNULL || hasharray == BNULL) ! 111: panic("bufinit: insufficient memory for %d buffers", NBUF); ! 112: ! 113: for (i = 0; i < NHASH; ++i) ! 114: hasharray[i] = BNULL; ! 115: ! 116: /* ! 117: * initialize the buffer header array with the physical and ! 118: * virtual addresses of the buffers, NULL values for the ! 119: * hash chain pointers, and pointers to the successor and ! 120: * predecessor of the current node. ! 121: */ ! 122: firstbuf = &bufl[0]; ! 123: for (bp = lastbuf = &bufl[NBUF-1]; bp >= bufl; --bp) { ! 124: bp->b_dev = NODEV; ! 125: bp->b_paddr = p; ! 126: bp->b_vaddr = v; ! 127: bp->b_hashf = BNULL; ! 128: bp->b_hashb = BNULL; ! 129: bp->b_LRUf = bp + 1; /* next entry in chain */ ! 130: bp->b_LRUb = bp - 1; /* prev entry in chain */ ! 131: p += BSIZE; ! 132: v += BSIZE; ! 133: } ! 134: /* ! 135: * the first and last headers are special cases. ! 136: */ ! 137: bufl[0].b_LRUb = BNULL; /* no predecessor */ ! 138: bufl[NBUF-1].b_LRUf = BNULL; /* no successor */ ! 139: } ! 140: ! 141: /* ! 142: * Synchronise the buffer cache. ! 143: */ ! 144: bsync() ! 145: { ! 146: register BUF *bp; ! 147: ! 148: #if BDEBUG ! 149: ++bufdebug.bsync; ! 150: #endif ! 151: for (bp = &bufl[NBUF-1]; bp >= bufl; --bp) { ! 152: if ((bp->b_flag&BFMOD) == 0) ! 153: continue; ! 154: lock(bp->b_gate); ! 155: if (bp->b_flag&BFMOD) ! 156: bwrite(bp, 1); ! 157: unlock(bp->b_gate); ! 158: } ! 159: } ! 160: ! 161: /* ! 162: * Synchronise all block for a particular device in the buffer cache ! 163: * and invalidate all references. ! 164: */ ! 165: bflush(dev) ! 166: register dev_t dev; ! 167: { ! 168: register BUF *bp; ! 169: ! 170: #if BDEBUG ! 171: ++bufdebug.bflush; ! 172: #endif ! 173: for (bp = &bufl[NBUF-1]; bp >= bufl; --bp) { ! 174: if (bp->b_dev != dev) ! 175: continue; ! 176: lock(bp->b_gate); ! 177: if (bp->b_dev == dev) { ! 178: if (bp->b_flag&BFMOD) ! 179: bwrite(bp, 1); ! 180: bp->b_dev = NODEV; ! 181: } ! 182: unlock(bp->b_gate); ! 183: } ! 184: } ! 185: ! 186: /* ! 187: * Return a buffer containing the given block from the given device. ! 188: * If `sync' is not set, the read is asynchronous and no buffer is returned. ! 189: */ ! 190: BUF * ! 191: bread(dev, bno, sync) ! 192: dev_t dev; ! 193: daddr_t bno; ! 194: register int sync; ! 195: { ! 196: register BUF *bp; ! 197: register int s; ! 198: ! 199: #if BDEBUG ! 200: ++bufdebug.bread; ! 201: #endif ! 202: bp = bclaim(dev, bno); ! 203: if (bp->b_flag&BFNTP) { ! 204: if (sync) ! 205: bp->b_flag &= ~BFASY; ! 206: else { ! 207: bp->b_flag |= BFASY; ! 208: bumap(bp); ! 209: } ! 210: bp->b_req = BREAD; ! 211: bp->b_count = BSIZE; ! 212: s = sphi(); ! 213: dblock(dev, bp); ! 214: if (!sync) { ! 215: spl(s); ! 216: return (NULL); ! 217: } ! 218: /* ! 219: * If buffer is not valid, wait for it. ! 220: */ ! 221: while (bp->b_flag&BFNTP) { ! 222: v_sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO, "bpwait"); ! 223: /* If buffer is not valid, wait for it. */ ! 224: } ! 225: spl(s); ! 226: if (bp->b_flag&BFERR) { ! 227: SET_U_ERROR(bp->b_err ? bp->b_err : EIO, "bread()"); ! 228: brelease(bp); ! 229: return (NULL); ! 230: } ! 231: if (bp->b_resid == BSIZE) { ! 232: brelease(bp); ! 233: return (NULL); ! 234: } ! 235: } ! 236: if (!sync) { ! 237: brelease(bp); ! 238: return (NULL); ! 239: } ! 240: u.u_block++; ! 241: return (bp); ! 242: } ! 243: ! 244: /* ! 245: * Perform an LRU chain update by unlinking the specified buffer ! 246: * from it present location in the LRU chain and inserting it ! 247: * at the head of the chain, as pointed to by "firstbuf". Handle ! 248: * updating "lastbuf" if current buffer is the last buffer on the chain. ! 249: */ ! 250: static ! 251: LRUupdate(bp) ! 252: register BUF *bp; ! 253: { ! 254: if (bp != firstbuf) { ! 255: if (bp == lastbuf) ! 256: lastbuf = bp->b_LRUb; ! 257: if (bp->b_LRUb != BNULL) ! 258: bp->b_LRUb->b_LRUf = bp->b_LRUf; ! 259: if (bp->b_LRUf != BNULL) ! 260: bp->b_LRUf->b_LRUb = bp->b_LRUb; ! 261: bp->b_LRUb = BNULL; ! 262: bp->b_LRUf = firstbuf; ! 263: firstbuf->b_LRUb = bp; ! 264: firstbuf = bp; ! 265: } ! 266: } ! 267: ! 268: /* ! 269: * If the requested buffer header is in the hash chain, delete it. ! 270: */ ! 271: static ! 272: HASHdelete(bp) ! 273: register BUF *bp; ! 274: { ! 275: if (bp->b_hashb == BNULL) { /* we're first in the chain */ ! 276: hasharray[bp->b_hashval] = bp->b_hashf; ! 277: if (bp->b_hashf != BNULL) ! 278: bp->b_hashf->b_hashb = BNULL; ! 279: } else { ! 280: bp->b_hashb->b_hashf = bp->b_hashf; ! 281: if (bp->b_hashf != BNULL) ! 282: bp->b_hashf->b_hashb = bp->b_hashb; ! 283: } ! 284: bp->b_hashf = BNULL; ! 285: bp->b_hashb = BNULL; ! 286: } ! 287: ! 288: /* ! 289: * Insert the current buffer at the head of the appropriate hash chain. ! 290: */ ! 291: static ! 292: HASHinsert(bp) ! 293: register BUF *bp; ! 294: { ! 295: if (bp->b_hashf != BNULL || bp->b_hashb != BNULL) ! 296: panic("HASHinsert"); ! 297: bp->b_hashf = hasharray[bp->b_hashval]; ! 298: if (bp->b_hashf != BNULL) ! 299: bp->b_hashf->b_hashb = bp; ! 300: hasharray[bp->b_hashval] = bp; ! 301: } ! 302: ! 303: /* ! 304: * If the requested buffer is in the buffer cache, return a pointer to ! 305: * it. If not, pick an empty buffer, set it up and return it. ! 306: */ ! 307: BUF * ! 308: bclaim(dev, bno) ! 309: dev_t dev; ! 310: register daddr_t bno; ! 311: { ! 312: register BUF *bp; ! 313: register int s; ! 314: unsigned long hashval; ! 315: static GATE bufgate; /* better than sphi()/spl() */ ! 316: ! 317: #if BDEBUG ! 318: ++bufdebug.bclaim; ! 319: #endif ! 320: hashval = HASH(dev, bno) % NHASH; /* select a hash bucket */ ! 321: ! 322: again: ! 323: lock(bufgate); /* avoid pointer updates */ ! 324: ! 325: for (bp = hasharray[hashval]; bp != BNULL; bp = bp->b_hashf) { ! 326: #if BDEBUG ! 327: ++bufdebug.compares; ! 328: #endif ! 329: if (bp->b_bno == bno && bp->b_dev == dev) { ! 330: lock(bp->b_gate); ! 331: if (bp->b_bno != bno || bp->b_dev != dev) { ! 332: #if BDEBUG ! 333: ++bufdebug.fails; ! 334: #endif ! 335: unlock(bp->b_gate); ! 336: unlock(bufgate); ! 337: goto again; ! 338: } ! 339: #if BDEBUG ! 340: ++bufdebug.hits; ! 341: #endif ! 342: /* ! 343: * Now that we have located the buffer in the cache, ! 344: * unlink it from its current location in the ! 345: * LRU chain and move it to the front. ! 346: */ ! 347: LRUupdate(bp); ! 348: ! 349: /* ! 350: * If the buffer had an I/O error, mark it as ! 351: * invalid. Unlock the buffer gate and return ! 352: * the buffer to the requestor. ! 353: */ ! 354: if (bp->b_flag&BFERR) ! 355: bp->b_flag |= BFNTP; ! 356: unlock(bufgate); ! 357: bsmap(bp); ! 358: return (bp); ! 359: } ! 360: } ! 361: unlock(bufgate); ! 362: #if BDEBUG ! 363: ++bufdebug.misses; ! 364: #endif ! 365: ! 366: /* ! 367: * The requested buffer is not resident in our cache. Locate the ! 368: * oldest (least recently used) available buffer. If it's dirty, ! 369: * queue up an asynchronous write for it and continue searching ! 370: * for the next old candidate. Once a candidate is found, move it ! 371: * to the front of the LRU chain, update the hash pointers, mark ! 372: * the buffer as invalid, unlock our buffer gate and return the ! 373: * buffer to the requestor. ! 374: */ ! 375: for (;;) { /* loop until successful */ ! 376: lock(bufgate); ! 377: for (bp = lastbuf; bp != BNULL; bp = bp->b_LRUb) { ! 378: if (locked(bp->b_gate)) ! 379: continue; /* not available */ ! 380: s = sphi(); ! 381: if (locked(bp->b_gate)) { ! 382: spl(s); ! 383: continue; /* they snuck in ;-) */ ! 384: } ! 385: lock(bp->b_gate); ! 386: spl(s); ! 387: if (bp->b_flag&BFMOD) ! 388: bwrite(bp, 0); /* flush dirty buffer */ ! 389: else { ! 390: /* ! 391: * Update the hash chain for this old ! 392: * buffer. Unlink it from it's old location ! 393: * fixing up any references. Also, update ! 394: * the LRU chain to move the buffer to the head. ! 395: */ ! 396: HASHdelete(bp); ! 397: LRUupdate(bp); ! 398: ! 399: bp->b_flag = BFNTP; ! 400: bp->b_dev = dev; ! 401: bp->b_bno = bno; ! 402: bp->b_hashval = hashval; ! 403: ! 404: HASHinsert(bp); ! 405: unlock(bufgate); ! 406: bsmap(bp); ! 407: return (bp); ! 408: } ! 409: } ! 410: unlock(bufgate); ! 411: #if BDEBUG ! 412: ++bufdebug.needbuf; ! 413: #endif ! 414: s = sphi(); ! 415: bufneed = 1; ! 416: v_sleep((char *)&bufneed, CVBLKIO, IVBLKIO, SVBLKIO, "bufneed"); ! 417: /* There are no buffers available. */ ! 418: spl(s); ! 419: } /* forever */ ! 420: } ! 421: ! 422: /* ! 423: * Write the given buffer out. If `sync' is set, the write is synchronous, ! 424: * otherwise asynchronous. This routine must be called with the buffer ! 425: * gate locked. ! 426: */ ! 427: bwrite(bp, sync) ! 428: register BUF *bp; ! 429: { ! 430: register int s; ! 431: ! 432: #if BDEBUG ! 433: ++bufdebug.bwrite; ! 434: #endif ! 435: if (sync) ! 436: bp->b_flag &= ~BFASY; ! 437: else { ! 438: bp->b_flag |= BFASY; ! 439: bumap(bp); ! 440: } ! 441: bp->b_flag |= BFNTP; ! 442: bp->b_req = BWRITE; ! 443: bp->b_count = BSIZE; ! 444: s = sphi(); ! 445: dblock(bp->b_dev, bp); ! 446: if (!sync) { ! 447: spl(s); ! 448: return; ! 449: } ! 450: while (bp->b_flag&BFNTP) { ! 451: v_sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO, "bwrite"); ! 452: /* Waiting for a buffer write to finish. */ ! 453: } ! 454: spl(s); ! 455: } ! 456: ! 457: /* ! 458: * This is called by the driver when I/O has completed on a buffer. ! 459: */ ! 460: bdone(bp) ! 461: register BUF *bp; ! 462: { ! 463: #if BDEBUG ! 464: ++bufdebug.bdone; ! 465: #endif ! 466: if (bp->b_req == BWRITE) ! 467: bp->b_flag &= ~BFMOD; ! 468: if (bp->b_req == BREAD) { ! 469: if (bp->b_flag&BFERR) ! 470: bp->b_dev = NODEV; ! 471: } ! 472: if (bp->b_flag&BFASY) { ! 473: bp->b_flag &= ~BFASY; ! 474: brelease(bp); ! 475: } ! 476: bp->b_flag &= ~BFNTP; ! 477: dwakeup((char *)bp); ! 478: } ! 479: ! 480: /* ! 481: * Release the given buffer. ! 482: */ ! 483: brelease(bp) ! 484: register BUF *bp; ! 485: { ! 486: #if BDEBUG ! 487: ++bufdebug.brelease; ! 488: #endif ! 489: if (bp->b_flag&BFERR) { ! 490: bp->b_flag &= ~BFERR; ! 491: bp->b_dev = NODEV; ! 492: } ! 493: bp->b_flag &= ~BFNTP; ! 494: bumap(bp); ! 495: unlock(bp->b_gate); ! 496: if (bufneed) { ! 497: bufneed = 0; ! 498: wakeup((char *)&bufneed); ! 499: } ! 500: } ! 501: ! 502: /* ! 503: * Map the given buffer. ! 504: */ ! 505: bsmap(bp) ! 506: register BUF *bp; ! 507: { ! 508: bsave(bp->b_map); ! 509: bp->b_flag |= BFMAP; ! 510: bmapv(bconv(bp->b_paddr)); ! 511: } ! 512: ! 513: /* ! 514: * Unmap the given buffer. ! 515: */ ! 516: bumap(bp) ! 517: register BUF *bp; ! 518: { ! 519: if ((bp->b_flag&BFMAP) == 0) ! 520: return; ! 521: bp->b_flag &= ~BFMAP; ! 522: brest(bp->b_map); ! 523: } ! 524: ! 525: /* ! 526: * Read data from the I/O segment into kernel space. ! 527: */ ! 528: ioread(iop, v, n) ! 529: register IO *iop; ! 530: register char *v; ! 531: register unsigned n; ! 532: { ! 533: #if BDEBUG ! 534: ++bufdebug.ioread; ! 535: #endif ! 536: switch (iop->io_seg) { ! 537: case IOSYS: ! 538: #if BDEBUG ! 539: ++bufdebug.iosys; ! 540: #endif ! 541: iop->io.vbase += kkcopy(iop->io.vbase, v, n); ! 542: break; ! 543: case IOUSR: ! 544: #if BDEBUG ! 545: ++bufdebug.iousr; ! 546: #endif ! 547: iop->io.vbase += ukcopy(iop->io.vbase, v, n); ! 548: break; ! 549: case IOPHY: ! 550: #if BDEBUG ! 551: ++bufdebug.iophy; ! 552: #endif ! 553: dmain(n, iop->io.pbase, v); ! 554: iop->io.pbase += n; ! 555: break; ! 556: } ! 557: iop->io_ioc -= n; ! 558: } ! 559: ! 560: /* ! 561: * Write data from kernel space to the I/O segment. ! 562: */ ! 563: iowrite(iop, v, n) ! 564: register IO *iop; ! 565: register char *v; ! 566: register unsigned n; ! 567: { ! 568: #if BDEBUG ! 569: ++bufdebug.iowrite; ! 570: #endif ! 571: switch (iop->io_seg) { ! 572: case IOSYS: ! 573: #if BDEBUG ! 574: ++bufdebug.iosys; ! 575: #endif ! 576: iop->io.vbase += kkcopy(v, iop->io.vbase, n); ! 577: break; ! 578: case IOUSR: ! 579: #if BDEBUG ! 580: ++bufdebug.iousr; ! 581: #endif ! 582: iop->io.vbase += kucopy(v, iop->io.vbase, n); ! 583: break; ! 584: case IOPHY: ! 585: #if BDEBUG ! 586: ++bufdebug.iophy; ! 587: #endif ! 588: dmaout(n, iop->io.pbase, v); ! 589: iop->io.pbase += n; ! 590: break; ! 591: } ! 592: iop->io_ioc -= n; ! 593: } ! 594: ! 595: /* ! 596: * Get a character from the I/O segment. ! 597: */ ! 598: iogetc(iop) ! 599: register IO *iop; ! 600: { ! 601: register int c; ! 602: ! 603: #if BDEBUG ! 604: ++bufdebug.iogetc; ! 605: #endif ! 606: if (iop->io_ioc == 0) ! 607: return (-1); ! 608: --iop->io_ioc; ! 609: if (iop->io_seg == IOSYS) ! 610: c = *(char*) iop->io.vbase++ & 0377; ! 611: else { ! 612: c = getubd(iop->io.vbase++); ! 613: if (u.u_error) ! 614: return (-1); ! 615: } ! 616: return (c); ! 617: } ! 618: ! 619: /* ! 620: * Put a character using the I/O segment. ! 621: */ ! 622: ioputc(c, iop) ! 623: register IO *iop; ! 624: { ! 625: #if BDEBUG ! 626: ++bufdebug.ioputc; ! 627: #endif ! 628: if (iop->io_ioc == 0) ! 629: return (-1); ! 630: --iop->io_ioc; ! 631: if (iop->io_seg == IOSYS) ! 632: * (char *)iop->io.vbase++ = c; ! 633: else { ! 634: putubd(iop->io.vbase++, c); ! 635: if (u.u_error) ! 636: return (-1); ! 637: } ! 638: return (c); ! 639: } ! 640: ! 641: /* ! 642: * Given a buffer pointer, an I/O structure, a device, request type, and ! 643: * a flags word, check the I/O structure and perform the I/O request. ! 644: */ ! 645: ioreq(bp, iop, dev, req, f) ! 646: register BUF *bp; ! 647: register IO *iop; ! 648: dev_t dev; ! 649: { ! 650: register int n; ! 651: register int s; ! 652: register CON *cp; ! 653: dold_t dold; ! 654: ! 655: #if BDEBUG ! 656: ++bufdebug.ioreq; ! 657: #endif ! 658: if ((cp=drvmap(dev, &dold)) == NULL) ! 659: return; ! 660: lock(bp->b_gate); ! 661: n = cp->c_flag; /* n should do something with that flag */ ! 662: drest(dold); ! 663: if (iop) { ! 664: if (f&BFBLK) { ! 665: if (blocko(iop->io_seek)) { ! 666: SET_U_ERROR(EIO, "ioreq()"); ! 667: goto out; ! 668: } ! 669: } ! 670: if (f&BFIOC) { ! 671: if (!iomapvp(iop, bp)) { ! 672: SET_U_ERROR(EIO, "ioreq()"); ! 673: goto out; ! 674: } ! 675: } ! 676: } ! 677: bp->b_flag = f|BFNTP; ! 678: bp->b_req = req; ! 679: bp->b_dev = dev; ! 680: if (iop) { ! 681: bp->b_bno = blockn(iop->io_seek); ! 682: bp->b_count = iop->io_ioc; ! 683: } ! 684: s = sphi(); ! 685: dblock(dev, bp); ! 686: while (bp->b_flag&BFNTP) { ! 687: v_sleep((char *)bp, CVBLKIO, IVBLKIO, SVBLKIO, "ioreq"); ! 688: /* Ask norm what this sleep means. */ ! 689: } ! 690: spl(s); ! 691: if (stimer.t_last) ! 692: wakeup((char *)&stimer); ! 693: if (bp->b_flag&BFERR) { ! 694: SET_U_ERROR(bp->b_err ? bp->b_err : EIO, "ioreq()"); ! 695: goto out; ! 696: } ! 697: if (iop) { ! 698: n = iop->io_ioc - bp->b_resid; ! 699: iop->io_seek += n; ! 700: iop->io_ioc -= n; ! 701: } ! 702: out: ! 703: unlock(bp->b_gate); ! 704: } ! 705: ! 706: /* ! 707: * Given an I/O structure and a buffer header, see if the addresses ! 708: * in the I/O structure are valid and set up the buffer header. ! 709: * ! 710: * Search the u area segment table for a data segment containing ! 711: * iop->io.vbase. If one is found, put the corresponding system ! 712: * global address into bp->b_paddr and return the corresponding ! 713: * SEG pointer, else return NULL. ! 714: */ ! 715: SEG * ! 716: iomapvp(iop, bp) ! 717: register IO *iop; ! 718: register BUF *bp; ! 719: { ! 720: register SR *srp; ! 721: register SEG *sp; ! 722: register vaddr_t b, base; ! 723: ! 724: if (iop->io_seg != IOUSR) ! 725: panic("Raw I/O from non user"); ! 726: for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) { ! 727: if ((sp=srp->sr_segp) == NULL) ! 728: continue; ! 729: if ((srp->sr_flag&SRFDATA) == 0) ! 730: continue; ! 731: /* ! 732: * The following calculation is because the system represents ! 733: * the 'base' of a stack as its upper limit (because it is the ! 734: * upper limit that is fixed). ! 735: */ ! 736: base = srp->sr_base; ! 737: if (srp==&u.u_segl[SISTACK]) ! 738: base -= srp->sr_size; ! 739: ! 740: if ((b=iop->io.vbase) < base) ! 741: continue; ! 742: if ((long)b+iop->io_ioc > base + sp->s_size) ! 743: continue; ! 744: bp->b_paddr = MAPIO(sp->s_vmem, b-base); ! 745: return (sp); ! 746: } ! 747: return 0; ! 748: } ! 749: ! 750: /* ! 751: * Initialise devices. ! 752: * Mark all initialized devices as loaded. ! 753: */ ! 754: devinit() ! 755: { ! 756: register DRV *dp; ! 757: register int mind; ! 758: ! 759: for ( dp = drvl, mind = 0; mind < drvn; mind++, dp++ ) { ! 760: if (dp->d_conp && dp->d_conp->c_load) { ! 761: (*dp->d_conp->c_load)(); ! 762: dev_loaded |= (1<<mind); ! 763: } ! 764: } ! 765: } ! 766: ! 767: /* ! 768: * Open a device. ! 769: */ ! 770: dopen(dev, m, f) ! 771: register dev_t dev; ! 772: { ! 773: register CON *cp; ! 774: dold_t dold; ! 775: ! 776: if ((cp=drvmap(dev, &dold)) == NULL) ! 777: return; ! 778: if ((cp->c_flag&f) == 0) { ! 779: SET_U_ERROR(ENXIO, "dopen()"); ! 780: return; ! 781: } ! 782: (*cp->c_open)(dev, m); ! 783: drest(dold); ! 784: } ! 785: ! 786: /* ! 787: * Close a device. ! 788: */ ! 789: dclose(dev) ! 790: register dev_t dev; ! 791: { ! 792: register CON *cp; ! 793: dold_t dold; ! 794: ! 795: if ((cp=drvmap(dev, &dold)) == NULL) ! 796: return; ! 797: (*cp->c_close)(dev); ! 798: drest(dold); ! 799: } ! 800: ! 801: /* ! 802: * Call the block entry point of a device. ! 803: */ ! 804: dblock(dev, bp) ! 805: dev_t dev; ! 806: BUF *bp; ! 807: { ! 808: register CON *cp; ! 809: dold_t dold; ! 810: ! 811: if ((cp=drvmap(dev, &dold)) == NULL) ! 812: return; ! 813: (*cp->c_block)(bp); ! 814: drest(dold); ! 815: } ! 816: ! 817: /* ! 818: * Read from a device. ! 819: */ ! 820: dread(dev, iop) ! 821: register dev_t dev; ! 822: register IO *iop; ! 823: { ! 824: register CON *cp; ! 825: dold_t dold; ! 826: ! 827: if ((cp=drvmap(dev, &dold)) == NULL) ! 828: return; ! 829: (*cp->c_read)(dev, iop); ! 830: drest(dold); ! 831: } ! 832: ! 833: /* ! 834: * Write to a device. ! 835: */ ! 836: dwrite(dev, iop) ! 837: register dev_t dev; ! 838: register IO *iop; ! 839: { ! 840: register CON *cp; ! 841: dold_t dold; ! 842: ! 843: if ((cp=drvmap(dev, &dold)) == NULL) ! 844: return; ! 845: (*cp->c_write)(dev, iop); ! 846: drest(dold); ! 847: } ! 848: ! 849: /* ! 850: * Call the ioctl function for a device. ! 851: */ ! 852: dioctl(dev, com, vec) ! 853: register dev_t dev; ! 854: union ioctl *vec; ! 855: { ! 856: register CON *cp; ! 857: dold_t dold; ! 858: ! 859: if ((cp=drvmap(dev, &dold)) == NULL) ! 860: return; ! 861: (*cp->c_ioctl)(dev, com, vec); ! 862: drest(dold); ! 863: } ! 864: ! 865: /* ! 866: * Call the powerfail entry point of a device. ! 867: */ ! 868: dpower(dev) ! 869: register dev_t dev; ! 870: { ! 871: register CON *cp; ! 872: dold_t dold; ! 873: ! 874: if ((cp=drvmap(dev, &dold)) == NULL) ! 875: return; ! 876: (*cp->c_power)(dev); ! 877: drest(dold); ! 878: } ! 879: ! 880: /* ! 881: * Call the timeout entry point of a device. ! 882: */ ! 883: dtime(dev) ! 884: register dev_t dev; ! 885: { ! 886: register CON *cp; ! 887: dold_t dold; ! 888: ! 889: if ((cp=drvmap(dev, &dold)) == NULL) ! 890: return; ! 891: (*cp->c_timer)(dev); ! 892: drest(dold); ! 893: } ! 894: ! 895: /* ! 896: * Poll a device. ! 897: */ ! 898: dpoll(dev, ev, msec) ! 899: register dev_t dev; ! 900: int ev; ! 901: int msec; ! 902: { ! 903: register CON *cp; ! 904: dold_t dold; ! 905: ! 906: if ((cp=drvmap(dev, &dold)) == NULL) ! 907: return POLLNVAL; ! 908: ! 909: if ( cp->c_flag & DFPOL ) ! 910: ev = (*cp->c_poll)(dev, ev, msec); ! 911: else ! 912: ev = POLLNVAL; ! 913: ! 914: drest(dold); ! 915: return ev; ! 916: } ! 917: ! 918: /* ! 919: * Given a device, return the flags word. ! 920: */ ! 921: dflag(dev) ! 922: dev_t dev; ! 923: { ! 924: register CON *cp; ! 925: register int f; ! 926: dold_t dold; ! 927: ! 928: if ((cp=drvmap(dev, &dold)) == NULL) ! 929: return (DFERR); ! 930: f = cp->c_flag; ! 931: drest(dold); ! 932: return (f); ! 933: } ! 934: ! 935: /* ! 936: * Given a device, and a pointer to a driver map save area, save the ! 937: * current map in the driver map save area and map in the new device, ! 938: * returning a pointer to the configuration entry for that device. ! 939: */ ! 940: CON * ! 941: drvmap(dev, doldp) ! 942: dev_t dev; ! 943: dold_t *doldp; ! 944: { ! 945: register DRV *dp; ! 946: register unsigned m; ! 947: ! 948: if ((m=major(dev)) >= drvn) { ! 949: SET_U_ERROR(ENXIO, "drvmap()"); ! 950: return (NULL); ! 951: } ! 952: dp = &drvl[m]; ! 953: if (locked(dp->d_gate)) { ! 954: SET_U_ERROR(ENXIO, "drvmap()"); ! 955: return (NULL); ! 956: } ! 957: if (dp->d_conp == NULL) { ! 958: SET_U_ERROR(ENXIO, "drvmap()"); ! 959: return (NULL); ! 960: } ! 961: dsave(*doldp); ! 962: if (dp->d_map) ! 963: dmapv(dp->d_map); ! 964: return (dp->d_conp); ! 965: } ! 966: ! 967: /* ! 968: * Non existant device. ! 969: */ ! 970: nonedev() ! 971: { ! 972: SET_U_ERROR(ENXIO, "nonedev()"); ! 973: } ! 974: ! 975: /* ! 976: * Null device. ! 977: */ ! 978: nulldev() ! 979: { ! 980: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.