summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--asm/asm_int.h1
-rw-r--r--asm/asm_int.s2
-rw-r--r--driver/e1000.c427
-rw-r--r--driver/e1000.h5
-rw-r--r--driver/keyboard.c9
-rw-r--r--driver/pci.c40
-rw-r--r--driver/pci.h1
-rw-r--r--kernel/acpi.c4
-rw-r--r--kernel/apic.c19
-rw-r--r--kernel/interrupts.c9
-rw-r--r--kernel/interrupts.h1
-rw-r--r--kernel/kernel.c13
-rw-r--r--kernel/kernel.h2
-rw-r--r--kernel/scheduler.c1
-rw-r--r--kernel/vmem.c7
-rw-r--r--kernel/vmem.h2
17 files changed, 522 insertions, 28 deletions
diff --git a/Makefile b/Makefile
index f852009..78696d5 100644
--- a/Makefile
+++ b/Makefile
@@ -189,7 +189,7 @@ run-qemu-debug: all
# qemu -enable-kvm -s -singlestep disk.img
# qemu-system-i386 -enable-kvm -s -S -kernel foolos.img -smp 4 -initrd userspace/ext2.img
echo XDOTOOL HACK...&& sleep 0.2 && xdotool search --name "QEMU" windowsize 100 100 && echo XDOTOOL HACK END. &
- qemu-system-i386 -s -S $(FOOLOS_ISO) -smp 4 -serial stdio #-enable-kvm -smp 1
+ qemu-system-i386 -s -S $(FOOLOS_ISO) -smp 4 -serial stdio #-enable-kvm -smp 1
monitor:
echo XDOTOOL HACK...&& sleep 0.2 && xdotool search --name "QEMU" windowsize 100 100 && echo XDOTOOL HACK END. &
qemu-system-i386 -s -S $(FOOLOS_ISO) -smp 4 -monitor stdio # -serial stdio #-enable-kvm -smp 1
@@ -250,3 +250,8 @@ doxygen: clean
## headers ##
list_headers:
find asm/ driver/ fs/ kernel/ lib/ -iname *.h -exec basename {} \; | sort | uniq -c
+
+#qemu-system-i386 -netdev tap,id=mynet0,ifname=tap0,script=no,downscript=no -enable-kvm fool-os-i386.iso -smp 4 -serial stdio
+#sudo tunctl -t tap0 -u miguel
+qemu-22:
+ qemu-system-i386 -s -enable-kvm fool-os-i386.iso -smp 4 -serial stdio -net user,hostfwd=tcp::10022-:22 -net nic -net dump,file=./netfool
diff --git a/asm/asm_int.h b/asm/asm_int.h
index 2940ab4..d28a321 100644
--- a/asm/asm_int.h
+++ b/asm/asm_int.h
@@ -29,6 +29,7 @@ void int140(); // scheduler
void int144(); // scheduler
void int145(); // scheduler
void int146(); // scheduler
+void int147(); // scheduler
void int200(); // apic timer
void int170(); // smp scheduler
void int255(); // unhandled
diff --git a/asm/asm_int.s b/asm/asm_int.s
index 8d5ac9a..9ea0d4b 100644
--- a/asm/asm_int.s
+++ b/asm/asm_int.s
@@ -23,6 +23,7 @@
.global int144
.global int145
.global int146
+.global int147
.global int170
.global int255
@@ -215,6 +216,7 @@ int140: intx ack0 $140 interrupt_handler
int144: intx ack0 $144 interrupt_handler
int145: intx ack0 $145 interrupt_handler
int146: intx ack0 $146 interrupt_handler
+int147: intx ack0 $147 interrupt_handler
int255: intx ack0 $255 interrupt_handler
int200: intx ack0 $200 interrupt_handler
diff --git a/driver/e1000.c b/driver/e1000.c
index 99194be..21d3924 100644
--- a/driver/e1000.c
+++ b/driver/e1000.c
@@ -1,4 +1,429 @@
+//https://github.com/blanham/ChickenOS/blob/master/src/device/net/e1000.c
+//https://wiki.osdev.org/Intel_Ethernet_i217
+#include <stdint.h>
+#include "log.h"
+#include "e1000.h"
+#include "kmalloc.h"
-void init_e1000()
+#define INTEL_VEND 0x8086 // Vendor ID for Intel
+#define E1000_DEV 0x100E // Device ID for the e1000 Qemu, Bochs, and VirtualBox emmulated NICs
+#define E1000_I217 0x153A // Device ID for Intel I217
+#define E1000_82577LM 0x10EA // Device ID for Intel 82577LM
+
+
+// I have gathered those from different Hobby online operating systems instead of getting them one by one from the manual
+
+#define REG_CTRL 0x0000
+#define REG_STATUS 0x0008
+#define REG_EEPROM 0x0014
+#define REG_CTRL_EXT 0x0018
+#define REG_IMASK 0x00D0
+#define REG_RCTRL 0x0100
+#define REG_RXDESCLO 0x2800
+#define REG_RXDESCHI 0x2804
+#define REG_RXDESCLEN 0x2808
+#define REG_RXDESCHEAD 0x2810
+#define REG_RXDESCTAIL 0x2818
+
+#define REG_TCTRL 0x0400
+#define REG_TXDESCLO 0x3800
+#define REG_TXDESCHI 0x3804
+#define REG_TXDESCLEN 0x3808
+#define REG_TXDESCHEAD 0x3810
+#define REG_TXDESCTAIL 0x3818
+
+
+#define REG_RDTR 0x2820 // RX Delay Timer Register
+#define REG_RXDCTL 0x3828 // RX Descriptor Control
+#define REG_RADV 0x282C // RX Int. Absolute Delay Timer
+#define REG_RSRPD 0x2C00 // RX Small Packet Detect Interrupt
+
+
+
+#define REG_TIPG 0x0410 // Transmit Inter Packet Gap
+#define ECTRL_SLU 0x40 //set link up
+
+
+#define RCTL_EN (1 << 1) // Receiver Enable
+#define RCTL_SBP (1 << 2) // Store Bad Packets
+#define RCTL_UPE (1 << 3) // Unicast Promiscuous Enabled
+#define RCTL_MPE (1 << 4) // Multicast Promiscuous Enabled
+#define RCTL_LPE (1 << 5) // Long Packet Reception Enable
+#define RCTL_LBM_NONE (0 << 6) // No Loopback
+#define RCTL_LBM_PHY (3 << 6) // PHY or external SerDesc loopback
+#define RTCL_RDMTS_HALF (0 << 8) // Free Buffer Threshold is 1/2 of RDLEN
+#define RTCL_RDMTS_QUARTER (1 << 8) // Free Buffer Threshold is 1/4 of RDLEN
+#define RTCL_RDMTS_EIGHTH (2 << 8) // Free Buffer Threshold is 1/8 of RDLEN
+#define RCTL_MO_36 (0 << 12) // Multicast Offset - bits 47:36
+#define RCTL_MO_35 (1 << 12) // Multicast Offset - bits 46:35
+#define RCTL_MO_34 (2 << 12) // Multicast Offset - bits 45:34
+#define RCTL_MO_32 (3 << 12) // Multicast Offset - bits 43:32
+#define RCTL_BAM (1 << 15) // Broadcast Accept Mode
+#define RCTL_VFE (1 << 18) // VLAN Filter Enable
+#define RCTL_CFIEN (1 << 19) // Canonical Form Indicator Enable
+#define RCTL_CFI (1 << 20) // Canonical Form Indicator Bit Value
+#define RCTL_DPF (1 << 22) // Discard Pause Frames
+#define RCTL_PMCF (1 << 23) // Pass MAC Control Frames
+#define RCTL_SECRC (1 << 26) // Strip Ethernet CRC
+
+// Buffer Sizes
+#define RCTL_BSIZE_256 (3 << 16)
+#define RCTL_BSIZE_512 (2 << 16)
+#define RCTL_BSIZE_1024 (1 << 16)
+#define RCTL_BSIZE_2048 (0 << 16)
+#define RCTL_BSIZE_4096 ((3 << 16) | (1 << 25))
+#define RCTL_BSIZE_8192 ((2 << 16) | (1 << 25))
+#define RCTL_BSIZE_16384 ((1 << 16) | (1 << 25))
+
+
+// Transmit Command
+
+#define CMD_EOP (1 << 0) // End of Packet
+#define CMD_IFCS (1 << 1) // Insert FCS
+#define CMD_IC (1 << 2) // Insert Checksum
+#define CMD_RS (1 << 3) // Report Status
+#define CMD_RPS (1 << 4) // Report Packet Sent
+#define CMD_VLE (1 << 6) // VLAN Packet Enable
+#define CMD_IDE (1 << 7) // Interrupt Delay Enable
+
+
+// TCTL Register
+
+#define TCTL_EN (1 << 1) // Transmit Enable
+#define TCTL_PSP (1 << 3) // Pad Short Packets
+#define TCTL_CT_SHIFT 4 // Collision Threshold
+#define TCTL_COLD_SHIFT 12 // Collision Distance
+#define TCTL_SWXOFF (1 << 22) // Software XOFF Transmission
+#define TCTL_RTLC (1 << 24) // Re-transmit on Late Collision
+
+#define TSTA_DD (1 << 0) // Descriptor Done
+#define TSTA_EC (1 << 1) // Excess Collisions
+#define TSTA_LC (1 << 2) // Late Collision
+#define LSTA_TU (1 << 3) // Transmit Underrun
+
+// buffers
+#define E1000_NUM_RX_DESC 32
+#define E1000_NUM_TX_DESC 8
+
+struct e1000_rx_desc {
+ volatile uint64_t addr;
+ volatile uint16_t length;
+ volatile uint16_t checksum;
+ volatile uint8_t status;
+ volatile uint8_t errors;
+ volatile uint16_t special;
+} __attribute__((packed));
+
+struct e1000_tx_desc {
+ volatile uint64_t addr;
+ volatile uint16_t length;
+ volatile uint8_t cso;
+ volatile uint8_t cmd;
+ volatile uint8_t status;
+ volatile uint8_t css;
+ volatile uint16_t special;
+} __attribute__((packed));
+
+ uint8_t bar_type; // Type of BOR0
+ uint16_t io_base; // IO Base Address
+ uint32_t mem_base; // MMIO Base Address
+ bool eerprom_exists; // A flag indicating if eeprom exists
+ uint8_t mac [6]; // A buffer for storing the mack address
+ struct e1000_rx_desc *rx_descs[E1000_NUM_RX_DESC]; // Receive Descriptor Buffers
+ struct e1000_tx_desc *tx_descs[E1000_NUM_TX_DESC]; // Transmit Descriptor Buffers
+ uint16_t rx_cur; // Current Receive Descriptor Buffer
+ uint16_t tx_cur; // Current Transmit Descriptor Buffer
+
+
+
+
+void writeCommand( uint16_t p_address, uint32_t p_value)
+{
+// if ( bar_type == 0 )
+// {
+ (*((volatile uint32_t*)(mem_base+p_address)))=(p_value);
+// }
+// else
+// {
+ //outportl(io_base, p_address);
+ //outportl(io_base + 4, p_value);
+// }
+}
+
+uint32_t readCommand( uint16_t p_address)
+{
+// if ( bar_type == 0 )
+// {
+ return *((volatile uint32_t*)(mem_base+p_address));
+// }
+// else
+// {
+ //outportl(io_base, p_address);
+ //return inportl(io_base + 4);
+// }
+}
+
+bool detectEEProm()
+{
+ uint32_t val = 0;
+ writeCommand(REG_EEPROM, 0x1);
+
+ for(int i = 0; i < 1000 && ! eerprom_exists; i++)
+ {
+ val = readCommand( REG_EEPROM);
+ if(val & 0x10)
+ eerprom_exists = true;
+ else
+ eerprom_exists = false;
+ }
+
+ klog("eeprom %s",eerprom_exists?"YES":"NO");
+ return eerprom_exists;
+}
+
+uint32_t eepromRead( uint8_t addr)
+{
+ uint16_t data = 0;
+ uint32_t tmp = 0;
+ if ( eerprom_exists)
+ {
+ writeCommand( REG_EEPROM, (1) | ((uint32_t)(addr) << 8) );
+ while( !((tmp = readCommand(REG_EEPROM)) & (1 << 4)) );
+ }
+ else
+ {
+ writeCommand( REG_EEPROM, (1) | ((uint32_t)(addr) << 2) );
+ while( !((tmp = readCommand(REG_EEPROM)) & (1 << 1)) );
+ }
+ data = (uint16_t)((tmp >> 16) & 0xFFFF);
+ return data;
+}
+
+bool readMACAddress()
+{
+ if ( eerprom_exists)
+ {
+ uint32_t temp;
+ temp = eepromRead( 0);
+ mac[0] = temp &0xff;
+ mac[1] = temp >> 8;
+ temp = eepromRead( 1);
+ mac[2] = temp &0xff;
+ mac[3] = temp >> 8;
+ temp = eepromRead( 2);
+ mac[4] = temp &0xff;
+ mac[5] = temp >> 8;
+ }
+ else
+ {
+ uint8_t * mem_base_mac_8 = (uint8_t *) (mem_base+0x5400);
+ uint32_t * mem_base_mac_32 = (uint32_t *) (mem_base+0x5400);
+ if ( mem_base_mac_32[0] != 0 )
+ {
+ for(int i = 0; i < 6; i++)
+ {
+ mac[i] = mem_base_mac_8[i];
+ }
+ }
+ else return false;
+ }
+ return true;
+}
+
+
+void rxinit()
+{
+ uint8_t * ptr;
+ struct e1000_rx_desc *descs;
+
+ // Allocate buffer for receive descriptors. For simplicity, in my case khmalloc returns a virtual address that is identical to it physical mapped address.
+ // In your case you should handle virtual and physical addresses as the addresses passed to the NIC should be physical onesk
+
+ uint32_t alloc_pages=1+(sizeof(struct e1000_rx_desc)*E1000_NUM_RX_DESC + 16)/4096;
+
+ ptr = kballoc(alloc_pages);
+
+ descs = (struct e1000_rx_desc *)ptr;
+ for(int i = 0; i < E1000_NUM_RX_DESC; i++)
+ {
+ rx_descs[i] = (struct e1000_rx_desc *)((uint8_t *)descs + i*16);
+ rx_descs[i]->addr = kballoc(3); // what a waste :( TODO!
+ rx_descs[i]->status = 0;
+ }
+
+ /*
+ writeCommand(REG_TXDESCLO, (uint32_t)((uint64_t)ptr >> 32) );
+ writeCommand(REG_TXDESCHI, (uint32_t)((uint64_t)ptr & 0xFFFFFFFF));
+
+ writeCommand(REG_TXDESCLO, (uint32_t)(0) );
+ writeCommand(REG_TXDESCHI, (uint32_t)(ptr));
+ */
+
+ writeCommand(REG_RXDESCLO, ptr);
+ writeCommand(REG_RXDESCHI, 0);
+
+ writeCommand(REG_RXDESCLEN, E1000_NUM_RX_DESC * 16);
+
+ writeCommand(REG_RXDESCHEAD, 0);
+ writeCommand(REG_RXDESCTAIL, E1000_NUM_RX_DESC-1);
+ rx_cur = 0;
+
+ //enable receiving
+ uint32_t flags = (2 << 16) | (1 << 25) | (1 << 26) | (1 << 15) | (1 << 5) | (0 << 8) | (0 << 4) | (0 << 3) | ( 1 << 2);
+ writeCommand(REG_RCTRL, flags);
+ //writeCommand(REG_RCTRL, RCTL_EN| RCTL_SBP| RCTL_UPE | RCTL_MPE | RCTL_LBM_NONE | RTCL_RDMTS_HALF | RCTL_BAM | RCTL_SECRC | RCTL_BSIZE_2048);
+
+}
+
+void txinit()
+{
+ uint8_t * ptr;
+ struct e1000_tx_desc *descs;
+
+ // Allocate buffer for receive descriptors. For simplicity, in my case khmalloc returns a virtual address that is identical to it physical mapped address.
+ // In your case you should handle virtual and physical addresses as the addresses passed to the NIC should be physical ones
+ //
+ uint32_t alloc_pages=1+(sizeof(struct e1000_tx_desc)*E1000_NUM_TX_DESC + 16)/4096;
+
+ ptr = kballoc(alloc_pages);
+ descs = (struct e1000_tx_desc *)ptr;
+
+ for(int i = 0; i < E1000_NUM_TX_DESC; i++)
+ {
+ tx_descs[i] = (struct e1000_tx_desc *)((uint8_t*)descs + i*16);
+ tx_descs[i]->addr = 0;
+ tx_descs[i]->cmd = 0;
+ tx_descs[i]->status = TSTA_DD;
+ }
+
+ writeCommand(REG_TXDESCHI, (uint32_t)(0) );
+ writeCommand(REG_TXDESCLO, (uint32_t)(ptr));
+
+ //now setup total length of descriptors
+ writeCommand(REG_TXDESCLEN, E1000_NUM_TX_DESC * 16);
+
+ //setup numbers
+ writeCommand( REG_TXDESCHEAD, 0);
+ writeCommand( REG_TXDESCTAIL, 0);
+ tx_cur = 0;
+ writeCommand(REG_TCTRL, TCTL_EN
+ | TCTL_PSP
+ | (15 << TCTL_CT_SHIFT)
+ | (64 << TCTL_COLD_SHIFT)
+ | TCTL_RTLC);
+
+ // This line of code overrides the one before it but I left both to
+ // highlight that the previous one works with e1000 cards, but for the
+ // e1000e cards you should set the TCTRL register as follows. For detailed
+ // description of each bit, please refer to the Intel Manual. In the case
+ // of I217 and 82577LM packets will not be sent if the TCTRL is not
+ // configured using the following bits.
+
+ // writeCommand(REG_TCTRL, 0b0110000000000111111000011111010);
+ // writeCommand(REG_TIPG, 0x0060200A);
+
+}
+
+void e1000_handleReceive()
+{
+ uint16_t old_cur;
+ bool got_packet = false;
+
+ while((rx_descs[rx_cur]->status & 0x1))
+ {
+ got_packet = true;
+ klog("GOT FIRST PACKET WOOOOW");
+ uint8_t *buf = (uint8_t *)(uint32_t)rx_descs[rx_cur]->addr;
+ uint16_t len = rx_descs[rx_cur]->length;
+
+ // Here you should inject the received packet into your network stack
+
+ rx_descs[rx_cur]->status = 0;
+ old_cur = rx_cur;
+ rx_cur = (rx_cur + 1) % E1000_NUM_RX_DESC;
+ writeCommand(REG_RXDESCTAIL, old_cur );
+ }
+}
+
+int e1000_sendPacket(const void * p_data, uint16_t p_len)
+{
+ tx_descs[tx_cur]->addr = p_data;
+ tx_descs[tx_cur]->length = p_len;
+ tx_descs[tx_cur]->cmd = CMD_EOP | CMD_IFCS | CMD_RS | CMD_RPS;
+ tx_descs[tx_cur]->status = 0;
+ uint8_t old_cur = tx_cur;
+ tx_cur = (tx_cur + 1) % E1000_NUM_TX_DESC;
+ writeCommand(REG_TXDESCTAIL, tx_cur);
+ while(!(tx_descs[old_cur]->status & 0xff));
+ return 0;
+}
+
+
+void enableInterrupt()
+{
+ writeCommand(REG_IMASK ,0x1F6DC);
+ writeCommand(REG_IMASK ,0xff & ~4);
+ readCommand(0xc0);
+}
+
+void e1000_linkup()
+{
+ uint32_t val;
+ val = readCommand(REG_CTRL);
+ writeCommand(REG_CTRL, val | ECTRL_SLU);
+}
+
+
+bool e1000_init(uint32_t base)
{
+ klog("init E1000");
+ if(base!=0) mem_base=base;
+ detectEEProm();
+ if (! readMACAddress()) return false;
+
+ klog("mac : %02x:%02x:%02x:%02x:%02x:%02x",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],mac[6]);
+
+ e1000_linkup();
+
+ for(int i = 0; i < 0x80; i++)writeCommand(0x5200 + i*4, 0);
+
+ enableInterrupt();
+
+ rxinit();
+ txinit();
+
+ klog("E1000 initialized");
+
+ return true;
+}
+void e1000_irq (int irq)
+{
+// if ( p_interruptContext->getInteruptNumber() == pciConfigHeader->getIntLine()+IRQ0)
+ // {
+ /* This might be needed here if your handler doesn't clear interrupts
+ * from each device and must be done before EOI if using the PIC.
+ Without this, the card will spam interrupts as the int-line will
+ stay high. */
+
+ writeCommand(REG_IMASK, 0x1);
+ enableInterrupt();
+
+ uint32_t status = readCommand(0xc0);
+ klog("e1000_irq status=%d",status);
+
+ if(status & 0x04)
+ {
+ e1000_linkup();
+// startLink();
+ }
+ else if(status & 0x10)
+ {
+ // good threshold
+ }
+ else if(status & 0x80)
+ {
+ e1000_handleReceive();
+ }
+
+ //}
}
diff --git a/driver/e1000.h b/driver/e1000.h
index 5413fe1..8534b6d 100644
--- a/driver/e1000.h
+++ b/driver/e1000.h
@@ -1 +1,4 @@
-void init_e1000();
+#include <stdint.h>
+bool e1000_init(uint32_t base);
+int e1000_sendPacket(const void * p_data, uint16_t p_len);
+void e1000_irq (int irq);
diff --git a/driver/keyboard.c b/driver/keyboard.c
index ac2028c..2352532 100644
--- a/driver/keyboard.c
+++ b/driver/keyboard.c
@@ -2,6 +2,7 @@
#include "keyboard.h"
#include "syscalls.h"
#include "log.h"
+#include "e1000.h"
#include <stdbool.h>
@@ -15,7 +16,13 @@ static char num_syms[]={')','!','@','#','$','%','^','&','*','('};
static void put(uint8_t c)
{
- //syscall_write(kb_stream,(char *)&c,1);
+ uint16_t dat[]={
+ 0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x52,0x5,0x50a,0x00,0x02,0x02,0x08,0x06,0x00,
+ 0x01,0x08,0x00,0x06,0x04,0x00,0x01,0x52,0x5,0x50a,0x00,0x02,0x02,0x0a,0x00,0x02};
+
+ if(c=='y')e1000_sendPacket(dat,32);
+ if(c=='x')e1000_init(0);
+ if(c=='i')e1000_irq(11);
syscall_generic(SYSCALL_WRITE,kb_stream, (char *)&c , 1, 0);
}
diff --git a/driver/pci.c b/driver/pci.c
index 1e2f660..b5e5791 100644
--- a/driver/pci.c
+++ b/driver/pci.c
@@ -1,5 +1,3 @@
-
-
#include "kernel/kernel.h"
#include "log.h"
#include "asm_x86.h"
@@ -8,6 +6,17 @@
#define PCI_CONFIG_DATA 0xCFC
#define PCI_CONFIG_ADDRESS 0xCF8
+static uint32_t e1000_addr;
+
+static char *get_class(uint8_t v)
+{
+ switch(v)
+ {
+ case 0x00: return "Unclassified";
+ }
+ return "Unknown";
+}
+
void pciConfigSet (uint8_t bus, uint8_t slot,
uint8_t func, uint8_t offset, uint32_t data)
{
@@ -47,7 +56,7 @@
return (tmp);
}
-void test_bar(uint8_t bus, uint8_t slot, uint8_t offset)
+uint32_t test_bar(uint8_t bus, uint8_t slot, uint8_t offset)
{
uint16_t bar_low=pciConfigReadWord(bus,slot,0,offset);
@@ -64,36 +73,44 @@ void test_bar(uint8_t bus, uint8_t slot, uint8_t offset)
// restore original values
pciConfigSet(bus,slot,0,offset,(bar_high<<16)+bar_low);
-
klog("%s bar: (0x%x 0x%x) size: 0x%x" ,bar_low&1?"i/o":"mem",bar_high, bar_low, size);
+ if((bar_low&1)==0) // mem space
+ {
+ klog("type=0x%x,base_addr=0x%08X",0b110&bar_low,(bar_low+(bar_high<<16))&0xFFFFFFF0);
+ }
+ return (bar_low+(bar_high<<16))&0xFFFFFFF0;
}
uint16_t pciCheck(uint8_t bus, uint8_t slot)
{
- uint16_t vendor, device;
+ uint16_t vendor, device, irq;
/* try and read the first configuration register. Since there are no */
/* vendors that == 0xFFFF, it must be a non-existent device. */
if ((vendor = pciConfigReadWord(bus,slot,0,0)) != 0xFFFF)
{
device = pciConfigReadWord(bus,slot,0,2);
+
+ //pciConfigSet(bus,slot,0,0x3c+2,0x3);
+ irq = pciConfigReadWord(bus,slot,0,0x3c);
+ uint8_t header = pciConfigReadWord(bus,slot,0,0xd)&0xff;
+
klog("[%d,%d]: vendor: 0x%x / device: 0x%x",bus,slot,vendor,device);
+ klog("header_typ=%x, %d,pin=%d , irq=%d",header,irq,irq&0xFf00,irq&0xFf);
+
// check for: E1000 (82540EM). PCI Ethernet Controller
if(vendor==0x8086&&device==0x100e)
{
// uint16_t irq=pciConfigReadWord(bus,slot,0,0x3C);
// uint16_t irq2=pciConfigReadWord(bus,slot,0,0x3E);
//
- init_e1000();
- test_bar(bus,slot,0x10);
+ e1000_addr=test_bar(bus,slot,0x10);
test_bar(bus,slot,0x14);
- test_bar(bus,slot,0x18);
-
// scr_put_hex(irq);
// scr_put_hex(irq2);
// scr_put_string_nl(";");
@@ -110,7 +127,7 @@ uint16_t pciCheck(uint8_t bus, uint8_t slot)
}
-void pci_init()
+uint32_t pci_init()
{
klog("scanning bus");
// todo: recurse on pci to pci bridges!
@@ -124,11 +141,10 @@ void pci_init()
{
for(device = 0; device < 32; device++)
{
-
pciCheck(bus, device);
-
}
}
+ return e1000_addr;
}
diff --git a/driver/pci.h b/driver/pci.h
index f02c5c7..1357710 100644
--- a/driver/pci.h
+++ b/driver/pci.h
@@ -1 +1,2 @@
+uint32_t pci_init();
//stub
diff --git a/kernel/acpi.c b/kernel/acpi.c
index b6370c3..2ab889b 100644
--- a/kernel/acpi.c
+++ b/kernel/acpi.c
@@ -79,7 +79,9 @@ static uint8_t *apci_get_next_entry(uint8_t *addr,acpi_information *procdata)
fixme("support multiple IO Apics and consider interrupt source overrides during irq config!");
}
else if(*addr==2){
- klog("Type 2: Interrupt Source Override (bus src=%d) (irq src=%d) (global=%d) (flags=%d)",addr[2],addr[3],*((uint32_t*)&addr[4]),*((uint16_t*)&addr[8]));
+ uint16_t flags=*((uint16_t*)&addr[8]);
+ klog("Type 2: Interrupt Source Override (bus src=%d) (irq src=%d) (global=%d) (flags=%d)",addr[2],addr[3],*((uint32_t*)&addr[4]),flags);
+ klog(" Active %s, %s triggered", flags&2?"low":"high", flags&8?"level":"edge");
}
else if(*addr==4){
klog("Type 4: Non-maskable interrupts (proc id=%d) (flags=%d) (LINT#=%d)",addr[2],*((uint16_t*)&addr[3]),addr[5]);
diff --git a/kernel/apic.c b/kernel/apic.c
index 3ec10b9..f78a03a 100644
--- a/kernel/apic.c
+++ b/kernel/apic.c
@@ -146,15 +146,20 @@ void ioapic_config()
{
fixme("use acpi info to setup IOAPIC");
// setup IO APIC
- // PIT irq 00 -> 02 flags 0 -> 0x90
- // kb irq 01 -> 01 flags ? -> 0x91
- // mouse irq 12 -> 12 flags ? -> 0x92
-// ioapic_config_entry(2,0x90|0x2000,0x3<<24); // egde trigger on falling
+ // DEVICE SOURCE OVERRIDE FLAGS FOOL-OS-INTERRUPT
+ // PIT 00 -> 02 0 high/edge 0x90 / 144
+ // kb 01 -> 01 ? 0x91 / 145
+ // mouse 12 -> 12 ? 0x92 / 146
+ // e1000 11 -> 11 13? high/level 0x93 / 147
+// ioapic_config_entry(3,0x90|0x2000,0x3<<24); // egde trigger on falling
// ioapic_config_entry(2,0x90|0x8000,0x3<<24); // level trigger on high
// ioapic_config_entry(2,0x90|0xa000,0x3<<24); // level trigger on low
- ioapic_config_entry(2,0x90,0x0);
- ioapic_config_entry(1,0x91,0x0);
- ioapic_config_entry(12,0x92,0x0);
+
+// CPU
+ ioapic_config_entry(2, 0x90, 0x0<<24); // pit
+ ioapic_config_entry(1, 0x91, 0x0<<24); // kb
+ ioapic_config_entry(12, 0x92, 0x0<<24); // mouse
+ ioapic_config_entry(11, 0x93|0x8000, 0x0<<24); // e1000 (level trigger on high)
}
/** startup other cpus*/
diff --git a/kernel/interrupts.c b/kernel/interrupts.c
index 94eda2e..10537f7 100644
--- a/kernel/interrupts.c
+++ b/kernel/interrupts.c
@@ -1,5 +1,6 @@
#include "kernel.h"
#include "log.h"
+#include "e1000.h"
#include "asm_int.h"
#include "asm_pit.h"
#include "driver/mouse.h"
@@ -77,6 +78,11 @@ uint32_t interrupt_handler(uint32_t esp, uint32_t irq)
task_syscall(stack[11],stack[8],stack[10],stack[9]); //eax,ebx,ecx,edx
break;
+ case INTERRUPT_E1000:
+ klog("e1");
+ e1000_irq(INTERRUPT_E1000);
+ break;
+
case INTERRUPT_APIC_TIMER:
case INTERRUPT_IPI:
esp=scheduler_run(esp,0);
@@ -149,6 +155,9 @@ void interrupts_init(uint16_t sel)
// Mouse (IOAPIC)
int_install_ir(0x92, 0b10001110, 0x08,&int146);
+ // E1000
+ int_install_ir(0x93, 0b10001110, 0x08,&int147);
+
// APIC Timer (LAPIC)
int_install_ir(0x8C, 0b10001110, 0x08,&int140);
diff --git a/kernel/interrupts.h b/kernel/interrupts.h
index 3d28dc4..344369d 100644
--- a/kernel/interrupts.h
+++ b/kernel/interrupts.h
@@ -48,6 +48,7 @@
#define INTERRUPT_PIT_TIMER 0x90
#define INTERRUPT_KEYBOARD 0x91
#define INTERRUPT_MOUSE 0x92
+#define INTERRUPT_E1000 0x93
#define INTERRUPT_APIC_TIMER 0x8C
#define INTERRUPT_SYSCALL 0x80
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 6bda4bf..c244b9a 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -13,6 +13,8 @@
//-- clean below headers --//
#include "sysfs.h"
+#include "pci.h"
+#include "e1000.h"
#include "pipe.h"
#include "testing/testing.h"
#include "ext2.h"
@@ -82,6 +84,12 @@ void kernel_main(uint32_t eax,uint32_t ebx)
interrupts_install();
fixme("register interrupt callback funcs (instead hardcoded dispatcher)");
+
+ // -- PCI SCAN --/
+ klog("PCI init ...");
+ uint32_t e1000_addr=pci_init();
+ klog("E1000 addr=0x%08X",e1000_addr);
+
// -- MEMORY MANAGEMENT -- //
klog("Memory init ... ");
mem_init(cfg_multiboot);
@@ -91,7 +99,7 @@ void kernel_main(uint32_t eax,uint32_t ebx)
fixme("write convenneint management funcs as: mapCPU, mapKErnel, map USerspace..");
fixme("move stack and guard with empty pages!");
- vmem_init(cfg_multiboot,&cfg_acpi);
+ vmem_init(cfg_multiboot,&cfg_acpi,e1000_addr);
struct pdirectory_struct *dir=vmem_kernel_dir();
x86_set_page_directory(dir);
@@ -120,6 +128,7 @@ void kernel_main(uint32_t eax,uint32_t ebx)
vesa_init(cfg_multiboot,addr);
// -- STD STREAMS -- //
+ klog("Standard Streams init ...");
fd_init_std_streams(0,cfg_multiboot->framebuffer_type!=2);
// -- KB -- //
@@ -136,6 +145,8 @@ void kernel_main(uint32_t eax,uint32_t ebx)
uint64_t unixtime=timer_init();
klog("Unix Time = %u seconds",unixtime);
+ e1000_init(e1000_addr);
+
klog("Symmetric Multi Processing (SMP) start ... ");
smp_start_aps(&cfg_acpi);
}
diff --git a/kernel/kernel.h b/kernel/kernel.h
index b2bb81b..07e5fda 100644
--- a/kernel/kernel.h
+++ b/kernel/kernel.h
@@ -23,7 +23,7 @@ REFERENCES
#define FOOLOS_CONFIG_H
//#define FOOLOS_UNIT_TESTING // Run Unit Tests
-#define FOOLOS_LOG_OFF // Turn off logging (disables serial port alltogether)
+//#define FOOLOS_LOG_OFF // Turn off logging (disables serial port alltogether)
//#define FOOLOS_COLORLESS // Turn off colors in log
#define HIDE_FIXME
diff --git a/kernel/scheduler.c b/kernel/scheduler.c
index 667abf8..f6067e5 100644
--- a/kernel/scheduler.c
+++ b/kernel/scheduler.c
@@ -10,6 +10,7 @@
#include "asm_task.h"
#include "asm_usermode.h"
#include "kmalloc.h"
+#include "e1000.h"
#include "vmem.h"
#include "spinlock.h"
diff --git a/kernel/vmem.c b/kernel/vmem.c
index 590722d..4f854b6 100644
--- a/kernel/vmem.c
+++ b/kernel/vmem.c
@@ -26,6 +26,8 @@
//! page sizes are 4kb
#define PAGE_SIZE 4096
+uint32_t e1000_addr;
+
//! page table entry
typedef uint32_t pt_entry;
@@ -296,6 +298,7 @@ pdirectory* vmem_kernel_dir()
pdirectory* dir = vmem_clean_dir();
vmem_add_identity(dir,0,1024*8,false);//identity map first 32 megs...
+ vmem_add_identity(dir,e1000_addr,32,false);//identity map 32 pages for e1000
vmem_add_remap(dir,fb_addr,VMEM_FRAMEBUFFER,1024*8,false);//32megs should be enough for 4k (think about pitch)
vmem_add_remap(dir,local_apic_addr,VMEM_LAPIC,1,false); //apic addr should be at pagestart, right? TODO: check.
@@ -417,8 +420,9 @@ pdirectory* vmem_new_space_dir(pdirectory *copy_dir,bool stack_only)
return dir;
}
-void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi)
+void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi,uint32_t e1000addr)
{
+ e1000_addr=e1000addr;
fixme("do not share fb_addr with syscalls like that!");
fb_addr=cfg_multiboot->framebuffer_addr;
local_apic_addr=cfg_acpi->local_apic_address;
@@ -427,3 +431,4 @@ void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi)
mod_start=mod->mod_start;
mod_end=mod->mod_end;
}
+
diff --git a/kernel/vmem.h b/kernel/vmem.h
index c85d36b..211b5d3 100644
--- a/kernel/vmem.h
+++ b/kernel/vmem.h
@@ -53,7 +53,7 @@
struct pdirectory_struct;
-void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi);
+void vmem_init(multiboot_information *cfg_multiboot, acpi_information *cfg_acpi,uint32_t e1000_addr);
void vmem_free_dir(struct pdirectory_struct *dir);
struct pdirectory_struct* vmem_new_space_dir(struct pdirectory_struct *copy_dir,bool stack_only);
void vmem_free_space_dir(struct pdirectory_struct *dir,bool stack_only);