Merge branch 'net-dev'. See body of commit for details.
authorPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 17 Sep 2009 00:42:04 +0000 (17:42 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 17 Sep 2009 00:42:04 +0000 (17:42 -0700)
This is a merge of the mptable, ioapic, pci, ethernet, and ethernet based remote syscall code.

By default on x86, the mptable, ioapic, and pci code is enabled. Network code is not.

In order to enable the ethernet driver, you must define __NETWORK__
in your make local, and set USER_MAC_ADDRESS to the correct value
in order to communicate with your front end machine. The front end
server app now lives in tools/. Setting __NETWORK__ will cause the
driver to initialize on real hardware, or perform a series of interrupt
tests for simulation. This will also cause parlab_matrix to be the userspace
application booted, instead of the standard apps in manager.c. Network
support is x86 dependent.

Other things handled in this commit include:

Updated doxygen support. Doxygen will now strip out ivy annotations, and
be optimized for C code.

Rewritten newlib_backend. The code is now several orders of magnitude better
(no seriously, look at it).

Conflicts:
kern/arch/i386/Makefrag
kern/include/kfs.h
kern/include/ros/syscall.h
kern/src/Makefrag
kern/src/init.c
kern/src/kfs.c
kern/src/kmalloc.c
kern/src/manager.c
kern/src/syscall.c
kern/src/testing.c
user/roslib/inc/sys

31 files changed:
1  2 
GNUmakefile
kern/arch/i386/Makefrag
kern/arch/i386/apic.c
kern/arch/i386/apic.h
kern/arch/i386/ioapic.c
kern/arch/i386/ioapic.h
kern/arch/i386/mptables.c
kern/arch/i386/mptables.h
kern/arch/i386/ne2k.c
kern/arch/i386/ne2k.h
kern/arch/i386/pci.c
kern/arch/i386/rl8168.c
kern/arch/i386/rl8168.h
kern/arch/i386/smp_boot.c
kern/arch/i386/trap.c
kern/include/ros/syscall.h
kern/include/testing.h
kern/src/Makefrag
kern/src/init.c
kern/src/kfs.c
kern/src/kmalloc.c
kern/src/manager.c
kern/src/monitor.c
kern/src/syscall.c
kern/src/testing.c
user/apps/parlib/Makefrag
user/apps/parlib/file_io.c
user/apps/parlib/matrix.c
user/parlib/inc/newlib_backend.h
user/parlib/inc/parlib.h
user/parlib/src/i386/newlib_backend.c

diff --cc GNUmakefile
Simple merge
@@@ -25,5 -25,9 +25,10 @@@ KERN_ARCH_SRCFILES := $(KERN_ARCH_SRC_D
                        $(KERN_ARCH_SRC_DIR)/smp.c \
                        $(KERN_ARCH_SRC_DIR)/apic.c \
                        $(KERN_ARCH_SRC_DIR)/kdebug.c \
 -                        $(KERN_ARCH_SRC_DIR)/mptables.c \
 -                        $(KERN_ARCH_SRC_DIR)/pci.c \
 -                        $(KERN_ARCH_SRC_DIR)/ioapic.c \
 -                        $(KERN_ARCH_SRC_DIR)/rl8168.c \
 -                        $(KERN_ARCH_SRC_DIR)/ne2k.c \
 +                      $(KERN_ARCH_SRC_DIR)/process.c \
++                      $(KERN_ARCH_SRC_DIR)/mptables.c \
++                      $(KERN_ARCH_SRC_DIR)/pci.c \
++                      $(KERN_ARCH_SRC_DIR)/ioapic.c \
++                      $(KERN_ARCH_SRC_DIR)/rl8168.c \
++                      $(KERN_ARCH_SRC_DIR)/ne2k.c \
                        $(KERN_ARCH_SRC_DIR)/env.c
Simple merge
Simple merge
index 0000000,4dc20fe..483f32b
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,205 +1,213 @@@
 -
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
++#ifdef __SHARC__
++#pragma nosharc
++#endif
++// Not currently sharc complient.
++
+ /** @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 <arch/mptables.h>
+ #include <arch/pci.h>
+ 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
+  *
+  * 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.
+  */
+ 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 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. 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 line = irq_pci_map[i].line;
+               
+               if (bus == INVALID_BUS)
+                       continue;
+               // 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;
+               
+               // 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 (by MP Spec)
+               // We also use this to denote non-existent ioapics in our map
+               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[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 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 (dst_apic_id == INVALID_DEST_APIC)
+                       continue;
+                       
+               if (ioapic_redirects[i].ioapic_address != NULL) {
+                       // 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");
+               }
+               
+               // Code to check if this isa irq entry claims to be pci
+               uint16_t pci_bus = irq_pci_map[i].bus;
+               if (pci_bus != INVALID_BUS) {
+                       // PCI bus had an entry for this irq, but we didn't set it during our pci run
+                       //  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;
+                       num_inconsistent_pci_mappings--;
+               }
+               else {
+                       ioapic_redirects[i].ioapic_flags = IOAPIC_ISA_FLAGS;
+               }
+               
+               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 (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.
+       */
+ }
+ /** @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
++  * @todo Decide on a synchronization mechinism
+   *
+   * @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)) {
+               panic("TRYING TO REROUTE AN INVALID IRQ!");
+       }
+       // THIS IS A TEMP CHECK. IF WE USE LOGICAL PARTITIONS THIS MUST BE REMOVED
++        extern uint8_t num_cpus;
+       if (dest >= num_cpus)
+               panic("TRYING TO REROUTE TO AN INVALID DESTINATION!");
+       
+       if (irq == 0 && dest != 0)
+               cprintf("WARNING: Rerouting IRQ to core != 0 may cause undefined behavior!\n");
+       // 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. 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.
++  *
++  * @todo Decide on a synchronization mechinism
+   * 
+   * @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 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 , 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);
++}
index 0000000,88ba7c2..157407f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,61 +1,61 @@@
 -#include <arch/types.h>
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
+ #ifndef ROS_KERN_IOAPIC_H
+ #define ROS_KERN_IOAPIC_H
++#include <ros/common.h>
+ /* 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
+  * 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
+ /* 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);
+ #endif /* ROS_KERN_IOAPIC_H */
index 0000000,518516c..4cc6a62
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,542 +1,549 @@@
 -}
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
++#ifdef __SHARC__
++#pragma nosharc
++#endif
++// Not currently sharc complient. However
++// we should never be modifying these structures post smp_boot().
++
+ #include <arch/ioapic.h>
+ #include <arch/pci.h>
+ #include <arch/mptables.h>
++#include <ros/common.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <kmalloc.h>
+ #include <arch/x86.h>
+ /** @file
+  * @brief Basic MP Tables Parser
+  *
+  * This file is responsible for locating, checksuming, and parsing the 
+  * MultiProcessor Specification Tables.
+  *
+  * 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?
+  */
+ // Important global items
+ enum interrupt_modes current_interrupt_mode;
+ 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_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 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 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 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");
+       mpfps = find_floating_pointer((physaddr_t)KADDR(BIOS_ROM_BASE), (physaddr_t)KADDR(BIOS_ROM_BOUND));
+       
+       if (mpfps == NULL) {
+               
+               /* 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;
+                       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_FROM_STORED_PHYSADDR32(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 (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.
+                * This IS tested. Thanks VirtualBox!
+                */
+                               
+               physaddr_t top_of_mem = DEFAULT_TOPOFMEM;
+               
+               if (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 640K cap, incase CMOS lied...\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");
+               // TODO: Do SOMETHING here. We've never found such a system (they are generally ancient). Should we just panic?
+       }
+       else {
+               current_interrupt_mode = VW;
+               mptables_info("Virtual Wire\n");
+       }
+       
+       configuration_parse((physaddr_t)KADDR((uint32_t)(mpfps->pap)));
+       
+       proc_parse();
+       bus_parse();
+       ioapic_parse();
+       int_parse();
+       lint_parse();
+       
+ }
+ /** @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);
+       // This trusted count was authorized with the blessing of Zach.
+       // Blame Intel and the MP Spec for making me do this cast.
+       mpfps_t* mpfps = (mpfps_t* COUNT(count)) TC(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_FROM_STORED_VIRTADDR32(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;
+ }
+ /** @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;
+       
+       // Yet another trusted cast. 
+       // See comment at start of find_floating_pointer
+       uint8_t *addr_p = (uint8_t* COUNT(len)) TC(addr);
+       for (int i = 0; i < len; i++)
+               checksum += *(addr_p + i);
+       return (checksum == 0);
+ }
+ /** @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];
+       
+       // Another. See comment at start of find_floating_pointer
+       mpcth_t *mpcth = (mpcth_t* COUNT(1)) TC(conf_addr);
+       
+       for (int i = 0; i < NUM_ENTRY_TYPES; i++) {
+               mp_entries_count[i] = num_processed[i] = 0;
+       }
+               
+       // 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 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(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;
+               if (current_type >= NUM_ENTRY_TYPES)
+                       panic("CORRUPT MPTABLES CONFIGURATION ENTRY");
+                       
+               mp_entries_count[current_type]++;
+               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] * 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] * 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] * 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] * 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] * entry_types[LINT].length , 0);
+               if (mp_lint_entries == NULL)
+                       panic("Failed to allocate space for mp_lint_entires");
+       }
+       
+       current_addr = entry_base;
+       
+       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.");
+               
+               if (num_processed[current_type] >= mp_entries_count[current_type])
+                       panic("MPTABLES LIED ABOUT NUMBER OF ENTRIES. NO IDEA WHAT TO DO!");
+               
+               switch (current_type) {
+                       case PROC:
+                               memcpy( &mp_proc_entries[num_processed[PROC]], 
+                                               current_addr,  
+                                               entry_types[PROC].length);
+                               break;
+                       
+                       case BUS:
+                               memcpy( &mp_bus_entries[num_processed[BUS]], 
+                                               current_addr,  
+                                               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_t* COUNT(1)) TC(current_addr),  
+                                               entry_types[IOAPIC].length);
+                               break;
+                       case INT:
+                               memcpy( &mp_int_entries[num_processed[INT]], 
+                                               current_addr,  
+                                               entry_types[INT].length);
+                               break;
+                       case LINT:
+                               memcpy( &mp_lint_entries[num_processed[LINT]], 
+                                               (void*)current_addr,  
+                                               entry_types[LINT].length);
+                               break;
+                                               
+                       default: panic("UNKNOWN ENTRY TYPE");
+               }
+               num_processed[current_type]++;
+               current_addr += entry_types[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.
+ }
+ /** @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("-->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].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("-->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
+       // This should be done elsewhere.
+       
+       // 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("-->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");
+ }
+ /** @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("-->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].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].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
+                                */
+                               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.
+                                */
+                       }
+                                               
+                       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].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("-->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);
+               
+       }
++}
index 0000000,4fb7f0f..afee595
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,218 +1,218 @@@
 -#include <arch/types.h>
