commit f36a1b337545b233e93a0a0788995ae1169645bc
parent d7063b910f1653a2a28e02c349040c5354273e56
Author: erai <erai@omiltem.net>
Date: Wed, 1 May 2024 04:08:38 -0400
ahci basics
Diffstat:
M | kernel.c | | | 824 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------- |
A | watch.sh | | | 8 | ++++++++ |
2 files changed, 576 insertions(+), 256 deletions(-)
diff --git a/kernel.c b/kernel.c
@@ -190,6 +190,58 @@ bzero(s: *byte, size: int) {
}
}
+panic(r: *regs) {
+ cli();
+
+ kputs("\n");
+ kputh(r.rax);
+ kputs(" ");
+ kputh(r.rcx);
+ kputs(" ");
+ kputh(r.rdx);
+ kputs(" ");
+ kputh(r.rbx);
+ kputs("\n");
+
+ kputh(r.rsi);
+ kputs(" ");
+ kputh(r.rdi);
+ kputs(" ");
+ kputh(r.r8);
+ kputs(" ");
+ kputh(r.r9);
+ kputs("\n");
+
+ kputh(r.r10);
+ kputs(" ");
+ kputh(r.r11);
+ kputs(" ");
+ kputh(r.r12);
+ kputs(" ");
+ kputh(r.r13);
+ kputs("\n");
+
+ kputh(r.r14);
+ kputs(" ");
+ kputh(r.r15);
+ kputs(" ");
+ kputh(r.rbp);
+ kputs(" ");
+ kputh(r.rsp);
+ kputs("\n");
+
+ kputh(r.rip);
+ kputs(" ");
+ kputh(r.rflags);
+ kputs(" ");
+ kputh(rdcr2());
+ kputs("\n");
+
+ loop {
+ hlt();
+ }
+}
+
_isr(r: *regs) {
var global: *global;
global = g();
@@ -197,10 +249,22 @@ _isr(r: *regs) {
if (r.trap < 32) {
kputs("EX ");
kputd(r.trap);
+ kputs(":");
+ kputd(r.err);
kputs("\n");
+ panic(r);
+ loop {
+ hlt();
+ }
+ } else if (r.trap == 32) {
+ tick();
+ outb(IO_PIC1, 0x20);
} else {
- if (r.trap == 32) {
+ kputd(r.trap);
+ if (r.trap == 33) {
isr_realtek();
+ } else if (r.trap == 34) {
+ isr_ahci();
}
// apic end of interrupt
_w32(&global.lapic[0xb0], 0);
@@ -437,12 +501,17 @@ find_acpi(xsdt: int, sig: *byte): int {
}
}
-map_pci(va: *byte, pa: int): *byte {
+map_pci(pa: int): *byte {
+ var global: *global;
+ var va: int;
var pt4p: int;
var pt4: *int;
var pt3: *int;
var v2: int;
var flags: int;
+ global = g();
+ global.mmio = global.mmio - (1 << 31);
+ va = global.mmio;
pt4p = rdcr3();
pt4 = ptov(pt4p):*int;
v2 = ((va: int) >> 30) & 511;
@@ -451,7 +520,7 @@ map_pci(va: *byte, pa: int): *byte {
pt3[v2] = (pa & -(1 << 30)) | flags;
pt3[v2 + 1] = ((pa + (1 << 30)) & -(1 << 30)) | flags;
wrcr3(pt4p);
- return &va[pa & ((1 << 30) - 1)];
+ return (va + (pa & ((1 << 30) - 1))):*byte;
}
struct pcidev {
@@ -521,6 +590,7 @@ scan_pci(base: *byte, visit: func(dev: *pcidev)) {
if capid == 5 {
dev.msi = &base[i * 4096 + cap];
+ break;
}
cap = base[i * 4096 + cap + 1]:int;
@@ -559,45 +629,25 @@ show_pcidev(dev: *pcidev) {
kputc('\n');
}
-map_bar(va: *byte, dev: *pcidev): *byte {
- var type: int;
- var pa: int;
-
- type = (dev.bar0 >> 1) & 3;
- pa = dev.bar0 & -16;
-
- // io bar
- if (dev.bar0 & 1) != 0 || type == 3 {
- return 0:*byte;
- }
-
- // 64 bit bar
- if type == 1 {
- pa = pa | (dev.bar1 << 32);
- }
-
- return map_pci(va, pa);
-}
-
-enum {
- E1_TXDESCLO = 0x3800,
- E1_TXDESCHI = 0x3804,
- E1_TXDESCLEN = 0x3808,
- E1_TXDESCHEAD = 0x3810,
- E1_TXDESCTAIL = 0x3818,
- E1_TCTRL = 0x0400,
- E1_TIPG = 0x0410,
-
- E1_RXDESCLO = 0x2800,
- E1_RXDESCHI = 0x2804,
- E1_RXDESCLEN = 0x2808,
- E1_RXDESCHEAD = 0x2810,
- E1_RXDESCTAIL = 0x2818,
- E1_RCTRL = 0x0100,
-
- E1_IMASK = 0x00d0,
- E1_ICR = 0x00C0,
-}
+//enum {
+// E1_TXDESCLO = 0x3800,
+// E1_TXDESCHI = 0x3804,
+// E1_TXDESCLEN = 0x3808,
+// E1_TXDESCHEAD = 0x3810,
+// E1_TXDESCTAIL = 0x3818,
+// E1_TCTRL = 0x0400,
+// E1_TIPG = 0x0410,
+//
+// E1_RXDESCLO = 0x2800,
+// E1_RXDESCHI = 0x2804,
+// E1_RXDESCLEN = 0x2808,
+// E1_RXDESCHEAD = 0x2810,
+// E1_RXDESCTAIL = 0x2818,
+// E1_RCTRL = 0x0100,
+//
+// E1_IMASK = 0x00d0,
+// E1_ICR = 0x00C0,
+//}
onesum(h: *byte, n: int): int {
var i: int;
@@ -633,182 +683,182 @@ icmp_checksum(p: *byte) {
p[3] = s:byte;
}
-init_e1000(dev: *pcidev) {
- var flag: *int;
- var base: *byte;
- var mac: int;
- var i: int;
- var txring: *byte;
-
- if *flag || dev.vid != 0x8086 || (
- dev.did != 0x100e
- && dev.did != 0x1539
- ) {
- return;
- }
- *flag = 1;
- *dev.trap = 10:byte;
-
- base = map_bar(ptov(-(1<<34)), dev);
- if !base {
- return;
- }
-
- // Enable dma
- _w16(&dev.addr[4], 6);
-
- // Disable interrupts
- _w32(&base[E1_IMASK], 0);
-
- // Clear MTA
- i = 0;
- loop {
- if i == 0x80 {
- break;
- }
- _w32(&base[0x5200 + 4 * i], 0);
- i = i + 1;
- }
-
- // Read mac
- mac = _r32(&base[0x5400]) + (_r32(&base[0x5404])) << 32;
-
- txring = map_pci((-(1<<35)):*byte, 1024*1024*3);
-
- i = 0;
- loop {
- if i == 16 {
- break;
- }
- bzero(&txring[16*32 + 16*i], 16);
- ((&txring[16*32 + 16*i]):*int)[0] = 1024*1024*3 + 4096 * (i + 1);
- _w16(&txring[16*32 + 16*i + 8], 2048);
- i = i + 1;
- }
-
- // Create tx descriptors
- _w32(&base[E1_TXDESCLO], 1024*1024*3);
- _w32(&base[E1_TXDESCHI], 0);
- _w32(&base[E1_TXDESCLEN], 16*32);
- _w32(&base[E1_TXDESCHEAD], 0);
- _w32(&base[E1_TXDESCTAIL], 0);
-
- // Create rx descriptors
- _w32(&base[E1_RXDESCLO], 1024*1024*3+16*32);
- _w32(&base[E1_RXDESCHI], 0);
- _w32(&base[E1_RXDESCLEN], 16*32);
- _w32(&base[E1_RXDESCHEAD], 0);
- _w32(&base[E1_RXDESCTAIL], 31);
-
- // Enable interrupts
- _w32(&base[E1_IMASK], 0);
-
- // Enable rx and tx
- _w32(&base[E1_TCTRL], 0x3003f0fa);
- _w32(&base[E1_RCTRL],
- // Enable
- (1 << 1)
- // StoreBadPackets
- + (1 << 2)
- // UnicastPromiscuous
- + (1 << 3)
- // MulticastPromiscuous
- + (1 << 4)
- // LoobackMode
- + (0 << 6)
- // BroadcastAccept
- + (1 << 15)
- // ReceiveBufferSize
- + (0 << 16)
- // StripEthernetCRC
- + (1 << 26));
-
- // Send a packet
- (txring:*int)[0] = 1024*1024*3 + 16*32*2;
- _w16(&txring[8], 60);
- txring[10] = 0:byte;
- // ReportStatus + InsertFrameCheckSequence + EndOfPacket
- txring[11] = ((0 << 3) + (1 << 1) + 1):byte;
- txring[12] = 0:byte;
- txring[13] = 0:byte;
- txring[14] = 0:byte;
- txring[15] = 0:byte;
- txring[16*32*2 + 0] = (mac >> 40):byte;
- txring[16*32*2 + 1] = (mac >> 32):byte;
- txring[16*32*2 + 2] = (mac >> 24):byte;
- txring[16*32*2 + 3] = (mac >> 16):byte;
- txring[16*32*2 + 4] = (mac >> 8):byte;
- txring[16*32*2 + 5] = mac:byte;
- txring[16*32*2 + 6] = 0x36:byte;
- txring[16*32*2 + 7] = 0xb9:byte;
- txring[16*32*2 + 8] = 0x55:byte;
- txring[16*32*2 + 9] = 0x54:byte;
- txring[16*32*2 + 10] = 0xba:byte;
- txring[16*32*2 + 11] = 0xcf:byte;
- txring[16*32*2 + 12] = 0x08:byte;
- txring[16*32*2 + 13] = 0x00:byte;
-
- txring[16*32*2 + 14] = 0x45:byte;
- txring[16*32*2 + 15] = 0:byte;
- txring[16*32*2 + 16] = 0:byte;
- txring[16*32*2 + 17] = 28:byte;
- txring[16*32*2 + 18] = 0:byte;
- txring[16*32*2 + 19] = 0:byte;
- txring[16*32*2 + 20] = 0:byte;
- txring[16*32*2 + 21] = 0:byte;
- txring[16*32*2 + 22] = 64:byte;
- txring[16*32*2 + 23] = 1:byte;
- txring[16*32*2 + 24] = 0:byte;
- txring[16*32*2 + 25] = 0:byte;
- txring[16*32*2 + 26] = 192:byte;
- txring[16*32*2 + 27] = 168:byte;
- txring[16*32*2 + 28] = 32:byte;
- txring[16*32*2 + 29] = 2:byte;
- txring[16*32*2 + 30] = 192:byte;
- txring[16*32*2 + 31] = 168:byte;
- txring[16*32*2 + 32] = 32:byte;
- txring[16*32*2 + 33] = 1:byte;
-
- ip_checksum(&txring[16*32*2 + 14]);
-
- txring[16*32*2 + 34] = 8:byte;
- txring[16*32*2 + 35] = 0:byte;
- txring[16*32*2 + 36] = 0:byte;
- txring[16*32*2 + 37] = 0:byte;
- txring[16*32*2 + 38] = 0:byte;
- txring[16*32*2 + 39] = 0:byte;
- txring[16*32*2 + 40] = 0:byte;
-
- icmp_checksum(&txring[16*32*2 + 34]);
-
- _w32(&base[E1_TXDESCTAIL], 1);
- _w32(&base[E1_IMASK], (1 << 0) + (1 << 4));
-}
-
-init_nvme(dev: *pcidev) {
- var flag: *int;
- var base: *byte;
-
- if *flag || dev.cls != 1 || dev.subcls != 8 {
- return;
- }
- *flag = 1;
- *dev.trap = 11:byte;
-
- // Enable dma
- _w16(&dev.addr[4], 6);
-
- // Map bar
- base = map_bar(ptov(-(1<<36)), dev);
- if !base {
- return;
- }
-
- kputs("nvme\n");
-
- // setup admin ring
- // enable interrupts
-}
+//init_e1000(dev: *pcidev) {
+// var flag: *int;
+// var base: *byte;
+// var mac: int;
+// var i: int;
+// var txring: *byte;
+//
+// if *flag || dev.vid != 0x8086 || (
+// dev.did != 0x100e
+// && dev.did != 0x1539
+// ) {
+// return;
+// }
+// *flag = 1;
+// *dev.trap = 10:byte;
+//
+// base = map_bar(ptov(-(1<<34)), dev);
+// if !base {
+// return;
+// }
+//
+// // Enable dma
+// _w16(&dev.addr[4], 6);
+//
+// // Disable interrupts
+// _w32(&base[E1_IMASK], 0);
+//
+// // Clear MTA
+// i = 0;
+// loop {
+// if i == 0x80 {
+// break;
+// }
+// _w32(&base[0x5200 + 4 * i], 0);
+// i = i + 1;
+// }
+//
+// // Read mac
+// mac = _r32(&base[0x5400]) + (_r32(&base[0x5404])) << 32;
+//
+// txring = alloc_page();
+//
+// i = 0;
+// loop {
+// if i == 16 {
+// break;
+// }
+// bzero(&txring[16*32 + 16*i], 16);
+// ((&txring[16*32 + 16*i]):*int)[0] = 1024*1024*3 + 4096 * (i + 1);
+// _w16(&txring[16*32 + 16*i + 8], 2048);
+// i = i + 1;
+// }
+//
+// // Create tx descriptors
+// _w32(&base[E1_TXDESCLO], 1024*1024*3);
+// _w32(&base[E1_TXDESCHI], 0);
+// _w32(&base[E1_TXDESCLEN], 16*32);
+// _w32(&base[E1_TXDESCHEAD], 0);
+// _w32(&base[E1_TXDESCTAIL], 0);
+//
+// // Create rx descriptors
+// _w32(&base[E1_RXDESCLO], 1024*1024*3+16*32);
+// _w32(&base[E1_RXDESCHI], 0);
+// _w32(&base[E1_RXDESCLEN], 16*32);
+// _w32(&base[E1_RXDESCHEAD], 0);
+// _w32(&base[E1_RXDESCTAIL], 31);
+//
+// // Enable interrupts
+// _w32(&base[E1_IMASK], 0);
+//
+// // Enable rx and tx
+// _w32(&base[E1_TCTRL], 0x3003f0fa);
+// _w32(&base[E1_RCTRL],
+// // Enable
+// (1 << 1)
+// // StoreBadPackets
+// + (1 << 2)
+// // UnicastPromiscuous
+// + (1 << 3)
+// // MulticastPromiscuous
+// + (1 << 4)
+// // LoobackMode
+// + (0 << 6)
+// // BroadcastAccept
+// + (1 << 15)
+// // ReceiveBufferSize
+// + (0 << 16)
+// // StripEthernetCRC
+// + (1 << 26));
+//
+// // Send a packet
+// (txring:*int)[0] = 1024*1024*3 + 16*32*2;
+// _w16(&txring[8], 60);
+// txring[10] = 0:byte;
+// // ReportStatus + InsertFrameCheckSequence + EndOfPacket
+// txring[11] = ((0 << 3) + (1 << 1) + 1):byte;
+// txring[12] = 0:byte;
+// txring[13] = 0:byte;
+// txring[14] = 0:byte;
+// txring[15] = 0:byte;
+// txring[16*32*2 + 0] = (mac >> 40):byte;
+// txring[16*32*2 + 1] = (mac >> 32):byte;
+// txring[16*32*2 + 2] = (mac >> 24):byte;
+// txring[16*32*2 + 3] = (mac >> 16):byte;
+// txring[16*32*2 + 4] = (mac >> 8):byte;
+// txring[16*32*2 + 5] = mac:byte;
+// txring[16*32*2 + 6] = 0x36:byte;
+// txring[16*32*2 + 7] = 0xb9:byte;
+// txring[16*32*2 + 8] = 0x55:byte;
+// txring[16*32*2 + 9] = 0x54:byte;
+// txring[16*32*2 + 10] = 0xba:byte;
+// txring[16*32*2 + 11] = 0xcf:byte;
+// txring[16*32*2 + 12] = 0x08:byte;
+// txring[16*32*2 + 13] = 0x00:byte;
+//
+// txring[16*32*2 + 14] = 0x45:byte;
+// txring[16*32*2 + 15] = 0:byte;
+// txring[16*32*2 + 16] = 0:byte;
+// txring[16*32*2 + 17] = 28:byte;
+// txring[16*32*2 + 18] = 0:byte;
+// txring[16*32*2 + 19] = 0:byte;
+// txring[16*32*2 + 20] = 0:byte;
+// txring[16*32*2 + 21] = 0:byte;
+// txring[16*32*2 + 22] = 64:byte;
+// txring[16*32*2 + 23] = 1:byte;
+// txring[16*32*2 + 24] = 0:byte;
+// txring[16*32*2 + 25] = 0:byte;
+// txring[16*32*2 + 26] = 192:byte;
+// txring[16*32*2 + 27] = 168:byte;
+// txring[16*32*2 + 28] = 32:byte;
+// txring[16*32*2 + 29] = 2:byte;
+// txring[16*32*2 + 30] = 192:byte;
+// txring[16*32*2 + 31] = 168:byte;
+// txring[16*32*2 + 32] = 32:byte;
+// txring[16*32*2 + 33] = 1:byte;
+//
+// ip_checksum(&txring[16*32*2 + 14]);
+//
+// txring[16*32*2 + 34] = 8:byte;
+// txring[16*32*2 + 35] = 0:byte;
+// txring[16*32*2 + 36] = 0:byte;
+// txring[16*32*2 + 37] = 0:byte;
+// txring[16*32*2 + 38] = 0:byte;
+// txring[16*32*2 + 39] = 0:byte;
+// txring[16*32*2 + 40] = 0:byte;
+//
+// icmp_checksum(&txring[16*32*2 + 34]);
+//
+// _w32(&base[E1_TXDESCTAIL], 1);
+// _w32(&base[E1_IMASK], (1 << 0) + (1 << 4));
+//}
+
+//init_nvme(dev: *pcidev) {
+// var flag: *int;
+// var base: *byte;
+//
+// if *flag || dev.cls != 1 || dev.subcls != 8 {
+// return;
+// }
+// *flag = 1;
+// *dev.trap = 11:byte;
+//
+// // Enable dma
+// _w16(&dev.addr[4], 6);
+//
+// // Map bar
+// base = map_bar(ptov(-(1<<36)), dev);
+// if !base {
+// return;
+// }
+//
+// kputs("nvme\n");
+//
+// // setup admin ring
+// // enable interrupts
+//}
struct vga {
base: *byte;
@@ -914,14 +964,15 @@ kputs(s: *byte) {
struct global {
ptr: *global;
+ ms: int;
vga: vga;
fr: *free_range;
fpage: *free_page;
lapicp: int;
lapic: *byte;
- rtkio: int;
- rxring: int;
- txring: int;
+ mmio: int;
+ realtek_port: *realtek_port;
+ ahci_port: *ahci_port;
}
struct free_page {
@@ -1221,10 +1272,17 @@ fill_packet(ringp: int) {
ring:*int[0] = (0xb000 << 16) + (64);
}
+struct realtek_port {
+ next: *realtek_port;
+ io: int;
+ rxring: *byte;
+ txring: *byte;
+}
+
init_realtek(dev: *pcidev) {
var global: *global;
+ var realtek_port: *realtek_port;
var io: int;
- var pg: int;
global = g();
@@ -1232,8 +1290,11 @@ init_realtek(dev: *pcidev) {
return;
}
+ if dev.bar0 & 1 != 1 {
+ return;
+ }
+
io = dev.bar0 & -2;
- global.rtkio = io;
// Enable dma
_w16(&dev.addr[4], 7);
@@ -1246,11 +1307,14 @@ init_realtek(dev: *pcidev) {
}
}
+ // Disable interrupts
+ outw(io + 0x3c, 0x0000);
+
// Setup MSI
_w16(&dev.msi[2], 0x0081);
_w32(&dev.msi[4], global.lapicp);
- _w32(&dev.msi[8], 0);
- _w16(&dev.msi[12], 32);
+ _w32(&dev.msi[8], global.lapicp >> 32);
+ _w16(&dev.msi[12], 33);
// Config write enable
outb(io + 0x50, 0xc0);
@@ -1268,25 +1332,25 @@ init_realtek(dev: *pcidev) {
// tx packet size
outd(io + 0xec, 0x00000010);
- pg = alloc_page();
- setup_ring(pg, 0);
- fill_packet(pg);
- global.txring = pg;
+ var txringp: int;
+ txringp = alloc_page();
+ setup_ring(txringp, 0);
+ fill_packet(txringp);
// tx ring
- outd(io + 0x20, pg);
- outd(io + 0x24, pg >> 32);
+ outd(io + 0x20, txringp);
+ outd(io + 0x24, txringp >> 32);
// tx max size
outb(io + 0xec, 16);
- pg = alloc_page();
- setup_ring(pg, 1);
- global.rxring = pg;
+ var rxringp: int;
+ rxringp = alloc_page();
+ setup_ring(rxringp, 1);
// rx ring
- outd(io + 0xe4, pg);
- outd(io + 0xe8, pg >> 32);
+ outd(io + 0xe4, rxringp);
+ outd(io + 0xe8, rxringp >> 32);
// Enable rx/tx
outd(io + 0x37, 0x0c);
@@ -1300,33 +1364,280 @@ init_realtek(dev: *pcidev) {
// TX Doorbell
outb(io + 0x38, 0x40);
+
+ realtek_port = ptov(alloc_page()):*realtek_port;
+ realtek_port.next = global.realtek_port;
+ realtek_port.io = io;
+ realtek_port.rxring = ptov(rxringp);
+ realtek_port.txring = ptov(txringp);
+ global.realtek_port = realtek_port;
}
isr_realtek() {
- var v: *byte;
var global: *global;
+ var realtek_port: *realtek_port;
var i: int;
global = g();
- v = ptov(global.rxring);
+ realtek_port = global.realtek_port;
+ loop {
+ if !realtek_port {
+ break;
+ }
+
+ i = 0;
+ loop {
+ if i == 16 {
+ break;
+ }
+
+ _w32(&realtek_port.rxring[i * 16], (1 << 31) | ((i == 15) << 30) | 4096);
+ _w32(&realtek_port.rxring[i * 16 + 4], 0);
+
+ i = i + 1;
+ }
+
+ // clear interrupt flags
+ outw(realtek_port.io + 0x3e, 0xffff);
+
+ realtek_port = realtek_port.next;
+ }
+}
+
+init_ahci(dev: *pcidev) {
+ var global: *global;
+ var ahci: *byte;
+
+ global = g();
+
+ if dev.cls != 1 || dev.subcls != 6 {
+ return;
+ }
+
+ ahci = map_pci(dev.bar5);
+ // Enable dma
+ _w16(&dev.addr[4], 6);
+
+ // Enable message signaled interrupts
+ _w16(&dev.msi[8], 34);
+ _w32(&dev.msi[4], global.lapicp);
+ _w16(&dev.msi[2], 0x0001);
+
+ // Find populated ports
+ if _r32(&ahci[0x00]) & (1 << 31) == 0 {
+ kputs("AHCI does not support 64 bit dma\n");
+ return;
+ }
+
+ // Enable ahci and interrupts
+ _w32(&ahci[0x4], (1 << 31) + (1 << 1));
+ _w32(&ahci[0x08], -1);
+
+ var pi: int;
+ var i: int;
+
+ pi = _r32(&ahci[0xc]);
i = 0;
loop {
- if i == 16 {
+ if pi == 0 {
break;
}
- _w32(&v[i * 16], (1 << 31) | ((i == 15) << 30) | 4096);
- _w32(&v[i * 16 + 4], 0);
+ if pi & 1 {
+ init_ahci_port(ahci, i);
+ }
+ pi = pi >> 1;
i = i + 1;
}
+}
+
+struct ahci_port {
+ next: *ahci_port;
+ ahci: *byte;
+ port: *byte;
+ cmd: *byte;
+ ctabp: int;
+ ctab: *byte;
+ fis: *byte;
+ bufp: int;
+ buf: *byte;
+}
+
+init_ahci_port(ahci: *byte, i: int) {
+ var global: *global;
+ var port: *byte;
+
+ global = g();
- kputc('.');
+ port = &ahci[0x100 + 0x80 * i];
- // clear interrupt flags
- outw(global.rtkio + 0x3e, 0xffff);
+ // Set ST=0
+ _w32(&port[0x18], _r32(&port[0x18]) & -2 & ~(15 << 28));
+
+ // Wait for DMA finish
+ loop {
+ if _r32(&port[0x18]) & (1 << 15) == 0 {
+ break;
+ }
+ }
+
+ // Clear errors
+ _w32(&port[0x30], -1);
+
+ var ahci_port: *ahci_port;
+ ahci_port = ptov(alloc_page()): *ahci_port;
+ ahci_port.next = 0:*ahci_port;
+ ahci_port.ahci = ahci;
+ ahci_port.port = port;
+
+ // Allocate queues
+ var cmdp: int;
+ var fisp: int;
+ var ctabp: int;
+
+ // each command list header is 32 bytes, there are 32 of them
+ cmdp = alloc_page();
+ ahci_port.cmd = ptov(cmdp);
+ bzero(ahci_port.cmd, 4096);
+
+ //// each table must be aligned to 128 bytes
+ //// allocate one 128 block to each command list from this page
+ ctabp = alloc_page();
+ ahci_port.ctabp = ctabp;
+ ahci_port.ctab = ptov(ctabp);
+ bzero(ahci_port.ctab, 4096);
+
+ //// fis is 256 bytes
+ fisp = alloc_page();
+ ahci_port.fis = ptov(fisp);
+ bzero(ahci_port.fis, 4096);
+
+ // Set command list and fis pointers
+ _w32(&port[0x00], cmdp);
+ _w32(&port[0x04], cmdp >> 32);
+ _w32(&port[0x08], fisp);
+ _w32(&port[0x0c], fisp >> 32);
+
+ // Spin up device
+ _w32(&port[0x18], 0x11);
+
+ // Wait for busy and drq to clear
+ loop {
+ if _r32(&port[0x20]) & 0x88 == 0 {
+ break;
+ }
+ }
+
+ // Enable interrupts
+ _w32(&port[0x14], -1);
+ _w32(&port[0x10], -1);
+
+ // Send ATA IDENTIFY
+ ahci_port.bufp = alloc_page();
+ ahci_port.buf = ptov(ahci_port.bufp);
+
+ // Set command list header
+ bzero(ahci_port.cmd, 4096);
+ _w32(&ahci_port.cmd[0x00], (1 << 16) + (1 << 10) + 5);
+ _w32(&ahci_port.cmd[0x04], 0);
+ _w32(&ahci_port.cmd[0x08], ahci_port.ctabp);
+ _w32(&ahci_port.cmd[0x0c], ahci_port.ctabp >> 32);
+
+ bzero(ahci_port.ctab, 4096);
+
+ // Fill command FIS
+ ahci_port.ctab[0x00] = 0x27:byte;
+ ahci_port.ctab[0x01] = 0x80:byte;
+ ahci_port.ctab[0x02] = 0xec:byte;
+
+ // Fill PRDT
+ _w32(&ahci_port.ctab[0x80], ahci_port.bufp);
+ _w32(&ahci_port.ctab[0x84], ahci_port.bufp >> 32);
+ _w32(&ahci_port.ctab[0x88], 0);
+ _w32(&ahci_port.ctab[0x8c], (1 << 31) + 511);
+
+ // Set AHCI Doorbell
+ _w32(&ahci_port.port[0x38], 1);
+
+ //loop {
+ // _w32(&port[0x30], -1);
+ // if _r32(&ahci_port.port[0x38]) & 1 == 0 {
+ // break;
+ // }
+ //}
+
+ //if _r32(&port[0x30]) != 0 {
+ // kputs("got error");
+ // return;
+ //}
+
+ //kputs("Found ");
+ //kputd((512 * (&ahci_port.buf[200]):*int[0]) / 1000000000);
+ //kputs("GB\n");
+
+ ahci_port.next = global.ahci_port;
+ global.ahci_port = ahci_port;
+}
+
+isr_ahci() {
+ var global: *global;
+ var ahci_port: *ahci_port;
+ var i: int;
+
+ kputc('a');
+
+ global = g();
+
+ ahci_port = global.ahci_port;
+ loop {
+ if !ahci_port {
+ break;
+ }
+
+ ahci_port = ahci_port.next;
+ }
+}
+
+tick() {
+ var global: *global;
+ global = g();
+ global.ms = global.ms + 1;
+}
+
+kdie(msg: *byte) {
+ kputs("die: ");
+ kputs(msg);
+ kputs("\n");
+ cli();
+ loop {
+ hlt();
+ }
+}
+
+sleep(ms: int) {
+ var global: *global;
+ var deadline: int;
+
+ global = g();
+
+ if ms <= 0 {
+ return;
+ }
+
+ if rdflags() & 0x200 == 0 {
+ kdie("attempt to sleep with interrupts disabled");
+ }
+
+ deadline = global.ms + ms;
+ loop {
+ if global.ms > deadline {
+ break;
+ }
+ hlt();
+ }
}
_kstart(mb: int) {
@@ -1349,9 +1660,12 @@ _kstart(mb: int) {
var mmap_count: int;
var fr: *free_range;
+ bzero((&global):*byte, sizeof(global));
global.ptr = &global;
wrmsr((0xc000 << 16) + 0x0101, global.ptr:int);
+ global.mmio = -(1 << 31);
+
vinit(&global.vga, ptov(0xB8000));
vclear(&global.vga);
kputs("Starting up\n");
@@ -1381,7 +1695,7 @@ _kstart(mb: int) {
if i + 1 < mmap_count {
if mmap_end > mmap[i * 3 + 3] {
- kputs("panic: OVERLAP\n");
+ kdie("OVERLAP");
loop {
cli();
hlt();
@@ -1478,19 +1792,17 @@ _kstart(mb: int) {
outb(IO_PIC1 + 1, 32);
outb(IO_PIC2 + 1, 40);
- // 100 hz pit
+ // 1000 hz pit
outb(IO_PIT + 3, 0x36);
- outb(IO_PIT + 0, 0x9b);
- outb(IO_PIT + 0, 0x2e);
-
- // Disable serial ports
- outb(0x3f8 + 1, 0x00);
- outb(0x2f8 + 1, 0x00);
+ outb(IO_PIT + 0, 0xa9);
+ outb(IO_PIT + 0, 0x04);
// unmask pit
- outb(IO_PIC1 + 1, 0xff);
+ outb(IO_PIC1 + 1, 0xfe);
outb(IO_PIC2 + 1, 0xff);
+ sti();
+
// Find ACPI tables
xsdt = find_xsdt();
mcfg = find_acpi(xsdt, "MCFG");
@@ -1507,19 +1819,19 @@ _kstart(mb: int) {
var lapicp: int;
lapicp = rdmsr(0x1b) & -4096;
var lapic: *byte;
- lapic = map_pci(ptov(-32 << 30), lapicp);
+ lapic = map_pci(lapicp);
_w32(&lapic[0xf0], _r32(&lapic[0xf0]) | 0x1ff);
global.lapicp = lapicp;
global.lapic = lapic;
- pci = map_pci(ptov(-34 << 30), pcip);
+ pci = map_pci(pcip);
scan_pci(pci, show_pcidev);
scan_pci(pci, init_realtek);
+ scan_pci(pci, init_ahci);
// Wait for interrupts
kputs("Sleeping...\n");
loop {
- sti();
hlt();
}
}
diff --git a/watch.sh b/watch.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+clear
+cmd="${1:-./pxe.sh}"
+shift
+"${cmd}" "$@"
+date
+: < ~/.post
+exec "$0" "$@"