Moved x86 specific files into the arch/i386 directory. Modified files as needed.
authorPaul Pearce <pearce@eecs.berkeley.edu>
Wed, 9 Sep 2009 03:04:56 +0000 (20:04 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Wed, 9 Sep 2009 03:04:56 +0000 (20:04 -0700)
22 files changed:
kern/arch/i386/Makefrag
kern/arch/i386/ioapic.c [new file with mode: 0644]
kern/arch/i386/mptables.c [new file with mode: 0644]
kern/arch/i386/mptables.h [new file with mode: 0644]
kern/arch/i386/ne2k.c [new file with mode: 0644]
kern/arch/i386/ne2k.h [new file with mode: 0644]
kern/arch/i386/pci.c [new file with mode: 0644]
kern/arch/i386/pci.h [new file with mode: 0644]
kern/arch/i386/rl8168.c [new file with mode: 0644]
kern/arch/i386/rl8168.h [new file with mode: 0644]
kern/include/mptables.h [deleted file]
kern/include/ne2k.h [deleted file]
kern/include/pci.h [deleted file]
kern/include/rl8168.h [deleted file]
kern/src/Makefrag
kern/src/init.c
kern/src/ioapic.c [deleted file]
kern/src/mptables.c [deleted file]
kern/src/ne2k.c [deleted file]
kern/src/pci.c [deleted file]
kern/src/rl8168.c [deleted file]
kern/src/syscall.c

index 3789053..84aed02 100644 (file)
@@ -25,4 +25,9 @@ KERN_ARCH_SRCFILES := $(KERN_ARCH_SRC_DIR)/entry.S \
                       $(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)/env.c
diff --git a/kern/arch/i386/ioapic.c b/kern/arch/i386/ioapic.c
new file mode 100644 (file)
index 0000000..4dc20fe
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+/** @file
+ * @brief Basic IOAPIC Driver.
+ *
+ * This file is responsible for the initalization of the Intel x58 IOAPIC(s)
+ * Once the IOAPIC is setup, the function ioapic_route_irq() can be used
+ * to route
+ *
+ * See Ch 17.5.26 in Intel X58 Express Chipset Datasheet
+ *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ *
+ * @todo Come up with an impliment a concurrency model for use of the route/unroute functions
+ * @todo Once we begin using logical core ID's for groups, adjust route/unroute to utilize this (adjust high word)
+ * @todo Some notion of a 'initalized' flag we can check to ensure bootup call order.
+ */
+
+
+#include <arch/mmu.h>
+#include <arch/x86.h>
+#include <arch/apic.h>
+#include <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
+  *
+  * @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
+       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.
+  * 
+  * @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);
+
+}
\ No newline at end of file
diff --git a/kern/arch/i386/mptables.c b/kern/arch/i386/mptables.c
new file mode 100644 (file)
index 0000000..518516c
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#include <arch/ioapic.h>
+#include <arch/pci.h>
+#include <arch/mptables.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);
+               
+       }
+}
\ No newline at end of file
diff --git a/kern/arch/i386/mptables.h b/kern/arch/i386/mptables.h
new file mode 100644 (file)
index 0000000..4fb7f0f
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#ifndef ROS_INC_MPTABLES_H
+#define ROS_INC_MPTABLES_H
+
+#include <arch/types.h>
+#include <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 */
diff --git a/kern/arch/i386/ne2k.c b/kern/arch/i386/ne2k.c
new file mode 100644 (file)
index 0000000..b204ada
--- /dev/null
@@ -0,0 +1,164 @@
+#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/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>
+
+/* NE2000 NIC Driver Sketch
+ *
+ * Written by Paul Pearce.
+ *
+ */
+
+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;                         
+}
diff --git a/kern/arch/i386/ne2k.h b/kern/arch/i386/ne2k.h
new file mode 100644 (file)
index 0000000..f64f1c7
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef ROS_INC_NE2K_H
+#define ROS_INC_NE2K_H
+
+#include <arch/types.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 */
diff --git a/kern/arch/i386/pci.c b/kern/arch/i386/pci.c
new file mode 100644 (file)
index 0000000..c6767fc
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+/** @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");
+                       }               
+}
\ No newline at end of file
diff --git a/kern/arch/i386/pci.h b/kern/arch/i386/pci.h
new file mode 100644 (file)
index 0000000..ce35923
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2009 The Regents of the University of California
+ * See LICENSE for details.
+ */
+
+#ifndef ROS_INC_PCI_H
+#define ROS_INC_PCI_H
+
+#define pci_debug(...) // printk(__VA_ARGS__)  
+
+// Macro for creating the address fed to the PCI config register 
+// Several generations away from OSDev inline code.
+#define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
+                                                             (FUNC << 8) | REG  | \
+                                                             ((uint32_t)0x80000000))
+
+// General PCI Magic numbers yanked from OSDev / BSD. Yay magic!
+#define PCI_CONFIG_ADDR     0xCF8
+#define PCI_CONFIG_DATA     0xCFC
+#define INVALID_VENDOR_ID   0xFFFF
+
+#define INVALID_IRQ                    0xFFFF
+#define INVALID_BUS                    0xFFFF
+#define INVALID_LINE           0x0000
+
+#define PCI_IO_MASK         0xFFF8
+#define PCI_MEM_MASK        0xFFFFFFF0
+#define PCI_IRQ_MASK           0xFF
+#define PCI_LINE_MASK          0xFF00
+#define PCI_LINE_SHFT          0x8
+#define PCI_VENDOR_MASK                0xFFFF
+#define PCI_DEVICE_OFFSET      0x10
+#define PCI_IRQ_REG                    0x3c
+
+#define PCI_MAX_BUS                    256
+#define PCI_MAX_DEV                    32
+#define PCI_MAX_FUNC           8
+#define PCI_BAR_IO_MASK                0x1
+#define NUM_IRQS                       256
+
+// Offset used for indexing IRQs. Why isnt this defined elsewhere?
+#define KERNEL_IRQ_OFFSET      32
+
+// Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs, dont check em.
+#define CHECK_BARS                     0
+
+typedef struct PCIIRQENTRY {
+       uint16_t bus; // Bus larger than 255 denotes invalid entry.
+                                 // This is why bus is 16 bits not 8.
+       uint8_t dev;
+       uint8_t func;
+       uint8_t line;
+} pci_irq_entry_t;
+
+typedef struct PCIDEVENTRY {
+       uint16_t dev_id; 
+       uint16_t ven_id;
+} pci_dev_entry_t;
+
+void pci_init();
+
+#endif /* !ROS_INC_PCI_H */
diff --git a/kern/arch/i386/rl8168.c b/kern/arch/i386/rl8168.c
new file mode 100644 (file)
index 0000000..69cd044
--- /dev/null
@@ -0,0 +1,716 @@
+#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>
+
+/* 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!
+ */
+
+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
+const 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;     
+}
diff --git a/kern/arch/i386/rl8168.h b/kern/arch/i386/rl8168.h
new file mode 100644 (file)
index 0000000..a0447ac
--- /dev/null
@@ -0,0 +1,149 @@
+#ifndef ROS_INC_REALTEK_H
+#define ROS_INC_REALTEK_H
+
+#include <arch/types.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.
+
+const 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 */
diff --git a/kern/include/mptables.h b/kern/include/mptables.h
deleted file mode 100644 (file)
index 4fb7f0f..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-#ifndef ROS_INC_MPTABLES_H
-#define ROS_INC_MPTABLES_H
-
-#include <arch/types.h>
-#include <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 */
diff --git a/kern/include/ne2k.h b/kern/include/ne2k.h
deleted file mode 100644 (file)
index f64f1c7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef ROS_INC_NE2K_H
-#define ROS_INC_NE2K_H
-
-#include <arch/types.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 */
diff --git a/kern/include/pci.h b/kern/include/pci.h
deleted file mode 100644 (file)
index ce35923..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-#ifndef ROS_INC_PCI_H
-#define ROS_INC_PCI_H
-
-#define pci_debug(...) // printk(__VA_ARGS__)  
-
-// Macro for creating the address fed to the PCI config register 
-// Several generations away from OSDev inline code.
-#define MK_CONFIG_ADDR(BUS, DEV, FUNC, REG) (unsigned long)( (BUS << 16) | (DEV << 11) | \
-                                                             (FUNC << 8) | REG  | \
-                                                             ((uint32_t)0x80000000))
-
-// General PCI Magic numbers yanked from OSDev / BSD. Yay magic!
-#define PCI_CONFIG_ADDR     0xCF8
-#define PCI_CONFIG_DATA     0xCFC
-#define INVALID_VENDOR_ID   0xFFFF
-
-#define INVALID_IRQ                    0xFFFF
-#define INVALID_BUS                    0xFFFF
-#define INVALID_LINE           0x0000
-
-#define PCI_IO_MASK         0xFFF8
-#define PCI_MEM_MASK        0xFFFFFFF0
-#define PCI_IRQ_MASK           0xFF
-#define PCI_LINE_MASK          0xFF00
-#define PCI_LINE_SHFT          0x8
-#define PCI_VENDOR_MASK                0xFFFF
-#define PCI_DEVICE_OFFSET      0x10
-#define PCI_IRQ_REG                    0x3c
-
-#define PCI_MAX_BUS                    256
-#define PCI_MAX_DEV                    32
-#define PCI_MAX_FUNC           8
-#define PCI_BAR_IO_MASK                0x1
-#define NUM_IRQS                       256
-
-// Offset used for indexing IRQs. Why isnt this defined elsewhere?
-#define KERNEL_IRQ_OFFSET      32
-
-// Run the PCI Code to loop over the PCI BARs. For now we don't use the BARs, dont check em.
-#define CHECK_BARS                     0
-
-typedef struct PCIIRQENTRY {
-       uint16_t bus; // Bus larger than 255 denotes invalid entry.
-                                 // This is why bus is 16 bits not 8.
-       uint8_t dev;
-       uint8_t func;
-       uint8_t line;
-} pci_irq_entry_t;
-
-typedef struct PCIDEVENTRY {
-       uint16_t dev_id; 
-       uint16_t ven_id;
-} pci_dev_entry_t;
-
-void pci_init();
-
-#endif /* !ROS_INC_PCI_H */
diff --git a/kern/include/rl8168.h b/kern/include/rl8168.h
deleted file mode 100644 (file)
index a0447ac..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef ROS_INC_REALTEK_H
-#define ROS_INC_REALTEK_H
-
-#include <arch/types.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.
-
-const 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 */
index bbd8884..a556e52 100644 (file)
@@ -20,9 +20,6 @@ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
                  $(KERN_SRC_DIR)/sched.c \
                  $(KERN_SRC_DIR)/kdebug.c \
                  $(KERN_SRC_DIR)/apic.c \
