From c183ae40db5e81ed6d8f1b2926fef7c6725e72cd Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 20 Mar 2020 13:30:41 +0200 Subject: [PATCH] rtl8139: Add packet send --- drivers/net/rtl8139.c | 55 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 53f5195..1de97e1 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -2,6 +2,7 @@ #include "arch/amd64/hw/io.h" #include "drivers/pci/pci.h" #include "sys/assert.h" +#include "sys/string.h" #include "sys/debug.h" #include "sys/heap.h" #include "sys/attr.h" @@ -11,13 +12,18 @@ #define CR_RST (1 << 4) #define CR_RE (1 << 3) +#define CR_TE (1 << 2) #define CR_BUFE (1 << 0) #define IMR_ROK (1 << 0) #define IMR_RER (1 << 1) +#define IMR_TOK (1 << 2) +#define IMR_TER (1 << 3) #define ISR_ROK (1 << 0) #define ISR_RER (1 << 1) +#define ISR_TOK (1 << 2) +#define ISR_TER (1 << 3) #define RCR_WRAP (1 << 7) #define RCR_AR (1 << 4) @@ -27,6 +33,8 @@ #define RCR_AAP (1 << 0) // All #define REG_IDR(i) ((i)) +#define REG_TSD(i) ((i) * 4 + 0x10) +#define REG_TSAD(i) ((i) * 4 + 0x20) #define REG_RBSTART 0x30 #define REG_CAPR 0x38 #define REG_CBR 0x3A @@ -41,8 +49,11 @@ struct rtl8139 { struct pci_device *dev; struct netdev *net; + int free_txds; uintptr_t recv_buf_phys; + uintptr_t send_buf_pages[4]; uint16_t rx_pos; + size_t tx_pos; uint16_t iobase; }; @@ -57,10 +68,25 @@ static void rtl8139_reset(struct rtl8139 *rtl) { } static int rtl8139_netdev_send(struct netdev *net, const void *data, size_t len) { - // TODO - kdebug("%s: send stub:\n", net->name); - debug_dump(DEBUG_DEFAULT, data, len); - return -1; + struct rtl8139 *rtl = net->device; + _assert(rtl); + _assert((len & ~0xFFF) == 0); + + if (!rtl->free_txds) { + panic("No free TXDs\n"); + } + + uintptr_t page = rtl->send_buf_pages[rtl->tx_pos]; + void *tx_buf = (void *) MM_VIRTUALIZE(page); + + memcpy(tx_buf, data, len); + + outl(rtl->iobase + REG_TSAD(rtl->tx_pos), page & 0xFFFFFFFF); + outl(rtl->iobase + REG_TSD(rtl->tx_pos), len & 0xFFF); + rtl->tx_pos = (rtl->tx_pos + 1) % 4; + --rtl->free_txds; + + return 0; } static uint32_t rtl8139_irq(void *ctx) { @@ -88,6 +114,11 @@ static uint32_t rtl8139_irq(void *ctx) { ret = IRQ_HANDLED; outw(rtl->iobase + REG_ISR, ISR_ROK); + } else if (isr & ISR_TOK) { + ++rtl->free_txds; + + ret = IRQ_HANDLED; + outw(rtl->iobase + REG_ISR, ISR_TOK); } else { kinfo("???\n"); } @@ -109,6 +140,14 @@ static void rtl8139_init(struct pci_device *dev) { rtl->recv_buf_phys = amd64_phys_alloc_contiguous(3); _assert(rtl->recv_buf_phys != MM_NADDR); + // Allocate Tx pages + for (size_t i = 0; i < 4; ++i) { + rtl->send_buf_pages[i] = amd64_phys_alloc_page(); + _assert(rtl->send_buf_pages[i] != MM_NADDR); + } + rtl->free_txds = 4; + rtl->tx_pos = 0; + // Enable device bus mastering cmd = pci_config_read_dword(dev, PCI_CONFIG_CMD); cmd |= 1 << 2; @@ -141,14 +180,14 @@ static void rtl8139_init(struct pci_device *dev) { outl(rtl->iobase + REG_RBSTART, rtl->recv_buf_phys); // Unmask IRQs - outw(rtl->iobase + REG_IMR, IMR_ROK | IMR_RER); - outw(rtl->iobase + REG_ISR, 0); + outw(rtl->iobase + REG_IMR, IMR_ROK | IMR_RER | IMR_TOK | IMR_TER); // Set RCR to receive all outl(rtl->iobase + REG_RCR, RCR_WRAP | RCR_AB | RCR_APM | RCR_AAP | RCR_AM); - // Enable receiver - outb(rtl->iobase + REG_CR, CR_RE); + // Enable receiver and trasnmitter + outb(rtl->iobase + REG_CR, CR_RE | CR_TE); + outw(rtl->iobase + REG_ISR, 0); pci_add_irq(dev, rtl8139_irq, rtl); }