Annotation of researchv9/sys/sun3/autoconf.c, revision 1.1.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.