+ /*
+  * 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 <ros/common.h>
+ #include <pmap.h>
+ /* 
+  * 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__)  
+ // The HEX representation of the ascii string _MP_ we search for
+ #define MP_SIG                                0x5f504d5f      /* _MP_ */
+ // Base and (inclusive bound) of the BIOS region to check
+ #define BIOS_ROM_BASE         0xf0000
+ #define BIOS_ROM_BOUND                0xffff0 
+ // Where to look for the EBDA pointer
+ // Bound is dynamic. In first KB
+ #define EBDA_POINTER          0x040e 
+ #define EBDA_SIZE                     1024
+ /* 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
+ // 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)
+ enum interrupt_modes {
+       PIC, // PIC Mode 
+       VW,  // Virtural Wire Mode (Dev Boxes)
+       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,
+       IOAPIC =        2,
+       INT =           3,
+       LINT =          4
+ };
+ enum bus_types {
+     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 ];
+ } bus_type_name_t;
+ static bus_type_name_t bus_type_table[] =
+ {
+     { 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 ];
+ } 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 {
+     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           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_t;
+ typedef struct BUSENTRY {
+     uint8_t   type;
+     uint8_t   bus_id;
+     char (NT bus_type)[ 6 ];
+ } bus_entry_t;
+ typedef struct IOAPICENTRY {
+     uint8_t   type;
+     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           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  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_t isa_int_entry_t;
+ 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);
+ void configuration_parse(physaddr_t conf_addr);
+ void proc_parse();
+ void bus_parse();
+ void ioapic_parse();
+ void int_parse();
+ void lint_parse();
+ #endif /* !ROS_INC_MPTABLES_H */
index 0000000,b204ada..911c30f
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,164 +1,180 @@@
 -/* NE2000 NIC Driver Sketch
++/*
++ * Copyright (c) 2009 The Regents of the University of California
++ * See LICENSE for details.
++ */
++
+ #ifdef __DEPUTY__
+ #pragma nodeputy
+ #endif
++#ifdef __SHARC__
++#pragma nosharc
++#endif
++
+ #include <arch/mmu.h>
+ #include <arch/x86.h>
+ #include <arch/smp.h>
+ #include <arch/apic.h>
+ #include <arch/pci.h>
+ #include <arch/ne2k.h>
+ #include <ros/memlayout.h>
+ #include <atomic.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <trap.h>
+ #include <kmalloc.h>
+ #include <pmap.h>
+ #include <timing.h>
 - * Written by Paul Pearce.
++/** @file
++ * @brief NE2K Driver Sketch
++ *
++ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
++ *
++ * This driver will attempt to detect a ne2k device and run some interrupt
++ * tests. This is used for ioapic debugging in simulation
+  *
++ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+  *
++ * @todo Everything
+  */
+ extern uint32_t eth_up; // Fix this                               
+ uint32_t ne2k_irq;      // And this
+ uint32_t ne2k_io_base_addr;
+ void ne2k_init() {
+       
+       if (ne2k_scan_pci() < 0) return;
+       ne2k_setup_interrupts();
+       ne2k_configure_nic();
+       eth_up = 1;
+       
+       return;
+ }
+ int ne2k_scan_pci() {
+       
+       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...");
+       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++) {
+                               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 != NE2K_VENDOR_ID || dev_id != NE2K_DEV_ID)
+                                       continue;
+                               cprintf(" found on BUS %x DEV %x\n", i, j);
+                               // Find the IRQ
+                               ne2k_irq = pci_irq_map[i][j][k];
+                               ne2k_debug("-->IRQ: %u\n", ne2k_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;
+                                               ne2k_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
+                                       } else {
+                                               result = result & PCI_MEM_MASK;
+                                               ne2k_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
+                                               ne2k_io_base_addr = result;                                             
+                               }
+                               
+               return 0;
+       }
+       cprintf(" not found. No device configured.\n");
+       
+       return -1;
+ }
+ void ne2k_configure_nic() {
+       
+       ne2k_debug("-->Configuring Device.\n");
+         // Reset
+       inb(ne2k_io_base_addr + 0x1f);
+       // Configure
+         outb(ne2k_io_base_addr + 0x00, 0x22);
+         outb(ne2k_io_base_addr + 0x07, 0xFF);
+       outb(ne2k_io_base_addr + 0x0F, 0xFF);
+         uint8_t isr = inb(ne2k_io_base_addr + 0x07);
+         //cprintf("isr: %x\n", isr);
+       cprintf("Generating Interrupt...\n");
+       outb(ne2k_io_base_addr + 0x0A, 0x00);
+       outb(ne2k_io_base_addr + 0x0B, 0x00);
+       outb(ne2k_io_base_addr + 0x00, 0x0A);
+       udelay(10000000);
+         cprintf("Generating Interrupt again...\n");
+         outb(ne2k_io_base_addr + 0x0A, 0x00);
+         outb(ne2k_io_base_addr + 0x0B, 0x00);
+         outb(ne2k_io_base_addr + 0x00, 0x0A);
+         udelay(10000000);
+       
+       return;
+ }
+ void ne2k_setup_interrupts() {
+       
+       extern handler_t interrupt_handlers[];
+       
+       ne2k_debug("-->Setting interrupts.\n");
+       
+       // Kernel based interrupt stuff
+       register_interrupt_handler(interrupt_handlers, KERNEL_IRQ_OFFSET + ne2k_irq, ne2k_interrupt_handler, 0);
+       
+       ioapic_route_irq(ne2k_irq, 6);  
+       
+       return;
+ }
+ // We need to evaluate this routine in terms of concurrency.
+ // We also need to figure out whats up with different core interrupts
+ void ne2k_interrupt_handler(trapframe_t *tf, void* data) {
+       
+       cprintf("\nNE2K interrupt on core %u!\n", lapic_get_id());
+       uint8_t isr= inb(ne2k_io_base_addr + 0x07);
+       cprintf("isr: %x\n", isr);
+       outb(ne2k_io_base_addr + 0x07, isr);
+       return;                         
+ }
index 0000000,f64f1c7..8a4b9e5
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,29 +1,29 @@@
 -#include <arch/types.h>
+ #ifndef ROS_INC_NE2K_H
+ #define ROS_INC_NE2K_H
++#include <ros/common.h>
+ #include <trap.h>
+ #include <pmap.h>
+ #define ne2k_debug(...)  cprintf(__VA_ARGS__)  
+ #define ne2k_interrupt_debug(...) //cprintf(__VA_ARGS__)  
+ #define ne2k_frame_debug(...)  cprintf(__VA_ARGS__)  
+ #define NIC_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 NE2K_VENDOR_ID 0x10EC
+ #define NE2K_DEV_ID 0x8029
+ void ne2k_init();
+ int ne2k_scan_pci();
+ void ne2k_configure_nic();
+ void ne2k_setup_interrupts();
+ void ne2k_interrupt_handler(trapframe_t *tf, void* data);
+ #endif /* !ROS_INC_NE2K_H */
index 0000000,c6767fc..7276444
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,143 +1,148 @@@
 -}
