--- /dev/null
+#include <geekos/malloc.h>
+#include <geekos/pci.h>
+#include <geekos/io.h>
+#include <geekos/debug.h>
+
+#define PCI_CONFIG_ADDRESS 0xcf8 // 32 bit, little endian
+#define PCI_CONFIG_DATA 0xcfc // 32 bit, little endian
+
+#define PCI_MAX_NUM_BUSES 4
+
+
+struct pci_device_config {
+ ushort_t device_id;
+ ushort_t vendor_id;
+ ushort_t status;
+ ushort_t command;
+ uchar_t class_code;
+ uchar_t subclass;
+ ushort_t revision;
+ uchar_t BIST;
+ uchar_t header_type;
+ uchar_t latency_time;
+ uchar_t cache_line_size;
+ uint_t BAR[6];
+ uint_t cardbus_cis_pointer;
+ ushort_t subsystem_id;
+ ushort_t subsystem_vendor_id;
+ uint_t expansion_rom_address;
+ uint_t reserved[2];
+ uchar_t max_latency;
+ uchar_t min_grant;
+ uchar_t intr_pin;
+ uchar_t intr_line;
+} __attribute__((__packed__)) ;
+
+struct pci_bus {
+ uint_t number;
+ struct pci_bus *next;
+
+ struct pci_device *device_list; //
+
+};
+
+struct pci_device {
+ uint_t number;
+ struct pci_bus *bus;
+ struct pci_device *next;
+
+ struct pci_device_config config;
+};
+
+struct pci {
+ uint_t num_buses;
+ struct pci_bus *bus_list;
+};
+
+
+static uint_t ReadPCIDWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
+{
+ uint_t address;
+ uint_t data;
+
+ address = ((bus << 16) | (dev << 11) |
+ (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
+
+ Out_DWord(PCI_CONFIG_ADDRESS,address);
+ data=In_DWord(PCI_CONFIG_DATA);
+
+ return data;
+}
+
+#if 0
+
+static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
+{
+ uint_t address;
+ uint_t data;
+
+ address = ((bus << 16) | (dev << 11) |
+ (func << 8) | (offset & 0xfc) | ((uint_t)0x80000000));
+
+ Out_DWord(PCI_CONFIG_ADDRESS,address);
+ data=In_DWord(PCI_CONFIG_DATA);
+
+ //PrintBoth("PCI: [0x%x] = 0x%x\n",address,data);
+
+
+ return (ushort_t) ((data>>((offset&0x2)*8)) & 0xffff);
+}
+
+#endif
+
+static ushort_t ReadPCIWord(uint_t bus, uint_t dev, uint_t func, uint_t offset)
+{
+ return (ushort_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x2)*8));
+}
+
+#if 0 // not currently used
+static uchar_t ReadPCIByte(uint_t bus, uint_t dev, uint_t func, uint_t offset)
+{
+ return (uchar_t) (ReadPCIDWord(bus,dev,func,offset)>>((offset&0x3)*8));
+}
+#endif
+
+static struct pci *NewPCI()
+{
+ struct pci *p = (struct pci *)Malloc(sizeof(struct pci));
+ p->bus_list=NULL;
+ p->num_buses=0;
+ return p;
+}
+
+static void AddPCIBus(struct pci *p, struct pci_bus *bus)
+{
+ bus->next = p->bus_list;
+ p->bus_list=bus;
+}
+
+
+static struct pci_bus *NewPCIBus(struct pci *p)
+{
+ struct pci_bus *pb = (struct pci_bus *)Malloc(sizeof(struct pci_bus));
+ pb->device_list=NULL;
+ pb->number = (p->num_buses);
+ p->num_buses++;
+ return pb;
+}
+
+static void AddPCIDevice(struct pci_bus *b, struct pci_device *d)
+{
+ d->bus=b;
+ d->next=b->device_list;
+ b->device_list=d;
+}
+
+static struct pci_device *NewPCIDevice(struct pci_bus *pb)
+{
+ struct pci_device *pd = (struct pci_device *)Malloc(sizeof(struct pci_device));
+ pd->number=0;
+ pd->bus=NULL;
+ pd->next=NULL;
+ return pd;
+}
+
+static void GetPCIDeviceConfig(uint_t bus,
+ uint_t dev,
+ struct pci_device *d)
+{
+ uint_t numdwords=sizeof(struct pci_device_config) / 4;
+ uint_t i;
+
+ uint_t *p = (uint_t *) (&(d->config));
+
+ for (i=0;i<numdwords;i++) {
+ p[i]=ReadPCIDWord(bus,dev,0,i*4);
+ }
+}
+
+
+
+static struct pci *ScanPCI()
+{
+ uint_t bus, dev;
+ ushort_t vendor;
+
+ struct pci *thepci = NewPCI();
+ struct pci_bus *thebus;
+
+ for (bus=0;bus<PCI_MAX_NUM_BUSES;bus++) {
+ // Are there any devices on the bus?
+ for (dev=0;dev<32;dev++) {
+ vendor=ReadPCIWord(bus,dev,0,0);
+ if (vendor!=0xffff) {
+ break;
+ }
+ }
+ if (dev==32) {
+ continue;
+ }
+ // There are devices. Create a bus.
+ thebus = NewPCIBus(thepci);
+ thebus->number=bus;
+ // Add the devices to the bus
+ for (dev=0;dev<32;dev++) {
+ vendor=ReadPCIWord(bus,dev,0,0);
+ if (vendor!=0xffff) {
+ struct pci_device *thedev=NewPCIDevice(thebus);
+ thedev->number=dev;
+ GetPCIDeviceConfig(bus,dev,thedev);
+ AddPCIDevice(thebus,thedev);
+ }
+ }
+ AddPCIBus(thepci,thebus);
+ }
+ return thepci;
+}
+
+static void PrintPCIDevice(struct pci_device *thedev)
+{
+ PrintBoth(" PCI Device: \n");
+ PrintBoth(" Slot: %u\n",thedev->number);
+ PrintBoth(" device_id: 0x%x\n", (uint_t) thedev->config.device_id);
+ PrintBoth(" vendor_id: 0x%x\n", (uint_t) thedev->config.vendor_id);
+ PrintBoth(" status: 0x%x\n", (uint_t) thedev->config.status);
+ PrintBoth(" command: 0x%x\n", (uint_t) thedev->config.command);
+ PrintBoth(" class_code: 0x%x\n", (uint_t) thedev->config.class_code);
+ PrintBoth(" subclass: 0x%x\n", (uint_t) thedev->config.subclass);
+ PrintBoth(" revision: 0x%x\n", (uint_t) thedev->config.revision);
+ PrintBoth(" BIST: 0x%x\n", (uint_t) thedev->config.BIST);
+ PrintBoth(" header_type: 0x%x\n", (uint_t) thedev->config.header_type);
+ PrintBoth(" latency_time: 0x%x\n", (uint_t) thedev->config.latency_time);
+ PrintBoth(" cache_line_size: 0x%x\n", (uint_t) thedev->config.cache_line_size);
+ PrintBoth(" BAR[0]: 0x%x\n", (uint_t) thedev->config.BAR[0]);
+ PrintBoth(" BAR[1]: 0x%x\n", (uint_t) thedev->config.BAR[1]);
+ PrintBoth(" BAR[2]: 0x%x\n", (uint_t) thedev->config.BAR[2]);
+ PrintBoth(" BAR[3]: 0x%x\n", (uint_t) thedev->config.BAR[3]);
+ PrintBoth(" BAR[4]: 0x%x\n", (uint_t) thedev->config.BAR[4]);
+ PrintBoth(" BAR[5]: 0x%x\n", (uint_t) thedev->config.BAR[5]);
+ PrintBoth(" cardbus_cis_ptr: 0x%x\n", (uint_t) thedev->config.cardbus_cis_pointer);
+ PrintBoth(" subsystem_id: 0x%x\n", (uint_t) thedev->config.subsystem_id);
+ PrintBoth(" subsystem_vendor: 0x%x\n", (uint_t) thedev->config.subsystem_vendor_id);
+ PrintBoth(" exp_rom_address: 0x%x\n", (uint_t) thedev->config.expansion_rom_address);
+ PrintBoth(" reserved[0]: 0x%x\n", (uint_t) thedev->config.reserved[0]);
+ PrintBoth(" reserved[1]: 0x%x\n", (uint_t) thedev->config.reserved[1]);
+ PrintBoth(" max_latency: 0x%x\n", (uint_t) thedev->config.max_latency);
+ PrintBoth(" min_grant: 0x%x\n", (uint_t) thedev->config.min_grant);
+ PrintBoth(" intr_pin: 0x%x\n", (uint_t) thedev->config.intr_pin);
+ PrintBoth(" intr_line: 0x%x\n", (uint_t) thedev->config.intr_line);
+}
+
+static void PrintPCIBus(struct pci_bus *thebus)
+{
+ struct pci_device *thedev;
+
+ PrintBoth(" PCI Bus:\n");
+ PrintBoth(" Number: %u\n",thebus->number);
+
+ thedev=thebus->device_list;
+
+ while (thedev) {
+ PrintPCIDevice(thedev);
+ thedev=thedev->next;
+ }
+}
+
+static void PrintPCI(struct pci *thepci)
+{
+ struct pci_bus *thebus;
+
+ PrintBoth("PCI Configuration:\n");
+ PrintBoth(" Number of Buses: %u\n",thepci->num_buses);
+ thebus=thepci->bus_list;
+ while (thebus) {
+ PrintPCIBus(thebus);
+ thebus=thebus->next;
+ }
+
+}
+
+int Init_PCI()
+{
+ PrintPCI(ScanPCI());
+
+ return 0;
+
+}