summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/init/init.c4
-rw-r--r--src/kernel/arch/amd64/driver/rtl8139.c110
-rw-r--r--src/kernel/arch/amd64/driver/util.h1
3 files changed, 72 insertions, 43 deletions
diff --git a/src/cmd/init/init.c b/src/cmd/init/init.c
index 68268bf..2bef5d8 100644
--- a/src/cmd/init/init.c
+++ b/src/cmd/init/init.c
@@ -124,8 +124,8 @@ int main(void) {
execv(argv[0], (void*)argv);
}
MOUNT_AT("/net/") {
- const char *allow[] = {"/bin/netstack", "/dev/eth", NULL};
- const char *argv[] = {"/bin/netstack", "/dev/eth", "192.168.0.11", "192.168.0.2", NULL};
+ const char *allow[] = {"/bin/netstack", "/dev/eth/", NULL};
+ const char *argv[] = {"/bin/netstack", "/dev/eth/net", "192.168.0.11", "192.168.0.2", NULL};
MOUNT_AT("/") { fs_whitelist(allow); }
execv(argv[0], (void*)argv);
}
diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c
index 42b2abb..d1054a4 100644
--- a/src/kernel/arch/amd64/driver/rtl8139.c
+++ b/src/kernel/arch/amd64/driver/rtl8139.c
@@ -1,3 +1,4 @@
+#include <camellia/errno.h>
#include <kernel/arch/amd64/driver/driver.h>
#include <kernel/arch/amd64/driver/util.h>
#include <kernel/arch/amd64/interrupts.h>
@@ -16,18 +17,18 @@ static VfsReq *blocked_on = NULL;
enum {
- MAC = 0,
- TXSTATUS0 = 0x10,
- TXSTART0 = 0x20,
- RBSTART = 0x30,
- CMD = 0x37,
- CAPR = 0x38,
- CBR = 0x3A,
- INTRMASK = 0x3C,
- INTRSTATUS = 0x3E,
- TCR = 0x40,
- RCR = 0x44,
- CONFIG1 = 0x52,
+ Mac = 0,
+ TxStatus0 = 0x10,
+ TxStart0 = 0x20,
+ RbStart = 0x30,
+ Cmd = 0x37,
+ Capr = 0x38,
+ Cbr = 0x3A,
+ IntrMask = 0x3C,
+ IntrStatus = 0x3E,
+ Tcr = 0x40,
+ Rcr = 0x44,
+ Config1 = 0x52,
};
static uint16_t iobase;
@@ -40,10 +41,11 @@ static size_t rxpos;
#define txbuf_len 2048
static char txbuf[4][txbuf_len];
+static uint8_t mac[6];
static void rx_irq_enable(bool v) {
uint16_t mask = 1; /* rx ok */
- port_out16(iobase + INTRMASK, v ? mask : 0);
+ port_out16(iobase + IntrMask, v ? mask : 0);
}
void rtl8139_init(uint32_t bdf) {
@@ -57,15 +59,15 @@ void rtl8139_init(uint32_t bdf) {
pcicfg_w32(bdf, PCICFG_CMD, cmd);
- port_out8(iobase + CONFIG1, 0); /* power on */
+ port_out8(iobase + Config1, 0); /* power on */
- port_out8(iobase + CMD, 0x10); /* software reset */
- while (port_in8(iobase + CMD) & 0x10);
+ port_out8(iobase + Cmd, 0x10); /* software reset */
+ while (port_in8(iobase + Cmd) & 0x10);
assert((long)(void*)rxbuf <= 0xFFFFFFFF);
- port_out32(iobase + RBSTART, (long)(void*)rxbuf);
+ port_out32(iobase + RbStart, (long)(void*)rxbuf);
- port_out32(iobase + TCR, 0);
+ port_out32(iobase + Tcr, 0);
uint32_t rcr = 0;
// rcr |= 1 << 0; /* accept all packets */
@@ -74,17 +76,22 @@ void rtl8139_init(uint32_t bdf) {
rcr |= 1 << 3; /* accept broadcast */
rcr |= buflen_shift << 11;
rcr |= 7 << 13; /* no rx threshold, copy whole packets */
- port_out32(iobase + RCR, rcr);
+ port_out32(iobase + Rcr, rcr);
- port_out8(iobase + CMD, 0xC); /* enable RX TX */
+ port_out8(iobase + Cmd, 0xC); /* enable RX TX */
rx_irq_enable(false);
- vfs_root_register("/dev/eth", accept);
+ for (int i = 0; i < 6; i++) {
+ mac[i] = port_in8(iobase + Mac + i);
+ }
+ kprintf("%02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+
+ vfs_root_register("/dev/eth/", accept);
}
static void rtl8139_irq(void) {
- uint16_t status = port_in16(iobase + INTRSTATUS);
+ uint16_t status = port_in16(iobase + IntrStatus);
if (!(status & 1)) {
kprintf("bad rtl8139 status 0x%x\n", status);
panic_unimplemented();
@@ -93,21 +100,21 @@ static void rtl8139_irq(void) {
/* bit 0 of cmd - Rx Buffer Empty
* not a do while() because sometimes the bit is empty on IRQ. no clue why. */
- while (!(port_in8(iobase + CMD) & 1)) {
+ while (!(port_in8(iobase + Cmd) & 1)) {
if (!postqueue_pop(&blocked_on, accept)) {
rx_irq_enable(false);
break;
}
}
- //kprintf("rxpos %x cbr %x\n", rxpos, port_in16(iobase + CBR));
- port_out16(iobase + INTRSTATUS, status);
+ //kprintf("rxpos %x cbr %x\n", rxpos, port_in16(iobase + Cbr));
+ port_out16(iobase + IntrStatus, status);
}
static int try_rx(Proc *proc, void __user *dest, size_t dlen) {
uint16_t flags, size;
/* bit 0 - Rx Buffer Empty */
- if (port_in8(iobase + CMD) & 1) return WAIT;
+ if (port_in8(iobase + Cmd) & 1) return WAIT;
/* https://github.com/qemu/qemu/blob/04ddcda6a/hw/net/rtl8139.c#L1169 */
/* https://www.cs.usfca.edu/~cruse/cs326f04/RTL8139D_DataSheet.pdf page 12
@@ -136,7 +143,7 @@ static int try_rx(Proc *proc, void __user *dest, size_t dlen) {
rxpos = (rxpos + 3) & ~3;
while (rxpos >= rxbuf_baselen) rxpos -= rxbuf_baselen;
/* the device adds the 0x10 back, it's supposed to avoid overflow */
- port_out16(iobase + CAPR, rxpos - 0x10);
+ port_out16(iobase + Capr, rxpos - 0x10);
return size;
}
@@ -146,7 +153,7 @@ static int try_tx(Proc *proc, const void __user *src, size_t slen) {
if (slen > 0xFFF) return -1;
if (slen > txbuf_len) return -1;
- uint32_t status = port_in32(iobase + TXSTATUS0 + desc*4);
+ uint32_t status = port_in32(iobase + TxStatus0 + desc*4);
if (!(status & (1<<13))) {
/* can't (?) be caused (and thus, tested) on a vm */
kprintf("try_tx called with all descriptors full.");
@@ -157,24 +164,40 @@ static int try_tx(Proc *proc, const void __user *src, size_t slen) {
return -1;
}
assert((long)(void*)txbuf <= 0xFFFFFFFF);
- port_out32(iobase + TXSTART0 + desc*4, (long)(void*)txbuf[desc]);
- port_out32(iobase + TXSTATUS0 + desc*4, slen);
+ port_out32(iobase + TxStart0 + desc*4, (long)(void*)txbuf[desc]);
+ port_out32(iobase + TxStatus0 + desc*4, slen);
desc = (desc + 1) & 3;
return slen;
}
+enum {
+ HandleRoot,
+ HandleNet,
+};
+
static void accept(VfsReq *req) {
+ long ret;
+ long id = (long __force)req->id;
+
if (!req->caller) {
vfsreq_finish_short(req, -1);
return;
}
+
switch (req->type) {
- long ret;
- case VFSOP_OPEN:
- vfsreq_finish_short(req, req->input.len == 0 ? 0 : -1);
- break;
- case VFSOP_READ:
+ case VFSOP_OPEN:
+ if (reqpathcmp(req, "")) ret = HandleRoot;
+ else if (reqpathcmp(req, "net")) ret = HandleNet;
+ else ret = -ENOENT;
+ vfsreq_finish_short(req, ret);
+ break;
+ case VFSOP_READ:
+ if (id == HandleRoot) {
+ const char data[] = "net";
+ ret = req_readcopy(req, data, sizeof data);
+ vfsreq_finish_short(req, ret);
+ } else if (id == HandleNet) {
ret = try_rx(req->caller, req->output.buf, req->output.len);
if (ret == WAIT) {
postqueue_join(&blocked_on, req);
@@ -182,13 +205,18 @@ static void accept(VfsReq *req) {
} else {
vfsreq_finish_short(req, ret);
}
- break;
- case VFSOP_WRITE:
+ } else panic_invalid_state();
+ break;
+ case VFSOP_WRITE:
+ if (id == HandleNet) {
assert(!req->input.kern);
vfsreq_finish_short(req, try_tx(req->caller, req->input.buf, req->input.len));
- break;
- default:
- vfsreq_finish_short(req, -1);
- break;
+ } else {
+ vfsreq_finish_short(req, -ENOSYS);
+ }
+ break;
+ default:
+ vfsreq_finish_short(req, -1);
+ break;
}
}
diff --git a/src/kernel/arch/amd64/driver/util.h b/src/kernel/arch/amd64/driver/util.h
index c49b859..6fae977 100644
--- a/src/kernel/arch/amd64/driver/util.h
+++ b/src/kernel/arch/amd64/driver/util.h
@@ -1,5 +1,6 @@
#pragma once
#include <kernel/types.h>
+#include <shared/mem.h>
#include <shared/ring.h>
#include <stdbool.h>
#include <stddef.h>