-                 $(KERN_SRC_DIR)/mptables.c \
-                 $(KERN_SRC_DIR)/pci.c \
-                 $(KERN_SRC_DIR)/ioapic.c \
                  $(KERN_SRC_DIR)/printfmt.c \
                  $(KERN_SRC_DIR)/smp.c \
                  $(KERN_SRC_DIR)/multiboot.c \
@@ -40,8 +37,6 @@ KERN_SRCFILES := $(KERN_ARCH_SRCFILES) \
                  $(KERN_SRC_DIR)/kfs.c \
                  $(KERN_SRC_DIR)/process.c \
                  $(KERN_SRC_DIR)/kmalloc.c \
-                 $(KERN_SRC_DIR)/rl8168.c \
-                 $(KERN_SRC_DIR)/ne2k.c \
                  $(KERN_SRC_DIR)/schedule.c \
                  $(KERN_SRC_DIR)/testing.c
 
index 2ea8098..5aff619 100644 (file)
 #include <kclock.h>
 #include <manager.h>
 
-#include <rl8168.h>
-#include <ne2k.h>
-#include <mptables.h>
-#include <pci.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)
@@ -61,14 +61,21 @@ void kernel_init(multiboot_info_t *mboot_info)
        idt_init();
        sysenter_init();
        timer_init();
