summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2017-08-01 16:23:09 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2017-08-01 16:23:09 +0200
commitd86f301ecb8c773cde8afc646a8b7ae578b8a232 (patch)
treec97556261bd02ec2765522e5451a018fa18a25fc
parent0f6576eba813fdb30b619b9b0b5fa7a76c6cf636 (diff)
downloadabaos-d86f301ecb8c773cde8afc646a8b7ae578b8a232.tar.gz
abaos-d86f301ecb8c773cde8afc646a8b7ae578b8a232.tar.bz2
we can receive network events, but the receive buffer remains empty
this is because we must enable DMA transfering on the PCI bus (bus master enable)
-rw-r--r--src/Makefile2
-rw-r--r--src/drivers/net/network.c20
-rw-r--r--src/drivers/net/network.h9
-rw-r--r--src/drivers/net/rtl8139.c200
-rw-r--r--src/drivers/net/rtl8139.h4
-rw-r--r--src/kernel/kernel.c16
6 files changed, 230 insertions, 21 deletions
diff --git a/src/Makefile b/src/Makefile
index 9222125..c71cfa8 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
CC := gcc
DEFINES = -DOS_ABAOS
OPT := -O0
-INCLUDES = -I. -Ilibc -Ihardware -Idrivers -Idrivers/hdi -Idrivers/hdi/ps2 -Idrivers/video -Ikernel -Igui
+INCLUDES = -I. -Ilibc -Ihardware -Idrivers -Idrivers/hdi -Idrivers/hdi/ps2 -Idrivers/video -Idrivers/net -Ikernel -Igui
CFLAGS := -std=c99 -m32 -march=i486 -ffreestanding $(OPT) -g -Werror $(INCLUDES) $(DEFINES)
LD := ld
LDFLAGS := -lgcc
diff --git a/src/drivers/net/network.c b/src/drivers/net/network.c
index 46a3295..85bfdf2 100644
--- a/src/drivers/net/network.c
+++ b/src/drivers/net/network.c
@@ -7,11 +7,12 @@
static network_vtable_t const network_vtable = {
{
- driver_activate,
- driver_deactivate,
- driver_deinit,
- driver_print_info
- }
+ driver_activate,
+ driver_deactivate,
+ driver_deinit,
+ driver_print_info
+ },
+ network_register_handler
};
void network_init( network_t *network, interrupt_t *interrupt, void *context )
@@ -20,9 +21,18 @@ void network_init( network_t *network, interrupt_t *interrupt, void *context )
driver_init( (driver_t *)network, DRIVER_TYPE_NETWORK, interrupt, context );
+ network->handler = NULL;
+
((driver_t *)network)->vtable = (driver_vtable_t *)&network_vtable;
}
+void network_register_handler( void *obj, network_event_handler_t handler )
+{
+ network_t *network = (network_t *)obj;
+
+ network->handler = handler;
+}
+
char *network_mac_to_string( network_mac_address_t mac, char *buf, size_t buflen )
{
snprintf( buf, buflen, "%X:%X:%X:%X:%X:%X",
diff --git a/src/drivers/net/network.h b/src/drivers/net/network.h
index 8ec17cb..751ca40 100644
--- a/src/drivers/net/network.h
+++ b/src/drivers/net/network.h
@@ -11,16 +11,25 @@ typedef struct {
} network_mac_address_t;
typedef struct {
+} network_event_t;
+
+typedef void (*network_event_handler_t)( network_event_t *event, void *context );
+
+typedef struct {
driver_t base;
network_mac_address_t mac_address;
+ network_event_handler_t handler;
} network_t;
typedef struct {
driver_vtable_t base;
+ void (*register_handler)( void *obj, network_event_handler_t handler );
} network_vtable_t;
void network_init( network_t *network, interrupt_t *interrupt, void *context );
+void network_register_handler( void *obj, network_event_handler_t handler );
+
char *network_mac_to_string( network_mac_address_t mac, char *buf, size_t buflen );
#endif // NETWORK_H
diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c
index 78a552a..e6898d4 100644
--- a/src/drivers/net/rtl8139.c
+++ b/src/drivers/net/rtl8139.c
@@ -8,27 +8,34 @@
static rtl8139_vtable_t const rtl8139_vtable = {
{
- rtl8139_activate,
- rtl8139_deactivate,
- rtl8139_deinit,
- rtl8139_print_name,
- rtl8139_print_info
+ {
+ rtl8139_activate,
+ rtl8139_deactivate,
+ rtl8139_deinit,
+ rtl8139_print_name,
+ rtl8139_print_info
+ },
+ network_register_handler
}
};
// registers
#define REG_MAC0 0x00
#define REG_RBSTART 0x30
+#define REG_ERSR 0x36
#define REG_CMD 0x37
+#define REG_CAPR 0x38
#define REG_IMR 0x3C
#define REG_ISR 0x3E
#define REG_TCR 0x40
#define REG_RCR 0x44
+#define REG_MPC 0x4C
// commands for REG_CMD (command register)
#define CMD_RESET 0x10
#define CMD_RECEIVER_ENABLE 0x08
#define CMD_TRANSMITTER_ENABLE 0x04
+#define CMD_BUFFER_EMPTY 0x01
// mask for reading the version in from the REG_TCR (transmit configuration register)
#define TCR_MODEL_VERSION_AM 0x7C000000
@@ -52,7 +59,10 @@ static rtl8139_vtable_t const rtl8139_vtable = {
// values for REG_RCR (receive configuration register)
#define RCR_MXDMA_UNLIMITED 0x00000700
+#define RCR_RECEIVE_BUFFER_8K_16 0x00000000
+#define RCR_WRAP 0x00000080
#define RCR_ACCEPT_BROADCAST 0x00000008
+#define RCR_ACCEPT_MULTICAST 0x00000004
#define RCR_ACCEPT_PHYS_MATCH 0x00000002
// values for REG_IMR/REG_ISR (interrupt mask/status registers)
@@ -73,8 +83,11 @@ static rtl8139_vtable_t const rtl8139_vtable = {
ISR_RECEIVE_BUFFER_OVERFLOW | ISR_TRANSMIT_ERROR | ISR_TRANSMIT_OK | \
ISR_RECEIVE_ERROR | ISR_RECEIVE_OK
-// for now we follow the guide line on OSDEV on the size of the receive buffer
-#define RECEIVE_BUFFER_SIZE 8192 + 16
+// header
+#define PACKET_HEADER_ROK 0x0001
+
+// receive buffer, set to 8k + header (16) + wrap (2k)
+#define RECEIVE_BUFFER_SIZE 8192 + 16 + 2048
void rtl8139_init( rtl8139_t *rtl8139, pci_device_descriptor_t *descriptor, interrupt_t *interrupt, void *context )
{
@@ -90,11 +103,14 @@ void rtl8139_init( rtl8139_t *rtl8139, pci_device_descriptor_t *descriptor, inte
port8_init( &rtl8139->MAC_port[i], descriptor->port_base + REG_MAC0 + i );
}
port8_init( &rtl8139->CMD_port, descriptor->port_base + REG_CMD );
+ port16_init( &rtl8139->CAPR_port, descriptor->port_base + REG_CAPR );
port32_init( &rtl8139->RBSTART_port, descriptor->port_base + REG_RBSTART );
+ port8_init( &rtl8139->ERSR_port, descriptor->port_base + REG_ERSR );
port16_init( &rtl8139->IMR_port, descriptor->port_base + REG_IMR );
port16_init( &rtl8139->ISR_port, descriptor->port_base + REG_ISR );
port32_init( &rtl8139->TCR_port, descriptor->port_base + REG_TCR );
port32_init( &rtl8139->RCR_port, descriptor->port_base + REG_RCR );
+ port32_init( &rtl8139->MPC_port, descriptor->port_base + REG_MPC );
// software reset, the CR_RESET bit remains high till the
// reset is finished
@@ -106,7 +122,8 @@ void rtl8139_init( rtl8139_t *rtl8139, pci_device_descriptor_t *descriptor, inte
rtl8139->base.mac_address.byte[i] = port8_read( &rtl8139->MAC_port[i] );
}
- // enable receiver and transmitter early
+ // enable receiver and transmitter early (TODO: lowlevel says as later as
+ // possible, Osdev and others say as early as possible)
port8_write( &rtl8139->CMD_port, CMD_RECEIVER_ENABLE | CMD_TRANSMITTER_ENABLE );
// get model
@@ -154,20 +171,27 @@ void rtl8139_init( rtl8139_t *rtl8139, pci_device_descriptor_t *descriptor, inte
// initialize TCR/RCR (take Lowlevel suggestions: TCR = 0x03000700, RCR = 0x0000070a)
port32_write( &rtl8139->TCR_port, TCR_IFG_STANDARD | TCR_MXDMA_2048 );
- port32_write( &rtl8139->RCR_port, RCR_MXDMA_UNLIMITED | RCR_ACCEPT_BROADCAST | RCR_ACCEPT_PHYS_MATCH );
+ port32_write( &rtl8139->RCR_port, RCR_MXDMA_UNLIMITED |
+ RCR_RECEIVE_BUFFER_8K_16 | RCR_WRAP |
+ RCR_ACCEPT_BROADCAST | RCR_ACCEPT_MULTICAST | RCR_ACCEPT_PHYS_MATCH );
// allocate receive buffer and register it
- rtl8139->receive_buffer = (uint8_t *)malloc( RECEIVE_BUFFER_SIZE );
+ rtl8139->receive_buffer = (uint8_t *)aligned_alloc( 16, RECEIVE_BUFFER_SIZE + 16 );
+ memset( rtl8139->receive_buffer, 0xFE, RECEIVE_BUFFER_SIZE + 16 );
port32_write( &rtl8139->RBSTART_port, (uint32_t)rtl8139->receive_buffer );
+ rtl8139->receive_buffer_pos = 0;
+
+ // reset missed packet counter
+ port32_write( &rtl8139->MPC_port, 0 );
+
+ interrupt_handler_init( &rtl8139->interrupt_handler, IRQ_BASE + descriptor->interrupt, interrupt, rtl8139_handle_interrupt, rtl8139 );
+ interrupts_register_interrupt_handler( rtl8139->interrupt_handler );
// register interrupts we are interested in (we want all and
// filter them in the interrupt handler), read ISR to clear
// the current values (if there are bits set)
port16_write( &rtl8139->IMR_port, ISR_ALL );
(void)port16_read( &rtl8139->ISR_port );
-
- interrupt_handler_init( &rtl8139->interrupt_handler, IRQ_BASE + descriptor->interrupt, interrupt, rtl8139_handle_interrupt, rtl8139 );
- interrupts_register_interrupt_handler( rtl8139->interrupt_handler );
rtl8139_print_info( rtl8139 );
@@ -195,14 +219,158 @@ void rtl8139_deinit( void *obj )
free( rtl8139->receive_buffer );
}
+static void handle_receive_packet( rtl8139_t *rtl8139 )
+{
+ network_event_t event;
+ rtl8139->base.handler( &event, rtl8139 );
+
+ while( true ) {
+ uint8_t data = port8_read( &rtl8139->CMD_port );
+
+ // still data in the buffer
+ if( data & CMD_BUFFER_EMPTY ) {
+ break;
+ }
+
+ uint8_t *buffer = rtl8139->receive_buffer + rtl8139->receive_buffer_pos;
+
+#ifdef DEBUG
+ uint16_t capr = port16_read( &rtl8139->CAPR_port );
+ uint32_t rbstart = port32_read( &rtl8139->RBSTART_port );
+ uint32_t mpc = port32_read( &rtl8139->MPC_port );
+ uint8_t ersr = port8_read( &rtl8139->ERSR_port );
+ printf( "rtl8139: ERSR: %X, RBSTART: %X, CAPR: %X, RBPOS: %X, MPC: %X\n",
+ ersr, rbstart, capr, rtl8139->receive_buffer_pos, mpc );
+ printf( "rtl8139: " );
+ for( int i = 0; i < 80; i++ ) {
+ printf( "%X ", rtl8139->receive_buffer[rtl8139->receive_buffer_pos+i] );
+ }
+ puts( "" );
+#endif
+
+ // kprintf("%s: rtl8139_rx() status %4.4x, size %4.4x, cur %4.4x\n", dev->name, rx_status, rx_size, cur_rx);
+ // kprintf("%s: Frame contents ", dev->name);
+ // for (i = 0; i < 70; i++) kprintf(" %2.2x", rx_ring[ring_offset + i]);
+
+
+ // packet header
+ uint16_t header = *( (uint16_t *)buffer );
+#ifdef DEBUG
+ printf( "rtl8139: rcv header %X\n", header );
+#endif
+ if( ( header & PACKET_HEADER_ROK ) == 0 ) {
+ printf( "rtl8139: illegal packet header, no ROK\n", header );
+ break;
+ }
+ buffer += sizeof( uint16_t );
+
+ // buffer is 16-bit alligned
+ uint16_t len = *( (uint16_t *)buffer );
+ buffer += sizeof( uint16_t );
+#ifdef DEBUG
+ printf( "rtl8139: rcv len: %d\n", len );
+#endif
+
+ for( int i = 0; i < len; i++ ) {
+ }
+
+ }
+
+#if 0
+
+ while (1)
+ {
+
+ void* buffer = netcard->rx_buffer + netcard->rx_buffer_offset;
+
+ uint16_t packet_header = *((uint16_t*) buffer);
+ buffer += 2;
+
+ if ((packet_header & 1) == 0) {
+ DEBUG_MSG("Paketheader: Kein ROK.\n");
+ break;
+ }
+
+ // Die L�nge enth�lt die CRC-Pr�fsumme, nicht aber den Paketheader
+ uint16_t length = *((uint16_t*) buffer);
+ buffer += 2;
+
+ /*
+ * RECEIVE_BUFFER_SIZE
+ printf("Empfangen: %d Bytes\n", length);
+ printf("netcard->rx_buffer_offset = %08x\n", netcard->rx_buffer_offset);
+ */
+ /*int i;
+ for (i = 0; i < length; i++) {
+ printf("%02x ", ((char*) buffer)[i]);
+ }
+ printf("\n");*/
+
+ netcard->rx_buffer_offset += 4;
+
+ if (length >= sizeof(struct eth_packet_header))
+ {
+ uint8_t data[length - 4];
+ if ((netcard->rx_buffer_offset + length - 4) >= RX_BUFFER_SIZE) {
+ // FIXME Beim Umbruch gehen Daten kaputt
+ memcpy(data, buffer, RX_BUFFER_SIZE - netcard->rx_buffer_offset);
+ memcpy(
+ data + RX_BUFFER_SIZE - netcard->rx_buffer_offset,
+ netcard->rx_buffer,
+ (length - 4) - (RX_BUFFER_SIZE - netcard->rx_buffer_offset)
+ );
+ } else {
+ memcpy(data, buffer, length - 4);
+ }
+
+ cdi_net_receive(
+ (struct cdi_net_device*) netcard,
+ data,
+ length - 4);
+ }
+
+ // Den aktuellen Offset im Lesepuffer anpassen. Jedes Paket ist
+ // uint32_t-aligned, daher anschlie�end Aufrundung.
+ netcard->rx_buffer_offset += length;
+ netcard->rx_buffer_offset = (netcard->rx_buffer_offset + 3) & ~0x3;
+
+ // �berl�ufe abfangen
+ netcard->rx_buffer_offset %= RX_BUFFER_SIZE;
+
+ write_register_word(netcard, REG_CUR_READ_ADDR,
+ netcard->rx_buffer_offset - 0x10);
+
+
+
+ }
+#endif
+}
+
uint32_t rtl8139_handle_interrupt( interrupt_handler_t *handler, uint32_t esp )
{
rtl8139_t *rtl8139 = (rtl8139_t *)handler->driver;
+ uint16_t isr = port16_read( &rtl8139->ISR_port );
+ //~ uint16_t reset_isr = 0;
+
+ port16_write( &rtl8139->ISR_port, isr );
+
#ifdef DEBUG
- printf( "RTL8139 INTERRUPT\n" );
+ printf( "rtl8139: INTERRUPT: %X\n", isr );
#endif
+
+ if( isr & ISR_RECEIVE_OK ) {
+ // TODO: manual says, we should reset the ISR bit first,
+ // then go into a read loop?
+ handle_receive_packet( rtl8139 );
+
+ //~ reset_isr |= ISR_RECEIVE_OK;
+ }
+
+ // reset interrupt lines when consumed
+ //~ port16_write( &rtl8139->ISR_port, reset_isr );
+
return esp;
}
@@ -217,7 +385,9 @@ void rtl8139_print_info( void *obj )
char buf[20];
char buf2[30];
- snprintf( buf2, 30, "unknown submodel 0x%X", rtl8139->model_id );
+ if( rtl8139->model == NULL ) {
+ snprintf( buf2, 30, "unknown submodel 0x%X", rtl8139->model_id );
+ }
network_mac_to_string( rtl8139->base.mac_address, buf, 20 );
printf( "rtl8139 NIC type %s\n at I/O base 0x%X, interrupt 0x%X, MAC: %s\n",
( rtl8139->model != NULL ) ? rtl8139->model : buf2,
diff --git a/src/drivers/net/rtl8139.h b/src/drivers/net/rtl8139.h
index 91a7495..58b2167 100644
--- a/src/drivers/net/rtl8139.h
+++ b/src/drivers/net/rtl8139.h
@@ -11,15 +11,19 @@ typedef struct {
network_t base;
port8_t MAC_port[NOF_MAC_REGISTERS];
port32_t RBSTART_port;
+ port8_t ERSR_port;
port8_t CMD_port;
+ port16_t CAPR_port;
port16_t IMR_port;
port16_t ISR_port;
port32_t TCR_port;
port32_t RCR_port;
+ port32_t MPC_port;
pci_device_descriptor_t pci_descriptor;
uint32_t model_id;
const char *model;
uint8_t *receive_buffer;
+ uint16_t receive_buffer_pos;
interrupt_handler_t interrupt_handler;
} rtl8139_t;
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index c1f7cd1..486e04f 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -16,6 +16,7 @@
#include "video.h"
#include "pci.h"
#include "memorymanagement.h"
+#include "network.h"
#include "setjmp.h"
@@ -35,6 +36,7 @@ static jmp_buf panic_jmp_buf;
static void handle_keyboard_event( keyboard_event_t *event, void *context );
static void handle_mouse_event( mouse_event_t *event, void *context );
+static void handle_network_event( network_event_t *event, void *context );
typedef enum {
MODE_TEXT,
@@ -55,6 +57,7 @@ typedef struct {
window_t window2;
window_t window3;
text_widget_t widget3;
+ network_t *network;
} global_context_t;
static global_context_t global_context;
@@ -150,6 +153,14 @@ void kernel_main( void )
// TODO: also, what to do if there is more than one driver?
global_context.video = (video_t *)driver_manager_find_driver( &global_context.driver_manager, DRIVER_TYPE_VIDEO );
+ // network driver testing
+ global_context.network = (network_t *)driver_manager_find_driver( &global_context.driver_manager, DRIVER_TYPE_NETWORK );
+ if( global_context.network == NULL ) {
+ puts( "No suitable network driver found" );
+ } else {
+ ((network_vtable_t *)( global_context.network->base.vtable ))->register_handler( global_context.network, handle_network_event );
+ }
+
puts( "Activating drivers" );
driver_manager_activate_all( &global_context.driver_manager );
@@ -438,3 +449,8 @@ void __stack_chk_fail( void )
// make gcc happy on noreturn does return
for( ;; );
}
+
+void handle_network_event( network_event_t *event, void *context )
+{
+ puts( "NETWORK EVENT" );
+}