[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     ! 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