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

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

unix.superglobalmegacorp.com

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