Kill lwip stuff; add back in native rtl driver
Now with actual working stuff.
This commit is contained in:
parent
50824abdec
commit
b824abf250
1
contrib/netif/.gitignore
vendored
1
contrib/netif/.gitignore
vendored
@ -1 +0,0 @@
|
||||
lwip*
|
@ -1,72 +0,0 @@
|
||||
CC = i686-pc-toaru-gcc
|
||||
LD = i686-pc-toaru-ld
|
||||
|
||||
CFLAGS = -O2 -std=c99
|
||||
CFLAGS += -finline-functions -ffreestanding
|
||||
CFLAGS += -Wall -Wextra -Wno-unused-function -Wno-unused-parameter
|
||||
CFLAGS += -pedantic -fno-omit-frame-pointer
|
||||
CFLAGS += -D_KERNEL_
|
||||
|
||||
LWIPDIR=./lwip-STABLE-1_4_1/src
|
||||
|
||||
LWIPARCH=.
|
||||
|
||||
KERNEL_HEADERS = -I../../kernel/include
|
||||
LWIP_HEADERS = -I$(LWIPDIR)/include
|
||||
LWIP_HEADERS += -I$(LWIPARCH)/include
|
||||
LWIP_HEADERS += -I$(LWIPARCH)/include/arch
|
||||
LWIP_HEADERS += -I$(LWIPDIR)/include/ipv4
|
||||
|
||||
COREFILES=$(LWIPDIR)/core/mem.c \
|
||||
$(LWIPDIR)/core/memp.c \
|
||||
$(LWIPDIR)/core/netif.c \
|
||||
$(LWIPDIR)/core/pbuf.c \
|
||||
$(LWIPDIR)/core/raw.c \
|
||||
$(LWIPDIR)/core/stats.c \
|
||||
$(LWIPDIR)/core/sys.c \
|
||||
$(LWIPDIR)/core/tcp.c \
|
||||
$(LWIPDIR)/core/tcp_in.c \
|
||||
$(LWIPDIR)/core/tcp_out.c \
|
||||
$(LWIPDIR)/core/udp.c \
|
||||
$(LWIPDIR)/core/dns.c \
|
||||
$(LWIPDIR)/core/dhcp.c \
|
||||
$(LWIPDIR)/core/timers.c \
|
||||
$(LWIPDIR)/core/init.c
|
||||
|
||||
CORE4FILES=$(LWIPDIR)/core/ipv4/icmp.c \
|
||||
$(LWIPDIR)/core/ipv4/ip.c \
|
||||
$(LWIPDIR)/core/ipv4/inet.c \
|
||||
$(LWIPDIR)/core/ipv4/ip_addr.c \
|
||||
$(LWIPDIR)/core/ipv4/ip_frag.c \
|
||||
$(LWIPDIR)/core/ipv4/inet_chksum.c
|
||||
|
||||
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/err.c \
|
||||
$(LWIPDIR)/api/netbuf.c $(LWIPDIR)/api/netdb.c $(LWIPDIR)/api/netifapi.c \
|
||||
$(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/tcpip.c
|
||||
|
||||
NETIFFILES=$(LWIPDIR)/netif/etharp.c
|
||||
|
||||
LWIPFILES=$(COREFILES) $(CORE4FILES) $(APIFILES) $(NETIFFILES)
|
||||
|
||||
MODULELD = -T ../../modules/link.ld
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: netif.ko rtl8139.ko
|
||||
|
||||
LWIPFILESW=$(wildcard $(LWIPFILES))
|
||||
LWIPOBJS=$(LWIPFILESW:.c=.o)
|
||||
|
||||
%.o: %.c
|
||||
${CC} ${MODULELD} ${KERNEL_HEADERS} ${LWIP_HEADERS} -nostdlib ${CFLAGS} -c -o $@ $(<:.o=.c)
|
||||
|
||||
netif.ko: ${LWIPOBJS} netif.o
|
||||
${LD} -r -o $@ $^
|
||||
|
||||
rtl8139.ko: rtl8139.o
|
||||
${LD} -r -o $@ $^
|
||||
|
||||
clean:
|
||||
rm -f netif.ko
|
||||
rm -f rtl8139.ko
|
||||
rm -f ${LWIPOBJS}
|
@ -1,48 +0,0 @@
|
||||
#ifndef __ARCH_CC_H__
|
||||
#define __ARCH_CC_H__
|
||||
|
||||
#include <system.h>
|
||||
#include <logging.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define LWIP_TIMEVAL_PRIVATE 0
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
|
||||
typedef uint8_t u8_t;
|
||||
typedef int8_t s8_t;
|
||||
typedef uint16_t u16_t;
|
||||
typedef int16_t s16_t;
|
||||
typedef uint32_t u32_t;
|
||||
typedef int32_t s32_t;
|
||||
typedef uintptr_t mem_ptr_t;
|
||||
|
||||
#define X8_F "2x"
|
||||
#define U16_F "d"
|
||||
#define S16_F "d"
|
||||
#define X16_F "4x"
|
||||
#define U32_F "d"
|
||||
#define S32_F "d"
|
||||
#define X32_F "x"
|
||||
#define SZT_F "d"
|
||||
|
||||
#define PACK_STRUCT_FIELD(x) x
|
||||
#define PACK_STRUCT_STRUCT __attribute__((packed))
|
||||
#define PACK_STRUCT_BEGIN
|
||||
#define PACK_STRUCT_END
|
||||
|
||||
#define FOOBAR(...) do {debug_print (NOTICE, "", __VA_ARGS__);} while(0)
|
||||
#define LWIP_PLATFORM_DIAG(...) FOOBAR __VA_ARGS__
|
||||
#define LWIP_PLATFORM_ASSERT(x) do {debug_print(ERROR, "Assertion \"%s\" failed at line %d in %s\n", \
|
||||
x, __LINE__, __FILE__); kexit(1); } while(0)
|
||||
|
||||
#define LWIP_PLATFORM_BYTESWAP 1
|
||||
#define LWIP_PLATFORM_HTONS(x) ( (((u16_t)(x))>>8) | (((x)&0xFF)<<8) )
|
||||
#define LWIP_PLATFORM_HTONL(x) ( (((u32_t)(x))>>24) | (((x)&0xFF0000)>>8) \
|
||||
| (((x)&0xFF00)<<8) | (((x)&0xFF)<<24) )
|
||||
|
||||
#define LWIP_RAND() ((u32_t)krand())
|
||||
|
||||
extern void * heap_external;
|
||||
|
||||
|
||||
#endif /* __ARCH_CC_H__ */
|
@ -1,13 +0,0 @@
|
||||
#ifndef __ARCH_PERF_H__
|
||||
#define __ARCH_PERF_H__
|
||||
|
||||
#ifdef PERF
|
||||
#define PERF_START
|
||||
#define PERF_STOP(x)
|
||||
#else /* PERF */
|
||||
#define PERF_START /* null definition */
|
||||
#define PERF_STOP(x) /* null definition */
|
||||
#endif /* PERF */
|
||||
|
||||
#endif /* __ARCH_PERF_H__ */
|
||||
|
@ -1,24 +0,0 @@
|
||||
#ifndef __ARCH_SYS_ARCH_H__
|
||||
#define __ARCH_SYS_ARCH_H__
|
||||
|
||||
#define SYS_MBOX_NULL NULL
|
||||
#define SYS_SEM_NULL NULL
|
||||
|
||||
typedef u32_t sys_prot_t;
|
||||
|
||||
struct sys_sem;
|
||||
typedef struct sys_sem * sys_sem_t;
|
||||
#define sys_sem_valid(sem) (((sem) != NULL) && (*(sem) != NULL))
|
||||
#define sys_sem_set_invalid(sem) do { if((sem) != NULL) { *(sem) = NULL; }}while(0)
|
||||
|
||||
/* let sys.h use binary semaphores for mutexes */
|
||||
#define LWIP_COMPAT_MUTEX 1
|
||||
|
||||
struct sys_mbox;
|
||||
typedef struct sys_mbox *sys_mbox_t;
|
||||
#define sys_mbox_valid(mbox) (((mbox) != NULL) && (*(mbox) != NULL))
|
||||
#define sys_mbox_set_invalid(mbox) do { if((mbox) != NULL) { *(mbox) = NULL; }}while(0)
|
||||
|
||||
typedef void * sys_thread_t;
|
||||
|
||||
#endif /* __ARCH_SYS_ARCH_H__ */
|
@ -1,184 +0,0 @@
|
||||
#include <module.h>
|
||||
#include <printf.h>
|
||||
#include <mod/shell.h>
|
||||
|
||||
#include "lwip/init.h"
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "lwip/ip.h"
|
||||
#include "lwip/ip_frag.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
|
||||
#include "netif/etharp.h"
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
const uint8_t *b1 = (const uint8_t *)s1;
|
||||
const uint8_t *b2 = (const uint8_t *)s2;
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
if (*b1 < *b2) return -1;
|
||||
if (*b1 > *b2) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t sys_now(void) {
|
||||
unsigned long s, ss;
|
||||
relative_time(0,0,&s,&ss);
|
||||
return s * 1000 + ss * 10;
|
||||
}
|
||||
|
||||
void * heap_external = NULL;
|
||||
|
||||
void sys_init(void) {
|
||||
debug_print(NOTICE, "lwip sys_init() called");
|
||||
heap_external = malloc(16000);
|
||||
}
|
||||
|
||||
#if 1
|
||||
sys_thread_t sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize, int prio) {
|
||||
(void)stacksize;
|
||||
(void)prio;
|
||||
debug_print(WARNING, "lwip is creating thread [%s] point to 0x%x", name, thread);
|
||||
int pid = create_kernel_tasklet((tasklet_t)thread, (char *)name, arg);
|
||||
return (sys_thread_t)process_from_pid(pid);
|
||||
}
|
||||
|
||||
|
||||
struct sys_sem {
|
||||
volatile uint8_t i;
|
||||
};
|
||||
|
||||
err_t sys_sem_new(sys_sem_t *sem, u8_t count) {
|
||||
sys_sem_t s = malloc(sizeof(struct sys_sem));
|
||||
s->i = 0;
|
||||
*sem = s;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_sem_free(sys_sem_t * sem) {
|
||||
free(*sem);
|
||||
}
|
||||
|
||||
void sys_sem_signal(sys_sem_t *sem) {
|
||||
debug_print(NOTICE, "Unlocking sem 0x%x", *sem);
|
||||
spin_unlock(&(*sem)->i);
|
||||
}
|
||||
|
||||
u32_t sys_arch_sem_wait(sys_sem_t * sem, u32_t timeout) {
|
||||
debug_print(NOTICE, "Waiting on sem 0x%x", *sem);
|
||||
int i = now();
|
||||
spin_lock(&(*sem)->i);
|
||||
debug_print(NOTICE, "wait for sem 0x%x is done", *sem);
|
||||
return (now() - i) * 1000;
|
||||
}
|
||||
|
||||
struct sys_mbox {
|
||||
volatile uint8_t i;
|
||||
void * msg;
|
||||
};
|
||||
|
||||
err_t sys_mbox_new(sys_mbox_t *mbox, int size) {
|
||||
sys_mbox_t m = malloc(sizeof(struct sys_mbox));
|
||||
m->i = 0;
|
||||
m->msg = NULL;
|
||||
*mbox = m;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sys_mbox_post(sys_mbox_t *mbox, void *msg) {
|
||||
debug_print(NOTICE, "lwip post");
|
||||
while (1) {
|
||||
spin_lock(&(*mbox)->i);
|
||||
if (!(*mbox)->msg) {
|
||||
(*mbox)->msg = msg;
|
||||
spin_unlock(&(*mbox)->i);
|
||||
return;
|
||||
}
|
||||
spin_unlock(&(*mbox)->i);
|
||||
}
|
||||
}
|
||||
|
||||
err_t sys_mbox_trypost(sys_mbox_t *mbox, void *msg) {
|
||||
debug_print(NOTICE, "lwip trypost");
|
||||
spin_lock(&(*mbox)->i);
|
||||
if ((*mbox)->msg) {
|
||||
spin_unlock(&(*mbox)->i);
|
||||
return 1;
|
||||
}
|
||||
(*mbox)->msg = msg;
|
||||
spin_unlock(&(*mbox)->i);
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32_t sys_arch_mbox_fetch(sys_mbox_t *mbox, void **msg, u32_t timeout) {
|
||||
debug_print(NOTICE, "lwip fetch timeout=%d", timeout);
|
||||
unsigned long ts, tss;
|
||||
relative_time(0, 0, &ts, &tss);
|
||||
unsigned long s, ss;
|
||||
relative_time(0, timeout / 10, &s, &ss);
|
||||
while (1) {
|
||||
spin_lock(&(*mbox)->i);
|
||||
if ((*mbox)->msg) {
|
||||
*msg = (*mbox)->msg;
|
||||
spin_unlock(&(*mbox)->i);
|
||||
unsigned long _s, _ss;
|
||||
relative_time(0, 0, &_s, &_ss);
|
||||
return (_s - ts) * 1000 + (_ss - tss) * 10;
|
||||
}
|
||||
spin_unlock(&(*mbox)->i);
|
||||
unsigned long _s, _ss;
|
||||
relative_time(0, 0, &_s, &_ss);
|
||||
if (_s > s || (_s == s && _ss > ss)) {
|
||||
debug_print(NOTICE, "lwip fetch timed out");
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
u32_t sys_arch_mbox_tryfetch(sys_mbox_t *mbox, void **msg) {
|
||||
debug_print(NOTICE, "lwip tryfetch");
|
||||
spin_lock(&(*mbox)->i);
|
||||
if ((*mbox)->msg) {
|
||||
*msg = (*mbox)->msg;
|
||||
spin_unlock(&(*mbox)->i);
|
||||
return 0;
|
||||
}
|
||||
spin_unlock(&(*mbox)->i);
|
||||
return SYS_MBOX_EMPTY;
|
||||
}
|
||||
|
||||
void sys_mbox_free(sys_mbox_t *mbox) {
|
||||
free(*mbox);
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_SHELL_FUNCTION(netif_test, "networking stuff") {
|
||||
fprintf(tty, "Initializing LWIP...\n");
|
||||
|
||||
lwip_init();
|
||||
|
||||
unsigned long s, ss;
|
||||
relative_time(0, 200, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
|
||||
fprintf(tty, "LWIP is initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void) {
|
||||
BIND_SHELL_FUNCTION(netif_test);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_DEF(netif, init, fini);
|
||||
MODULE_DEPENDS(debugshell);
|
@ -1,232 +0,0 @@
|
||||
#include <module.h>
|
||||
#include <logging.h>
|
||||
#include <printf.h>
|
||||
#include <pci.h>
|
||||
#include <ipv4.h>
|
||||
#include <mod/shell.h>
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "ipv4/lwip/ip.h"
|
||||
#include "lwip/tcpip.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
static uint32_t rtl_device_pci = 0x00000000;
|
||||
|
||||
static void find_rtl(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
|
||||
if ((vendorid == 0x10ec) && (deviceid == 0x8139)) {
|
||||
*((uint32_t *)extra) = device;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTL_PORT_MAC 0x00
|
||||
#define RTL_PORT_MAR 0x08
|
||||
#define RTL_PORT_RBSTART 0x30
|
||||
#define RTL_PORT_CMD 0x37
|
||||
#define RTL_PORT_IMR 0x3C
|
||||
#define RTL_PORT_ISR 0x3E
|
||||
#define RTL_PORT_RCR 0x44
|
||||
#define RTL_PORT_CONFIG 0x52
|
||||
|
||||
static uint8_t rtl_rx_buffer[8192+16];
|
||||
static struct netif rtl_lwip_netif;
|
||||
static ip_addr_t ipaddr, netmask, gw;
|
||||
|
||||
err_t rtl_linkoutput(struct netif * netif, struct pbuf * p) {
|
||||
debug_print(NOTICE, "tx %x %x", netif, p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_t rtl_output(struct netif * netif, struct pbuf * p, struct ip_addr* dest) {
|
||||
debug_print(NOTICE, "tx %x %x %x", netif, p, dest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_t rtl_init(struct netif * netif) {
|
||||
debug_print(NOTICE, "rtl init");
|
||||
netif->linkoutput = rtl_linkoutput;
|
||||
netif->output = rtl_output; //etharp_output;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dhcp_thread(void * arg, char * name) {
|
||||
dhcp_start(&rtl_lwip_netif);
|
||||
|
||||
int mscnt = 0;
|
||||
while (rtl_lwip_netif.ip_addr.addr == 0) {
|
||||
unsigned long s, ss;
|
||||
relative_time(0, DHCP_FINE_TIMER_MSECS / 100, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
dhcp_fine_tmr();
|
||||
mscnt += DHCP_FINE_TIMER_MSECS;
|
||||
if (mscnt >= DHCP_COARSE_TIMER_SECS * 1000) {
|
||||
debug_print(NOTICE, "coarse timer");
|
||||
dhcp_coarse_tmr();
|
||||
mscnt = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tcpip_init_done(void * arg) {
|
||||
netif_add(&rtl_lwip_netif, &ipaddr, &netmask, &gw, 0, rtl_init, ethernet_input);
|
||||
|
||||
netif_set_default(&rtl_lwip_netif);
|
||||
netif_set_up(&rtl_lwip_netif);
|
||||
|
||||
create_kernel_tasklet(dhcp_thread, "[[dhcpd]]", NULL);
|
||||
}
|
||||
|
||||
|
||||
DEFINE_SHELL_FUNCTION(rtl, "rtl8139 experiments") {
|
||||
if (rtl_device_pci) {
|
||||
fprintf(tty, "Located an RTL 8139: 0x%x\n", rtl_device_pci);
|
||||
|
||||
uint16_t command_reg = pci_read_field(rtl_device_pci, PCI_COMMAND, 2);
|
||||
fprintf(tty, "COMMAND register before: 0x%4x\n", command_reg);
|
||||
if (command_reg & 0x0002) {
|
||||
fprintf(tty, "Bus mastering already enabled.\n");
|
||||
} else {
|
||||
command_reg |= 0x2; /* bit 2 */
|
||||
fprintf(tty, "COMMAND register after: 0x%4x\n", command_reg);
|
||||
fprintf(tty, "XXX: I can't write config registers :(\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t rtl_irq = pci_read_field(rtl_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
|
||||
fprintf(tty, "Interrupt Line: %x\n", rtl_irq);
|
||||
|
||||
uint32_t rtl_bar0 = pci_read_field(rtl_device_pci, PCI_BAR0, 4);
|
||||
uint32_t rtl_bar1 = pci_read_field(rtl_device_pci, PCI_BAR1, 4);
|
||||
|
||||
fprintf(tty, "BAR0: 0x%8x\n", rtl_bar0);
|
||||
fprintf(tty, "BAR1: 0x%8x\n", rtl_bar1);
|
||||
|
||||
uint32_t rtl_iobase = 0x00000000;
|
||||
|
||||
if (rtl_bar0 & 0x00000001) {
|
||||
rtl_iobase = rtl_bar0 & 0xFFFFFFFC;
|
||||
} else {
|
||||
fprintf(tty, "This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar.");
|
||||
}
|
||||
|
||||
fprintf(tty, "RTL iobase: 0x%x\n", rtl_iobase);
|
||||
|
||||
fprintf(tty, "Determining mac address...\n");
|
||||
|
||||
uint8_t mac[6];
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
mac[i] = inports(rtl_iobase + RTL_PORT_MAC + i);
|
||||
}
|
||||
|
||||
fprintf(tty, "%2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
fprintf(tty, "Enabling RTL8139.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CONFIG, 0x0);
|
||||
|
||||
fprintf(tty, "Resetting RTL8139.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CMD, 0x10);
|
||||
while ((inportb(rtl_iobase + 0x37) & 0x10) != 0) { }
|
||||
|
||||
fprintf(tty, "Done resetting RTL8139.\n");
|
||||
|
||||
fprintf(tty, "Initializing receive buffer.\n");
|
||||
outportl(rtl_iobase + RTL_PORT_RBSTART, (unsigned long)&rtl_rx_buffer);
|
||||
|
||||
fprintf(tty, "Enabling IRQs.\n");
|
||||
outports(rtl_iobase + RTL_PORT_IMR, 0x0005); /* TOK, ROK */
|
||||
|
||||
fprintf(tty, "Configuring receive buffer.\n");
|
||||
outportl(rtl_iobase + RTL_PORT_RCR, 0xF | (1 << 7)); /* 0xF = AB+AM+APM+AAP */
|
||||
|
||||
fprintf(tty, "Enabling receive and transmit.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CMD, 0x0C);
|
||||
|
||||
memset(&rtl_lwip_netif, 0, sizeof(struct netif));
|
||||
|
||||
IP4_ADDR(&gw, 0,0,0,0);
|
||||
IP4_ADDR(&ipaddr, 0,0,0,0);
|
||||
IP4_ADDR(&netmask, 0,0,0,0);
|
||||
|
||||
rtl_lwip_netif.hwaddr_len = 6;
|
||||
rtl_lwip_netif.hwaddr[0] = mac[0];
|
||||
rtl_lwip_netif.hwaddr[1] = mac[1];
|
||||
rtl_lwip_netif.hwaddr[2] = mac[2];
|
||||
rtl_lwip_netif.hwaddr[3] = mac[3];
|
||||
rtl_lwip_netif.hwaddr[4] = mac[4];
|
||||
rtl_lwip_netif.hwaddr[5] = mac[5];
|
||||
|
||||
debug_print(NOTICE, "Going to init stuff.");
|
||||
switch_task(1);
|
||||
|
||||
tcpip_init(tcpip_init_done, NULL);
|
||||
|
||||
debug_print(NOTICE, "okay, stuff should be running in the background now\n");
|
||||
switch_task(1);
|
||||
|
||||
#if 0
|
||||
fprintf(tty, "Going to try to force-send a UDP packet...\n");
|
||||
struct ipv4_packet p;
|
||||
p.version_ihl = (4 << 4) & (5 << 0); /* IPv4, no options */
|
||||
p.dscp_ecn = 0; /* nope nope nope */
|
||||
p.length = sizeof(struct ipv4_packet) + sizeof(struct udp_packet) + sizeof(struct dhcp_packet);
|
||||
p.ident = 0;
|
||||
p.flags_fragment = 0;
|
||||
p.ttl = 0xFF;
|
||||
p.protocol = 17;
|
||||
p.checksum = 0; /* calculate this later */
|
||||
p.source = 0x00000000; /* 0.0.0.0 */
|
||||
p.destination = 0xFFFFFFFF; /* 255.255.255.255 */
|
||||
|
||||
uint16_t * packet = (uint16_t *)&p;
|
||||
uint32_t total = 0;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
total += packet[i];
|
||||
if (total & 0x80000000) {
|
||||
total = (total & 0xFFFF) + (total >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
while (total >> 16) {
|
||||
total = (total & 0xFFFF) + (total >> 16);
|
||||
}
|
||||
|
||||
p.checksum = ~total;
|
||||
|
||||
struct udp_packet u;
|
||||
u.source = p.source;
|
||||
u.destination = p.destination;
|
||||
u.zeroes = 0;
|
||||
u.protocol = p.protocol;
|
||||
u.udp_length = p.length;
|
||||
u.source_port = 68;
|
||||
u.destination_port = 67;
|
||||
u.length = sizeof(struct dhcp_packet);
|
||||
u.checksum = 0;
|
||||
#endif
|
||||
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void) {
|
||||
BIND_SHELL_FUNCTION(rtl);
|
||||
pci_scan(&find_rtl, -1, &rtl_device_pci);
|
||||
if (!rtl_device_pci) {
|
||||
debug_print(ERROR, "No RTL 8139 found?");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_DEF(rtl8139, init, fini);
|
||||
MODULE_DEPENDS(debugshell);
|
||||
MODULE_DEPENDS(netif);
|
@ -8,6 +8,10 @@
|
||||
#include <pci_list.h>
|
||||
|
||||
|
||||
void pci_write_field(uint32_t device, int field, int size, uint32_t value) {
|
||||
outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
|
||||
outportl(PCI_VALUE_PORT, value);
|
||||
}
|
||||
|
||||
uint32_t pci_read_field(uint32_t device, int field, int size) {
|
||||
outportl(PCI_ADDRESS_PORT, pci_get_addr(device, field));
|
||||
|
@ -58,6 +58,7 @@ static inline uint32_t pci_box_device(int bus, int slot, int func) {
|
||||
}
|
||||
|
||||
uint32_t pci_read_field(uint32_t device, int field, int size);
|
||||
void pci_write_field(uint32_t device, int field, int size, uint32_t value);
|
||||
uint16_t pci_find_type(uint32_t dev);
|
||||
const char * pci_vendor_lookup(unsigned short vendor_id);
|
||||
const char * pci_device_lookup(unsigned short vendor_id, unsigned short device_id);
|
||||
|
333
modules/rtl.c
Normal file
333
modules/rtl.c
Normal file
@ -0,0 +1,333 @@
|
||||
#include <module.h>
|
||||
#include <logging.h>
|
||||
#include <printf.h>
|
||||
#include <pci.h>
|
||||
#include <mem.h>
|
||||
#include <ipv4.h>
|
||||
#include <mod/shell.h>
|
||||
|
||||
static uint32_t rtl_device_pci = 0x00000000;
|
||||
|
||||
static void find_rtl(uint32_t device, uint16_t vendorid, uint16_t deviceid, void * extra) {
|
||||
if ((vendorid == 0x10ec) && (deviceid == 0x8139)) {
|
||||
*((uint32_t *)extra) = device;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTL_PORT_MAC 0x00
|
||||
#define RTL_PORT_MAR 0x08
|
||||
#define RTL_PORT_TXSTAT 0x10
|
||||
#define RTL_PORT_TXBUF 0x20
|
||||
#define RTL_PORT_RBSTART 0x30
|
||||
#define RTL_PORT_CMD 0x37
|
||||
#define RTL_PORT_RXPTR 0x38
|
||||
#define RTL_PORT_RXADDR 0x3A
|
||||
#define RTL_PORT_IMR 0x3C
|
||||
#define RTL_PORT_ISR 0x3E
|
||||
#define RTL_PORT_TCR 0x40
|
||||
#define RTL_PORT_RCR 0x44
|
||||
#define RTL_PORT_RXMISS 0x4C
|
||||
#define RTL_PORT_CONFIG 0x52
|
||||
|
||||
static int rtl_irq = 0;
|
||||
static uint32_t rtl_iobase = 0;
|
||||
static uint8_t * rtl_rx_buffer;
|
||||
static uint8_t * rtl_tx_buffer[4];
|
||||
|
||||
static uintptr_t rtl_rx_phys;
|
||||
static uintptr_t rtl_tx_phys[4];
|
||||
|
||||
static uint32_t cur_rx = 0;
|
||||
|
||||
static uint8_t _dhcp_packet[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x08, 0x00, 0x45, 0x00,
|
||||
0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x40, 0x11, 0x79, 0xDD, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0x44, 0x00, 0x43, 0x00, 0xFC, 0x81, 0xCC, 0x01, 0x01, 0x06, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x54, 0x00, 0x12, 0x34, 0x56, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x82, 0x53, 0x63, 0x35, 0x01, 0x01, 0xFF
|
||||
};
|
||||
|
||||
static void rtl_irq_handler(struct regs *r) {
|
||||
uint16_t status = inports(rtl_iobase + RTL_PORT_ISR);
|
||||
outports(rtl_iobase + RTL_PORT_ISR, status);
|
||||
|
||||
irq_ack(rtl_irq);
|
||||
|
||||
debug_print(NOTICE, "herp a derp");
|
||||
|
||||
if (status & 0x01 || status & 0x02) {
|
||||
/* Receive */
|
||||
debug_print(NOTICE, "rx response");
|
||||
while((inportb(rtl_iobase + RTL_PORT_CMD) & 0x01) == 0) {
|
||||
int offset = cur_rx % 0x2000;
|
||||
|
||||
#if 0
|
||||
uint16_t buf_addr = inports(rtl_iobase + RTL_PORT_RXADDR);
|
||||
uint16_t buf_ptr = inports(rtl_iobase + RTL_PORT_RXPTR);
|
||||
uint8_t cmd = inportb(rtl_iobase + RTL_PORT_CMD);
|
||||
#endif
|
||||
|
||||
uint32_t * buf_start = (uint32_t *)((uintptr_t)rtl_rx_buffer + offset);
|
||||
uint32_t rx_status = buf_start[0];
|
||||
int rx_size = rx_status >> 16;
|
||||
|
||||
if (rx_status & (0x0020 | 0x0010 | 0x0004 | 0x0002)) {
|
||||
debug_print(WARNING, "rx error :(");
|
||||
} else {
|
||||
uint8_t * buf_8 = (uint8_t *)&(buf_start[1]);
|
||||
|
||||
|
||||
debug_print(NOTICE, "Some bytes from this packet: %2x%2x%2x%2x",
|
||||
buf_8[0],
|
||||
buf_8[1],
|
||||
buf_8[2],
|
||||
buf_8[3]);
|
||||
|
||||
}
|
||||
|
||||
cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
|
||||
outports(rtl_iobase + RTL_PORT_RXPTR, cur_rx - 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (status & 0x08 || status & 0x04) {
|
||||
debug_print(NOTICE,"tx response");
|
||||
unsigned int i = inportl(rtl_iobase + RTL_PORT_TXSTAT);
|
||||
debug_print(NOTICE, "Other bits: 0x%x; status=0x%x", i, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DEFINE_SHELL_FUNCTION(rtl, "rtl8139 experiments") {
|
||||
if (rtl_device_pci) {
|
||||
fprintf(tty, "Located an RTL 8139: 0x%x\n", rtl_device_pci);
|
||||
|
||||
uint16_t command_reg = pci_read_field(rtl_device_pci, PCI_COMMAND, 4);
|
||||
fprintf(tty, "COMMAND register before: 0x%4x\n", command_reg);
|
||||
if (command_reg & (1 << 2)) {
|
||||
fprintf(tty, "Bus mastering already enabled.\n");
|
||||
} else {
|
||||
command_reg |= (1 << 2); /* bit 2 */
|
||||
fprintf(tty, "COMMAND register after: 0x%4x\n", command_reg);
|
||||
pci_write_field(rtl_device_pci, PCI_COMMAND, 4, command_reg);
|
||||
command_reg = pci_read_field(rtl_device_pci, PCI_COMMAND, 4);
|
||||
fprintf(tty, "COMMAND register after: 0x%4x\n", command_reg);
|
||||
}
|
||||
|
||||
rtl_irq = pci_read_field(rtl_device_pci, PCI_INTERRUPT_LINE, 1);
|
||||
|
||||
fprintf(tty, "Interrupt Line: %x\n", rtl_irq);
|
||||
irq_install_handler(rtl_irq, rtl_irq_handler);
|
||||
|
||||
uint32_t rtl_bar0 = pci_read_field(rtl_device_pci, PCI_BAR0, 4);
|
||||
uint32_t rtl_bar1 = pci_read_field(rtl_device_pci, PCI_BAR1, 4);
|
||||
|
||||
fprintf(tty, "BAR0: 0x%8x\n", rtl_bar0);
|
||||
fprintf(tty, "BAR1: 0x%8x\n", rtl_bar1);
|
||||
|
||||
rtl_iobase = 0x00000000;
|
||||
|
||||
if (rtl_bar0 & 0x00000001) {
|
||||
rtl_iobase = rtl_bar0 & 0xFFFFFFFC;
|
||||
} else {
|
||||
fprintf(tty, "This doesn't seem right! RTL8139 should be using an I/O BAR; this looks like a memory bar.");
|
||||
}
|
||||
|
||||
fprintf(tty, "RTL iobase: 0x%x\n", rtl_iobase);
|
||||
|
||||
fprintf(tty, "Determining mac address...\n");
|
||||
|
||||
uint8_t mac[6];
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
mac[i] = inports(rtl_iobase + RTL_PORT_MAC + i);
|
||||
_dhcp_packet[6+i] = mac[i];
|
||||
}
|
||||
|
||||
fprintf(tty, "%2x:%2x:%2x:%2x:%2x:%2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
|
||||
fprintf(tty, "Enabling RTL8139.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CONFIG, 0x0);
|
||||
|
||||
fprintf(tty, "Resetting RTL8139.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CMD, 0x10);
|
||||
while ((inportb(rtl_iobase + 0x37) & 0x10) != 0) { }
|
||||
|
||||
fprintf(tty, "Done resetting RTL8139.\n");
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
rtl_tx_buffer[i] = (void*)kvmalloc_p(0x1000, &rtl_tx_phys[i]);
|
||||
for (int j = 0; j < 60; ++j) {
|
||||
rtl_tx_buffer[i][j] = 0xF0;
|
||||
}
|
||||
}
|
||||
|
||||
rtl_rx_buffer = (uint8_t *)kvmalloc(0x3000);
|
||||
|
||||
/* This is a terrible hack, we need to be able to allocate
|
||||
* linear pages from, say, sbrk or similar.... */
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x0000, 1, current_directory), 1, 0, 0x20000000);
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x1000, 1, current_directory), 1, 0, 0x20001000);
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x2000, 1, current_directory), 1, 0, 0x20002000);
|
||||
|
||||
/* Also map them in the kernel directory */
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x0000, 1, kernel_directory), 1, 0, 0x20000000);
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x1000, 1, kernel_directory), 1, 0, 0x20001000);
|
||||
dma_frame(get_page((uintptr_t)rtl_rx_buffer + 0x2000, 1, kernel_directory), 1, 0, 0x20002000);
|
||||
|
||||
memset(rtl_rx_buffer, 0x00, 0x3000);
|
||||
|
||||
rtl_rx_phys = 0x20000000;
|
||||
|
||||
fprintf(tty, "Buffers:\n");
|
||||
fprintf(tty, " rx 0x%x [phys 0x%x:0x%x]\n", rtl_rx_buffer, rtl_rx_phys, map_to_physical((uintptr_t)rtl_rx_buffer));
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
fprintf(tty, " tx 0x%x [phys 0x%x:0x%x]\n", rtl_tx_buffer[i], rtl_tx_phys[i], map_to_physical((uintptr_t)rtl_tx_buffer[i]));
|
||||
}
|
||||
|
||||
fprintf(tty, "Initializing receive buffer.\n");
|
||||
outportl(rtl_iobase + RTL_PORT_RBSTART, rtl_rx_phys);
|
||||
|
||||
fprintf(tty, "Enabling IRQs.\n");
|
||||
outports(rtl_iobase + RTL_PORT_IMR,
|
||||
0x8000 | /* PCI error */
|
||||
0x4000 | /* PCS timeout */
|
||||
0x40 | /* Rx FIFO over */
|
||||
0x20 | /* Rx underrun */
|
||||
0x10 | /* Rx overflow */
|
||||
0x08 | /* Tx error */
|
||||
//0x04 | /* Tx okay */
|
||||
0x02 | /* Rx error */
|
||||
0x01 /* Rx okay */
|
||||
); /* TOK, ROK */
|
||||
|
||||
fprintf(tty, "Configuring transmit\n");
|
||||
outportl(rtl_iobase + RTL_PORT_TCR,
|
||||
0
|
||||
);
|
||||
|
||||
fprintf(tty, "Configuring receive buffer.\n");
|
||||
outportl(rtl_iobase + RTL_PORT_RCR,
|
||||
(0) | /* 8K receive */
|
||||
0x08 | /* broadcast */
|
||||
0x01 /* all physical */
|
||||
);
|
||||
|
||||
fprintf(tty, "Enabling receive and transmit.\n");
|
||||
outportb(rtl_iobase + RTL_PORT_CMD, 0x08 | 0x04);
|
||||
|
||||
fprintf(tty, "Resetting rx stats\n");
|
||||
outportl(rtl_iobase + RTL_PORT_RXMISS, 0);
|
||||
|
||||
fprintf(tty, "Going to send a packet. I hope\n");
|
||||
memcpy(rtl_tx_buffer[0], _dhcp_packet, sizeof(_dhcp_packet));
|
||||
outportl(rtl_iobase + RTL_PORT_TXBUF, rtl_tx_phys[0]);
|
||||
outportl(rtl_iobase + RTL_PORT_TXSTAT, sizeof(_dhcp_packet));
|
||||
|
||||
#if 0
|
||||
fprintf(tty, "Going to send a packet. I hope\n");
|
||||
memcpy(rtl_tx_buffer[1], _dhcp_packet, sizeof(_dhcp_packet));
|
||||
|
||||
outportl(rtl_iobase + RTL_PORT_TXBUF+4, rtl_tx_phys[1]);
|
||||
outportl(rtl_iobase + RTL_PORT_TXSTAT+4, sizeof(_dhcp_packet));
|
||||
|
||||
fprintf(tty, "Going to send a packet. I hope\n");
|
||||
memcpy(rtl_tx_buffer[2], _dhcp_packet, sizeof(_dhcp_packet));
|
||||
|
||||
outportl(rtl_iobase + RTL_PORT_TXBUF+8, rtl_tx_phys[2]);
|
||||
outportl(rtl_iobase + RTL_PORT_TXSTAT+8, sizeof(_dhcp_packet));
|
||||
#endif
|
||||
|
||||
{
|
||||
unsigned long s, ss;
|
||||
relative_time(0, 100, &s, &ss);
|
||||
sleep_until((process_t *)current_process, s, ss);
|
||||
switch_task(0);
|
||||
|
||||
fprintf(tty, "Awoken from sleep, checking receive buffer: 0x%x\n", &rtl_rx_buffer[0]);
|
||||
}
|
||||
|
||||
/* Okay, going to evaluate some things */
|
||||
fprintf(tty, "If I'm right, DHCP wants to assign us %d.%d.%d.%d\n",
|
||||
rtl_rx_buffer[0x3A+4],
|
||||
rtl_rx_buffer[0x3B+4],
|
||||
rtl_rx_buffer[0x3C+4],
|
||||
rtl_rx_buffer[0x3D+4]);
|
||||
|
||||
#if 0
|
||||
fprintf(tty, "Going to try to force-send a UDP packet...\n");
|
||||
struct ipv4_packet p;
|
||||
p.version_ihl = (4 << 4) & (5 << 0); /* IPv4, no options */
|
||||
p.dscp_ecn = 0; /* nope nope nope */
|
||||
p.length = sizeof(struct ipv4_packet) + sizeof(struct udp_packet) + sizeof(struct dhcp_packet);
|
||||
p.ident = 0;
|
||||
p.flags_fragment = 0;
|
||||
p.ttl = 0xFF;
|
||||
p.protocol = 17;
|
||||
p.checksum = 0; /* calculate this later */
|
||||
p.source = 0x00000000; /* 0.0.0.0 */
|
||||
p.destination = 0xFFFFFFFF; /* 255.255.255.255 */
|
||||
|
||||
uint16_t * packet = (uint16_t *)&p;
|
||||
uint32_t total = 0;
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
total += packet[i];
|
||||
if (total & 0x80000000) {
|
||||
total = (total & 0xFFFF) + (total >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
while (total >> 16) {
|
||||
total = (total & 0xFFFF) + (total >> 16);
|
||||
}
|
||||
|
||||
p.checksum = ~total;
|
||||
|
||||
struct udp_packet u;
|
||||
u.source = p.source;
|
||||
u.destination = p.destination;
|
||||
u.zeroes = 0;
|
||||
u.protocol = p.protocol;
|
||||
u.udp_length = p.length;
|
||||
u.source_port = 68;
|
||||
u.destination_port = 67;
|
||||
u.length = sizeof(struct dhcp_packet);
|
||||
u.checksum = 0;
|
||||
#endif
|
||||
|
||||
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init(void) {
|
||||
BIND_SHELL_FUNCTION(rtl);
|
||||
pci_scan(&find_rtl, -1, &rtl_device_pci);
|
||||
if (!rtl_device_pci) {
|
||||
debug_print(ERROR, "No RTL 8139 found?");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fini(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
MODULE_DEF(rtl, init, fini);
|
||||
MODULE_DEPENDS(debugshell);
|
Loading…
x
Reference in New Issue
Block a user