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

1.1       root        1: /* $Header: /src386/STREAMS/coh.386/RCS/null.c,v 2.3 93/08/09 13:35:51 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:  * Null and memory driver.
                     17:  *  Minor device 0 is /dev/null
                     18:  *  Minor device 1 is /dev/mem, physical memory
                     19:  *  Minor device 2 is /dev/kmem, kernel data
                     20:  *  Minor device 3 is /dev/cmos
                     21:  *  Minor device 4 is /dev/boot_gift
                     22:  *  Minor device 5 is /dev/clock
                     23:  *  Minor device 6 is /dev/ps
                     24:  *  Minor device 7 is /dev/kmemhi, virtual memory 0x8000_0000-0xFFFF_FFFF
                     25:  *  Minor device 11 is /dev/idle
                     26:  *
                     27:  * $Log:       null.c,v $
                     28:  * Revision 2.3  93/08/09  13:35:51  bin
                     29:  * Kernel 82 changes
                     30:  * 
                     31:  * Revision 2.2  93/07/26  14:28:57  nigel
                     32:  * Nigel's R80
                     33:  * 
                     34:  * Revision 1.7  93/04/14  10:06:37  root
                     35:  * r75
                     36:  * 
                     37:  * Revision 1.10  93/03/02  08:16:25  bin
                     38:  * kernel 73 update
                     39:  * 
                     40:  * Revision 1.6  92/11/09  17:10:54  root
                     41:  * Just before adding vio segs.
                     42:  * 
                     43:  * Revision 1.2  92/01/06  11:59:49  hal
                     44:  * Compile with cc.mwc.
                     45:  * 
                     46:  * Revision 1.1        88/03/24  16:14:04      src
                     47:  * Initial revision
                     48:  * 
                     49:  */
                     50: 
                     51: /*
                     52:  * The symbol "DANGEROUS" should be undefined for a production system.
                     53:  */
                     54: #ifdef TRACER
                     55: #define NULL_IOCTL     /* Allow ioctl()s for /dev/kmem.  */
                     56: #define DANGEROUS      /* Allow dangerous ioctl()s for /dev/null.  */
                     57: #endif
                     58: #define IDLE_DEV
                     59: 
                     60: #include <kernel/typed.h>
                     61: 
                     62: #include <sys/coherent.h>
                     63: #include <sys/con.h>
                     64: #include <sys/errno.h>
                     65: #include <sys/stat.h>
                     66: #include <sys/inode.h>
                     67: #include <sys/seg.h>
                     68: #include <sys/coh_ps.h>
                     69: #include <sys/file.h>
                     70: #if defined NULL_IOCTL || defined IDLE_DEV
                     71:    #include <sys/null.h>
                     72: #endif /* NULL_IOCTL || IDLE_DEV */
                     73: 
                     74: 
                     75: #if    TRACER
                     76: #include <sys/buf.h>
                     77: #endif
                     78: 
                     79: /* These are minor numbers.  */
                     80: #define DEV_NULL       0       /* /dev/null    */
                     81: #define DEV_MEM                1       /* /dev/mem     */
                     82: #define DEV_KMEM       2       /* /dev/kmem    */
                     83: #define DEV_CMOS       3       /* /dev/cmos    */
                     84: #define DEV_BOOTGIFT   4       /* /dev/bootgift  */
                     85: #define DEV_CLOCK      5       /* /dev/clock  */
                     86: #define DEV_PS         6       /* /dev/ps  */
                     87: #define DEV_KMEMHI     7       /* /dev/kmemhi  */
                     88: #define DEV_IDLE       11      /* /dev/idle    */
                     89: 
                     90: #define KMEMHI_BASE    0x80000000
                     91: #define PXCOPY_LIM     4096
                     92: 
                     93: /*
                     94:  * CMOS devices are limited by an 8 bit address.
                     95:  */
                     96: #define MAX_CMOS       255
                     97: #define CMOS_LEN       256
                     98: 
                     99: /*
                    100:  * The first 14 bytes of the CMOS are the clock.
                    101:  */
                    102: #define MAX_CLOCK      13
                    103: #define CLOCK_LEN      14
                    104: 
                    105: /*
                    106:  * These are definitions for mucking with the CMOS clock.
                    107:  */
                    108: #define SRA    10      /* Status Register A */
                    109: #define SRB    11      /* Status Register B */
                    110: #define SRC    12      /* Status Register C */
                    111: #define SRD    13      /* Status Register D */
                    112: 
                    113: #define UIP    0x80    /* Update In Progress bit of SRA.       */
                    114: #define NO_UPD 0x80    /* No Update bit of SRB.                */
                    115: 
                    116: /*
                    117:  * Functions for configuration.
                    118:  */
                    119: void   nlopen();
                    120: void   nlclose();
                    121: void   nlread();
                    122: void   nlwrite();
                    123: int    nlioctl();
                    124: int    nulldev();
                    125: int    nonedev();
                    126: 
                    127: /*
                    128:  * Configuration table.
                    129:  */
                    130: CON nlcon ={
                    131:        DFCHR,                          /* Flags */
                    132:        0,                              /* Major index */
                    133:        nlopen,                         /* Open */
                    134:        nlclose,                        /* Close */
                    135:        nulldev,                        /* Block */
                    136:        nlread,                         /* Read */
                    137:        nlwrite,                        /* Write */
                    138: #if defined NULL_IOCTL || defined IDLE_DEV
                    139:        nlioctl,                        /* Ioctl */
                    140: #else /* NULL_IOCTL || IDLE_DEV */
                    141:        nonedev,                        /* Ioctl */
                    142: #endif /* NULL_IOCTL || IDLE_DEV */
                    143:        nulldev,                        /* Powerfail */
                    144:        nulldev,                        /* Timeout */
                    145:        nulldev,                        /* Load */
                    146:        nulldev                         /* Unload */
                    147: };
                    148: 
                    149: int lock_clock();
                    150: void unlock_clock();
                    151: 
                    152: /*
                    153:  * Null/memory open routine.
                    154:  */
                    155: void
                    156: nlopen(dev, mode)
                    157: dev_t dev;
                    158: int mode;
                    159: {
                    160:        switch (minor(dev)) {
                    161: #ifdef IDLE_DEV
                    162:        case DEV_IDLE:
                    163: #endif
                    164:        case DEV_PS:
                    165:                /* /dev/ps is read only */
                    166:                if (IPR != (IPR & mode)) 
                    167:                        SET_U_ERROR( EACCES, "/dev/ps is read only" );
                    168:                break;
                    169:        default:
                    170:                /*
                    171:                 * For minor devices on NULL there is
                    172:                 * usually no action for open().
                    173:                 */
                    174:                break;
                    175:        }
                    176:        return;
                    177: } /* nlopen() */
                    178: 
                    179: /*
                    180:  * Null/memory close routine.
                    181:  */
                    182: void
                    183: nlclose(dev, mode)
                    184: dev_t dev;
                    185: int mode;
                    186: {
                    187:        /*
                    188:         * For minor devices on NULL there is
                    189:         * Usually no action for close().
                    190:         */
                    191:        return;
                    192: } /* nlclose() */
                    193: 
                    194: /*
                    195:  * Null/memory read routine.
                    196:  */
                    197: void
                    198: nlread(dev, iop)
                    199: dev_t dev;
                    200: register IO *iop;
                    201: {
                    202:        register unsigned       bytesRead;
                    203:        register PROC           *pp1;           /* */
                    204:        char                    psBuf[ARGSZ];   /* buffer for command line
                    205:                                                 * arguments for ps. */
                    206:        stMonitor               psData;         /* All process data for */
                    207:        UPROC                   *uprc;          /* pointer to u area */
                    208:        int                     ndpUseg;        /* System global address 
                    209:                                                 * of U segment */
                    210:        unsigned int            seek;
                    211:        unsigned char           read_cmos();
                    212:        extern typed_space      boot_gift;
                    213: 
                    214:        switch (minor (dev)) {
                    215:        case DEV_NULL:
                    216:                /*
                    217:                 * Read nothing.
                    218:                 * Do NOT update iop->io_ioc.
                    219:                 * This way, caller knows 0 bytes were read.
                    220:                 */
                    221:                break;
                    222: 
                    223:        case DEV_MEM: {
                    224:                int src = iop->io_seek;
                    225:                int dest = iop->io.pbase;
                    226: 
                    227:                while (iop->io_ioc) {
                    228:                        int numBytes = PXCOPY_LIM;
                    229:                        if (numBytes > iop->io_ioc)
                    230:                                numBytes = iop->io_ioc;
                    231: 
                    232:                        bytesRead = pxcopy (src, dest, numBytes,
                    233:                                            SEG_386_UD | R_USR);
                    234:                        src += bytesRead;
                    235:                        dest += bytesRead;
                    236:                        iop->io_ioc -= bytesRead;
                    237:                        if (u.u_error == EFAULT) {
                    238:                                u.u_error = 0;
                    239:                                break;
                    240:                        }
                    241:                }
                    242:                break;
                    243:        }
                    244: 
                    245:        case DEV_KMEM:
                    246:                iowrite (iop, iop->io_seek, iop->io_ioc);
                    247:                if (u.u_error == EFAULT)
                    248:                        u.u_error = 0;
                    249:                break;
                    250: 
                    251:        case DEV_CLOCK:
                    252:                /*
                    253:                 * Don't go past the end of the CLOCK.
                    254:                 */
                    255:                if (iop->io_seek >= CLOCK_LEN)
                    256:                        break;
                    257: 
                    258:                /*
                    259:                 * Lock the clock before any reading.
                    260:                 */
                    261: 
                    262:                if (lock_clock () == 0) {
                    263:                        SET_U_ERROR (EIO, "RT clock will not settle.");
                    264:                        break;
                    265:                }
                    266: 
                    267:                /*
                    268:                 * Read the requested data out of the CMOS.
                    269:                 */
                    270:                for (seek = iop->io_seek; seek < CLOCK_LEN; seek++) {
                    271:                        if(ioputc(read_cmos(seek), iop) == -1)
                    272:                                break;
                    273:                }
                    274: 
                    275:                /*
                    276:                 * Now that we are done reading the CMOS, let
                    277:                 * the clock loose.
                    278:                 */
                    279:                unlock_clock();
                    280:                break;
                    281: 
                    282:        case DEV_CMOS:
                    283:                /*
                    284:                 * Don't go past the end of the CMOS.
                    285:                 */
                    286:                if (iop->io_seek >= CMOS_LEN)
                    287:                        break;
                    288: 
                    289:                /*
                    290:                 * Read the requested data out of the CMOS.
                    291:                 */
                    292:                for (seek = iop->io_seek; seek < CMOS_LEN; seek++) {
                    293:                        if(ioputc(read_cmos(seek), iop) == -1)
                    294:                                break;
                    295:                }
                    296:                break;
                    297: 
                    298:        case DEV_BOOTGIFT:
                    299:                /*
                    300:                 * Reads all from the data structure boot_gift.
                    301:                 */
                    302:                if (iop->io_seek < BG_LEN) {
                    303:                        bytesRead = iop->io_ioc;
                    304: 
                    305:                        /*
                    306:                         * Copy no more than to the end of boot_gift.
                    307:                         */
                    308:                        if (iop->io_seek + bytesRead > BG_LEN)
                    309:                                bytesRead = BG_LEN - iop->io_seek;
                    310: 
                    311:                        iowrite (iop, (char *) (& boot_gift) + iop->io_seek,
                    312:                                 bytesRead);
                    313:                }
                    314:                break;
                    315: 
                    316:        case DEV_PS:
                    317:                /* Lock the process table. It allows to have an atomic ps. */
                    318:                lock (pnxgate);
                    319:                /* Main driver loop. Go through all processes. Fill struct PS
                    320:                 * and send put to user buffer.
                    321:                 */
                    322:                for (pp1 = & procq; (pp1 = pp1->p_nforw) != & procq; ) {
                    323:                        register int            i;      /* loop index */
                    324:                        register unsigned       uLen,   /* Process size */
                    325:                                                uLenR;  /* Real process size */
                    326:                        register SEG    *sp;    /* u area segment */
                    327:                        int work;       /* virtual click number */
                    328: 
                    329:                        /* Check if driver can send next proc data */ 
                    330:                        if (iop->io_ioc < sizeof (stMonitor)) 
                    331:                                break;
                    332:                                
                    333:                        /* Calculate the size of process. */
                    334:                        uLen = uLenR = 0;
                    335:                        for (i = 0 ; i < NUSEG ; i++) {
                    336:                                if ((sp = pp1->p_segp [i]) == NULL)
                    337:                                        continue;
                    338:                                uLenR += sp->s_size;
                    339:                                if (i == SIUSERP || i == SIAUXIL)
                    340:                                        continue;
                    341:                                uLen += sp->s_size;
                    342:                
                    343:                        } 
                    344: 
                    345:                        /* Find u area for process pp1 */
                    346:                        sp = pp1->p_segp [SIUSERP];
                    347:                        ndpUseg = MAPIO (sp->s_vmem, U_OFFSET);
                    348:                        work = workAlloc ();
                    349:                        ptable1_v [work] = 
                    350:                                   sysmem.u.pbase [btocrd (ndpUseg)] | SEG_RW;
                    351:                        uprc = (UPROC *) (ctob (work) + U_OFFSET);
                    352:                        memcpy (psData.u_comm, uprc->u_comm, ARGSZ);
                    353:                        memcpy (psData.u_sleep, uprc->u_sleep, U_SLEEP_LEN);
                    354:                        workFree (work);
                    355: 
                    356: #ifdef TRACER
                    357:                        if (strncmp (psData.u_sleep, "lock",
                    358:                                     U_SLEEP_LEN) == 0) {
                    359:                                GATE          * g = pp1->p_event;
                    360:                                printf ("[%d] locked at %x lock %s (%d) = %x\n",
                    361:                                        pp1->p_pid, g, g->_name, g->_count,
                    362:                                        g->_lock [0]);
                    363:                        }
                    364:                        if (strncmp (psData.u_sleep, "bpwait",
                    365:                                     U_SLEEP_LEN) == 0) {
                    366:                                BUF           * bp = pp1->p_event;
                    367:                                printf ("[%d] blocked on %x flags = %x\n",
                    368:                                        pp1->p_pid, bp, bp->b_flag);
                    369:                        }
                    370: #endif
                    371: 
                    372:                        /* fill up stMonitor */
                    373:                        psData.p_pid = pp1->p_pid;
                    374:                        psData.p_ppid = pp1->p_ppid;
                    375:                        psData.p_uid = pp1->p_uid;
                    376:                        psData.p_ruid = pp1->p_ruid;
                    377:                        psData.p_rgid = pp1->p_rgid;
                    378:                        psData.p_state = pp1->p_state;
                    379:                        psData.p_flags = pp1->p_flags;
                    380:                        psData.rrun = (char *) pp1 != pp1->p_event;
                    381:                        psData.p_event = pp1->p_event;
                    382:                        psData.p_ttdev = pp1->p_ttdev;
                    383:                        psData.p_nice = pp1->p_nice;
                    384:                        psData.size = (short) (uLen >> 10);
                    385:                        psData.rsize = (short) (uLenR >> 10);
                    386:                        psData.p_schedPri = pp1->p_schedPri;
                    387:                        psData.p_utime = pp1->p_utime;
                    388:                        psData.p_stime = pp1->p_stime;
                    389: 
                    390:                        memcpy (psData.pr_argv, psBuf, ARGSZ);
                    391: 
                    392:                        /* send data to user */
                    393:                        iowrite (iop, (char *) & psData, sizeof (stMonitor));
                    394:                }
                    395:                unlock (pnxgate);
                    396:                break;
                    397: 
                    398:        case DEV_KMEMHI:
                    399:                iowrite (iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc);
                    400:                if (u.u_error == EFAULT)
                    401:                        u.u_error = 0;
                    402:                break;
                    403: 
                    404:        default:
                    405:                SET_U_ERROR (ENXIO, "nlread(): illegal minor device for null");
                    406:        }
                    407:        return;
                    408: }
                    409: 
                    410: /*
                    411:  * Null/memory write routine.
                    412:  */
                    413: void
                    414: nlwrite(dev, iop)
                    415: dev_t dev;
                    416: register IO *iop;
                    417: {
                    418:        register unsigned bytesWrit;
                    419:        unsigned write_cmos();
                    420:        unsigned seek;
                    421:        int     ch;
                    422: 
                    423:        switch (minor (dev)) {
                    424:        case DEV_NULL:
                    425:                /*
                    426:                 * Tell caller all bytes were written.
                    427:                 */
                    428:                iop->io_ioc = 0;
                    429:                break;
                    430: 
                    431:        case DEV_MEM:
                    432:                while (iop->io_ioc) {
                    433:                        int src = iop->io.pbase;
                    434:                        int dest = iop->io_seek;
                    435:                        int numBytes = PXCOPY_LIM;
                    436:                        if (numBytes > iop->io_ioc)
                    437:                                numBytes = iop->io_ioc;
                    438: 
                    439:                        bytesWrit = xpcopy (src, dest, numBytes,
                    440:                                            SEG_386_UD | R_USR);
                    441:                        src += bytesWrit;
                    442:                        dest += bytesWrit;
                    443:                        iop->io_ioc -= bytesWrit;
                    444:                        if (u.u_error == EFAULT) {
                    445:                                u.u_error = 0;
                    446:                                break;
                    447:                        }
                    448:                }
                    449:                break;
                    450: 
                    451:        case DEV_KMEM:
                    452:                ioread (iop, iop->io_seek, iop->io_ioc);
                    453:                break;
                    454: 
                    455:        case DEV_CLOCK:
                    456:                /*
                    457:                 * Don't go past the end of the CLOCK.
                    458:                 */
                    459:                if (iop->io_seek >= CLOCK_LEN)
                    460:                        break;
                    461: 
                    462:                /*
                    463:                 * Lock the clock before any writing.
                    464:                 */
                    465:                if (lock_clock () == 0) {
                    466:                        SET_U_ERROR (EIO, "RT clock will not settle.");
                    467:                        break;
                    468:                }
                    469: 
                    470:                /*
                    471:                 * Write the requested data into the CMOS.
                    472:                 */
                    473: 
                    474:                for (seek = iop->io_seek ; seek < CLOCK_LEN ; seek ++) {
                    475:                        if ((ch = iogetc (iop)) == -1)
                    476:                                break;
                    477:                        write_cmos (seek, ch);
                    478:                }
                    479: 
                    480:                /*
                    481:                 * Now that we are done writing the CMOS, let
                    482:                 * the clock loose.
                    483:                 */
                    484:                unlock_clock ();
                    485:                break;
                    486: 
                    487:        case DEV_CMOS:
                    488:                /*
                    489:                 * Don't go past the end of the CMOS.
                    490:                 */
                    491:                if (iop->io_seek >= CMOS_LEN)
                    492:                        break;
                    493: 
                    494:                /*
                    495:                 * Write the requested data into the CMOS.
                    496:                 */
                    497:                for (seek = iop->io_seek ; seek < CMOS_LEN ; seek ++) {
                    498:                        if ((ch = iogetc (iop)) == -1)
                    499:                                break;
                    500:                        write_cmos (seek, ch);
                    501:                }
                    502:                break;
                    503: 
                    504:        case DEV_BOOTGIFT:
                    505:                /*
                    506:                 * /dev/bootgift is not writable.
                    507:                 */
                    508:                break;
                    509: 
                    510:        case DEV_PS:
                    511:                /*
                    512:                 * We should not be able to open /dev/ps to write.
                    513:                 * Just paranoya.
                    514:                 */
                    515:                break;
                    516: 
                    517:        case DEV_KMEMHI:
                    518:                ioread (iop, iop->io_seek - KMEMHI_BASE, iop->io_ioc);
                    519:                break;
                    520: 
                    521:        default:
                    522:                SET_U_ERROR (ENXIO,
                    523:                             "nlwrite(): illegal minor device for null");
                    524:        }
                    525:        return;
                    526: }
                    527: 
                    528: #if defined NULL_IOCTL || defined IDLE_DEV /* Includes all of nlioctl().  */
                    529: 
                    530: /*
                    531:  * Do an ioctl call for /dev/null.
                    532:  */
                    533: int
                    534: nlioctl(dev, cmd, vec)
                    535:        dev_t dev;
                    536:        int cmd;
                    537:        char * vec;
                    538: {
                    539:        /* Only /dev/kmem and /dev/idle have an ioctl.  */
                    540:        switch (minor (dev)) {
                    541: #ifdef NULL_IOCTL
                    542:        case DEV_KMEM:
                    543:                switch (cmd) {
                    544: #ifdef DANGEROUS
                    545:                case NLCALL:    /* Call a function.  */
                    546:                return docall (vec);
                    547: #endif /* DANGEROUS */
                    548:                default:
                    549:                        SET_U_ERROR (EINVAL,
                    550:                                     "nioctl(): illegal command for kmem");
                    551:                        return -1;
                    552:                }
                    553: #endif /* NULL_IOCTL */
                    554: #ifdef IDLE_DEV
                    555:        case DEV_IDLE:
                    556:                if (cmd != NLIDLE) { 
                    557:                        SET_U_ERROR (EINVAL,
                    558:                                     "nioctl(): illegal command for idle");
                    559:                        return -1;
                    560:                } else {
                    561:                        register PROC *pp;
                    562:                        register int *mem = vec;
                    563: 
                    564: 
                    565:                        pp = & procq;   /* point to process queue */
                    566: 
                    567:                        if (pp->p_pid != 0) {
                    568:                                while ((pp = pp->p_nforw) != &procq)
                    569:                                        if (pp->p_pid == 0)       /* idle process ? */
                    570:                                                break;
                    571:                        }
                    572: 
                    573:                        /*
                    574:                         * At this point, pp->p_utime and pp->p_stime contain
                    575:                         * the idle time of the system process
                    576:                         */
                    577: 
                    578:                        if (pp->p_pid != 0)
                    579:                                putuwd (mem ++, 0);
                    580:                        else
                    581:                                putuwd (mem ++, pp->p_utime + pp->p_stime);
                    582:                        putuwd (mem, lbolt);
                    583:                        return 1; 
                    584:                }
                    585: 
                    586: #endif /* IDLE_DEV */
                    587:        default:
                    588:                SET_U_ERROR(EINVAL, "illegal minor device for null ioctl");
                    589:                return -1;
                    590:        } /* switch on minor device */
                    591: 
                    592: } /* nlioctl() */
                    593: 
                    594: #endif /* NULL_IOCTL || IDLE_DEV */
                    595: 
                    596: #ifdef DANGEROUS /* Includes all of docall().  */
                    597: /*
                    598:  * MASSIVE SECURITY HOLE!  This should NOT be included in a distribution
                    599:  * system.  Among other problems, it becomes possible to do "setuid(0)".
                    600:  *
                    601:  * Call a function with arguments.
                    602:  *
                    603:  * Takes an array of unsigned ints.  The first element is the length of
                    604:  * the whole array, the second element is a pointer to the function to
                    605:  * call, all other elements are arguments.  At most 5 arguments may be
                    606:  * passed.
                    607:  *
                    608:  * Returns the return value of the called fuction in uvec[0].
                    609:  */
                    610: int
                    611: docall(uvec)
                    612:        unsigned uvec[];
                    613: {
                    614:        int (* func)();
                    615:        unsigned kvec[7];
                    616:        int retval;
                    617: 
                    618:        printf("NLCALL security hole.\n");
                    619: 
                    620:        /* Fetch the first element of vec.  */
                    621:        ukcopy (uvec, kvec, sizeof (unsigned));
                    622: 
                    623:        if (kvec [0] < 2 || kvec[0] > 7) {
                    624:                /* Invalid number of elements in uvec.  */
                    625:                SET_U_ERROR (EINVAL, "Invalid number of elements in uvec");
                    626:                return -1;
                    627:        }
                    628:        
                    629:        /* Fetch the whole vector.  */
                    630:        ukcopy (uvec, kvec, kvec [0] * sizeof (unsigned));
                    631: 
                    632:        /* Extract the function.  */
                    633:        func = (int (*)()) kvec [1];
                    634: 
                    635:        /* Call the function with all arguments.  */
                    636:        retval = (* func) (kvec [2], kvec [3], kvec [4], kvec [5], kvec [6]);
                    637: 
                    638:        kucopy (& retval, uvec, sizeof (unsigned));
                    639: } /* docall() */
                    640: 
                    641: #endif /* DANGEROUS */
                    642: 
                    643: /*
                    644:  * int lock_clock() -- Stop the update cycle on the CMOS RT clock and
                    645:  * wait for it to settle.  Returns 0 if the clock would not settle
                    646:  * in time.
                    647:  */
                    648: int
                    649: lock_clock()
                    650: {
                    651:        register int i;
                    652: 
                    653:        /*
                    654:         * Wait for the clock to settle.  If it does not settle in
                    655:         * a reasonable amount of time, give up.
                    656:         */
                    657: 
                    658:        i = 65536;      /* Loop for a longish time.  */
                    659:        while (-- i > 0) {
                    660:                if (0 == (UIP & read_cmos (SRA))) {
                    661:                        break;  /* Break if there is no update in progress.  */
                    662:                }
                    663:        }
                    664:        
                    665:        if (0 == i) {
                    666:                /* The clock would not settle.  */
                    667:                return 0;
                    668:        }
                    669: 
                    670:        /*
                    671:         * There is a tiny race here--an interrupt could conceivably
                    672:         * come here, thus allowing enough delay for another update to
                    673:         * begin.  But if we take interrupts that take a full second
                    674:         * to process, other things are going to break horribly.
                    675:         */
                    676:        
                    677:        /*
                    678:         * Lock out updates.
                    679:         * We set the No Updates bit in Clock Status Register B.
                    680:         */
                    681:        write_cmos (SRB, read_cmos (SRB) | NO_UPD);
                    682:        return 1;
                    683: } /* lock_clock() */
                    684: 
                    685: /*
                    686:  * void unlock_clock() -- Restart the update cycle on the CMOS RT clock.
                    687:  */ 
                    688: void
                    689: unlock_clock()
                    690: {
                    691:        /*
                    692:         * We clear the No Updates bit in Clock Status Register B.
                    693:         */
                    694:        write_cmos (SRB, read_cmos(SRB) & ~ NO_UPD);
                    695: } /* unlock_clock() */

unix.superglobalmegacorp.com

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