+ /*
+  * Copyright (c) 2009 The Regents of the University of California
+  * See LICENSE for details.
+  */
++#ifdef __SHARC__
++#pragma nosharc
++#endif
++// Not currently sharc complient. 
++
+ /** @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. 
+  *
+  * No PCI Specifications (or even consulted) were harmed in the making of this file.
+  *
+  * @author Paul Pearce <pearce@eecs.berkeley.edu>
+  *
+  * @todo Build an entire useful PCI subsystem, not this hack with a few data structures laying around
+  *
+  */
+ #include <arch/x86.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <arch/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_t pci_dev_map[PCI_MAX_BUS][PCI_MAX_DEV][PCI_MAX_FUNC];
+ // 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
+ 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 = INVALID_BUS = 0xFFFF.
+       memset(irq_pci_map, 0xFF, sizeof(irq_pci_map));
+       
+       uint32_t address;
+       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");
+       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++) {
+                               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(bus, dev, func, reg); 
+                               // 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(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 line (a-d)
+                               address = MK_CONFIG_ADDR(bus, dev, func, PCI_IRQ_REG);
+                               outl(PCI_CONFIG_ADDR, address);
+                               uint8_t line = (inl(PCI_CONFIG_DATA) & PCI_LINE_MASK) >> PCI_LINE_SHFT;
+                               
+                               // If intn == 0, no interrupts used.
+                               if (line != INVALID_LINE) {
+                                       
+                                       // Now shift A to 0, B to 1, etc.
+                                       // 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;
+                                       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].line = line;
+                                       
+                                       // @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
+                                * 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++) {
+                                       reg = 4 + k;
+                                       address = MK_CONFIG_ADDR(bus, dev, func, reg << 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);
+                                       }                                       
+                               }
+                               #endif
+                               
+                               pci_debug("\n");
+                       }               
++}
index 0000000,69cd044..4ffc499
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,716 +1,754 @@@
 -const char *rl8168_packet_wrap(const char* data, size_t len) {
++/** @file
++ * @brief NE2K Driver Sketch       
++ *
++ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
++ *
++ * This driver will attempt to detect a ne2k device and run some interrupt
++ * tests. This is used for ioapic debugging in simulation
++ *
++ * @author Paul Pearce <pearce@eecs.berkeley.edu>
++ *
++ * @todo Everything                   
++ */
++
++#ifdef __SHARC__
++#pragma nosharc
++#endif
++
+ #ifdef __DEPUTY__
+ #pragma nodeputy
+ #endif
+ #include <arch/mmu.h>
+ #include <arch/x86.h>
+ #include <arch/smp.h>
+ #include <arch/apic.h>
+ #include <arch/pci.h>
+ #include <arch/rl8168.h>
+ #include <ros/memlayout.h>
+ #include <atomic.h>
+ #include <stdio.h>
+ #include <string.h>
+ #include <trap.h>
+ #include <kmalloc.h>
+ #include <pmap.h>
++/** @file
++ * @brief Realtek RL8168 Driver
++ *
++ * EXPERIMENTAL. DO NOT USE IF YOU DONT KNOW WHAT YOU ARE DOING
++ *
++ * This is a function rl8168 driver, that uses some really ugly hacks to achieve
++ * UDP communication with a remote syscall server, without a network stack.
++ *
++ * To enable use, define __NETWORK__ in your Makelocal
++ *
++ * @author Paul Pearce <pearce@eecs.berkeley.edu>
++ *
++ * @todo Move documention below into doxygen format.
++ * @todo See list in code
++ */
++
++
+ /* RealTek 8168d (8111d) NIC Driver
+  *
+  * Written by Paul Pearce.
+  *
+  * This is a really rough "driver". Really, its not a driver, just a kernel hack to give
+  * the kernel a way to receive and send packets. The basis of the init code is the OSDEV
+  * page on the 8169 chipset, which is a varient of this chipset (most 8169 drivers work 
+  * on the 8168d). http://wiki.osdev.org/RTL8169
+  * 
+  * Basic ideas (although no direct code) were gleamed from the OpenBSD re(4) driver,
+  * which can be found in sys/dev/ic/re.c. sys/dev/ic/rtl81x9reg.h is needed to make
+  * sense of the constants used in re.c.
+  *
+  * This is an ongoing work in progress. Main thing is we need a kernel interface for PCI
+  * devices and network devices, that we can hook into, instead of providing arbitary functions
+  * 
+  * TODO: Remove hacky syscall hack stuff (once we get a real stack).
+  * TODO: Jumbo frame support
+  * TODO: Use high priority transmit ring for syscall stuff.
+  * TODO: Discuss panic conditions.
+  * TODO: Shutdown cleanup kfrees()
+  * TODO: Use onboard timer interrupt to check for packets, instead of writing a bit each time we have a packet.
+  * TODO: CONCURRENCY!
+  */
++#ifndef USER_MAC_ADDRESS
++#define USER_MAC_ADDRESS {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
++#endif
++
+ struct Descriptor
+ {
+     unsigned int command,  /* command/status dword */
+                  vlan,     /* currently unused */
+                  low_buf,  /* low 32-bits of physical buffer address */
+                  high_buf; /* high 32-bits of physical buffer address */
+ };
+ uint32_t rl8168_io_base_addr = 0;
+ uint32_t rl8168_irq = 0;
+ char device_mac[6];
+ struct Descriptor *rx_des_kva;
+ struct Descriptor *rx_des_pa;
+ struct Descriptor *tx_des_kva;
+ struct Descriptor *tx_des_pa;
+ uint32_t rx_des_cur = 0;
+ uint32_t tx_des_cur = 0;
+ uint8_t eth_up = 0; // TODO: This needs to be somewhere global.
+ // Hacky stuff for syscall hack. Go away.
+ int packet_waiting;
+ int packet_buffer_size;
+ char* packet_buffer;
+ char* packet_buffer_orig;
+ int packet_buffer_pos = 0;
+ // End hacky stuff
+ void rl8168_init() {
+       
+       if (rl8168_scan_pci() < 0) return;
+       rl8168_read_mac();
+       rl8168_setup_descriptors();
+       rl8168_configure();
+       rl8168_setup_interrupts();
+       eth_up = 1;
+       
+       //Trigger sw based nic interrupt
+ /*    cprintf("Generating interrupt...\n");
+       outb(rl8168_io_base_addr + 0x38, 0x1);
+       cprintf("sleeping\n");
+       udelay(3000000);
+       cprintf("done\n");
+ */
+       return;
+ }
+ int rl8168_scan_pci() {
+       
+       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...");
+       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++) {
+                               uint32_t address;
+                               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;
+                               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
+                               rl8168_irq = pci_irq_map[i][j][k];
+                               rl8168_debug("-->IRQ: %u\n", rl8168_irq);
+                               // Loop over the BARs
+                               for (int k = 0; k <= 5; k++) {
+                                       reg = 4 + k;
+                                       address = MK_CONFIG_ADDR(bus, dev, func, reg << 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;
+                                               rl8168_debug("-->BAR%u: %s --> %x\n", k, "IO", result);
+                                       } else {
+                                               result = result & PCI_MEM_MASK;
+                                               rl8168_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
+                                               rl8168_io_base_addr = result;                                           
+                               }
+               
+               rl8168_debug("-->hwrev: %x\n", inl(rl8168_io_base_addr + RL_HWREV_REG) & RL_HWREV_MASK);
+               
+               return 0;
+       }
+       cprintf(" not found. No device configured.\n");
+       
+       return -1;
+ }
+ void rl8168_read_mac() {
+       
+       for (int i = 0; i < 6; i++)
+          device_mac[i] = inb(rl8168_io_base_addr + RL_MAC_OFFSET + i); 
+       
+       rl8168_debug("-->DEVICE MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & device_mac[0], 0xFF & device_mac[1],      
+                                                                   0xFF & device_mac[2], 0xFF & device_mac[3], 
+                                                                 0xFF & device_mac[4], 0xFF & device_mac[5]);
+       return;
+ }
+ void rl8168_setup_descriptors() {
+       
+       rl8168_debug("-->Setting up tx/rx descriptors.\n");
+                       
+       // Allocate room for the buffers. Include an extra ALIGN space.
+       // Buffers need to be on 256 byte boundries.
+       // Note: Buffers are alligned by kmalloc automatically to powers of 2 less than the size requested
+       // We request more than 256, thus they are aligned on 256 byte boundries
+       rx_des_kva = kmalloc(NUM_RX_DESCRIPTORS * sizeof(struct Descriptor), 0);
+       tx_des_kva = kmalloc(NUM_TX_DESCRIPTORS * sizeof(struct Descriptor), 0);
+       
+       if (rx_des_kva == NULL) panic("Can't allocate page for RX Ring");
+       if (tx_des_kva == NULL) panic("Can't allocate page for TX Ring");
+       
+       rx_des_pa = (struct Descriptor *)PADDR(rx_des_kva);
+       tx_des_pa = (struct Descriptor *)PADDR(tx_des_kva);
+       
+     for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
+               rl8168_set_rx_descriptor(i, TRUE); // Allocate memory for the descriptor
+               
+       for (int i = 0; i < NUM_TX_DESCRIPTORS; i++) 
+               rl8168_set_tx_descriptor(i);
+               
+       return;
+ }
+ void rl8168_set_rx_descriptor(uint32_t des_num, uint8_t reset_buffer) {
+       
+       // Set the OWN bit on all descriptors. Also set the buffer size.
+       rx_des_kva[des_num].command = (DES_OWN_MASK | (RL_RX_MAX_BUFFER_SIZE & DES_RX_SIZE_MASK));
+       
+       if (des_num == (NUM_RX_DESCRIPTORS - 1)) 
+               rx_des_kva[des_num].command = rx_des_kva[des_num].command | DES_EOR_MASK;
+       
+       if (reset_buffer) {
+               // Must be aligned on 8 byte boundries. Taken care of by kmalloc.
+               char *rx_buffer = kmalloc(RL_RX_MAX_BUFFER_SIZE, 0);
+       
+               if (rx_buffer == NULL) panic ("Can't allocate page for RX Buffer");
+               rx_des_kva[des_num].low_buf = PADDR(rx_buffer);
+               //.high_buf used if we do 64bit.
+       }
+       
+       return;
+ }
+ void rl8168_set_tx_descriptor(uint32_t des_num) {
+       
+       // Clear the command bits.
+       tx_des_kva[des_num].command = 0;
+       
+       // Set EOR bit on last descriptor
+       if (des_num == (NUM_TX_DESCRIPTORS - 1))
+               tx_des_kva[des_num].command = DES_EOR_MASK;     
+               
+       char *tx_buffer = kmalloc(RL_TX_MAX_BUFFER_SIZE, 0);
+       if (tx_buffer == NULL) panic ("Can't allocate page for TX Buffer");
+       tx_des_kva[des_num].low_buf = PADDR(tx_buffer);
+       //.high_buf used if we do 64bit.
+               
+       return;
+ }
+ void rl8168_configure() {
+       
+       // TODO: Weigh resetting the nic. Not really needed. Remove?
+       // TODO Check ordering of what we set.
+       // TODO Remove C+ register setting?
+       
+       rl8168_debug("-->Configuring Device.\n");
+       rl8168_reset();
+       // Magic to handle the C+ register. Completely undocumented, ripped from the BSE RE driver.
+       outl(rl8168_io_base_addr + RL_CP_CTRL_REG, RL_CP_MAGIC_MASK);
+       // Unlock EPPROM CTRL REG
+       outb(rl8168_io_base_addr + RL_EP_CTRL_REG, RL_EP_CTRL_UL_MASK);         
+       
+       // Set max RX Packet Size
+     outw(rl8168_io_base_addr + RL_RX_MXPKT_REG, RL_RX_MAX_SIZE);      
+               
+       // Set max TX Packet Size
+     outb(rl8168_io_base_addr + RL_TX_MXPKT_REG, RL_TX_MAX_SIZE);                      
+       // Set TX Des Ring Start Addr
+     outl(rl8168_io_base_addr + RL_TX_DES_REG, (unsigned long)tx_des_pa); 
+       
+       // Set RX Des Ring Start Addr
+     outl(rl8168_io_base_addr + RL_RX_DES_REG, (unsigned long)rx_des_pa);      
+       // Configure TX
+       outl(rl8168_io_base_addr + RL_TX_CFG_REG, RL_TX_CFG_MASK); 
+       
+       // Configure RX
+       outl(rl8168_io_base_addr + RL_TX_CFG_REG, RL_RX_CFG_MASK);                      
+       // Enable RX and TX in the CTRL Reg
+       outb(rl8168_io_base_addr + RL_CTRL_REG, RL_CTRL_RXTX_MASK);                     
+       // Lock the EPPROM Ctrl REG
+     outl(rl8168_io_base_addr + RL_EP_CTRL_REG, RL_EP_CTRL_L_MASK);            
+       
+       return;
+ }
+ void rl8168_reset() {
+       
+       rl8168_debug("-->Resetting device..... ");
+       outb(rl8168_io_base_addr + RL_CTRL_REG, RL_CTRL_RESET_MASK);
+       
+       // Wait for NIC to answer "done resetting" before continuing on
+       while (inb(rl8168_io_base_addr + RL_CTRL_REG) & RL_CTRL_RESET_MASK);
+       rl8168_debug(" done.\n");
+       
+       return;
+ }
+ void rl8168_setup_interrupts() {
+       
+       extern handler_t interrupt_handlers[];
+       
+       rl8168_debug("-->Setting interrupts.\n");
+       
+       // Enable NIC interrupts
+       outw(rl8168_io_base_addr + RL_IM_REG, RL_INTERRUPT_MASK);
+       
+       //Clear the current interrupts.
+       outw(rl8168_io_base_addr + RL_IS_REG, RL_INTRRUPT_CLEAR);
+       
+       // Kernel based interrupt stuff
+       register_interrupt_handler(interrupt_handlers, KERNEL_IRQ_OFFSET + rl8168_irq, rl8168_interrupt_handler, 0);
+       ioapic_route_irq(rl8168_irq, NE2K_IRQ_CPU);     
+       
+       return;
+ }
+ // We need to evaluate this routine in terms of concurrency.
+ // We also need to figure out whats up with different core interrupts
+ void rl8168_interrupt_handler(trapframe_t *tf, void* data) {
+       
+       rl8168_interrupt_debug("\nNic interrupt on core %u!\n", lapic_get_id());
+                               
+       // Read the offending interrupt(s)
+       uint16_t interrupt_status = inw(rl8168_io_base_addr + RL_IS_REG);
+       // Clear interrupts immediately so we can get the flag raised again.
+       outw(rl8168_io_base_addr + RL_IS_REG, interrupt_status);
+       
+       // Loop to deal with TOCTOU 
+       while (interrupt_status != 0x0000) {
+               // We can have multiple interrupts fire at once. I've personally seen this.
+               // This means we need to handle this as a series of independent if's
+               if (interrupt_status & RL_INT_ROK) {
+                       rl8168_interrupt_debug("-->RX OK\n");
+                       rl8168_handle_rx_packet();
+               }       
+       
+               if (interrupt_status & RL_INT_RERR) {
+                       rl8168_interrupt_debug("-->RX ERR\n");                  
+               }
+       
+               if (interrupt_status & RL_INT_TOK) {
+                       rl8168_interrupt_debug("-->TX OK\n");
+               }
+       
+               if (interrupt_status & RL_INT_TERR) {
+                       rl8168_interrupt_debug("-->TX ERR\n");                  
+               }
+       
+               if (interrupt_status & RL_INT_RDU) {
+                       rl8168_interrupt_debug("-->RX Descriptor Unavailable\n");                       
+               }
+       
+               if (interrupt_status & RL_INT_LINKCHG) {
+                       rl8168_interrupt_debug("-->Link Status Changed\n");                     
+               }
+       
+               if (interrupt_status & RL_INT_FOVW) {
+                       rl8168_interrupt_debug("-->RX Fifo Overflow\n");                        
+               }
+       
+               if (interrupt_status & RL_INT_TDU) {
+                       rl8168_interrupt_debug("-->TX Descriptor Unavailable\n");                       
+               }
+       
+               if (interrupt_status & RL_INT_SWINT) {
+                       rl8168_interrupt_debug("-->Software Generated Interrupt\n");
+               }
+       
+               if (interrupt_status & RL_INT_TIMEOUT) {
+                       rl8168_interrupt_debug("-->Timer Expired\n");
+               }
+       
+               if (interrupt_status & RL_INT_SERR) {
+                       rl8168_interrupt_debug("-->PCI Bus System Error\n");                    
+               }
+       
+               rl8168_interrupt_debug("\n");
+               
+               // Clear interrupts     
+               interrupt_status = inw(rl8168_io_base_addr + RL_IS_REG);
+               outw(rl8168_io_base_addr + RL_IS_REG, interrupt_status);
+       }
+       
+       // In the event that we got really unlucky and more data arrived after we set 
+       //  set the bit last, try one more check
+       rl8168_handle_rx_packet();
+       return;
+ }
+ // TODO: Does a packet too large get dropped or just set the error bits in the descriptor? Find out.
+ // TODO: Should we move on to look for the next descriptor? is it safe? TOCTOU
+ void rl8168_handle_rx_packet() {
+       
+       uint32_t current_command = rx_des_kva[rx_des_cur].command;
+       uint16_t packet_size;
+       
+       if (current_command & DES_OWN_MASK) {
+               rl8168_frame_debug("-->Nothing to process. Returning.");
+               return;
+       }
+               
+       rl8168_frame_debug("-->RX Des: %u\n", rx_des_cur);
+       
+       // Make sure we are processing from the start of a packet segment
+       if (!(current_command & DES_FS_MASK)) {
+               rl8168_frame_debug("-->ERR: Current RX descriptor not marked with FS mask. Panic!");
+               panic("RX Descriptor Ring FS out of sync");
+       }
+       
+       // NOTE: We are currently configured that the max packet size is large enough to fit inside 1 descriptor buffer,
+       // So we should never be in a situation where a packet spans multiple descriptors.
+       // When we change this, this should operate in a loop until the LS mask is found
+       // Loop would begin here.
+       
+       uint32_t rx_des_loop_cur = rx_des_cur;
+       uint32_t frame_size = 0;
+       uint32_t fragment_size = 0;
+       uint32_t num_frags = 0;
+       
+       char *rx_buffer = kmalloc(MAX_FRAME_SIZE, 0);
+       
+       if (rx_buffer == NULL) panic ("Can't allocate page for incoming packet.");
+       
+       do {
+               current_command =  rx_des_kva[rx_des_loop_cur].command;
+               fragment_size = rx_des_kva[rx_des_loop_cur].command & DES_RX_SIZE_MASK;
+               
+               // If we've looped through the entire ring and not found a terminating packet, bad nic state.
+               // Panic or clear all descriptors? This is a nic hardware error. 
+               if (num_frags && (rx_des_loop_cur == rx_des_cur)) {
+                       //for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
+                       //      set_rx_descriptor(i, FALSE); // Dont reallocate memory for the descriptor
+                       // rx_des_cur = 0;
+                       // return;
+                       rl8168_frame_debug("-->ERR: No ending segment found in RX buffer.\n");
+                       panic("RX Descriptor Ring out of sync.");
+               }
+               
+               num_frags++;
+               
+               
+               // Make sure we own the current packet. Kernel ownership is denoted by a 0. Nic by a 1.
+               if (current_command & DES_OWN_MASK) {
+                       rl8168_frame_debug("-->ERR: Current RX descriptor not owned by kernel. Panic!");
+                       panic("RX Descriptor Ring OWN out of sync");
+               }
+               
+               // Make sure if we are at the end of the buffer, the des is marked as end
+               if ((rx_des_loop_cur == (NUM_RX_DESCRIPTORS - 1)) && !(current_command & DES_EOR_MASK)) {
+                       rl8168_frame_debug("-->ERR: Last RX descriptor not marked with EOR mask. Panic!\n");
+                       panic("RX Descriptor Ring EOR Missing");
+               }
+               
+               // We set a max frame size and the nic violated that. 
+               // Panic or clear all desriptors?
+               if ((frame_size + fragment_size) > MAX_FRAME_SIZE) {
+                       //for (int i = 0; i < NUM_RX_DESCRIPTORS; i++) 
+                       //      set_rx_descriptor(i, FALSE); // Dont reallocate memory for the descriptor
+                       // rx_des_cur = 0;
+                       // return;
+                       rl8168_frame_debug("-->ERR: Nic sent %u byte packet. Max is %u\n", frame_size, MAX_FRAME_SIZE);
+                       panic("NIC Sent packets larger than configured.");
+               }
+               
+               // Move the fragment data into the buffer
+               memcpy(rx_buffer + frame_size, KADDR(rx_des_kva[rx_des_loop_cur].low_buf), fragment_size);
+               
+               // Reset the descriptor. No reuse buffer.
+               rl8168_set_rx_descriptor(rx_des_loop_cur, FALSE);
+               
+               // Note: We mask out fragment sizes at 0x3FFFF. There can be at most 1024 of them.
+               // This can not overflow the uint32_t we allocated for frame size, so
+               // we dont need to worry about mallocing too little then overflowing when we read.
+               frame_size = frame_size + fragment_size;
+               
+               // Advance to the next descriptor
+               rx_des_loop_cur = (rx_des_loop_cur + 1) % NUM_RX_DESCRIPTORS;
+               
+       } while (!(current_command & DES_LS_MASK));
+       
+       // Hack for UDP syscall hack. 
+       // This is a quick hack to let us deal with where to put packets coming in. This is not concurrency friendly
+       // In the event that we get 2 incoming frames for our syscall test (shouldnt happen)
+       // We cant process more until another packet comes in. This is ugly, but this code goes away as soon as we integrate a real stack.
+       // This keys off the source port, fix it for dest port. 
+       // Also this may access packet regions that are wrong. If someone addresses empty packet for our interface
+       // and the bits that happened to be in memory before are the right port, this will trigger. this is bad
+       // but since syscalls are a hack for only 1 machine connected, we dont care for now.
+       
+       if ((current_command & DES_PAM_MASK) && (*((uint16_t*)(rx_buffer + 36)) == 0x9bad)) {
+               
+               if (packet_waiting) return;
+               packet_buffer = rx_buffer + PACKET_HEADER_SIZE;
+               
+               // So ugly I want to cry
+               packet_buffer_size = *((uint16_t*)(rx_buffer + 38)); 
+               packet_buffer_size = (((uint16_t)packet_buffer_size & 0xff00) >> 8) |  (((uint16_t)packet_buffer_size & 0x00ff) << 8);          
+               packet_buffer_size = packet_buffer_size - 8;
+               packet_buffer_orig = rx_buffer;
+               packet_buffer_pos = 0;
+               
+               packet_waiting = 1;
+               
+               rl8168_process_frame(rx_buffer, frame_size, current_command);
+               
+               rx_des_cur = rx_des_loop_cur;
+               
+               return;
+       }
+       
+       // END HACKY STUFF
+       
+       // Chew on the frame data. Command bits should be the same for all frags.
+       rl8168_process_frame(rx_buffer, frame_size, current_command);
+       rx_des_cur = rx_des_loop_cur;
+       
+       kfree(rx_buffer);
+       
+       return;
+ }
+ // This is really more of a debug level function. Will probably go away once we get a stack going.
+ void rl8168_process_frame(char *frame_buffer, uint32_t frame_size, uint32_t command) {
+               
+       rl8168_frame_debug("-->Command: %x\n", command);
+       rl8168_frame_debug("-->Size: %u\n", frame_size);
+       
+       if (frame_buffer == NULL)
+               return;
+       
+       // This is hacky. Once we know what our stack will look like, change this.
+       // Once remove check for 0 size.
+       if (frame_size < MINIMUM_PACKET_SIZE) {
+               rl8168_frame_debug("-->Packet too small. Discarding.\n");
+               return;
+       }
+       
+       char dest_mac[6];
+       char source_mac[6];
+       char eth_type[2];
+       
+       for (int i = 0; i < 6; i++) {
+               dest_mac[i] = frame_buffer[i];
+       }
+       
+       for (int i = 0; i < 6; i++) {
+               source_mac[i] = frame_buffer[i+6];
+       }
+       
+       eth_type[0] = frame_buffer[12];
+       eth_type[1] = frame_buffer[13];
+       
+       if (command & DES_MAR_MASK) {
+               rl8168_frame_debug("-->Multicast Packet.\n");
+       }
+       
+       if (command & DES_PAM_MASK) {
+               rl8168_frame_debug("-->Physical Address Matched.\n");
+       }
+       
+       if (command & DES_BAR_MASK) {
+               rl8168_frame_debug("-->Broadcast Packet.\n");
+       }
+       
+       // Note: DEST comes before SRC in the ethernet frame, but that 
+       
+       rl8168_frame_debug("-->DEST   MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & dest_mac[0], 0xFF & dest_mac[1],    
+                                                                            0xFF & dest_mac[2], 0xFF & dest_mac[3],    
+                                                                              0xFF & dest_mac[4], 0xFF & dest_mac[5]);
+       
+       rl8168_frame_debug("-->SOURCE MAC: %02x:%02x:%02x:%02x:%02x:%02x\n", 0xFF & source_mac[0], 0xFF & source_mac[1],        
+                                                                            0xFF & source_mac[2], 0xFF & source_mac[3],        
+                                                                              0xFF & source_mac[4], 0xFF & source_mac[5]);
+       rl8168_frame_debug("-->ETHR MODE: %02x%02x\n", 0xFF & eth_type[0], 0xFF & eth_type[1]);
+               
+       return;
+ }
+ // Main routine to send a frame. Just sends it and goes.
+ // Card supports sending across multiple fragments.
+ // Would we want to write a function that takes a larger packet and generates fragments?
+ // This seems like the stacks responsibility. Leave this for now. may in future
+ // Remove the max size cap and generate multiple packets.
+ int rl8168_send_frame(const char *data, size_t len) {
+       if (data == NULL)
+               return -1;
+       if (len == 0)
+               return 0;
+       if (tx_des_kva[tx_des_cur].command & DES_OWN_MASK) {
+               rl8168_frame_debug("-->TX Ring Buffer Full!\n");
+               return -1;
+       }
+       
+       if (len > MAX_FRAME_SIZE) {
+               rl8168_frame_debug("-->Frame Too Large!\n");
+               return -1;
+       }
+       
+       memcpy(KADDR(tx_des_kva[tx_des_cur].low_buf), data, len);
+       tx_des_kva[tx_des_cur].command = tx_des_kva[tx_des_cur].command | len | DES_OWN_MASK | DES_FS_MASK | DES_LS_MASK;
+       // For this revision of the NIC, the checksum bits get set in the vlan field not the command field.
+       // THIS IS A HACK: Need to reach inside the frame we are sending and detect if its of type ip/udp/tcp and set right flag
+       // For now, for the syscall hack, force ip checksum on. (we dont care about udp checksum).
+       // Add an argument to function to specify packet type?
+       tx_des_kva[tx_des_cur].vlan = DES_TX_IP_CHK_MASK;
+       
+       tx_des_cur = (tx_des_cur + 1) % NUM_TX_DESCRIPTORS;
+       
+       //rl8168_frame_debug("-->Sent packet.\n");
+       
+       outb(rl8168_io_base_addr + RL_TX_CTRL_REG, RL_TX_SEND_MASK);
+       
+       return len;
+ }
+ // This function is a complete hack for syscalls until we get a stack.
+ // the day I delete this monstrosity of code I will be a happy man --Paul
++char *rl8168_packet_wrap(const char* data, size_t len) {
+       
+       #define htons(A) ((((uint16_t)(A) & 0xff00) >> 8) | \
+                           (((uint16_t)(A) & 0x00ff) << 8))
+       #define htonl(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \
+                           (((uint32_t)(A) & 0x00ff0000) >> 8)  | \
+                           (((uint32_t)(A) & 0x0000ff00) << 8)  | \
+                           (((uint32_t)(A) & 0x000000ff) << 24))
+       #define ntohs  htons
+       #define ntohl  htohl
+       if ((len == 0) || (data == NULL))
+               return NULL;
+       
+       struct ETH_Header
+       {
+               char dest_mac[6];
+               char source_mac[6];
+               uint16_t eth_type;
+       };
+       
+       struct IP_Header
+       {
+               uint32_t ip_opts0;
+               uint32_t ip_opts1;
+               uint32_t ip_opts2;
+               uint32_t source_ip;
+               uint32_t dest_ip;
+       };
+       
+       struct UDP_Header
+       {
+               uint16_t source_port;
+               uint16_t dest_port;
+               uint16_t length;
+               uint16_t checksum;
+       };      
+       
+       // Hard coded to paul's laptop's mac
+       //Format for Makelocal file: -DUSER_MAC_ADDRESS="{0x00, 0x23, 0x32, 0xd5, 0xae, 0x82}"
+       char dest_mac_address[6] = USER_MAC_ADDRESS;
+       
+       
+       uint32_t source_ip = 0xC0A8000A; // 192.168.0.10
+       uint32_t dest_ip   = 0xC0A8000B; // 192.168.0.11
+  
+       
+       if (len > MAX_PACKET_DATA) {
+               rl8168_frame_debug("Bad packet size for packet wrapping");
+               return NULL;
+       }
+       
+       char* wrap_buffer = kmalloc(MAX_PACKET_SIZE, 0);
+       
+       if (wrap_buffer == NULL) {
+               rl8168_frame_debug("Can't allocate page for packet wrapping");
+               return NULL;
+       }
+       
+       struct ETH_Header *eth_header = (struct ETH_Header*) wrap_buffer;
+       struct IP_Header *ip_header = (struct IP_Header*) (wrap_buffer + sizeof(struct ETH_Header));
+       struct UDP_Header *udp_header = (struct UDP_Header*) (wrap_buffer + sizeof(struct ETH_Header) + sizeof(struct IP_Header));
+       
+       // Setup eth data
+       for (int i = 0; i < 6; i++) 
+               eth_header->dest_mac[i] = dest_mac_address[i];
+               
+       for (int i = 0; i < 6; i++) 
+               eth_header->source_mac[i] = device_mac[i];
+               
+       eth_header->eth_type = htons(0x0800);
+       
+       // Setup IP data
+       ip_header->ip_opts0 = htonl((4<<28) | (5 << 24) | (len + 28));
+       ip_header->ip_opts1 = 0;
+       ip_header->ip_opts2 = 0x00110a;
+       ip_header->source_ip = htonl(source_ip);
+       ip_header->dest_ip = htonl(dest_ip);
+       
+       // Setup UDP Data
+       udp_header->source_port = htons(44443);
+       udp_header->dest_port = htons(44444);
+       udp_header->length = htons(8 + len);
+       udp_header->checksum = 0;
+       
+       memcpy (wrap_buffer + PACKET_HEADER_SIZE, data, len);
+       
+       return wrap_buffer;     
+ }
index 0000000,a0447ac..03b2365
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,149 +1,149 @@@
 -#include <arch/types.h>
