[BACK]Return to acpiprt.c CVS log [TXT][DIR] Up to [local] / sys / dev / acpi

Annotation of sys/dev/acpi/acpiprt.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: acpiprt.c,v 1.16 2007/02/23 00:04:40 jordan Exp $     */
                      2: /*
                      3:  * Copyright (c) 2006 Mark Kettenis <kettenis@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: #include <sys/param.h>
                     19: #include <sys/proc.h>
                     20: #include <sys/signalvar.h>
                     21: #include <sys/systm.h>
                     22: #include <sys/device.h>
                     23: #include <sys/malloc.h>
                     24:
                     25: #include <machine/bus.h>
                     26:
                     27: #include <dev/acpi/acpireg.h>
                     28: #include <dev/acpi/acpivar.h>
                     29: #include <dev/acpi/acpidev.h>
                     30: #include <dev/acpi/amltypes.h>
                     31: #include <dev/acpi/dsdt.h>
                     32:
                     33: #include <dev/pci/pcivar.h>
                     34: #include <dev/pci/ppbreg.h>
                     35:
                     36: #include <machine/i82093reg.h>
                     37: #include <machine/i82093var.h>
                     38:
                     39: #include <machine/mpbiosvar.h>
                     40:
                     41: #include "ioapic.h"
                     42:
                     43: int    acpiprt_match(struct device *, void *, void *);
                     44: void   acpiprt_attach(struct device *, struct device *, void *);
                     45: int    acpiprt_getirq(union acpi_resource *crs, void *arg);
                     46: int    acpiprt_getminbus(union acpi_resource *, void *);
                     47:
                     48:
                     49: struct acpiprt_softc {
                     50:        struct device           sc_dev;
                     51:
                     52:        struct acpi_softc       *sc_acpi;
                     53:        struct aml_node         *sc_devnode;
                     54:
                     55:        int                     sc_bus;
                     56: };
                     57:
                     58: struct cfattach acpiprt_ca = {
                     59:        sizeof(struct acpiprt_softc), acpiprt_match, acpiprt_attach
                     60: };
                     61:
                     62: struct cfdriver acpiprt_cd = {
                     63:        NULL, "acpiprt", DV_DULL
                     64: };
                     65:
                     66: void   acpiprt_prt_add(struct acpiprt_softc *, struct aml_value *);
                     67: int    acpiprt_getpcibus(struct acpiprt_softc *, struct aml_node *);
                     68:
                     69: int
                     70: acpiprt_match(struct device *parent, void *match, void *aux)
                     71: {
                     72:        struct acpi_attach_args *aa = aux;
                     73:        struct cfdata  *cf = match;
                     74:
                     75:        /* sanity */
                     76:        if (aa->aaa_name == NULL ||
                     77:            strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
                     78:            aa->aaa_table != NULL)
                     79:                return (0);
                     80:
                     81:        return (1);
                     82: }
                     83:
                     84: void
                     85: acpiprt_attach(struct device *parent, struct device *self, void *aux)
                     86: {
                     87:        struct acpiprt_softc *sc = (struct acpiprt_softc *)self;
                     88:        struct acpi_attach_args *aa = aux;
                     89:        struct aml_value res;
                     90:        int i;
                     91:
                     92:        sc->sc_acpi = (struct acpi_softc *)parent;
                     93:        sc->sc_devnode = aa->aaa_node;
                     94:        sc->sc_bus = acpiprt_getpcibus(sc, sc->sc_devnode);
                     95:
                     96:        printf(": bus %d (%s)", sc->sc_bus, sc->sc_devnode->parent->name);
                     97:
                     98:        if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PRT", 0, NULL, &res)) {
                     99:                printf(": no PCI interrupt routing table\n");
                    100:                return;
                    101:        }
                    102:
                    103:        if (res.type != AML_OBJTYPE_PACKAGE) {
                    104:                printf(": _PRT is not a package\n");
                    105:                aml_freevalue(&res);
                    106:                return;
                    107:        }
                    108:
                    109:        printf("\n");
                    110:
                    111:        if (sc->sc_bus == -1)
                    112:                return;
                    113:
                    114:        for (i = 0; i < res.length; i++)
                    115:                acpiprt_prt_add(sc, res.v_package[i]);
                    116:
                    117:        aml_freevalue(&res);
                    118: }
                    119:
                    120: int
                    121: acpiprt_getirq(union acpi_resource *crs, void *arg)
                    122: {
                    123:        int *irq = (int *)arg;
                    124:        int typ;
                    125:
                    126:        typ = AML_CRSTYPE(crs);
                    127:        switch (typ) {
                    128:        case SR_IRQ:
                    129:                *irq = ffs(aml_letohost16(crs->sr_irq.irq_mask)) - 1;
                    130:                break;
                    131:        case LR_EXTIRQ:
                    132:                *irq = aml_letohost32(crs->lr_extirq.irq[0]);
                    133:                break;
                    134:        default:
                    135:                printf("Unknown interrupt : %x\n", typ);
                    136:        }
                    137:        return (0);
                    138: }
                    139:
                    140: void
                    141: acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v)
                    142: {
                    143:        struct aml_node *node;
                    144:        struct aml_value res, *pp;
                    145:        u_int64_t addr;
                    146:        int pin, irq, sta;
                    147: #if NIOAPIC > 0
                    148:        struct mp_intr_map *map;
                    149:        struct ioapic_softc *apic;
                    150: #endif
                    151:        pci_chipset_tag_t pc = NULL;
                    152:        pcitag_t tag;
                    153:        pcireg_t reg;
                    154:        int bus, dev, func, nfuncs;
                    155:
                    156:        if (v->type != AML_OBJTYPE_PACKAGE || v->length != 4) {
                    157:                printf("invalid mapping object\n");
                    158:                return;
                    159:        }
                    160:
                    161:        addr = aml_val2int(v->v_package[0]);
                    162:        pin = aml_val2int(v->v_package[1]);
                    163:        if (pin > 3) {
                    164:                return;
                    165:        }
                    166:
                    167:        pp = v->v_package[2];
                    168:        if (pp->type == AML_OBJTYPE_NAMEREF) {
                    169:                node = aml_searchname(sc->sc_devnode, pp->v_nameref);
                    170:                if (node == NULL) {
                    171:                        printf("Invalid device!\n");
                    172:                        return;
                    173:                }
                    174:                pp = node->value;
                    175:        }
                    176:        if (pp->type == AML_OBJTYPE_OBJREF) {
                    177:                pp = pp->v_objref.ref;
                    178:        }
                    179:        if (pp->type == AML_OBJTYPE_DEVICE) {
                    180:                node = pp->node;
                    181:                if (aml_evalname(sc->sc_acpi, node, "_STA", 0, NULL, &res))
                    182:                        printf("no _STA method\n");
                    183:
                    184:                sta = aml_val2int(&res) & STA_ENABLED;
                    185:                aml_freevalue(&res);
                    186:                if (sta == 0)
                    187:                        return;
                    188:
                    189:                if (aml_evalname(sc->sc_acpi, node, "_CRS", 0, NULL, &res))
                    190:                        printf("no _CRS method\n");
                    191:
                    192:                if (res.type != AML_OBJTYPE_BUFFER || res.length < 6) {
                    193:                        printf("invalid _CRS object\n");
                    194:                        aml_freevalue(&res);
                    195:                        return;
                    196:                }
                    197:                aml_parse_resource(res.length, res.v_buffer,
                    198:                    acpiprt_getirq, &irq);
                    199:                aml_freevalue(&res);
                    200:        } else {
                    201:                irq = aml_val2int(v->v_package[3]);
                    202:        }
                    203:
                    204: #ifdef ACPI_DEBUG
                    205:        printf("%s: %s addr 0x%llx pin %d irq %d\n",
                    206:            DEVNAME(sc), aml_nodename(pp->node), addr, pin, irq);
                    207: #endif
                    208:
                    209: #if NIOAPIC > 0
                    210:        if (nioapics > 0) {
                    211:                apic = ioapic_find_bybase(irq);
                    212:                if (apic == NULL) {
                    213:                        printf("%s: no apic found for irq %d\n", DEVNAME(sc), irq);
                    214:                        return;
                    215:                }
                    216:
                    217:                map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
                    218:                if (map == NULL)
                    219:                        return;
                    220:
                    221:                memset(map, 0, sizeof *map);
                    222:                map->ioapic = apic;
                    223:                map->ioapic_pin = irq - apic->sc_apic_vecbase;
                    224:                map->bus_pin = ((addr >> 14) & 0x7c) | (pin & 0x3);
                    225:                map->redir = IOAPIC_REDLO_ACTLO | IOAPIC_REDLO_LEVEL;
                    226:                map->redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
                    227:
                    228:                map->ioapic_ih = APIC_INT_VIA_APIC |
                    229:                    ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
                    230:                    (map->ioapic_pin << APIC_INT_PIN_SHIFT));
                    231:
                    232:                apic->sc_pins[map->ioapic_pin].ip_map = map;
                    233:
                    234:                map->next = mp_busses[sc->sc_bus].mb_intrs;
                    235:                mp_busses[sc->sc_bus].mb_intrs = map;
                    236:
                    237:                return;
                    238:        }
                    239: #endif
                    240:
                    241:        bus = sc->sc_bus;
                    242:        dev = ACPI_PCI_DEV(addr << 16);
                    243:        tag = pci_make_tag(pc, bus, dev, 0);
                    244:
                    245:        reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
                    246:        if (PCI_HDRTYPE_MULTIFN(reg))
                    247:                nfuncs = 8;
                    248:        else
                    249:                nfuncs = 1;
                    250:
                    251:        for (func = 0; func < nfuncs; func++) {
                    252:                tag = pci_make_tag(pc, bus, dev, func);
                    253:                reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
                    254:                if (PCI_INTERRUPT_PIN(reg) == pin + 1) {
                    255:                        reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
                    256:                        reg |= irq << PCI_INTERRUPT_LINE_SHIFT;
                    257:                        pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
                    258:                }
                    259:        }
                    260: }
                    261:
                    262: int
                    263: acpiprt_getminbus(union acpi_resource *crs, void *arg)
                    264: {
                    265:        int *bbn = arg;
                    266:        int typ = AML_CRSTYPE(crs);
                    267:
                    268:        /* Check for embedded bus number */
                    269:        if (typ == LR_WORD && crs->lr_word.type == 2)
                    270:                *bbn = crs->lr_word._min;
                    271:        return 0;
                    272: }
                    273:
                    274: int
                    275: acpiprt_getpcibus(struct acpiprt_softc *sc, struct aml_node *node)
                    276: {
                    277:        struct aml_node *parent = node->parent;
                    278:        struct aml_value res;
                    279:        pci_chipset_tag_t pc = NULL;
                    280:        pcitag_t tag;
                    281:        pcireg_t reg;
                    282:        int bus, dev, func, rv;
                    283:
                    284:        if (parent == NULL)
                    285:                return 0;
                    286:
                    287:        if (aml_evalname(sc->sc_acpi, parent, "_ADR", 0, NULL, &res) == 0) {
                    288:                bus = acpiprt_getpcibus(sc, parent);
                    289:                dev = ACPI_PCI_DEV(aml_val2int(&res) << 16);
                    290:                func = ACPI_PCI_FN(aml_val2int(&res) << 16);
                    291:                aml_freevalue(&res);
                    292:
                    293:                /*
                    294:                 * Some systems return 255 as the device number for
                    295:                 * devices that are not really there.
                    296:                 */
                    297:                if (dev >= pci_bus_maxdevs(pc, bus))
                    298:                        return (-1);
                    299:
                    300:                tag = pci_make_tag(pc, bus, dev, func);
                    301:                reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
                    302:                if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
                    303:                    PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) {
                    304:                        reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
                    305:                        return (PPB_BUSINFO_SECONDARY(reg));
                    306:                }
                    307:        }
                    308:
                    309:        if (aml_evalname(sc->sc_acpi, parent, "_CRS", 0, NULL, &res) == 0) {
                    310:                rv = -1;
                    311:                if (res.type == AML_OBJTYPE_BUFFER)
                    312:                        aml_parse_resource(res.length, res.v_buffer,
                    313:                            acpiprt_getminbus, &rv);
                    314:                aml_freevalue(&res);
                    315:                if (rv != -1)
                    316:                        return rv;
                    317:        }
                    318:        if (aml_evalname(sc->sc_acpi, parent, "_BBN", 0, NULL, &res) == 0) {
                    319:                rv = aml_val2int(&res);
                    320:                aml_freevalue(&res);
                    321:                return (rv);
                    322:        }
                    323:
                    324:        return (0);
                    325: }

CVSweb