acpipci.c revision 1.3
133965Sjdp/* $OpenBSD: acpipci.c,v 1.3 2018/07/28 13:59:08 kettenis Exp $ */ 278828Sobrien/* 3218822Sdim * Copyright (c) 2018 Mark Kettenis 433965Sjdp * 533965Sjdp * Permission to use, copy, modify, and distribute this software for any 633965Sjdp * purpose with or without fee is hereby granted, provided that the above 733965Sjdp * copyright notice and this permission notice appear in all copies. 833965Sjdp * 933965Sjdp * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1033965Sjdp * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1133965Sjdp * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1233965Sjdp * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1333965Sjdp * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1433965Sjdp * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1533965Sjdp * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1633965Sjdp */ 1733965Sjdp 1833965Sjdp#include <sys/param.h> 19218822Sdim#include <sys/device.h> 20218822Sdim#include <sys/extent.h> 2133965Sjdp#include <sys/malloc.h> 2233965Sjdp#include <sys/systm.h> 2333965Sjdp 2433965Sjdp#include <machine/bus.h> 2533965Sjdp 2633965Sjdp#include <dev/acpi/acpireg.h> 2733965Sjdp#include <dev/acpi/acpivar.h> 2877298Sobrien#include <dev/acpi/acpidev.h> 2933965Sjdp#include <dev/acpi/amltypes.h> 3033965Sjdp#include <dev/acpi/dsdt.h> 3133965Sjdp 3277298Sobrien#include <dev/pci/pcidevs.h> 3377298Sobrien#include <dev/pci/pcireg.h> 3477298Sobrien#include <dev/pci/pcivar.h> 3577298Sobrien#include <dev/pci/ppbreg.h> 3677298Sobrien 37130561Sobrienbus_addr_t pci_mcfg_addr; 38130561Sobrienint pci_mcfg_min_bus, pci_mcfg_max_bus; 3933965Sjdpbus_space_tag_t pci_mcfgt; 4033965Sjdpbus_space_handle_t pci_mcfgh; 4133965Sjdp 4233965Sjdpstruct acpipci_trans { 4333965Sjdp struct acpipci_trans *at_next; 4433965Sjdp bus_space_tag_t at_iot; 4533965Sjdp bus_addr_t at_base; 4633965Sjdp bus_size_t at_size; 4733965Sjdp bus_size_t at_offset; 4833965Sjdp}; 4960484Sobrien 5060484Sobrienstruct acpipci_softc { 5160484Sobrien struct device sc_dev; 5260484Sobrien struct acpi_softc *sc_acpi; 5360484Sobrien struct aml_node *sc_node; 5460484Sobrien 5560484Sobrien bus_space_tag_t sc_iot; 5660484Sobrien bus_space_handle_t sc_ioh; 5760484Sobrien 5833965Sjdp struct bus_space sc_bus_iot; 5933965Sjdp struct bus_space sc_bus_memt; 6033965Sjdp struct acpipci_trans *sc_io_trans; 6133965Sjdp struct acpipci_trans *sc_mem_trans; 6233965Sjdp 6333965Sjdp struct arm64_pci_chipset sc_pc; 6433965Sjdp struct extent *sc_busex; 6533965Sjdp struct extent *sc_memex; 6633965Sjdp struct extent *sc_ioex; 6733965Sjdp char sc_busex_name[32]; 6833965Sjdp char sc_ioex_name[32]; 6933965Sjdp char sc_memex_name[32]; 7033965Sjdp int sc_bus; 7133965Sjdp}; 7233965Sjdp 7333965Sjdpint acpipci_match(struct device *, void *, void *); 7433965Sjdpvoid acpipci_attach(struct device *, struct device *, void *); 7533965Sjdp 7633965Sjdpstruct cfattach acpipci_ca = { 7733965Sjdp sizeof(struct acpipci_softc), acpipci_match, acpipci_attach 7833965Sjdp}; 7933965Sjdp 8033965Sjdpstruct cfdriver acpipci_cd = { 8133965Sjdp NULL, "acpipci", DV_DULL 8233965Sjdp}; 83130561Sobrien 8433965Sjdpconst char *acpipci_hids[] = { 8533965Sjdp "PNP0A08", 8633965Sjdp NULL 8738889Sjdp}; 8838889Sjdp 8938889Sjdpint acpipci_parse_resources(int, union acpi_resource *, void *); 9038889Sjdpint acpipci_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, 9133965Sjdp bus_space_handle_t *); 9233965Sjdp 9333965Sjdpvoid acpipci_attach_hook(struct device *, struct device *, 9433965Sjdp struct pcibus_attach_args *); 9533965Sjdpint acpipci_bus_maxdevs(void *, int); 9633965Sjdppcitag_t acpipci_make_tag(void *, int, int, int); 9738889Sjdpvoid acpipci_decompose_tag(void *, pcitag_t, int *, int *, int *); 9838889Sjdpint acpipci_conf_size(void *, pcitag_t); 9933965Sjdppcireg_t acpipci_conf_read(void *, pcitag_t, int); 10038889Sjdpvoid acpipci_conf_write(void *, pcitag_t, int, pcireg_t); 10138889Sjdp 10233965Sjdpint acpipci_intr_map(struct pci_attach_args *, pci_intr_handle_t *); 10338889Sjdpint acpipci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *); 10438889Sjdpint acpipci_intr_map_msix(struct pci_attach_args *, int, 10538889Sjdp pci_intr_handle_t *); 10638889Sjdpconst char *acpipci_intr_string(void *, pci_intr_handle_t); 10738889Sjdpvoid *acpipci_intr_establish(void *, pci_intr_handle_t, int, 10838889Sjdp int (*)(void *), void *, char *); 10938889Sjdpvoid acpipci_intr_disestablish(void *, void *); 11038889Sjdp 11138889Sjdpint 11238889Sjdpacpipci_match(struct device *parent, void *match, void *aux) 11338889Sjdp{ 11433965Sjdp struct acpi_attach_args *aaa = aux; 11538889Sjdp struct cfdata *cf = match; 11677298Sobrien 11733965Sjdp return acpi_matchhids(aaa, acpipci_hids, cf->cf_driver->cd_name); 11833965Sjdp} 11933965Sjdp 12033965Sjdpvoid 12133965Sjdpacpipci_attach(struct device *parent, struct device *self, void *aux) 12238889Sjdp{ 12338889Sjdp struct acpi_attach_args *aaa = aux; 12433965Sjdp struct acpipci_softc *sc = (struct acpipci_softc *)self; 12538889Sjdp struct pcibus_attach_args pba; 12638889Sjdp struct aml_value res; 12733965Sjdp uint64_t bbn = 0; 12833965Sjdp 12933965Sjdp /* Bail out early if we don't have a valid MCFG table. */ 13033965Sjdp if (pci_mcfg_addr == 0 || pci_mcfg_max_bus <= pci_mcfg_min_bus) { 13133965Sjdp printf(": no registers\n"); 13233965Sjdp return; 13333965Sjdp } 13433965Sjdp 13577298Sobrien sc->sc_acpi = (struct acpi_softc *)parent; 13677298Sobrien sc->sc_node = aaa->aaa_node; 13733965Sjdp printf(" %s", sc->sc_node->name); 13833965Sjdp 13933965Sjdp if (aml_evalname(sc->sc_acpi, sc->sc_node, "_CRS", 0, NULL, &res)) { 14033965Sjdp printf(": can't find resources\n"); 14133965Sjdp return; 14233965Sjdp } 14333965Sjdp 14433965Sjdp aml_evalinteger(sc->sc_acpi, sc->sc_node, "_BBN", 0, NULL, &bbn); 14533965Sjdp sc->sc_bus = bbn; 14633965Sjdp 14733965Sjdp sc->sc_iot = pci_mcfgt; 14833965Sjdp sc->sc_ioh = pci_mcfgh; 14933965Sjdp 15033965Sjdp printf("\n"); 151218822Sdim 15233965Sjdp /* Create extents for our address spaces. */ 15333965Sjdp snprintf(sc->sc_busex_name, sizeof(sc->sc_busex_name), 15433965Sjdp "%s pcibus", sc->sc_dev.dv_xname); 15533965Sjdp snprintf(sc->sc_ioex_name, sizeof(sc->sc_ioex_name), 15633965Sjdp "%s pciio", sc->sc_dev.dv_xname); 15733965Sjdp snprintf(sc->sc_memex_name, sizeof(sc->sc_memex_name), 15833965Sjdp "%s pcimem", sc->sc_dev.dv_xname); 15933965Sjdp sc->sc_busex = extent_create(sc->sc_busex_name, 0, 255, 16033965Sjdp M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 16160484Sobrien sc->sc_ioex = extent_create(sc->sc_ioex_name, 0, 0xffffffff, 16233965Sjdp M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 16333965Sjdp sc->sc_memex = extent_create(sc->sc_memex_name, 0, (u_long)-1, 16433965Sjdp M_DEVBUF, NULL, 0, EX_WAITOK | EX_FILLED); 16533965Sjdp 16633965Sjdp aml_parse_resource(&res, acpipci_parse_resources, sc); 16733965Sjdp 16833965Sjdp memcpy(&sc->sc_bus_iot, sc->sc_iot, sizeof(sc->sc_bus_iot)); 16933965Sjdp sc->sc_bus_iot.bus_private = sc->sc_io_trans; 17033965Sjdp sc->sc_bus_iot._space_map = acpipci_bs_map; 17133965Sjdp memcpy(&sc->sc_bus_memt, sc->sc_iot, sizeof(sc->sc_bus_memt)); 17233965Sjdp sc->sc_bus_memt.bus_private = sc->sc_mem_trans; 17333965Sjdp sc->sc_bus_memt._space_map = acpipci_bs_map; 17477298Sobrien 17533965Sjdp sc->sc_pc.pc_conf_v = sc; 17677298Sobrien sc->sc_pc.pc_attach_hook = acpipci_attach_hook; 177130561Sobrien sc->sc_pc.pc_bus_maxdevs = acpipci_bus_maxdevs; 17833965Sjdp sc->sc_pc.pc_make_tag = acpipci_make_tag; 17933965Sjdp sc->sc_pc.pc_decompose_tag = acpipci_decompose_tag; 18078828Sobrien sc->sc_pc.pc_conf_size = acpipci_conf_size; 18133965Sjdp sc->sc_pc.pc_conf_read = acpipci_conf_read; 18233965Sjdp sc->sc_pc.pc_conf_write = acpipci_conf_write; 18333965Sjdp 18433965Sjdp sc->sc_pc.pc_intr_v = sc; 18533965Sjdp sc->sc_pc.pc_intr_map = acpipci_intr_map; 18633965Sjdp sc->sc_pc.pc_intr_map_msi = acpipci_intr_map_msi; 18733965Sjdp sc->sc_pc.pc_intr_map_msix = acpipci_intr_map_msix; 18833965Sjdp sc->sc_pc.pc_intr_string = acpipci_intr_string; 18933965Sjdp sc->sc_pc.pc_intr_establish = acpipci_intr_establish; 19033965Sjdp sc->sc_pc.pc_intr_disestablish = acpipci_intr_disestablish; 19133965Sjdp 19233965Sjdp memset(&pba, 0, sizeof(pba)); 19333965Sjdp pba.pba_busname = "pci"; 19478828Sobrien pba.pba_iot = &sc->sc_bus_iot; 19578828Sobrien pba.pba_memt = &sc->sc_bus_memt; 19678828Sobrien pba.pba_dmat = aaa->aaa_dmat; 19778828Sobrien pba.pba_pc = &sc->sc_pc; 19833965Sjdp pba.pba_busex = sc->sc_busex; 19933965Sjdp pba.pba_ioex = sc->sc_ioex; 20033965Sjdp pba.pba_memex = sc->sc_memex; 20133965Sjdp pba.pba_domain = pci_ndomains++; 20233965Sjdp pba.pba_bus = sc->sc_bus; 20378828Sobrien pba.pba_flags |= PCI_FLAGS_MSI_ENABLED; 20478828Sobrien 20578828Sobrien config_found(self, &pba, NULL); 20678828Sobrien} 20733965Sjdp 20833965Sjdpint 20933965Sjdpacpipci_parse_resources(int crsidx, union acpi_resource *crs, void *arg) 21033965Sjdp{ 21133965Sjdp struct acpipci_softc *sc = arg; 21289857Sobrien struct acpipci_trans *at; 21333965Sjdp int type = AML_CRSTYPE(crs); 21433965Sjdp int restype, tflags; 21533965Sjdp u_long min, len = 0, tra; 21633965Sjdp 21733965Sjdp switch (type) { 21833965Sjdp case LR_WORD: 21933965Sjdp restype = crs->lr_word.type; 22089857Sobrien tflags = crs->lr_word.tflags; 22133965Sjdp min = crs->lr_word._min; 22233965Sjdp len = crs->lr_word._len; 22333965Sjdp tra = crs->lr_word._tra; 22433965Sjdp break; 22533965Sjdp case LR_DWORD: 22633965Sjdp restype = crs->lr_dword.type; 22733965Sjdp tflags = crs->lr_dword.tflags; 22889857Sobrien min = crs->lr_dword._min; 22933965Sjdp len = crs->lr_dword._len; 23033965Sjdp tra = crs->lr_dword._tra; 23133965Sjdp break; 23233965Sjdp case LR_QWORD: 23333965Sjdp restype = crs->lr_qword.type; 23433965Sjdp tflags = crs->lr_qword.tflags; 23599461Sobrien min = crs->lr_qword._min; 23699461Sobrien len = crs->lr_qword._len; 23799461Sobrien tra = crs->lr_qword._tra; 23899461Sobrien break; 23999461Sobrien } 24099461Sobrien 24199461Sobrien if (len == 0) 242104834Sobrien return 0; 24333965Sjdp 24433965Sjdp switch (restype) { 24533965Sjdp case LR_TYPE_MEMORY: 24633965Sjdp if (tflags & LR_MEMORY_TTP) 24789857Sobrien return 0; 24833965Sjdp extent_free(sc->sc_memex, min, len, EX_WAITOK); 24933965Sjdp at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 25033965Sjdp at->at_iot = sc->sc_iot; 25133965Sjdp at->at_base = min; 25233965Sjdp at->at_size = len; 25333965Sjdp at->at_offset = tra; 25433965Sjdp at->at_next = sc->sc_mem_trans; 25533965Sjdp sc->sc_mem_trans = at; 25633965Sjdp break; 25733965Sjdp case LR_TYPE_IO: 25833965Sjdp if ((tflags & LR_IO_TTP) == 0) 25933965Sjdp return 0; 26033965Sjdp extent_free(sc->sc_ioex, min, len, EX_WAITOK); 26133965Sjdp at = malloc(sizeof(struct acpipci_trans), M_DEVBUF, M_WAITOK); 26233965Sjdp at->at_iot = sc->sc_iot; 26333965Sjdp at->at_base = min; 26433965Sjdp at->at_size = len; 26533965Sjdp at->at_offset = tra; 26633965Sjdp at->at_next = sc->sc_io_trans; 26733965Sjdp sc->sc_io_trans = at; 26833965Sjdp break; 26933965Sjdp case LR_TYPE_BUS: 27033965Sjdp extent_free(sc->sc_busex, min, len, EX_WAITOK); 27133965Sjdp break; 27233965Sjdp } 27333965Sjdp 27433965Sjdp return 0; 27533965Sjdp} 27633965Sjdp 27733965Sjdpvoid 27833965Sjdpacpipci_attach_hook(struct device *parent, struct device *self, 27933965Sjdp struct pcibus_attach_args *pba) 28033965Sjdp{ 28133965Sjdp} 28233965Sjdp 28333965Sjdpint 28433965Sjdpacpipci_bus_maxdevs(void *v, int bus) 28533965Sjdp{ 28633965Sjdp return 32; 28733965Sjdp} 28833965Sjdp 28933965Sjdppcitag_t 29033965Sjdpacpipci_make_tag(void *v, int bus, int device, int function) 29133965Sjdp{ 29233965Sjdp return ((bus << 20) | (device << 15) | (function << 12)); 29333965Sjdp} 29433965Sjdp 29533965Sjdpvoid 29633965Sjdpacpipci_decompose_tag(void *v, pcitag_t tag, int *bp, int *dp, int *fp) 29733965Sjdp{ 29833965Sjdp if (bp != NULL) 29933965Sjdp *bp = (tag >> 20) & 0xff; 30033965Sjdp if (dp != NULL) 30133965Sjdp *dp = (tag >> 15) & 0x1f; 30233965Sjdp if (fp != NULL) 30333965Sjdp *fp = (tag >> 12) & 0x7; 30433965Sjdp} 30533965Sjdp 30633965Sjdpint 30733965Sjdpacpipci_conf_size(void *v, pcitag_t tag) 30833965Sjdp{ 30933965Sjdp return PCIE_CONFIG_SPACE_SIZE; 31033965Sjdp} 31133965Sjdp 31260484Sobrienpcireg_t 31360484Sobrienacpipci_conf_read(void *v, pcitag_t tag, int reg) 31460484Sobrien{ 31560484Sobrien struct acpipci_softc *sc = v; 31633965Sjdp 31733965Sjdp return bus_space_read_4(sc->sc_iot, sc->sc_ioh, tag | reg); 31833965Sjdp} 31933965Sjdp 32033965Sjdpvoid 32133965Sjdpacpipci_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 32233965Sjdp{ 32333965Sjdp struct acpipci_softc *sc = v; 32433965Sjdp 32533965Sjdp bus_space_write_4(sc->sc_iot, sc->sc_ioh, tag | reg, data); 32633965Sjdp} 32733965Sjdp 32833965Sjdpstruct acpipci_intr_handle { 32933965Sjdp pci_chipset_tag_t ih_pc; 33033965Sjdp pcitag_t ih_tag; 33133965Sjdp int ih_intrpin; 33233965Sjdp int ih_msi; 33333965Sjdp}; 33433965Sjdp 33533965Sjdpint 33633965Sjdpacpipci_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 33733965Sjdp{ 33833965Sjdp struct acpipci_softc *sc = pa->pa_pc->pc_intr_v; 33933965Sjdp struct aml_node *node; 34033965Sjdp struct aml_value res; 34133965Sjdp uint64_t addr, pin, source, index; 34233965Sjdp struct acpipci_intr_handle *ih; 34378828Sobrien int i; 344104834Sobrien 34578828Sobrien if (pa->pa_bridgetag == NULL) 34633965Sjdp return -1; 34733965Sjdp 34833965Sjdp node = acpi_find_pci(pa->pa_pc, *pa->pa_bridgetag); 34933965Sjdp if (node == NULL) 35033965Sjdp return -1; 35133965Sjdp 35233965Sjdp if (aml_evalname(sc->sc_acpi, node, "_PRT", 0, NULL, &res)) 35333965Sjdp return -1; 35433965Sjdp 35533965Sjdp if (res.type != AML_OBJTYPE_PACKAGE) 35633965Sjdp return -1; 35733965Sjdp 35833965Sjdp for (i = 0; i < res.length; i++) { 35933965Sjdp struct aml_value *val = res.v_package[i]; 36033965Sjdp 36133965Sjdp if (val->type != AML_OBJTYPE_PACKAGE) 36233965Sjdp continue; 36333965Sjdp if (val->length != 4) 36433965Sjdp continue; 36533965Sjdp if (val->v_package[0]->type != AML_OBJTYPE_INTEGER || 36633965Sjdp val->v_package[1]->type != AML_OBJTYPE_INTEGER || 36733965Sjdp val->v_package[2]->type != AML_OBJTYPE_INTEGER || 368130561Sobrien val->v_package[3]->type != AML_OBJTYPE_INTEGER) 36933965Sjdp continue; 37033965Sjdp 37133965Sjdp addr = val->v_package[0]->v_integer; 37233965Sjdp pin = val->v_package[1]->v_integer; 37333965Sjdp source = val->v_package[2]->v_integer; 37433965Sjdp index = val->v_package[3]->v_integer; 37533965Sjdp if (ACPI_ADR_PCIDEV(addr) != pa->pa_device || 37633965Sjdp ACPI_ADR_PCIFUN(addr) != 0xffff || 37733965Sjdp pin != pa->pa_intrpin - 1 || source != 0) 37833965Sjdp continue; 37933965Sjdp 38033965Sjdp ih = malloc(sizeof(struct acpipci_intr_handle), 38133965Sjdp M_DEVBUF, M_WAITOK); 38233965Sjdp ih->ih_pc = pa->pa_pc; 38333965Sjdp ih->ih_tag = pa->pa_tag; 38433965Sjdp ih->ih_intrpin = index; 38533965Sjdp ih->ih_msi = 0; 38633965Sjdp *ihp = (pci_intr_handle_t)ih; 38733965Sjdp 38833965Sjdp return 0; 38933965Sjdp } 39033965Sjdp 39133965Sjdp return -1; 39233965Sjdp} 39333965Sjdp 39433965Sjdpint 39577298Sobrienacpipci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp) 39633965Sjdp{ 39733965Sjdp pci_chipset_tag_t pc = pa->pa_pc; 398130561Sobrien pcitag_t tag = pa->pa_tag; 39933965Sjdp struct acpipci_intr_handle *ih; 40033965Sjdp 40133965Sjdp if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 || 40233965Sjdp pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0) 40377298Sobrien return -1; 40433965Sjdp 40533965Sjdp ih = malloc(sizeof(struct acpipci_intr_handle), M_DEVBUF, M_WAITOK); 406130561Sobrien ih->ih_pc = pa->pa_pc; 40733965Sjdp ih->ih_tag = pa->pa_tag; 40833965Sjdp ih->ih_intrpin = pa->pa_intrpin; 40933965Sjdp ih->ih_msi = 1; 41033965Sjdp *ihp = (pci_intr_handle_t)ih; 41133965Sjdp 41233965Sjdp return 0; 41333965Sjdp} 41433965Sjdp 41533965Sjdpint 41633965Sjdpacpipci_intr_map_msix(struct pci_attach_args *pa, int vec, 41733965Sjdp pci_intr_handle_t *ihp) 41833965Sjdp{ 41933965Sjdp return -1; 42033965Sjdp} 42160484Sobrien 42233965Sjdpconst char * 42333965Sjdpacpipci_intr_string(void *v, pci_intr_handle_t ihp) 42433965Sjdp{ 42533965Sjdp struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp; 42633965Sjdp static char irqstr[32]; 42733965Sjdp 42833965Sjdp if (ih->ih_msi) 42933965Sjdp return "msi"; 43033965Sjdp 43133965Sjdp snprintf(irqstr, sizeof(irqstr), "irq %d", ih->ih_intrpin); 43233965Sjdp return irqstr; 43333965Sjdp} 43433965Sjdp 43533965Sjdpvoid * 43633965Sjdpacpipci_intr_establish(void *v, pci_intr_handle_t ihp, int level, 43733965Sjdp int (*func)(void *), void *arg, char *name) 43833965Sjdp{ 43933965Sjdp struct acpipci_intr_handle *ih = (struct acpipci_intr_handle *)ihp; 44033965Sjdp struct interrupt_controller *ic; 44133965Sjdp void *cookie; 44233965Sjdp 44333965Sjdp extern LIST_HEAD(, interrupt_controller) interrupt_controllers; 44433965Sjdp LIST_FOREACH(ic, &interrupt_controllers, ic_list) { 44533965Sjdp if (ic->ic_establish_msi) 44633965Sjdp break; 44733965Sjdp } 44877298Sobrien if (ic == NULL) 44933965Sjdp return NULL; 45077298Sobrien 45133965Sjdp if (ih->ih_msi) { 45233965Sjdp uint64_t addr, data; 45333965Sjdp pcireg_t reg; 45433965Sjdp int off; 45533965Sjdp 45633965Sjdp cookie = ic->ic_establish_msi(ic->ic_cookie, &addr, 45733965Sjdp &data, level, func, arg, name); 45833965Sjdp if (cookie == NULL) 45933965Sjdp return NULL; 46033965Sjdp 46133965Sjdp /* TODO: translate address to the PCI device's view */ 46233965Sjdp 46333965Sjdp if (pci_get_capability(ih->ih_pc, ih->ih_tag, PCI_CAP_MSI, 46433965Sjdp &off, ®) == 0) 46533965Sjdp panic("%s: no msi capability", __func__); 46689857Sobrien 46733965Sjdp if (reg & PCI_MSI_MC_C64) { 46833965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 46933965Sjdp off + PCI_MSI_MA, addr); 47033965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 47133965Sjdp off + PCI_MSI_MAU32, addr >> 32); 47233965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 47333965Sjdp off + PCI_MSI_MD64, data); 47433965Sjdp } else { 47533965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 47633965Sjdp off + PCI_MSI_MA, addr); 47733965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 47833965Sjdp off + PCI_MSI_MD32, data); 47933965Sjdp } 48033965Sjdp pci_conf_write(ih->ih_pc, ih->ih_tag, 48133965Sjdp off, reg | PCI_MSI_MC_MSIE); 48233965Sjdp } else { 48338889Sjdp cookie = acpi_intr_establish(ih->ih_intrpin, 0, level, 48460484Sobrien func, arg, name); 48538889Sjdp } 48638889Sjdp 487130561Sobrien free(ih, M_DEVBUF, sizeof(struct acpipci_intr_handle)); 48838889Sjdp return cookie; 48960484Sobrien} 49060484Sobrien 49160484Sobrienvoid 49260484Sobrienacpipci_intr_disestablish(void *v, void *cookie) 493130561Sobrien{ 494130561Sobrien panic("%s", __func__); 495130561Sobrien} 496130561Sobrien 497130561Sobrien/* 498130561Sobrien * Translate memory address if needed. 499130561Sobrien */ 500130561Sobrienint 501130561Sobrienacpipci_bs_map(bus_space_tag_t t, bus_addr_t addr, bus_size_t size, 50260484Sobrien int flags, bus_space_handle_t *bshp) 50360484Sobrien{ 50460484Sobrien struct acpipci_trans *at; 50560484Sobrien 50660484Sobrien for (at = t->bus_private; at; at = at->at_next) { 50760484Sobrien if (addr >= at->at_base && addr < at->at_base + at->at_size) { 50860484Sobrien return bus_space_map(at->at_iot, 509130561Sobrien addr + at->at_offset, size, flags, bshp); 51060484Sobrien } 51138889Sjdp } 51260484Sobrien 51338889Sjdp return ENXIO; 51438889Sjdp} 51577298Sobrien 51677298Sobrienstruct arm64_pci_chipset pci_mcfg_chipset; 51777298Sobrien 518130561Sobrienpcireg_t 51938889Sjdppci_mcfg_conf_read(void *v, pcitag_t tag, int reg) 52077298Sobrien{ 52177298Sobrien return bus_space_read_4(pci_mcfgt, pci_mcfgh, tag | reg); 52277298Sobrien} 52377298Sobrien 52438889Sjdpvoid 52538889Sjdppci_mcfg_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) 52638889Sjdp{ 52738889Sjdp bus_space_write_4(pci_mcfgt, pci_mcfgh, tag | reg, data); 52838889Sjdp} 52938889Sjdp 53077298Sobrienpci_chipset_tag_t 53177298Sobrienpci_mcfg_init(bus_space_tag_t iot, bus_addr_t addr, int min_bus, int max_bus) 53277298Sobrien{ 53377298Sobrien pci_chipset_tag_t pc = &pci_mcfg_chipset; 53477298Sobrien 53577298Sobrien pci_mcfgt = iot; 53677298Sobrien pci_mcfg_addr = addr; 53777298Sobrien pci_mcfg_min_bus = min_bus; 53877298Sobrien pci_mcfg_max_bus = max_bus; 53977298Sobrien 54077298Sobrien if (bus_space_map(iot, addr, (pci_mcfg_max_bus + 1) << 20, 0, 54138889Sjdp &pci_mcfgh)) 54277298Sobrien panic("%s: can't map config space", __func__); 54389857Sobrien 54438889Sjdp memset(pc, 0, sizeof(*pc)); 54577298Sobrien pc->pc_bus_maxdevs = acpipci_bus_maxdevs; 54677298Sobrien pc->pc_make_tag = acpipci_make_tag; 54777298Sobrien pc->pc_decompose_tag = acpipci_decompose_tag; 54877298Sobrien pc->pc_conf_size = acpipci_conf_size; 54960484Sobrien pc->pc_conf_read = pci_mcfg_conf_read; 55077298Sobrien pc->pc_conf_write = pci_mcfg_conf_write; 55177298Sobrien 55238889Sjdp return pc; 55377298Sobrien} 55477298Sobrien