Added doxygen support to pci/mptables/ioapic.c. General code cleanup across all files...
authorPaul Pearce <pearce@eecs.berkeley.edu>
Mon, 31 Aug 2009 05:37:53 +0000 (22:37 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Mon, 31 Aug 2009 06:49:01 +0000 (23:49 -0700)
Went through and redocumented / expanded documentation for ioapic.c, pci.c, mptables.c. I also added doxygen support for the 3 files.
Note: Currently doxygen does not like the ivy annotations and is doing really bizzare things. Zach has been notified.

Went through and cleaned up the code and variables in general for the 3 files and their headers.
This involved a few minor changes in the nic drivers.

Adjusted a doxygen configuration option that keeps random structs from showing up on versions of
doxygen newer than kevin's

Edited the GNUmakefile to no longer try to compile all of the kernel before building the docs.

Edited sys_run_binary() to restore support for dropping back into the previous enviroment, instead of the monitor.
This involved editing manager() to behave differently as well. I also setup manager() to run matrix instead of hello.

13 files changed:
GNUmakefile
doc/rosdoc.cfg
kern/arch/i386/ioapic.h
kern/include/mptables.h
kern/include/pci.h
kern/include/rl8168.h
kern/src/ioapic.c
kern/src/manager.c
kern/src/mptables.c
kern/src/ne2k.c
kern/src/pci.c
kern/src/rl8168.c
kern/src/syscall.c

index c1a7291..0a1a680 100644 (file)
@@ -112,7 +112,7 @@ $(OBJDIR)/.deps: $(foreach dir, $(OBJDIRS), $(wildcard $(OBJDIR)/$(dir)/*.d))
 -include $(OBJDIR)/.deps
 
 # Use doxygen to make documentation for ROS
-docs: all
+docs: 
        @doxygen doc/rosdoc.cfg
        @if [ ! -d doc/rosdoc/html/img ];          \
         then                                      \
index 02ace14..0086427 100644 (file)
@@ -186,7 +186,7 @@ ALIASES                =
 # For instance, some of the names that are used will be different. The list 
 # of all members will be omitted, etc.
 
-OPTIMIZE_OUTPUT_FOR_C  = NO
+OPTIMIZE_OUTPUT_FOR_C  = YES
 
 # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
 # sources only. Doxygen will then generate output that is more tailored for 
@@ -332,7 +332,7 @@ HIDE_UNDOC_MEMBERS     = NO
 # If set to NO (the default) these classes will be included in the various 
 # overviews. This option has no effect if EXTRACT_ALL is enabled.
 
-HIDE_UNDOC_CLASSES     = NO
+HIDE_UNDOC_CLASSES     = YES
 
 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
 # friend (class|struct|union) declarations. 
index aa4a88d..88ba7c2 100644 (file)
@@ -6,28 +6,54 @@
 #ifndef ROS_KERN_IOAPIC_H
 #define ROS_KERN_IOAPIC_H
 
-#include <arch/mmu.h>
-#include <arch/x86.h>
-#include <arch/apic.h>
+#include <arch/types.h>
 
-// IOAPIC
-// Paul wants this next constant to go away. its only still used
-//  for the top of memory calculations
+/* IOAPIC_BASE really go away. This is NOT required by the spec as far as I know.
+ * This was originally in apic.h, but Paul moved it here. This is NOT used by
+ * anything in the IOAPIC, just some other kernel stuff which uses it for
+ * size calculations. It should be called something else and moved.
+ */
 #define IOAPIC_BASE                                    0xfec00000 // this is the default, can be changed
 
-// These are things like level sensitive, edge triggered, fixed, nmi, extint, etc
-// I should elaborate upon these.
+/* These are things like level sensitive, edge triggered, fixed, nmi, extint, etc
+ * This is based on the x58 chipset spec. There are only 2 combinations so
+ * Paul didn't bother to spell them out bit by bit and or them together.
+ */
 #define IOAPIC_PCI_FLAGS                       0xa0
 #define IOAPIC_ISA_FLAGS                       0x00
-#define IOAPIC_PIC_FLAGS                       0x07 // Not used. 
-#define IOAPIC_BROKEN_PCI_FLAGS                IOAPIC_ISA_FLAGS // No idea if this is correct, or it should be pci.
+/* This says how we should treat PCI interrupts that are listed as ISA by mptables.
+ * This was determined by trial and error in the VM's. All current VMs that have this
+ * 'feature' use ISA style flags. 
+ * Author's note: Paul really hates whoever wrote the bochs bios (which is
+ * the source of this problem for bochs/kvm/qemu).
+ */
+#define IOAPIC_BROKEN_PCI_FLAGS                IOAPIC_ISA_FLAGS 
 
+// Obvious
 #define IOAPIC_MAX_ID                          256
 
+// The magic bits we write to kill unroute an irq. The 16th bit is the important one, being set to 1. 
+// Other bits are just to restore it to a clean boot-like state.
 #define IOAPIC_UNROUTE_LOW                     0x00010000
 #define IOAPIC_UNROUTE_HIGH                    0x00000000
 
+// Mem mapped register magic numbers. Oo magic!
+#define IOAPIC_REDIRECT_OFFSET         0x10
+#define IOAPIC_WRITE_WINDOW_OFFSET     0x10
+
+/* Structure used to define an interrupt redirection entry. 
+ * This structure encapsulates:
+ *             An IRQ
+ *             The flags used for rerouting (edge sensitive, level triggered, etc)
+ *             Ioapic ADDR (physical Addr)
+ */
+typedef struct IOAPICREDIRECT {
+    void*                      ioapic_address; // NULL means invalid
+       uint8_t                 ioapic_flags;
+       uint8_t                 ioapic_int;
+} ioapic_redirect_t;
 
+// Everyone loves a protoype.
 void ioapic_init();
 void ioapic_route_irq(uint8_t irq, uint8_t dest);
 void ioapic_unroute_irq(uint8_t irq);
index 1b1dc2c..4fb7f0f 100644 (file)
@@ -1,37 +1,66 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
 #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__)  
+/* 
+ * LICENCE NOTE: Most of these structures and some constants
+ * were blatently ripped out of BSD with <3. Only the camel 
+ * casing has been changed to protect the innocent.
+ */
+
+// OBSCENELY IMPORTANT NOTE: None of this is packed. I didn't do it because BSD didnt. This may need to change
 
+#define mptables_info(...)  printk(__VA_ARGS__)  
+#define mptables_dump(...)  //printk(__VA_ARGS__)  
 
-#define MP_SIG                 0x5f504d5f      /* _MP_ */
+// The HEX representation of the ascii string _MP_ we search for
+#define MP_SIG                         0x5f504d5f      /* _MP_ */
 
-#define BIOS_ROM_BASE  0xf0000
-#define BIOS_ROM_BOUND  0xffff0 // Inclusive.
+// Base and (inclusive bound) of the BIOS region to check
+#define BIOS_ROM_BASE          0xf0000
+#define BIOS_ROM_BOUND                 0xffff0 
 
-#define EBDA_POINTER   0x040e // Bound is dynamic. In first KB
-#define EBDA_SIZE              1024
+// Where to look for the EBDA pointer
+// Bound is dynamic. In first KB
+#define EBDA_POINTER           0x040e 
+#define EBDA_SIZE                      1024
 
-#define TOPOFMEM_POINTER       0x0413          /* BIOS: base memory size */
-#define IMCRP_MASK             0x80
+/* BIOS: base memory size */
+#define TOPOFMEM_POINTER       0x0413          
+#define IMCRP_MASK                     0x80
 
+// Sometimes the BIOS is a lying pain in my ass
+// so don't believe it and assume this top of memory and check it
 #define DEFAULT_TOPOFMEM       0xa0000
 
-#define NUM_ENTRY_TYPES 5
+// How many entry types exist? Won't ever change
+#define NUM_ENTRY_TYPES        5
+
+#define INVALID_DEST_APIC      0xffff
+
+#define MPFPS_SIZE                     16 // For ivy
+#define MPCTH_SIZE                     44
+
+// Sorry Zach, this has to be done.
+#define READ_FROM_STORED_PHYSADDR32(addr)  READ_FROM_STORED_VIRTADDR32(KADDR(addr))
+#define READ_FROM_STORED_VIRTADDR32(addr)  *((uint32_t* SAFE)addr)
 
-#define MPFPS_SIZE 16 // For ivy
 
 enum interrupt_modes {
-       PIC, // PIC Mode (Bocsh, KVM)
+       PIC, // PIC Mode 
        VW,  // Virtural Wire Mode (Dev Boxes)
-       SIO  // Once we fix up the ioapic, shift to this mode, sym io.
+       SIO  // Once we fix up the ioapic, shift to this mode (not currently used)
 };
 
+// Start BSDs lovingly barrowed structs/etc
+
 enum entry_types {
        PROC =          0,
        BUS  =          1,
@@ -40,7 +69,7 @@ enum entry_types {
        LINT =          4
 };
 
-enum busTypes {
+enum bus_types {
     CBUS = 1,
     CBUSII = 2,
     EISA = 3,
@@ -54,9 +83,9 @@ enum busTypes {
 typedef struct BUSTYPENAME {
     uint8_t    type;
     char       name[ 7 ];
-} busTypeName;
+} bus_type_name_t;
 
-static busTypeName busTypeTable[] =
+static bus_type_name_t bus_type_table[] =
 {
     { CBUS,            "CBUS"   },
     { CBUSII,          "CBUSII" },
@@ -79,11 +108,22 @@ static busTypeName busTypeTable[] =
     { UNKNOWN_BUSTYPE, "---"    }
 };
 
+
+
 typedef struct TABLE_ENTRY {
     uint8_t    type;
     uint8_t    length;
     char       name[ 32 ];
-} tableEntry;
+} table_entry_t;
+
+static table_entry_t entry_types[] =
+{
+    { 0, 20, "Processor" },
+    { 1,  8, "Bus" },
+    { 2,  8, "I/O APIC" },
+    { 3,  8, "I/O INT" },
+    { 4,  8, "Local INT" }
+};
 
 /* MP Floating Pointer Structure */
 typedef struct MPFPS {
@@ -119,50 +159,51 @@ typedef struct MPCTH {
 
 typedef struct PROCENTRY {
     uint8_t            type;
-    uint8_t            apicID;
-    uint8_t            apicVersion;
-    uint8_t            cpuFlags;
-    uint32_t   cpuSignature;
-    uint32_t   featureFlags;
+    uint8_t            apic_id;
+    uint8_t            apic_version;
+    uint8_t            cpu_flags;
+    uint32_t   cpu_signature;
+    uint32_t   feature_flags;
     uint32_t   reserved1;
     uint32_t   reserved2;
-} proc_entry;
+} proc_entry_t;
 
 typedef struct BUSENTRY {
     uint8_t    type;
-    uint8_t    busID;
-    char (NT busType)[ 6 ];
-} bus_entry;
+    uint8_t    bus_id;
+    char (NT bus_type)[ 6 ];
+} bus_entry_t;
 
 typedef struct IOAPICENTRY {
     uint8_t    type;
-    uint8_t    apicID;
-    uint8_t    apicVersion;
-    uint8_t    apicFlags;
-    void*      apicAddress;
-} ioapic_entry;
+    uint8_t    apic_id;
+    uint8_t    apic_version;
+    uint8_t    apic_flags;
+    void*      apic_address;
+} ioapic_entry_t;
 
 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;
+    uint8_t            int_type;
+    uint16_t   int_flags;
+    uint8_t            src_bus_id;
+    uint8_t            src_bus_irq;
+    uint8_t            dst_apic_id;
+    uint8_t            dst_apic_int;
+} int_entry_t;
 
 typedef struct PCIINTENTRY {
-    uint16_t           dstApicID; // A value of 256 or greater means not valid.
-    uint8_t            dstApicINT;
-} pci_int_entry;
+    uint16_t   dst_apic_id; // A value of INVALID_DEST_APIC means invalid (>=256)
+    uint8_t            dst_apic_int;
+} pci_int_entry_t;
 
-typedef pci_int_entry isa_int_entry;
+typedef pci_int_entry_t isa_int_entry_t;
 
-typedef struct PCIINTGROUP {
-       pci_int_entry intn[4];
-} pci_int_group;
+typedef struct PCIINTDEVICE {
+       pci_int_entry_t line[4];
+} pci_int_device_t;
 
+// Prototypes
 void mptables_parse();
 mpfps_t * COUNT(MPFPS_SIZE) find_floating_pointer(physaddr_t base, physaddr_t bound);
 bool checksum(physaddr_t addr, uint32_t len);
index 17e995c..ce35923 100644 (file)
@@ -1,33 +1,33 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
 #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__)  
+#define pci_debug(...) // printk(__VA_ARGS__)  
 
-// Macro for formatting PCI Configuration Address queries
+// Macro for creating the address fed to the PCI config register 
+// Several generations away from OSDev inline code.
 #define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
                                                              (FUNC << 8) | REG  | \
                                                              ((uint32_t)0x80000000))
 
-// General PCI Constants
+// General PCI Magic numbers yanked from OSDev / BSD. Yay magic!
 #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 INVALID_LINE           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_LINE_MASK          0xFF00
+#define PCI_LINE_SHFT          0x8
 #define PCI_VENDOR_MASK                0xFFFF
 #define PCI_DEVICE_OFFSET      0x10
 #define PCI_IRQ_REG                    0x3c
 #define PCI_BAR_IO_MASK                0x1
 #define NUM_IRQS                       256
 
-// Offset used for indexing IRQs
+// Offset used for indexing IRQs. Why isnt this defined elsewhere?
 #define KERNEL_IRQ_OFFSET      32
 
+// Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs, dont check em.
+#define CHECK_BARS                     0
+
 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;
+       uint8_t line;
+} pci_irq_entry_t;
 
 typedef struct PCIDEVENTRY {
        uint16_t dev_id; 
        uint16_t ven_id;
-} pci_dev_entry;
+} pci_dev_entry_t;
 
 void pci_init();
 
