First run at migrating from PIC to IOAPIC. Includes mptable parsing, moving pci to...
authorPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 23 Jul 2009 04:33:13 +0000 (21:33 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 23 Jul 2009 04:33:13 +0000 (21:33 -0700)
1) Moved PCI out of the NIC driver and into its own file. Created structures that map from irq->pci device, and pci device->irq
2) Created mptables.c, which parses the mptables and creates a ton of structures that allows us to locate an ioapic interupt line
   based on pci device, so we can ...
3) Added a function in apic.c that allows us to route an irq to a specific lapic, based on the info from the mptables and pci bus
4) Changed the init order to setup the nic after smp boot. This is needed since we want to route interupts to a core
   that wasn't yet booted (in the old init order).

Note: PIT functionality is not yet known. Also the ioapic_route_irq() relies on a few constants that need to be expanded into structs.

12 files changed:
include/arch/apic.h
include/mptables.h [new file with mode: 0644]
include/pci.h [new file with mode: 0644]
include/rl8168.h
kern/src/Makefrag
kern/src/apic.c
kern/src/init.c
kern/src/mptables.c [new file with mode: 0644]
kern/src/pci.c [new file with mode: 0644]
kern/src/rl8168.c
kern/src/trap.c
user/parlib/src/newlib_backend.c

index 613f42e..922db84 100644 (file)
@@ -93,6 +93,7 @@ extern system_timing_t system_timing;
 void pic_remap(void);
 void pic_mask_irq(uint8_t irq);
 void pic_unmask_irq(uint8_t irq);
+void ioapic_route_irq(uint8_t irq, uint8_t dest);
 void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
 void lapic_set_timer(uint32_t usec, bool periodic);
 uint32_t lapic_get_default_id(void);
diff --git a/include/mptables.h b/include/mptables.h
new file mode 100644 (file)
index 0000000..dc2210f
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef ROS_INC_MPTABLES_H
+#define ROS_INC_MPTABLES_H
+
+#include <arch/types.h>
+#include <trap.h>
+#include <pmap.h>
+
+#define mptables_info(...)  cprintf(__VA_ARGS__)  
+#define mptables_dump(...)  //cprintf(__VA_ARGS__)  
+
+
+#define MP_SIG                 0x5f504d5f      /* _MP_ */
+
+#define BIOS_ROM_BASE  0xf0000
+#define BIOS_ROM_BOUND  0xffff0 // Inclusive.
+
+#define EBDA_POINTER   0x040e // Bound is dynamic. In first KB
+#define EBDA_SIZE              1024
+
+#define TOPOFMEM_POINTER       0x0413          /* BIOS: base memory size */
+#define IMCRP_MASK             0x8000
+
+#define IOAPIC_MAX_ID  256
+
+#define NUM_ENTRY_TYPES 5
+
+enum interrupt_modes {
+       PIC, // PIC Mode (Bocsh, KVM)
+       VW,  // Virtural Wire Mode (Dev Boxes)
+       SIO  // Once we fix up the ioapic, shift to this mode, sym io.
+};
+
+enum entry_types {
+       PROC =          0,
+       BUS  =          1,
+       IOAPIC =        2,
+       INT =           3,
+       LINT =          4
+};
+
+enum busTypes {
+    CBUS = 1,
+    CBUSII = 2,
+    EISA = 3,
+    ISA = 6,
+    PCI = 13,
+    XPRESS = 18,
+    MAX_BUSTYPE = 18,
+    UNKNOWN_BUSTYPE = 0xff
+};
+
+typedef struct BUSTYPENAME {
+    uint8_t    type;
+    char       name[ 7 ];
+} busTypeName;
+
+static busTypeName busTypeTable[] =
+{
+    { CBUS,            "CBUS"   },
+    { CBUSII,          "CBUSII" },
+    { EISA,            "EISA"   },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { ISA,             "ISA"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { PCI,             "PCI"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    },
+    { UNKNOWN_BUSTYPE, "---"    }
+};
+
+typedef struct TABLE_ENTRY {
+    uint8_t    type;
+    uint8_t    length;
+    char       name[ 32 ];
+} tableEntry;
+
+/* MP Floating Pointer Structure */
+typedef struct MPFPS {
+    char       signature[ 4 ];
+    void*      pap;
+    uint8_t    length;
+    uint8_t    spec_rev;
+    uint8_t    checksum;
+    uint8_t    mpfb1;
+    uint8_t    mpfb2;
+    uint8_t    mpfb3;
+    uint8_t    mpfb4;
+    uint8_t    mpfb5;
+} mpfps_t;
+
+
+/* MP Configuration Table Header */
+typedef struct MPCTH {
+    char       signature[ 4 ];
+    uint16_t   base_table_length;
+    uint8_t            spec_rev;
+    uint8_t            checksum;
+    uint8_t            oem_id[ 8 ];
+    uint8_t            product_id[ 12 ];
+    void*              oem_table_pointer;
+    uint16_t   oem_table_size;
+    uint16_t   entry_count;
+    void*              apic_address;
+    uint16_t   extended_table_length;
+    uint8_t            extended_table_checksum;
+    uint8_t            reserved;
+} mpcth_t;
+
+
+typedef struct PROCENTRY {
+    uint8_t            type;
+    uint8_t            apicID;
+    uint8_t            apicVersion;
+    uint8_t            cpuFlags;
+    uint32_t   cpuSignature;
+    uint32_t   featureFlags;
+    uint32_t   reserved1;
+    uint32_t   reserved2;
+} proc_entry;
+
+typedef struct BUSENTRY {
+    uint8_t    type;
+    uint8_t    busID;
+    char       busType[ 6 ];
+} bus_entry;
+
+typedef struct IOAPICENTRY {
+    uint8_t    type;
+    uint8_t    apicID;
+    uint8_t    apicVersion;
+    uint8_t    apicFlags;
+    void*      apicAddress;
+} ioapic_entry;
+
+typedef struct INTENTRY {
+    uint8_t            type;
+    uint8_t            intType;
+    uint16_t   intFlags;
+    uint8_t            srcBusID;
+    uint8_t            srcBusIRQ;
+    uint8_t            dstApicID;
+    uint8_t            dstApicINT;
+} int_entry;
+
+typedef struct PCIINTENTRY {
+    uint16_t           dstApicID; // A value of 256 or greater means not valid.
+    uint8_t            dstApicINT;
+} pci_int_entry;
+
+typedef struct PCIINTGROUP {
+       pci_int_entry intn[4];
+} pci_int_group;
+
+void mptables_parse();
+mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound);
+bool checksum(physaddr_t addr, uint32_t len);
+void configuration_parse(physaddr_t conf_addr);
+
+void proc_parse(proc_entry* entry, uint32_t count);
+void bus_parse(bus_entry* entry, uint32_t count);
+void ioapic_parse(ioapic_entry* entry, uint32_t count);
+void int_parse(int_entry* entry, uint32_t count);
+void lint_parse(int_entry* entry, uint32_t count);
+
+#endif /* !ROS_INC_MPTABLES_H */
diff --git a/include/pci.h b/include/pci.h
new file mode 100644 (file)
index 0000000..17e995c
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef ROS_INC_PCI_H
+#define ROS_INC_PCI_H
+
+#include <arch/types.h>
+#include <trap.h>
+#include <pmap.h>
+
+#define pci_debug(...) // cprintf(__VA_ARGS__)  
+
+// Macro for formatting PCI Configuration Address queries
+#define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
+                                                             (FUNC << 8) | REG  | \
+                                                             ((uint32_t)0x80000000))
+
+// General PCI Constants
+#define PCI_CONFIG_ADDR     0xCF8
+#define PCI_CONFIG_DATA     0xCFC
+#define INVALID_VENDOR_ID   0xFFFF
+
+#define INVALID_IRQ                    0xFFFF
+#define INVALID_BUS                    0xFFFF
+
+#define INVALID_INTN           0x0000
+
+
+#define PCI_IO_MASK         0xFFF8
+#define PCI_MEM_MASK        0xFFFFFFF0
+#define PCI_IRQ_MASK           0xFF
+#define PCI_INTN_MASK          0xFF00
+#define PCI_INTN_SHFT          0x8
+#define PCI_VENDOR_MASK                0xFFFF
+#define PCI_DEVICE_OFFSET      0x10
+#define PCI_IRQ_REG                    0x3c
+
+#define PCI_MAX_BUS                    256
+#define PCI_MAX_DEV                    32
+#define PCI_MAX_FUNC           8
+#define PCI_BAR_IO_MASK                0x1
+#define NUM_IRQS                       256
+
+// Offset used for indexing IRQs
+#define KERNEL_IRQ_OFFSET      32
+
+typedef struct PCIIRQENTRY {
+       uint16_t bus; // Bus larger than 255 denotes invalid entry.
+                                 // This is why bus is 16 bits not 8.
+       uint8_t dev;
+       uint8_t func;
+       uint8_t intn;
+} pci_irq_entry;
+
+typedef struct PCIDEVENTRY {
+       uint16_t dev_id; 
+       uint16_t ven_id;
+} pci_dev_entry;
+
+void pci_init();
+
+
+#endif /* !ROS_INC_PCI_H */
index 9fc731a..9e6856a 100644 (file)
@@ -5,34 +5,17 @@
 #include <trap.h>
 #include <pmap.h>
 
