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

Annotation of sys/arch/amd64/amd64/mpbios.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mpbios.c,v 1.9 2007/01/15 23:19:05 jsg Exp $  */
                      2: /*     $NetBSD: mpbios.c,v 1.7 2003/05/15 16:32:50 fvdl Exp $  */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2000 The NetBSD Foundation, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to The NetBSD Foundation
                      9:  * by RedBack Networks Inc.
                     10:  *
                     11:  * Author: Bill Sommerfeld
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. All advertising materials mentioning features or use of this software
                     22:  *    must display the following acknowledgement:
                     23:  *        This product includes software developed by the NetBSD
                     24:  *        Foundation, Inc. and its contributors.
                     25:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     26:  *    contributors may be used to endorse or promote products derived
                     27:  *    from this software without specific prior written permission.
                     28:  *
                     29:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     30:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     31:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     32:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     33:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     34:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     35:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     36:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     37:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     38:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     39:  * POSSIBILITY OF SUCH DAMAGE.
                     40:  */
                     41:
                     42: /*
                     43:  * Copyright (c) 1999 Stefan Grefen
                     44:  *
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  * 1. Redistributions of source code must retain the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer.
                     50:  * 2. Redistributions in binary form must reproduce the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer in the
                     52:  *    documentation and/or other materials provided with the distribution.
                     53:  * 3. All advertising materials mentioning features or use of this software
                     54:  *    must display the following acknowledgement:
                     55:  *      This product includes software developed by the NetBSD
                     56:  *      Foundation, Inc. and its contributors.
                     57:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     58:  *    contributors may be used to endorse or promote products derived
                     59:  *    from this software without specific prior written permission.
                     60:  *
                     61:  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
                     62:  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     63:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     64:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
                     65:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     66:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     67:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     68:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     69:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     70:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     71:  * SUCH DAMAGE.
                     72:  */
                     73: /*
                     74:  * Derived from FreeBSD's mp_machdep.c
                     75:  */
                     76: /*
                     77:  * Copyright (c) 1996, by Steve Passe
                     78:  * All rights reserved.
                     79:  *
                     80:  * Redistribution and use in source and binary forms, with or without
                     81:  * modification, are permitted provided that the following conditions
                     82:  * are met:
                     83:  * 1. Redistributions of source code must retain the above copyright
                     84:  *    notice, this list of conditions and the following disclaimer.
                     85:  * 2. The name of the developer may NOT be used to endorse or promote products
                     86:  *    derived from this software without specific prior written permission.
                     87:  *
                     88:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     89:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     90:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     91:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     92:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     93:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     94:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     95:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     96:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     97:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     98:  * SUCH DAMAGE.
                     99:  */
                    100:
                    101: /*
                    102:  * The Intel MP-stuff is just one way of x86 SMP systems
                    103:  * so only Intel MP specific stuff is here.
                    104:  */
                    105:
                    106: #include <sys/param.h>
                    107: #include <sys/systm.h>
                    108: #include <sys/kernel.h>
                    109: #include <sys/device.h>
                    110: #include <sys/malloc.h>
                    111:
                    112: #include <uvm/uvm_extern.h>
                    113:
                    114: #include <machine/specialreg.h>
                    115: #include <machine/cpuvar.h>
                    116: #include <machine/bus.h>
                    117: #include <machine/mpbiosvar.h>
                    118:
                    119: #include <machine/i82093reg.h>
                    120: #include <machine/i82093var.h>
                    121: #include <machine/i82489reg.h>
                    122: #include <machine/i82489var.h>
                    123:
                    124: #include <dev/isa/isareg.h>
                    125: #include <dev/pci/pcivar.h>
                    126:
                    127: #ifdef X86_MPBIOS_SUPPORT_EISA
                    128: #include <dev/eisa/eisavar.h>  /* for ELCR* def'ns */
                    129: #endif
                    130:
                    131: #include "pci.h"
                    132:
                    133:
                    134: static struct mpbios_ioapic default_ioapic = {
                    135:     2, 0, 1, IOAPICENTRY_FLAG_EN, (u_int32_t)IOAPIC_BASE_DEFAULT
                    136: };
                    137:
                    138: /* descriptions of MP basetable entries */
                    139: struct mpbios_baseentry {
                    140:        u_int8_t        type;
                    141:        u_int8_t        length;
                    142:        u_int16_t       count;
                    143:        const char      *name;
                    144: };
                    145:
                    146: static const char *loc_where[] = {
                    147:        "extended bios data area",
                    148:        "last page of base memory",
                    149:        "bios"
                    150: };
                    151:
                    152: struct mp_map
                    153: {
                    154:        vaddr_t         baseva;
                    155:        int             vsize;
                    156:        paddr_t         pa;
                    157:        paddr_t         pg;
                    158:        int             psize;
                    159: };
                    160:
                    161: int mp_print(void *, const char *);
                    162: int mp_match(struct device *, void *,void *);
                    163: const void *mpbios_search(struct device *, paddr_t, int, struct mp_map *);
                    164: static __inline int mpbios_cksum(const void *,int);
                    165:
                    166: void mp_cfg_special_intr(const struct mpbios_int *, u_int32_t *);
                    167: void mp_print_special_intr(int intr);
                    168:
                    169: void mp_cfg_pci_intr(const struct mpbios_int *, u_int32_t *);
                    170: void mp_print_pci_intr(int intr);
                    171:
                    172: #ifdef X86_MPBIOS_SUPPORT_EISA
                    173: void mp_print_eisa_intr(int intr);
                    174: void mp_cfg_eisa_intr(const struct mpbios_int *, u_int32_t *);
                    175: #endif
                    176:
                    177: void mp_cfg_isa_intr(const struct mpbios_int *, u_int32_t *);
                    178: void mp_print_isa_intr (int intr);
                    179:
                    180: void mpbios_cpu(const u_int8_t *, struct device *);
                    181: void mpbios_bus(const u_int8_t *, struct device *);
                    182: void mpbios_ioapic(const u_int8_t *, struct device *);
                    183: int mpbios_int(const u_int8_t *, int, struct mp_intr_map *);
                    184:
                    185: const void *mpbios_map(paddr_t, int, struct mp_map *);
                    186: void mpbios_unmap(struct mp_map *);
                    187:
                    188: /*
                    189:  * globals to help us bounce our way through parsing the config table.
                    190:  */
                    191:
                    192: static struct mp_map mp_cfg_table_map;
                    193: static struct mp_map mp_fp_map;
                    194: const struct mpbios_cth        *mp_cth;
                    195: const struct mpbios_fps        *mp_fps;
                    196:
                    197: int mpbios_scanned;
                    198:
                    199: int
                    200: mp_print(void *aux, const char *pnp)
                    201: {
                    202:        struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
                    203:        if (pnp)
                    204:                printf("%s at %s:",caa->caa_name, pnp);
                    205:        return (UNCONF);
                    206: }
                    207:
                    208: int
                    209: mp_match(struct device *parent, void *cfv, void *aux)
                    210: {
                    211:        struct cfdata *cf = (struct cfdata *)cfv;
                    212:        struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
                    213:        if (strcmp(caa->caa_name, cf->cf_driver->cd_name))
                    214:                return 0;
                    215:
                    216:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
                    217: }
                    218:
                    219: /*
                    220:  * Map a chunk of memory read-only and return an appropraitely
                    221:  * const'ed pointer.
                    222:  */
                    223:
                    224: const void *
                    225: mpbios_map(paddr_t pa, int len, struct mp_map *handle)
                    226: {
                    227:        paddr_t pgpa = trunc_page(pa);
                    228:        paddr_t endpa = round_page(pa + len);
                    229:        vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
                    230:        vaddr_t retva = va + (pa & PGOFSET);
                    231:
                    232:        handle->pa = pa;
                    233:        handle->pg = pgpa;
                    234:        handle->psize = len;
                    235:        handle->baseva = va;
                    236:        handle->vsize = endpa-pgpa;
                    237:
                    238:        do {
                    239:                pmap_kenter_pa (va, pgpa, VM_PROT_READ);
                    240:                va += PAGE_SIZE;
                    241:                pgpa += PAGE_SIZE;
                    242:        } while (pgpa < endpa);
                    243:
                    244:        return (const void *)retva;
                    245: }
                    246:
                    247: void
                    248: mpbios_unmap(struct mp_map *handle)
                    249: {
                    250:        pmap_kremove (handle->baseva, handle->vsize);
                    251:        uvm_km_free (kernel_map, handle->baseva, handle->vsize);
                    252: }
                    253:
                    254: /*
                    255:  * Look for an Intel MP spec table, indicating SMP capable hardware.
                    256:  */
                    257: int
                    258: mpbios_probe(struct device *self)
                    259: {
                    260:        paddr_t         ebda, memtop;
                    261:
                    262:        paddr_t         cthpa;
                    263:        int             cthlen;
                    264:        const u_int8_t  *mpbios_page;
                    265:        int             scan_loc;
                    266:
                    267:        struct          mp_map t;
                    268:
                    269:        /*
                    270:         * Skip probe if someone else (e.g. acpi) already provided the
                    271:         * necessary details.
                    272:         */
                    273:        if (mp_busses)
                    274:                return (0);
                    275:
                    276:        /* see if EBDA exists */
                    277:
                    278:        mpbios_page = mpbios_map (0, PAGE_SIZE, &t);
                    279:
                    280:        ebda =   *(const u_int16_t *) (&mpbios_page[0x40e]);
                    281:        ebda <<= 4;
                    282:
                    283:        memtop = *(const u_int16_t *) (&mpbios_page[0x413]);
                    284:        memtop <<= 10;
                    285:
                    286:        mpbios_page = NULL;
                    287:        mpbios_unmap(&t);
                    288:
                    289:        scan_loc = 0;
                    290:
                    291:        if (ebda && ebda < IOM_BEGIN ) {
                    292:                mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
                    293:                if (mp_fps != NULL)
                    294:                        goto found;
                    295:        }
                    296:
                    297:        scan_loc = 1;
                    298:
                    299:        if (memtop && memtop <= IOM_BEGIN ) {
                    300:                mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
                    301:                if (mp_fps != NULL)
                    302:                        goto found;
                    303:        }
                    304:
                    305:        scan_loc = 2;
                    306:
                    307:        mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
                    308:        if (mp_fps != NULL)
                    309:                goto found;
                    310:
                    311:        /* nothing found */
                    312:        return 0;
                    313:
                    314:  found:
                    315:        if (mp_verbose)
                    316:                printf("%s: MP floating pointer found in %s at 0x%lx\n",
                    317:                    self->dv_xname, loc_where[scan_loc], mp_fp_map.pa);
                    318:
                    319:        if (mp_fps->pap == 0) {
                    320:                if (mp_fps->mpfb1 == 0) {
                    321:                        printf("%s: MP fps invalid: "
                    322:                            "no default config and no configuration table\n",
                    323:                            self->dv_xname);
                    324:
                    325:                        goto err;
                    326:                }
                    327:                printf("%s: MP default configuration %d\n",
                    328:                    self->dv_xname, mp_fps->mpfb1);
                    329:                return 10;
                    330:        }
                    331:
                    332:        cthpa = mp_fps->pap;
                    333:
                    334:        mp_cth = mpbios_map (cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
                    335:        cthlen = mp_cth->base_len;
                    336:        mpbios_unmap(&mp_cfg_table_map);
                    337:
                    338:        mp_cth = mpbios_map (cthpa, cthlen, &mp_cfg_table_map);
                    339:
                    340:        if (mp_verbose)
                    341:                printf("%s: MP config table at 0x%lx, %d bytes long\n",
                    342:                    self->dv_xname, cthpa, cthlen);
                    343:
                    344:        if (mp_cth->signature != MP_CT_SIG) {
                    345:                printf("%s: MP signature mismatch (%x vs %x)\n",
                    346:                    self->dv_xname,
                    347:                    MP_CT_SIG, mp_cth->signature);
                    348:                goto err;
                    349:        }
                    350:
                    351:        if (mpbios_cksum(mp_cth, cthlen)) {
                    352:                printf ("%s: MP Configuration Table checksum mismatch\n",
                    353:                    self->dv_xname);
                    354:                goto err;
                    355:        }
                    356:        return 10;
                    357:  err:
                    358:        if (mp_fps) {
                    359:                mp_fps = NULL;
                    360:                mpbios_unmap(&mp_fp_map);
                    361:        }
                    362:        if (mp_cth) {
                    363:                mp_cth = NULL;
                    364:                mpbios_unmap(&mp_cfg_table_map);
                    365:        }
                    366:        return 0;
                    367: }
                    368:
                    369:
                    370: /*
                    371:  * Simple byte checksum used on config tables.
                    372:  */
                    373:
                    374: static __inline int
                    375: mpbios_cksum(const void *start, int len)
                    376: {
                    377:        unsigned char res=0;
                    378:        const char *p = start;
                    379:        const char *end = p + len;
                    380:
                    381:        while (p < end)
                    382:                res += *p++;
                    383:
                    384:        return res;
                    385: }
                    386:
                    387:
                    388: /*
                    389:  * Look for the MP floating pointer signature in the given physical
                    390:  * address range.
                    391:  *
                    392:  * We map the memory, scan through it, and unmap it.
                    393:  * If we find it, remap the floating pointer structure and return it.
                    394:  */
                    395:
                    396: const void *
                    397: mpbios_search(struct device *self, paddr_t start, int count, struct mp_map *map)
                    398: {
                    399:        struct mp_map t;
                    400:
                    401:        int i, len;
                    402:        const struct mpbios_fps *m;
                    403:        int end = count - sizeof(*m);
                    404:        const u_int8_t *base = mpbios_map (start, count, &t);
                    405:
                    406:        if (mp_verbose)
                    407:                printf("%s: scanning 0x%lx to 0x%lx for MP signature\n",
                    408:                    self->dv_xname, start, start+count-sizeof(*m));
                    409:
                    410:        for (i = 0; i <= end; i += 4) {
                    411:                m = (struct mpbios_fps *)&base[i];
                    412:
                    413:                if ((m->signature == MP_FP_SIG) &&
                    414:                    ((len = m->length << 4) != 0) &&
                    415:                    mpbios_cksum(m, (m->length << 4)) == 0) {
                    416:
                    417:                        mpbios_unmap (&t);
                    418:
                    419:                        return mpbios_map (start+i, len, map);
                    420:                }
                    421:        }
                    422:        mpbios_unmap(&t);
                    423:
                    424:        return 0;
                    425: }
                    426:
                    427: /*
                    428:  * MP configuration table parsing.
                    429:  */
                    430:
                    431: static struct mpbios_baseentry mp_conf[] =
                    432: {
                    433:        {0, 20, 0, "cpu"},
                    434:        {1, 8, 0, "bus"},
                    435:        {2, 8, 0, "ioapic"},
                    436:        {3, 8, 0, "ioint"},
                    437:        {4, 8, 0, "lint"},
                    438: };
                    439:
                    440: static struct mp_bus extint_bus = {
                    441:        "ExtINT",
                    442:        -1,
                    443:        mp_print_special_intr,
                    444:        mp_cfg_special_intr,
                    445:        0
                    446: };
                    447: static struct mp_bus smi_bus = {
                    448:        "SMI",
                    449:        -1,
                    450:        mp_print_special_intr,
                    451:        mp_cfg_special_intr,
                    452:        0
                    453: };
                    454: static struct mp_bus nmi_bus = {
                    455:        "NMI",
                    456:        -1,
                    457:        mp_print_special_intr,
                    458:        mp_cfg_special_intr,
                    459:        0
                    460: };
                    461:
                    462:
                    463: /*
                    464:  * 1st pass on BIOS's Intel MP specification table.
                    465:  *
                    466:  * initializes:
                    467:  *     mp_ncpus = 1
                    468:  *
                    469:  * determines:
                    470:  *     cpu_apic_address (common to all CPUs)
                    471:  *     ioapic_address[N]
                    472:  *     mp_naps
                    473:  *     mp_nbusses
                    474:  *     mp_napics
                    475:  *     nintrs
                    476:  */
                    477: void
                    478: mpbios_scan(struct device *self)
                    479: {
                    480:        const u_int8_t  *position, *end;
                    481:        int             count;
                    482:        int             type;
                    483:        int             intr_cnt, cur_intr;
                    484:        paddr_t         lapic_base;
                    485:        const struct mpbios_int *iep;
                    486:        struct mpbios_int ie;
                    487:        struct ioapic_softc *sc;
                    488:
                    489:        printf ("%s: Intel MP Specification ", self->dv_xname);
                    490:
                    491:        switch (mp_fps->spec_rev) {
                    492:        case 1:
                    493:                printf("(Version 1.1)\n");
                    494:                break;
                    495:        case 4:
                    496:                printf("(Version 1.4)\n");
                    497:                break;
                    498:        default:
                    499:                printf("(unrecognized rev %d)\n", mp_fps->spec_rev);
                    500:        }
                    501:
                    502:        /*
                    503:         * looks like we've got a MP system.  start setting up
                    504:         * infrastructure..
                    505:         * XXX is this the right place??
                    506:         */
                    507:
                    508:        lapic_base = LAPIC_BASE;
                    509:        if (mp_cth != NULL)
                    510:                lapic_base = (paddr_t)mp_cth->apic_address;
                    511:
                    512:        lapic_boot_init(lapic_base);
                    513:
                    514:        /* check for use of 'default' configuration */
                    515:        if (mp_fps->mpfb1 != 0) {
                    516:                struct mpbios_proc pe;
                    517:
                    518:                printf("\n%s: MP default configuration %d\n",
                    519:                    self->dv_xname, mp_fps->mpfb1);
                    520:
                    521:                /* use default addresses */
                    522:                pe.apic_id = lapic_cpu_number();
                    523:                pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP;
                    524:                pe.cpu_signature = cpu_info_primary.ci_signature;
                    525:                pe.feature_flags = cpu_info_primary.ci_feature_flags;
                    526:
                    527:                mpbios_cpu((u_int8_t *)&pe, self);
                    528:
                    529:                pe.apic_id = 1 - lapic_cpu_number();
                    530:                pe.cpu_flags = PROCENTRY_FLAG_EN;
                    531:
                    532:                mpbios_cpu((u_int8_t *)&pe, self);
                    533:
                    534:                mpbios_ioapic((u_int8_t *)&default_ioapic, self);
                    535:
                    536:                /* XXX */
                    537:                printf("%s: WARNING: interrupts not configured\n",
                    538:                    self->dv_xname);
                    539:                panic("lazy bum");
                    540:                return;
                    541:        } else {
                    542:                /*
                    543:                 * should not happen; mp_probe returns 0 in this case,
                    544:                 * but..
                    545:                 */
                    546:                if (mp_cth == NULL)
                    547:                        panic ("mpbios_scan: no config (can't happen?)");
                    548:
                    549:                /*
                    550:                 * Walk the table once, counting items
                    551:                 */
                    552:                position = (const u_int8_t *)(mp_cth);
                    553:                end = position + mp_cth->base_len;
                    554:                position += sizeof(*mp_cth);
                    555:
                    556:                count = mp_cth->entry_count;
                    557:                intr_cnt = 0;
                    558:
                    559:                while ((count--) && (position < end)) {
                    560:                        type = *position;
                    561:                        if (type >= MPS_MCT_NTYPES) {
                    562:                                printf("%s: unknown entry type %x"
                    563:                                    " in MP config table\n",
                    564:                                    self->dv_xname, type);
                    565:                                break;
                    566:                        }
                    567:                        mp_conf[type].count++;
                    568:                        if (type == MPS_MCT_BUS) {
                    569:                                const struct mpbios_bus *bp =
                    570:                                    (const struct mpbios_bus *)position;
                    571:                                if (bp->bus_id >= mp_nbus)
                    572:                                        mp_nbus = bp->bus_id + 1;
                    573:                        }
                    574:                        /*
                    575:                         * Count actual interrupt instances.
                    576:                         * dst_apic_id of MPS_ALL_APICS means "wired to all
                    577:                         * apics of this type".
                    578:                         */
                    579:                        if (type == MPS_MCT_IOINT) {
                    580:                                iep = (const struct mpbios_int *)position;
                    581:                                if (iep->dst_apic_id == MPS_ALL_APICS)
                    582:                                        intr_cnt +=
                    583:                                            mp_conf[MPS_MCT_IOAPIC].count;
                    584:                                else
                    585:                                        intr_cnt++;
                    586:                        } else if (type == MPS_MCT_LINT)
                    587:                                intr_cnt++;
                    588:                        position += mp_conf[type].length;
                    589:                }
                    590:
                    591:                mp_busses = malloc(sizeof(struct mp_bus)*mp_nbus,
                    592:                    M_DEVBUF, M_NOWAIT);
                    593:                memset(mp_busses, 0, sizeof(struct mp_bus) * mp_nbus);
                    594:                mp_intrs = malloc(sizeof(struct mp_intr_map)*intr_cnt,
                    595:                    M_DEVBUF, M_NOWAIT);
                    596:
                    597:                /* re-walk the table, recording info of interest */
                    598:                position = (const u_int8_t *) mp_cth + sizeof(*mp_cth);
                    599:                count = mp_cth->entry_count;
                    600:                cur_intr = 0;
                    601:
                    602:                while ((count--) && (position < end)) {
                    603:                        switch (type = *(u_char *) position) {
                    604:                        case MPS_MCT_CPU:
                    605:                                mpbios_cpu(position, self);
                    606:                                break;
                    607:                        case MPS_MCT_BUS:
                    608:                                mpbios_bus(position, self);
                    609:                                break;
                    610:                        case MPS_MCT_IOAPIC:
                    611:                                mpbios_ioapic(position, self);
                    612:                                break;
                    613:                        case MPS_MCT_IOINT:
                    614:                                iep = (const struct mpbios_int *)position;
                    615:                                ie = *iep;
                    616:                                if (iep->dst_apic_id == MPS_ALL_APICS) {
                    617:                                        for (sc = ioapics ; sc != NULL;
                    618:                                             sc = sc->sc_next) {
                    619:                                                ie.dst_apic_id = sc->sc_apicid;
                    620:                                                if (mpbios_int((char *)&ie,
                    621:                                                    type, &mp_intrs[cur_intr]) == 0)
                    622:                                                        cur_intr++;
                    623:                                        }
                    624:                                } else {
                    625:                                        if (mpbios_int(position, type,
                    626:                                            &mp_intrs[cur_intr]) == 0)
                    627:                                                cur_intr++;
                    628:                                }
                    629:                                break;
                    630:                        case MPS_MCT_LINT:
                    631:                                if (mpbios_int(position, type,
                    632:                                    &mp_intrs[cur_intr]) == 0)
                    633:                                        cur_intr++;
                    634:                                break;
                    635:                        default:
                    636:                                printf("%s: unknown entry type %x in MP config table\n",
                    637:                                    self->dv_xname, type);
                    638:                                /* NOTREACHED */
                    639:                                return;
                    640:                        }
                    641:
                    642:                        (u_char*)position += mp_conf[type].length;
                    643:                }
                    644:                mp_nintr = cur_intr;
                    645:
                    646:                if (mp_verbose && mp_cth->ext_len)
                    647:                        printf("%s: MP WARNING: %d bytes of extended entries not examined\n",
                    648:                            self->dv_xname,
                    649:                            mp_cth->ext_len);
                    650:        }
                    651:
                    652:        /* Clean up. */
                    653:        mp_fps = NULL;
                    654:        mpbios_unmap (&mp_fp_map);
                    655:        if (mp_cth != NULL) {
                    656:                mp_cth = NULL;
                    657:                mpbios_unmap (&mp_cfg_table_map);
                    658:        }
                    659:        mpbios_scanned = 1;
                    660:
                    661: #if NPCI > 0
                    662:        if (pci_mode != 0)
                    663:                mpbios_intr_fixup();
                    664: #endif
                    665: }
                    666:
                    667: void
                    668: mpbios_cpu(const u_int8_t *ent, struct device *self)
                    669: {
                    670:        const struct mpbios_proc *entry = (const struct mpbios_proc *)ent;
                    671:        struct cpu_attach_args caa;
                    672:
                    673:        /* XXX move this into the CPU attachment goo. */
                    674:        /* check for usability */
                    675:        if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
                    676:                return;
                    677:
                    678:        /* check for BSP flag */
                    679:        if (entry->cpu_flags & PROCENTRY_FLAG_BP)
                    680:                caa.cpu_role = CPU_ROLE_BP;
                    681:        else
                    682:                caa.cpu_role = CPU_ROLE_AP;
                    683:
                    684:        caa.caa_name   = "cpu";
                    685:        caa.cpu_number = entry->apic_id;
                    686:        caa.cpu_func = &mp_cpu_funcs;
                    687:
                    688:        config_found_sm(self, &caa, mp_print, mp_match);
                    689: }
                    690:
                    691: /*
                    692:  * The following functions conspire to compute base ioapic redirection
                    693:  * table entry for a given interrupt line.
                    694:  *
                    695:  * Fill in: trigger mode, polarity, and possibly delivery mode.
                    696:  */
                    697: void mp_cfg_special_intr (const struct mpbios_int *entry, u_int32_t *redir)
                    698: {
                    699:
                    700:        /*
                    701:         * All of these require edge triggered, zero vector,
                    702:         * appropriate delivery mode.
                    703:         * see page 13 of the 82093AA datasheet.
                    704:         */
                    705:        *redir &= ~IOAPIC_REDLO_DEL_MASK;
                    706:        *redir &= ~IOAPIC_REDLO_VECTOR_MASK;
                    707:        *redir &= ~IOAPIC_REDLO_LEVEL;
                    708:
                    709:        switch (entry->int_type) {
                    710:        case MPS_INTTYPE_NMI:
                    711:                *redir |= (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
                    712:                break;
                    713:
                    714:        case MPS_INTTYPE_SMI:
                    715:                *redir |= (IOAPIC_REDLO_DEL_SMI<<IOAPIC_REDLO_DEL_SHIFT);
                    716:                break;
                    717:        case MPS_INTTYPE_ExtINT:
                    718:                /*
                    719:                 * We are using the ioapic in "native" mode.
                    720:                 * This indicates where the 8259 is wired to the ioapic
                    721:                 * and/or local apic..
                    722:                 */
                    723:                *redir |= (IOAPIC_REDLO_DEL_EXTINT<<IOAPIC_REDLO_DEL_SHIFT);
                    724:                *redir |= (IOAPIC_REDLO_MASK);
                    725:                break;
                    726:        default:
                    727:                panic("unknown MPS interrupt type %d", entry->int_type);
                    728:        }
                    729: }
                    730:
                    731: /* XXX too much duplicated code here. */
                    732:
                    733: void
                    734: mp_cfg_pci_intr(const struct mpbios_int *entry, u_int32_t *redir)
                    735: {
                    736:        int mpspo = entry->int_flags & 0x03; /* XXX magic */
                    737:        int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
                    738:
                    739:        *redir &= ~IOAPIC_REDLO_DEL_MASK;
                    740:        switch (mpspo) {
                    741:        case MPS_INTPO_ACTHI:
                    742:                *redir &= ~IOAPIC_REDLO_ACTLO;
                    743:                break;
                    744:        case MPS_INTPO_DEF:
                    745:        case MPS_INTPO_ACTLO:
                    746:                *redir |= IOAPIC_REDLO_ACTLO;
                    747:                break;
                    748:        default:
                    749:                panic("unknown MPS interrupt polarity %d", mpspo);
                    750:        }
                    751:
                    752:        if (entry->int_type != MPS_INTTYPE_INT) {
                    753:                mp_cfg_special_intr(entry, redir);
                    754:                return;
                    755:        }
                    756:        *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
                    757:
                    758:        switch (mpstrig) {
                    759:        case MPS_INTTR_DEF:
                    760:        case MPS_INTTR_LEVEL:
                    761:                *redir |= IOAPIC_REDLO_LEVEL;
                    762:                break;
                    763:        case MPS_INTTR_EDGE:
                    764:                *redir &= ~IOAPIC_REDLO_LEVEL;
                    765:                break;
                    766:        default:
                    767:                panic("unknown MPS interrupt trigger %d", mpstrig);
                    768:        }
                    769: }
                    770:
                    771: #ifdef X86_MPBIOS_SUPPORT_EISA
                    772: void
                    773: mp_cfg_eisa_intr(const struct *entry, u_int32_t *redir)
                    774: {
                    775:        int mpspo = entry->int_flags & 0x03; /* XXX magic */
                    776:        int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
                    777:
                    778:        *redir &= ~IOAPIC_REDLO_DEL_MASK;
                    779:        switch (mpspo) {
                    780:        case MPS_INTPO_DEF:
                    781:        case MPS_INTPO_ACTHI:
                    782:                *redir &= ~IOAPIC_REDLO_ACTLO;
                    783:                break;
                    784:        case MPS_INTPO_ACTLO:
                    785:                *redir |= IOAPIC_REDLO_ACTLO;
                    786:                break;
                    787:        default:
                    788:                panic("unknown MPS interrupt polarity %d", mpspo);
                    789:        }
                    790:
                    791:        if (entry->int_type != MPS_INTTYPE_INT) {
                    792:                mp_cfg_special_intr(entry, redir);
                    793:                return;
                    794:        }
                    795:        *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
                    796:
                    797:        switch (mpstrig) {
                    798:        case MPS_INTTR_LEVEL:
                    799:                *redir |= IOAPIC_REDLO_LEVEL;
                    800:                break;
                    801:        case MPS_INTTR_EDGE:
                    802:                *redir &= ~IOAPIC_REDLO_LEVEL;
                    803:                break;
                    804:        case MPS_INTTR_DEF:
                    805:                /*
                    806:                 * Set "default" setting based on ELCR value snagged
                    807:                 * earlier.
                    808:                 */
                    809:                if (mp_busses[entry->src_bus_id].mb_data &
                    810:                    (1<<entry->src_bus_irq)) {
                    811:                        *redir |= IOAPIC_REDLO_LEVEL;
                    812:                } else {
                    813:                        *redir &= ~IOAPIC_REDLO_LEVEL;
                    814:                }
                    815:                break;
                    816:        default:
                    817:                panic("unknown MPS interrupt trigger %d", mpstrig);
                    818:        }
                    819: }
                    820: #endif
                    821:
                    822:
                    823: void
                    824: mp_cfg_isa_intr(const struct mpbios_int *entry, u_int32_t *redir)
                    825: {
                    826:        int mpspo = entry->int_flags & 0x03; /* XXX magic */
                    827:        int mpstrig = (entry->int_flags >> 2) & 0x03; /* XXX magic */
                    828:
                    829:        *redir &= ~IOAPIC_REDLO_DEL_MASK;
                    830:        switch (mpspo) {
                    831:        case MPS_INTPO_DEF:
                    832:        case MPS_INTPO_ACTHI:
                    833:                *redir &= ~IOAPIC_REDLO_ACTLO;
                    834:                break;
                    835:        case MPS_INTPO_ACTLO:
                    836:                *redir |= IOAPIC_REDLO_ACTLO;
                    837:                break;
                    838:        default:
                    839:                panic("unknown MPS interrupt polarity %d", mpspo);
                    840:        }
                    841:
                    842:        if (entry->int_type != MPS_INTTYPE_INT) {
                    843:                mp_cfg_special_intr(entry, redir);
                    844:                return;
                    845:        }
                    846:        *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
                    847:
                    848:        switch (mpstrig) {
                    849:        case MPS_INTTR_LEVEL:
                    850:                *redir |= IOAPIC_REDLO_LEVEL;
                    851:                break;
                    852:        case MPS_INTTR_DEF:
                    853:        case MPS_INTTR_EDGE:
                    854:                *redir &= ~IOAPIC_REDLO_LEVEL;
                    855:                break;
                    856:        default:
                    857:                panic("unknown MPS interrupt trigger %d", mpstrig);
                    858:        }
                    859: }
                    860:
                    861: void
                    862: mp_print_special_intr(int intr)
                    863: {
                    864: }
                    865:
                    866: void
                    867: mp_print_pci_intr(int intr)
                    868: {
                    869:        printf(" device %d INT_%c", (intr>>2)&0x1f, 'A' + (intr & 0x3));
                    870: }
                    871:
                    872: void
                    873: mp_print_isa_intr(int intr)
                    874: {
                    875:        printf(" irq %d", intr);
                    876: }
                    877:
                    878: #ifdef X86_MPBIOS_SUPPORT_EISA
                    879: void
                    880: mp_print_eisa_intr(int intr)
                    881: {
                    882:        printf(" EISA irq %d", intr);
                    883: }
                    884: #endif
                    885:
                    886:
                    887:
                    888: #define TAB_UNIT       4
                    889: #define TAB_ROUND(a)   _TAB_ROUND(a, TAB_UNIT)
                    890:
                    891: #define _TAB_ROUND(a,u)        (((a) + (u - 1)) & ~(u-1))
                    892: #define EXTEND_TAB(a,u)        (!(_TAB_ROUND(a,u) == _TAB_ROUND((a+1),u)))
                    893:
                    894: void
                    895: mpbios_bus(const u_int8_t *ent, struct device *self)
                    896: {
                    897:        const struct mpbios_bus *entry = (const struct mpbios_bus *)ent;
                    898:        int bus_id = entry->bus_id;
                    899:
                    900:        printf("mpbios: bus %d is type %6.6s\n", bus_id, entry->bus_type);
                    901:
                    902: #ifdef DIAGNOSTIC
                    903:        /*
                    904:         * This "should not happen" unless the table changes out
                    905:         * from underneath us
                    906:         */
                    907:        if (bus_id >= mp_nbus) {
                    908:                panic("mpbios: bus number %d out of range?? (type %6.6s)",
                    909:                    bus_id, entry->bus_type);
                    910:        }
                    911: #endif
                    912:
                    913:        mp_busses[bus_id].mb_intrs = NULL;
                    914:
                    915:        if (memcmp(entry->bus_type, "PCI   ", 6) == 0) {
                    916:                mp_busses[bus_id].mb_name = "pci";
                    917:                mp_busses[bus_id].mb_idx = bus_id;
                    918:                mp_busses[bus_id].mb_intr_print = mp_print_pci_intr;
                    919:                mp_busses[bus_id].mb_intr_cfg = mp_cfg_pci_intr;
                    920: #ifdef X86_MPBIOS_SUPPORT_EISA
                    921:        } else if (memcmp(entry->bus_type, "EISA  ", 6) == 0) {
                    922:                mp_busses[bus_id].mb_name = "eisa";
                    923:                mp_busses[bus_id].mb_idx = bus_id;
                    924:                mp_busses[bus_id].mb_intr_print = mp_print_eisa_intr;
                    925:                mp_busses[bus_id].mb_intr_cfg = mp_cfg_eisa_intr;
                    926:
                    927:                mp_busses[bus_id].mb_data =
                    928:                    inb(ELCR0) | (inb(ELCR1) << 8);
                    929:
                    930:                if (mp_eisa_bus)
                    931:                        printf("%s: multiple isa busses?\n",
                    932:                            self->dv_xname);
                    933:                else
                    934:                        mp_eisa_bus = &mp_busses[bus_id];
                    935: #endif
                    936:
                    937:        } else if (memcmp(entry->bus_type, "ISA   ", 6) == 0) {
                    938:                mp_busses[bus_id].mb_name = "isa";
                    939:                mp_busses[bus_id].mb_idx = bus_id;
                    940:                mp_busses[bus_id].mb_intr_print = mp_print_isa_intr;
                    941:                mp_busses[bus_id].mb_intr_cfg = mp_cfg_isa_intr;
                    942:                if (mp_isa_bus)
                    943:                        printf("%s: multiple isa busses?\n",
                    944:                            self->dv_xname);
                    945:                else
                    946:                        mp_isa_bus = &mp_busses[bus_id];
                    947:        } else {
                    948:                printf("%s: unsupported bus type %6.6s\n", self->dv_xname,
                    949:                    entry->bus_type);
                    950:        }
                    951: }
                    952:
                    953:
                    954: void
                    955: mpbios_ioapic(const u_int8_t *ent, struct device *self)
                    956: {
                    957:        const struct mpbios_ioapic *entry = (const struct mpbios_ioapic *)ent;
                    958:        struct apic_attach_args aaa;
                    959:
                    960:        /* XXX let flags checking happen in ioapic driver.. */
                    961:        if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
                    962:                return;
                    963:
                    964:        aaa.aaa_name   = "ioapic";
                    965:        aaa.apic_id = entry->apic_id;
                    966:        aaa.apic_version = entry->apic_version;
                    967:        aaa.apic_address = (paddr_t)entry->apic_address;
                    968:        aaa.apic_vecbase = -1;
                    969:        aaa.flags =  (mp_fps->mpfb2 & 0x80) ? IOAPIC_PICMODE : IOAPIC_VWIRE;
                    970:
                    971:        config_found_sm(self, &aaa, mp_print, mp_match);
                    972: }
                    973:
                    974: int
                    975: mpbios_int(const u_int8_t *ent, int enttype, struct mp_intr_map *mpi)
                    976: {
                    977:        const struct mpbios_int *entry = (const struct mpbios_int *)ent;
                    978:        struct ioapic_softc *sc = NULL, *sc2;
                    979:
                    980:        struct mp_intr_map *altmpi;
                    981:        struct mp_bus *mpb;
                    982:
                    983:        u_int32_t id = entry->dst_apic_id;
                    984:        u_int32_t pin = entry->dst_apic_int;
                    985:        u_int32_t bus = entry->src_bus_id;
                    986:        u_int32_t dev = entry->src_bus_irq;
                    987:        u_int32_t type = entry->int_type;
                    988:        u_int32_t flags = entry->int_flags;
                    989:
                    990:        switch (type) {
                    991:        case MPS_INTTYPE_INT:
                    992:                mpb = &(mp_busses[bus]);
                    993:                break;
                    994:        case MPS_INTTYPE_ExtINT:
                    995:                mpb = &extint_bus;
                    996:                break;
                    997:        case MPS_INTTYPE_SMI:
                    998:                mpb = &smi_bus;
                    999:                break;
                   1000:        case MPS_INTTYPE_NMI:
                   1001:                mpb = &nmi_bus;
                   1002:                break;
                   1003:        }
                   1004:        mpi->bus = mpb;
                   1005:        mpi->bus_pin = dev;
                   1006:        mpi->global_int = -1;
                   1007:
                   1008:        mpi->type = type;
                   1009:        mpi->flags = flags;
                   1010:        mpi->redir = 0;
                   1011:        if (mpb->mb_intr_cfg == NULL) {
                   1012:                printf("mpbios: can't find bus %d for apic %d pin %d\n",
                   1013:                    bus, id, pin);
                   1014:                return (1);
                   1015:        }
                   1016:
                   1017:        (*mpb->mb_intr_cfg)(entry, &mpi->redir);
                   1018:
                   1019:        if (enttype == MPS_MCT_IOINT) {
                   1020:                sc = ioapic_find(id);
                   1021:                if (sc == NULL) {
                   1022:                        printf("mpbios: can't find ioapic %d\n", id);
                   1023:                        return (1);
                   1024:                }
                   1025:
                   1026:                /*
                   1027:                 * XXX workaround for broken BIOSs that put the ACPI
                   1028:                 * global interrupt number in the entry, not the pin
                   1029:                 * number.
                   1030:                 */
                   1031:                if (pin >= sc->sc_apic_sz) {
                   1032:                        sc2 = ioapic_find_bybase(pin);
                   1033:                        if (sc2 != sc) {
                   1034:                                printf("mpbios: bad pin %d for apic %d\n",
                   1035:                                    pin, id);
                   1036:                                return (1);
                   1037:                        }
                   1038:                        printf("mpbios: WARNING: pin %d for apic %d too high; "
                   1039:                               "assuming ACPI global int value\n", pin, id);
                   1040:                        pin -= sc->sc_apic_vecbase;
                   1041:                }
                   1042:
                   1043:                mpi->ioapic = sc;
                   1044:                mpi->ioapic_pin = pin;
                   1045:
                   1046:                altmpi = sc->sc_pins[pin].ip_map;
                   1047:
                   1048:                if (altmpi != NULL) {
                   1049:                        if ((altmpi->type != type) ||
                   1050:                            (altmpi->flags != flags)) {
                   1051:                                printf("%s: conflicting map entries for pin %d\n",
                   1052:                                    sc->sc_pic.pic_dev.dv_xname, pin);
                   1053:                        }
                   1054:                } else {
                   1055:                        sc->sc_pins[pin].ip_map = mpi;
                   1056:                }
                   1057:        } else {
                   1058:                if (pin >= 2)
                   1059:                        printf("pin %d of local apic doesn't exist!\n", pin);
                   1060:                else {
                   1061:                        mpi->ioapic = NULL;
                   1062:                        mpi->ioapic_pin = pin;
                   1063:                        mpi->cpu_id = id;
                   1064:                }
                   1065:        }
                   1066:
                   1067:        mpi->ioapic_ih = APIC_INT_VIA_APIC |
                   1068:            ((id<<APIC_INT_APIC_SHIFT) | ((pin<<APIC_INT_PIN_SHIFT)));
                   1069:
                   1070:        if (mp_verbose) {
                   1071:
                   1072:                printf("%s: int%d attached to %s",
                   1073:                    sc ? sc->sc_pic.pic_dev.dv_xname : "local apic",
                   1074:                    pin, mpb->mb_name);
                   1075:
                   1076:                if (mpb->mb_idx != -1)
                   1077:                        printf("%d", mpb->mb_idx);
                   1078:
                   1079:                (*(mpb->mb_intr_print))(dev);
                   1080:
                   1081:                printf(" (type 0x%x flags 0x%x)\n", type, flags);
                   1082:        }
                   1083:
                   1084:        mpi->next = mpb->mb_intrs;
                   1085:        mpb->mb_intrs = mpi;
                   1086:
                   1087:        return (0);
                   1088: }

CVSweb