summaryrefslogtreecommitdiff
path: root/src
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 /src
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)
Diffstat (limited to 'src')
-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" );
+}