Nucleus
Barry Driver core e4c4dfe (3 years, 2 months ago)
diff --git a/kernel/acpi/pci.c b/kernel/acpi/pci.c
new file mode 100644
index 0000000..b7c74c1
--- /dev/null
+++ b/kernel/acpi/pci.c
@@ -0,0 +1,84 @@
+/*
+ * This file controls the PCI interface. It contains utility functions for
+ * accessing PCI configuration space. It scans all devices connected to the
+ * system and tries to initialise them.
+ */
+
+#include <stdint.h>
+#include <io.h>
+#include <nucleus/pci.h>
+
+/* PCI Configuration Ports */
+enum PCIConfigPort {
+ CONFIG_ADDRESS = 0xCF8,
+ CONFIG_DATA = 0xCFC,
+};
+
+/* Make a PCI Address */
+static inline uint32_t
+make_pci_address(int bus, int dev, int func, int off)
+{
+ return (1 << 31) | (bus << 16) | (dev << 11) | (func << 8) |
+ (off & 0xFC);
+}
+
+/* Read PCI config byte */
+uint8_t
+pci_read_byte(int bus, int dev, int func, int off)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ return inb(CONFIG_DATA + (off & 3));
+}
+
+/* Read PCI config word */
+uint16_t
+pci_read_word(int bus, int dev, int func, int off)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ return inw(CONFIG_DATA + (off & 2));
+}
+
+/* Read PCI config dword */
+uint32_t
+pci_read_dword(int bus, int dev, int func, int off)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ return inl(CONFIG_DATA);
+}
+
+/* Write PCI config byte */
+void
+pci_write_byte(int bus, int dev, int func, int off, uint8_t value)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ outb(CONFIG_DATA + (off & 3), value);
+}
+
+/* Write PCI config word */
+void
+pci_write_word(int bus, int dev, int func, int off, uint16_t value)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ outw(CONFIG_DATA + (off & 2), value);
+}
+
+/* Write PCI config dword */
+void
+pci_write_dword(int bus, int dev, int func, int off, uint32_t value)
+{
+ outl(CONFIG_ADDRESS, make_pci_address(bus, dev, func, off));
+ outl(CONFIG_DATA, value);
+}
+
+/* Scan for PCI devices */
+void
+init_pci(void)
+{
+ uint16_t bus, dev, func;
+ /* This is one massive iteration */
+ for (bus = 0; bus < 256; bus++)
+ for (dev = 0; dev < 32; dev++)
+ for (func = 0; func < 8; func++)
+ if (pci_read_word(bus, dev, func, 0) != 0xFFFF)
+ init_pci_device(bus, dev, func);
+}