Annotation of coherent/b/kernel/coh.386/bio.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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