-
 #endif /* !ROS_INC_PCI_H */
index b536d5e..a0447ac 100644 (file)
 #define packet_wrap rl8168_packet_wrap
 #define send_frame rl8168_send_frame
 
-#define NE2K_IRQ_CPU                   5
+#define NE2K_IRQ_CPU           5
 
-// 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))
 #define REALTEK_VENDOR_ID   0x10ec
 #define REALTEK_DEV_ID      0x8168
 
index 4c7ddff..b600a21 100644 (file)
  * See LICENSE for details.
  */
 
+/** @file
+ * @brief Basic IOAPIC Driver.
+ *
+ * This file is responsible for the initalization of the Intel x58 IOAPIC(s)
+ * Once the IOAPIC is setup, the function ioapic_route_irq() can be used
+ * to route
+ *
+ * See Ch 17.5.26 in Intel X58 Express Chipset Datasheet
+ *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Come up with an impliment a concurrency model for use of the route/unroute functions
+ * @todo Once we begin using logical core ID's for groups, adjust route/unroute to utilize this (adjust high word)
+ * @todo Some notion of a 'initalized' flag we can check to ensure bootup call order.
+ */
+
+
 #include <arch/mmu.h>
 #include <arch/x86.h>
 #include <arch/apic.h>
-#include <assert.h>
 #include <mptables.h>
 #include <pci.h>
 