+       
+       #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__
        rl8168_init();          
        ne2k_init();
+       #endif // __i386__
 
        manager();
 }
diff --git a/kern/src/ioapic.c b/kern/src/ioapic.c
deleted file mode 100644 (file)
index b600a21..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-/** @file
- * @brief Basic IOAPIC Driver.
- *
- * This file is responsible for the initalization of the Intel x58 IOAPIC(s)
- * Once the IOAPIC is setup, the function ioapic_route_irq() can be used
- * to route
- *
- * See Ch 17.5.26 in Intel X58 Express Chipset Datasheet
- *
- * @author Paul Pearce <pearce@eecs.berkeley.edu>
- *
- * @todo Come up with an impliment a concurrency model for use of the route/unroute functions
- * @todo Once we begin using logical core ID's for groups, adjust route/unroute to utilize this (adjust high word)
- * @todo Some notion of a 'initalized' flag we can check to ensure bootup call order.
- */
-
-
-#include <arch/mmu.h>
-#include <arch/x86.h>
-#include <arch/apic.h>
-#include <mptables.h>
-#include <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
-  *
-  * @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
-       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.
-  * 
-  * @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);
-
-}
\ No newline at end of file
diff --git a/kern/src/mptables.c b/kern/src/mptables.c
deleted file mode 100644 (file)
index 6218148..0000000
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-#include <arch/ioapic.h>
-#include <pci.h>
-#include <stdio.h>
-#include <string.h>
-#include <kmalloc.h>
-#include <arch/x86.h>
-
-#include <mptables.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);
-               
-       }
-}
\ No newline at end of file
diff --git a/kern/src/ne2k.c b/kern/src/ne2k.c
deleted file mode 100644 (file)
index 06eeb5f..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-#include <arch/mmu.h>
-#include <arch/x86.h>
-#include <arch/smp.h>
-#include <arch/apic.h>
-
-#include <ros/memlayout.h>
-
-#include <atomic.h>
-#include <stdio.h>
-#include <string.h>
-#include <trap.h>
-#include <kmalloc.h>
-
-#include <pmap.h>
-#include <pci.h>
-#include <ne2k.h>
-#include <timing.h>
-
-/* NE2000 NIC Driver Sketch
- *
- * Written by Paul Pearce.
- *
- */
-
-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;                         
-}
diff --git a/kern/src/pci.c b/kern/src/pci.c
deleted file mode 100644 (file)
index 7f33ccd..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2009 The Regents of the University of California
- * See LICENSE for details.
- */
-
-/** @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 <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");
-                       }               
-}
\ No newline at end of file
diff --git a/kern/src/rl8168.c b/kern/src/rl8168.c
deleted file mode 100644 (file)
index ce452ac..0000000
+++ /dev/null
@@ -1,716 +0,0 @@
-#ifdef __DEPUTY__
-#pragma nodeputy
-#endif
-
-#include <arch/mmu.h>
-#include <arch/x86.h>
-#include <arch/smp.h>
-#include <arch/apic.h>
-
-#include <ros/memlayout.h>
-
-#include <atomic.h>
-#include <stdio.h>
-#include <string.h>
-#include <rl8168.h>
-#include <trap.h>
-#include <kmalloc.h>
-
-#include <pmap.h>
-#include <pci.h>
-
-/* 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!
- */
-
-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
-const 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 0adc939..569bd71 100644 (file)
@@ -12,7 +12,7 @@
 #include <ros/timer.h>
 #include <ros/error.h>
 
-#include <rl8168.h>
+#include <arch/rl8168.h>
 #include <string.h>
 #include <assert.h>
 #include <process.h>