-/* $OpenBSD: acpipci.c,v 1.27 2021/03/15 22:48:57 patrick Exp $ */
+/* $OpenBSD: acpipci.c,v 1.28 2021/03/22 20:30:21 patrick Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis
*
uint32_t sc_seg;
};
+struct acpipci_intr_handle {
+ struct arm_intr_handle aih_ih;
+ bus_dma_tag_t aih_dmat;
+ bus_dmamap_t aih_map;
+};
+
int acpipci_match(struct device *, void *, void *);
void acpipci_attach(struct device *, struct device *, void *);
{
struct acpipci_softc *sc = v;
struct interrupt_controller *ic;
- struct arm_intr_handle *aih;
+ struct acpipci_intr_handle *aih;
+ bus_dma_segment_t seg;
void *cookie;
extern LIST_HEAD(, interrupt_controller) interrupt_controllers;
if (cookie == NULL)
return NULL;
- /* TODO: translate address to the PCI device's view */
+ aih = malloc(sizeof(*aih), M_DEVBUF, M_WAITOK);
+ aih->aih_ih.ih_ic = ic;
+ aih->aih_ih.ih_ih = cookie;
+ aih->aih_dmat = ih.ih_dmat;
+
+ if (bus_dmamap_create(aih->aih_dmat, sizeof(uint32_t), 1,
+ sizeof(uint32_t), 0, BUS_DMA_WAITOK, &aih->aih_map)) {
+ free(aih, M_DEVBUF, sizeof(*aih));
+ ic->ic_disestablish(cookie);
+ return NULL;
+ }
+
+ memset(&seg, 0, sizeof(seg));
+ seg.ds_addr = addr;
+ seg.ds_len = sizeof(uint32_t);
+ if (bus_dmamap_load_raw(aih->aih_dmat, aih->aih_map,
+ &seg, 1, sizeof(uint32_t), BUS_DMA_WAITOK)) {
+ bus_dmamap_destroy(aih->aih_dmat, aih->aih_map);
+ free(aih, M_DEVBUF, sizeof(*aih));
+ ic->ic_disestablish(cookie);
+ return NULL;
+ }
+
+ addr = aih->aih_map->dm_segs[0].ds_addr;
if (ih.ih_type == PCI_MSIX) {
pci_msix_enable(ih.ih_pc, ih.ih_tag,
&sc->sc_bus_memt, ih.ih_intrpin, addr, data);
} else
pci_msi_enable(ih.ih_pc, ih.ih_tag, addr, data);
- aih = malloc(sizeof(*aih), M_DEVBUF, M_WAITOK);
- aih->ih_ic = ic;
- aih->ih_ih = cookie;
cookie = aih;
} else {
if (ci != NULL && !CPU_IS_PRIMARY(ci))
void
acpipci_intr_disestablish(void *v, void *cookie)
{
- struct arm_intr_handle *aih = cookie;
- struct interrupt_controller *ic = aih->ih_ic;
-
- if (ic->ic_establish_msi)
- ic->ic_disestablish(aih->ih_ih);
- else
+ struct acpipci_intr_handle *aih = cookie;
+ struct interrupt_controller *ic = aih->aih_ih.ih_ic;
+
+ if (ic->ic_establish_msi) {
+ ic->ic_disestablish(aih->aih_ih.ih_ih);
+ bus_dmamap_unload(aih->aih_dmat, aih->aih_map);
+ bus_dmamap_destroy(aih->aih_dmat, aih->aih_map);
+ free(aih, M_DEVBUF, sizeof(*aih));
+ } else
acpi_intr_disestablish(cookie);
}
-/* $OpenBSD: pci_machdep.c,v 1.4 2019/06/25 16:46:32 kettenis Exp $ */
+/* $OpenBSD: pci_machdep.c,v 1.5 2021/03/22 20:30:21 patrick Exp $ */
/*
* Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
ihp->ih_pc = pa->pa_pc;
ihp->ih_tag = pa->pa_tag;
ihp->ih_type = PCI_MSI;
+ ihp->ih_dmat = pa->pa_dmat;
return 0;
}
ihp->ih_tag = pa->pa_tag;
ihp->ih_intrpin = vec;
ihp->ih_type = PCI_MSIX;
+ ihp->ih_dmat = pa->pa_dmat;
return 0;
}
-/* $OpenBSD: pciecam.c,v 1.13 2021/02/28 21:06:58 patrick Exp $ */
+/* $OpenBSD: pciecam.c,v 1.14 2021/03/22 20:30:21 patrick Exp $ */
/*
* Copyright (c) 2013,2017 Patrick Wildt <patrick@blueri.se>
*
struct arm64_pci_chipset sc_pc;
};
+struct pciecam_intr_handle {
+ struct arm_intr_handle pih_ih;
+ bus_dma_tag_t pih_dmat;
+ bus_dmamap_t pih_map;
+};
+
int pciecam_match(struct device *, void *, void *);
void pciecam_attach(struct device *, struct device *, void *);
void pciecam_attach_hook(struct device *, struct device *, struct pcibus_attach_args *);
int pciecam_bs_map(bus_space_tag_t, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
paddr_t pciecam_bs_mmap(bus_space_tag_t, bus_addr_t, off_t, int, int);
+struct interrupt_controller pciecam_ic = {
+ .ic_barrier = intr_barrier
+};
+
struct cfattach pciecam_ca = {
sizeof (struct pciecam_softc), pciecam_match, pciecam_attach
};
struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
{
struct pciecam_softc *sc = (struct pciecam_softc *)self;
+ struct pciecam_intr_handle *pih;
+ bus_dma_segment_t seg;
void *cookie;
KASSERT(ih.ih_type != PCI_NONE);
if (cookie == NULL)
return NULL;
- /* TODO: translate address to the PCI device's view */
+ pih = malloc(sizeof(*pih), M_DEVBUF, M_WAITOK);
+ pih->pih_ih.ih_ic = &pciecam_ic;
+ pih->pih_ih.ih_ih = cookie;
+ pih->pih_dmat = ih.ih_dmat;
+
+ if (bus_dmamap_create(pih->pih_dmat, sizeof(uint32_t), 1,
+ sizeof(uint32_t), 0, BUS_DMA_WAITOK, &pih->pih_map)) {
+ free(pih, M_DEVBUF, sizeof(*pih));
+ fdt_intr_disestablish(cookie);
+ return NULL;
+ }
+
+ memset(&seg, 0, sizeof(seg));
+ seg.ds_addr = addr;
+ seg.ds_len = sizeof(uint32_t);
+ if (bus_dmamap_load_raw(pih->pih_dmat, pih->pih_map,
+ &seg, 1, sizeof(uint32_t), BUS_DMA_WAITOK)) {
+ bus_dmamap_destroy(pih->pih_dmat, pih->pih_map);
+ free(pih, M_DEVBUF, sizeof(*pih));
+ fdt_intr_disestablish(cookie);
+ return NULL;
+ }
+
+ addr = pih->pih_map->dm_segs[0].ds_addr;
if (ih.ih_type == PCI_MSIX) {
pci_msix_enable(ih.ih_pc, ih.ih_tag,
&sc->sc_bus, ih.ih_intrpin, addr, data);
cookie = fdt_intr_establish_imap_cpu(sc->sc_node, reg,
sizeof(reg), level, ci, func, arg, name);
+ if (cookie == NULL)
+ return NULL;
+
+ pih = malloc(sizeof(*pih), M_DEVBUF, M_WAITOK);
+ pih->pih_ih.ih_ic = &pciecam_ic;
+ pih->pih_ih.ih_ih = cookie;
+ pih->pih_dmat = NULL;
}
- return cookie;
+ return pih;
}
void
pciecam_intr_disestablish(void *sc, void *cookie)
{
- /* do something */
+ struct pciecam_intr_handle *pih = cookie;
+
+ fdt_intr_disestablish(pih->pih_ih.ih_ih);
+ if (pih->pih_dmat) {
+ bus_dmamap_unload(pih->pih_dmat, pih->pih_map);
+ bus_dmamap_destroy(pih->pih_dmat, pih->pih_map);
+ }
+ free(pih, M_DEVBUF, sizeof(*pih));
}
/*
-/* $OpenBSD: pci_machdep.h,v 1.8 2021/02/25 23:07:48 patrick Exp $ */
+/* $OpenBSD: pci_machdep.h,v 1.9 2021/03/22 20:30:21 patrick Exp $ */
/*
* Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
pcitag_t ih_tag;
int ih_intrpin;
int ih_type;
+ bus_dma_tag_t ih_dmat;
} pci_intr_handle_t;
struct pci_attach_args;
-/* $OpenBSD: dwpcie.c,v 1.27 2021/03/01 21:03:24 patrick Exp $ */
+/* $OpenBSD: dwpcie.c,v 1.28 2021/03/22 20:30:21 patrick Exp $ */
/*
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
*
void *sc_ih;
};
+struct dwpcie_intr_handle {
+ struct arm_intr_handle pih_ih;
+ bus_dma_tag_t pih_dmat;
+ bus_dmamap_t pih_map;
+};
+
int dwpcie_match(struct device *, void *, void *);
void dwpcie_attach(struct device *, struct device *, void *);
int dwpcie_bs_memmap(bus_space_tag_t, bus_addr_t, bus_size_t, int,
bus_space_handle_t *);
+struct interrupt_controller dwpcie_ic = {
+ .ic_barrier = intr_barrier
+};
+
void
dwpcie_attach(struct device *parent, struct device *self, void *aux)
{
struct cpu_info *ci, int (*func)(void *), void *arg, char *name)
{
struct dwpcie_softc *sc = v;
+ struct dwpcie_intr_handle *pih;
+ bus_dma_segment_t seg;
void *cookie;
KASSERT(ih.ih_type != PCI_NONE);
if (cookie == NULL)
return NULL;
- /* TODO: translate address to the PCI device's view */
+ pih = malloc(sizeof(*pih), M_DEVBUF, M_WAITOK);
+ pih->pih_ih.ih_ic = &dwpcie_ic;
+ pih->pih_ih.ih_ih = cookie;
+ pih->pih_dmat = ih.ih_dmat;
+
+ if (bus_dmamap_create(pih->pih_dmat, sizeof(uint32_t), 1,
+ sizeof(uint32_t), 0, BUS_DMA_WAITOK, &pih->pih_map)) {
+ free(pih, M_DEVBUF, sizeof(*pih));
+ fdt_intr_disestablish(cookie);
+ return NULL;
+ }
+
+ memset(&seg, 0, sizeof(seg));
+ seg.ds_addr = addr;
+ seg.ds_len = sizeof(uint32_t);
+ if (bus_dmamap_load_raw(pih->pih_dmat, pih->pih_map,
+ &seg, 1, sizeof(uint32_t), BUS_DMA_WAITOK)) {
+ bus_dmamap_destroy(pih->pih_dmat, pih->pih_map);
+ free(pih, M_DEVBUF, sizeof(*pih));
+ fdt_intr_disestablish(cookie);
+ return NULL;
+ }
+
+ addr = pih->pih_map->dm_segs[0].ds_addr;
if (ih.ih_type == PCI_MSIX) {
pci_msix_enable(ih.ih_pc, ih.ih_tag,
&sc->sc_bus_memt, ih.ih_intrpin, addr, data);
cookie = fdt_intr_establish_imap_cpu(sc->sc_node, reg,
sizeof(reg), level, ci, func, arg, name);
+ if (cookie == NULL)
+ return NULL;
+
+ pih = malloc(sizeof(*pih), M_DEVBUF, M_WAITOK);
+ pih->pih_ih.ih_ic = &dwpcie_ic;
+ pih->pih_ih.ih_ih = cookie;
+ pih->pih_dmat = NULL;
}
- return cookie;
+ return pih;
}
void
dwpcie_intr_disestablish(void *v, void *cookie)
{
- panic("%s", __func__);
+ struct dwpcie_intr_handle *pih = cookie;
+
+ fdt_intr_disestablish(pih->pih_ih.ih_ih);
+ if (pih->pih_dmat) {
+ bus_dmamap_unload(pih->pih_dmat, pih->pih_map);
+ bus_dmamap_destroy(pih->pih_dmat, pih->pih_map);
+ }
+ free(pih, M_DEVBUF, sizeof(*pih));
}
int