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

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

unix.superglobalmegacorp.com

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