|
| 1 | +#include <arch/riscv64/insns.h> |
| 2 | + |
| 3 | +#include <drivers/rtl8139.h> |
| 4 | + |
| 5 | +#include <mm/paging.h> |
| 6 | +#include <physical.h> |
| 7 | +#include <print.h> |
| 8 | + |
| 9 | +#define READ_U8(addr, off) physical_read_u8(paddr_of_bits(addr + off)) |
| 10 | +#define WRITE_U8(addr, off, value) physical_write_u8(paddr_of_bits(addr + off), value) |
| 11 | + |
| 12 | +#define READ_U16(addr, off) physical_read_u16le(paddr_of_bits(addr + off)) |
| 13 | +#define WRITE_U16(addr, off, value) physical_write_u16le(paddr_of_bits(addr + off), value) |
| 14 | + |
| 15 | +#define READ_U32(addr, off) physical_read_u32le(paddr_of_bits(addr + off)) |
| 16 | +#define WRITE_U32(addr, off, value) physical_write_u32le(paddr_of_bits(addr + off), value) |
| 17 | + |
| 18 | +#define READ_REG(reg) READ_U8(g_regs_addr, reg) |
| 19 | +#define WRITE_REG(reg, value) WRITE_U8(g_regs_addr, reg, value) |
| 20 | + |
| 21 | +#define READ_REG_32(reg) READ_U32(g_regs_addr, reg) |
| 22 | +#define WRITE_REG_32(reg, value) WRITE_U32(g_regs_addr, reg, value) |
| 23 | + |
| 24 | +#define REG_TSADn(N) (0x20 + N * 4) |
| 25 | +#define REG_TSDn(N) (0x10 + N * 4) |
| 26 | + |
| 27 | +enum RTL8139_REGS { |
| 28 | + REG_COM = 0x37, |
| 29 | + REG_TCR = 0x40, |
| 30 | + REG_CONFIG1 = 0x52 |
| 31 | +}; |
| 32 | + |
| 33 | +enum RTL8139_CONST { |
| 34 | + TSD_TOK = (1 << 15), |
| 35 | + TSD_OWN = (1 << 13), |
| 36 | + |
| 37 | + COM_RST = (1 << 4), |
| 38 | + COM_RE = (1 << 3), |
| 39 | + COM_TE = (1 << 2) |
| 40 | +}; |
| 41 | + |
| 42 | + |
| 43 | +#define REG_IDR0 0x0 |
| 44 | +#define REG_IDR4 0x4 |
| 45 | + |
| 46 | + |
| 47 | +#define TX_BUFF_SIZE 0x1700 |
| 48 | + |
| 49 | +u8 rtl8139_tbuff[4][TX_BUFF_SIZE] __attribute__((aligned(256))); |
| 50 | + |
| 51 | +u8 mac_addr[6]; |
| 52 | + |
| 53 | +u64 g_regs_addr; |
| 54 | +u64 g_cur_buf = 0; |
| 55 | + |
| 56 | + |
| 57 | +bool rtl8139_send_packet(u8 *buffer, u32 len) { |
| 58 | + u32 phys_buffer = (u32) walkaddr((uaddr) (&rtl8139_tbuff[0])); |
| 59 | + u64 i; |
| 60 | + |
| 61 | + for (i=0; i<len; ++i) { |
| 62 | + rtl8139_tbuff[0][i] = buffer[i]; |
| 63 | + } |
| 64 | + |
| 65 | + if ((READ_REG_32(REG_TSDn(g_cur_buf)) & TSD_OWN) == 0) { |
| 66 | + return false; |
| 67 | + } |
| 68 | + |
| 69 | + sfence_vma(); |
| 70 | + WRITE_REG_32(REG_TSADn(g_cur_buf), phys_buffer); |
| 71 | + WRITE_REG_32(REG_TSDn(g_cur_buf), len); |
| 72 | + |
| 73 | + ++g_cur_buf; |
| 74 | + return true; |
| 75 | +} |
| 76 | + |
| 77 | +bool eth_send_packet(u8 *buffer, u32 len) { |
| 78 | + u8 buf[0x100]; |
| 79 | + u64 i; |
| 80 | + |
| 81 | + for (i=0; i<6; ++i) { |
| 82 | + buf[i] = 0xff; |
| 83 | + buf[i + 6] = mac_addr[i]; |
| 84 | + } |
| 85 | + buf[12] = 0x08; |
| 86 | + buf[13] = 0x00; |
| 87 | + |
| 88 | + for (i=0; i<len; ++i) { |
| 89 | + buf[i + 14] = buffer[i]; |
| 90 | + } |
| 91 | + for (i=len; i<64; ++i) { |
| 92 | + buf[i + 14] = 0; |
| 93 | + } |
| 94 | + if (len < 64) len = 64; |
| 95 | + |
| 96 | + return rtl8139_send_packet(buf, len + 13); |
| 97 | +} |
| 98 | + |
| 99 | + |
| 100 | +void read_mac(u8 * mac) { |
| 101 | + u8 i; |
| 102 | + |
| 103 | + for (i=0; i<6; ++i) |
| 104 | + mac[i] = READ_REG(i); |
| 105 | +} |
| 106 | + |
| 107 | + |
| 108 | +void rtl8139_test() { |
| 109 | + eth_send_packet((u8*) "yellow submarine", 16); |
| 110 | + |
| 111 | + assert(READ_REG_32(REG_TSADn(0)) != 0); |
| 112 | + assert((READ_REG_32(REG_TSDn(0)) & TSD_TOK) != 0); |
| 113 | +} |
| 114 | + |
| 115 | + |
| 116 | +void rtl8139_init(u64 pci_device) { |
| 117 | + print("initializing rtl8139"); |
| 118 | + |
| 119 | + u32 reg_addr = 0x40000000; |
| 120 | + g_regs_addr = reg_addr; |
| 121 | + |
| 122 | + /* TODO: Maybe move PCI init to pci.c? */ |
| 123 | + |
| 124 | + /* Setup BAR for MMIO - we just pick a nice number for now */ |
| 125 | + WRITE_U32(pci_device,0x14,reg_addr); |
| 126 | + |
| 127 | + /* Enable memory mapped regs */ |
| 128 | + u8 cmd = READ_U8(pci_device, 0x4); |
| 129 | + WRITE_U8(pci_device,0x4,cmd | 0x6); |
| 130 | + |
| 131 | + WRITE_REG(REG_CONFIG1, 0); |
| 132 | + |
| 133 | + WRITE_REG(REG_COM, COM_RST); |
| 134 | + while (READ_REG(REG_COM) & COM_RST) ; |
| 135 | + WRITE_REG(REG_COM, COM_RE | COM_TE); |
| 136 | + |
| 137 | + read_mac(mac_addr); |
| 138 | + rtl8139_test(); |
| 139 | +} |
0 commit comments