[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

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