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