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

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

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

CVSweb