-#define nic_debug(...)  //cprintf(__VA_ARGS__)  
-#define nic_interrupt_debug(...) // cprintf(__VA_ARGS__)  
+#define nic_debug(...)  cprintf(__VA_ARGS__)  
+#define nic_interrupt_debug(...) cprintf(__VA_ARGS__)  
 #define nic_frame_debug(...)  //cprintf(__VA_ARGS__)  
 
 // Macro for formatting PCI Configuration Address queries
 #define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
                                                              (FUNC << 8) | REG  | \
                                                              ((uint32_t)0x80000000))
-
-// General PCI Constants
-#define PCI_CONFIG_ADDR     0xCF8
-#define PCI_CONFIG_DATA     0xCFC
-
 #define REALTEK_VENDOR_ID   0x10ec
-#define INVALID_VENDOR_ID   0xFFFF
 #define REALTEK_DEV_ID      0x8168
 
-#define PCI_IO_MASK         0xFFF8
-#define PCI_MEM_MASK        0xFFFFFFF0
-#define PCI_IRQ_MASK           0xFF
-#define PCI_VENDOR_MASK                0xFFFF
-#define PCI_DEVICE_OFFSET      0x10
-#define PCI_IRQ_REG                    0x3c
-
-#define PCI_MAX_BUS                    256
-#define PCI_MAX_DEV                    32
-#define PCI_BAR_IO_MASK                0x1
-
 // Realtek Offsets
 #define RL_HWREV_REG           0x40
 #define RL_MAC_OFFSET          0x00
 // v----- Good line ------v
 
 
-void init_nic(void);
+void nic_init(void);
 void reset_nic(void);
 void nic_interrupt_handler(trapframe_t *tf, void* data);
 int scan_pci(void);
index 3290f37..f9cb775 100644 (file)
@@ -30,6 +30,8 @@ KERN_SRCFILES := $(KERN_SRC_DIR)/entry.S \
                  $(KERN_SRC_DIR)/testing.c \
                  $(KERN_SRC_DIR)/workqueue.c \
                  $(KERN_SRC_DIR)/manager.c \
+                 $(KERN_SRC_DIR)/mptables.c \
+                 $(KERN_SRC_DIR)/pci.c \
                  $(KERN_SRC_DIR)/atomic.c \
                  $(KERN_SRC_DIR)/smp.c \
                  $(KERN_SRC_DIR)/printfmt.c \
index dd17656..8cf2a96 100644 (file)
@@ -8,6 +8,8 @@
 #include <arch/apic.h>
 #include <arch/timer.h>
 #include <assert.h>
+#include <mptables.h>
+#include <pci.h>
 
 system_timing_t system_timing = {0, 0, 0xffff, 0};
 
@@ -55,6 +57,54 @@ void pic_unmask_irq(uint8_t irq)
                outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
 }
 
