commit afb43b59137edc9507341270674c11f7f5431ee6
parent 778abaa4a0c04cb4227d5ce01f6f9c1508a85032
Author: erai <erai@omiltem.net>
Date: Sun, 28 Apr 2024 01:34:53 -0400
dumb rtl 10ec:8168
Diffstat:
M | as.c | | | 5 | +++++ |
M | cc1.c | | | 55 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | kernel.c | | | 890 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
M | pxe.asm | | | 26 | ++++++++++++++------------ |
4 files changed, 843 insertions(+), 133 deletions(-)
diff --git a/as.c b/as.c
@@ -54,12 +54,17 @@ enum {
}
enum {
+ OP_GS = 0x65,
+ OP_OS = 0x66,
+
OP_CLD = 0xfc,
OP_CLI = 0xfa,
OP_STI = 0xfb,
OP_CPUID = 0x0fa2,
OP_IN = 0xec,
+ OP_IND = 0xed,
OP_OUT = 0xee,
+ OP_OUTD = 0xef,
OP_HLT = 0xf4,
OP_NOP = 0x90,
OP_WBINVD = 0x0f09,
diff --git a/cc1.c b/cc1.c
@@ -1527,6 +1527,50 @@ main(argc: int, argv: **byte, envp: **byte) {
emit_ret(c.as);
}
+ d = find(c, "inw", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_preamble(c.as, 0, 0);
+ as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16);
+ as_emit(c.as, OP_OS);
+ as_op(c.as, OP_IND);
+ as_opr(c.as, OP_PUSHR, R_RAX);
+ emit_ret(c.as);
+ }
+
+ d = find(c, "outw", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_preamble(c.as, 0, 0);
+ as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16);
+ as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 24);
+ as_emit(c.as, OP_OS);
+ as_op(c.as, OP_OUTD);
+ as_opr(c.as, OP_PUSHR, R_RAX);
+ emit_ret(c.as);
+ }
+
+ d = find(c, "ind", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_preamble(c.as, 0, 0);
+ as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16);
+ as_op(c.as, OP_IND);
+ as_opr(c.as, OP_PUSHR, R_RAX);
+ emit_ret(c.as);
+ }
+
+ d = find(c, "outd", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_preamble(c.as, 0, 0);
+ as_modrm(c.as, OP_LOAD, R_RDX, R_RBP, 0, 0, 16);
+ as_modrm(c.as, OP_LOAD, R_RAX, R_RBP, 0, 0, 24);
+ as_op(c.as, OP_OUTD);
+ as_opr(c.as, OP_PUSHR, R_RAX);
+ emit_ret(c.as);
+ }
+
d = find(c, "rdmsr", 0:*byte, 1);
if (d.func_defined && !d.func_label.fixed) {
fixup_label(c.as, d.func_label);
@@ -1789,6 +1833,17 @@ main(argc: int, argv: **byte, envp: **byte) {
emit_isr(c);
}
+ d = find(c, "_rgs", 0:*byte, 1);
+ if (d.func_defined && !d.func_label.fixed) {
+ fixup_label(c.as, d.func_label);
+ emit_preamble(c.as, 0, 0);
+ as_modrm(c.as, OP_LOAD, R_RSI, R_RBP, 0, 0, 16);
+ as_emit(c.as, OP_GS);
+ as_modrm(c.as, OP_LOAD, R_RAX, R_RSI, 0, 0, 0);
+ as_opr(c.as, OP_PUSHR, R_RAX);
+ emit_ret(c.as);
+ }
+
d = find(c, "_r32", 0:*byte, 1);
if (d.func_defined && !d.func_label.fixed) {
fixup_label(c.as, d.func_label);
diff --git a/kernel.c b/kernel.c
@@ -5,6 +5,12 @@ cpuid(a: *int, c: *int, d: *int, b: *int);
inb(a: int): int;
outb(a: int, x: int);
+inw(a: int): int;
+outw(a: int, x: int);
+
+ind(a: int): int;
+outd(a: int, x: int);
+
rdmsr(r: int): int;
wrmsr(r: int, x: int);
@@ -35,6 +41,8 @@ invlpg(x: int);
_isr0();
+_rgs(x: int): int;
+
struct regs {
rax: int; // 0
rcx: int; // 8
@@ -183,50 +191,40 @@ bzero(s: *byte, size: int) {
}
_isr(r: *regs) {
- if (r.trap < 32) {
- //sputs("EX ");
- //sputd(r.trap);
- //sputs("\n");
- }
+ var global: *global;
+ global = g();
- if (r.trap == 2) {
- //sputs("NMI\n");
- }
-
- var vga: *byte;
-
- vga = ptov(0xB8000);
-
- vga[2] = ('A' + r.trap):byte;
- vga[3] = 0x0e:byte;
-
- // pic end of interrupt
- if (r.trap >= 32 && r.trap < 48) {
+ if (r.trap < 32) {
+ kputs("EX ");
+ kputd(r.trap);
+ kputs("\n");
+ } else {
if (r.trap == 32) {
- } else if (r.trap == 42) {
- //sputc('n');
- //sputc('\n');
- } else if (r.trap == 43) {
- // ethernet interrupt
- //sputc('e');
- }
- if (r.trap < 40) {
- outb(IO_PIC1, 0x0b);
- if inb(IO_PIC1) & (1 << (r.trap & 7)) {
- outb(IO_PIC1, 0x20);
- } else {
- //sputs("s\n");
- }
- } else {
- outb(IO_PIC2, 0x0b);
- if inb(IO_PIC2) & (1 << (r.trap & 7)) {
- outb(IO_PIC2, 0x20);
- outb(IO_PIC1, 0x20);
- } else {
- //sputs("s\n");
- }
+ isr_realtek();
}
+ // apic end of interrupt
+ _w32(&global.lapic[0xb0], 0);
}
+
+ // pic end of interrupt
+ //if (r.trap >= 32 && r.trap < 48) {
+ // if (r.trap < 40) {
+ // outb(IO_PIC1, 0x0b);
+ // if inb(IO_PIC1) & (1 << (r.trap & 7)) {
+ // outb(IO_PIC1, 0x20);
+ // } else {
+ // kputs("s\n");
+ // }
+ // } else {
+ // outb(IO_PIC2, 0x0b);
+ // if inb(IO_PIC2) & (1 << (r.trap & 7)) {
+ // outb(IO_PIC2, 0x20);
+ // outb(IO_PIC1, 0x20);
+ // } else {
+ // kputs("s\n");
+ // }
+ // }
+ //}
}
fill_idt(s: *int) {
@@ -286,7 +284,11 @@ bytesum(a: *byte, n: int): byte {
}
ptov(p: int): *byte {
- return (p + (-0x8000 << 16)): *byte;
+ if p < (1 << 30) {
+ return (p + (-0x8000 << 16)): *byte;
+ } else {
+ return (p + (-1 << 47)): *byte;
+ }
}
acpi_len(p: int): int {
@@ -318,79 +320,120 @@ valid_table(p: int, sig: *byte): int {
return len;
}
-show_addr(x: int) {
- var vga: *byte;
- var i: int;
- var j: int;
+kputh(x: int) {
+ _kputh(x, 64);
+}
+
+kputh8(x: int) {
+ _kputh(x, 8);
+}
- vga = ptov(0xB8000);
+kputh16(x: int) {
+ _kputh(x, 16);
+}
+
+kputh32(x: int) {
+ _kputh(x, 32);
+}
- i = 64;
- j = 160;
+_kputh(x: int, d: int) {
loop {
- if i == 0 {
+ if d == 0 {
break;
}
- i = i - 4;
- vga[j] = "0123456789abcdef"[(x >> i) & 15];
- vga[j + 1] = 0x0e:byte;
- j = j + 2;
+ d = d - 4;
+ kputc("0123456789abcdef"[(x >> d) & 15]:int);
+ }
+}
+
+kputd(x: int) {
+ var a: int;
+
+ if x < 0 {
+ kputc('-');
+ a = -(x % 10);
+ x = x / -10;
+ } else {
+ a = x % 10;
+ x = x / 10;
+ }
+
+ if x != 0 {
+ kputd(x);
}
+ kputc('0' + a);
}
find_xsdt(): int {
var p: int;
+ var v: *byte;
+ var len: int;
// Find the RDSP
p = 0xe0000;
loop {
+ v = ptov(p);
+
if p + 20 >= 0xfffff {
return 0;
}
- if !memcmp(ptov(p), "RSD PTR ", 8) {
- if !bytesum(ptov(p), 20) {
+
+ if !memcmp(v, "RSD PTR ", 8) {
+ if !bytesum(v, 20) {
break;
}
}
+
p = p + 16;
}
- //p = _r32(ptov(p + 16));
+ // Revision
+ if v[15]:int != 2 {
+ return 0;
+ }
- p = ptov(p + 24):*int[0];
- show_addr(p);
- //if valid_table(p, "XSDT") == 0 {
- //return 0;
- //}
+ len = _r32(&v[20]);
+ if len < 36 || len > 128 {
+ return 0;
+ }
+
+ if bytesum(v, len) {
+ return 0;
+ }
+
+ p = (&v[24]):*int[0];
+ if valid_table(p, "XSDT") == 0 {
+ return 0;
+ }
return p;
}
-find_acpi(rsdt: int, sig: *byte): int {
+find_acpi(xsdt: int, sig: *byte): int {
var i: int;
var len: int;
var p: int;
- if rsdt == 0 {
+ if xsdt == 0 {
return 0;
}
i = 36;
- len = acpi_len(rsdt);
+ len = acpi_len(xsdt);
loop {
if i >= len {
return 0;
}
- p = _r32(ptov(rsdt + i));
+ p = ptov(xsdt + i):*int[0];
if valid_table(p, sig) != 0 {
return p;
}
- i = i + 4;
+ i = i + 8;
}
}
@@ -412,8 +455,8 @@ map_pci(va: *byte, pa: int): *byte {
}
struct pcidev {
- user: *void;
addr: *byte;
+ type: int;
bus: int;
vid: int;
did: int;
@@ -426,21 +469,25 @@ struct pcidev {
bar4: int;
bar5: int;
trap: *byte;
+ msi: *byte;
}
-scan_pci(base: *byte, visit: func(dev: *pcidev), user: *void) {
+scan_pci(base: *byte, visit: func(dev: *pcidev)) {
var i: int;
+ var cap: int;
+ var capid: int;
var dev: pcidev;
i = 0;
loop {
- if i == 256 {
+ if i == 256*64 {
break;
}
- dev.user = user;
dev.addr = &base[i * 4096];
dev.bus = i;
+ dev.type = base[i * 4096 + 14]:int;
+
dev.vid = (base[i * 4096 + 0]:int)
+ (base[i * 4096 + 1]:int << 8);
dev.did = (base[i * 4096 + 2]:int)
@@ -461,41 +508,55 @@ scan_pci(base: *byte, visit: func(dev: *pcidev), user: *void) {
continue;
}
+ dev.msi = 0:*byte;
+
+ if dev.type == 0 {
+ cap = base[i * 4096 + 0x34]: int;
+ loop {
+ if cap == 0 || cap > 4094 {
+ break;
+ }
+
+ capid = base[i * 4096 + cap]:int;
+
+ if capid == 5 {
+ dev.msi = &base[i * 4096 + cap];
+ }
+
+ cap = base[i * 4096 + cap + 1]:int;
+ }
+ }
+
visit(&dev);
i = i + 1;
}
}
-clear_int(dev: *pcidev) {
- *dev.trap = 0xff:byte;
- _w16(&dev.addr[4], 0);
-}
-
show_pcidev(dev: *pcidev) {
- sputh(dev.bus);
- sputc(':');
- sputc('\t');
- sputh(dev.vid);
- sputc(':');
- sputh(dev.did);
- sputc('\t');
- sputh(dev.cls);
- sputc(':');
- sputh(dev.subcls);
- sputc('\t');
- sputh(dev.bar0);
- sputc('\t');
- sputh(dev.bar1);
- sputc('\t');
- sputh(dev.bar2);
- sputc('\t');
- sputh(dev.bar3);
- sputc('\t');
- sputh(dev.bar4);
- sputc('\t');
- sputh(dev.bar5);
- sputc('\n');
+ kputh16(dev.bus);
+ kputc(':');
+ kputc(' ');
+ kputh16(dev.vid);
+ kputc(':');
+ kputh16(dev.did);
+ kputc(' ');
+ kputh8(dev.cls);
+ kputc(':');
+ kputh8(dev.subcls);
+ kputc(' ');
+ kputh32(dev.bar0);
+ kputc(' ');
+ kputh32(dev.bar1);
+ kputc(' ');
+ kputh32(dev.bar2);
+ kputc(' ');
+ kputh32(dev.bar3);
+ kputc(' ');
+ kputh32(dev.bar4);
+ kputc(' ');
+ kputh32(dev.bar5);
+ kputc('\n');
}
map_bar(va: *byte, dev: *pcidev): *byte {
@@ -579,7 +640,6 @@ init_e1000(dev: *pcidev) {
var i: int;
var txring: *byte;
- flag = dev.user: *int;
if *flag || dev.vid != 0x8086 || (
dev.did != 0x100e
&& dev.did != 0x1539
@@ -729,7 +789,6 @@ init_nvme(dev: *pcidev) {
var flag: *int;
var base: *byte;
- flag = dev.user: *int;
if *flag || dev.cls != 1 || dev.subcls != 8 {
return;
}
@@ -745,15 +804,533 @@ init_nvme(dev: *pcidev) {
return;
}
- sputs("nvme\n");
+ kputs("nvme\n");
// setup admin ring
// enable interrupts
+}
+
+struct vga {
+ base: *byte;
+ cx: int;
+ cy: int;
+ x: int;
+ y: int;
+}
+
+vinit(v: *vga, base: *byte) {
+ v.base = base;
+ v.cx = 80;
+ v.cy = 25;
+ v.x = 0;
+ v.y = 0;
+}
+
+vcursor(v: *vga) {
+ var i: int;
+ i = v.y * v.cx + v.x;
+ outb(0x3d4, 0x0f);
+ outb(0x3d5, i);
+ outb(0x3d4, 0x0e);
+ outb(0x3d5, i >> 8);
+}
+
+vclear(v: *vga) {
+ var i: int;
+ v.x = 0;
+ v.y = 0;
+ vcursor(v);
+ i = 0;
+ loop {
+ if i == v.cx * v.cy {
+ return;
+ }
+ v.base[2 * i] = 0:byte;
+ v.base[2 * i + 1] = 0x0f:byte;
+ i = i + 1;
+ }
+}
+vshift(v: *vga) {
+ var i: int;
+ memcpy(v.base, &v.base[v.cx * 2], (v.cy - 1) * v.cx * 2);
+ i = (v.cy - 1) * v.cx;
+ loop {
+ if i == v.cx * v.cy {
+ break;
+ }
+ v.base[2 * i] = 0:byte;
+ v.base[2 * i + 1] = 0x0f:byte;
+ i = i + 1;
+ }
+ if v.y > 0 {
+ v.y = v.y - 1;
+ }
+}
+
+vputc(v: *vga, c: int) {
+ if c == '\r' {
+ v.x = 0;
+ } else if c == '\n' {
+ v.x = 0;
+ v.y = v.y + 1;
+ if v.y == v.cy {
+ vshift(v);
+ }
+ } else {
+ v.base[(v.y * v.cx + v.x) * 2] = c:byte;
+ v.base[(v.y * v.cx + v.x) * 2 + 1] = 0x0f:byte;
+ v.x = v.x + 1;
+ if v.x == v.cx {
+ v.x = 0;
+ v.y = v.y + 1;
+ if v.y == v.cy {
+ vshift(v);
+ }
+ }
+ }
+ vcursor(v);
+}
+
+kputc(c: int) {
+ var global: *global;
+ global = g();
+ vputc(&global.vga, c);
+}
+
+kputs(s: *byte) {
+ var i: int;
+ var global: *global;
+ global = g();
+ i = 0;
+ loop {
+ if !s[i] {
+ break;
+ }
+ vputc(&global.vga, s[i]:int);
+ i = i + 1;
+ }
+}
+
+struct global {
+ ptr: *global;
+ vga: vga;
+ fr: *free_range;
+ fpage: *free_page;
+ lapicp: int;
+ lapic: *byte;
+ rtkio: int;
+ rxring: int;
+ txring: int;
+}
+
+struct free_page {
+ next: *free_page;
+}
+
+struct free_range {
+ next: *free_range;
+ start: int;
+ end: int;
+}
+
+g(): *global {
+ return _rgs(0):**global[0];
+}
+
+memset(dest: *byte, c: int, size: int) {
+ var i: int;
+
+ if size < 0 {
+ return;
+ }
+
+ i = 0;
+ loop {
+ if i == size {
+ break;
+ }
+ dest[i] = c:byte;
+ i = i + 1;
+ }
+}
+memcpy(dest: *byte, src: *byte, size: int) {
+ var i: int;
+
+ if size < 0 {
+ return;
+ }
+
+ if src > dest {
+ i = 0;
+ loop {
+ if i == size {
+ break;
+ }
+ dest[i] = src[i];
+ i = i + 1;
+ }
+ } else if src < dest {
+ i = size;
+ loop {
+ if i == 0 {
+ break;
+ }
+ i = i - 1;
+ dest[i] = src[i];
+ }
+ }
+}
+
+memswap(a: *byte, b: *byte, size: int) {
+ var i: int;
+ var t: byte;
+
+ if size < 0 {
+ return;
+ }
+
+ i = 0;
+ loop {
+ if i == size {
+ break;
+ }
+ t = a[i];
+ a[i] = b[i];
+ b[i] = t;
+ i = i + 1;
+ }
+}
+
+insert_sort(arr: *void, nitems: int, size: int, cmp: (func(a: *void, b: *void): int)) {
+ var i: int;
+ var j: int;
+ var a: *void;
+ var b: *void;
+
+ if nitems <= 1 || size <= 0 {
+ return;
+ }
+
+ i = 1;
+ loop {
+ if i == nitems {
+ break;
+ }
+
+ j = i - 1;
+
+ b = (&arr:*byte[size * i]):*void;
+
+ loop {
+ a = (&arr:*byte[size * j]):*void;
+
+ if cmp(a, b) <= 0 {
+ break;
+ }
+
+ memswap(a: *byte, b: *byte, size);
+
+ if j == 0 {
+ break;
+ }
+
+ j = j - 1;
+ }
+
+ i = i + 1;
+ }
+}
+
+mmap_cmp(a: *void, b: *void): int {
+ var a_addr: int;
+ var b_addr: int;
+ a_addr = a:*int[0];
+ b_addr = b:*int[0];
+ if a_addr < b_addr {
+ return -1;
+ } else if a_addr > b_addr {
+ return 1;
+ }
+ return 0;
+}
+
+alloc_page(): int {
+ var global: *global;
+ var fr: *free_range;
+ var ret: int;
+ global = g();
+ fr = global.fr;
+ loop {
+ if !fr {
+ break;
+ }
+
+ if fr.start < fr.end {
+ ret = fr.start;
+ fr.start = fr.start + 4096;
+ return ret;
+ }
+
+ fr = fr.next;
+ }
+
+ kputs("OOM\n");
+
+ loop {
+ cli();
+ hlt();
+ }
+}
+
+direct_map(brk: *int) {
+ var pt4p: int;
+ var pt4: *int;
+ var pt3p: int;
+ var pt3: *int;
+ var va: int;
+ var pa: int;
+ var page_size: int;
+ var map_size: int;
+ var i: int;
+ var n: int;
+
+ map_size = 1 << 46;
+ page_size = 1 << 30;
+
+ va = -1 << 47;
+ pa = 0;
+
+ pt4p = rdcr3();
+ pt4 = ptov(pt4p):*int;
+
+ brk[0] = (brk[0] + 4095) & -4096;
+
+ loop {
+ if pa == map_size {
+ break;
+ }
+
+ n = 512;
+
+ pt3 = brk[0]:*int;
+ brk[0] = brk[0] + 4096;
+ pt3p = (pt3:int) & ((1 << 31) - 1);
+
+ i = (va >> 39) & 511;
+ pt4[i] = pt3p | 0x003;
+
+ loop {
+ if pa == map_size || n == 0 {
+ break;
+ }
+
+ i = (va >> 30) & 511;
+ pt3[i] = pa | 0x083;
+
+ va = va + page_size;
+ pa = pa + page_size;
+ n = n - 1;
+ }
+ }
+
+ wrcr3(pt4p);
+}
+
+setup_ring(ring: int, own: int) {
+ var v: *byte;
+ var i: int;
+ var p: int;
+
+ v = ptov(ring);
+ i = 0;
+
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ p = alloc_page();
+
+ _w32(&v[i * 16], (own << 31) | ((i == 15) << 30) | 4096);
+ _w32(&v[i * 16 + 4], 0);
+ _w32(&v[i * 16 + 8], p);
+ _w32(&v[i * 16 + 12], p >> 32);
+
+ i = i + 1;
+ }
+}
+
+fill_packet(ringp: int) {
+ var ring: *byte;
+ var packet: *byte;
+
+ ring = ptov(ringp);
+ packet = ptov(ring:*int[1]);
+
+ // Send a packet
+ packet[0] = 0xff:byte;
+ packet[1] = 0xff:byte;
+ packet[2] = 0xff:byte;
+ packet[3] = 0xff:byte;
+ packet[4] = 0xff:byte;
+ packet[5] = 0xff:byte;
+ packet[6] = 0xff:byte;
+ packet[7] = 0xff:byte;
+ packet[8] = 0xff:byte;
+ packet[9] = 0xff:byte;
+ packet[10] = 0xff:byte;
+ packet[11] = 0xff:byte;
+ packet[12] = 0x08:byte;
+ packet[13] = 0x00:byte;
+
+ packet[14] = 0x45:byte;
+ packet[15] = 0:byte;
+ packet[16] = 0:byte;
+ packet[17] = 28:byte;
+ packet[18] = 0:byte;
+ packet[19] = 0:byte;
+ packet[20] = 0:byte;
+ packet[21] = 0:byte;
+ packet[22] = 64:byte;
+ packet[23] = 1:byte;
+ packet[24] = 0:byte;
+ packet[25] = 0:byte;
+ packet[26] = 192:byte;
+ packet[27] = 168:byte;
+ packet[28] = 2:byte;
+ packet[29] = 100:byte;
+ packet[30] = 192:byte;
+ packet[31] = 168:byte;
+ packet[32] = 1:byte;
+ packet[33] = 178:byte;
+
+ ip_checksum(&packet[14]);
+
+ packet[34] = 8:byte;
+ packet[35] = 0:byte;
+ packet[36] = 0:byte;
+ packet[37] = 0:byte;
+ packet[38] = 0:byte;
+ packet[39] = 0:byte;
+ packet[40] = 0:byte;
+
+ icmp_checksum(&packet[34]);
+
+ ring:*int[0] = (0xb000 << 16) + (64);
+}
+
+init_realtek(dev: *pcidev) {
+ var global: *global;
+ var io: int;
+ var pg: int;
+
+ global = g();
+
+ if dev.vid != 0x10ec || dev.did != 0x8168 {
+ return;
+ }
+
+ io = dev.bar0 & -2;
+ global.rtkio = io;
+
+ // Enable dma
+ _w16(&dev.addr[4], 7);
+
+ // Reset
+ outb(io + 0x37, 0x10);
+ loop {
+ if (inb(io + 0x37) & 0x10) == 0 {
+ break;
+ }
+ }
+
+ // Setup MSI
+ _w16(&dev.msi[2], 0x0081);
+ _w32(&dev.msi[4], global.lapicp);
+ _w32(&dev.msi[8], 0);
+ _w16(&dev.msi[12], 32);
+
+ // Config write enable
+ outb(io + 0x50, 0xc0);
+
+ // rx config
+ outd(io + 0x44, 0x0000e70f);
+
+ // tx config
+ outb(io + 0x37, 0x0c);
+ outd(io + 0x40, 0x03000700);
+
+ // rx packet size
+ outd(io + 0xda, 0x00000800);
+
+ // tx packet size
+ outd(io + 0xec, 0x00000010);
+
+ pg = alloc_page();
+ setup_ring(pg, 0);
+ fill_packet(pg);
+ global.txring = pg;
+
+ // tx ring
+ outd(io + 0x20, pg);
+ outd(io + 0x24, pg >> 32);
+
+ // tx max size
+ outb(io + 0xec, 16);
+
+ pg = alloc_page();
+ setup_ring(pg, 1);
+ global.rxring = pg;
+
+ // rx ring
+ outd(io + 0xe4, pg);
+ outd(io + 0xe8, pg >> 32);
+
+ // Enable rx/tx
+ outd(io + 0x37, 0x0c);
+
+ // Enable interrupts
+ outw(io + 0x3c, 0x00ff);
+ outw(io + 0x3e, 0xffff);
+
+ // Config write disable
+ outb(io + 0x50, 0x00);
+
+ // TX Doorbell
+ outb(io + 0x38, 0x40);
+}
+
+isr_realtek() {
+ var v: *byte;
+ var global: *global;
+ var i: int;
+
+ global = g();
+
+ v = ptov(global.rxring);
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ _w32(&v[i * 16], (1 << 31) | ((i == 15) << 30) | 4096);
+ _w32(&v[i * 16 + 4], 0);
+
+ i = i + 1;
+ }
+
+ kputc('.');
+
+ // clear interrupt flags
+ outw(global.rtkio + 0x3e, 0xffff);
}
_kstart(mb: int) {
+ var global: global;
var brk: int;
var tss: *int;
var tss_size: int;
@@ -766,16 +1343,73 @@ _kstart(mb: int) {
var pcip: int;
var pci: *byte;
var flag: int;
- var vga: *byte;
+ var mbinfo: *byte;
+ var mmap: *int;
+ var mmap_len: int;
+ var mmap_count: int;
+ var fr: *free_range;
+
+ global.ptr = &global;
+ wrmsr((0xc000 << 16) + 0x0101, global.ptr:int);
+
+ vinit(&global.vga, ptov(0xB8000));
+ vclear(&global.vga);
+ kputs("Starting up\n");
+
+ global.fr = 0:*free_range;
+
+ brk = ptov(1024 * 1024 * 3):int;
+
+ mbinfo = ptov(mb);
+ mmap = ptov(_r32(&mbinfo[48])): *int;
+ mmap_len = _r32(&mbinfo[44]);
+ mmap_count = mmap_len / 24;
+
+ insert_sort(mmap:*void, mmap_count, 24, mmap_cmp);
+
+ var i: int;
+ var mmap_start: int;
+ var mmap_end: int;
+ i = 0;
+ loop {
+ if i == mmap_count {
+ break;
+ }
+
+ mmap_start = mmap[i * 3];
+ mmap_end = mmap_start + mmap[i * 3 + 1];
+
+ if i + 1 < mmap_count {
+ if mmap_end > mmap[i * 3 + 3] {
+ kputs("panic: OVERLAP\n");
+ loop {
+ cli();
+ hlt();
+ }
+ }
+ }
+
+ mmap_start = (mmap_start + 4095) & -4096;
+ mmap_end = mmap_end & -4096;
- vga = ptov(0xB8000);
+ if mmap_start < 0x400000 {
+ mmap_start = 0x400000;
+ }
- vga[0] = 'a':byte;
- vga[1] = 0x0e:byte;
+ if mmap_start < mmap_end && _r32((&mmap[i * 3 + 2]):*byte) == 1 {
+ fr = brk: *free_range;
+ brk = brk + sizeof(*fr);
+ fr.next = global.fr;
+ fr.start = mmap_start;
+ fr.end = mmap_end;
+ global.fr = fr;
+ }
- //setup_serial();
+ i = i + 1;
+ }
- brk = ptov(1024 * 512 * 3):int;
+ // Directly map all memory to just above the architectural hole
+ direct_map(&brk);
// Zero tss and add interrupt stacks
tss = brk: *int;
@@ -808,6 +1442,7 @@ _kstart(mb: int) {
// Load gdt idt tss and segments
lgdt(gdt, gdt_size);
lseg(8, 16);
+ wrmsr((0xc000 << 16) + 0x0101, global.ptr:int);
lldt(0);
ltr(5 * 8);
lidt(idt, idt_size);
@@ -848,28 +1483,41 @@ _kstart(mb: int) {
outb(IO_PIT + 0, 0x9b);
outb(IO_PIT + 0, 0x2e);
- // unmask pit
- outb(IO_PIC1 + 1, 0xfa);
- outb(IO_PIC2 + 1, 0xf3);
+ // Disable serial ports
+ outb(0x3f8 + 1, 0x00);
+ outb(0x2f8 + 1, 0x00);
- show_addr(ptov(mb + 44):*int[0]);
+ // unmask pit
+ outb(IO_PIC1 + 1, 0xff);
+ outb(IO_PIC2 + 1, 0xff);
// Find ACPI tables
- //xsdt = find_xsdt();
+ xsdt = find_xsdt();
+ mcfg = find_acpi(xsdt, "MCFG");
+ if !mcfg {
+ kputs("No mcfg?\n");
+ }
- //mcfg = find_acpi(xsdt, "MCFG");
+ pcip = (ptov(mcfg + 44):*int)[0];
+ if !pcip {
+ kputs("No pci?\n");
+ }
- //pcip = (ptov(mcfg + 44):*int)[0];
- //pci = map_pci(ptov(-(1<<31)), pcip);
+ // Enable the local apic
+ var lapicp: int;
+ lapicp = rdmsr(0x1b) & -4096;
+ var lapic: *byte;
+ lapic = map_pci(ptov(-32 << 30), lapicp);
+ _w32(&lapic[0xf0], _r32(&lapic[0xf0]) | 0x1ff);
+ global.lapicp = lapicp;
+ global.lapic = lapic;
- //scan_pci(pci, show_pcidev, 0:*void);
- //scan_pci(pci, clear_int, 0:*void);
- //flag = 0;
- //scan_pci(pci, init_e1000, (&flag):*void);
- //flag = 0;
- //scan_pci(pci, init_nvme, (&flag):*void);
+ pci = map_pci(ptov(-34 << 30), pcip);
+ scan_pci(pci, show_pcidev);
+ scan_pci(pci, init_realtek);
// Wait for interrupts
+ kputs("Sleeping...\n");
loop {
sti();
hlt();
diff --git a/pxe.asm b/pxe.asm
@@ -196,6 +196,8 @@ detect_mem:
.1:
pop bp
sub bp, .1
+ push cs
+ pop es
; BIOS - Get memory size
clc
int 0x12
@@ -204,7 +206,7 @@ detect_mem:
xor eax, eax
pop ax
shl eax, 10
- mov cs:[bp + low_mem_size], eax
+ mov es:[bp + low_mem_size], eax
; BIOS - Get high memory size
mov ah, 0x88
clc
@@ -214,13 +216,13 @@ detect_mem:
xor eax, eax
pop ax
shl eax, 10
- mov cs:[bp + high_mem_size], eax
+ mov es:[bp + high_mem_size], eax
; Zero kernel size
- mov dword cs:[bp + kernel_size], 0
+ mov dword es:[bp + kernel_size], 0
mov di, bp
add di, mmap + 4
mov ebx, 0
- mov word cs:[bp + mmap_size], 0
+ mov word es:[bp + mmap_size], 0
.loop:
; BIOS - Get system memory map
mov edx, 0x534D4150
@@ -234,9 +236,9 @@ detect_mem:
jnz .no_mem
cmp ecx, 20
jnz .no_mem
- mov cs:[di - 4], ecx
- add word cs:[bp + mmap_size], 24
- cmp word cs:[bp + mmap_size], (mmap_end - mmap)
+ mov es:[di - 4], ecx
+ add word es:[bp + mmap_size], 24
+ cmp word es:[bp + mmap_size], (mmap_end - mmap)
jz .no_mem
add di, 24
test ebx, ebx
@@ -268,7 +270,6 @@ enter_unreal:
.1:
xor ebx, ebx
pop bx
-
; Load the gdt
sub sp, 6
mov bp, sp
@@ -797,7 +798,8 @@ parse_mb:
mov dword ds:[edi + 8], eax
; Save mmap_len
- mov eax, cs:[bx + mmap_size - .1]
+ xor eax, eax
+ mov ax, cs:[bx + mmap_size - .1]
mov dword ds:[edi + 44], eax
; Save mmap_addr
@@ -805,7 +807,7 @@ parse_mb:
mov ax, cs
shl eax, 4
add eax, ebx
- mov eax, (mmap - .1)
+ add eax, (mmap + 4 - .1)
mov dword ds:[edi + 48], eax
popf
@@ -993,5 +995,5 @@ frame equ $
page equ frame + 256
;times 512 db 0
mmap equ page + 512
- ;times 8192 db 0
-mmap_end equ mmap + 8192
+ ;times (8192 + 8192) db 0
+mmap_end equ mmap + (8192 + 8192)