feat: PCI bus probing
authorMinep <zelong56@gmail.com>
Mon, 27 Jun 2022 14:35:27 +0000 (15:35 +0100)
committerMinep <zelong56@gmail.com>
Mon, 27 Jun 2022 14:35:27 +0000 (15:35 +0100)
fix: typo in ESC perfix for ANSI color code.

lunaix-os/hal/pci.c [new file with mode: 0644]
lunaix-os/includes/hal/pci.h [new file with mode: 0644]
lunaix-os/includes/hal/pic.h
lunaix-os/kernel/kprintf.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/tty/tty.c

diff --git a/lunaix-os/hal/pci.c b/lunaix-os/hal/pci.c
new file mode 100644 (file)
index 0000000..8bc35ce
--- /dev/null
@@ -0,0 +1,112 @@
+#include <hal/pci.h>
+#include <lunaix/mm/kalloc.h>
+#include <lunaix/syslog.h>
+
+LOG_MODULE("PCI")
+
+static struct llist_header pci_devices;
+
+void
+pci_probe_device(int bus, int dev, int funct)
+{
+    pci_reg_t reg1 = pci_read_cspace(bus, dev, funct, 0);
+    uint32_t vendor = reg1 & 0xffff;
+    pci_reg_t dev_id = reg1 >> 16;
+
+    // Vendor=0xffff则表示设备不存在
+    if (vendor == PCI_VENDOR_INVLD) {
+        return;
+    }
+
+    pci_reg_t hdr_type = pci_read_cspace(bus, dev, funct, 3);
+    hdr_type = (hdr_type >> 16) & 0xff;
+
+    if ((hdr_type & 0x80)) {
+        hdr_type = hdr_type & ~0x80;
+        // 探测多用途设备(multi-function device)
+        for (int i = 1; i < 7; i++) {
+            pci_probe_device(bus, dev, i);
+        }
+    }
+
+    if (hdr_type != 0) {
+        // XXX: 目前忽略所有桥接设备,比如PCI-PCI桥接器,或者是CardBus桥接器
+        return;
+    }
+
+    pci_reg_t intr = pci_read_cspace(bus, dev, funct, 15);
+    pci_reg_t class = pci_read_cspace(bus, dev, funct, 2) >> 8;
+
+    struct pci_device* device = lxmalloc(sizeof(struct pci_device));
+    *device = (struct pci_device){ .bus = bus,
+                                   .dev = dev,
+                                   .function = funct,
+                                   .class_code = class,
+                                   .vendor = vendor,
+                                   .deviceId = dev_id,
+                                   .type = hdr_type,
+                                   .intr_line = intr & 0xff,
+                                   .intr_pintype = (intr >> 8) & 0xff };
+
+    // 读取设备的内存映射的寄存器的基地址
+    for (int i = 0; i < 6; i++) {
+        device->bars[i] = pci_read_cspace(bus, dev, funct, 4 + i);
+    }
+
+    llist_append(&pci_devices, &device->dev_chain);
+}
+
+void
+pci_probe()
+{
+    // 暴力扫描所有PCI设备
+    // XXX: 尽管最多会有256条PCI总线,但就目前而言,只考虑bus #0就足够了
+    for (int bus = 0; bus < 1; bus++) {
+        for (int dev = 0; dev < 32; dev++) {
+            pci_probe_device(bus, dev, 0);
+        }
+    }
+}
+
+void
+pci_print_device()
+{
+    struct pci_device *pos, *n;
+    llist_for_each(pos, n, &pci_devices, dev_chain)
+    {
+        kprintf(KINFO "(B%xh:D%xh:F%xh) Dev %x:%x, Class 0x%x\n",
+                pos->bus,
+                pos->dev,
+                pos->function,
+                pos->vendor,
+                pos->deviceId,
+                pos->class_code);
+
+        for (int i = 0; i < 6; i++) {
+            kprintf(KINFO "\t BAR#%d: %p\n", i, pos->bars[i]);
+        }
+        kprintf(
+          KINFO "\t IRQ: %d, INT#x: %d\n\n", pos->intr_line, pos->intr_pintype);
+    }
+}
+
+struct pci_device*
+pci_get_device(uint16_t vendorId, uint16_t deviceId)
+{
+    struct pci_device *pos, *n;
+    llist_for_each(pos, n, &pci_devices, dev_chain)
+    {
+        if (pos->vendor == vendorId && pos->deviceId == deviceId) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+void
+pci_init()
+{
+    llist_init_head(&pci_devices);
+    pci_probe();
+}
\ No newline at end of file
diff --git a/lunaix-os/includes/hal/pci.h b/lunaix-os/includes/hal/pci.h
new file mode 100644 (file)
index 0000000..3e421ee
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __LUNAIX_PCI_H
+#define __LUNAIX_PCI_H
+
+#include <hal/io.h>
+#include <lunaix/ds/llist.h>
+
+#define PCI_CONFIG_ADDR 0xcf8
+#define PCI_CONFIG_DATA 0xcfc
+
+#define PCI_TDEV 0x0
+#define PCI_TPCIBRIDGE 0x1
+#define PCI_TCARDBRIDGE 0x2
+
+#define PCI_VENDOR_INVLD 0xffff
+
+#define PCI_REG_VENDER 0x0
+#define PCI_REG_DEV 0x1
+#define PCI_REG_HDRTYPE 0x7
+
+#define PCI_ADDRESS(bus, dev, funct, reg)                                      \
+    (((bus)&0xff) << 16) | (((dev)&0xff) << 11) | (((funct)&0xff) << 8) |      \
+      (((reg)&0xff) << 2) | 0x80000000
+
+typedef unsigned int pci_reg_t;
+
+// PCI device header format
+// Ref: "PCI Local Bus Specification, Rev.3, Section 6.1"
+
+struct pci_device
+{
+    struct llist_header dev_chain;
+    uint16_t vendor;
+    uint16_t deviceId;
+    uint32_t class_code;
+    uint8_t bus;
+    uint8_t dev;
+    uint8_t function;
+    uint8_t type;
+    uint8_t intr_line;
+    uint8_t intr_pintype;
+    uint32_t bars[6];
+};
+
+// PCI Configuration Space (C-Space) r/w:
+//      Refer to "PCI Local Bus Specification, Rev.3, Section 3.2.2.3.2"
+
+inline pci_reg_t
+pci_read_cspace(int bus, int dev, int funct, int reg)
+{
+    io_outl(PCI_CONFIG_ADDR, PCI_ADDRESS(bus, dev, funct, reg));
+    return io_inl(PCI_CONFIG_DATA);
+}
+
+inline void
+pci_write_cspace(int bus, int dev, int funct, int reg, pci_reg_t data)
+{
+    io_outl(PCI_CONFIG_ADDR, PCI_ADDRESS(bus, dev, funct, reg));
+    io_outl(PCI_CONFIG_DATA, data);
+}
+
+void
+pci_probe();
+
+void
+pci_init();
+
+void
+pci_print_device();
+
+struct pci_device*
+pci_get_device(uint16_t vendorId, uint16_t deviceId);
+
+#endif /* __LUNAIX_PCI_H */
index 8fdcd040e860c982e34915620d2f5087568f9a65..b13aae5bf1da819b51c3fbda55e94098f696eec1 100644 (file)
@@ -6,9 +6,9 @@ static inline void
 pic_disable()
 {
     // ref: https://wiki.osdev.org/8259_PIC
-    asm volatile ("movb $0xff, %al\n"
-        "outb %al, $0xa1\n"
-        "outb %al, $0x21\n");
+    asm volatile("movb $0xff, %al\n"
+                 "outb %al, $0xa1\n"
+                 "outb %al, $0x21\n");
 }
 
 #endif /* __LUNAIX_PIC_H */
index 75b9fc4afaa9b69173c27c0646280abc3ee46de1..af47a8abae297a857d19405b775c75215fb0febd 100644 (file)
@@ -33,7 +33,7 @@ __kprintf(const char* component, const char* fmt, va_list args)
             // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12);
             snprintf(expanded_fmt,
                      MAX_XFMT_SIZE,
-                     "\x033[6;0m[%s] (%s) %s\x033[39;49m",
+                     "\033[6;0m[%s] (%s) %s\033[39;49m",
                      "WARN",
                      component,
                      fmt);
@@ -42,7 +42,7 @@ __kprintf(const char* component, const char* fmt, va_list args)
             // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12);
             snprintf(expanded_fmt,
                      MAX_XFMT_SIZE,
-                     "\x033[12;0m[%s] (%s) %s\x033[39;49m",
+                     "\033[12;0m[%s] (%s) %s\033[39;49m",
                      "EROR",
                      component,
                      fmt);
@@ -51,7 +51,7 @@ __kprintf(const char* component, const char* fmt, va_list args)
             // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12);
             snprintf(expanded_fmt,
                      MAX_XFMT_SIZE,
-                     "\x033[9;0m[%s] (%s) %s\x033[39;49m",
+                     "\033[9;0m[%s] (%s) %s\033[39;49m",
                      "DEBG",
                      component,
                      fmt);
index 663eff254743b8419627b45112b6faf705037323..92d3fd3df34478c42da249d81649b43414902e0d 100644 (file)
@@ -14,6 +14,7 @@
 #include <hal/acpi/acpi.h>
 #include <hal/apic.h>
 #include <hal/ioapic.h>
+#include <hal/pci.h>
 
 LOG_MODULE("PROC0")
 
@@ -32,6 +33,7 @@ unlock_reserved_memory();
 void
 __do_reserved_memory(int unlock);
 
+//#define USE_DEMO
 #define DEMO_SIGNAL
 
 extern void
@@ -52,14 +54,16 @@ __proc0_usr()
     }
 
     if (!(p = fork())) {
-#ifdef DEMO_SIGNAL
+#ifndef USE_DEMO
+        _exit(0);
+#elif defined DEMO_SIGNAL
         _signal_demo_main();
 #else
         _lxinit_main();
 #endif
     }
 
-    // waitpid(p, 0, 0);
+    waitpid(p, 0, 0);
 
     while (1) {
         yield();
@@ -126,6 +130,8 @@ init_platform()
     timer_init(SYS_TIMER_FREQUENCY_HZ);
     clock_init();
     ps2_kbd_init();
+    pci_init();
+    pci_print_device();
 
     syscall_install();
 
index b4913559410ffb7993a85fe04979ef5d240c5571..d4ac8d07c4746340846fdb4aefcd318585996938 100644 (file)
@@ -53,7 +53,7 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size)
             break;
         }
         char chr = data[pos];
-        if (state == 0 && chr == '\x033') {
+        if (state == 0 && chr == '\033') {
             state = 1;
         } else if (state == 1 && chr == '[') {
             state = 2;