diff options
author | dzwdz | 2022-08-21 16:02:38 +0200 |
---|---|---|
committer | dzwdz | 2022-08-21 16:02:38 +0200 |
commit | dc5098f83ac55722744a97d2950f50ef2a221f1a (patch) | |
tree | b9f4f0f1172cb75abec3e355d4e7e72ebd1475ac /src/kernel/arch/amd64/driver | |
parent | 2c3df5122edc3aaee5f8d3776a7d296310a5021e (diff) |
amd64/rtl8139: fix incorrect ring buffer wrapping reads
I was reading from the buffer as if the WRAP flag was enabled, but it
actually isn't supported with a 64K buffer.
Besides, if it worked correctly, then the code for updating the ring
position would land in the wrong place, because it didn't take WARP
into account.
Diffstat (limited to 'src/kernel/arch/amd64/driver')
-rw-r--r-- | src/kernel/arch/amd64/driver/rtl8139.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c index e50fb63..fd7717f 100644 --- a/src/kernel/arch/amd64/driver/rtl8139.c +++ b/src/kernel/arch/amd64/driver/rtl8139.c @@ -32,7 +32,8 @@ static uint16_t iobase; #define buflen_shift 3 #define rxbuf_baselen ((8 * 1024) << buflen_shift) -static char rxbuf[rxbuf_baselen + 16 + 1500]; +/* the +16 is apparently required for... something */ +static char rxbuf[rxbuf_baselen + 16]; static size_t rxpos; #define txbuf_len 2048 @@ -68,7 +69,6 @@ void rtl8139_init(uint32_t bdf) { rcr |= 1 << 1; /* accept packets with our mac */ rcr |= 1 << 2; /* accept multicast */ rcr |= 1 << 3; /* accept broadcast */ - rcr |= 1 << 7; /* WARP */ rcr |= buflen_shift << 11; rcr |= 7 << 13; /* no rx threshold, copy whole packets */ port_out32(iobase + RCR, rcr); @@ -126,7 +126,13 @@ static int try_rx(struct pagedir *pages, void __user *dest, size_t dlen) { // kprintf("packet size 0x%x, flags 0x%x, rxpos %x\n", size, flags, rxpos - 4); if (dlen > size) dlen = size; - virt_cpy_to(pages, dest, rxbuf + rxpos, dlen); + if (rxpos + dlen <= rxbuf_baselen) { + virt_cpy_to(pages, dest, rxbuf + rxpos, dlen); + } else { + size_t chunk = rxbuf_baselen - rxpos; + virt_cpy_to(pages, dest, rxbuf + rxpos, chunk); + virt_cpy_to(pages, dest + chunk, rxbuf, dlen - chunk); + } rxpos += size; rxpos = (rxpos + 3) & ~3; |