+ #ifndef ROS_INC_REALTEK_H
+ #define ROS_INC_REALTEK_H
 -const char *rl8168_packet_wrap(const char* data, size_t len);
++#include <ros/common.h>
+ #include <trap.h>
+ #include <pmap.h>
+ #define rl8168_debug(...)  //cprintf(__VA_ARGS__)  
+ #define rl8168_interrupt_debug(...) //cprintf(__VA_ARGS__)  
+ #define rl8168_frame_debug(...)  //cprintf(__VA_ARGS__)  
+ // We need to provide some global interface for sending and receiving packets to a generic interface
+ //  for now, that is this set of Macros! They aren't in caps since the final inteface shoudn't be.
+ #define packet_wrap rl8168_packet_wrap
+ #define send_frame rl8168_send_frame
+ #define NE2K_IRQ_CPU          5
+ #define REALTEK_VENDOR_ID   0x10ec
+ #define REALTEK_DEV_ID      0x8168
+ // Realtek Offsets
+ #define RL_HWREV_REG          0x40
+ #define RL_MAC_OFFSET         0x00
+ #define RL_CTRL_REG         0x37
+ #define RL_IM_REG                     0x3c
+ #define RL_IS_REG                     0x3E
+ #define RL_EP_CTRL_REG                0x50
+ #define RL_RX_CFG_REG                 0x44
+ #define RL_TX_CFG_REG         0x40
+ #define RL_RX_MXPKT_REG     0xDA
+ #define RL_TX_MXPKT_REG     0xEC
+ #define RL_RX_DES_REG       0xE4
+ #define RL_TX_DES_REG       0x20
+ #define RL_TX_CTRL_REG                0x38    
+ #define RL_CP_CTRL_REG                0xE0            
+ // Realtek masks
+ #define RL_HWREV_MASK         0x7C800000
+ #define RL_CTRL_RXTX_MASK     0x0C
+ #define RL_CTRL_RESET_MASK  0x10
+ #define RL_EP_CTRL_UL_MASK    0xC0
+ #define RL_EP_CTRL_L_MASK     0x00
+ #define RL_TX_SEND_MASK               0x40
+ #define RL_CP_MAGIC_MASK      0x002B // Magic bits pulled from the BSD driver.
+                                                                  // Are listed as needed for TX/RX checksumming
+ // NOTE: THESE SHOULD BE BROKEN DOWN INTO A SERIES OF BITS TO REPERSENT THE VARIOUS OPTIONS
+ // AND THEN THE MASK SHOULD BE DEFINED TO BE AN OR OF THOSE BITS. THIS IS A QUICK HACK JOB.
+ // See interrupts below for how this should be done
+ #define RL_RX_CFG_MASK                0x0000E70F  // RXFTH: unlimited, MXDMA: unlimited, AAP: set (promisc. mode set)
+ #define RL_TX_CFG_MASK                0x3000700  // IFG: normal, MXDMA: unlimited.  crc appended
+ // Realtek interrupt bits
+ #define RL_INT_SERR                   0x8000
+ #define RL_INT_TIMEOUT                0x4000
+ #define RL_INT_SWINT          0x0100
+ #define RL_INT_TDU                    0x0080
+ #define RL_INT_FOVW                   0x0040
+ #define RL_INT_LINKCHG                0x0020
+ #define RL_INT_RDU                    0x0010
+ #define RL_INT_TERR                   0x0008
+ #define RL_INT_TOK                    0x0004
+ #define RL_INT_RERR                   0x0002
+ #define RL_INT_ROK                    0x0001
+ #define RL_INTERRUPT_MASK     RL_INT_LINKCHG | RL_INT_TOK | RL_INT_ROK | RL_INT_SWINT
+ #define RL_INTRRUPT_CLEAR     0xFFFF
+ // Realtek descriptor command bits
+ #define DES_OWN_MASK          0x80000000
+ #define DES_EOR_MASK          0x40000000
+ #define DES_RX_SIZE_MASK      0x3FFF
+ #define DES_FS_MASK                   0x20000000
+ #define DES_LS_MASK                   0x10000000
+ #define DES_MAR_MASK          0x08000000
+ #define DES_PAM_MASK          0x04000000
+ #define DES_BAR_MASK          0x02000000
+ // TFor some reaosn the bits are in an undocumented position for our NIC
+ // They should be part of the command field, at the commented addrs below. instead
+ // they are part of the vlan field as stated below.
+ //#define DES_TX_IP_CHK_MASK  0x40000
+ //#define DES_TX_UDP_CHK_MASK 0x20000
+ //#define DES_TX_TCP_CHK_MASK 0x10000
+ #define DES_TX_IP_CHK_MASK  0x20000000
+ #define DES_TX_UDP_CHK_MASK 0x80000000
+ #define DES_TX_TCP_CHK_MASK 0x40000000
+ // Offset used for indexing IRQs
+ #define KERNEL_IRQ_OFFSET     32
+ // Basic packet sizing
+ // TODO handle jumbo packets
+ #define ETHERNET_ENCAP_SIZE   18
+ #define MTU                                   1500    
+ #define MAX_FRAME_SIZE                ETHERNET_ENCAP_SIZE + MTU       
+       
+ // Realtek Descriptor Related Sizing
+ #define NUM_TX_DESCRIPTORS    1024
+ #define NUM_RX_DESCRIPTORS    1024
+ // !!!!!!!!! need to verify the 128byte nature of this field. Spec says it could be 32 for some chips.
+ #define RL_TX_MAX_BUFFER_SIZE  ROUNDUP(MAX_FRAME_SIZE, 128)
+ #define RL_RX_MAX_BUFFER_SIZE  ROUNDUP(MAX_FRAME_SIZE, 8)    // Might be able to be 4 less. Does it strip out the crc flag?
+ #define RL_TX_MAX_SIZE                RL_TX_MAX_BUFFER_SIZE / 128
+ #define RL_RX_MAX_SIZE                RL_RX_MAX_BUFFER_SIZE
+ #define RL_DES_ALIGN  256
+ #define RL_BUF_ALIGN  8
+ // ^----- Good line ------^
+ // v----- Evil line ------v
+ // Hacky stuff for syscalls go away.
+ #define MINIMUM_PACKET_SIZE 14 // kinda evil. probably evil.
+ #define MAX_PACKET_SIZE               MTU
+ #define PACKET_HEADER_SIZE  20 + 8 + 14 //IP UDP ETH
+ #define MAX_PACKET_DATA               MAX_FRAME_SIZE - PACKET_HEADER_SIZE
+ // This number needs verification! Also, this is a huge hack, as the driver shouldnt care about UDP/IP etc.
++char *rl8168_packet_wrap(const char* data, size_t len);
+ // ^----- Evil line ------^
+ // v----- Good line ------v
+ void rl8168_init(void);
+ void rl8168_reset(void);
+ void rl8168_interrupt_handler(trapframe_t *tf, void* data);
+ int rl8168_scan_pci(void);
+ void rl8168_read_mac(void);
+ void rl8168_setup_interrupts(void);
+ void rl8168_setup_descriptors(void);
+ void rl8168_configure(void);
+ void rl8168_handle_rx_packet(void);
+ void rl8168_set_rx_descriptor(uint32_t des_num, uint8_t reset_buffer);
+ void rl8168_set_tx_descriptor(uint32_t des_num);
+ void rl8168_process_frame(char *frame_buffer, uint32_t frame_size, uint32_t command);
+ int rl8168_send_frame(const char *data, size_t len);
+ #endif /* !ROS_INC_REALTEK_H */
Simple merge
Simple merge
@@@ -15,6 -15,11 +15,17 @@@ enu
        SYS_cputs,
        SYS_cgetc,
        SYS_getcpuid,
 -      SYS_serial_write,
 -      SYS_serial_read,
