diff options
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | asm/asm_int.h | 1 | ||||
| -rw-r--r-- | asm/asm_int.s | 2 | ||||
| -rw-r--r-- | driver/e1000.c | 427 | ||||
| -rw-r--r-- | driver/e1000.h | 5 | ||||
| -rw-r--r-- | driver/keyboard.c | 9 | ||||
| -rw-r--r-- | driver/pci.c | 40 | ||||
| -rw-r--r-- | driver/pci.h | 1 | ||||
| -rw-r--r-- | kernel/acpi.c | 4 | ||||
| -rw-r--r-- | kernel/apic.c | 19 | ||||
| -rw-r--r-- | kernel/interrupts.c | 9 | ||||
| -rw-r--r-- | kernel/interrupts.h | 1 | ||||
| -rw-r--r-- | kernel/kernel.c | 13 | ||||
| -rw-r--r-- | kernel/kernel.h | 2 | ||||
| -rw-r--r-- | kernel/scheduler.c | 1 | ||||
| -rw-r--r-- | kernel/vmem.c | 7 | ||||
| -rw-r--r-- | kernel/vmem.h | 2 |
17 files changed, 522 insertions, 28 deletions
@@ -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); |
