Annotation of coherent/d/PS2_KERNEL/coh.386/bio.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.