Skip to content

Commit

Permalink
課題用リポジトリにファイルを追加
Browse files Browse the repository at this point in the history
  • Loading branch information
sgotand committed Jul 2, 2018
0 parents commit f57587e
Show file tree
Hide file tree
Showing 16 changed files with 772 additions and 0 deletions.
22 changes: 22 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -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.
70 changes: 70 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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) *~
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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を再起動してください。


Binary file added checker.a
Binary file not shown.
23 changes: 23 additions & 0 deletions checker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#define CHECK_LEVEL ((check_level)CHECK_STRICT)

#include <stdint.h>

// 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);
30 changes: 30 additions & 0 deletions desc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdint.h>
#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); }
47 changes: 47 additions & 0 deletions desc.h
Original file line number Diff line number Diff line change
@@ -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));


155 changes: 155 additions & 0 deletions init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>

#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); }
8 changes: 8 additions & 0 deletions init.h
Original file line number Diff line number Diff line change
@@ -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);
Loading

0 comments on commit f57587e

Please sign in to comment.