++
++      // The next 3 syscalls go with the experimental network
++      // driver. These syscalls are used by newlib_backend /
++      // our remote binary loader to pull data from / put data
++      // into a buffer managed by the network driver.
++      // These should go away as things mature. 
+       SYS_eth_read,
+       SYS_eth_write,
+       SYS_run_binary,
++      // End of extra network syscalls
++
        SYS_getpid,
        SYS_proc_destroy,
        SYS_shared_page_alloc,
Simple merge
@@@ -44,10 -49,10 +49,11 @@@ KERN_APPFILES := 
                   $(USER_APPS_ROSLIB_DIR)/null \
                   $(USER_APPS_ROSLIB_DIR)/spawn \
                   $(USER_APPS_ROSLIB_DIR)/hello \
 +                 $(USER_APPS_ROSLIB_DIR)/mhello \
+                  $(USER_APPS_ROSLIB_DIR)/measurements \
+                  $(USER_APPS_PARLIB_DIR)/draw_nanwan_standalone \
                   $(USER_APPS_PARLIB_DIR)/channel_test_client \
                   $(USER_APPS_PARLIB_DIR)/channel_test_server \
-                  $(USER_APPS_ROSLIB_DIR)/measurements \
                   $(USER_APPS_PARLIB_DIR)/hello \
                   $(USER_APPS_PARLIB_DIR)/matrix
  #                 $(USER_APPS_PARLIB_DIR)/open_read
