Annotation of researchv9/sys/sun3/machdep.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)machdep.c 1.1 86/02/03 Copyr 1986 Sun Micro";
        !             3: #endif lint
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1986 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: #include "../h/param.h"
        !            10: #include "../h/systm.h"
        !            11: #include "../h/dir.h"
        !            12: #include "../h/user.h"
        !            13: #include "../h/map.h"
        !            14: #include "../h/vm.h"
        !            15: #include "../h/lnode.h"
        !            16: #include "../h/proc.h"
        !            17: #include "../h/msgbuf.h"
        !            18: #include "../h/buf.h"
        !            19: #include "../h/inode.h"
        !            20: #include "../h/file.h"
        !            21: #include "../h/text.h"
        !            22: #include "../h/callout.h"
        !            23: #include "../h/cmap.h"
        !            24: #include "../h/reboot.h"
        !            25: 
        !            26: #include "../machine/mbvar.h"
        !            27: #include "../machine/psl.h"
        !            28: #include "../machine/reg.h"
        !            29: #include "../machine/clock.h"
        !            30: #include "../machine/pte.h"
        !            31: #include "../machine/scb.h"
        !            32: #include "../machine/mmu.h"
        !            33: #include "../machine/cpu.h"
        !            34: #include "../machine/eeprom.h"
        !            35: #include "../machine/interreg.h"
        !            36: #include "../machine/memerr.h"
        !            37: #include "../machine/eccreg.h"
        !            38: #include "../machine/frame.h"
        !            39: 
        !            40: /*
        !            41:  * Declare these as initialized data so we can patch them.
        !            42:  */
        !            43: int nbuf = 0;
        !            44: int nswbuf = 0;
        !            45: int bufpages = 0;
        !            46: int physmem = 0;       /* memory size in pages, patch if you want less */
        !            47: int kernprot = 1;      /* write protect kernel text */
        !            48: int msgbufinit = 0;    /* message buffer has been initialized, ok to printf */
        !            49: dev_t consdev = 0;
        !            50: 
        !            51: int (*exit_vector)() = (int (*)())0;   /* Where to go when halting UNIX */
        !            52: 
        !            53: #define TESTVAL        0xA55A  /* memory test value */
        !            54: 
        !            55: u_char getsegmap(), pmegallocres();
        !            56: long   getpgmap();
        !            57: 
        !            58: #ifdef SUN3_260
        !            59: /*
        !            60:  * Since there is no implied ordering of the memory cards, we store
        !            61:  * a zero terminated list of pointers to eccreg's that are active so
        !            62:  * that we only look at existent memory cards during softecc() handling.
        !            63:  */
        !            64: struct eccreg *ecc_alive[MAX_ECC+1];
        !            65: #endif SUN3_260
        !            66: 
        !            67: /*
        !            68:  * We make use of CMAPn (the pte address)
        !            69:  * and CADDRn (the virtual address)
        !            70:  * which are both temporaries defined in locore.s,
        !            71:  * not preserved across context switches,
        !            72:  * and not to be used in interrupt routines
        !            73:  */
        !            74: 
        !            75: /*
        !            76:  * Machine-dependent startup code
        !            77:  */
        !            78: startup()
        !            79: {
        !            80:        register int unixsize, dvmapage;
        !            81:        register unsigned i;
        !            82:        register int c;
        !            83:        register struct pte *pte;
        !            84:        register caddr_t v;
        !            85:        u_int firstaddr;                /* next free physical page number */
        !            86:        extern char start[], etext[], end[], CADDR1[], Syslimit[];
        !            87:        u_char oc, u_pmeg;
        !            88:        u_int mapaddr;
        !            89:        caddr_t zmemall();
        !            90:        void v_handler();
        !            91:        int mon_mem;
        !            92: 
        !            93:        initscb();                      /* set trap vectors */
        !            94:        *INTERREG |= IR_ENA_INT;        /* make sure interrupts can occur */
        !            95:        firstaddr = btoc((int)end - KERNELBASE) + UPAGES;
        !            96: 
        !            97:        /* 
        !            98:         * Initialize map of allocated page map groups.
        !            99:         * Must be done before mapin of unallocated segments.
        !           100:         */
        !           101:        pmeginit();                     /* init list of pmeg data structures */
        !           102:        ctxinit();                      /* init context data structures */
        !           103: 
        !           104:        /*
        !           105:         * Reserve necessary pmegs and set segment mapping.
        !           106:         * It is assumed here that the pmegs for low
        !           107:         * memory have already been duplicated for the
        !           108:         * segments up in the kernel virtual address space.
        !           109:         */
        !           110: 
        !           111:        /*
        !           112:         * invalidate to start of high mapping
        !           113:         */
        !           114:        for (i = 0; i < KERNELBASE >> SGSHIFT; i++)
        !           115:                setsegmap(i, (u_char)SEGINV);
        !           116: 
        !           117:        /* reserve kernel pmegs */
        !           118:        for (; i < ptos(NPAGSEG - 1 + btoc(end)); i++)
        !           119:                pmegreserve(getsegmap(i));
        !           120: 
        !           121:        for (; i < (MONSTART >> SGSHIFT); i++)  /* invalidate to mon start */
        !           122:                setsegmap(i, (u_char)SEGINV);
        !           123: 
        !           124:        for (; i < (MONEND >> SGSHIFT); i++)    /* reserve monitor pmegs */
        !           125:                if ((oc = getsegmap(i)) != (u_char)SEGINV)      
        !           126:                        pmegreserve(oc);
        !           127: 
        !           128:        for (; i < NSEGMAP - 1; i++)            /* invalid until last seg */
        !           129:                setsegmap(i, (u_char)SEGINV);
        !           130: 
        !           131:        /*
        !           132:         * Last segment contains the u area itself, 
        !           133:         * the pmeg here is reserved for all contexts.
        !           134:         * We also reserve the invalid pmeg itself.
        !           135:         */
        !           136:        u_pmeg = getsegmap(NSEGMAP - 1);
        !           137:        pmegreserve(u_pmeg);
        !           138:        pmegreserve((u_char)SEGINV);
        !           139: 
        !           140:        setcputype();                   /* sets cpu and dvmasize variables */
        !           141: 
        !           142:        /*
        !           143:         * Make sure the memory error register is
        !           144:         * set up to generate interrupts on error.
        !           145:         */
        !           146: #if defined(SUN3_160) || defined(SUN3_50)
        !           147:        if (cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50)
        !           148:                MEMREG->mr_per = PER_INTENA | PER_CHECK;
        !           149: #endif defined(SUN3_160) || defined(SUN3_50)
        !           150: 
        !           151: #ifdef SUN3_260
        !           152:        if (cpu == CPU_SUN3_260) {
        !           153:                register struct eccreg **ecc_nxt = ecc_alive;
        !           154:                register struct eccreg *ecc;
        !           155: 
        !           156:                /*
        !           157:                 * Go probe for all memory cards and perform initialization.
        !           158:                 * The address of the cards found is stashed in ecc_alive[].
        !           159:                 * We assume that the cards are already enabled and the
        !           160:                 * base addresses have been set correctly by the monitor.
        !           161:                 */
        !           162:                for (ecc = ECCREG; ecc < &ECCREG[MAX_ECC]; ecc++) {
        !           163:                        if (peekc((char *)ecc) == -1)
        !           164:                                continue;
        !           165:                        ecc->eccena.ena_scrub = 1;
        !           166:                        ecc->eccena.ena_busena = 1;
        !           167:                        *ecc_nxt++ = ecc;
        !           168:                }
        !           169:                *ecc_nxt = (struct eccreg *)0;          /* terminate list */
        !           170: 
        !           171:                MEMREG->mr_eer = EER_INTENA | EER_CE_ENA;
        !           172:        }
        !           173: #endif SUN3_260
        !           174: 
        !           175:        /*
        !           176:         * Allocate pmegs for DVMA space
        !           177:         */
        !           178:        for (i = ptos(btop(DVMA)); i < ptos(btop(DVMA) + dvmasize); i++) {
        !           179:                u_char pm = pmegallocres();
        !           180: 
        !           181:                setsegmap(i, pm);
        !           182:                for (v = (caddr_t)ctob(NPAGSEG * i);
        !           183:                        v < (caddr_t)ctob(NPAGSEG * (i+1));
        !           184:                    v += NBPG)
        !           185:                        setpgmap(v, (long)0);
        !           186:        }
        !           187: 
        !           188:        /*
        !           189:         * Now go through all the other contexts and set up the segment
        !           190:         * maps so that all segments are mapped the same.
        !           191:         * We have to use a PROM routine to do this since we don't want
        !           192:         * to switch to a new (unmapped) context to call setsegmap()!
        !           193:         */
        !           194:        for (c = 0; c < NCONTEXT; c++) {
        !           195:                if (c == KCONTEXT)
        !           196:                        continue;
        !           197: 
        !           198:                for (v = (caddr_t)0, i = 0;
        !           199:                    v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBSG, i++)
        !           200:                        (*romp->v_setcxsegmap)(c, v, getsegmap(i));
        !           201:        }
        !           202: 
        !           203:        /*
        !           204:         * Initialize kernel page table entries.
        !           205:         */
        !           206:        pte = &Sysmap[0];
        !           207: 
        !           208:        /* invalid until start except scb page which is kernel writable */
        !           209:        for (v = (caddr_t)KERNELBASE; v < (caddr_t)start; v += NBPG) {
        !           210:                if (v == (caddr_t)&scb)
        !           211:                        *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
        !           212:                else
        !           213:                        *(int *)pte = 0;
        !           214:                setpgmap(v, *(long *)pte++);
        !           215:        }
        !           216: 
        !           217:        /* set up kernel text pages */
        !           218:        for (; v < (caddr_t)etext; v += NBPG) {
        !           219:                if (kernprot)           /* is kernel to be protected? */
        !           220:                        *(int *)pte = PG_V | PG_KR | getpgmap(v) & PG_PFNUM;
        !           221:                else
        !           222:                        *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
        !           223:                setpgmap(v, *(long *)pte++);
        !           224:        }
        !           225: 
        !           226:        /* set up kernel data/bss pages to be writeable */
        !           227:        for (; v < (caddr_t)end; v += NBPG) {
        !           228:                *(int *)pte = PG_V | PG_KW | getpgmap(v) & PG_PFNUM;
        !           229:                setpgmap(v, *(long *)pte++);
        !           230:        }
        !           231: 
        !           232:        /* invalid until end of this segment */
        !           233:        i = ((u_int)end + SGOFSET) & ~SGOFSET;
        !           234:        for (; v < (caddr_t)i; v += NBPG)
        !           235:                setpgmap(v, (long)0);
        !           236: 
        !           237:        /*
        !           238:         * Remove user access to monitor-set-up maps.
        !           239:         */
        !           240:        for (i = MONSTART>>SGSHIFT; i < MONEND>>SGSHIFT; i++) {
        !           241:                if (getsegmap(i) == SEGINV)
        !           242:                        continue;
        !           243:                for (v = (caddr_t)ctob(NPAGSEG * i); 
        !           244:                        v < (caddr_t)ctob(NPAGSEG * (i+1));
        !           245:                    v += NBPG)
        !           246:                        setpgmap(v, (long)(((getpgmap(v) & ~PG_PROT) | PG_KW)));
        !           247:        }
        !           248: 
        !           249:        /*
        !           250:         * Invalidate any other pages in last segment
        !           251:         * besides the u area, EEPROM_ADDR, CLKADDR,
        !           252:         * MEMREG, INTERREG and MONSHORTPAGE.  This sets
        !           253:         * up the kernel redzone below the u area.  We
        !           254:         * get interrupt redzone for free when the kernel
        !           255:         * is write protected as the interrupt stack is
        !           256:         * the first thing in the data area.  Since u
        !           257:         * and MONSHORTPAGE are defined as 32 bit virtual
        !           258:         * addresses (to get short references to work),
        !           259:         * we must mask to get only the 28 bits we really
        !           260:         * want to look at.
        !           261:         */
        !           262:        for (v = (caddr_t)ctob(NPAGSEG * (NSEGMAP - 1));
        !           263:             v < (caddr_t)ctob(NPAGSEG * NSEGMAP); v += NBPG) {
        !           264:                if (((u_int)v < ((u_int)&u & 0x0FFFFFFF) ||
        !           265:                    (u_int)v >= (((u_int)&u & 0x0FFFFFFF) + UPAGES*NBPG)) &&
        !           266:                    (u_int)v != ((u_int)MONSHORTPAGE & 0x0FFFFFFF) &&
        !           267:                    (u_int)v != (u_int)EEPROM_ADDR &&
        !           268:                    (u_int)v != (u_int)CLKADDR &&
        !           269:                    (u_int)v != (u_int)MEMREG &&
        !           270:                    (u_int)v != (u_int)INTERREG)
        !           271:                        setpgmap(v, (long)0);
        !           272:        }
        !           273: 
        !           274:        /*
        !           275:         * v_memorysize is the amount of physical memory while
        !           276:         * v_memoryavail is the amount of usable memory in versions
        !           277:         * equal or greater to 1.  Mon_mem is the difference which
        !           278:         * is the number of pages hidden by the monitor.
        !           279:         */
        !           280:        if (romp->v_romvec_version >= 1)
        !           281:                mon_mem = btop(*romp->v_memorysize - *romp->v_memoryavail);
        !           282:        else
        !           283:                mon_mem = 0;
        !           284:        /*
        !           285:         * If physmem is patched to be non-zero, use it instead of
        !           286:         * the monitor value unless physmem is larger than the total
        !           287:         * amount of memory on hand.
        !           288:         */
        !           289:        if (physmem == 0 || physmem > btop(*romp->v_memorysize))
        !           290:                physmem = btop(*romp->v_memorysize);
        !           291:        /*
        !           292:         * Adjust physmem down for the pages stolen by the monitor.
        !           293:         */
        !           294:        physmem -= mon_mem;
        !           295:        maxmem = physmem;
        !           296: 
        !           297:        /*
        !           298:         * v_vector_cmd is the handler for new monitor vector
        !           299:         * command in versions equal or greater to 2.
        !           300:         * We install v_handler() there for Unix.
        !           301:         */
        !           302:        if (romp->v_romvec_version >= 2)
        !           303:                *romp->v_vector_cmd = v_handler;
        !           304: 
        !           305: #include "bwtwo.h"
        !           306: #if NBWTWO > 0
        !           307:        if (physmem > btop(OBFBADDR + FBSIZE))
        !           308:                fbobmemavail = 1;
        !           309:        else
        !           310:                fbobmemavail = 0;
        !           311: #else
        !           312:        fbobmemavail = 0;
        !           313: #endif
        !           314: 
        !           315:        /*
        !           316:         * Determine if anything lives in DVMA bus space.
        !           317:         * We're paranoid and go through both the 16 bit
        !           318:         * and 32 bit device types.
        !           319:         */
        !           320:        disable_dvma();
        !           321:        for (dvmapage = 0; dvmapage < btoc(dvmasize); dvmapage++) {
        !           322:                mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D16),
        !           323:                    1, PG_V | PG_KW);
        !           324:                if (poke((short *)CADDR1, TESTVAL) == 0)
        !           325:                        break;
        !           326:                mapin(CMAP1, btop(CADDR1), (u_int)(dvmapage | PGT_VME_D32),
        !           327:                    1, PG_V | PG_KW);
        !           328:                if (poke((short *)CADDR1, TESTVAL) == 0)
        !           329:                        break;
        !           330:        }
        !           331:        enable_dvma();
        !           332: 
        !           333:        /*
        !           334:         * Initialize error message buffer (in low real memory before start).
        !           335:         * Printf's which occur prior to this will not be captured.
        !           336:         */
        !           337:        mapin(msgbufmap, (u_int)btop(&msgbuf),
        !           338:            (u_int)btop((int)start - sizeof (struct msgbuf) - KERNELBASE),
        !           339:            (int)btoc(sizeof (struct msgbuf)), PG_V | PG_KW);
        !           340:        msgbufinit = 1;
        !           341: 
        !           342:        /*
        !           343:         * Allocate IOPB memory space just below the message
        !           344:         * buffer and map it to the first pages of DVMA space.
        !           345:         */
        !           346:        maxmem -= IOPBMEM;
        !           347:        for (v = (caddr_t)DVMA, i = maxmem; i < maxmem + IOPBMEM;
        !           348:            v += NBPG, i++) {
        !           349:                struct pte tmp;                 /* scratch pte */
        !           350: 
        !           351:                mapin(&tmp, btop(v), i, 1, PG_V | PG_KW);
        !           352:        }
        !           353: 
        !           354:        /*
        !           355:         * Good {morning,afternoon,evening,night}.
        !           356:         * When printing memory, use the total including
        !           357:         * those hidden by the monitor (mon_mem).
        !           358:         */
        !           359:        printf(version);
        !           360: 
        !           361:        if (dvmapage < btoc(dvmasize)) {
        !           362:                printf("CAN'T HAVE PERIPHERALS IN RANGE 0 - %dKB\n",
        !           363:                    ctob(dvmasize) / 1024);
        !           364:                panic("dvma collision");
        !           365:        }
        !           366: 
        !           367: #ifndef lint
        !           368:        if ((int)start - (int)ctob(btoc(sizeof (struct msgbuf))) <= (int)&scb)
        !           369:                panic("msgbuf too large");
        !           370: 
        !           371:        if (sizeof (struct user) > UPAGES * NBPG)
        !           372:                panic("user area too large");
        !           373: #endif lint
        !           374: 
        !           375:        if ((int)Syslimit > (CSEG << SGSHIFT))
        !           376:                panic("system map tables too large");
        !           377: 
        !           378:         /*
        !           379:         * Determine how many buffers to allocate.
        !           380:         * Use 10% of memory (not counting 512K for kernel), with min of 16.
        !           381:         * We allocate 1/4 as many swap buffer headers as file i/o buffers.
        !           382:         */
        !           383:        if (bufpages == 0)
        !           384:                bufpages = (physmem * NBPG - 512 * 1024) / 10 / CLBYTES;
        !           385:        if (nbuf == 0) {
        !           386:                nbuf = bufpages;
        !           387:                if (nbuf < 16)
        !           388:                        nbuf = 16;
        !           389:        }
        !           390:        if (bufpages > nbuf * (BUFSIZE / CLBYTES))
        !           391:                bufpages = nbuf * (BUFSIZE / CLBYTES);
        !           392:        if (nswbuf == 0) {
        !           393:                nswbuf = (nbuf / 4) &~ 1;       /* force even */
        !           394:                if (nswbuf > 32)
        !           395:                        nswbuf = 32;            /* sanity */
        !           396:        }
        !           397:        printf("real mem = %d nbuf = %d nswbuf = %d\n",
        !           398:                ctob(physmem + mon_mem), nbuf, nswbuf);
        !           399: 
        !           400:        /*
        !           401:         * Allocate space for system data structures.
        !           402:         * The first available real memory address is in "firstaddr".
        !           403:         * The first available kernel virtual address is in "v".
        !           404:         * As pages of kernel virtual memory are allocated, "v" is incremented.
        !           405:         * "mapaddr" is the real memory address where the tables start.
        !           406:         * It is used when remapping the tables later.
        !           407:         * In order to support the frame buffer which might appear in 
        !           408:         * the middle of contiguous memory we adjust the map address to 
        !           409:         * start after the end of the frame buffer.  Later we will adjust
        !           410:         * the core map to take this hole into account.  The reason for
        !           411:         * this is to keep all the kernel tables contiguous in virtual space.
        !           412:         */
        !           413:        if (fbobmemavail)
        !           414:                mapaddr = btoc(OBFBADDR + FBSIZE);
        !           415:        else
        !           416:                mapaddr = firstaddr;
        !           417:        v = (caddr_t)(ctob(firstaddr) + KERNELBASE);
        !           418: #define        valloc(name, type, num) \
        !           419:            (name) = (type *)(v); (v) = (caddr_t)((name)+(num))
        !           420: #define        valloclim(name, type, num, lim) \
        !           421:            (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num)))
        !           422:        valloc(swbuf, struct buf, nswbuf);
        !           423:        valloclim(inode, struct inode, ninode, inodeNINODE);
        !           424:        valloclim(file, struct file, nfile, fileNFILE);
        !           425:        valloclim(proc, struct proc, nproc, procNPROC);
        !           426:        valloclim(text, struct text, ntext, textNTEXT);
        !           427:        valloclim(lnodes, struct kern_lnode, maxusers, lnodesMAXUSERS);
        !           428:        valloc(callout, struct callout, ncallout);
        !           429:        valloc(swapmap, struct map, nswapmap = nproc * 2);
        !           430:        valloc(argmap, struct map, ARGMAPSIZE);
        !           431:        valloc(kernelmap, struct map, nproc);
        !           432:        valloc(iopbmap, struct map, IOPBMAPSIZE);
        !           433:        valloc(mb_hd.mh_map, struct map, DVMAMAPSIZE);
        !           434: 
        !           435:        /*
        !           436:         * Now allocate space for core map
        !           437:         * Allow space for all of physical memory minus the amount 
        !           438:         * dedicated to the system. The amount of physical memory
        !           439:         * dedicated to the system is the total virtual memory of
        !           440:         * the system minus the space in the buffers which is not
        !           441:         * allocated real memory.
        !           442:         */
        !           443:        ncmap = physmem - firstaddr;
        !           444:        valloclim(cmap, struct cmap, ncmap, ecmap);
        !           445:        unixsize = btoc((int)(ecmap+1) - KERNELBASE);
        !           446: 
        !           447:        if ((int)unixsize > SYSPTSIZE)
        !           448:                panic("sys pt too small");
        !           449: 
        !           450:        /*
        !           451:         * Clear allocated space, and make r/w entries
        !           452:         * for the space in the kernel map.
        !           453:         */
        !           454:        if (unixsize >= physmem - 8*UPAGES)
        !           455:                panic("no memory");
        !           456: 
        !           457:        pte = &Sysmap[firstaddr];
        !           458:        for (i = firstaddr + btop(KERNELBASE); i < btoc(v); i++) {
        !           459:                mapin(pte++, i, mapaddr,  1, PG_V | PG_KW);
        !           460:                clearseg(mapaddr++);
        !           461:        }
        !           462: 
        !           463:        /*
        !           464:         * Initialize callouts.
        !           465:         */
        !           466:        callfree = callout;
        !           467:        for (i = 1; i < ncallout; i++)
        !           468:                callout[i-1].c_next = &callout[i];
        !           469: 
        !           470:        /*
        !           471:         * Initialize memory allocator and swap
        !           472:         * and user page table maps.
        !           473:         */
        !           474:        if (fbobmemavail) {
        !           475:                meminit((int)firstaddr, maxmem);
        !           476:                memialloc((int)firstaddr, (int)btop(OBFBADDR));
        !           477:                memialloc((int)(1 + mapaddr), maxmem);
        !           478:        } else {
        !           479:                meminit((int)mapaddr, maxmem);
        !           480:                memialloc((int)mapaddr, maxmem);
        !           481:        }
        !           482:        maxmem = freemem;
        !           483:        printf("avail mem = %d\n", ctob(maxmem));
        !           484:        rminit(kernelmap, (long)(USRPTSIZE - CLSIZE), (long)CLSIZE,
        !           485:            "usrpt", nproc);
        !           486:        rminit(iopbmap, (long)ctob(IOPBMEM), (long)DVMA, 
        !           487:            "IOPB space", IOPBMAPSIZE);
        !           488:        rminit(mb_hd.mh_map, (long)(dvmasize - IOPBMEM), (long)IOPBMEM,
        !           489:            "DVMA map space", DVMAMAPSIZE);
        !           490: 
        !           491:        /*
        !           492:         * Configure the system.
        !           493:         */
        !           494:        bootflags();            /* get the boot options */
        !           495:        configure();            /* set up devices */
        !           496:        if (fbobmemavail) {
        !           497:                /*
        !           498:                 * Onboard frame buffer memory still
        !           499:                 * available, put back onto the free list.
        !           500:                 */
        !           501:                memialloc((int)btop(OBFBADDR), (int)btop(OBFBADDR + FBSIZE));
        !           502:                fbobmemavail = 0;
        !           503:        }
        !           504:        bufmemall();
        !           505:        uinit();                /* initialize the u area */
        !           506:        (void) spl0();          /* drop priority */
        !           507: }
        !           508: 
        !           509: /*
        !           510:  * set up a physical address
        !           511:  * into users virtual address space.
        !           512:  */
        !           513: sysphys()
        !           514: {
        !           515: 
        !           516:        if(!suser())
        !           517:                return;
        !           518:        u.u_error = EINVAL;
        !           519: }
        !           520: 
        !           521: /*
        !           522:  * This system call sets the time of year clock without touching
        !           523:  * the software clock.  It returns the previous clock value.  If
        !           524:  * the argument is zero or the caller is not the super-user, it
        !           525:  * does not change the clock.
        !           526:  * Since the clocks are the same on the SUN, it just calls stime.
        !           527:  */
        !           528: settod()
        !           529: {
        !           530:        register struct a {
        !           531:                long unsigned tod;
        !           532:        } *uap;
        !           533: 
        !           534:        u.u_r.r_time = time;
        !           535:        if (uap->tod != 0 && suser())
        !           536:                stime();
        !           537: }
        !           538: 
        !           539: /*
        !           540:  * Allocate physical memory for system buffers
        !           541:  * In Ethernet memory if the right board exists &
        !           542:  * the root device is ND & there are no block I/O DMA devices
        !           543:  */
        !           544: bufmemall()
        !           545: {
        !           546:        struct pte *pte;
        !           547:        long a, va;
        !           548:        int npages;
        !           549:        int i, j, base, residual;
        !           550: 
        !           551:        a = rmalloc(kernelmap, (long)(nbuf*BUFSIZE/NBPG));
        !           552:        if (a == 0)
        !           553:                panic("no vmem for buffers");
        !           554:        buffers = (caddr_t)kmxtob(a);
        !           555:        pte = &Usrptmap[a];
        !           556:        base = bufpages / nbuf;
        !           557:        residual = bufpages % nbuf;
        !           558:        for (i = 0; i < nbuf; i++) {
        !           559:                if (i < residual)
        !           560:                        npages = base+1;
        !           561:                else
        !           562:                        npages = base;
        !           563:                /* XXX - this loop only works if CLSIZE == 1 */
        !           564:                for (j = 0; j < npages; j += CLSIZE) {
        !           565:                        if (memall(pte+j, CLSIZE, &proc[0], CSYS) == 0)
        !           566:                                panic("no mem for buffers");
        !           567:                        *(int *)(pte+j) |= PG_V|PG_KW;
        !           568:                        va = (int)kmxtob(a+j);
        !           569:                        vmaccess(pte+j, (caddr_t)va, 1);
        !           570:                        bzero((caddr_t)va, CLBYTES);
        !           571:                }
        !           572:                pte += BUFSIZE/CLBYTES;
        !           573:                a += BUFSIZE/CLBYTES;
        !           574:        }
        !           575:        /*
        !           576:         * Double map and then unmap the last page of the last
        !           577:         * buffer to insure the presence of a pmeg.
        !           578:         * AARRRGGGHHH. Kludge away.
        !           579:         */
        !           580:        if (base < BUFSIZE/CLBYTES) {
        !           581:                pte -= BUFSIZE/CLBYTES;
        !           582:                va = (int)kmxtob(a-1);
        !           583:                pte[BUFSIZE/CLBYTES - 1] = pte[0];
        !           584:                vmaccess(&pte[BUFSIZE/CLBYTES - 1], (caddr_t)va, 1);
        !           585:                /* now unmap without disturbing the pmeg */
        !           586:                *(int *)&pte[BUFSIZE/CLBYTES - 1] = 0;
        !           587:                setpgmap((caddr_t)va, (long)0);
        !           588:        }
        !           589:        buf = (struct buf *)zmemall(memall, nbuf * sizeof(struct buf));
        !           590:        if (buf == 0)
        !           591:                panic("no mem for buf headers");
        !           592: }
        !           593: 
        !           594: struct bootf {
        !           595:        char    let;
        !           596:        short   bit;
        !           597: } bootf[] = {
        !           598:        'a',    RB_ASKNAME,
        !           599:        's',    RB_SINGLE,
        !           600:        'i',    RB_INITNAME,
        !           601:        'h',    RB_HALT,
        !           602:        0,      0,
        !           603: };
        !           604: char *initname = "/etc/init";
        !           605: 
        !           606: /*
        !           607:  * Parse the boot line to determine boot flags .
        !           608:  */
        !           609: bootflags()
        !           610: {
        !           611:        register struct bootparam *bp = (*romp->v_bootparam);
        !           612:        register char *cp;
        !           613:        register int i;
        !           614: 
        !           615:        cp = bp->bp_argv[1];
        !           616:        if (cp && *cp++ == '-')
        !           617:                do {
        !           618:                        for (i = 0; bootf[i].let; i++) {
        !           619:                                if (*cp == bootf[i].let) {
        !           620:                                        boothowto |= bootf[i].bit;
        !           621:                                        break;
        !           622:                                }
        !           623:                        }
        !           624:                        cp++;
        !           625:                } while (bootf[i].let && *cp);
        !           626:        if (boothowto & RB_INITNAME)
        !           627:                initname = bp->bp_argv[2];
        !           628:        if (boothowto & RB_HALT)
        !           629:                halt("bootflags");
        !           630: }
        !           631: 
        !           632: /*
        !           633:  * Start the initial user process.
        !           634:  * The program [initname] is invoked with one argument
        !           635:  * containing the boot flags.
        !           636:  */
        !           637: icode()
        !           638: {
        !           639:        struct execa {
        !           640:                char    *fname;
        !           641:                char    **argp;
        !           642:                char    **envp;
        !           643:        } *ap;
        !           644:        char *ucp, **uap, *arg0, *arg1;
        !           645:        int i;
        !           646: 
        !           647:        u.u_error = 0;                          /* paranoid */
        !           648:        /* Make a user stack (1 page) */
        !           649:        expand(1, 1);
        !           650:        (void) swpexpand(0, 1, &u.u_dmap, &u.u_smap);
        !           651: 
        !           652:        /* Move out the boot flag argument */
        !           653:        ucp = (char *)USRSTACK;
        !           654:        (void) subyte(--ucp, 0);                /* trailing zero */
        !           655:        for (i = 0; bootf[i].let; i++) {
        !           656:                if (boothowto & bootf[i].bit)
        !           657:                        (void) subyte(--ucp, bootf[i].let);
        !           658:        }
        !           659:        (void) subyte(--ucp, '-');              /* leading hyphen */
        !           660:        arg1 = ucp;
        !           661: 
        !           662:        /* Move out the file name (also arg 0) */
        !           663:        for (i = 0; initname[i]; i++)
        !           664:                ;                               /* size the name */
        !           665:        for (; i >= 0; i--)
        !           666:                (void) subyte(--ucp, initname[i]);
        !           667:        arg0 = ucp;
        !           668: 
        !           669:        /* Move out the arg pointers */
        !           670:        uap = (char **) ((int)ucp & ~(NBPW-1));
        !           671:        (void) suword((caddr_t)--uap, 0);       /* terminator */
        !           672:        (void) suword((caddr_t)--uap, (int)arg1);
        !           673:        (void) suword((caddr_t)--uap, (int)arg0);
        !           674: 
        !           675:        /* Point at the arguments */
        !           676:        u.u_ap = u.u_arg;
        !           677:        ap = (struct execa *)u.u_ap;
        !           678:        ap->fname = arg0;
        !           679:        ap->argp = uap;
        !           680:        ap->envp = 0;
        !           681:        u.u_dirp = (caddr_t)u.u_arg[0];
        !           682:        
        !           683:        /* Now let exec do the hard work */
        !           684:        exece();
        !           685:        if (u.u_error) {
        !           686:                printf("Can't invoke %s, error %d\n", initname, u.u_error);
        !           687:                panic("icode");
        !           688:        }
        !           689: }
        !           690: 
        !           691: /*
        !           692:  * Set up page tables for process 0 U pages.
        !           693:  * This is closely related to way the code
        !           694:  * in locore.s sets things up.
        !           695:  */
        !           696: uinit()
        !           697: {
        !           698:        register struct pte *pte;
        !           699:        u_int page;
        !           700:        register int i;
        !           701:        extern char end[];
        !           702: 
        !           703:        /*
        !           704:         * main() will initialize proc[0].p_p0br to u.u_pcb.pcb_p0br
        !           705:         * and proc[0].p_szpt to 1.  All we have to do is set up
        !           706:         * the pcb_p{0,1}{b,l}r registers in the pcb for now.
        !           707:         */
        !           708: 
        !           709:        /* initialize base and length of P0 region */
        !           710:        u.u_pcb.pcb_p0br = usrpt;
        !           711:        u.u_pcb.pcb_p0lr = 0;           /* no user text/data (P0) for proc 0 */
        !           712: 
        !           713:        /*
        !           714:         * initialize base and length of P1 region,
        !           715:         * where the length here is for invalid pages
        !           716:         */
        !           717:        u.u_pcb.pcb_p1br = initp1br(usrpt + 1 * NPTEPG);
        !           718:        u.u_pcb.pcb_p1lr = P1PAGES;     /* no user stack (P1) for proc 0 */
        !           719: 
        !           720:        /*
        !           721:         * Doublely map the page containing the scb to contain the
        !           722:         * ptes whose virtual address is usrpt.  Got that?
        !           723:         */
        !           724:        page = (u_int)(getpgmap((caddr_t)&scb) & PG_PFNUM);
        !           725:        mapin(&Usrptmap[0], btop(usrpt), page, 1, PG_V | PG_KW); 
        !           726: 
        !           727:        /*
        !           728:         * Now build the software page maps to map virtual U to physical U.
        !           729:         * These pages have already been set up using the real pages beyond
        !           730:         * end by locore.s.
        !           731:         */
        !           732:        pte = usrpt + 1 * NPTEPG - UPAGES;
        !           733:        page = btop((int)end + (NBPG - 1) - KERNELBASE);
        !           734:        for (i = 0; i < UPAGES; i++)
        !           735:                *(int *)pte++ = PG_V | PG_KW | page++;
        !           736: }
        !           737: 
        !           738: struct sigcontext {
        !           739:        int     sc_sp;                  /* sp to restore */
        !           740:        int     sc_pc;                  /* pc to retore */
        !           741:        int     sc_ps;                  /* psl to restore */
        !           742: };
        !           743: /*
        !           744:  * Send an interrupt to process.
        !           745:  *
        !           746:  * When using new signals user code must do a
        !           747:  * sys #139 to return from the signal, which
        !           748:  * calls sigcleanup below, which resets the
        !           749:  * signal mask and the notion of onsigstack,
        !           750:  * and returns from the signal handler.
        !           751:  */
        !           752: sendsig(p, sig)
        !           753:        int (*p)(), sig;
        !           754: {
        !           755:        register int usp, *regs, scp;
        !           756:        struct nframe {
        !           757:                int     sig;
        !           758:                int     code;
        !           759:                int     scp;
        !           760:        } frame;
        !           761:        struct sigcontext sc;
        !           762: 
        !           763: #define        mask(s) (1<<((s)-1))
        !           764:        regs = u.u_ar0;
        !           765: 
        !           766:        usp = regs[SP];
        !           767:        usp -= sizeof (struct sigcontext);
        !           768:        scp = usp;
        !           769:        usp -= sizeof (frame);
        !           770:        if (usp <= USRSTACK - ctob(u.u_ssize))
        !           771:                (void) grow((unsigned)usp);
        !           772:        if (useracc((caddr_t)usp, sizeof(frame) + sizeof(sc), B_WRITE) == 0) {
        !           773:                /*
        !           774:                 * Process has trashed its stack; give it an illegal
        !           775:                 * instruction to halt it in its tracks.
        !           776:                 */
        !           777:                u.u_signal[SIGILL] = SIG_DFL;
        !           778:                u.u_procp->p_siga0 &= ~(1<<(SIGILL-1));
        !           779:                u.u_procp->p_siga1 &= ~(1<<(SIGILL-1));
        !           780:                psignal(u.u_procp, SIGILL);
        !           781:        }
        !           782:        /*
        !           783:         * push sigcontext structure.
        !           784:         */
        !           785:        sc.sc_sp = regs[SP];
        !           786:        sc.sc_pc = regs[PC];
        !           787:        sc.sc_ps = regs[PS];
        !           788:        /*
        !           789:         * If trace mode was on for the user process
        !           790:         * when we came in here, it may have been because
        !           791:         * of an ast-induced trace on a trap instruction,
        !           792:         * in which case we do not want to restore the
        !           793:         * trace bit in the status register later on
        !           794:         * in sigcleanup().  If we were to restore it
        !           795:         * and another ast trap had been posted, we would
        !           796:         * end up marking the trace trap as a user-requested
        !           797:         * real trace trap and send a bogus "Trace/BPT" signal.
        !           798:         */
        !           799:        if ((sc.sc_ps & PSL_T) && (u.u_pcb.pcb_p0lr & TRACE_AST))
        !           800:                sc.sc_ps &= ~PSL_T;
        !           801:        (void) copyout((caddr_t)&sc, (caddr_t)scp, sizeof (sc));
        !           802:        /*
        !           803:         * push call frame.
        !           804:         */
        !           805:        frame.sig = sig;
        !           806:        if (sig == SIGILL || sig == SIGFPE || sig == SIGEMT) {
        !           807:                frame.code = u.u_code;
        !           808:                u.u_code = 0;
        !           809:        } else
        !           810:                frame.code = 0;
        !           811:        frame.scp = scp;
        !           812:        (void) copyout((caddr_t)&frame, (caddr_t)usp, sizeof (frame));
        !           813:        regs[SP] = usp;
        !           814:        regs[PC] = (int)p;
        !           815: }
        !           816: 
        !           817: /*
        !           818:  * Routine to cleanup state after a signal
        !           819:  * has been taken.  Reset signal mask and
        !           820:  * notion of on signal stack from context
        !           821:  * left there by sendsig (above).  Pop these
        !           822:  * values and perform rti.
        !           823:  */
        !           824: sigcleanup()
        !           825: {
        !           826:        struct sigcontext *scp, sc;
        !           827: 
        !           828:        scp = (struct sigcontext *)fuword((caddr_t)u.u_ar0[SP] + sizeof(int));
        !           829:        if ((int)scp == -1)
        !           830:                return;
        !           831:        if (copyin((caddr_t)scp, (caddr_t)&sc, sizeof (sc)))
        !           832:                return;
        !           833:        u.u_ar0[SP] = sc.sc_sp;
        !           834:        u.u_ar0[PC] = sc.sc_pc;
        !           835:        u.u_ar0[PS] = sc.sc_ps;
        !           836:        u.u_ar0[PS] &= ~PSL_USERCLR;
        !           837:        u.u_ar0[PS] |= PSL_USERSET;
        !           838:        u.u_eosys = REALLYRETURN;
        !           839: }
        !           840: #undef mask
        !           841: 
        !           842: int    waittime = -1;
        !           843: 
        !           844: boot(arghowto)
        !           845:        int arghowto;
        !           846: {
        !           847:        register int howto;
        !           848:        static int prevflag = 0;
        !           849:        register struct buf *bp;
        !           850:        int iter, nbusy;
        !           851:        int s;
        !           852: 
        !           853:        consdev = 0;
        !           854:        startnmi();
        !           855:        howto = arghowto;
        !           856:        if ((howto&RB_NOSYNC)==0 && waittime < 0 && bfreelist[0].b_forw) {
        !           857:                waittime = 0;
        !           858:                update();
        !           859:                printf("syncing disks... ");
        !           860:                while (++waittime <= 5)
        !           861:                        sleep((caddr_t)&lbolt, PZERO);
        !           862:                printf("done\n");
        !           863:        }
        !           864:        s = spl7();                             /* extreme priority */
        !           865:        if (howto & RB_HALT) {
        !           866:                halt((char *)NULL);
        !           867:                /* MAYBE REACHED */
        !           868:        } else {
        !           869:                if ((howto & RB_PANIC) && prevflag == 0) {
        !           870:                        prevflag = 1;
        !           871:                        dumpsys();
        !           872: 
        !           873:                }
        !           874:                printf("Rebooting Unix...\n");
        !           875:                (*romp->v_boot_me)(howto & RB_SINGLE ? "-s" : "");
        !           876:                /*NOTREACHED*/
        !           877:        }
        !           878:        (void) splx(s);
        !           879: }
        !           880: 
        !           881: /*
        !           882:  * Initialize UNIX's vector table:
        !           883:  * Vectors are copied from protoscb unless
        !           884:  * they are zero; zero means preserve whatever the
        !           885:  * monitor put there.  If the protoscb is zero,
        !           886:  * then the original contents are copied into
        !           887:  * the scb we are setting up.
        !           888:  */
        !           889: initscb()
        !           890: {
        !           891:        register int *s, *p, *f;
        !           892:        register int n;
        !           893:        struct scb *orig, *getvbr();
        !           894: 
        !           895:        orig = getvbr();
        !           896:        exit_vector = orig->scb_trap[14];
        !           897:        s = (int *)&scb;
        !           898:        p = (int *)&protoscb;
        !           899:        f = (int *)orig;
        !           900:        for (n = sizeof (struct scb)/sizeof (int); n--; s++, p++, f++) {
        !           901:                if (*p) 
        !           902:                        *s = *p;
        !           903:                else
        !           904:                        *s = *f;
        !           905:        }
        !           906:        setvbr(&scb);
        !           907: }
        !           908: 
        !           909: /*
        !           910:  * Clear a segment (page (click)).
        !           911:  */
        !           912: clearseg(pgno)
        !           913:        u_int pgno;
        !           914: {
        !           915:        extern char CADDR1[];
        !           916: 
        !           917:        mapin(CMAP1, btop(CADDR1), pgno, 1, PG_V | PG_KW); 
        !           918:        bzero(CADDR1, NBPG);
        !           919: }
        !           920: 
        !           921: /*
        !           922:  * Copy a segment (page) from a user virtual address
        !           923:  * to a physical page number.
        !           924:  */
        !           925: copyseg(vaddr, pgno)
        !           926:        caddr_t vaddr;
        !           927:        int pgno;
        !           928: {
        !           929:        register struct pte *pte;
        !           930:        register int lock;
        !           931:        extern char CADDR1[];
        !           932: 
        !           933:        /*
        !           934:         * Make sure the user's page is valid and locked.
        !           935:         */
        !           936:        pte = vtopte(u.u_procp, btop(vaddr));
        !           937:        if (lock = !pte->pg_v) {
        !           938:                pagein((u_int)vaddr, &u, 1);            /* return it locked */
        !           939:                pte = vtopte(u.u_procp, btop(vaddr));   /* pte may move */
        !           940:        }
        !           941:        /*
        !           942:         * Map the destination page into kernel address space.
        !           943:         */
        !           944:        mapin(CMAP1, btop(CADDR1), (u_int)pgno, 1, PG_V | PG_KW);
        !           945:        (void) copyin(vaddr, CADDR1, CLBYTES);
        !           946:        if (lock)
        !           947:                munlock(pte->pg_pfnum);
        !           948: }
        !           949: 
        !           950: /*
        !           951:  * Handle "physical" block transfers.
        !           952:  */
        !           953: physstrat(bp, strat, pri)
        !           954:        register struct buf *bp;
        !           955:        int (*strat)();
        !           956:        int pri;
        !           957: {
        !           958:        register int npte, n;
        !           959:        register long a;
        !           960:        unsigned v;
        !           961:        register struct pte *pte, *kpte;
        !           962:        struct proc *rp;
        !           963:        int va, s, o;
        !           964: 
        !           965:        v = btop(bp->b_un.b_addr);
        !           966:        o = (int)bp->b_un.b_addr & PGOFSET;
        !           967:        npte = btoc(bp->b_bcount + o) + 1;
        !           968:        while ((a = rmalloc(kernelmap, (long)npte)) == NULL) {
        !           969:                kmapwnt++;
        !           970:                sleep((caddr_t)kernelmap, PSWP+4);
        !           971:        }
        !           972:        kpte = &Usrptmap[a];
        !           973:        rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc;
        !           974:        if ((bp->b_flags & B_PHYS) == 0)
        !           975:                pte = &Sysmap[btop((int)bp->b_un.b_addr - KERNELBASE)];
        !           976:        else if (bp->b_flags & B_UAREA)
        !           977:                pte = &rp->p_addr[v];
        !           978:        else if (bp->b_flags & B_PAGET)
        !           979:                pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)];
        !           980:        else
        !           981:                pte = vtopte(rp, v);
        !           982:        for (n = npte; --n != 0; kpte++, pte++)
        !           983:                *(int *)kpte = PG_V | PG_KW | (*(int *)pte & PG_PFNUM);
        !           984:        *(int *)kpte = 0;
        !           985:        va = (int)kmxtob(a);
        !           986:        vmaccess(&Usrptmap[a], (caddr_t)va, npte);
        !           987:        bp->b_saddr = bp->b_un.b_addr;
        !           988:        bp->b_un.b_addr = (caddr_t)(va | o);
        !           989:        bp->b_kmx = a;
        !           990:        bp->b_npte = npte;
        !           991:        (*strat)(bp);
        !           992:        if (bp->b_flags & B_DIRTY)
        !           993:                return;
        !           994:        s = spl6();
        !           995:        while ((bp->b_flags & B_DONE) == 0)
        !           996:                sleep((caddr_t)bp, pri);
        !           997:        (void) splx(s);
        !           998:        bp->b_un.b_addr = bp->b_saddr;
        !           999:        bp->b_kmx = 0;
        !          1000:        bp->b_npte = 0;
        !          1001:        mapout(&Usrptmap[a], npte);
        !          1002:        rmfree(kernelmap, (long)npte, a);
        !          1003: }
        !          1004: 
        !          1005: /*
        !          1006:  * Halt the machine and return to the monitor
        !          1007:  */
        !          1008: halt(s)
        !          1009:        char *s;
        !          1010: {
        !          1011:        extern struct scb *getvbr();
        !          1012: 
        !          1013:        if (s)
        !          1014:                (*romp->v_printf)("(%s) ", s);
        !          1015:        (*romp->v_printf)("Unix Halted\n\n");
        !          1016:        startnmi();
        !          1017:        if (exit_vector)
        !          1018:                getvbr()->scb_trap[14] = exit_vector;
        !          1019:        asm("trap #14");
        !          1020:        if (exit_vector)
        !          1021:                getvbr()->scb_trap[14] = protoscb.scb_trap[14];
        !          1022:        stopnmi();
        !          1023: }
        !          1024: 
        !          1025: /*
        !          1026:  * Print out a traceback for the caller - can be called anywhere
        !          1027:  * within the kernel or from the monitor by typing "g4" (for sun-2
        !          1028:  * compatibility) or "w trace".  This causes the monitor to call
        !          1029:  * the v_handler() routine which will call tracedump() for these cases.
        !          1030:  */
        !          1031: /*VARARGS0*/
        !          1032: tracedump(x1)
        !          1033:        caddr_t x1;
        !          1034: {
        !          1035:        struct frame *fp = (struct frame *)(&x1 - 2);
        !          1036:        u_int tospage = btoc(fp);
        !          1037: 
        !          1038:        (*romp->v_printf)("Begin traceback...fp = %x\n", fp);
        !          1039:        while (btoc(fp) == tospage) {
        !          1040:                if (fp == fp->fr_savfp) {
        !          1041:                        (*romp->v_printf)("FP loop at %x", fp);
        !          1042:                        break;
        !          1043:                }
        !          1044:                (*romp->v_printf)("Called from %x, fp=%x, args=%x %x %x %x\n",
        !          1045:                    fp->fr_savpc, fp->fr_savfp,
        !          1046:                    fp->fr_arg[0], fp->fr_arg[1], fp->fr_arg[2], fp->fr_arg[3]);
        !          1047:                fp = fp->fr_savfp;
        !          1048:        }
        !          1049:        (*romp->v_printf)("End traceback...\n");
        !          1050: }
        !          1051: 
        !          1052: /*
        !          1053:  * Buscheck is called by mbsetup to check to see it the requested
        !          1054:  * setup is a valid busmem type (i.e. VMEbus).  Returns 1 if ok
        !          1055:  * busmem type, returns 0 if not busmem type.  This routine
        !          1056:  * make checks and panic's if an illegal busmem type request is detected.
        !          1057:  */
        !          1058: buscheck(pte, npf)
        !          1059:        register struct pte *pte;
        !          1060:        register int npf;
        !          1061: {
        !          1062:        register int i, pf;
        !          1063:        register int pt = *(int *)pte & PGT_MASK;
        !          1064: 
        !          1065:        if (pt == PGT_VME_D16 || pt == PGT_VME_D32) {
        !          1066:                pf = pte->pg_pfnum;
        !          1067:                if (pf < btoc(DVMASIZE))
        !          1068:                        panic("buscheck: busmem in DVMA range");
        !          1069:                for (i = 0; i < npf; i++, pte++, pf++) {
        !          1070:                        if ((*(int *)pte & PGT_MASK) != pt ||
        !          1071:                            pte->pg_pfnum != pf)
        !          1072:                                panic("buscheck: request not contiguous");
        !          1073:                }
        !          1074:                return (1);
        !          1075:        }
        !          1076:        return (0);
        !          1077: }
        !          1078: 
        !          1079: /* 
        !          1080:  * Compute the address of an I/O device within standard address
        !          1081:  * ranges and return the result.  This is used by DKIOCINFO
        !          1082:  * ioctl to get the best guess possible for the actual address
        !          1083:  * set on the card.
        !          1084:  */
        !          1085: getdevaddr(addr)
        !          1086:        caddr_t addr;
        !          1087: {
        !          1088:        int off = (int)addr & PGOFSET;
        !          1089:        int pte = getkpgmap(addr);
        !          1090:        int physaddr = ((pte & PG_PFNUM) & ~PGT_MASK) * NBPG;
        !          1091: 
        !          1092:        switch (pte & PGT_MASK) {
        !          1093:        case PGT_VME_D16:
        !          1094:        case PGT_VME_D32:
        !          1095:                if (physaddr > VME16_BASE) {
        !          1096:                        /* 16 bit VMEbus address */
        !          1097:                        physaddr -= VME16_BASE;
        !          1098:                } else if (physaddr > VME24_BASE) {
        !          1099:                        /* 24 bit VMEbus address */
        !          1100:                        physaddr -= VME24_BASE;
        !          1101:                }
        !          1102:                /*
        !          1103:                 * else 32 bit VMEbus address,
        !          1104:                 * physaddr doesn't require adjustments
        !          1105:                 */
        !          1106:                break;
        !          1107: 
        !          1108:        case PGT_OBMEM:
        !          1109:        case PGT_OBIO:
        !          1110:                /* physaddr doesn't require adjustments */
        !          1111:                break;
        !          1112:        }
        !          1113: 
        !          1114:        return (physaddr + off);
        !          1115: }
        !          1116: 
        !          1117: static int (*mon_nmi)();               /* monitor's level 7 nmi routine */
        !          1118: extern int level7();                   /* Unix's level 7 nmi routine */
        !          1119: 
        !          1120: stopnmi()
        !          1121: {
        !          1122:        struct scb *vbr, *getvbr();
        !          1123: 
        !          1124:        vbr = getvbr();
        !          1125:        if (vbr->scb_autovec[7 - 1] != level7) {
        !          1126: #ifndef GPROF
        !          1127:                set_clk_mode(0, IR_ENA_CLK7);   /* disable level 7 clk intr */
        !          1128: #endif !GPROF
        !          1129:                mon_nmi = vbr->scb_autovec[7 - 1];      /* save mon vec */
        !          1130:                vbr->scb_autovec[7 - 1] = level7;       /* install Unix vec */
        !          1131:        }
        !          1132: }
        !          1133: 
        !          1134: startnmi()
        !          1135: {
        !          1136:        struct scb *getvbr();
        !          1137: 
        !          1138:        if (mon_nmi) {
        !          1139:                getvbr()->scb_autovec[7 - 1] = mon_nmi; /* install mon vec */
        !          1140: #ifndef GPROF
        !          1141:                set_clk_mode(IR_ENA_CLK7, 0);   /* enable level 7 clk intr */
        !          1142: #endif !GPROF
        !          1143:        }
        !          1144: }
        !          1145: 
        !          1146: /*
        !          1147:  * Handler for monitor vector cmd -
        !          1148:  * For now we just implement the old "g0" and "g4"
        !          1149:  * commands and a printf hack.
        !          1150:  */
        !          1151: void
        !          1152: v_handler(addr, str)
        !          1153:        int addr;
        !          1154:        char *str;
        !          1155: {
        !          1156: 
        !          1157:        switch (*str) {
        !          1158:        case '\0':
        !          1159:                /*
        !          1160:                 * No (non-hex) letter was specified on
        !          1161:                 * command line, use only the number given
        !          1162:                 */
        !          1163:                switch (addr) {
        !          1164:                case 0:         /* old g0 */
        !          1165:                case 0xd:       /* 'd'ump short hand */
        !          1166:                        panic("zero");
        !          1167:                        /*NOTREACHED*/
        !          1168:                
        !          1169:                case 4:         /* old g4 */
        !          1170:                        tracedump();
        !          1171:                        break;
        !          1172: 
        !          1173:                default:
        !          1174:                        goto err;
        !          1175:                }
        !          1176:                break;
        !          1177: 
        !          1178:        case 'p':               /* 'p'rint string command */
        !          1179:        case 'P':
        !          1180:                (*romp->v_printf)("%s\n", (char *)addr);
        !          1181:                break;
        !          1182: 
        !          1183:        case '%':               /* p'%'int anything a la printf */
        !          1184:                (*romp->v_printf)(str, addr);
        !          1185:                (*romp->v_printf)("\n");
        !          1186:                break;
        !          1187: 
        !          1188:        case 't':               /* 't'race kernel stack */
        !          1189:        case 'T':
        !          1190:                tracedump();
        !          1191:                break;
        !          1192: 
        !          1193:        case 'u':               /* d'u'mp hack ('d' look like hex) */
        !          1194:        case 'U':
        !          1195:                if (addr == 0xd) {
        !          1196:                        panic("zero");
        !          1197:                } else
        !          1198:                        goto err;
        !          1199:                break;
        !          1200: 
        !          1201:        default:
        !          1202:        err:
        !          1203:                (*romp->v_printf)("Don't understand 0x%x '%s'\n", addr, str);
        !          1204:        }
        !          1205: }
        !          1206: 
        !          1207: /*
        !          1208:  * Handle parity/ECC memory errors.  XXX - use something like
        !          1209:  * vax to only look for soft ecc errors periodically?
        !          1210:  */
        !          1211: memerr()
        !          1212: {
        !          1213:        u_char per, eer;
        !          1214:        char *mess = 0;
        !          1215:        int c;
        !          1216:        long pme;
        !          1217: 
        !          1218:        eer = per = MEMREG->mr_er;
        !          1219: #ifdef SUN3_260
        !          1220:        if (cpu == CPU_SUN3_260 && (eer & EER_ERR) == EER_CE) {
        !          1221:                softecc();
        !          1222:                MEMREG->mr_dvma = 1;    /* clear latching */
        !          1223:                return;
        !          1224:        } 
        !          1225: #endif SUN3_260
        !          1226: 
        !          1227:        /*
        !          1228:         * Since we are going down in flames, disable further
        !          1229:         * memory error interrupts to prevent confusion.
        !          1230:         */
        !          1231:        MEMREG->mr_er &= ~ER_INTENA;
        !          1232: 
        !          1233: #if defined(SUN3_160) || defined(SUN3_50)
        !          1234:        if ((cpu == CPU_SUN3_160 || cpu == CPU_SUN3_50) &&
        !          1235:            (per & PER_ERR) != 0) {
        !          1236:                printf("Parity Error Register %b\n", per, PARERR_BITS);
        !          1237:                mess = "parity error";
        !          1238:        }
        !          1239: #endif defined(SUN3_160) || defined(SUN3_50)
        !          1240: 
        !          1241: #ifdef SUN3_260
        !          1242:        if ((cpu == CPU_SUN3_260) && (eer & EER_ERR) != 0) {
        !          1243:                printf("ECC Error Register %b\n", eer, ECCERR_BITS);
        !          1244:                mess = "uncorrectable ECC error";
        !          1245:        }
        !          1246: #endif SUN3_260
        !          1247: 
        !          1248:        if (!mess) {
        !          1249:                printf("Memory Error Register %b %b\n",
        !          1250:                    per, PARERR_BITS, eer, ECCERR_BITS);
        !          1251:                mess = "unknown memory error";
        !          1252:        }
        !          1253: 
        !          1254:        printf("DVMA = %x, context = %x, virtual address = %x\n",
        !          1255:                MEMREG->mr_dvma, MEMREG->mr_ctx, MEMREG->mr_vaddr);
        !          1256: 
        !          1257:        c = getcontext();
        !          1258:        setcontext((int)MEMREG->mr_ctx);
        !          1259:        pme = getpgmap((caddr_t)MEMREG->mr_vaddr);
        !          1260:        printf("pme = %x, physical address = %x\n", pme,
        !          1261:            ptob(((struct pte *)&pme)->pg_pfnum) + (MEMREG->mr_vaddr&PGOFSET));
        !          1262:        setcontext(c);
        !          1263: 
        !          1264:        /*
        !          1265:         * Clear the latching by writing to the top
        !          1266:         * nibble of the memory address register
        !          1267:         */
        !          1268:        MEMREG->mr_dvma = 1;
        !          1269: 
        !          1270:        panic(mess);
        !          1271:        /*NOTREACHED*/
        !          1272: }
        !          1273: 
        !          1274: #ifdef SUN3_260
        !          1275: int prtsoftecc = 1;
        !          1276: 
        !          1277: /*
        !          1278:  * Probe memory cards to find which one(s) had ecc error(s).
        !          1279:  * If prtsoftecc is non-zero, log messages regarding the failing
        !          1280:  * syndrome.  Then clear the latching on the memory card.
        !          1281:  */
        !          1282: softecc()
        !          1283: {
        !          1284:        register struct eccreg **ecc_nxt, *ecc;
        !          1285: 
        !          1286:        for (ecc_nxt = ecc_alive; *ecc_nxt != (struct eccreg *)0; ecc_nxt++) {
        !          1287:                ecc = *ecc_nxt;
        !          1288:                if (ecc->syndrome.sy_ce) {
        !          1289:                        if (prtsoftecc) {
        !          1290:                                printf("mem%d: soft ecc addr %x+%x=%x syn %b\n",
        !          1291:                                    ecc - ECCREG,
        !          1292:                                    (ecc->eccena.ena_addr << 22),
        !          1293:                                    (ecc->syndrome.sy_addr << 3),
        !          1294:                                    (ecc->eccena.ena_addr << 22) +
        !          1295:                                      (ecc->syndrome.sy_addr << 3),
        !          1296:                                    ecc->syndrome.sy_synd, SYNDERR_BITS);
        !          1297:                        }
        !          1298:                        ecc->syndrome.sy_ce = 1;        /* clear latching */
        !          1299:                }
        !          1300:        }
        !          1301: }
        !          1302: #endif SUN3_260

unix.superglobalmegacorp.com

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