+// MUST NOT BE CALLED BEFORE THE MPTABLES ARE PARSED
+void ioapic_route_irq(uint8_t irq, uint8_t dest) {
+       
+       extern pci_irq_entry irq_pci_map[NUM_IRQS];
+       extern uint8_t num_cpus;
+       extern pci_int_group pci_int_groups[PCI_MAX_BUS][PCI_MAX_DEV];
+       extern ioapic_entry ioapic_entries[IOAPIC_MAX_ID];
+       
+       // Need special check for PCI vs non PCI interrupts.
+
+       uint16_t bus = irq_pci_map[irq].bus;
+       uint8_t dev = irq_pci_map[irq].dev;
+       uint8_t intn = irq_pci_map[irq].intn;
+       
+       if (bus == INVALID_BUS)
+               panic("TRYING TO REROUTE TO AN INVALID IRQ!");
+       
+       // THIS IS A TEMP CHECK. IF WE USE LOGICAL PARTITIONS THIS MUST BE REMOVED
+       // Since we rely on SMP_BOOT to set the num_cpus, and we currently setup interrupt redirection BEFORE bootup. This is a problem
+//     if (dest >= num_cpus)
+//             panic("TRYING TO REROUTE TO AN INVALID DESTINATION!");
+               
+       uint16_t dstApicID = pci_int_groups[bus][dev].intn[intn].dstApicID;
+       uint8_t dstApicINT = pci_int_groups[bus][dev].intn[intn].dstApicINT;
+       
+       // MP Tables uses 8 bits to store the apic id. If our value is larger, is invalid entry
+       if (dstApicID == 0xFFFF)
+               panic("IRQ->PCI map and PCI->IOAPIC map are out of sync");
+       
+       if ((ioapic_entries[dstApicID].apicFlags & 0x1) == 0) 
+               panic("TRYING TO ROUTE TO AN INVALID DESTINATION");
+               
+       uint32_t ioapic_base = (uint32_t)ioapic_entries[dstApicID].apicAddress;
+       
+       cprintf("ioapic_addr: %x\n", ioapic_base);
+       
+       // This is ugly. Fix it. I just gave up because i need sleep and I wanted it working so I can commit.
+       uint32_t redirect_low = KERNEL_IRQ_OFFSET + irq;
+       redirect_low = redirect_low | 0xa000;
+       uint32_t redirect_high = dest << 24;
+       
+       write_mmreg32(ioapic_base, 0x10 + 2*dstApicINT);
+       write_mmreg32(ioapic_base + 0x10, redirect_low);
+       write_mmreg32(ioapic_base, 0x10 + 2*dstApicINT + 1);
+       write_mmreg32(ioapic_base + 0x10, redirect_high);
+
+}
+
 
 /*
  * Sets the LAPIC timer to go off after a certain number of ticks.  The primary
index 2ec771f..c8e5f7f 100644 (file)
@@ -29,6 +29,8 @@
 #include <manager.h>
 
 #include <rl8168.h>
+#include <mptables.h>
+#include <pci.h>
 
 static void print_cpuinfo(void);
 
@@ -57,9 +59,14 @@ void kernel_init(multiboot_info_t *mboot_info)
        idt_init();
        sysenter_init();
        timer_init();
-       init_nic();
+       mptables_parse();
+       pci_init();
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
+       
+       nic_init();
+
+               
        /*
        test_smp_call_functions();
        test_checklists();
diff --git a/kern/src/mptables.c b/kern/src/mptables.c
new file mode 100644 (file)
index 0000000..c51fcf8
--- /dev/null
@@ -0,0 +1,668 @@
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/smp.h>
+#include <arch/apic.h>
+
+#include <ros/memlayout.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pmap.h>
+#include <kmalloc.h>
+
+#include <mptables.h>
+#include <pci.h>
+
+/* Basic MP Tables Parser
+ *
+ * Memory Locations and table structs taken from FreeBSD's mptable.c and modified.
+ *
+ * Put cool text here
+ * 
+ * TODO: Extended table support
+ * TODO: KMALLOC null checks
+ * TODO: Error checking, pci device not found, etc.
+ */
+
+
+tableEntry basetableEntryTypes[] =
+{
+    { 0, 20, "Processor" },
+    { 1,  8, "Bus" },
+    { 2,  8, "I/O APIC" },
+    { 3,  8, "I/O INT" },
+    { 4,  8, "Local INT" }
+};
+
+// Important global items
+enum interrupt_modes current_interrupt_mode;
+
+void * mp_entries[NUM_ENTRY_TYPES]; // Array of entry type arrays. Indexable by entry id
+int mp_entries_count[NUM_ENTRY_TYPES]; // How large each array is.
+
+pci_int_group pci_int_groups[PCI_MAX_BUS][PCI_MAX_DEV];
+ioapic_entry ioapic_entries[IOAPIC_MAX_ID];
+
+int max_pci_device = -1;
+int max_pci_bus = -1;
+int num_ioapics = -1;
+int max_ioapic_id = -1;
+
+
+void mptables_parse() {
+       
+       mpfps_t *mpfps;
+       
+       mptables_info("Starting MPTables Parsing...\n");
+       
+       // Basic struct:
+       //      1) Find floating pointer
+       //      2) Go to addr referenced by floating pointer
+       //      3) Read table header info
+       
+       // We now have to search through 3 address regions searching for a magic string.
+       
+       // I unrolled this loop because I thought it was easier to read. This can be 
+       // easily packed into a for loop on an array.
+       
+       // Note: The pointer can actually be elsewhere. See the FBSD MPTables implimentation for more info
+       // Just doesn't make sense right now to check more places.
+       
+       // Search the BIOS ROM Address Space (MOST LIKELY)
+       mptables_dump("-->Searching BIOS ROM Area...\n");
+       mpfps = find_floating_pointer((physaddr_t)KADDR(BIOS_ROM_BASE), (physaddr_t)KADDR(BIOS_ROM_BOUND));
+       
+       if (mpfps == NULL) {
+               
+               // Search the EBDA UNTESTED
+               
+               // First, we have to find the darn EBDA Addr.
+               // This USSUALLY works. May be some cases where it doesnt.
+               // See osdev x86 mem-map for more information
+               physaddr_t ebda_base = read_mmreg32((uint32_t)KADDR(EBDA_POINTER));
+               
+               if (ebda_base) {
+                       ebda_base = ebda_base << 4;
+                       ebda_base = (physaddr_t)KADDR(ebda_base);
+                       physaddr_t ebda_bound = ebda_base + EBDA_SIZE - sizeof(mpfps_t);
+                       
+                       mptables_dump("-->Searching EBDA...\n");
+                       mpfps = find_floating_pointer(ebda_base, ebda_bound);
+               }
+       }
+
+       if (mpfps == NULL) {
+               // Search the last KB of system memory UNTESTED
+               
+               // Note: Will only be there if it not in the EBDA. So this must be called after the EBDA check.
+               
+               // This logic is ripped from mptables without much understanding. No machine to test it on.
+               
+               physaddr_t top_of_mem = read_mmreg32((uint32_t)KADDR(TOPOFMEM_POINTER));
+               
+               if (top_of_mem) {
+                       --top_of_mem;
+                       top_of_mem = top_of_mem * 1024;
+                       
+                       top_of_mem = (physaddr_t)KADDR(top_of_mem);
+               
+               mptables_dump("-->Searching top of (real mode) Ram...\n");
+                       mpfps = find_floating_pointer(top_of_mem, top_of_mem + 1024 - sizeof(mpfps_t));
+               }
+       }
+
+       // If we can't find the pointer, it means we are running on a non-mp compliant machine.
+       // This is bad. We can't do interrupts the way we want.
+       // We could have this trigger a MODE in which we operate using the standard PIC, if we really wanted.
+       if (mpfps == NULL) {
+               panic("MPTABLES Not found. IOAPIC and interrupts will not function properly. <Insert whale held up by smaller birds here>");
+       }
+       
+       mptables_info("-->MPTables Floating Pointer Structure found @ KVA 0x%p.\n", mpfps);
+       
+       mptables_info("-->Current Interrupt Mode: ");
+       // Identify our interrupt mode
+       if (mpfps->mpfb2 & IMCRP_MASK) {
+               current_interrupt_mode = PIC;
+               mptables_info("PIC\n");
+       }
+       else {
+               current_interrupt_mode = VW;
+               mptables_info("Virtual Wire\n");
+       }
+       
+       mptables_info("\n");
+       
+       configuration_parse((physaddr_t)KADDR((uint32_t)(mpfps->pap)));
+       proc_parse(             mp_entries[PROC], mp_entries_count[PROC]);
+       bus_parse(              mp_entries[BUS], mp_entries_count[BUS]);
+       ioapic_parse(   mp_entries[IOAPIC], mp_entries_count[IOAPIC]);
+       int_parse(              mp_entries[INT], mp_entries_count[INT]);
+       lint_parse(             mp_entries[LINT], mp_entries_count[LINT]);
+       
+/*
+       // debugging the parsing.
+       cprintf("\n");
+       cprintf("max_pci_device: %u\n", max_pci_device);
+       cprintf("max_pci_bus: %u\n", max_pci_bus);
+       cprintf("num_ioapics: %u\n", num_ioapics);
+       cprintf("max_ioapic_id: %u\n", max_ioapic_id);
+       int n =0;
+       for (int i = 0; i <= max_pci_bus; i++) {
+               for (int j = 0; j <= max_pci_device; j++) {
+                       for (int k = 0; k < 4; k++) {
+                               if (pci_int_groups[i][j].intn[k].dstApicID != 0xFF) {
+                                       cprintf("Bus: %u\n", i);
+                                       cprintf("Device: %u\n", j);
+                                       cprintf("ApicID: %u\n", pci_int_groups[i][j].intn[k].dstApicID);
+                                       cprintf("INTLINE: %u\n", pci_int_groups[i][j].intn[k].dstApicINT);
+                                       cprintf("\n");
+                                       n++;
+                               }
+                       }
+               }
+       }
+       cprintf("n: %u\n", n);
+       for (int i = 0; i <= max_ioapic_id; i++) {
+               if ((ioapic_entries[i].apicFlags & 0x1) != 0) {
+                       cprintf("IOAPIC ID: %u\n", ioapic_entries[i].apicID);
+                       cprintf("IOAPIC Offset: %x\n", ioapic_entries[i].apicAddress);
+                       cprintf("\n");
+               }
+       }
+*/     
+       
+}
+
+// Searches the given address range, starting at addr first, to (including) last, for the mptables pointer.
+// Does not esure base/bounds are sane.
+mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound) {
+
+       mpfps_t* mpfps = (mpfps_t*)base;        
+
+       // Loop over the entire range looking for the signature. The signature is ascii _MP_, which is
+       //  stored in the given MP_SIG
+       while ( ((physaddr_t)mpfps <= bound) && (read_mmreg32((uint32_t)(mpfps->signature)) != MP_SIG)) {
+               mpfps++;
+       }
+       
+       if ((physaddr_t)mpfps > bound) 
+               return NULL;
+       
+       // Now perform a checksum on the float
+       if (checksum((physaddr_t)mpfps, sizeof(mpfps_t) * mpfps->length) == FALSE) {
+               mptables_dump("-->Failed a MPTables Floating Pointer Structure checksum @ KVA 0x%p.\n", mpfps);
+               
+               // If we fail we need to keep checking. But if we are on the last addr
+               //      we just fail.
+               if ((physaddr_t)mpfps == bound)
+                       return NULL;
+               
+               return find_floating_pointer((physaddr_t)(mpfps + 1), bound);
+       }
+       
+       return mpfps;
+}
+
+bool checksum(physaddr_t addr, uint32_t len) {
+       // MP Table checksums must add up to 0.
+       uint8_t checksum = 0;
+
+       for (int i = 0; i < len; i++)
+               checksum += *((uint8_t*)addr + i);
+
+       return (checksum == 0);
+}
+
+// Go over the configuration table and parse / load the data into the global variables
+// NOTE: This uses kmalloc. Might be cleaner (but less flexable) to allocate fixed amounts
+//     set to high numbers.
+void configuration_parse(physaddr_t conf_addr) {
+       
+       int num_processed[NUM_ENTRY_TYPES];
+       
+       mpcth_t *mpcth = (mpcth_t*)conf_addr;
+       
+       for (int i = 0; i < NUM_ENTRY_TYPES; i++) {
+               mp_entries_count[i] = num_processed[i] = 0;
+               mp_entries[i] = 0;
+       }
+               
+       // Do 1 pass to figure out how much space to allocate we need.
+       uint16_t num_entries = mpcth->entry_count;
+       physaddr_t current_addr = (physaddr_t)(mpcth + 1);
+               
+       for (int i = 0; i < num_entries; i++) {
+               uint8_t current_type = *((uint8_t*)current_addr);
+               if (current_type >= NUM_ENTRY_TYPES)
+                       panic("CORRUPT MPTABLES CONFIGURATION ENTRY");
+                       
+               mp_entries_count[current_type]++;
+               current_addr += basetableEntryTypes[current_type].length;
+       }
+       
+       // Allocate the correct space in the mp_entries array
+       for (int i = 0; i < NUM_ENTRY_TYPES; i++) {
+               mp_entries[i] = kmalloc(mp_entries_count[i] * basetableEntryTypes[i].length , 0);
+       }
+       
+       current_addr = current_addr = (physaddr_t)(mpcth + 1);
+       for (int i = 0; i < num_entries; i++) {
+               uint8_t current_type = *((uint8_t*)current_addr);
+               if (current_type >= NUM_ENTRY_TYPES)
+                       panic("CORRUPT MPTABLES CONFIGURATION ENTRY.. after we already checked? Huh.");
+               
+               memcpy( mp_entries[current_type] + num_processed[current_type] * basetableEntryTypes[current_type].length, 
+                               (void*)current_addr,  
+                               basetableEntryTypes[current_type].length);
+
+               num_processed[current_type]++;
+               current_addr += basetableEntryTypes[current_type].length;
+       }
+       
+       // We'd do extended table support stuff here (or alter the loop above)
+       
+       // We now have all of our entries copied into a single structure we can index into. Yay.
+}
+
+void proc_parse(proc_entry* entries, uint32_t count) {
+       // For now, we don't do anything with the processor entries. Just print them.
+       
+       for (int i = 0; i < count; i++){
+               mptables_dump("Proc entry %u\n", i);
+               mptables_dump("-->type: %x\n", entries[i].type);
+               mptables_dump("-->apicID: %x\n", entries[i].apicID);
+               mptables_dump("-->apicVersion: %x\n", entries[i].apicVersion);
+               mptables_dump("-->cpuFlags: %x\n", entries[i].cpuFlags);
+               mptables_dump("-->cpuSignaure: %x\n", entries[i].cpuSignature);
+               mptables_dump("-->featureFlags: %x\n", entries[i].featureFlags);
+       }
+       
+       mptables_dump("\n");
+}
+
+void bus_parse(bus_entry* entries, uint32_t count) {
+       // Do we need to sort this?
+       // For now, don't. We assume the index into this structure matches the type.
+       // This seems to be implied from the configuration
+       
+       for (int i = 0; i < count; i++){
+               if (i != entries[i].busID) 
+                       panic("Oh noes! We need to sort entries. The MP Spec lied! Ok lied is too strong a word, it implied.");
+                       
+               mptables_dump("Bus entry %u\n", i);
+               mptables_dump("-->type: %x\n", entries[i].type);
+               mptables_dump("-->BusID: %x\n", entries[i].busID);
+               mptables_dump("-->Bus: %c%c%c\n", entries[i].busType[0], entries[i].busType[1], entries[i].busType[2]);
+               
+               if ((strncmp(entries[i].busType, "PCI", 3) == 0) && (entries[i].busID > max_pci_bus))
+                       max_pci_bus = entries[i].busID;
+               
+       }
+       
+       mptables_dump("\n");
+}
+
+void ioapic_parse(ioapic_entry* entries, uint32_t count) {
+
+       // Note: We don't check if the apicFlags is 0. If zero, unusable
+       // This should be done elsewhere.
+       
+       num_ioapics = count;
+       
+       for (int i = 0; i < count; i++){
+               mptables_dump("IOAPIC entry %u\n", i);
+               mptables_dump("-->type: %x\n", entries[i].type);
+               mptables_dump("-->apicID: %x\n", entries[i].apicID);
+               mptables_dump("-->apicVersion: %x\n", entries[i].apicVersion);
+               mptables_dump("-->apicFlags: %x\n", entries[i].apicFlags);
+               mptables_dump("-->apicAddress: %p\n", entries[i].apicAddress);
+               
+               if (entries[i].apicID > max_ioapic_id)
+                       max_ioapic_id = entries[i].apicID;
+       }
+       mptables_dump("\n");
+       
+       // Setup the indexable ioapic array.
+       // YOU MUST check the flag field to see if its 0. If 0, unusable.
+       // Ths is defined by MPTables, and I leaverage this with the memset below.
+       memset(ioapic_entries, 0, sizeof(ioapic_entries));
+       
+       for (int i = 0; i < count; i++) {
+               memcpy((void*)(ioapic_entries + entries[i].apicID), (void*)(entries + i), sizeof(ioapic_entry));
+       }
+}
+
+void int_parse(int_entry* entries, uint32_t count) {
+       // create a massive array, tied together with bus/dev, for indexing
+       
+       for (int i = 0; i < count; i++){
+               mptables_dump("Interrupt entry %u\n", i);
+               mptables_dump("-->type: %x\n", entries[i].type);
+               mptables_dump("-->intType: %x\n", entries[i].intType);
+               mptables_dump("-->srcBusID: %u\n", entries[i].srcBusID);
+               mptables_dump("-->srcDevice: %u\n", (entries[i].srcBusIRQ >> 2) & 0x1F);
+               mptables_dump("-->srcBusIRQ: %x\n", entries[i].srcBusIRQ);
+               mptables_dump("-->dstApicID: %u\n", entries[i].dstApicID);
+               mptables_dump("-->dstApicINT: %u\n", entries[i].dstApicINT);
+               
+               // Find the max PCI device.
+               if (strncmp(((bus_entry*)mp_entries[BUS])[entries[i].srcBusID].busType, "PCI", 3) == 0) {
+                       
+                       // Mask out the device number
+                       int device_num = (entries[i].srcBusIRQ >> 2) & 0x1F;
+                       if (device_num > max_pci_device)
+                               max_pci_device= device_num;
+               }                       
+       }
+       mptables_dump("\n");
+       
+       memset(pci_int_groups, 0xFF, sizeof(pci_int_groups));
+
+       // We define an IOAPIC ID over 255 to be invalid.
+
+       // Populate the PCI structure with the interrupt entries.
+       for (int i = 0; i < count; i++) {
+               if (strncmp(((bus_entry*)mp_entries[BUS])[entries[i].srcBusID].busType, "PCI", 3) == 0) {
+                       int bus_idx, dev_idx, int_idx;
+                       bus_idx = entries[i].srcBusID;
+                       dev_idx = (entries[i].srcBusIRQ >> 2) & 0x1F;
+                       int_idx = entries[i].srcBusIRQ & 0x3;
+                       pci_int_groups[bus_idx][dev_idx].intn[int_idx].dstApicID = entries[i].dstApicID;
+                       pci_int_groups[bus_idx][dev_idx].intn[int_idx].dstApicINT = entries[i].dstApicINT;
+               }                       
+       }
+}
+
+void lint_parse(int_entry* entries, uint32_t count) {
+       // For now, we don't do anything with the local interrupt entries
+       
+       for (int i = 0; i < count; i++){
+               mptables_dump("Local Interrupt entry %u\n", i);
+               mptables_dump("-->type: %x\n", entries[i].type);
+               mptables_dump("-->intType: %x\n", entries[i].intType);
+               mptables_dump("-->srcBusID: %x\n", entries[i].srcBusID);
+               mptables_dump("-->srcBusIRQ: %x\n", entries[i].srcBusIRQ);
+               mptables_dump("-->dstApicID: %p\n", entries[i].dstApicID);
+               mptables_dump("-->dstApicINT: %p\n", entries[i].dstApicINT);
+               
+       }
+}
+
+
+
+// Old backup code of how we made it work before. 
+// void setup_interrupts() {
+//     
+//     extern handler_t interrupt_handlers[];
+//     
+//     nic_debug("-->Setting interrupts.\n");
+//     
+//     // Enable NIC interrupts
+//     outw(io_base_addr + RL_IM_REG, RL_INTERRUPT_MASK);
+//     
+//     //Clear the current interrupts.
+//     outw(io_base_addr + RL_IS_REG, RL_INTRRUPT_CLEAR);
+//     
+//     // Kernel based interrupt stuff
+//     register_interrupt_handler(interrupt_handlers, KERNEL_IRQ_OFFSET + irq, nic_interrupt_handler, 0);
+//     //pic_unmask_irq(irq); // move this after we setup redirection
+//     //unmask_lapic_lvt(LAPIC_LVT_LINT0);
+//     
+//     // Program the IOAPIC
+//     
+//     uint32_t redirect_low = KERNEL_IRQ_OFFSET + irq;
+//     redirect_low = redirect_low | 0xa000;
+//     uint32_t redirect_high = 0x7000000;
+// 
+//     cprintf("Trying table entry....\n");
+//     
+//     uint32_t table_entry = 16;
+//     write_mmreg32(IOAPIC_BASE, 0x10 + 2*table_entry);
+//     write_mmreg32(IOAPIC_BASE + 0x10, redirect_low);
+//     
+//     write_mmreg32(IOAPIC_BASE, 0x10 + 2*table_entry + 1);
+//     write_mmreg32(IOAPIC_BASE + 0x10, redirect_high);
+//     
+//     udelay(1000000);
+//     outb(io_base_addr + 0x38, 0x1);
+//     
+//     udelay(100000000);
+//     
+//     
+// /*
+//     udelay(1000000);
+//     uint32_t ka_mp_table = 0;
+//     uint32_t ka_mp_table_base = 0;
+// 
+//     for (int i = 0xf0000; i < 0xf0000 + 0x10000; i=i+4)
+//     {
+//             if(read_mmreg32((int)KADDR(i)) == 0x5f504d5f)
+//             {
+//                     cprintf("VICTORY! ");
+//                     ka_mp_table_base = (int)KADDR(i);
+//                     ka_mp_table = (int)KADDR(read_mmreg32((int)KADDR(i+4)));
+//                     cprintf("ADDR: %p\n", PADDR(ka_mp_table));
+//                     break;
+//             }
+//     }
+//     
+//     uint32_t ka_mp_table_cur_ptr = ka_mp_table;
+//     uint32_t num_entries = read_mmreg32(ka_mp_table_cur_ptr + 0x20) >> 16;
+//     
+//     cprintf("num_entires: %d\n", num_entries);
+//     cprintf("spec_rev: %x\n",   read_mmreg32(ka_mp_table_base + 9) & 0xFF);
+//     cprintf("checksum: %x\n",   read_mmreg32(ka_mp_table_base + 10) & 0xFF);
+//     cprintf("byte 1: %x\n",   read_mmreg32(ka_mp_table_base + 11) & 0xFF);
+//     cprintf("byte 2: %x\n",   read_mmreg32(ka_mp_table_base + 12) & 0xFF);
+//     
+//     
+//     ka_mp_table_cur_ptr = ka_mp_table + 0x2c;
+//     for (int i = 0; i < num_entries; i++) {
+//             
+//             uint32_t low = read_mmreg32(ka_mp_table_cur_ptr);
+//             uint32_t high = read_mmreg32(ka_mp_table_cur_ptr + 4);
+//             uint8_t type = low & 0xFF;
+//             
+//             switch(type) {
+//                     case 0:
+//                             cprintf("Found Processor Entry\n");
+//                             ka_mp_table_cur_ptr += 20;
+//                             break;
+//                     
+//                     case 1:
+//                             cprintf("Found Bus Entry\n");
+// 
+//                             cprintf("-->%c%c%c\n", (char)(low >>16 & 0xFF), (char)(low >> 24 & 0xFF), (char)(high & 0xFF));
+//                             cprintf("-->id: %u\n\n", (low >> 8) & 0xFF);
+//                             
+//                             
+//                             ka_mp_table_cur_ptr += 8;
+//                             break;
+//                     
+//                     case 2:
+//                             cprintf("Found IOAPIC Entry\n");
+//                             cprintf("-->ID: %u\n", (low >> 8) & 0xFF);
+//                             cprintf("-->addr: %p\n", high);
+//                             
+//                             ka_mp_table_cur_ptr += 8;
+//                             break;
+//                     
+//                     case 3:
+//                             cprintf("Found IO Interrupt Entry\n");
+// 
+//                             // only print if we found something hooked to the ioapic
+//                             if (((high >> 16) & 0xFF) == 8) {
+//     
+//                                     cprintf("-->TYPE: %u\n", (low >> 8) & 0xFF);
+//                                     cprintf("-->FLAGS: %x\n", (low >> 16) & 0xFFFF);
+//                                     cprintf("-->BUS ID: %u\n", (high) & 0xFF);
+//                                     cprintf("-->BUS IRQ: %x\n", (high >> 8) & 0xFF);
+//                                     cprintf("---->SOURCE INT#: %x\n", (high >> 8) & 0x03);
+//                                     cprintf("---->SOURCE DEV#: %x\n", (high >> 10) & 0x1F);
+//                                     cprintf("-->DEST APIC ID: %u\n", (high >> 16) & 0xFF);
+//                                     cprintf("-->DEST APIC ID INITIN: %u\n\n", (high >> 24) & 0xFF);
+//                             }
+//                     
+//                             
+//                             ka_mp_table_cur_ptr += 8;
+//                             break;
+//                     
+//                     case 4:
+//                             cprintf("Found Local Interrupt Entry\n");
+//                             ka_mp_table_cur_ptr += 8;
+//                             break;
+//                     
+//                     default:
+//                             cprintf("Unknown type! Danger! Failing out\n");
+//                             i = num_entries;
+//             }
+//             
+//     
+//             
+//     }
+// */
+// /*
+//     // ugly test code for ioapic
+//     udelay(1000000);
+// 
+//     cprintf("flooding table\n");
+//     
+//     for (int j = 0; j < 256; j++) {
+//             redirect_low = j << 8;
+//             redirect_low = redirect_low | (KERNEL_IRQ_OFFSET + irq);
+//             cprintf("trying %x\n", j);
+//             
+//             for (int i = 16; i < 17; i++) {
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//                     write_mmreg32(IOAPIC_BASE + 0x10, redirect_low);
+//             
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//                     write_mmreg32(IOAPIC_BASE + 0x10, redirect_high);
+//             }
+//             
+//             udelay(100000);
+//             
+//             outb(io_base_addr + 0x38, 0x1);
+//             
+//             udelay(100000);
+//     }
+// 
+//     udelay(10000000000);    
+// */          
+// 
+// /*
+//     
+//     cprintf("Generating test interrupt....\n");
+//     outb(io_base_addr + 0x38, 0x1);
+// 
+//     udelay(1000000);
+//     uint32_t old_low = -1;
+//     uint32_t old_high = -1;
+//     uint32_t new_low = -1;
+//     uint32_t new_high = -1;
+// 
+//     for (int i = 0; i <= 24; i++) {
+//             
+//             if (i != 0) {
+//                     cprintf("     masking %u with: %x %x\n\n", i-1, old_high, old_low);
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*(i-1));
+//                     write_mmreg32(IOAPIC_BASE + 0x10, old_low);
+//                     
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*(i-1) + 1);
+//                     write_mmreg32(IOAPIC_BASE + 0x10, old_high);
+//             }
+//             
+//             if (i == 24)
+//                     break;
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             old_low = read_mmreg32(IOAPIC_BASE + 0x10);
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             old_high = read_mmreg32(IOAPIC_BASE + 0x10);
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             write_mmreg32(IOAPIC_BASE + 0x10, redirect_low);
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             write_mmreg32(IOAPIC_BASE + 0x10, redirect_high);
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             new_low = read_mmreg32(IOAPIC_BASE + 0x10);
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             new_high = read_mmreg32(IOAPIC_BASE + 0x10);    
+//             
+//             //Trigger sw based nic interrupt
+//             cprintf("Trying entry: %u....(WAS: %x %x   NOW: %x %x)\n", i, old_high, old_low, new_high, new_low);
+//             outb(io_base_addr + 0x38, 0x1);
+//             udelay(100000);
+//             outb(io_base_addr + 0x38, 0x1);
+//             udelay(1000000);
+//     }
+// */  
+//     
+//     /*
+//     udelay(1000000);
+//     
+//     old_high = -1;
+//     old_low = -1;
+//     
+//     for (int i = 23; i >= -1; i--) {
+//             
+//             if (i != 23) {
+//                     cprintf("     masking %u with: %x %x\n\n", i+1, old_high, old_low);
+//                     
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*(i + 1));
+//                     write_mmreg32(IOAPIC_BASE + 0x10, old_low);
+//                     
+//                     write_mmreg32(IOAPIC_BASE, 0x10 + 2*(i + 1) + 1);
+//                     write_mmreg32(IOAPIC_BASE + 0x10, old_high);
+// 
+//             }
+//             
+//             if (i == -1)
+//                     break;
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             old_low = read_mmreg32(IOAPIC_BASE + 0x10);
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             old_high = read_mmreg32(IOAPIC_BASE + 0x10);
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             write_mmreg32(IOAPIC_BASE + 0x10, redirect_low);
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             write_mmreg32(IOAPIC_BASE + 0x10, redirect_high);       
+//             
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i);
+//             new_low = read_mmreg32(IOAPIC_BASE + 0x10);
+//             write_mmreg32(IOAPIC_BASE, 0x10 + 2*i + 1);
+//             new_high = read_mmreg32(IOAPIC_BASE + 0x10);    
+//             
+//             //Trigger sw based nic interrupt
+//             cprintf("Trying entry: %u....(WAS: %x %x   NOW: %x %x)\n", i, old_high, old_low, new_high, new_low);
+//             outb(io_base_addr + 0x38, 0x1);
+//             udelay(100000);
+//             outb(io_base_addr + 0x38, 0x1);
+//             udelay(1000000);
+//     }
+//     udelay(1000000); 
+//     
+// */  
+//     /*
+//     cprintf("low: %u\nhigh %u\n", redirect_low, redirect_high);
+// 
+//     write_mmreg32(IOAPIC_BASE, 0xA0 );
+//     cprintf("IOAPIC Mappings%x\n", read_mmreg32(IOAPIC_BASE + 0x10));*/
+// 
+// //  cprintf("Core 1 LAPIC ID: %x\n", read_mmreg32(0x0FEE00020));
+// 
+//     
+// //  panic("WERE ALL GONNA DIE!");
+// 
+//     return;
+// }
\ No newline at end of file
diff --git a/kern/src/pci.c b/kern/src/pci.c
new file mode 100644 (file)
index 0000000..c75d0e2
--- /dev/null
@@ -0,0 +1,135 @@
+#ifdef __DEPUTY__
+#pragma nodeputy
+#endif
+
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/smp.h>
+#include <arch/apic.h>
+
+#include <ros/memlayout.h>
+
+#include <atomic.h>
+#include <stdio.h>
+#include <string.h>
+#include <pci.h>
+#include <trap.h>
+#include <kmalloc.h>
+
+#include <pmap.h>
+
+/* PCI ?Driver?
+ *
+ * Written by Paul Pearce.
+ *
+ * Insight into functionality goes here
+ *
+ * TODO: Write it
+ */
+
+// 256 or larger means invalid irq.
+uint16_t pci_irq_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+
+pci_dev_entry pci_dev_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+
+pci_irq_entry irq_pci_map[NUM_IRQS];
+// NOTE: If we care about ALL devices associated with an IRQ, not just the last device, this needs to be some sort of linked structure
+// For now we don't so this isnt.
+
+void pci_init() {
+       
+       // Initalize the irq->pci table (pci->irq below)
+       // Setting all 1's forces an invalid entry, as bus > 255.
+       memset(irq_pci_map, 0xFF, sizeof(irq_pci_map));
+       
+       
+       uint32_t address;
+       uint32_t lbus = 0;
+       uint32_t ldev = 0;
+       uint32_t lfunc = 0;
+       uint32_t lreg = 0; 
+       uint32_t result  = 0;
+       pci_debug("Scanning PCI Bus....\n");
+
+       for (int i = 0; i < PCI_MAX_BUS; i++)
+               for (int j = 0; j < PCI_MAX_DEV; j++)
+                       for (int k = 0; k < PCI_MAX_FUNC; k++) {
+
+                               lbus = i;
+                               ldev = j;
+                               lfunc = k;
+                               lreg = 0; // PCI REGISTER 0
+                               
+                               // Set the fields invalid.
+                               pci_irq_map[i][j][k] = INVALID_IRQ;
+                               pci_dev_map[i][j][k].dev_id = INVALID_VENDOR_ID;
+
+                               address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg); 
+
+                               // Probe current bus/dev
+                               outl(PCI_CONFIG_ADDR, address);
+                               result = inl(PCI_CONFIG_DATA);
+       
+                               uint16_t dev_id = result >> PCI_DEVICE_OFFSET;
+                               uint16_t ven_id = result & PCI_VENDOR_MASK;
+
+                               // Vender DNE
+                               if (ven_id == INVALID_VENDOR_ID) 
+                                       continue;
+
+                               pci_debug("Found device on BUS %x DEV %x FUNC %x: DEV_ID: %x VEN_ID: %x\n", i, j, k, dev_id, ven_id);
+
+                               // Find the IRQ
+                               address = MK_CONFIG_ADDR(lbus, ldev, lfunc, PCI_IRQ_REG);
+                               outl(PCI_CONFIG_ADDR, address);
+                               uint16_t irq = inl(PCI_CONFIG_DATA) & PCI_IRQ_MASK;
+                               pci_debug("-->IRQ: %u\n", irq);
+                               
+                               // Find the INTN
+                               address = MK_CONFIG_ADDR(lbus, ldev, lfunc, PCI_IRQ_REG);
+                               outl(PCI_CONFIG_ADDR, address);
+                               uint8_t intn = (inl(PCI_CONFIG_DATA) & PCI_INTN_MASK) >> PCI_INTN_SHFT;
+                               
+                               // If intn == 0, no interrupts used.
+                               if (intn != INVALID_INTN) {
+                                       
+                                       // Now shift A to 0, B to 1, etc.
+                                       intn--;
+                               
+                                       pci_irq_map[i][j][k] = irq;
+                                       pci_dev_map[i][j][k].dev_id = dev_id;
+                                       pci_dev_map[i][j][k].ven_id = ven_id;
+                                       irq_pci_map[irq].bus = i;
+                                       irq_pci_map[irq].dev = j;
+                                       irq_pci_map[irq].func = k;
+                                       irq_pci_map[irq].intn = intn;
+                               }
+                               
+
+                               // Loop over the BARs
+                               // We should do something useful with this data. But what?
+                               for (int k = 0; k <= 5; k++) {
+                                       lreg = 4 + k;
+                                       address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
+                               outl(PCI_CONFIG_ADDR, address);
+                               result = inl(PCI_CONFIG_DATA);
+                                       
+                                       if (result == 0) // (0 denotes no valid data)
+                                               continue;
+
+                                       // Read the bottom bit of the BAR. 
+                                       if (result & PCI_BAR_IO_MASK) {
+                                               result = result & PCI_IO_MASK;
+                                               pci_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
+                                       } else {
+                                               result = result & PCI_MEM_MASK;
+                                               pci_debug("-->BAR%u: %s --> %x\n", k, "MEM", result);
+                                       }                                       
+                               }
+                               
+                               pci_debug("\n");
+                       }               
+}
+
+
index d23f1e6..e1e495c 100644 (file)
@@ -17,6 +17,7 @@
 #include <kmalloc.h>
 
 #include <pmap.h>