diff --cc kern/src/init.c
  #include <syscall.h>
  #include <kclock.h>
  #include <manager.h>
 +#include <testing.h>
  
+ #include <arch/rl8168.h>
+ #include <arch/ne2k.h>
+ #include <arch/mptables.h>
+ #include <arch/pci.h>
+ #include <arch/ioapic.h>
  void kernel_init(multiboot_info_t *mboot_info)
  {
        extern char (BND(__this, end) edata)[], (SNT end)[];
        idt_init();
        sysenter_init();
        timer_init();
+       
++      // @todo: Add an arch specific init? This is ugly
+       #ifdef __i386__
+       mptables_parse();
+       pci_init();
+       ioapic_init(); // MUST BE AFTER PCI/ISA INIT!
+       #endif // __i386__
 -      
 -      
++              
        // this returns when all other cores are done and ready to receive IPIs
        smp_boot();
 -      #ifdef __i386__
 +      env_init();
+       
 -      #endif // __i386__
++
++      /* EXPERIMENTAL NETWORK FUNCTIONALITY
++       * To enable, define __NETWORK__ in your Makelocal
++       * If enabled, will load the rl8168 driver (if device exists)
++       * and will a boot into userland matrix, so remote syscalls can be performed.
++       * If in simulation, will do some debugging information with the ne2k device
++       *
++       * Note: If you use this, you should also define the mac address of the 
++       * teathered machine via USER_MAC_ADDRESS in Makelocal.
++       *
++       * Additionally, you should have a look at the syscall server in the tools directory
++       */
++      #ifdef __NETWORK__
+       rl8168_init();          
+       ne2k_init();
++      #endif // __NETWORK__
  
        manager();
  }
