]> Joshua Wise's Git repositories - netwatch.git/commitdiff
Add PCI bus probe and enumeration routines.
authorJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 26 Sep 2008 03:16:58 +0000 (23:16 -0400)
committerJoshua Wise <joshua@rebirth.joshuawise.com>
Fri, 26 Sep 2008 03:16:58 +0000 (23:16 -0400)
grubload/Makefile
grubload/multiboot_c.c
include/pci.h
pci/pci.c [new file with mode: 0644]

index 0ff596ac8abc3d301de55bc87ecf77fa64b76b4a..3c7e395f7115f1c311c2cff84bf1e3622c862d24 100644 (file)
@@ -1,4 +1,4 @@
-OBJS=multiboot_c.o multiboot_asm.o realmode.o loader.o ../pci/pci-raw.o ../lib/minilib.o ../lib/console.o ../ich2/smram-ich2.o ../ich2/smi.o output.o ../lib/sprintf.o ../lib/doprnt.o
+OBJS=multiboot_c.o multiboot_asm.o realmode.o loader.o ../pci/pci-raw.o ../lib/minilib.o ../lib/console.o ../ich2/smram-ich2.o ../ich2/smi.o output.o ../lib/sprintf.o ../lib/doprnt.o ../pci/pci.o
 CC=gcc
 CFLAGS=-nostdlib -I../include -I../include/raw -I. -D__RAW__ -fno-builtin -nostdinc -Wall -Werror -pedantic -std=gnu99
 
index 17c1542cffcc1562ca2e4567801ca51e37c8f88d..372363c60b2c0e57cc7dc7d6853247bd2917a2d5 100644 (file)
@@ -54,7 +54,6 @@ void c_start(unsigned int magic, struct mb_info *mbinfo)
        outputf("Current USB state is: %04x %04x", pci_read16(0, 31, 2, 0xC0), pci_read16(0, 31, 4, 0xC0));
        outputf("Current SMI state is: %08x", inl(0x830));
        
-       
        smi_disable();
        
        /* Try really hard to shut up USB_LEGKEY. */
@@ -62,6 +61,8 @@ void c_start(unsigned int magic, struct mb_info *mbinfo)
        pci_write16(0, 31, 2, 0xC0, 0);
        pci_write16(0, 31, 4, 0xC0, pci_read16(0, 31, 4, 0xC0));
        pci_write16(0, 31, 4, 0xC0, 0);
+       
+       pci_bus_enum();
 
        /* Open the SMRAM aperture and load our ELF. */
        old_smramc = smram_save_state();
index 60b665f132f59480d1d99c47e14075ec39788b98..313b3e0d0570f39a5f8cb4ea6d8a9f01065e275e 100644 (file)
@@ -16,4 +16,29 @@ uint32_t pci_read32(int bus, int slot, int fn, int addr);
 uint16_t pci_read16(int bus, int slot, int fn, int addr);
 uint8_t pci_read8(int bus, int slot, int fn, int addr);
 
+/* Hardware-agnostic functions implemented by pci.c */
+typedef enum {
+       PCI_BAR_NONE = 0,
+       PCI_BAR_MEMORY32,
+       PCI_BAR_MEMORY64,
+       PCI_BAR_IO
+} pci_bar_type_t;
+
+typedef struct pci_bar {
+       pci_bar_type_t type;
+       unsigned char prefetchable;
+       unsigned long addr;
+} pci_bar_t;
+
+typedef struct pci_dev {
+       unsigned short vid, did;
+       int bus, dev, fn;
+       pci_bar_t bars[6];
+} pci_dev_t;
+
+typedef int (*pci_probe_fn_t)(pci_dev_t *);
+
+void pci_bus_enum();
+int pci_probe(pci_probe_fn_t probe);
+
 #endif
diff --git a/pci/pci.c b/pci/pci.c
new file mode 100644 (file)
index 0000000..e5ab816
--- /dev/null
+++ b/pci/pci.c
@@ -0,0 +1,100 @@
+#include <pci.h>
+#include <output.h>
+
+int pci_probe(pci_probe_fn_t probe)
+{
+       int devsfound = 0;
+       pci_dev_t pdev;
+       unsigned int bus;
+       unsigned int dev;
+       unsigned int fn;
+       
+       for (bus = 0; bus < 0x100; bus++)
+               for (dev = 0; dev < 0x20; dev++)
+                       if (pci_read32(bus, dev, 0, 0) != 0xFFFFFFFF)
+                               for (fn = 0; fn < 8; fn++)
+                               {
+                                       int bar;
+                                       
+                                       if (pci_read32(bus, dev, fn, 0) == 0xFFFFFFFF)
+                                               continue;
+                                       
+                                       if ((fn != 0) && !(pci_read8(bus, dev, 0, 0x0E) & 0x80))
+                                               continue;
+                                       
+                                       pdev.bus = bus;
+                                       pdev.dev = dev;
+                                       pdev.fn = fn;
+                                       pdev.vid = pci_read16(bus, dev, fn, 0);
+                                       pdev.did = pci_read16(bus, dev, fn, 2);
+                                       
+                                       for (bar = 0; bar < 6; bar++)
+                                       {
+                                               unsigned long bardat = pci_read32(bus, dev, fn, 0x10 + bar*4);
+                                               if (bardat == 0)
+                                               {
+                                                       pdev.bars[bar].type = PCI_BAR_NONE;
+                                                       continue;
+                                               }
+                                               if (bardat & 1)
+                                               {
+                                                       pdev.bars[bar].type = PCI_BAR_IO;
+                                                       pdev.bars[bar].addr = bardat & ~0x3;
+                                               } else {
+                                                       pdev.bars[bar].prefetchable = (bardat >> 3) & 1;
+                                                       switch ((bardat >> 1) & 0x3)
+                                                       {
+                                                       case 0:
+                                                               pdev.bars[bar].type = PCI_BAR_MEMORY32;
+                                                               pdev.bars[bar].addr = bardat & ~0xF;
+                                                               break;
+                                                       case 2:
+                                                               pdev.bars[bar].type = PCI_BAR_MEMORY64;
+                                                               bar++;
+                                                               pdev.bars[bar].type = PCI_BAR_NONE;
+                                                               break;
+                                                       default:
+                                                               pdev.bars[bar].type = PCI_BAR_NONE;
+                                                               continue;
+                                                       }
+                                               }
+                                       }
+                                       
+                                       devsfound += probe(&pdev);
+                               }
+       
+       return devsfound;
+}
+
+static int _enumfn(pci_dev_t *pdev)
+{
+       int bar;
+       
+       outputf("Found device: %02x:%02x.%1x: %04X:%04X",
+               pdev->bus, pdev->dev, pdev->fn,
+               pdev->vid, pdev->did);
+       for (bar = 0; bar < 6; bar++)
+       {
+               switch (pdev->bars[bar].type)
+               {
+               case PCI_BAR_IO:
+                       outputf("  BAR %d: I/O, Addr %04x", bar, pdev->bars[bar].addr);
+                       break;
+               case PCI_BAR_MEMORY32:
+                       outputf("  BAR %d: Mem32, Addr %04x", bar, pdev->bars[bar].addr);
+                       break;
+               case PCI_BAR_MEMORY64:
+                       outputf("  BAR %d: Mem64, Addr %04x", bar, pdev->bars[bar].addr);
+                       break;
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+
+void pci_bus_enum()
+{
+       pci_probe(_enumfn);
+}
+
This page took 0.037089 seconds and 4 git commands to generate.