From 4fc22f9295061d17e11828af625d9f92aabfb4a5 Mon Sep 17 00:00:00 2001
From: Ian Moffett <ian@osmora.org>
Date: Thu, 28 Mar 2024 19:49:47 -0400
Subject: kernel: pci: Add pci_writel()

Signed-off-by: Ian Moffett <ian@osmora.org>
---
 sys/dev/pci/pci.c         | 45 +++++++++++++++++++++++++++++++++++++++++++++
 sys/include/dev/pci/pci.h |  1 +
 2 files changed, 46 insertions(+)

(limited to 'sys')

diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index f681431..57133bf 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/pci/pci.c
@@ -74,6 +74,33 @@ pci_cam_read(const struct pci_device *dev, uint32_t offset)
 #endif
 }
 
+/*
+ * Write to device's legacy PCI CAM space
+ *
+ * @dev: Device to write to.
+ * @offset: Offset to write at.
+ *
+ * XXX: Do not use directly!
+ */
+static void
+pci_cam_write(const struct pci_device *dev, uint32_t offset, uint32_t value)
+{
+#if defined(__x86_64__)
+    uint32_t address;
+
+    address = __BIT(31)         |
+              (offset & ~3)     |
+              (dev->func << 8)  |
+              (dev->slot << 11) |
+              (dev->bus << 16);
+
+    outl(0xCF8, address);
+    outb(0xCFC, value);
+#else
+    panic("Invalid arch (%s())\n", __func__);
+#endif
+}
+
 static bool
 pci_device_exists(uint8_t bus, uint8_t slot, uint8_t func)
 {
@@ -167,6 +194,24 @@ pci_readl(struct pci_device *dev, uint32_t offset)
     __builtin_unreachable();
 }
 
+/*
+ * Write to PCI(e) configuration space.
+ *
+ * @dev: Device to write to.
+ * @offset: Offset to write at.
+ */
+void
+pci_writel(struct pci_device *dev, uint32_t offset, uint32_t val)
+{
+    if (access_method == PCI_ACCESS_CAM) {
+        pci_cam_write(dev, offset, val);
+        return;
+    }
+
+    panic("Invalid access method (%s())\n", __func__);
+    __builtin_unreachable();
+}
+
 struct pci_device *
 pci_get_device(struct pci_lookup lookup, uint16_t lookup_type)
 {
diff --git a/sys/include/dev/pci/pci.h b/sys/include/dev/pci/pci.h
index c17a08e..fbbbeab 100644
--- a/sys/include/dev/pci/pci.h
+++ b/sys/include/dev/pci/pci.h
@@ -65,6 +65,7 @@ struct pci_device {
 
 int pci_init(void);
 uint32_t pci_readl(struct pci_device *dev, uint32_t offset);
+void pci_writel(struct pci_device *dev, uint32_t offset, uint32_t val);
 struct pci_device *pci_get_device(struct pci_lookup lookup, uint16_t lookup_type);
 
 #endif  /* !_DEV_PCI_H_ */
-- 
cgit v1.2.3