diff --cc kern/src/kfs.c
@@@ -29,12 -25,12 +29,13 @@@ DECL_PROG(roslib_fptest)
  DECL_PROG(roslib_null);
  DECL_PROG(roslib_spawn);
  DECL_PROG(roslib_hello);
 +DECL_PROG(roslib_mhello);
  DECL_PROG(roslib_measurements);
+ DECL_PROG(parlib_draw_nanwan_standalone);
  DECL_PROG(parlib_channel_test_client);
  DECL_PROG(parlib_channel_test_server);
- DECL_PROG(parlib_matrix);
  DECL_PROG(parlib_hello);
+ DECL_PROG(parlib_matrix);
  
  struct kfs_entry kfs[MAX_KFS_FILES] = {
        KFS_ENTRY(roslib_proctests)
        KFS_ENTRY(roslib_null)
        KFS_ENTRY(roslib_spawn)
        KFS_ENTRY(roslib_hello)
 -        KFS_ENTRY(roslib_measurements)
 +      KFS_ENTRY(roslib_mhello)
 +      KFS_ENTRY(roslib_measurements)
+       KFS_ENTRY(parlib_draw_nanwan_standalone)
        KFS_ENTRY(parlib_channel_test_client)
        KFS_ENTRY(parlib_channel_test_server)
-       KFS_ENTRY(parlib_matrix)
        KFS_ENTRY(parlib_hello)
+       KFS_ENTRY(parlib_matrix)
  };
  
  ssize_t kfs_lookup_path(char* path)