+#include <pci.h>
 
 /* RealTek 8168d (8111d) NIC Driver
  *
@@ -77,7 +78,7 @@ char* packet_buffer_orig;
 int packet_buffer_pos = 0;
 // End hacky stuff
 
-void init_nic() {
+void nic_init() {
        
        if (scan_pci() < 0) return;
        read_mac();
@@ -87,78 +88,72 @@ void init_nic() {
        eth_up = 1;
        
        //Trigger sw based nic interrupt
-       //outb(io_base_addr + 0x38, 0x1);
-       //udelay(3000000);
-       
+/*     cprintf("Generating interrupt...\n");
+       outb(io_base_addr + 0x38, 0x1);
+       cprintf("sleeping\n");
+       udelay(3000000);
+       cprintf("done\n");
+*/
        return;
 }
 
 
 int scan_pci() {
        
-       uint32_t address;
-       uint32_t lbus = 0;
-       uint32_t ldev = 0;
-       uint32_t lfunc = 0; // We only look at function 0 for now.
-       uint32_t lreg = 0; 
-       uint32_t result  = 0;
+       extern pci_dev_entry pci_dev_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+       extern uint16_t pci_irq_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+
        cprintf("Searching for RealTek 8168 Network device......");
 
        for (int i = 0; i < PCI_MAX_BUS; i++)
-               for (int j = 0; j < PCI_MAX_DEV; j++) {
-
-               lbus = i;
-               ldev = j;
-               lreg = 0; // PCI REGISTER 0
-
-               address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg); 
-
-               // Probe current bus/dev
-               outl(PCI_CONFIG_ADDR, address);
-               result = inl(PCI_CONFIG_DATA);
-       
-               uint16_t dev_id = result >> PCI_DEVICE_OFFSET;
-               uint16_t ven_id = result & PCI_VENDOR_MASK;
-
-               // Vender DNE
-               if (ven_id == INVALID_VENDOR_ID) 
-                       continue;
-
-               // Ignore non RealTek 8168 Devices
-               if (ven_id != REALTEK_VENDOR_ID || dev_id != REALTEK_DEV_ID)
-                       continue;
-               cprintf(" found on BUS %x DEV %x\n", i, j);
-
-               // Find the IRQ
-               address = MK_CONFIG_ADDR(lbus, ldev, lfunc, PCI_IRQ_REG);
-               outl(PCI_CONFIG_ADDR, address);
-               irq = inl(PCI_CONFIG_DATA) & PCI_IRQ_MASK;
-               nic_debug("-->IRQ: %u\n", irq);
-
-               // Loop over the BARs
-               for (int k = 0; k <= 5; k++) {
-                       lreg = 4 + k;
-                       address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
-               outl(PCI_CONFIG_ADDR, address);
-               result = inl(PCI_CONFIG_DATA);
+               for (int j = 0; j < PCI_MAX_DEV; j++)
+                       for (int k = 0; k < PCI_MAX_FUNC; k++) {
+                               uint32_t address;
+                               uint32_t lbus = i;
+                               uint32_t ldev = j;
+                               uint32_t lfunc = k;
+                               uint32_t lreg = 0; 
+                               uint32_t result  = 0;
+       
+                               uint16_t dev_id = pci_dev_map[i][j][k].dev_id;
+                               uint16_t ven_id = pci_dev_map[i][j][k].ven_id;
+
+                               // Vender DNE
+                               if (ven_id == INVALID_VENDOR_ID) 
+                                       continue;
+
+                               // Ignore non RealTek 8168 Devices
+                               if (ven_id != REALTEK_VENDOR_ID || dev_id != REALTEK_DEV_ID)
+                                       continue;
+                               cprintf(" found on BUS %x DEV %x\n", i, j);
+
+                               // Find the IRQ
+                               irq = pci_irq_map[i][j][k];
+                               nic_debug("-->IRQ: %u\n", irq);
+
+                               // Loop over the BARs
+                               for (int k = 0; k <= 5; k++) {
+                                       lreg = 4 + k;
+                                       address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
+                               outl(PCI_CONFIG_ADDR, address);
+                               result = inl(PCI_CONFIG_DATA);
                                        
-                       if (result == 0) // (0 denotes no valid data)
-                               continue;
-
-                       // Read the bottom bit of the BAR. 
-                       if (result & PCI_BAR_IO_MASK) {
-                               result = result & PCI_IO_MASK;
-                               nic_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
-                       } else {
-                               result = result & PCI_MEM_MASK;
-                               nic_debug("-->BAR%u: %s --> %x\n", k, "MEM", result);
-                       }
+                                       if (result == 0) // (0 denotes no valid data)
+                                               continue;
+
+                                       // Read the bottom bit of the BAR. 
+                                       if (result & PCI_BAR_IO_MASK) {
+                                               result = result & PCI_IO_MASK;
+                                               nic_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
+                                       } else {
+                                               result = result & PCI_MEM_MASK;
+                                               nic_debug("-->BAR%u: %s --> %x\n", k, "MEM", result);
+                                       }
                        
-                       // TODO Switch to memory mapped instead of IO?
-                       if (k == 0) // BAR0 denotes the IO Addr for the device
-                               io_base_addr = result;                                          
-               }
+                                       // TODO Switch to memory mapped instead of IO?
+                                       if (k == 0) // BAR0 denotes the IO Addr for the device
+                                               io_base_addr = result;                                          
+                               }
                
                nic_debug("-->hwrev: %x\n", inl(io_base_addr + RL_HWREV_REG) & RL_HWREV_MASK);
                
@@ -349,9 +344,9 @@ void setup_interrupts() {
        
        // Kernel based interrupt stuff
        register_interrupt_handler(interrupt_handlers, KERNEL_IRQ_OFFSET + irq, nic_interrupt_handler, 0);
-       pic_unmask_irq(irq);
-       unmask_lapic_lvt(LAPIC_LVT_LINT0);
-       
+       //pic_unmask_irq(irq);
+       //unmask_lapic_lvt(LAPIC_LVT_LINT0);
+       ioapic_route_irq(irq, 7);       
        return;
 }
 
index 924ccd3..0c5210a 100644 (file)
@@ -251,10 +251,16 @@ void
        // All others are LAPIC (timer, IPIs, perf, non-ExtINT LINTS, etc)
        // For now, only 235-255 are available
        assert(tf->tf_trapno >= 32); // slows us down, but we should never have this
+       
+       lapic_send_eoi();
+       
+/*     Old PIC relatd code. Should be gone for good, but leaving it just incase.
        if (tf->tf_trapno < 48)
-               pic_send_eoi(tf->tf_trapno - PIC1_OFFSET);
+               //pic_send_eoi(tf->tf_trapno - PIC1_OFFSET);
+               ioapic_send_eoi(tf->tf_trapno); // Quick hack. Fix.
        else
                lapic_send_eoi();
+*/
 }
 
 void
index 3ce4de8..9f01d95 100644 (file)
@@ -119,9 +119,9 @@ int fstat(int file, struct stat *st)
        st->st_mode = S_IFCHR;
        
        // stdout hack
-//     if (file == 1)
-//             st->st_mode = 8592;
-//     return 0;
+       if (file == 1)
+               st->st_mode = 8592;
+       return 0;
 
 
        // Allocate a new buffer of proper size
@@ -182,9 +182,9 @@ int isatty(int file)
        debug_in_out("ISATTY\n");
 
        // Cheap hack to avoid sending serial comm for stuff we know
-//     if ((STDIN_FILENO == file) || (STDOUT_FILENO == file) 
-//                                || (STDERR_FILENO == file))
-//             return 1;
+       if ((STDIN_FILENO == file) || (STDOUT_FILENO == file) 
+                                || (STDERR_FILENO == file))
+               return 1;
 
        
        // Allocate a new buffer of proper size