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

1.1     ! root        1: #ifndef lint
        !             2: static char sccsid[] = "@(#)autoconf.c 1.1 86/02/03 Copyr 1985 Sun Micro";
        !             3: #endif
        !             4: 
        !             5: /*
        !             6:  * Copyright (c) 1985 by Sun Microsystems, Inc.
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * Setup the system to run on the current machine.
        !            11:  *
        !            12:  * Configure() is called at boot time and initializes the Mainbus
        !            13:  * device tables and the memory controller monitoring.  Available
        !            14:  * devices are determined (from possibilities mentioned in ioconf.c),
        !            15:  * and the drivers are initialized.
        !            16:  */
        !            17: 
        !            18: #include "../h/param.h"
        !            19: #include "../h/systm.h"
        !            20: #include "../h/map.h"
        !            21: #include "../h/buf.h"
        !            22: #include "../h/dk.h"
        !            23: #include "../h/vm.h"
        !            24: #include "../h/conf.h"
        !            25: #include "../h/file.h"
        !            26: #include "../h/dir.h"
        !            27: #include "../h/user.h"
        !            28: #include "../h/proc.h"
        !            29: 
        !            30: #include "../machine/pte.h"
        !            31: #include "../machine/mmu.h"
        !            32: #include "../machine/cpu.h"
        !            33: #include "../machine/scb.h"
        !            34: #include "../machine/mbvar.h"
        !            35: #include "../machine/zsvar.h"
        !            36: #include "../machine/sunromvec.h"
        !            37: #include "../machine/idprom.h"
        !            38: 
        !            39: /*
        !            40:  * The following several variables are related to
        !            41:  * the configuration process, and are used in initializing
        !            42:  * the machine.
        !            43:  */
        !            44: int    dkn;            /* number of iostat dk numbers assigned so far */
        !            45: 
        !            46: /*
        !            47:  * This allocates the space for the per-Mainbus information.
        !            48:  */
        !            49: struct mb_hd mb_hd;
        !            50: 
        !            51: /*
        !            52:  * Determine mass storage and memory configuration for a machine.
        !            53:  * Get cpu type, and then switch out to machine specific procedures
        !            54:  * which will probe adaptors to see what is out there.
        !            55:  */
        !            56: configure()
        !            57: {
        !            58: 
        !            59:        idprom();
        !            60:        /*
        !            61:         * Configure the Mainbus.
        !            62:         */
        !            63:        mbconfig();
        !            64: #ifdef GENERIC
        !            65:        setconf();
        !            66: #endif
        !            67: }
        !            68: 
        !            69: static int     (*vec_save)();  /* used to save original vector value */
        !            70: 
        !            71: /*
        !            72:  * Find devices on the Mainbus.
        !            73:  * Uses per-driver routine to probe for existence of the device
        !            74:  * and then fills in the tables, with help from a per-driver
        !            75:  * slave initialization routine.
        !            76:  */
        !            77: mbconfig()
        !            78: {
        !            79:        register struct mb_device *md;
        !            80:        register struct mb_ctlr *mc;
        !            81:        u_short *reg;
        !            82:        struct mb_driver *mdr;
        !            83:        u_short *doprobe();
        !            84: 
        !            85:        vec_save = scb.scb_user[0];     /* save default trap routine */
        !            86: 
        !            87:        /*
        !            88:         * Grab some memory to record the Mainbus address space in use,
        !            89:         * so we can be sure not to place two devices at the same address.
        !            90:         * If we run out of kernelmap space, we could reuse the mapped
        !            91:         * pages if we did all probes first to determine the target
        !            92:         * locations and sizes, and then remucked with the kernelmap to
        !            93:         * share spaces, then did all the attaches.
        !            94:         *
        !            95:         * We could use just 1/8 of this (we only want a 1 bit flag) but
        !            96:         * we are going to give it back anyway, and that would make the
        !            97:         * code here bigger (which we can't give back), so ...
        !            98:         */
        !            99: 
        !           100:        /*
        !           101:         * Check each Mainbus mass storage controller.
        !           102:         * See if it is really there, and if it is record it and
        !           103:         * then go looking for slaves.
        !           104:         */
        !           105:        for (mc = mbcinit; mdr = mc->mc_driver; mc++) {
        !           106:                if ((reg = doprobe((u_long)mc->mc_addr, (u_long)mc->mc_space,
        !           107:                    mdr, mdr->mdr_cname, mc->mc_ctlr, mc->mc_intpri,
        !           108:                    mc->mc_intr)) == 0)
        !           109:                        continue;
        !           110:                mc->mc_alive = 1;
        !           111:                mc->mc_mh = &mb_hd;
        !           112:                mc->mc_addr = (caddr_t)reg;
        !           113:                if (mdr->mdr_cinfo)
        !           114:                        mdr->mdr_cinfo[mc->mc_ctlr] = mc;
        !           115:                for (md = mbdinit; md->md_driver; md++) {
        !           116:                        if (md->md_driver != mdr || md->md_alive ||
        !           117:                            md->md_ctlr != mc->mc_ctlr && md->md_ctlr != '?')
        !           118:                                continue;
        !           119:                        if ((*mdr->mdr_slave)(md, reg)) {
        !           120:                                md->md_alive = 1;
        !           121:                                md->md_ctlr = mc->mc_ctlr;
        !           122:                                md->md_hd = &mb_hd;
        !           123:                                md->md_addr = (caddr_t)reg;
        !           124:                                if (md->md_dk && dkn < DK_NDRIVE)
        !           125:                                        md->md_dk = dkn++;
        !           126:                                else
        !           127:                                        md->md_dk = -1;
        !           128:                                md->md_mc = mc;
        !           129:                                /* md_type comes from driver */
        !           130:                                if (mdr->mdr_dinfo)
        !           131:                                        mdr->mdr_dinfo[md->md_unit] = md;
        !           132:                                printf("%s%d at %s%d slave %d\n",
        !           133:                                    mdr->mdr_dname, md->md_unit,
        !           134:                                    mdr->mdr_cname, mc->mc_ctlr, md->md_slave);
        !           135:                                if (mdr->mdr_attach)
        !           136:                                        (*mdr->mdr_attach)(md);
        !           137:                        }
        !           138:                }
        !           139:        }
        !           140: 
        !           141:        /*
        !           142:         * Now look for non-mass storage peripherals.
        !           143:         */
        !           144:        for (md = mbdinit; mdr = md->md_driver; md++) {
        !           145:                if (md->md_alive || md->md_slave != -1)
        !           146:                        continue;
        !           147:                if ((reg = doprobe((u_long)md->md_addr, (u_long)md->md_space,
        !           148:                    mdr, mdr->mdr_dname, md->md_unit, md->md_intpri,
        !           149:                    md->md_intr)) == 0)
        !           150:                        continue;
        !           151:                md->md_hd = &mb_hd;
        !           152:                md->md_alive = 1;
        !           153:                md->md_addr = (caddr_t)reg;
        !           154:                md->md_dk = -1;
        !           155:                /* md_type comes from driver */
        !           156:                if (mdr->mdr_dinfo)
        !           157:                        mdr->mdr_dinfo[md->md_unit] = md;
        !           158:                if (mdr->mdr_attach)
        !           159:                        (*mdr->mdr_attach)(md);
        !           160:        }
        !           161: }
        !           162: 
        !           163: /*
        !           164:  * Make non-zero if want to be set up to handle
        !           165:  * both vectored and auto-vectored interrupts
        !           166:  * for the same device at the same time.
        !           167:  */
        !           168: int paranoid = 0;
        !           169: 
        !           170: /*
        !           171:  * Probe for a device or controller at the specified addr.
        !           172:  * The space argument give the page type and cpu type for the device.
        !           173:  */
        !           174: u_short *
        !           175: doprobe(addr, space, mdr, dname, unit, br, vp)
        !           176:        register u_long addr, space;
        !           177:        register struct mb_driver *mdr;
        !           178:        char *dname;
        !           179:        int unit, br;
        !           180:        register struct vec *vp;
        !           181: {
        !           182:        register u_short *reg = NULL;
        !           183:        char *name;
        !           184:        long a = 0;
        !           185:        int i, extent, machine;
        !           186:        u_int pageval;
        !           187: 
        !           188: #define SP_MACHMASK    0xFFFF0000      /* space mask for machine type */
        !           189: #define        MAKE_MACH(m)    ((m)<<16)
        !           190: #define        SP_MACH_ALL     MAKE_MACH(0)
        !           191: 
        !           192: #define SP_BUSMASK     0x0000FFFF      /* mask for bus type */
        !           193: #define SP_VIRTUAL     0x00000001
        !           194: #define SP_OBMEM       0x00000002
        !           195: #define SP_OBIO                0x00000004
        !           196: #define        SP_VME16D16     0x00000100
        !           197: #define        SP_VME24D16     0x00000200
        !           198: #define        SP_VME32D16     0x00000400
        !           199: #define        SP_VME16D32     0x00001000
        !           200: #define        SP_VME24D32     0x00002000
        !           201: #define        SP_VME32D32     0x00004000
        !           202: 
        !           203:        machine = space & SP_MACHMASK;
        !           204: 
        !           205:        if (machine != SP_MACH_ALL && machine != MAKE_MACH(cpu & CPU_MACH))
        !           206:                return(0);
        !           207: 
        !           208:        switch (space & SP_BUSMASK) {
        !           209: 
        !           210:        case SP_VIRTUAL:
        !           211:                name = "virtual";
        !           212:                reg = (u_short *)addr;
        !           213:                break;
        !           214: 
        !           215:        case SP_OBMEM:
        !           216:                name = "obmem";
        !           217:                pageval = PGT_OBMEM | btop(addr);
        !           218:                break;
        !           219: 
        !           220:        case SP_OBIO:
        !           221:                name = "obio";
        !           222:                pageval = PGT_OBIO | btop(addr);
        !           223:                break;
        !           224: 
        !           225:        case SP_VME16D16:
        !           226:                name = "vme16d16";
        !           227:                pageval = PGT_VME_D16 | btop(VME16_BASE | (addr & VME16_MASK));
        !           228:                break;
        !           229: 
        !           230:        case SP_VME24D16:
        !           231:                name = "vme24d16";
        !           232:                pageval = PGT_VME_D16 | btop(VME24_BASE | (addr & VME24_MASK));
        !           233:                break;
        !           234: 
        !           235:        case SP_VME32D16:
        !           236:                name = "vme32d16";
        !           237:                pageval = PGT_VME_D16 | btop(addr);
        !           238:                break;
        !           239: 
        !           240:        case SP_VME16D32:
        !           241:                name = "vme16d32";
        !           242:                pageval = PGT_VME_D32 | btop(VME16_BASE | (addr & VME16_MASK));
        !           243:                break;
        !           244: 
        !           245:        case SP_VME24D32:
        !           246:                name = "vme24d32";
        !           247:                pageval = PGT_VME_D32 | btop(VME24_BASE | (addr & VME24_MASK));
        !           248:                break;
        !           249: 
        !           250:        case SP_VME32D32:
        !           251:                name = "vme32d32";
        !           252:                pageval = PGT_VME_D32 | btop(addr);
        !           253:                break;
        !           254: 
        !           255:        default:
        !           256:                return (0);
        !           257:        }
        !           258: 
        !           259:        if (reg == NULL) {
        !           260:                int offset = addr & PGOFSET;
        !           261: 
        !           262:                extent = btoc(mdr->mdr_size + offset);
        !           263:                if (extent == 0)
        !           264:                        extent = 1;
        !           265:                if ((a = rmalloc(kernelmap, (long)extent)) == 0)
        !           266:                        panic("out of kernelmap for devices");
        !           267:                reg = (u_short *)((int)kmxtob(a) | offset);
        !           268:                mapin(&Usrptmap[a], btop(reg), pageval, extent, PG_V | PG_KW);
        !           269:        }
        !           270: 
        !           271:        i = (*mdr->mdr_probe)(reg, unit);
        !           272:        if (i == 0) {
        !           273:                if (a)
        !           274:                        rmfree(kernelmap, (long)extent, a);
        !           275:                return (0);
        !           276:        }
        !           277:        printf("%s%d at %s %x ", dname, unit, name, addr);
        !           278:        if (br < 0 || br >= 7) {
        !           279:                printf("bad priority (%d)\n", br);
        !           280:                if (a)
        !           281:                        rmfree(kernelmap, (long)extent, a);
        !           282:                return (0);
        !           283:        }
        !           284: 
        !           285:        /*
        !           286:         * If br is 0, then no priority was specified in the
        !           287:         * config file and the device cannot use interrupts.
        !           288:         */
        !           289:        if (br != 0) {
        !           290:                /*
        !           291:                 * If we are paranoid or vectored interrupts are not
        !           292:                 * going to be used then set up for polling interrupts.
        !           293:                 */
        !           294:                if (paranoid || vp == (struct vec *)0) {
        !           295:                        printf("pri %d ", br);
        !           296:                        addintr(br, mdr);
        !           297:                }
        !           298: 
        !           299:                /*
        !           300:                 * now set up vectored interrupts if conditions are right
        !           301:                 */
        !           302:                if (vp != (struct vec *)0) {
        !           303:                        for (; vp->v_func; vp++) {
        !           304:                                printf("vec 0x%x ", vp->v_vec);
        !           305:                                if (vp->v_vec < VEC_MIN || vp->v_vec > VEC_MAX)
        !           306:                                        panic("bad vector");
        !           307:                                else if (scb.scb_user[vp->v_vec - VEC_MIN] !=
        !           308:                                    vec_save)
        !           309:                                        panic("duplicate vector");
        !           310:                                else
        !           311:                                        scb.scb_user[vp->v_vec - VEC_MIN] =
        !           312:                                            vp->v_func;
        !           313:                        }
        !           314:                }
        !           315:        }
        !           316:        printf("\n");
        !           317:        return (reg);
        !           318: }
        !           319: 
        !           320: #define SPURIOUS       0x80000000      /* recognized in locore.s */
        !           321: 
        !           322: int level2_spurious, level3_spurious, level4_spurious, level6_spurious;
        !           323: 
        !           324: not_serviced2()
        !           325: {
        !           326: 
        !           327:        call_default_intr();
        !           328:        if ((level2_spurious++ % 100) == 1)
        !           329:                printf("iobus level 2 interrupt not serviced\n");
        !           330:        return (SPURIOUS);
        !           331: }
        !           332: 
        !           333: not_serviced3()
        !           334: {
        !           335: 
        !           336:        call_default_intr();
        !           337:        if ((level3_spurious++ % 100) == 1)
        !           338:                printf("iobus level 3 interrupt not serviced\n");
        !           339:        return (SPURIOUS);
        !           340: }
        !           341: 
        !           342: not_serviced4()
        !           343: {
        !           344: 
        !           345:        call_default_intr();
        !           346:        if ((level4_spurious++ % 100) == 1)
        !           347:                printf("iobus level 4 interrupt not serviced\n");
        !           348:        return (SPURIOUS);
        !           349: }
        !           350: 
        !           351: not_serviced6()
        !           352: {
        !           353: 
        !           354:        call_default_intr();
        !           355:        if ((level6_spurious++ % 100) == 1)
        !           356:                printf("iobus level 6 interrupt not serviced\n");
        !           357:        return (SPURIOUS);
        !           358: }
        !           359: 
        !           360: typedef        int (*func)();
        !           361: 
        !           362: #define NVECT 10
        !           363: 
        !           364: /*
        !           365:  * These vectors are used in locore.s to jump to device interrupt routines.
        !           366:  */
        !           367: func   level2_vector[NVECT] = {not_serviced2};
        !           368: func   level3_vector[NVECT] = {not_serviced3};
        !           369: func   level4_vector[NVECT] = {not_serviced4};
        !           370: func   level6_vector[NVECT] = {not_serviced6};
        !           371: 
        !           372: func   *vector[7] = {NULL, NULL, level2_vector, level3_vector,
        !           373:        level4_vector, NULL, level6_vector};
        !           374: 
        !           375: /*
        !           376:  * Arrange for a driver to be called when a particular 
        !           377:  * auto-vectored interrupt occurs.
        !           378:  * NOTE: every device sharing a driver must be on the 
        !           379:  * same interrupt level for polling interrupts because
        !           380:  * there is only one entry made per driver.
        !           381:  */
        !           382: addintr(lvl, mdr)
        !           383:        struct mb_driver *mdr;
        !           384: {
        !           385:        register func f;
        !           386:        register func *fp;
        !           387:        register int i;
        !           388: 
        !           389:        switch (lvl) {
        !           390:        case 1:
        !           391:                return;         /* bogus - these devices don't interrupt */
        !           392:        case 2:
        !           393:                fp = level2_vector;
        !           394:                break;
        !           395:        case 3:
        !           396:                fp = level3_vector;
        !           397:                break;
        !           398:        case 4:
        !           399:                fp = level4_vector;
        !           400:                break;
        !           401:        case 5:
        !           402:                panic("addintr called with level 5");
        !           403:                /* NOTREACHED */
        !           404:        case 6:
        !           405:                fp = level6_vector;
        !           406:                break;
        !           407:        default:
        !           408:                panic("addintr: unknown level");
        !           409:                /* NOTREACHED */
        !           410:        }
        !           411:        if ((f = mdr->mdr_intr) == NULL)
        !           412:                return;
        !           413:        for (i = 0; i < NVECT; i++) {
        !           414:                if (*fp == NULL)        /* end of list found */
        !           415:                        break;
        !           416:                if (*fp == f)           /* already in list */
        !           417:                        return;
        !           418:                fp++;
        !           419:        }
        !           420:        if (i >= NVECT)
        !           421:                panic("addintr: too many devices");
        !           422:        fp[0] = fp[-1];         /* move not_serviced to end */
        !           423:        fp[-1] = f;             /* add f to list */
        !           424: }
        !           425: 
        !           426: /*
        !           427:  * This is for crazy devices that don't know when they interrupt.
        !           428:  * We just call them at the end after all the sane devices have decided
        !           429:  * the interrupt is not their fault.
        !           430:  */
        !           431: func   default_intrs[NVECT];
        !           432: 
        !           433: add_default_intr(f)
        !           434:        func f;
        !           435: {
        !           436:        register int i;
        !           437:        register func *fp;
        !           438: 
        !           439:        fp = default_intrs;
        !           440:        for (i = 0; i < NVECT; i++) {
        !           441:                if (*fp == NULL)        /* end of list found */
        !           442:                        break;
        !           443:                if (*fp == f)           /* already in list */
        !           444:                        return;
        !           445:                fp++;
        !           446:        }
        !           447:        if (i >= NVECT)
        !           448:                panic("add_default_intr: too many devices");
        !           449:        *fp = f;                /* add f to list */
        !           450: }
        !           451: 
        !           452: call_default_intr()
        !           453: {
        !           454:        register func *fp;
        !           455: 
        !           456:        for (fp = default_intrs; *fp; fp++)
        !           457:                (*fp)();
        !           458: }
        !           459: 
        !           460: /*
        !           461:  * Some things, like cputype, are contained in the idprom, but are
        !           462:  * needed and obtained earlier; hence they are not set (again) here.
        !           463:  */
        !           464: idprom()
        !           465: {
        !           466:        register u_char *cp, val = 0;
        !           467:        register int i;
        !           468:        struct idprom id;
        !           469: 
        !           470:        getidprom((char *)&id);
        !           471:        cp = (u_char *)&id;
        !           472:        for (i = 0; i < 16; i++)
        !           473:                val ^= *cp++;
        !           474:        if (val != 0)
        !           475:                printf("WARNING: ID prom checksum error\n");
        !           476:        if (id.id_format == 1) {
        !           477:                localetheraddr(id.id_ether, NULL);
        !           478:        } else
        !           479:                printf("INVALID FORMAT CODE IN ID PROM\n");
        !           480: }
        !           481: 
        !           482: int cpudelay = 3;              /* default to a medium range value here */
        !           483: 
        !           484: /*
        !           485:  * We set the cpu type and associated variables.  Should there get to
        !           486:  * be too many variables, they should be collected together in a
        !           487:  * structure and indexed by cpu type.
        !           488:  */
        !           489: setcputype()
        !           490: {
        !           491:        struct idprom id;
        !           492: 
        !           493:        cpu = -1;
        !           494:        getidprom((char *)&id);
        !           495:        if (id.id_format == 1) {
        !           496:                switch (id.id_machine) {
        !           497:                case CPU_SUN3_160:
        !           498:                case CPU_SUN3_50:
        !           499:                case CPU_SUN3_260:
        !           500:                        cpu = id.id_machine;
        !           501:                        break;
        !           502:                default:
        !           503:                        printf("UNKNOWN MACHINE TYPE 0x%x IN ID PROM\n",
        !           504:                            id.id_machine);
        !           505:                        break;
        !           506:                }
        !           507:        } else
        !           508:                printf("INVALID FORMAT TYPE IN ID PROM\n");
        !           509: 
        !           510:        if (cpu == -1) {
        !           511:                printf("DEFAULTING MACHINE TYPE TO SUN3_160\n");
        !           512:                cpu = CPU_SUN3_160;
        !           513:        }
        !           514: 
        !           515:        /*
        !           516:         * Can't use the last segment for DVMA.
        !           517:         * The last is for on-board Ethernet scratch,
        !           518:         * u area, and miscellanous on-board devices.
        !           519:         * On the Sun-3, we can set dvmasize independent
        !           520:         * of the implementation.
        !           521:         */
        !           522:        dvmasize = btoc(DVMASIZE) - NPAGSEG;
        !           523: 
        !           524:        switch (cpu) {
        !           525:        case CPU_SUN3_160:
        !           526: #ifndef SUN3_160
        !           527:                panic("not configured for SUN3_160");
        !           528: #endif !SUN3_160
        !           529:                cpudelay = 3;
        !           530:                break;
        !           531:        case CPU_SUN3_50:
        !           532: #ifndef SUN3_50
        !           533:                panic("not configured for SUN3_50");
        !           534: #endif !SUN3_50
        !           535:                cpudelay = 3;
        !           536:                break;
        !           537:        case CPU_SUN3_260:
        !           538: #ifndef SUN3_260
        !           539:                panic("not configured for SUN3_260");
        !           540: #endif !SUN3_260
        !           541:                cpudelay = 2;
        !           542:                break;
        !           543:        }
        !           544: }
        !           545: 
        !           546: machineid()
        !           547: {
        !           548:        struct idprom id;
        !           549:        register int x;
        !           550: 
        !           551:        getidprom((char *)&id);
        !           552:        x = id.id_machine << 24;
        !           553:        x += id.id_serial;
        !           554:        return (x);
        !           555: }

unix.superglobalmegacorp.com

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