From 80839982e9983c6ccadbf57a44e60eeb0e535421 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Sat, 4 May 2024 20:26:13 +0200 Subject: kernel/rtl8139: prepare for /dev/eth/mac --- src/cmd/init/init.c | 4 +- src/kernel/arch/amd64/driver/rtl8139.c | 110 +++++++++++++++++++++------------ src/kernel/arch/amd64/driver/util.h | 1 + 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 #include #include #include @@ -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 +#include #include #include #include -- cgit v1.2.3