summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile8
-rw-r--r--README.md2
-rw-r--r--kernel/e1000.c5
-rw-r--r--kernel/kernel.c3
-rw-r--r--kernel/pci.c175
5 files changed, 192 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index 629bc16..ea79f44 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,12 @@ vmem.o: kernel/vmem.c
mem.o: kernel/mem.c
gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0
+e1000.o: kernel/e1000.c
+ gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0
+
+pci.o: kernel/pci.c
+ gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0
+
console.o: kernel/console.c kernel/console.h
gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0
@@ -53,7 +59,7 @@ timer.o: kernel/timer.c
shell.o: kernel/shell.c
gcc -ffreestanding -m32 -o $@ -c $< -fno-asynchronous-unwind-tables -O0
-kernel.bin: kernel_entry.o kernel.o console.o interrupts.o keyboard.o timer.o shell.o mem.o vmem.o
+kernel.bin: kernel_entry.o kernel.o console.o interrupts.o keyboard.o timer.o shell.o mem.o vmem.o pci.o e1000.o
ld -o $@ -Ttext 0x1000 --oformat binary -melf_i386 $^ -O0
diff --git a/README.md b/README.md
index ea082dd..7bc5ea3 100644
--- a/README.md
+++ b/README.md
@@ -110,6 +110,7 @@ TODOS
* GNU HURD
* MINIX
* FreeBSD etc.
+ * xv6 (!)
look at following linux drivers:
* e1000
@@ -144,3 +145,4 @@ REFERENCES
* http://www.jamesmolloy.co.uk/tutorial_html/9.-Multitasking.html
* http://pdos.csail.mit.edu/6.828/2011/labs/lab6/
* http://wiki.osdev.org/Virtual_8086_Mode
+* http://pdos.csail.mit.edu/6.828/2011/xv6.html
diff --git a/kernel/e1000.c b/kernel/e1000.c
new file mode 100644
index 0000000..800b771
--- /dev/null
+++ b/kernel/e1000.c
@@ -0,0 +1,5 @@
+
+void init_e1000()
+{
+ scr_put_string_nl("initializing E1000 Intel PCI Ethernet Controller (TODO)");
+}
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 7dd89f7..91634ec 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -71,6 +71,9 @@ void kernel_main()
scr_put_string_nl("Interrupts are up and running");
scr_put_string_nl("");
+ // pci
+ pci_init();
+
//init shell
shell_init();
diff --git a/kernel/pci.c b/kernel/pci.c
new file mode 100644
index 0000000..6cf71f8
--- /dev/null
+++ b/kernel/pci.c
@@ -0,0 +1,175 @@
+#include "kernel.h"
+
+#define PCI_CONFIG_DATA 0xCFC
+#define PCI_CONFIG_ADDRESS 0xCF8
+
+void OutPort(unsigned short int IO_port,char Value)
+{
+ asm("outb %%al,%%dx;"
+ : //no output data
+ :"d"(IO_port),"a"(Value) //input data (EDX<-IO_port; AL<-Value)
+ );
+}
+char InPort(unsigned short int IO_port)
+{
+ asm("inb %%dx,%%al;"
+ : //output data is in al register
+ :"d"(IO_port) //input data (EDX<-IO_port AL<-Value)
+ );
+}
+
+x86_outl(int port, uint32_t data)
+{
+ __asm __volatile("outl %0,%w1" : : "a" (data), "d" (port));
+}
+
+
+
+x86_inl(int port)
+{
+ uint32_t data;
+ __asm __volatile("inl %w1,%0" : "=a" (data) : "d" (port));
+ return data;
+}
+
+ void pciConfigSet (uint8_t bus, uint8_t slot,
+ uint8_t func, uint8_t offset, uint32_t data)
+ {
+ uint32_t address;
+ uint32_t lbus = (uint32_t)bus;
+ uint32_t lslot = (uint32_t)slot;
+ uint32_t lfunc = (uint32_t)func;
+ uint16_t tmp = 0;
+
+ /* create configuration address as per Figure 1 */
+ address = (uint32_t)((lbus << 16) | (lslot << 11) |
+ (lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
+
+ /* write out the address */
+ x86_outl (0xCF8, address);
+ x86_outl (0xCFC,data);
+
+ }
+ uint16_t pciConfigReadWord (uint8_t bus, uint8_t slot,
+ uint8_t func, uint8_t offset)
+ {
+ uint32_t address;
+ uint32_t lbus = (uint32_t)bus;
+ uint32_t lslot = (uint32_t)slot;
+ uint32_t lfunc = (uint32_t)func;
+ uint16_t tmp = 0;
+
+ /* create configuration address as per Figure 1 */
+ address = (uint32_t)((lbus << 16) | (lslot << 11) |
+ (lfunc << 8) | (offset & 0xfc) | ((uint32_t)0x80000000));
+
+ /* write out the address */
+ x86_outl (0xCF8, address);
+ /* read in the data */
+ /* (offset & 2) * 8) = 0 will choose the first word of the 32 bits register */
+ tmp = (uint16_t)((x86_inl (0xCFC) >> ((offset & 2) * 8)) & 0xffff);
+ return (tmp);
+ }
+
+void test_bar(uint8_t bus, uint8_t slot, uint8_t offset)
+{
+
+ uint16_t bar_low=pciConfigReadWord(bus,slot,0,offset);
+ uint16_t bar_high=pciConfigReadWord(bus,slot,0,offset+2);
+
+ // check size
+ pciConfigSet(bus,slot,0,offset,0xffffffff);
+ uint16_t size_low=pciConfigReadWord(bus,slot,0,offset);
+ uint16_t size_high=pciConfigReadWord(bus,slot,0,offset+2);
+ uint32_t size=(size_high<<16)+size_low;
+ size=~size;
+ size++;
+ //
+
+ // restore original values
+ pciConfigSet(bus,slot,0,offset,(bar_high<<16)+bar_low);
+
+ scr_put_string("BAR: ");
+ if(bar_low& 1)scr_put_string("i/o ");
+ else scr_put_string("mem ");
+
+
+ scr_put_hex(bar_high);
+ scr_put_hex(bar_low);
+
+ scr_put_string(" size: ");
+
+ scr_put_hex(size_high);
+ scr_put_hex(size_low);
+ scr_put_string(" => ");
+ scr_put_hex32(size);
+
+
+ scr_put_string_nl(";");
+
+}
+
+uint16_t pciCheck(uint8_t bus, uint8_t slot)
+{
+
+ uint16_t vendor, device;
+
+ /* 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);
+ scr_put_hex(vendor);
+ scr_put_hex(device);
+ scr_put_string_nl(";");
+
+
+ // 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);
+
+ 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(";");
+
+
+ init_e1000();
+ }
+
+
+
+
+ }
+
+ return (vendor);
+
+}
+
+void pci_init()
+{
+ scr_put_string_nl("scanning pci bus");
+ // todo: recurse on pci to pci bridges!
+ // todo: support multiple pci host controllers!
+ // (check more funcitons of device 0:0)
+
+ uint16_t bus;
+ uint8_t device;
+
+ for(bus = 0; bus < 256; bus++)
+ {
+ for(device = 0; device < 32; device++)
+ {
+
+ pciCheck(bus, device);
+
+ }
+
+ }
+
+}