-/* IOAPIC ?Driver?
- *
- * Written by Paul Pearce.
- *
- * Insight into functionality goes here
+ioapic_redirect_t ioapic_redirects[NUM_IRQS];
+
+/**
+ * @brief Parse the entries from the mptables relevant to the IOAPIC and initalize the IOAPIC and its data structures
  *
- * TODO: Clean up array bounds checking (leaving it to ivy is lame, no offense to ivy, its just not good practice)
+ * This function will loop over the data structures created by MPTables to represent ISA and PCI interrupts
+ * and then setup the ioapic_redirects array to map IRQs->IOAPIC/Flags
+ * 
+ * This function must be called during bootup, before interrupts are rerouted, and after the PCI/MPTable initilization.
  */
-
-typedef struct IOAPICREDIRECT {
-    void*                      ioapic_address; // NULL means invalid (duh)
-       uint8_t                 ioapic_flags;
-       uint8_t                 ioapic_int;
-} ioapic_redirect;
-
-ioapic_redirect ioapic_redirects[NUM_IRQS];
-
 void ioapic_init() {
+       
        // Set all entires invalid.
+       // We define a entry to be invalid by having an ioapic_address of NULL (0x0)
        memset(ioapic_redirects, 0x0, sizeof(ioapic_redirects));
        
        extern uint8_t num_cpus;
-       uint32_t inconsistent_pci_mappings = 0;  // Set high if we find inconsistent mappings between
-                                                                                        //  mptables and the pci bus.
+       uint32_t num_inconsistent_pci_mappings = 0;     // Increment if we find inconsistent mappings between
+                                                                                               //  mptables and the pci bus.
        
-       // Pull in all the stuff we need from mptables and the pci parsing
-       extern pci_irq_entry irq_pci_map[NUM_IRQS];
-       extern pci_int_group pci_int_groups[PCI_MAX_BUS][PCI_MAX_DEV];
-       extern ioapic_entry ioapic_entries[IOAPIC_MAX_ID];
-       extern isa_int_entry isa_int_entries[NUM_IRQS];
+       // Pull in all the stuff we need from mptables and the pci parsing. These are all stack allocated (cant be null)
+       extern pci_irq_entry_t irq_pci_map[NUM_IRQS];
+       extern pci_int_device_t pci_int_devices[PCI_MAX_BUS][PCI_MAX_DEV];
+       extern ioapic_entry_t ioapic_entries[IOAPIC_MAX_ID];
+       extern isa_int_entry_t isa_int_entries[NUM_IRQS];
        
        // Setup the PCI entries
        for (int i = 0; i < NUM_IRQS; i++) {
+               // Bus is 16 bits as we use a sential BUS value (INVALID_BUS) to denote an invalid bus
+               //  and this valid is out of the range 0->2^8-1
                uint16_t bus = irq_pci_map[i].bus;
                uint8_t dev = irq_pci_map[i].dev;
-               uint8_t intn = irq_pci_map[i].intn;
+               uint8_t line = irq_pci_map[i].line;
                
                if (bus == INVALID_BUS)
                        continue;
 
-               uint16_t dstApicID = pci_int_groups[bus][dev].intn[intn].dstApicID;
-               uint8_t dstApicINT = pci_int_groups[bus][dev].intn[intn].dstApicINT;
+               // We do the same trick with the dest apic ID as we do with the PCI Bus, so its wider.
+               uint16_t dst_apic_id = pci_int_devices[bus][dev].line[line].dst_apic_id;
+               uint8_t dst_apic_int = pci_int_devices[bus][dev].line[line].dst_apic_int;
                
-               // MP Tables uses 8 bits to store the apic id. If our value is larger, is invalid entry
-               // If we have a valid bus in the irq->pci map, and the pic->int entry doesnt exist, we have a major problem
-               if (dstApicID == 0xFFFF) {
-                       if (!inconsistent_pci_mappings)
-                               cprintf("WARNING: INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS. Trying to cope...\n");
-                       inconsistent_pci_mappings++;
+               // Check if this entry has been set
+               if (dst_apic_id == INVALID_DEST_APIC) {
+                       // If we have a valid bus in the irq->pci map, and the pic->int entry doesnt exist, we have a (probably VM) problem
+                       if (num_inconsistent_pci_mappings == 0)
+                               printk("WARNING: INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS. Trying to cope...\n");
+                       num_inconsistent_pci_mappings++;
                        continue;
                }
                
-               // If the lowest bit of the apic flags is set to 0, it means the ioapic is not usable.
+               // If the lowest bit of the apic flags is set to 0, it means the ioapic is not usable (by MP Spec)
                // We also use this to denote non-existent ioapics in our map
-               if ((ioapic_entries[dstApicID].apicFlags & 0x1) == 0) 
+               if ((ioapic_entries[dst_apic_id].apic_flags & 0x1) == 0) 
                        panic("IRQ SAYS ITS GOING TO AN IOAPIC LISTED AS INVALID, THATS BAD.");
                                        
-               ioapic_redirects[i].ioapic_address = ioapic_entries[dstApicID].apicAddress;
-               ioapic_redirects[i].ioapic_int = dstApicINT;
+               ioapic_redirects[i].ioapic_address = ioapic_entries[dst_apic_id].apic_address;
+               ioapic_redirects[i].ioapic_int = dst_apic_int;
                ioapic_redirects[i].ioapic_flags = IOAPIC_PCI_FLAGS;
        }
        
        // Setup the ISA entries
        for (int i = 0; i < NUM_IRQS; i++) {
                
-               uint16_t dstApicID = isa_int_entries[i].dstApicID;
-               uint8_t dstApicINT = isa_int_entries[i].dstApicINT;
+               uint16_t dst_apic_id = isa_int_entries[i].dst_apic_id;
+               uint8_t dst_apic_int = isa_int_entries[i].dst_apic_int;
                
                
                // Skip invalid entries
-               if (dstApicID == 0xFFFF)
+               if (dst_apic_id == INVALID_DEST_APIC)
                        continue;
                        
                if (ioapic_redirects[i].ioapic_address != NULL) {
-                       // We could handle this so long as they would route to the same place. But we will say we cant
-                       //  because this shouldnt really happen
+                       // This is technically a lie. We could in theory handle this, so long as
+                       //  everything agrees.... however this shouldnt ever really happen
+                       //  as this means we have both PCI and ISA claiming an interrupt
                        panic("BOTH PCI AND ISA CLAIM TO SHARE AN IRQ. BAD");
                }
                
@@ -96,26 +111,47 @@ void ioapic_init() {
                        //  This means it is likely a broken mptable implimentation. this happens on bochs and kvm
                        //  lets just set the flags as if its broken, and move on. Hopefully it will work out.
                        ioapic_redirects[i].ioapic_flags = IOAPIC_BROKEN_PCI_FLAGS;
-                       inconsistent_pci_mappings--;
+                       num_inconsistent_pci_mappings--;
                }
                else {
                        ioapic_redirects[i].ioapic_flags = IOAPIC_ISA_FLAGS;
                }
                
 
-               ioapic_redirects[i].ioapic_address = ioapic_entries[dstApicID].apicAddress;
-               ioapic_redirects[i].ioapic_int = dstApicINT;
+               ioapic_redirects[i].ioapic_address = ioapic_entries[dst_apic_id].apic_address;
+               ioapic_redirects[i].ioapic_int = dst_apic_int;
        }
        
        // Things didn't balance out when we scanned the isa bus for the missing pci devices. Die.
-       if (inconsistent_pci_mappings != 0) 
+       if (num_inconsistent_pci_mappings != 0) 
                panic("FAILED TO COPE WITH INCONSISTENT IRQ->PCI AND PCI->IOAPIC MAPPINGS!");
        
        // Support for other type of IRQ's goes here.
+       
+       /* Note: We do not technically ever do anything to initalize the IOAPIC
+       *   According to the x58 chipset spec, this is done for us. It starts up
+       *   usable and with everything masked, so there isn't really anything to do
+       *   besides setup our structures.
+       */
 }
 
-// MUST NOT BE CALLED BEFORE THE MPTABLES ARE PARSED
-// INPUT IS NON-KERNEL-OFFSETTED. IE IRQ0 is Pit, not divide by 0.
+
+/** @brief Reconfigure the correct IOAPIC to route a given irq to a given dest
+  * 
+  * This function will take an irq given by 'irq' and using the interal IOAPIC
+  * strucures will adjust the IOAPIC to properly route that IRQ to a core 
+  * (or in the future group of cores) specified by the 'dest' bits.
+  *
+  * This function must be called after ioapic_init() is called.
+  *
+  * There is no notion of success besides invalid data, which casues a panic.
+  *
+  * @todo Logical partition support
+  *
+  * @param[in] irq     The IRQ we are trying to route. This is non-kernal-offseted. EX: Pit is IRQ 0, not 32.
+  * @param[in] dest    The core id we want to route irq to
+  */
+
 void ioapic_route_irq(uint8_t irq, uint8_t dest) {
        
        if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
@@ -129,29 +165,41 @@ void ioapic_route_irq(uint8_t irq, uint8_t dest) {
        if (irq == 0 && dest != 0)
                cprintf("WARNING: Rerouting IRQ to core != 0 may cause undefined behavior!\n");
 
-       // Bit pack our redirection entry       
+       // Bit pack our redirection entry. This is black magic based on the spec. See the x58 spec.
        uint32_t redirect_low = KERNEL_IRQ_OFFSET + irq;
        redirect_low = redirect_low | (ioapic_redirects[irq].ioapic_flags << 8);
        uint32_t redirect_high = dest << 24;
        
-       // YOU MUST MUST MUST MUST MUST MUST MUST write the high bits first. Ask Paul about that afternoon of his life.
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int + 1);
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, redirect_high);
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int);
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, redirect_low);
+       // YOU MUST MUST MUST MUST MUST MUST MUST write the high bits first. If you don't, you get interrupts going to crazy places
+       // Ask Paul about that afternoon of his life.
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int + 1);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, redirect_high);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, redirect_low);
 }
 
