[BACK]Return to autoconf.c CVS log [TXT][DIR] Up to [local] / sys / arch / hppa / hppa

Annotation of sys/arch/hppa/hppa/autoconf.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: autoconf.c,v 1.50 2007/06/01 22:40:33 miod Exp $      */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 1998-2003 Michael Shalayeff
        !             5:  * Copyright (c) 1992, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * This software was developed by the Computer Systems Engineering group
        !             9:  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
        !            10:  * contributed to Berkeley.
        !            11:  *
        !            12:  * All advertising materials mentioning features or use of this software
        !            13:  * must display the following acknowledgement:
        !            14:  *     This product includes software developed by the University of
        !            15:  *     California, Lawrence Berkeley Laboratory.
        !            16:  *
        !            17:  * Redistribution and use in source and binary forms, with or without
        !            18:  * modification, are permitted provided that the following conditions
        !            19:  * are met:
        !            20:  * 1. Redistributions of source code must retain the above copyright
        !            21:  *    notice, this list of conditions and the following disclaimer.
        !            22:  * 2. Redistributions in binary form must reproduce the above copyright
        !            23:  *    notice, this list of conditions and the following disclaimer in the
        !            24:  *    documentation and/or other materials provided with the distribution.
        !            25:  * 3. Neither the name of the University nor the names of its contributors
        !            26:  *    may be used to endorse or promote products derived from this software
        !            27:  *    without specific prior written permission.
        !            28:  *
        !            29:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            30:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            31:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            32:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            33:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            34:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            35:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            36:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            37:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            38:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            39:  * SUCH DAMAGE.
        !            40:  *
        !            41:  *     @(#)autoconf.c  8.4 (Berkeley) 10/1/93
        !            42:  */
        !            43:
        !            44: #include "pci.h"
        !            45:
        !            46: #include <sys/param.h>
        !            47: #include <sys/systm.h>
        !            48: #include <sys/buf.h>
        !            49: #include <sys/disklabel.h>
        !            50: #include <sys/conf.h>
        !            51: #include <sys/reboot.h>
        !            52: #include <sys/device.h>
        !            53: #include <sys/timeout.h>
        !            54:
        !            55: #include <uvm/uvm_extern.h>
        !            56:
        !            57: #include <machine/iomod.h>
        !            58: #include <machine/autoconf.h>
        !            59:
        !            60: #include <dev/cons.h>
        !            61:
        !            62: #include <hppa/dev/cpudevs.h>
        !            63:
        !            64: #if NPCI > 0
        !            65: #include <dev/pci/pcivar.h>
        !            66: #include <dev/pci/pcireg.h>
        !            67: #endif
        !            68:
        !            69: /* device we booted from */
        !            70: struct device *bootdv;
        !            71: void   dumpconf(void);
        !            72:
        !            73: void (*cold_hook)(int); /* see below */
        !            74:
        !            75: /*
        !            76:  * LED blinking thing
        !            77:  */
        !            78: #ifdef USELEDS
        !            79: #include <sys/dkstat.h>
        !            80: #include <sys/kernel.h>
        !            81:
        !            82: struct timeout heartbeat_tmo;
        !            83: void heartbeat(void *);
        !            84: #endif
        !            85:
        !            86: #include "cd.h"
        !            87: #include "sd.h"
        !            88: #include "st.h"
        !            89: #if NCD > 0 || NSD > 0 || NST > 0
        !            90: #include <scsi/scsi_all.h>
        !            91: #include <scsi/scsiconf.h>
        !            92: #endif
        !            93:
        !            94: #ifdef USELEDS
        !            95: /*
        !            96:  * turn the heartbeat alive.
        !            97:  * right thing would be to pass counter to each subsequent timeout
        !            98:  * as an argument to heartbeat() incrementing every turn,
        !            99:  * i.e. avoiding the static hbcnt, but doing timeout_set() on each
        !           100:  * timeout_add() sounds ugly, guts of struct timeout looks ugly
        !           101:  * to ponder in even more.
        !           102:  */
        !           103: void
        !           104: heartbeat(v)
        !           105:        void *v;
        !           106: {
        !           107:        static u_int hbcnt = 0, ocp_total, ocp_idle;
        !           108:        int toggle, cp_mask, cp_total, cp_idle;
        !           109:
        !           110:        timeout_add(&heartbeat_tmo, hz / 16);
        !           111:
        !           112:        cp_idle = cp_time[CP_IDLE];
        !           113:        cp_total = cp_time[CP_USER] + cp_time[CP_NICE] + cp_time[CP_SYS] +
        !           114:            cp_time[CP_INTR] + cp_time[CP_IDLE];
        !           115:        if (cp_total == ocp_total)
        !           116:                cp_total = ocp_total + 1;
        !           117:        if (cp_idle == ocp_idle)
        !           118:                cp_idle = ocp_idle + 1;
        !           119:        cp_mask = 0xf0 >> (cp_idle - ocp_idle) * 4 / (cp_total - ocp_total);
        !           120:        cp_mask &= 0xf0;
        !           121:        ocp_total = cp_total;
        !           122:        ocp_idle = cp_idle;
        !           123:        /*
        !           124:         * do this:
        !           125:         *
        !           126:         *   |~| |~|
        !           127:         *  _| |_| |_,_,_,_
        !           128:         *   0 1 2 3 4 6 7
        !           129:         */
        !           130:        toggle = 0;
        !           131:        if (hbcnt++ < 8 && hbcnt & 1)
        !           132:                toggle = PALED_HEARTBEAT;
        !           133:        hbcnt &= 15;
        !           134:        ledctl(cp_mask,
        !           135:            (~cp_mask & 0xf0) | PALED_NETRCV | PALED_NETSND | PALED_DISK,
        !           136:            toggle);
        !           137: }
        !           138: #endif
        !           139:
        !           140: /*
        !           141:  * This is called by configure to set dumplo and dumpsize.
        !           142:  * Dumps always skip the first CLBYTES of disk space
        !           143:  * in case there might be a disk label stored there.
        !           144:  * If there is extra space, put dump at the end to
        !           145:  * reduce the chance that swapping trashes it.
        !           146:  */
        !           147: void
        !           148: dumpconf(void)
        !           149: {
        !           150:        extern int dumpsize;
        !           151:        int nblks, dumpblks;    /* size of dump area */
        !           152:
        !           153:        if (dumpdev == NODEV ||
        !           154:            (nblks = (bdevsw[major(dumpdev)].d_psize)(dumpdev)) == 0)
        !           155:                return;
        !           156:        if (nblks <= ctod(1))
        !           157:                return;
        !           158:
        !           159:        dumpblks = cpu_dumpsize();
        !           160:        if (dumpblks < 0)
        !           161:                return;
        !           162:        dumpblks += ctod(physmem);
        !           163:
        !           164:        /* If dump won't fit (incl. room for possible label), punt. */
        !           165:        if (dumpblks > (nblks - ctod(1)))
        !           166:                return;
        !           167:
        !           168:        /* Put dump at end of partition */
        !           169:        dumplo = nblks - dumpblks;
        !           170:
        !           171:        /* dumpsize is in page units, and doesn't include headers. */
        !           172:        dumpsize = physmem;
        !           173: }
        !           174:
        !           175: void
        !           176: print_devpath(const char *label, struct pz_device *pz)
        !           177: {
        !           178:        int i;
        !           179:
        !           180:        printf("%s: ", label);
        !           181:
        !           182:        for (i = 0; i < 6; i++)
        !           183:                if (pz->pz_bc[i] >= 0)
        !           184:                        printf("%d/", pz->pz_bc[i]);
        !           185:
        !           186:        printf("%d.%x", pz->pz_mod, pz->pz_layers[0]);
        !           187:        for (i = 1; i < 6 && pz->pz_layers[i]; i++)
        !           188:                printf(".%x", pz->pz_layers[i]);
        !           189:
        !           190:        printf(" class=%d flags=%b hpa=%p spa=%p io=%p\n", pz->pz_class,
        !           191:            pz->pz_flags, PZF_BITS, pz->pz_hpa, pz->pz_spa, pz->pz_iodc_io);
        !           192: }
        !           193:
        !           194: struct pdc_memmap pdc_memmap PDC_ALIGNMENT;
        !           195: struct pdc_sysmap_find pdc_find PDC_ALIGNMENT;
        !           196: struct pdc_sysmap_addrs pdc_addr PDC_ALIGNMENT;
        !           197: struct pdc_iodc_read pdc_iodc_read PDC_ALIGNMENT;
        !           198:
        !           199: void
        !           200: pdc_scanbus(self, ca, maxmod, hpa)
        !           201:        struct device *self;
        !           202:        struct confargs *ca;
        !           203:        int maxmod;
        !           204:        hppa_hpa_t hpa;
        !           205: {
        !           206:        int i;
        !           207:
        !           208:        for (i = maxmod; i--; ) {
        !           209:                struct confargs nca;
        !           210:                int error;
        !           211:
        !           212:                bzero(&nca, sizeof(nca));
        !           213:                nca.ca_iot = ca->ca_iot;
        !           214:                nca.ca_dmatag = ca->ca_dmatag;
        !           215:                nca.ca_dp.dp_bc[0] = ca->ca_dp.dp_bc[1];
        !           216:                nca.ca_dp.dp_bc[1] = ca->ca_dp.dp_bc[2];
        !           217:                nca.ca_dp.dp_bc[2] = ca->ca_dp.dp_bc[3];
        !           218:                nca.ca_dp.dp_bc[3] = ca->ca_dp.dp_bc[4];
        !           219:                nca.ca_dp.dp_bc[4] = ca->ca_dp.dp_bc[5];
        !           220:                nca.ca_dp.dp_bc[5] = ca->ca_dp.dp_mod;
        !           221:                nca.ca_dp.dp_mod = i;
        !           222:                nca.ca_hpamask = ca->ca_hpamask;
        !           223:                nca.ca_naddrs = 0;
        !           224:                nca.ca_hpa = 0;
        !           225:
        !           226:                if (hpa) {
        !           227:                        nca.ca_hpa = hpa + IOMOD_HPASIZE * i;
        !           228:                        nca.ca_dp.dp_mod = i;
        !           229:                } else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_MEMMAP,
        !           230:                    PDC_MEMMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0)
        !           231:                        nca.ca_hpa = pdc_memmap.hpa;
        !           232:                else if ((error = pdc_call((iodcio_t)pdc, 0, PDC_SYSMAP,
        !           233:                    PDC_SYSMAP_HPA, &pdc_memmap, &nca.ca_dp)) == 0) {
        !           234:                        struct device_path path;
        !           235:                        int im, ia;
        !           236:
        !           237:                        nca.ca_hpa = pdc_memmap.hpa;
        !           238:
        !           239:                        for (im = 0; !(error = pdc_call((iodcio_t)pdc, 0,
        !           240:                            PDC_SYSMAP, PDC_SYSMAP_FIND,
        !           241:                            &pdc_find, &path, im)) &&
        !           242:                            pdc_find.hpa != nca.ca_hpa; im++)
        !           243:                                ;
        !           244:
        !           245:                        if (!error)
        !           246:                                nca.ca_hpasz = pdc_find.size << PGSHIFT;
        !           247:
        !           248:                        if (!error && pdc_find.naddrs) {
        !           249:                                nca.ca_naddrs = pdc_find.naddrs;
        !           250:                                if (nca.ca_naddrs > 16) {
        !           251:                                        nca.ca_naddrs = 16;
        !           252:                                        printf("WARNING: too many (%d) addrs\n",
        !           253:                                            pdc_find.naddrs);
        !           254:                                }
        !           255:
        !           256:                                if (autoconf_verbose)
        !           257:                                        printf(">> ADDRS:");
        !           258:
        !           259:                                for (ia = 0; !(error = pdc_call((iodcio_t)pdc,
        !           260:                                    0, PDC_SYSMAP, PDC_SYSMAP_ADDR, &pdc_addr,
        !           261:                                    im, ia)) && ia < nca.ca_naddrs; ia++) {
        !           262:                                        nca.ca_addrs[ia].addr = pdc_addr.hpa;
        !           263:                                        nca.ca_addrs[ia].size =
        !           264:                                            pdc_addr.size << PGSHIFT;
        !           265:
        !           266:                                        if (autoconf_verbose)
        !           267:                                                printf(" 0x%lx[0x%x]",
        !           268:                                                    nca.ca_addrs[ia].addr,
        !           269:                                                    nca.ca_addrs[ia].size);
        !           270:                                }
        !           271:                                if (autoconf_verbose)
        !           272:                                        printf("\n");
        !           273:                        }
        !           274:                }
        !           275:
        !           276:                if (!nca.ca_hpa)
        !           277:                        continue;
        !           278:
        !           279:                if (autoconf_verbose)
        !           280:                        printf(">> HPA 0x%lx[0x%x]\n",
        !           281:                            nca.ca_hpa, nca.ca_hpasz);
        !           282:
        !           283:                if ((error = pdc_call((iodcio_t)pdc, 0, PDC_IODC,
        !           284:                    PDC_IODC_READ, &pdc_iodc_read, nca.ca_hpa, IODC_DATA,
        !           285:                    &nca.ca_type, sizeof(nca.ca_type))) < 0) {
        !           286:                        if (autoconf_verbose)
        !           287:                                printf(">> iodc_data error %d\n", error);
        !           288:                        continue;
        !           289:                }
        !           290:
        !           291:                nca.ca_pdc_iodc_read = &pdc_iodc_read;
        !           292:                nca.ca_name = hppa_mod_info(nca.ca_type.iodc_type,
        !           293:                                            nca.ca_type.iodc_sv_model);
        !           294:
        !           295:                if (autoconf_verbose) {
        !           296:                        printf(">> probing: flags %b bc %d/%d/%d/%d/%d/%d ",
        !           297:                            nca.ca_dp.dp_flags, PZF_BITS,
        !           298:                            nca.ca_dp.dp_bc[0], nca.ca_dp.dp_bc[1],
        !           299:                            nca.ca_dp.dp_bc[2], nca.ca_dp.dp_bc[3],
        !           300:                            nca.ca_dp.dp_bc[4], nca.ca_dp.dp_bc[5]);
        !           301:                        printf("mod %x hpa %lx type %x sv %x\n",
        !           302:                            nca.ca_dp.dp_mod, nca.ca_hpa,
        !           303:                            nca.ca_type.iodc_type, nca.ca_type.iodc_sv_model);
        !           304:                }
        !           305:
        !           306:                config_found_sm(self, &nca, mbprint, mbsubmatch);
        !           307:        }
        !           308: }
        !           309:
        !           310: const struct hppa_mod_info hppa_knownmods[] = {
        !           311: #include <hppa/dev/cpudevs_data.h>
        !           312: };
        !           313:
        !           314: const char *
        !           315: hppa_mod_info(type, sv)
        !           316:        int type, sv;
        !           317: {
        !           318:        const struct hppa_mod_info *mi;
        !           319:        static char fakeid[32];
        !           320:
        !           321:        for (mi = hppa_knownmods; mi->mi_type >= 0 &&
        !           322:            (mi->mi_type != type || mi->mi_sv != sv); mi++);
        !           323:
        !           324:        if (mi->mi_type < 0) {
        !           325:                snprintf(fakeid, sizeof fakeid, "type %x, sv %x", type, sv);
        !           326:                return fakeid;
        !           327:        } else
        !           328:                return mi->mi_name;
        !           329: }
        !           330:
        !           331: void
        !           332: device_register(struct device *dev, void *aux)
        !           333: {
        !           334: #if NPCI > 0
        !           335:        extern struct cfdriver pci_cd;
        !           336: #endif
        !           337:        struct confargs *ca = aux;
        !           338:        char *basename;
        !           339:        static struct device *elder = NULL;
        !           340:
        !           341:        if (bootdv != NULL)
        !           342:                return; /* We already have a winner */
        !           343:
        !           344: #if NPCI > 0
        !           345:        if (dev->dv_parent &&
        !           346:            dev->dv_parent->dv_cfdata->cf_driver == &pci_cd) {
        !           347:                struct pci_attach_args *pa = aux;
        !           348:                pcireg_t addr;
        !           349:                int reg;
        !           350:
        !           351:                for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {
        !           352:                        addr = pci_conf_read(pa->pa_pc, pa->pa_tag, reg);
        !           353:                        if (PCI_MAPREG_TYPE(addr) == PCI_MAPREG_TYPE_IO)
        !           354:                                addr = PCI_MAPREG_IO_ADDR(addr);
        !           355:                        else
        !           356:                                addr = PCI_MAPREG_MEM_ADDR(addr);
        !           357:
        !           358:                        if (addr == (pcireg_t)PAGE0->mem_boot.pz_hpa) {
        !           359:                                elder = dev;
        !           360:                                break;
        !           361:                        }
        !           362:                }
        !           363:        } else
        !           364: #endif
        !           365:        if (ca->ca_hpa == (hppa_hpa_t)PAGE0->mem_boot.pz_hpa) {
        !           366:                /*
        !           367:                 * If hpa matches, the only thing we know is that the
        !           368:                 * booted device is either this one or one of its children.
        !           369:                 * And the children will not necessarily have the correct
        !           370:                 * hpa value.
        !           371:                 * Save this elder for now.
        !           372:                 */
        !           373:                elder = dev;
        !           374:        } else if (elder == NULL) {
        !           375:                return; /* not the device we booted from */
        !           376:        }
        !           377:
        !           378:        /*
        !           379:         * Unfortunately, we can not match on pz_class vs dv_class on
        !           380:         * older snakes netbooting using the rbootd protocol.
        !           381:         * In this case, we'll end up with pz_class == PCL_RANDOM...
        !           382:         * Instead, trust the device class from what the kernel attached
        !           383:         * now...
        !           384:         */
        !           385:        switch (dev->dv_class) {
        !           386:        case DV_IFNET:
        !           387:                /*
        !           388:                 * Netboot is the top elder
        !           389:                 */
        !           390:                if (elder == dev) {
        !           391:                        bootdv = dev;
        !           392:                }
        !           393:                return;
        !           394:        case DV_DISK:
        !           395:                if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_RANDOM)
        !           396:                        return;
        !           397:                break;
        !           398:        case DV_TAPE:
        !           399:                if ((PAGE0->mem_boot.pz_class & PCL_CLASS_MASK) != PCL_SEQU)
        !           400:                        return;
        !           401:                break;
        !           402:        default:
        !           403:                /* No idea what we were booted from, but better ask the user */
        !           404:                return;
        !           405:        }
        !           406:
        !           407:        /*
        !           408:         * If control goes here, we are booted from a block device and we
        !           409:         * matched a block device.
        !           410:         */
        !           411:        basename = dev->dv_cfdata->cf_driver->cd_name;
        !           412:
        !           413:        /*
        !           414:         * We only grok SCSI boot currently. Match on proper device hierarchy,
        !           415:         * name and unit/lun values.
        !           416:         */
        !           417: #if NCD > 0 || NSD > 0 || NST > 0
        !           418:        if (strcmp(basename, "sd") == 0 || strcmp(basename, "cd") == 0 ||
        !           419:            strcmp(basename, "st") == 0) {
        !           420:                struct scsi_attach_args *sa = aux;
        !           421:                struct scsi_link *sl = sa->sa_sc_link;
        !           422:
        !           423:                /*
        !           424:                 * sd/st/cd is attached to scsibus which is attached to
        !           425:                 * the controller. Hence the grandparent here should be
        !           426:                 * the elder.
        !           427:                 */
        !           428:                if (dev->dv_parent == NULL ||
        !           429:                    dev->dv_parent->dv_parent != elder) {
        !           430:                        return;
        !           431:                }
        !           432:
        !           433:                /*
        !           434:                 * And now check for proper target and lun values
        !           435:                 */
        !           436:                if (sl->target == PAGE0->mem_boot.pz_layers[0] &&
        !           437:                    sl->lun == PAGE0->mem_boot.pz_layers[1]) {
        !           438:                        bootdv = dev;
        !           439:                }
        !           440:        }
        !           441: #endif
        !           442: }
        !           443:
        !           444: /*
        !           445:  * cpu_configure:
        !           446:  * called at boot time, configure all devices on system
        !           447:  */
        !           448: void
        !           449: cpu_configure(void)
        !           450: {
        !           451:        splhigh();
        !           452:        if (config_rootfound("mainbus", "mainbus") == NULL)
        !           453:                panic("no mainbus found");
        !           454:
        !           455:        cpu_intr_init();
        !           456:        spl0();
        !           457:
        !           458:        print_devpath("bootpath", &PAGE0->mem_boot);
        !           459:
        !           460:        if (cold_hook)
        !           461:                (*cold_hook)(HPPA_COLD_HOT);
        !           462:
        !           463: #ifdef USELEDS
        !           464:        timeout_set(&heartbeat_tmo, heartbeat, NULL);
        !           465:        heartbeat(NULL);
        !           466: #endif
        !           467:        cold = 0;
        !           468: }
        !           469:
        !           470: void
        !           471: diskconf(void)
        !           472: {
        !           473:        setroot(bootdv, 0, RB_USERREQ);
        !           474:        dumpconf();
        !           475: }
        !           476:
        !           477: struct nam2blk nam2blk[] = {
        !           478:        { "rd",         3 },
        !           479:        { "sd",         4 },
        !           480:        { "st",         5 },
        !           481:        { "cd",         6 },
        !           482:        { "fd",         7 },
        !           483:        { "wd",         8 },
        !           484:        { NULL,         -1 }
        !           485: };

CVSweb