@@@ -122,9 -119,10 +122,10 @@@ void* kmalloc(size_t size, int flags
        for(int i=0; i<npages; i++) {
                page_t* page;
                page_alloc_specific(&page, first+i);
-               page_incref(page);
 -              // NEXT LINE MUST BE MERGED INTO MASTER (Also, Kevin doesn't like.)
++              // Kevin doesn't like this next line 
+               page_incref(page); 
                page->num_cons_links = npages-i;
 -              LIST_INSERT_HEAD(&pages_list, page, global_link);
 +              LIST_INSERT_HEAD(&pages_list, page, page_link);
                kmallocdebug("mallocing page: %u\n", first+i);
                kmallocdebug("at addr: %p\n", ppn2kva(first+i));
        }
  void manager(void)
  {
        static uint8_t progress = 0;
 -      env_t *envs[256];
 -      
++
 +      struct proc *envs[256];
 +      struct proc *p ;
 +
++      // This is a bypass of the standard manager structure, for network use
++      // If enabled, this spawns parlib_matrix, and allows the execution
++      // of a remote binary to function correctly (schedule() call below)
++      #ifdef __NETWORK__      
+       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();
++      #endif 
        switch (progress++) {
                case 0:
 +                      // Here's how to do a multicored/parallel process:
 +                      p = kfs_proc_create(kfs_lookup_path("roslib_mhello"));
 +                      // being proper and all:
 +                      proc_set_state(p, PROC_RUNNABLE_S);
 +                      proc_set_state(p, PROC_RUNNING_S);
 +                      proc_set_state(p, PROC_RUNNABLE_M);
 +      
 +                      // set vcoremap with dispatch plan.  usually done by schedule()
 +                      spin_lock_irqsave(&p->proc_lock);
 +                      p->num_vcores = 5; // assuming 5 are free, this is just an example
 +                      spin_lock(&idle_lock); // need to grab the cores
 +                      for (int i = 0; i < 5; i++) {
 +                              // grab the last one on the list
 +                              p->vcoremap[i] = idlecoremap[num_idlecores-1];
 +                              num_idlecores--;
 +                      }
 +                      spin_unlock(&idle_lock);
 +                      spin_unlock_irqsave(&p->proc_lock);
 +                      proc_run(p);
 +                      udelay(5000000);
 +                      printk("Killing p\n");
 +                      proc_destroy(p);
 +                      printk("Killed p\n");
 +                      udelay(1000000);
 +                      panic("This is okay");
 +                      break;
 +              case 1:
                        envs[0] = kfs_proc_create(kfs_lookup_path("roslib_hello"));
                        proc_set_state(envs[0], PROC_RUNNABLE_S);
                        proc_run(envs[0]);
Simple merge
@@@ -1,10 -1,11 +1,15 @@@
  /* See COPYRIGHT for copyright information. */
  
 -
 +#ifdef __SHARC__
 +#pragma nosharc
 +#endif
 +
+ #ifdef __DEPUTY__
+ #pragma nodeputy
+ #endif
 +#include <ros/common.h>
+ #include <arch/types.h>
  #include <arch/arch.h>
  #include <arch/mmu.h>
  #include <arch/console.h>
@@@ -57,6 -62,100 +66,94 @@@ static ssize_t sys_serial_read(env_t* e
        #endif
  }
  
 -// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
++//
++/* START OF REMOTE SYSTEMCALL SUPPORT SYSCALLS. THESE WILL GO AWAY AS THINGS MATURE */
++//
++
+ static ssize_t sys_run_binary(env_t* e, void *binary_buf, void* arg, size_t len) {
+       uint8_t* new_binary = kmalloc(len, 0);
+       if(new_binary == NULL)
+               return -ENOMEM;
+       memcpy(new_binary, binary_buf, len);
+       env_t* env = env_create((uint8_t*)new_binary, len);
+       kfree(new_binary);
+       proc_set_state(env, PROC_RUNNABLE_S);
+       schedule_proc(env);
+       sys_yield(e);
+       
+       return 0;
+ }
 -/*
 -static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
 -{ 
 -      extern int eth_up;
 -      
 -      if (eth_up) {
 -              
 -              char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
 -              
 -              return(send_frame(buf, len));
 -      }
 -      return -EINVAL;
 -}
 -*/
++
++// This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+ static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len) 
+ { 
+       extern int eth_up;
+       
+       if (eth_up) {
+               
+               char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
+               int total_sent = 0;
+               int just_sent = 0;
+               int cur_packet_len = 0;
+               while (total_sent != len) {
+                       cur_packet_len = ((len - total_sent) > MAX_PACKET_DATA) ? MAX_PACKET_DATA : (len - total_sent);
+                       char* wrap_buffer = packet_wrap(buf + total_sent, cur_packet_len);
+                       just_sent = send_frame(wrap_buffer, cur_packet_len + PACKET_HEADER_SIZE);
+                       
+                       if (just_sent < 0)
+                               return 0; // This should be an error code of its own
+                               
+                       if (wrap_buffer)
+                               kfree(wrap_buffer);
+                               
+                       total_sent += cur_packet_len;
+               }
+               
+               return (ssize_t)len;
+               
+       }
+       else
+               return -EINVAL;
+ }
 -
 -// This is probably not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
++// This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
+ static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf, size_t len) 
+ {
+       extern int eth_up;
+       
+       if (eth_up) {
+               extern int packet_waiting;
+               extern int packet_buffer_size;
+               extern char* packet_buffer;
+               extern char* packet_buffer_orig;
+               extern int packet_buffer_pos;
+                       
+               if (packet_waiting == 0)
+                       return 0;
+                       
+               int read_len = ((packet_buffer_pos + len) > packet_buffer_size) ? packet_buffer_size - packet_buffer_pos : len;
+               memcpy(buf, packet_buffer + packet_buffer_pos, read_len);
+       
+               packet_buffer_pos = packet_buffer_pos + read_len;
+       
+               if (packet_buffer_pos == packet_buffer_size) {
+                       kfree(packet_buffer_orig);
+                       packet_waiting = 0;
+               }
+       
+               return read_len;
+       }
+       else
+               return -EINVAL;
+ }
++//
++/* END OF REMOTE SYSTEMCALL SUPPORT SYSCALLS. */
++//
++
  static ssize_t sys_shared_page_alloc(env_t* p1,
                                       void**DANGEROUS _addr, envid_t p2_id,
                                       int p1_flags, int p2_flags
@@@ -385,6 -476,6 +482,14 @@@ intreg_t syscall(env_t* e, uintreg_t sy
                        return sys_serial_write(e, (char *DANGEROUS)a1, (size_t)a2);
                case SYS_serial_read:
                        return sys_serial_read(e, (char *DANGEROUS)a1, (size_t)a2);
++                case SYS_run_binary:
++                        return sys_run_binary(e, (char *DANGEROUS)a1,
++                                              (char* DANGEROUS)a2, (size_t)a3);
++                case SYS_eth_write:
++                        return sys_eth_write(e, (char *DANGEROUS)a1, (size_t)a2);
++                case SYS_eth_read:
++                        return sys_eth_read(e, (char *DANGEROUS)a1, (size_t)a2);
++
        #endif
  
        #ifdef __sparc_v8__
  #include <multiboot.h>
  #include <pmap.h>
  #include <page_alloc.h>
 -
+ #include <pmap.h>
  
 -#define test_vector 0xeb
 -
  #ifdef __i386__
  
  void test_ipi_sending(void)
Simple merge
Simple merge
Simple merge
@@@ -70,7 -150,7 +150,7 @@@ response_t *send_message(msg_t *msg, in
  /* write_to_channel()
   * Send a message out over the channel, defined by msg, of length len
   */
--int write_to_channel(char *msg, int len);
++int write_to_channel(msg_t *msg, int len);
  
  #endif //_NEWLIB_LIBC_WRAPPERS_H_
  
Simple merge
  #include <stdlib.h>
  #include <stdio.h>
  #include <debug.h>
 +#include <sys/times.h>
  
- #define debug_in_out(...) // debug(__VA_ARGS__)  
- #define debug_write_check(fmt, ...) // debug(fmt, __VA_ARGS__)
  /* environ
   * A pointer to a list of environment variables and their values. 
   * For a minimal environment, this empty list is adequate.
@@@ -783,8 -677,9 +678,9 @@@ ssize_t write(int file, const void *ptr
  /* write_to_channel()
   * Send a message out over the channel, defined by msg, of length len
   */
--int write_to_channel(char * msg, int len)
++int write_to_channel(msg_t * msg, int len)
  {
-       return sys_serial_write((char*)msg, len);
+       //return sys_serial_write((char*)msg, len);
 -      return sys_eth_write(msg, len);
++      return sys_eth_write((char*)msg, len);
+       
 -}
 +}