+/** @brief Reconfigure the correct IOAPIC to no longer route a given irq to any core
+  * 
+  * This function will take an irq given by 'irq' and using the interal IOAPIC
+  * strucures will adjust the IOAPIC to no longer route that irq to any destination
+  *
+  * This function must be called after ioapic_init() is called, but need not be called after a matching ioapic_route_irq()
+  *
+  * There is no notion of success besides invalid data, which casues a panic.
+  * 
+  * @param[in] irq     The IRQ we are trying to unroute. This is non-kernal-offseted. EX: Pit is IRQ 0, not 32.
+  */
 void ioapic_unroute_irq(uint8_t irq) {
 
        if (((irq + KERNEL_IRQ_OFFSET) >= NUM_IRQS) || (ioapic_redirects[irq].ioapic_address == NULL)) {
                panic("TRYING TO REROUTE AN INVALID IRQ!");
        }
        
-       // Must write low first, else we will reroute to a wrong core before turning off
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int);
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, IOAPIC_UNROUTE_LOW);
+       // Must write low first, else we will reroute to a wrong core for a split before turning off
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, IOAPIC_UNROUTE_LOW);
        
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , 0x10 + 2*ioapic_redirects[irq].ioapic_int + 1);
-       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + 0x10, IOAPIC_UNROUTE_HIGH);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address , IOAPIC_REDIRECT_OFFSET + 2*ioapic_redirects[irq].ioapic_int + 1);
+       write_mmreg32((uint32_t)ioapic_redirects[irq].ioapic_address  + IOAPIC_WRITE_WINDOW_OFFSET, IOAPIC_UNROUTE_HIGH);
 
-}
+}
\ No newline at end of file
index cf9f9e6..5ca0940 100644 (file)
@@ -27,6 +27,12 @@ void manager(void)
        static uint8_t progress = 0;
        env_t *envs[256];
        
