-# $OpenBSD: GENERIC,v 1.11 2021/05/12 01:20:52 jsg Exp $
+# $OpenBSD: GENERIC,v 1.12 2021/05/19 19:32:25 kettenis Exp $
#
# For further information on compiling OpenBSD kernels, see the config(8)
# man page.
include "../../../conf/GENERIC"
maxusers 32
+option PCIVERBOSE
+option USER_PCICONF
+
makeoptions KERNEL_BASE_PHYS="0x00200000"
makeoptions KERNEL_BASE_VIRT="0xffffffc000200000"
#option DEBUG
com* at fdt?
virtio* at fdt?
+virtio* at pci?
vio* at virtio? # Network
vioblk* at virtio?
vioscsi* at virtio? # Disk (SCSI)
dwmmc* at fdt?
sdmmc* at dwmmc?
+pciecam* at fdt?
+pci* at pciecam?
+
+# PCI
+ppb* at pci? # PCI-PCI bridges
+pci* at ppb?
+
scsibus* at scsi?
sd* at scsibus?
cd* at scsibus?
-# $OpenBSD: files.riscv64,v 1.9 2021/05/12 01:20:52 jsg Exp $
+# $OpenBSD: files.riscv64,v 1.10 2021/05/19 19:32:25 kettenis Exp $
# Standard stanzas config(8) can't run without
maxpartitions 16
file arch/riscv64/riscv64/db_interface.c ddb
file arch/riscv64/riscv64/db_trace.c ddb
+file arch/riscv64/dev/pci_machdep.c
+
pseudo-device openprom
file arch/riscv64/riscv64/openprom.c openprom needs-flag
# Machine-independent SCSI drivers
include "scsi/files.scsi"
+
+device pciecam: pcibus
+attach pciecam at fdt
+file dev/fdt/pciecam.c pciecam
--- /dev/null
+/* $OpenBSD: pci_machdep.c,v 1.1 2021/05/19 19:32:25 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2019 Mark Kettenis <kettenis@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+void
+pci_msi_enable(pci_chipset_tag_t pc, pcitag_t tag,
+ bus_addr_t addr, uint32_t data)
+{
+ pcireg_t reg;
+ int off;
+
+ if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®) == 0)
+ panic("%s: no msi capability", __func__);
+
+ if (reg & PCI_MSI_MC_C64) {
+ pci_conf_write(pc, tag, off + PCI_MSI_MA, addr);
+ pci_conf_write(pc, tag, off + PCI_MSI_MAU32, addr >> 32);
+ pci_conf_write(pc, tag, off + PCI_MSI_MD64, data);
+ } else {
+ pci_conf_write(pc, tag, off + PCI_MSI_MA, addr);
+ pci_conf_write(pc, tag, off + PCI_MSI_MD32, data);
+ }
+ pci_conf_write(pc, tag, off, reg | PCI_MSI_MC_MSIE);
+}
+
+int
+pci_msix_table_map(pci_chipset_tag_t pc, pcitag_t tag,
+ bus_space_tag_t memt, bus_space_handle_t *memh)
+{
+ bus_addr_t base;
+ pcireg_t reg, table, type;
+ int bir, offset;
+ int off, tblsz;
+
+ if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, ®) == 0)
+ panic("%s: no msix capability", __func__);
+
+ table = pci_conf_read(pc, tag, off + PCI_MSIX_TABLE);
+ bir = (table & PCI_MSIX_TABLE_BIR);
+ offset = (table & PCI_MSIX_TABLE_OFF);
+ tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1;
+
+ bir = PCI_MAPREG_START + bir * 4;
+ type = pci_mapreg_type(pc, tag, bir);
+ if (pci_mapreg_info(pc, tag, bir, type, &base, NULL, NULL) ||
+ bus_space_map(memt, base + offset, tblsz * 16, 0, memh))
+ return -1;
+
+ return 0;
+}
+
+void
+pci_msix_table_unmap(pci_chipset_tag_t pc, pcitag_t tag,
+ bus_space_tag_t memt, bus_space_handle_t memh)
+{
+ pcireg_t reg;
+ int tblsz;
+
+ if (pci_get_capability(pc, tag, PCI_CAP_MSIX, NULL, ®) == 0)
+ panic("%s: no msix capability", __func__);
+
+ tblsz = PCI_MSIX_MC_TBLSZ(reg) + 1;
+ bus_space_unmap(memt, memh, tblsz * 16);
+}
+
+void
+pci_msix_enable(pci_chipset_tag_t pc, pcitag_t tag, bus_space_tag_t memt,
+ int vec, bus_addr_t addr, uint32_t data)
+{
+ bus_space_handle_t memh;
+ pcireg_t reg;
+ uint32_t ctrl;
+ int off;
+
+ if (pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, ®) == 0)
+ panic("%s: no msix capability", __func__);
+
+ KASSERT(vec <= PCI_MSIX_MC_TBLSZ(reg));
+
+ if (pci_msix_table_map(pc, tag, memt, &memh))
+ panic("%s: cannot map registers", __func__);
+
+ bus_space_write_4(memt, memh, PCI_MSIX_MA(vec), addr);
+ bus_space_write_4(memt, memh, PCI_MSIX_MAU32(vec), addr >> 32);
+ bus_space_write_4(memt, memh, PCI_MSIX_MD(vec), data);
+ bus_space_barrier(memt, memh, PCI_MSIX_MA(vec), 16,
+ BUS_SPACE_BARRIER_WRITE);
+ ctrl = bus_space_read_4(memt, memh, PCI_MSIX_VC(vec));
+ bus_space_write_4(memt, memh, PCI_MSIX_VC(vec),
+ ctrl & ~PCI_MSIX_VC_MASK);
+
+ pci_msix_table_unmap(pc, tag, memt, memh);
+
+ pci_conf_write(pc, tag, off, reg | PCI_MSIX_MC_MSIXE);
+}
+
+int
+_pci_intr_map_msi(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
+{
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pcitag_t tag = pa->pa_tag;
+
+ if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
+ pci_get_capability(pc, tag, PCI_CAP_MSI, NULL, NULL) == 0)
+ return -1;
+
+ 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;
+}
+
+int
+_pci_intr_map_msix(struct pci_attach_args *pa, int vec,
+ pci_intr_handle_t *ihp)
+{
+ pci_chipset_tag_t pc = pa->pa_pc;
+ pcitag_t tag = pa->pa_tag;
+ pcireg_t reg, table, type;
+ int bir, off;
+
+ if ((pa->pa_flags & PCI_FLAGS_MSI_ENABLED) == 0 ||
+ pci_get_capability(pc, tag, PCI_CAP_MSIX, &off, ®) == 0)
+ return -1;
+
+ if (vec > PCI_MSIX_MC_TBLSZ(reg))
+ return -1;
+
+ table = pci_conf_read(pc, tag, off + PCI_MSIX_TABLE);
+ bir = PCI_MAPREG_START + (table & PCI_MSIX_TABLE_BIR) * 4;
+ type = pci_mapreg_type(pc, tag, bir);
+ if (pci_mapreg_assign(pa, bir, type, NULL, NULL))
+ return -1;
+
+ ihp->ih_pc = pa->pa_pc;
+ ihp->ih_tag = pa->pa_tag;
+ ihp->ih_intrpin = vec;
+ ihp->ih_type = PCI_MSIX;
+ ihp->ih_dmat = pa->pa_dmat;
+
+ return 0;
+}
+
--- /dev/null
+/* $OpenBSD: pci_machdep.h,v 1.1 2021/05/19 19:32:25 kettenis Exp $ */
+
+/*
+ * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+typedef struct machine_pci_chipset *pci_chipset_tag_t;
+typedef u_long pcitag_t;
+
+/* Supported interrupt types. */
+#define PCI_NONE 0
+#define PCI_INTX 1
+#define PCI_MSI 2
+#define PCI_MSIX 3
+
+typedef struct {
+ pci_chipset_tag_t ih_pc;
+ pcitag_t ih_tag;
+ int ih_intrpin;
+ int ih_type;
+ bus_dma_tag_t ih_dmat;
+} pci_intr_handle_t;
+
+struct pci_attach_args;
+
+/*
+ * Machine-specific PCI structure and type definitions.
+ * NOT TO BE USED DIRECTLY BY MACHINE INDEPENDENT CODE.
+ */
+struct machine_pci_chipset {
+ void *pc_conf_v;
+ void (*pc_attach_hook)(struct device *,
+ struct device *, struct pcibus_attach_args *);
+ int (*pc_bus_maxdevs)(void *, int);
+ pcitag_t (*pc_make_tag)(void *, int, int, int);
+ void (*pc_decompose_tag)(void *, pcitag_t, int *,
+ int *, int *);
+ int (*pc_conf_size)(void *, pcitag_t);
+ pcireg_t (*pc_conf_read)(void *, pcitag_t, int);
+ void (*pc_conf_write)(void *, pcitag_t, int, pcireg_t);
+ int (*pc_probe_device_hook)(void *, struct pci_attach_args *);
+
+ void *pc_intr_v;
+ int (*pc_intr_map)(struct pci_attach_args *,
+ pci_intr_handle_t *);
+ int (*pc_intr_map_msi)(struct pci_attach_args *,
+ pci_intr_handle_t *);
+ int (*pc_intr_map_msix)(struct pci_attach_args *,
+ int, pci_intr_handle_t *);
+ const char *(*pc_intr_string)(void *, pci_intr_handle_t);
+ void *(*pc_intr_establish)(void *, pci_intr_handle_t,
+ int, struct cpu_info *, int (*)(void *), void *,
+ char *);
+ void (*pc_intr_disestablish)(void *, void *);
+};
+
+/*
+ * Functions provided to machine-independent PCI code.
+ */
+#define pci_attach_hook(p, s, pba) \
+ (*(pba)->pba_pc->pc_attach_hook)((p), (s), (pba))
+#define pci_bus_maxdevs(c, b) \
+ (*(c)->pc_bus_maxdevs)((c)->pc_conf_v, (b))
+#define pci_make_tag(c, b, d, f) \
+ (*(c)->pc_make_tag)((c)->pc_conf_v, (b), (d), (f))
+#define pci_decompose_tag(c, t, bp, dp, fp) \
+ (*(c)->pc_decompose_tag)((c)->pc_conf_v, (t), (bp), (dp), (fp))
+#define pci_conf_size(c, t) \
+ (*(c)->pc_conf_size)((c)->pc_conf_v, (t))
+#define pci_conf_read(c, t, r) \
+ (*(c)->pc_conf_read)((c)->pc_conf_v, (t), (r))
+#define pci_conf_write(c, t, r, v) \
+ (*(c)->pc_conf_write)((c)->pc_conf_v, (t), (r), (v))
+#define pci_probe_device_hook(c, a) \
+ (*(c)->pc_probe_device_hook)((c)->pc_conf_v, (a))
+#define pci_intr_map(c, ihp) \
+ (*(c)->pa_pc->pc_intr_map)((c), (ihp))
+#define pci_intr_map_msi(c, ihp) \
+ (*(c)->pa_pc->pc_intr_map_msi)((c), (ihp))
+#define pci_intr_map_msix(c, vec, ihp) \
+ (*(c)->pa_pc->pc_intr_map_msix)((c), (vec), (ihp))
+#define pci_intr_string(c, ih) \
+ (*(c)->pc_intr_string)((c)->pc_intr_v, (ih))
+#define pci_intr_establish(c, ih, l, h, a, nm) \
+ (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), NULL, (h), (a),\
+ (nm))
+#define pci_intr_establish_cpu(c, ih, l, ci, h, a, nm) \
+ (*(c)->pc_intr_establish)((c)->pc_intr_v, (ih), (l), (ci), (h), (a),\
+ (nm))
+#define pci_intr_disestablish(c, iv) \
+ (*(c)->pc_intr_disestablish)((c)->pc_intr_v, (iv))
+
+#define pci_min_powerstate(c, t) (PCI_PMCSR_STATE_D3)
+#define pci_set_powerstate_md(c, t, s, p)
+
+#define pci_dev_postattach(a, b)
+
+void pci_mcfg_init(bus_space_tag_t, bus_addr_t, int, int, int);
+pci_chipset_tag_t pci_lookup_segment(int);
+
+void pci_msi_enable(pci_chipset_tag_t, pcitag_t, bus_addr_t, uint32_t);
+void pci_msix_enable(pci_chipset_tag_t, pcitag_t, bus_space_tag_t,
+ int, bus_addr_t, uint32_t);
+int _pci_intr_map_msi(struct pci_attach_args *, pci_intr_handle_t *);
+int _pci_intr_map_msix(struct pci_attach_args *, int, pci_intr_handle_t *);
+
+#define __HAVE_PCI_MSIX
+
+int pci_msix_table_map(pci_chipset_tag_t, pcitag_t,
+ bus_space_tag_t, bus_space_handle_t *);
+void pci_msix_table_unmap(pci_chipset_tag_t, pcitag_t,
+ bus_space_tag_t, bus_space_handle_t);