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