+       if (progress++ == 0) {
+               envs[0] = kfs_proc_create(kfs_lookup_path("parlib_matrix"));
+               proc_set_state(envs[0], PROC_RUNNABLE_S);
+               proc_run(envs[0]);
+       }
+       schedule();
 
        switch (progress++) {
                case 0:
index c4817cd..6218148 100644 (file)
@@ -1,86 +1,99 @@
-#include <arch/mmu.h>
-#include <arch/x86.h>
-#include <arch/smp.h>
-#include <arch/apic.h>
-#include <arch/ioapic.h>
-
-
-#include <ros/memlayout.h>
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
 
+#include <arch/ioapic.h>
+#include <pci.h>
 #include <stdio.h>
 #include <string.h>
-#include <pmap.h>
 #include <kmalloc.h>
+#include <arch/x86.h>
 
 #include <mptables.h>
-#include <pci.h>
 
-/* Basic MP Tables Parser
+/** @file
+ * @brief Basic MP Tables Parser
  *
- * Memory Locations and table structs taken from FreeBSD's mptable.c and modified.
+ * This file is responsible for locating, checksuming, and parsing the 
+ * MultiProcessor Specification Tables.
  *
- * Put cool text here
- * 
- * TODO: Extended table support
- * TODO: KMALLOC null checks
- * TODO: Error checking, pci device not found, etc.
+ * See Intel Multiprocessor Specification for more info
+ *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Extended table support (why?)
+ * @todo Expanded error checking?
+ * @todo virtaddr_t to match physaddr_t support?
  */
 
-
-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;
 
-proc_entry *COUNT(mp_entries_count[PROC]) mp_proc_entries;
-bus_entry *COUNT(mp_entries_count[BUS]) mp_bus_entries;
-ioapic_entry *COUNT(mp_entries_count[IOAPIC]) mp_ioapic_entries;
-int_entry *COUNT(mp_entries_count[INT]) mp_int_entries;
-int_entry *COUNT(mp_entries_count[LINT]) mp_lint_entries; // Not a type. lint entries == int entries
+proc_entry_t   *COUNT(mp_entries_count[PROC])   mp_proc_entries = NULL;
+bus_entry_t            *COUNT(mp_entries_count[BUS])    mp_bus_entries = NULL;
+ioapic_entry_t *COUNT(mp_entries_count[IOAPIC]) mp_ioapic_entries = NULL;
+int_entry_t            *COUNT(mp_entries_count[INT])    mp_int_entries = NULL;
+int_entry_t            *COUNT(mp_entries_count[LINT])   mp_lint_entries = NULL; 
+// ^ Not a typo. lint entries == int entries, so We just use that.
 
 
 int mp_entries_count[NUM_ENTRY_TYPES]; // How large each array is.
 
-pci_int_group pci_int_groups[PCI_MAX_BUS][PCI_MAX_DEV];
-isa_int_entry isa_int_entries[NUM_IRQS];
-ioapic_entry ioapic_entries[IOAPIC_MAX_ID];
+pci_int_device_t pci_int_devices[PCI_MAX_BUS][PCI_MAX_DEV];
+isa_int_entry_t isa_int_entries[NUM_IRQS];
+ioapic_entry_t ioapic_entries[IOAPIC_MAX_ID];
+
 
+/** @brief Entry function to the mptable parser. Calling this function results in the parsing of the tables and setup of all structures
+ *
+ * This function does the following:
+ *     - Search various locations in memory for the MP Floating Structure 
+ *  - Checkum the floating structure to make sure its valid
+ *  - Locate the MP Configuration Header, and checksum it
+ *  - Locate all entries of type proc, bus, ioapic, int, lint
+ *  - Parse the above entries and form the data structures that the rest of the system relies upon
+ */
 void mptables_parse() {
        
+       // Before we do anything. We didn't pack our structs because BSD didnt. Make sure we're sane.
+       if (    (sizeof(proc_entry_t)   != entry_types[PROC].length) || 
+                       (sizeof(bus_entry_t)    != entry_types[BUS].length) || 
+                       (sizeof(ioapic_entry_t) != entry_types[IOAPIC].length) || 
+                       (sizeof(int_entry_t)    != entry_types[INT].length) || 
+                       (sizeof(mpfps_t)                != MPFPS_SIZE) ||
+                       (sizeof(mpcth_t)                != MPCTH_SIZE) )
+                               panic("MPTable structure sizes out of sync with spec");
+                       
+                       
        mpfps_t *mpfps;
        
-       // Memsets.
-       // 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.
+       // Memsets to initalize all our structures to invalid entries
+       
+       /* Setup the indexable ioapic array.
+        * YOU MUST check the flag field to see if its 0. If 0, unusable.
+        * This is defined by MPTables, and I leaverage this with the memset below to set invalid
+        */
        memset(ioapic_entries, 0, sizeof(ioapic_entries));
        
-       // We define an IOAPIC ID over 255 to be invalid.
-       memset(pci_int_groups, 0xFF, sizeof(pci_int_groups));
+       // We define an IOAPIC DEST ID of 0xFF (>=256) to be invalid. Pack with all 1's.
+       memset(pci_int_devices, 0xFF, sizeof(pci_int_devices));
        memset(isa_int_entries, 0xFF, sizeof(isa_int_entries));
        
        
        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.
+       /*  Basic procedure:
+        *      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.
+        *
+        *
+        * 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");
@@ -88,12 +101,13 @@ void mptables_parse() {
        
        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));
+               /* Search the EBDA UNTESTED, haven't found something that uses this.
+                *
+                * First, we have to find the EBDA Addr.
+                * This USSUALLY works (based on third hand info). May be some cases where it doesnt.
+                * See osdev x86 mem-map for more information
+                */
+               physaddr_t ebda_base = READ_FROM_STORED_PHYSADDR32(EBDA_POINTER);
                
                if (ebda_base) {
                        ebda_base = ebda_base << 4;
@@ -106,11 +120,12 @@ void mptables_parse() {
        }
 
        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.
+               /* 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));
+               physaddr_t top_of_mem = READ_FROM_STORED_PHYSADDR32(TOPOFMEM_POINTER);
                
                if (top_of_mem) {
                        --top_of_mem;
@@ -124,8 +139,10 @@ void mptables_parse() {
        }
        
        if (mpfps == NULL) {
-               // Search the last KB of system memory based on a 640K limited, due to CMOS lying
-               // Note: Will only be there if it not in the EBDA. So this must be called after the EBDA check.
+               /* Search the last KB of system memory based on a 640K limited, due to CMOS lying
+                * Note: Will only be there if it not in the EBDA. So this must be called after the EBDA check.
+                * This IS tested. Thanks VirtualBox!
+                */
                                
                physaddr_t top_of_mem = DEFAULT_TOPOFMEM;
                
@@ -140,9 +157,10 @@ void mptables_parse() {
                }
        }
 
-       // 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 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>");
        }
@@ -154,6 +172,7 @@ void mptables_parse() {
        if (mpfps->mpfb2 & IMCRP_MASK) {
                current_interrupt_mode = PIC;
                mptables_info("PIC\n");
+               // TODO: Do SOMETHING here. We've never found such a system (they are generally ancient). Should we just panic?
        }
        else {
                current_interrupt_mode = VW;
@@ -170,8 +189,20 @@ void mptables_parse() {
        
 }
 
-// Searches the given address range, starting at addr first, to (including) last, for the mptables pointer.
-// Does not esure base/bounds are sane.
+
+/** @brief Take the given memory range and search for the MP Floating Structure
+ * 
+ * This function will look at every sizeof(mpfps_t) chunch of memory for a given 4byte value (_MP_)
+ * until bound is reached (inclusive).
+ *
+ * Note: Doesn't ensure bounds are sane. This shouldnt be an issue as this function should be priviate to mptables_parse()
+ *
+ * @param[in] base     The base (kernel virtual) address we start looking at
+ * @param[in] bound The bound (inclusive kernel virtual) address we stop looking at
+ * 
+ * @return MPFPS The virtual address of the base of the floating point structure
+ * @return NULL No floating point structure exists in this range
+ */
 mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound) {
 
        uint32_t count = (bound - base + sizeof(mpfps_t))/sizeof(mpfps_t);
@@ -182,7 +213,7 @@ mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound) {
 
        // 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)) {
+       while ( ((physaddr_t)mpfps <= bound) && (READ_FROM_STORED_VIRTADDR32(mpfps->signature) != MP_SIG)) {
                mpfps++;
        }
        
@@ -204,6 +235,17 @@ mpfps_t *find_floating_pointer(physaddr_t base, physaddr_t bound) {
        return mpfps;
 }
 
+/** @brief Perform the mptable checksum on the memory given by addr and len
+ *
+ * This function will take len bytes of memory starting at the (kernel virtual)
+ * address addr and sum them together. If the result is 0, the checksum is valid. 
+ *
+ * @param[in] addr     The base (kernel virtual) address we start checking 
+ * @param[in] len      How many bytes to look at
+ * 
+ * @return TRUE Valid checksum
+ * @return FALSE Invalid checksum
+ */
 bool checksum(physaddr_t addr, uint32_t len) {
        // MP Table checksums must add up to 0.
        uint8_t checksum = 0;
@@ -218,9 +260,14 @@ bool checksum(physaddr_t addr, uint32_t len) {
        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.
+/** @brief Parse the configuration MP Table given a valid address to the base of the table
+ *
+ * This function begin examining a given (kernel virtual) address assuming it is the base 
+ * of the configuration table. It will determine the size of the table, and then loop over
+ * each entry in the table, loading all entires into the correct corresponding data structures
+ *
+ * @param[in] conf_addr                The base (kernel virtual) address of the configuration table
+ */    
 void configuration_parse(physaddr_t conf_addr) {
        
        int num_processed[NUM_ENTRY_TYPES];
@@ -233,17 +280,18 @@ void configuration_parse(physaddr_t conf_addr) {
        }
                
        // Do 1 pass to figure out how much space to allocate.
+       // Note: Length here means length in bytes. This is from the mp spec.
        uint16_t num_entries = mpcth->entry_count;
        uint16_t mpct_length = mpcth->base_table_length;
-       uint16_t entry_length = mpct_length - sizeof(mpcth);
+       uint16_t entries_length = mpct_length - sizeof(mpcth);
        
        // Now perform a checksum on the configuration table
        if (checksum((physaddr_t)mpcth, mpct_length) == FALSE) {
                panic("FAILED MP CONFIGURATION CHECKSUM.");
        }
        
-       uint8_t * COUNT(entry_length) entry_base = (uint8_t* COUNT(entry_length)) TC(mpcth + 1);
-       uint8_t * BND(entry_base, entry_base + entry_length) current_addr = entry_base;
+       uint8_t * COUNT(entries_length) entry_base = (uint8_t* COUNT(entries_length)) TC(mpcth + 1);
+       uint8_t * BND(entry_base, entry_base + entries_length) current_addr = entry_base;
        
        for (int i = 0; i < num_entries; i++) {
                uint8_t current_type = *current_addr;
@@ -251,24 +299,39 @@ void configuration_parse(physaddr_t conf_addr) {
                        panic("CORRUPT MPTABLES CONFIGURATION ENTRY");
                        
                mp_entries_count[current_type]++;
-               current_addr += basetableEntryTypes[current_type].length;
+               current_addr += entry_types[current_type].length;
        }
        
        // Allocate the correct space in the arrays (unrolled for ivy reasons)
-       if (mp_entries_count[PROC] != 0)
-               mp_proc_entries = kmalloc(mp_entries_count[PROC] * basetableEntryTypes[PROC].length , 0);
+       if (mp_entries_count[PROC] != 0) {
+               mp_proc_entries = kmalloc(mp_entries_count[PROC] * entry_types[PROC].length , 0);
+               if (mp_proc_entries == NULL)
+                       panic("Failed to allocate space for mp_proc_entires");
+       }
 
-       if (mp_entries_count[BUS] != 0)
-               mp_bus_entries = kmalloc(mp_entries_count[BUS] * basetableEntryTypes[BUS].length , 0);
+       if (mp_entries_count[BUS] != 0) {
+               mp_bus_entries = kmalloc(mp_entries_count[BUS] * entry_types[BUS].length , 0);
+               if (mp_bus_entries == NULL)
+                       panic("Failed to allocate space for mp_bus_entires");
+       }
 
-       if (mp_entries_count[IOAPIC] != 0)
-               mp_ioapic_entries = kmalloc(mp_entries_count[IOAPIC] * basetableEntryTypes[IOAPIC].length , 0);
+       if (mp_entries_count[IOAPIC] != 0) {
+               mp_ioapic_entries = kmalloc(mp_entries_count[IOAPIC] * entry_types[IOAPIC].length , 0);
+               if (mp_ioapic_entries == NULL)
+                       panic("Failed to allocate space for mp_ioapic_entires");
+       }
        
-       if (mp_entries_count[INT] != 0)
-               mp_int_entries = kmalloc(mp_entries_count[INT] * basetableEntryTypes[INT].length , 0);
+       if (mp_entries_count[INT] != 0) {
+               mp_int_entries = kmalloc(mp_entries_count[INT] * entry_types[INT].length , 0);
+               if (mp_int_entries == NULL)
+                       panic("Failed to allocate space for mp_int_entires");
+       }
 
-       if (mp_entries_count[LINT] != 0)
-               mp_lint_entries = kmalloc(mp_entries_count[LINT] * basetableEntryTypes[LINT].length , 0);
+       if (mp_entries_count[LINT] != 0) {
+               mp_lint_entries = kmalloc(mp_entries_count[LINT] * entry_types[LINT].length , 0);
+               if (mp_lint_entries == NULL)
+                       panic("Failed to allocate space for mp_lint_entires");
+       }
        
        current_addr = entry_base;
        
@@ -284,37 +347,37 @@ void configuration_parse(physaddr_t conf_addr) {
                        case PROC:
                                memcpy( &mp_proc_entries[num_processed[PROC]], 
                                                current_addr,  
-                                               basetableEntryTypes[PROC].length);
+                                               entry_types[PROC].length);
                                break;
                        
                        case BUS:
                                memcpy( &mp_bus_entries[num_processed[BUS]], 
                                                current_addr,  
-                                               basetableEntryTypes[BUS].length);
+                                               entry_types[BUS].length);
                                break;
                        case IOAPIC:
                                memcpy( &mp_ioapic_entries[num_processed[IOAPIC]], 
                                                // This is needed due to the void* in the entry
                                                //  no clean way of doing this. Sorry Zach.
-                                               (ioapic_entry* COUNT(1)) TC(current_addr),  
-                                               basetableEntryTypes[IOAPIC].length);
+                                               (ioapic_entry_t* COUNT(1)) TC(current_addr),  
+                                               entry_types[IOAPIC].length);
                                break;
                        case INT:
                                memcpy( &mp_int_entries[num_processed[INT]], 
                                                current_addr,  
-                                               basetableEntryTypes[INT].length);
+                                               entry_types[INT].length);
                                break;
                        case LINT:
                                memcpy( &mp_lint_entries[num_processed[LINT]], 
                                                (void*)current_addr,  
-                                               basetableEntryTypes[LINT].length);
+                                               entry_types[LINT].length);
                                break;
                                                
                        default: panic("UNKNOWN ENTRY TYPE");
                }
 
                num_processed[current_type]++;
-               current_addr += basetableEntryTypes[current_type].length;
+               current_addr += entry_types[current_type].length;
        }
        
        // We'd do extended table support stuff here (or alter the loop above)
@@ -322,41 +385,56 @@ void configuration_parse(physaddr_t conf_addr) {
        // We now have all of our entries copied into a single structure we can index into. Yay.
 }
 
+/** @brief Parse all processor mptable entires
+ *
+ * This function will loop over the raw proc entry structure and parse it into a usable form.
+ * This currently just prints stuff if dumping is enabled.
+ */
 void proc_parse() {
        // For now, we don't do anything with the processor entries. Just print them.
        
        for (int i = 0; i < mp_entries_count[PROC]; i++){
                mptables_dump("Proc entry %u\n", i);
                mptables_dump("-->type: %x\n", mp_proc_entires[i].type);
-               mptables_dump("-->apicID: %x\n", mp_proc_entires[i].apicID);
-               mptables_dump("-->apicVersion: %x\n", mp_proc_entires[i].apicVersion);
-               mptables_dump("-->cpuFlags: %x\n", mp_proc_entires[i].cpuFlags);
-               mptables_dump("-->cpuSignaure: %x\n", mp_proc_entires[i].cpuSignature);
-               mptables_dump("-->featureFlags: %x\n", mp_proc_entires[i].featureFlags);
+               mptables_dump("-->apic ID: %x\n", mp_proc_entires[i].apic_id);
+               mptables_dump("-->apic Version: %x\n", mp_proc_entires[i].apic_version);
+               mptables_dump("-->cpu Flags: %x\n", mp_proc_entires[i].cpu_flags);
+               mptables_dump("-->cpu Signaure: %x\n", mp_proc_entires[i].cpu_signature);
+               mptables_dump("-->feature Flags: %x\n", mp_proc_entires[i].feature_flags);
        }
        
        mptables_dump("\n");
 }
 
+/** @brief Parse all bus mptable entires
+ *
+ * This function will loop over the raw bus entry structure and parse it into a usable form
+ * This currently just prints stuff if dumping is enabled. (With a basic sanity check).
+ */
 void bus_parse() {
        // 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 < mp_entries_count[BUS]; i++){
-               if (i != mp_bus_entries[i].busID
+               if (i != mp_bus_entries[i].bus_id
                        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", mp_bus_entries[i].type);
-               mptables_dump("-->BusID: %x\n", mp_bus_entries[i].busID);
-               mptables_dump("-->Bus: %c%c%c\n", mp_bus_entries[i].busType[0], mp_bus_entries[i].busType[1], mp_bus_entries[i].busType[2]);
+               mptables_dump("-->Bus ID: %x\n", mp_bus_entries[i].bus_id);
+               mptables_dump("-->Bus: %c%c%c\n", mp_bus_entries[i].bus_type[0], mp_bus_entries[i].bus_type[1], mp_bus_entries[i].bus_type[2]);
        
        }
        
        mptables_dump("\n");
 }
 
+/** @brief Parse all ioapic mptable entires
+ *
+ * This function will loop over the raw ioapic entry structure and parse it into a usable form.
+ * ioapic_entires[] contains all found ioapics after this function.
+ */
 void ioapic_parse() {
 
        // Note: We don't check if the apicFlags is 0. If zero, unusable
@@ -365,88 +443,100 @@ void ioapic_parse() {
        // mp_entries_count[IOAPIC] contains the number of ioapics on this system
        
        for (int i = 0; i < mp_entries_count[IOAPIC]; i++){
+               
+               memcpy((void*)(ioapic_entries + mp_ioapic_entries[i].apic_id), (void*)(mp_ioapic_entries + i), sizeof(ioapic_entry_t));
+               
                mptables_dump("IOAPIC entry %u\n", i);
                mptables_dump("-->type: %x\n", mp_ioapic_entries[i].type);
-               mptables_dump("-->apicID: %x\n", mp_ioapic_entries[i].apicID);
-               mptables_dump("-->apicVersion: %x\n", mp_ioapic_entries[i].apicVersion);
-               mptables_dump("-->apicFlags: %x\n", mp_ioapic_entries[i].apicFlags);
-               mptables_dump("-->apicAddress: %p\n", mp_ioapic_entries[i].apicAddress);
+               mptables_dump("-->apic_id: %x\n", mp_ioapic_entries[i].apic_id);
+               mptables_dump("-->apic_version: %x\n", mp_ioapic_entries[i].apic_version);
+               mptables_dump("-->apic_flags: %x\n", mp_ioapic_entries[i].apic_flags);
+               mptables_dump("-->apic_address: %p\n", mp_ioapic_entries[i].apic_address);
                
        }
        mptables_dump("\n");
-       
-       for (int i = 0; i < mp_entries_count[IOAPIC]; i++) {
-               memcpy((void*)(ioapic_entries + mp_ioapic_entries[i].apicID), (void*)(mp_ioapic_entries + i), sizeof(ioapic_entry));
-       }
 }
 
+/** @brief Parse all interrupt mptable entires
+ *
+ * This function will loop over the raw interrupt entry structure and parse it into a usable form.
+ * pci_int_devices[] and isa_int_entries[] will be populated after this function is called.
+ */
 void int_parse() {
        // create a massive array, tied together with bus/dev, for indexing
        
        for (int i = 0; i < mp_entries_count[INT]; i++){
                mptables_dump("Interrupt entry %u\n", i);
                mptables_dump("-->type: %x\n", mp_int_entries[i].type);
-               mptables_dump("-->intType: %x\n", mp_int_entries[i].intType);
-               mptables_dump("-->intFlags: %x\n", mp_int_entries[i].intFlags);
-               mptables_dump("-->srcBusID: %u\n", mp_int_entries[i].srcBusID);
-               mptables_dump("-->srcDevice: %u (PCI ONLY)\n", (mp_int_entries[i].srcBusIRQ >> 2) & 0x1F);
-               mptables_dump("-->srcBusIRQ: %x\n", mp_int_entries[i].srcBusIRQ);
-               mptables_dump("-->dstApicID: %u\n", mp_int_entries[i].dstApicID);
-               mptables_dump("-->dstApicINT: %u\n", mp_int_entries[i].dstApicINT);
+               mptables_dump("-->int Type: %x\n", mp_int_entries[i].int_type);
+               mptables_dump("-->int Flags: %x\n", mp_int_entries[i].int_flags);
+               mptables_dump("-->src Bus ID: %u\n", mp_int_entries[i].src_bus_id);
+               mptables_dump("-->src Device: %u (PCI ONLY)\n", (mp_int_entries[i].src_bus_irq >> 2) & 0x1F);
+               mptables_dump("-->src Bus IRQ: %x\n", mp_int_entries[i].src_bus_irq);
+               mptables_dump("-->dst Apic ID: %u\n", mp_int_entries[i].dst_apic_id);
+               mptables_dump("-->dst Apic INT: %u\n", mp_int_entries[i].dst_apic_int);
                                        
        }
        mptables_dump("\n");
 
        // Populate the PCI/ISA structure with the interrupt entries.
        for (int i = 0; i < mp_entries_count[INT]; i++) {
-               if (strncmp(mp_bus_entries[mp_int_entries[i].srcBusID].busType, "PCI", 3) == 0) {
-                       int bus_idx, dev_idx, int_idx;
-                       bus_idx = mp_int_entries[i].srcBusID;
-                       dev_idx = (mp_int_entries[i].srcBusIRQ >> 2) & 0x1F;
-                       int_idx = mp_int_entries[i].srcBusIRQ & 0x3;
-                       pci_int_groups[bus_idx][dev_idx].intn[int_idx].dstApicID = mp_int_entries[i].dstApicID;
-                       pci_int_groups[bus_idx][dev_idx].intn[int_idx].dstApicINT = mp_int_entries[i].dstApicINT;
+               if (strncmp(mp_bus_entries[mp_int_entries[i].src_bus_id].bus_type, "PCI", 3) == 0) {
+                       int bus_idx, dev_idx, line_idx;
+                       bus_idx = mp_int_entries[i].src_bus_id;
+                       dev_idx = (mp_int_entries[i].src_bus_irq >> 2) & 0x1F;
+                       line_idx = mp_int_entries[i].src_bus_irq & 0x3;
+                       pci_int_devices[bus_idx][dev_idx].line[line_idx].dst_apic_id = mp_int_entries[i].dst_apic_id;
+                       pci_int_devices[bus_idx][dev_idx].line[line_idx].dst_apic_int = mp_int_entries[i].dst_apic_int;
                }
                
-               if (strncmp(mp_bus_entries[mp_int_entries[i].srcBusID].busType, "ISA", 3) == 0) {
-                       int irq = mp_int_entries[i].srcBusIRQ;
-                       int int_type = mp_int_entries[i].intType;
+               if (strncmp(mp_bus_entries[mp_int_entries[i].src_bus_id].bus_type, "ISA", 3) == 0) {
+                       int irq = mp_int_entries[i].src_bus_irq;
+                       int int_type = mp_int_entries[i].int_type;
                        
                        if (int_type == 3) {
-                               // THIS IS WHERE THE PIC CONNECTS TO THE IOAPIC
-                               // WE DON'T CURRENTLY DO ANYTHING WITH THIS, BUT SHOULD WE NEED TO
-                               // HERES WHERE TO LOOK!
-                               // WE MUST NOT PLACE THIS INTO OUR TABLE AS IRQ HAS NO REAL MEANING AFAPK
+                               /* THIS IS WHERE THE PIC CONNECTS TO THE IOAPIC
+                                * WE DON'T CURRENTLY DO ANYTHING WITH THIS, BUT SHOULD WE NEED TO
+                                * HERES WHERE TO LOOK!
+                                * WE MUST NOT PLACE THIS INTO OUR TABLE AS IRQ HAS NO REAL MEANING AFAPK
+                                */
                                continue;
                                
-                               // Note. On the dev boxes the pit and pic both claim to be on irq 0
-                               // However the pit and the pic are on different ioapic entries.
-                               // Seems odd. Not sure whats up with this. Paul assumes the IRQ has no meaning
-                               // in regards to the pic... which makes sense.
+                               /* Note. On the dev boxes the pit and pic both claim to be on irq 0
+                                * However the pit and the pic are on different ioapic entries.
+                                * Seems odd. Not sure whats up with this. Paul assumes the IRQ has no meaning
+                                * in regards to the pic... which makes sense.
+                                */
                        }
                                                
-                       if ((isa_int_entries[irq].dstApicID != 0xFFFF) && 
-                                ((isa_int_entries[irq].dstApicID != mp_int_entries[i].dstApicID
-                                  || (isa_int_entries[irq].dstApicINT != mp_int_entries[i].dstApicINT)))
+                       if ((isa_int_entries[irq].dst_apic_id != 0xFFFF) && 
+                                ((isa_int_entries[irq].dst_apic_id != mp_int_entries[i].dst_apic_id
+                                  || (isa_int_entries[irq].dst_apic_int != mp_int_entries[i].dst_apic_int)))
                                panic("SAME IRQ MAPS TO DIFFERENT IOAPIC/INTN'S. THIS DEFIES LOGIC.");
                        
-                       isa_int_entries[irq].dstApicID = mp_int_entries[i].dstApicID;
-                       isa_int_entries[irq].dstApicINT = mp_int_entries[i].dstApicINT;
+                       isa_int_entries[irq].dst_apic_id = mp_int_entries[i].dst_apic_id;
+                       isa_int_entries[irq].dst_apic_int = mp_int_entries[i].dst_apic_int;
                }                       
        }
 }
 
+/** @brief Parse all local interrupt mptable entires
+ *
+ * This function will loop over the raw local interrupt entry structure and parse it into a usable form.
+ * This currently just prints stuff if dumping is enabled.
+ */
+
 void lint_parse() {
        // For now, we don't do anything with the local interrupt entries
        
        for (int i = 0; i < mp_entries_count[LINT]; i++){
                mptables_dump("Local Interrupt entry %u\n", i);
                mptables_dump("-->type: %x\n", mp_lint_entries[i].type);
-               mptables_dump("-->intType: %x\n", mp_lint_entries[i].intType);
-               mptables_dump("-->srcBusID: %x\n", mp_lint_entries[i].srcBusID);
-               mptables_dump("-->srcBusIRQ: %x\n", mp_lint_entries[i].srcBusIRQ);
-               mptables_dump("-->dstApicID: %p\n", mp_lint_entries[i].dstApicID);
-               mptables_dump("-->dstApicINT: %p\n", mp_lint_entries[i].dstApicINT);
+               mptables_dump("-->int Type: %x\n", mp_lint_entries[i].int_type);
+               mptables_dump("-->src Bus ID: %x\n", mp_lint_entries[i].src_bus_id);
+               mptables_dump("-->src Bus IRQ: %x\n", mp_lint_entries[i].src_bus_irq);
+               mptables_dump("-->dst Apic ID: %p\n", mp_lint_entries[i].dst_apic_id);
+               mptables_dump("-->dst Apic INT: %p\n", mp_lint_entries[i].dst_apic_int);
                
        }
-}
+}
\ No newline at end of file
index d657291..06eeb5f 100644 (file)
@@ -44,7 +44,7 @@ void ne2k_init() {
 
 int ne2k_scan_pci() {
        
-       extern pci_dev_entry pci_dev_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+       extern pci_dev_entry_t 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 NE2000 Network device...");
index 15bb309..7f33ccd 100644 (file)
@@ -1,49 +1,53 @@
-#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>
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
 
-/* PCI ?Driver?
+/** @file
+ * @brief Basic PCI Driver.
+ *
+ * This file is responsible for the scanning the PCI bus and recording
+ * all the information needed for ouR OS to function. 
  *
- * Written by Paul Pearce.
+ * No PCI Specifications (or even consulted) were harmed in the making of this file.
  *
- * Insight into functionality goes here
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Build an entire useful PCI subsystem, not this hack with a few data structures laying around
  *
- * TODO: See todo's below
  */
 
-// 256 or larger means invalid irq.
+#include <arch/x86.h>
+#include <stdio.h>
+#include <string.h>
+#include <pci.h>
+
+// A value of INVALID_IRQ (something 256 or larger) means invalid
 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_dev_entry_t 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.
+pci_irq_entry_t irq_pci_map[NUM_IRQS];
 
+/**
+ * @brief Perform the actual PCI bus parsing
+ *
+ * See file description.
+ * 
+ * This function must be called during bootup, before ioapic_init().
+ */
 void pci_init() {
        
        // Initalize the irq->pci table (pci->irq below)
-       // Setting all 1's forces an invalid entry, as bus > 255.
+       // Setting all 1's forces an invalid entry, as bus = INVALID_BUS = 0xFFFF.
        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 bus = 0;
+       uint32_t dev = 0;
+       uint32_t func = 0;
+       uint32_t reg = 0; 
        uint32_t result  = 0;
  
        pci_debug("Scanning PCI Bus....\n");
@@ -52,16 +56,16 @@ void pci_init() {
                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
+                               bus = i;
+                               dev = j;
+                               func = k;
+                               reg = 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); 
+                               address = MK_CONFIG_ADDR(bus, dev, func, reg); 
 
                                // Probe current bus/dev
                                outl(PCI_CONFIG_ADDR, address);
@@ -77,21 +81,22 @@ void pci_init() {
                                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);
+                               address = MK_CONFIG_ADDR(bus, dev, func, 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);
+                               // Find the line (a-d)
+                               address = MK_CONFIG_ADDR(bus, dev, func, PCI_IRQ_REG);
                                outl(PCI_CONFIG_ADDR, address);
-                               uint8_t intn = (inl(PCI_CONFIG_DATA) & PCI_INTN_MASK) >> PCI_INTN_SHFT;
+                               uint8_t line = (inl(PCI_CONFIG_DATA) & PCI_LINE_MASK) >> PCI_LINE_SHFT;
                                
                                // If intn == 0, no interrupts used.
-                               if (intn != INVALID_INTN) {
+                               if (line != INVALID_LINE) {
                                        
                                        // Now shift A to 0, B to 1, etc.
-                                       intn--;
+                                       // This starts off as A 1, B 2 (grr)
+                                       line--;
                                
                                        pci_irq_map[i][j][k] = irq;
                                        pci_dev_map[i][j][k].dev_id = dev_id;
@@ -99,18 +104,23 @@ void pci_init() {
                                        irq_pci_map[irq].bus = i;
                                        irq_pci_map[irq].dev = j;
                                        irq_pci_map[irq].func = k;
-                                       irq_pci_map[irq].intn = intn;
+                                       irq_pci_map[irq].line = line;
                                        
-                                       // Perform some check to make usre if we are overwriting a current irq that it goes to the same place. else panic
-                                       // TODO
+                                       // @todo We may want to perform some check to make sure we arent overwriting some current irq entry and maintain that info
                                }
                                
 
-                               // Loop over the BARs
-                               // We should do something useful with this data. But what?
+                               /* Loop over the BARs
+                                * Right now we don't do anything useful with this data. 
+                                * This is legacy code in which I pulled data from the BARS during NIC development
+                                * At some point we will have to use this, so the code is still here.
+                                */
+                               
+                               // Note: These magic numbers are from the PCI spec (according to OSDev).
+                               #ifdef CHECK_BARS
                                for (int k = 0; k <= 5; k++) {
-                                       lreg = 4 + k;
-                                       address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
+                                       reg = 4 + k;
+                                       address = MK_CONFIG_ADDR(bus, dev, func, reg << 2);     
                                outl(PCI_CONFIG_ADDR, address);
                                result = inl(PCI_CONFIG_DATA);
                                        
@@ -126,9 +136,8 @@ void pci_init() {
                                                pci_debug("-->BAR%u: %s --> %x\n", k, "MEM", result);
                                        }                                       
                                }
+                               #endif
                                
                                pci_debug("\n");
                        }               
-}
-
-
+}
\ No newline at end of file
index 3521f98..ce452ac 100644 (file)
@@ -98,7 +98,7 @@ void rl8168_init() {
 
 int rl8168_scan_pci() {
        
-       extern pci_dev_entry pci_dev_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+       extern pci_dev_entry_t 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...");
@@ -107,10 +107,10 @@ int rl8168_scan_pci() {
                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 bus = i;
+                               uint32_t dev = j;
+                               uint32_t func = k;
+                               uint32_t reg = 0; 
                                uint32_t result  = 0;
        
                                uint16_t dev_id = pci_dev_map[i][j][k].dev_id;
@@ -131,8 +131,8 @@ int rl8168_scan_pci() {
 
                                // Loop over the BARs
                                for (int k = 0; k <= 5; k++) {
-                                       lreg = 4 + k;
-                                       address = MK_CONFIG_ADDR(lbus, ldev, lfunc, lreg << 2); 
+                                       reg = 4 + k;
+                                       address = MK_CONFIG_ADDR(bus, dev, func, reg << 2);     
                                outl(PCI_CONFIG_ADDR, address);
                                result = inl(PCI_CONFIG_DATA);
                                        
index e24f38b..0adc939 100644 (file)
@@ -24,6 +24,8 @@
 #include <stdio.h>
 #include <kfs.h> // eventually replace this with vfs.h
 
+static void sys_yield(struct proc *p);
+
 //Do absolutely nothing.  Used for profiling.
 static void sys_null(void)
 {
@@ -66,11 +68,12 @@ static ssize_t sys_run_binary(env_t* e, void *binary_buf, void* arg, size_t len)
                return -ENOMEM;
        memcpy(new_binary, binary_buf, len);
 
-        env_t* env = env_create((uint8_t*)new_binary, len);
+       env_t* env = env_create((uint8_t*)new_binary, len);
        kfree(new_binary);
        proc_set_state(env, PROC_RUNNABLE_S);
-        proc_run(env);
-
+       schedule_proc(env);
+       sys_yield(e);
+       
        return 0;
 }