diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..9276d43 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,22 @@ +MIT License + +Copyright (c) 2018 Shotaro Gotanda, Masashi Ikarashi +https://github.com/progrunner17/e1000/blob/master/LICENSE.txt + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8e402f3 --- /dev/null +++ b/Makefile @@ -0,0 +1,70 @@ +CC = gcc +CFLAGS = -g -MMD -MP -Wall -Werror=implicit -pthread -std=gnu99 +SRCS = main.c init.c util.c mem.c reg.c desc.c +LIBS = checker.a +OBJS = $(SRCS:.c=.o) +DEPS= $(filter %.d, $(subst .o,.d, $(OBJS))) +TARGET = driver + + +TARGET_KEYWORD := I217 +TARGET_DEFAULT_DRIVER := e1000e +TARGET_PCI_BUS_ID:=$(if $(TARGET_PCI_BUS_ID),$(TARGET_PCI_BUS_ID),$(shell lspci -D | grep $(TARGET_KEYWORD) | cut -f 1 -d ' ' | head -n1)) +TARGET_PCI_VID_DID=$(shell lspci -n -s $(TARGET_PCI_BUS_ID) | cut -f 3 -d ' ') +TARGET_PCI_VID=$(shell echo $(TARGET_PCI_VID_DID) | cut -f 1 -d ':') +TARGET_PCI_DID=$(shell echo $(TARGET_PCI_VID_DID) | cut -f 2 -d ':') +TARGET_CURRENT_DRIVER=$(shell lspci -k -s $(TARGET_PCI_BUS_ID) | grep "Kernel driver in use:" | cut -f 2 -d ":" | tr -d " ") + +ARGS= + + + +default: $(TARGET) + +.PHONY: load restore run exec + +-include $(DEPS) + +run:load + trap '$(MAKE) restore;' INT ; $(MAKE) exec ; $(MAKE) restore; + +exec: $(TARGET) + sudo sh -c "echo 120 > /proc/sys/vm/nr_hugepages" + sudo ./$(TARGET) $(ARGS) + + +check: + @lspci -vvxxx -n -k -s $(TARGET_PCI_BUS_ID) + @echo " bus: $(TARGET_PCI_BUS_ID)" + @echo " vendor: $(TARGET_PCI_VID)" + @echo " device: $(TARGET_PCI_DID)" + @echo "driver current: $(TARGET_CURRENT_DRIVER)" + @echo " default: $(TARGET_DEFAULT_DRIVER)" + +load: +ifneq ($(shell lspci -v -s $(TARGET_PCI_BUS_ID) | grep $(TARGET_DEFAULT_DRIVER)),) + sudo modprobe uio_pci_generic + sudo sh -c "echo '$(TARGET_PCI_VID) $(TARGET_PCI_DID)' > /sys/bus/pci/drivers/uio_pci_generic/new_id" + sudo sh -c "echo -n $(TARGET_PCI_BUS_ID) > /sys/bus/pci/drivers/$(TARGET_CURRENT_DRIVER)/unbind" + sudo sh -c "echo -n $(TARGET_PCI_BUS_ID) > /sys/bus/pci/drivers/uio_pci_generic/bind" +endif + +restore: +ifeq ($(shell lspci -v -s $(TARGET_PCI_BUS_ID) | grep $(TARGET_DEFAULT_DRIVER)),) + sudo modprobe $(TARGET_DEFAULT_DRIVER) + sudo sh -c "echo -n $(TARGET_PCI_BUS_ID) > /sys/bus/pci/drivers/$(TARGET_CURRENT_DRIVER)/unbind" + sudo sh -c "echo -n $(TARGET_PCI_BUS_ID) > /sys/bus/pci/drivers/$(TARGET_DEFAULT_DRIVER)/bind" +endif + + +watch_irq: + watch -n1 "cat /proc/interrupts" + + + +$(TARGET): $(OBJS) $(LIBS) + $(CC) $(CFLAGS) -o $@ $^ + + +clean: + $(RM) $(TARGET) $(OBJS) $(DEPS) *~ diff --git a/README.md b/README.md new file mode 100644 index 0000000..f106a2a --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# e1000 + +e1000e向けのデバイスドライバ + +## 使用方法 +- `make run` + - プログラムの実行 +- `make check` + - デバイスの状態チェック +- `make clean` + +## PCに不調が出たら +`make check`で「driver current」と「default」がどちらもe1000eであることを確認してください +万が一「driver current」がuio_pci_genericとなっていた場合`make restore`を実行して下さい。 + +それでも直らない場合はPCを再起動してください。 + + diff --git a/checker.a b/checker.a new file mode 100644 index 0000000..c1804ec Binary files /dev/null and b/checker.a differ diff --git a/checker.h b/checker.h new file mode 100644 index 0000000..df9399c --- /dev/null +++ b/checker.h @@ -0,0 +1,23 @@ +#define CHECK_LEVEL ((check_level)CHECK_STRICT) + +#include + +// Define check level. +// When CHECK_NONE, these functions do nothing. +#define CHECK_STRICT 2 +#define CHECK_LOOSE 1 +#define CHECK_NONE 0 + +typedef int check_level; + + +void check_set_rqueue_head(check_level l, uint32_t val); +void check_set_tqueue_head(check_level l, uint32_t val); +void check_set_rqueue_tail(check_level l, uint32_t val); +void check_set_tqueue_tail(check_level l, uint32_t val); +void check_before_rqueue_enable(check_level l); +void check_before_tqueue_enable(check_level l); +void check_before_set_rdba(check_level l); +void check_before_set_tdba(check_level l); +void check_before_set_rdlen(check_level l); +void check_before_set_tdlen(check_level l); diff --git a/desc.c b/desc.c new file mode 100644 index 0000000..7f1d33a --- /dev/null +++ b/desc.c @@ -0,0 +1,30 @@ +#include +#include +#include "mem.h" +#define DANGER +#include "reg.h" +#include "desc.h" +#include "checker.h" + +uint64_t get_mac_addr(void) { + static uint64_t mac_addr = 0; + if (mac_addr == 0) { + uint32_t buf32; + buf32 = read_reg_wrapper(RAL_OFFSET); + mac_addr |= buf32; + buf32 = read_reg_wrapper(RAH_OFFSET); + mac_addr |= ((uint64_t)buf32 & 0xFFFFll) << 32; + } + return mac_addr; +} + +void enable_receive(void) { + check_before_rqueue_enable(CHECK_LEVEL); + set_flags((uint32_t)RCTL_OFFSET, (uint32_t)RCTL_EN); +} +void enable_transmit(void) { + check_before_tqueue_enable(CHECK_LEVEL); + set_flags((uint32_t)TCTL_OFFSET, (uint32_t)TCTL_EN); +} +void disable_receive(void) { clear_flags((uint32_t)RCTL_OFFSET, (uint32_t)RCTL_EN); } +void disable_transmit(void) { clear_flags((uint32_t)TCTL_OFFSET, (uint32_t)TCTL_EN); } diff --git a/desc.h b/desc.h new file mode 100644 index 0000000..15622c8 --- /dev/null +++ b/desc.h @@ -0,0 +1,47 @@ +#pragma once +#include "mem.h" +uint64_t get_mac_addr(void); +void enable_receive(void); +void enable_transmit(void); +void disable_receive(void); +void disable_transmit(void); + +/* Receive Descriptor +** Legacy Rx Descriptor (RCTL.DTYPE=00b,RFCTL.EXSTEN = 0b) +** see spec p23 3.2.4 Receive Descriptor Format +** 命名規則は基本的にはspec依存 +** 例外 +** buffer address -> addr +** packet checksum -> csm +** vlan tag -> vtag +*/ +typedef struct rdesc *Rdesc; +struct rdesc { + phys_addr addr; + uint16_t length; + uint16_t csm; + uint8_t status; + uint8_t errors; + uint16_t vtag; +}__attribute__((packed)); + +/* Transmit Descriptor +** Legacy Transmit Descriptor (デスクリプタのdext = 1bで設定) +** こちらの命名規則も基本的にはspec準拠 +** その結果ステータスがstaとなっていたりする。(Rxではstatus) +** reserved はstaにまとめた。 +** +*/ + +typedef struct tdesc *Tdesc; +struct tdesc { + phys_addr addr; + uint16_t length; + uint8_t cso; + uint8_t cmd; + uint8_t sta; + uint8_t css; + uint16_t special; +}__attribute__((packed)); + + diff --git a/init.c b/init.c new file mode 100644 index 0000000..53c3553 --- /dev/null +++ b/init.c @@ -0,0 +1,155 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "init.h" +#include "util.h" +#define DANGER +#include "reg.h" +#undef DANGER + +void init_pci() { + int uiofd, configfd, csrfd; + uint16_t buf16; + + uiofd = open("/dev/uio0", O_RDONLY); + if (uiofd < 0) { + perror("uio open:"); + panic(""); + } + print_log("open /dev/uio0"); + + configfd = open("/sys/class/uio/uio0/device/config", O_RDWR); + if (configfd < 0) { + perror("config open:"); + panic(""); + } + print_log("[init_pci] open /sys/class/uio/uio0/device/config"); + + // PCICMD see chipset c220 spec p365 + // Bus Master Enable, Memory Space Enable, I/O Space Enable + pread(configfd, &buf16, 2, 0x04); + buf16 |= 0b111; + pwrite(configfd, &buf16, 2, 0x04); + print_log("config PCIe CTRL register"); + + csrfd = open("/sys/class/uio/uio0/device/resource0", O_RDWR); + if (csrfd < 0) { + perror("open"); + panic(""); + } + print_log("[init_pci] open resource0"); + + // Internal registers and memories region is 128KB + // see spec Table 13-1 PCI Base Address Registers (p271) + void *base_addr = + mmap(NULL, 1 << 17, PROT_READ | PROT_WRITE, MAP_SHARED, csrfd, 0); + if (base_addr == MAP_FAILED) { + perror("mmap"); + panic(""); + } + set_regspace(base_addr); + close(csrfd); + print_log("[init_pci] map Internal registers and memories(resource0)"); + print_log("[init_pci] regspace = %p", base_addr); +} + +void init_dev(void) { + uint16_t buf16; + + // Disable Interrupts; + // see spec 14.4 Interrupts Duraing Initialization + // cf. spec 13.3.32 Interrupt Mask Clear Register + set_flags(IMC_OFFSET, 0xFFFFFFFF); + + print_log("[init_dev] Disable interrupts"); + usleep(10000); + print_log("wait 10ms"); + + // Global reset + // see spec chapter 14.5(p490) + // CHECK: are these really Global reset? + set_flags(CTRL_OFFSET, CTRL_LRST | CTRL_RST | CTRL_PHY_RST); + print_log("[init_dev] Global rest(Link reset & Device reset & PHY reset)"); + + // Disable Interrupts again; + // see spec 14.4 Interrupts Duraing Initialization + set_flags(IMC_OFFSET, 0xFFFFFFFF); + print_log("[init_dev] Disable interrupt(again)"); + + // General Configuration + // see spec 14.5 Global Reset and General Configuration + // there seems to be device specific setting (ignore them here) + // No use of XOFF flow control write 0 to FCAL, FCAH, FCT + write_reg(FCAL_OFFSET, 0); + write_reg(FCAH_OFFSET, 0); + write_reg(FCT_OFFSET, 0); + print_log("[init_dev] Configure XOFF Flow control(no use)"); + + // Setup PHY and Link + // see spec 14.8 Link Setup Mechanisms and Control/Status Bit Summary + + // PHY Initialization + // see spec 14.8.1 PHY Initialization + // see spec 13.3.8 MDI Control Register + buf16 = read_mdic(MDIC_PCTRL_POFFSET); + buf16 |= MDIC_PCTRL_PHYRST; + write_mdic(MDIC_PCTRL_POFFSET, buf16); + print_log("[init_dev] PHY RESET from MDI"); + + // MAC/PHY Link Setup + // see spec 14.8.2 MAC/PHY Link Setup + clear_flags(CTRL_OFFSET, CTRL_FRCSPD | CTRL_FRCDPLX); + set_flags(CTRL_OFFSET, CTRL_SLU | CTRL_RFCE); + print_log("[init_dev] MAC/PHY Link Setup"); + + // Initialize all statistical counters + // see spec 13.9 Statistics Registers + // dee spec 14.10 Initialization of Statistics + usleep(1000); + for (int offset = 0x04000; offset <= 0x04124; offset += 0x04) { + read_reg(offset); + } + print_log("[init_dev] reset statistical registers"); +} + +void init_receive(void) { + // see spec 14.6 Receive Initialization + + // MTA + // see spec 13.4.1 Multicast Table Array + for (int i = 0; i < MTA_LEN; i++) { + write_reg(MTA_OFFSET + i * 4, 0); + } + print_log("[Receive] Reset Multicast Table Array"); + + // RCTL + // see spec 13.3.34 Receive Control Register + // set receive buffer size to 2KB & disable VFE + clear_flags(RCTL_OFFSET, RCTL_BSIZE_MASK | RCTL_BSEX | RCTL_VFE); + set_flags(RCTL_OFFSET, RCTL_BSIZE_2K | RCTL_UPE | RCTL_MPE |RCTL_LPE); + print_log("[Receive] program RCTL"); +} + +void init_transmit(void) { + // TXDCTL values GRAN=1 WTHRESH=1(TXDCTL[21:16]) othes=0 + write_reg(TXDCTL_OFFSET, TXDCTL_GRAN | (1 << 16)); + print_log("[Transmit] program TXDCTL"); + + // TCTL CT=0x0F(TCTL[11:4]) COLD=0x03F(TCTL[21:12]) PSP=1b EN =1b others = 0 + write_reg(TCTL_OFFSET, (0x0F << 4) | (0x03F << 12) | TCTL_PSP); + print_log("[Transmit] program TCTL"); + + // Program TARC if use multi Txqueues + // TODO: + + // Program TIPG + // TODO: +} + +void disable_interrupts(uint32_t flags) { set_flags(IMC_OFFSET, flags); } +void enable_interrupts(uint32_t flags) { set_flags(IMS_OFFSET, flags); } diff --git a/init.h b/init.h new file mode 100644 index 0000000..a620bee --- /dev/null +++ b/init.h @@ -0,0 +1,8 @@ +#pragma once +// pciを初期化 +void init_pci(void); +void init_dev(void); +void init_receive(void); +void init_transmit(void); +void enable_interrupts(uint32_t); +void disable_interrupts(uint32_t); diff --git a/main.c b/main.c new file mode 100644 index 0000000..56eeb76 --- /dev/null +++ b/main.c @@ -0,0 +1,47 @@ +#include +#include +#include +#include +#include "desc.h" +#include "init.h" +#include "mem.h" +#include "reg.h" +#include "util.h" + +int main(int argc, char const *argv[]) { + init_pci(); + init_dev(); + init_mem(1024 * 1024 * 2); + + void *memory_base_virt = get_virt_ptr(); + size_t memory_base_phys = get_phys_ptr(); + + // initialize receive + print_log("initialize receive"); + init_receive(); + // TODO: set receive descriptor ring base address and length + + // receive buffer size is set to 2KB in init_receive + // TODO: allocate memory to each receivev descriptors + + enable_receive(); + + // initialize transmit + print_log("initialize transmit"); + init_transmit(); + // TODO: set transmit descriptor ring base address and length + + // TODO: allocate memory to each transmit descriptors + // this can be done on transmit + + enable_transmit(); + print_log("enable interrupts"); + enable_interrupts(0xFFFFFFFF); + usleep(1000); + + // TODO: program data communicaton + + // wait until NIC send packet physically + sleep(2); + return 0; +} diff --git a/mem.c b/mem.c new file mode 100644 index 0000000..5d2796a --- /dev/null +++ b/mem.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include +#include + +#include "mem.h" +#include "util.h" + +size_t v2p(size_t vaddr); +static virt_addr _virt; +static phys_addr _phys; +static size_t _req_size = 0; +static size_t _act_size = 0; + +phys_addr get_phys_ptr() { return _phys; } + +virt_addr get_virt_ptr() { return _virt; } + +void init_mem(size_t size) { + _req_size = size; + + if (_req_size > 0) { + _act_size = 2 * 1024 * 1024; + assert(_req_size <= _act_size); + _virt = + mmap(NULL, _act_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_HUGETLB | MAP_ANONYMOUS | MAP_POPULATE, 0, 0); + if (_virt == MAP_FAILED) { + perror("page alloc:"); + panic(""); + } + _phys = v2p((size_t)_virt); + } else { + _virt = 0; + _phys = 0; + } + bzero(get_virt_ptr(), _req_size); +} + +size_t v2p(size_t vaddr) { + FILE *pagemap; + size_t paddr = 0; + ssize_t offset = (vaddr / sysconf(_SC_PAGESIZE)) * sizeof(uint64_t); + uint64_t e; + + // https://www.kernel.org/doc/Documentation/vm/pagemap.txt + if ((pagemap = fopen("/proc/self/pagemap", "r"))) { + if (lseek(fileno(pagemap), offset, SEEK_SET) == offset) { + if (fread(&e, sizeof(uint64_t), 1, pagemap)) { + if (e & (1ULL << 63)) { // page present ? + paddr = e & ((1ULL << 55) - 1); // pfn mask + paddr = paddr * sysconf(_SC_PAGESIZE); + // add offset within page + paddr = paddr | (vaddr & (sysconf(_SC_PAGESIZE) - 1)); + } + } + } + fclose(pagemap); + } + return paddr; +} diff --git a/mem.h b/mem.h new file mode 100644 index 0000000..e5416dc --- /dev/null +++ b/mem.h @@ -0,0 +1,8 @@ +#pragma once + +typedef size_t phys_addr; +typedef void *virt_addr; + +void init_mem(size_t size); +phys_addr get_phys_ptr(); +virt_addr get_virt_ptr(); diff --git a/reg.c b/reg.c new file mode 100644 index 0000000..fd7c502 --- /dev/null +++ b/reg.c @@ -0,0 +1,117 @@ +#include +#include +#include +#define DANGER +#include "reg.h" +#include "checker.h" +#include "util.h" + +static void *regspace; + + +void set_regspace(void *addr) { regspace = addr; } + +uint32_t read_reg_wrapper(uint32_t off){ + switch(off){ + case RDBAL_OFFSET: + case RDBAH_OFFSET: + case RDLEN_OFFSET: + case RDH_OFFSET: + case RDT_OFFSET: + case RAL_OFFSET: + case RAH_OFFSET: + case TDBAL_OFFSET: + case TDBAH_OFFSET: + case TDLEN_OFFSET: + case TDH_OFFSET: + case TDT_OFFSET:break; + default:panic("this register is not allowed to access"); + } + return read_reg(off); +} +void write_reg_wrapper(uint32_t off, uint32_t val){ + switch(off){ + case RDBAL_OFFSET: + case RDBAH_OFFSET: + check_before_set_rdba(CHECK_LEVEL); + break; + case RDLEN_OFFSET: + check_before_set_rdlen(CHECK_LEVEL); + break; + case RDH_OFFSET: + check_set_rqueue_head(CHECK_LEVEL, val); + break; + case RDT_OFFSET: + check_set_rqueue_tail(CHECK_LEVEL, val); + break; + case TDBAL_OFFSET: + case TDBAH_OFFSET: + check_before_set_tdba(CHECK_LEVEL); + break; + case TDLEN_OFFSET: + check_before_set_tdlen(CHECK_LEVEL); + break; + case TDH_OFFSET: + check_set_tqueue_head(CHECK_LEVEL, val); + break; + case TDT_OFFSET: + check_set_tqueue_tail(CHECK_LEVEL, val);break; + default:panic("this register is not allowed to access"); + } + write_reg(off,val); +} + + + +void write_reg(uint32_t off, uint32_t val) { + ((uint32_t *)regspace)[off / 4] = val; +} +uint32_t read_reg(uint32_t off) { + return ((uint32_t *)regspace)[off / 4]; +} + +void set_flags(uint32_t off, uint32_t flags) { + uint32_t buf32; + buf32 = read_reg(off); + buf32 |= flags; + write_reg(off, buf32); +} +void clear_flags(uint32_t off, uint32_t flags) { + uint32_t buf32; + buf32 = read_reg(off); + buf32 &= ~flags; + write_reg(off, buf32); +} + +void write_mdic(uint32_t page, uint16_t val) { + uint32_t buf = 0; + buf |= val; + buf |= (page & ((1 << 17) - 1)) << 16; // set Page addr + buf |= 1 << 21; + buf |= 1 << 26; // OP = Write + buf = 0; + write_reg(MDIC_OFFSET, buf); + // Wait until ready + while (1) { + buf = read_reg(MDIC_OFFSET); + if (buf & (1 << 28)) break; + } +} + + + +uint16_t read_mdic(uint32_t page) { + uint32_t buf = 0; + buf |= (page & ((1 << 17) - 1)) << 16; // set Page addr + buf |= 1 << 21; + buf |= 1 << 27; // OP = Read + write_reg(MDIC_OFFSET, buf); + // Wait until ready + buf = 0; + while (1) { + buf = read_reg(MDIC_OFFSET); + if (buf & (1 << 28)) break; + } + return (uint16_t)(buf & 0xFFFF); + +} diff --git a/reg.h b/reg.h new file mode 100644 index 0000000..f3dc5fa --- /dev/null +++ b/reg.h @@ -0,0 +1,102 @@ +#pragma once +#include + + + + +//===========General========================== +#define CTRL_OFFSET 0x0000 +#define CTRL_LRST (1 << 3) +#define CTRL_SLU (1 << 6) +#define CTRL_FRCSPD (1 << 11) +#define CTRL_FRCDPLX (1 << 12) +#define CTRL_RST (1 << 26) +#define CTRL_RFCE (1 << 27) +#define CTRL_TFCE (1 << 28) +#define CTRL_PHY_RST (1 << 31) +#define STATUS_OFFSET 0x0008 + +//================MDIC======================= +// P means PAGE +#define MDIC_OFFSET 0x0020 +#define MDIC_PCTRL_POFFSET 0x00 +// Auto Negotiation Enable +#define MDIC_PCTRL_ANEN (1 << 12) +// Enable Loopback +#define MDIC_PCTRL_ENLB (1 << 14) +// PHY Reset +#define MDIC_PCTRL_PHYRST (1 << 15) + +//================Flow Control================ +#define FCAL_OFFSET 0x0028 +#define FCAH_OFFSET 0x002C +#define FCT_OFFSET 0x0030 +#define FCTTV_OFFSET 0x0170 + +//================Interrupt=================== +#define IMS_OFFSET 0x00D0 +#define IMS_RXT (1 << 7) +#define IMS_RXO (1 << 6) +#define IMS_RXDMT (1 << 4) +#define IMS_RXSEQ (1 << 3) +#define IMC_OFFSET 0x00D8 + +//================Receive===================== +#define RCTL_OFFSET 0x0100 +#define RCTL_EN (1 << 1) +#define RCTL_SBP (1 << 2) // Store Bad Packet +#define RCTL_UPE (1 << 3) +#define RCTL_MPE (1 << 4) +#define RCTL_LPE (1 << 5) +#define RCTL_DTYPE_MASK (0b11 << 10) +#define RCTL_DTYPE_LEGACY (0b00 << 10) +#define RCTL_DTYPE_PS (0b01 << 10) +#define RCTL_BSIZE_MASK (0b11 << 16) +#define RCTL_BSIZE_2K (0b00 << 16) +#define RCTL_BSIZE_1K (0b01 << 16) +#define RCTL_VFE (1 << 18) // VLAN Filter Enable +#define RCTL_BSEX (1 << 25) + +#define RDBAL_OFFSET 0x2800 +#define RDBAH_OFFSET 0x2804 +#define RDLEN_OFFSET 0x2808 +#define RDH_OFFSET 0x2810 +#define RDT_OFFSET 0x2818 +#define RDTR_OFFSET 0x2820 +#define RXDCTL_OFFSET 0x2828 + +//================Transmit=================== +#define TCTL_OFFSET 0x0400 +#define TCTL_EN (1 << 1) +#define TCTL_PSP (1 << 3) +#define TDBAL_OFFSET 0x3800 +#define TDBAH_OFFSET 0x3804 +#define TDLEN_OFFSET 0x3808 +#define TDH_OFFSET 0x3810 +#define TDT_OFFSET 0x3818 +#define TXDCTL_OFFSET 0x3828 +#define TXDCTL_GRAN (1 << 24) +#define TIDV_OFFSET 0x3820 + +//================Filter Registers============ +#define MTA_OFFSET 0x5200 +#define MTA_LEN 128 +#define RAL_OFFSET 0x5400 +#define RAH_OFFSET 0x5404 + + +#ifdef DANGER +void set_regspace(void *addr); + +uint32_t read_reg(uint32_t off); +void write_reg(uint32_t off, uint32_t val); + +void set_flags(uint32_t off, uint32_t val); +void clear_flags(uint32_t off, uint32_t val); + +uint16_t read_mdic(uint32_t poff); +void write_mdic(uint32_t poff, uint16_t val); +#endif + +uint32_t read_reg_wrapper(uint32_t off); +void write_reg_wrapper(uint32_t off, uint32_t val); \ No newline at end of file diff --git a/util.c b/util.c new file mode 100644 index 0000000..0967a23 --- /dev/null +++ b/util.c @@ -0,0 +1,58 @@ +#include +#include +#include + +#define DANGER +#include "reg.h" + +#include "util.h" + +#define DUMPREG(X) {X ## _OFFSET, #X} +struct { + uint32_t offset; + const char *name; +} dump_regs[] = { + DUMPREG(CTRL), + DUMPREG(STATUS), + DUMPREG(RCTL), + DUMPREG(RDBAL), + DUMPREG(RDBAH), + DUMPREG(RDLEN), + DUMPREG(RDH), + DUMPREG(RDT), + DUMPREG(RDTR), + DUMPREG(RXDCTL), + DUMPREG(RAL), + DUMPREG(RAH), + DUMPREG(TCTL), + DUMPREG(TDBAL), + DUMPREG(TDBAH), + DUMPREG(TDLEN), + DUMPREG(TDH), + DUMPREG(TDT), + DUMPREG(TXDCTL), + DUMPREG(TIDV), +}; +#undef DUMPREG + +void dump_registers() { + for(size_t i=0; i