Annotation of coherent/d/PS2_KERNEL/coh.386/bio.c, revision 1.1.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.