From a132fee060fcc849fe59c622ef8010c83f8c041b Mon Sep 17 00:00:00 2001 From: Andreas Baumann Date: Tue, 1 Aug 2017 21:06:18 +0200 Subject: correctly receiving data in the rtl8139 driver and passing it to the network handler, in Qemu user network we see complete ARP requests now (sent by Qemu itself presumably to update it's 'router' table (an external telnet localhost 8080 is needed to trigger that) --- README | 3 ++ doc/LINKS.TODO | 9 ++++ src/README | 2 + src/drivers/net/network.h | 2 + src/drivers/net/rtl8139.c | 117 ++++++++++++++++++++-------------------------- src/drivers/net/rtl8139.h | 1 - src/kernel/kernel.c | 2 +- 7 files changed, 68 insertions(+), 68 deletions(-) diff --git a/README b/README index f35750c..aa75fbd 100644 --- a/README +++ b/README @@ -98,3 +98,6 @@ https://code.google.com/archive/p/fpos/source/default/source, FreePascal https://mirage.io/ http://www.jamesmolloy.co.uk/tutorial_html/ http://prettyos.de +http://www.jbox.dk/sanos/index.htm +https://github.com/omarrx024/xos/ +http://minirighi.sourceforge.net diff --git a/doc/LINKS.TODO b/doc/LINKS.TODO index 557e598..4824e48 100644 --- a/doc/LINKS.TODO +++ b/doc/LINKS.TODO @@ -113,3 +113,12 @@ http://wiki.osdev.org/Detecting_Memory_(x86) Networking: http://wiki.osdev.org/RTL8139 http://lowlevel.eu/wiki/RTL8139 +https://gist.github.com/pdumais/f5a2aff025fc7a3fe6bc +http://linuxgazette.net/156/jangir.html +http://blog.elastocloud.org/2015/07/qemukvm-bridged-network-with-tap.html + +Ethernet: +https://en.wikipedia.org/wiki/EtherType + +ARP: +https://tools.ietf.org/html/rfc826 diff --git a/src/README b/src/README index 957d477..c2e9065 100644 --- a/src/README +++ b/src/README @@ -51,6 +51,8 @@ Driver framework and specific drivers. * hdi/ps2/ps2mouse.c - PS/2 mouse * video/video.c - generic video interface * video/vga.c - standard VGA video driver +* net/network.c - generic network interface +* net/rtl8139.c - driver for the RealTek8139 network card gui --- diff --git a/src/drivers/net/network.h b/src/drivers/net/network.h index 751ca40..a4ffca0 100644 --- a/src/drivers/net/network.h +++ b/src/drivers/net/network.h @@ -11,6 +11,8 @@ typedef struct { } network_mac_address_t; typedef struct { + uint16_t length; + uint8_t *data; } network_event_t; typedef void (*network_event_handler_t)( network_event_t *event, void *context ); diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index 4f32815..34f273c 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -22,7 +22,6 @@ static rtl8139_vtable_t const rtl8139_vtable = { // 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 @@ -56,6 +55,7 @@ static rtl8139_vtable_t const rtl8139_vtable = { // values for REG_TCR (transmit configuration register) #define TCR_IFG_STANDARD 0x03000000 #define TCR_MXDMA_2048 0x00000700 +#define TCR_APPEND_CRC 0x00010000 // values for REG_RCR (receive configuration register) #define RCR_MXDMA_UNLIMITED 0x00000700 @@ -87,7 +87,8 @@ static rtl8139_vtable_t const rtl8139_vtable = { #define PACKET_HEADER_ROK 0x0001 // receive buffer, set to 8k + header (16) + wrap (2k) -#define RECEIVE_BUFFER_SIZE 8192 + 16 + 2048 +#define RECEIVE_BUFFER_SIZE 8192 +#define RECEIVE_TOTAL_BUFFER_SIZE RECEIVE_BUFFER_SIZE + 16 + 2048 void rtl8139_init( rtl8139_t *rtl8139, pci_controller_t *pci, pci_device_descriptor_t *descriptor, interrupt_t *interrupt, void *context ) { @@ -106,7 +107,6 @@ void rtl8139_init( rtl8139_t *rtl8139, pci_controller_t *pci, pci_device_descrip 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 ); @@ -171,14 +171,14 @@ void rtl8139_init( rtl8139_t *rtl8139, pci_controller_t *pci, pci_device_descrip } // initialize TCR/RCR (take Lowlevel suggestions: TCR = 0x03000700, RCR = 0x0000070a) - port32_write( &rtl8139->TCR_port, TCR_IFG_STANDARD | TCR_MXDMA_2048 ); + port32_write( &rtl8139->TCR_port, TCR_IFG_STANDARD | TCR_APPEND_CRC | TCR_MXDMA_2048 ); 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 *)aligned_alloc( 16, RECEIVE_BUFFER_SIZE + 16 ); - memset( rtl8139->receive_buffer, 0xFE, RECEIVE_BUFFER_SIZE + 16 ); + rtl8139->receive_buffer = (uint8_t *)aligned_alloc( 16, RECEIVE_TOTAL_BUFFER_SIZE ); + memset( rtl8139->receive_buffer, 0, RECEIVE_TOTAL_BUFFER_SIZE ); port32_write( &rtl8139->RBSTART_port, (uint32_t)rtl8139->receive_buffer ); rtl8139->receive_buffer_pos = 0; @@ -226,9 +226,6 @@ void rtl8139_deinit( void *obj ) 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 ); @@ -238,31 +235,13 @@ static void handle_receive_packet( rtl8139_t *rtl8139 ) } 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; @@ -276,41 +255,46 @@ static void handle_receive_packet( rtl8139_t *rtl8139 ) printf( "rtl8139: rcv len: %d\n", len ); #endif +#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 ); + printf( "rtl8139: RBSTART: %X, CAPR: %X, RBPOS: %X, MPC: %X\n", + rbstart, capr, rtl8139->receive_buffer_pos, mpc ); + printf( "rtl8139: " ); for( int i = 0; i < len; i++ ) { + printf( "%X ", rtl8139->receive_buffer[rtl8139->receive_buffer_pos+i] ); + } + puts( "" ); +#endif + + // copy data for the handler of the network event + network_event_t event; + event.length = len; + event.data = (uint8_t *)malloc( len ); + memcpy( event.data, buffer, len ); + memset( rtl8139->receive_buffer, 0, len + 2 * sizeof( uint16_t ) ); + + // adjust buffer pos + rtl8139->receive_buffer_pos += 2 * sizeof( uint16_t ); + rtl8139->receive_buffer_pos += len; + rtl8139->receive_buffer_pos = ( rtl8139->receive_buffer_pos + 3 ) & ~0x3; + if( rtl8139->receive_buffer_pos >= RECEIVE_TOTAL_BUFFER_SIZE ) { + rtl8139->receive_buffer_pos = 0; } + // initial CAPS is set to FFF0, we deduce from this that we have + // to subtract 16 from the actual buffer offset (not mentioned in + // documentation of the card!) + port16_write( &rtl8139->CAPR_port, rtl8139->receive_buffer_pos - 16 ); + + rtl8139->base.handler( &event, rtl8139 ); } #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)) @@ -334,16 +318,18 @@ static void handle_receive_packet( rtl8139_t *rtl8139 ) 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; + // Den aktuellen Offset im Lesepuffer anpassen. Jedes Paket ist + // dword-aligned, daher anschließend Aufrundung. + netcard->rx_buffer_offset += length + 4; + netcard->rx_buffer_offset = (netcard->rx_buffer_offset + 3) & ~0x3; - write_register_word(netcard, REG_CUR_READ_ADDR, - netcard->rx_buffer_offset - 0x10); + // Überläufe abfangen + netcard->rx_buffer_offset %= 0x2000; + + write_register_word(netcard, REG_CUR_READ_ADDR, + netcard->rx_buffer_offset - 0x10); @@ -356,8 +342,9 @@ 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; + uint16_t reset_isr = 0; + // TODO: early interrupt line cleaning or later? port16_write( &rtl8139->ISR_port, isr ); #ifdef DEBUG @@ -369,12 +356,10 @@ uint32_t rtl8139_handle_interrupt( interrupt_handler_t *handler, uint32_t esp ) // 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 ); + //~ port16_write( &rtl8139->ISR_port, isr ); return esp; } diff --git a/src/drivers/net/rtl8139.h b/src/drivers/net/rtl8139.h index 7419f65..462526a 100644 --- a/src/drivers/net/rtl8139.h +++ b/src/drivers/net/rtl8139.h @@ -11,7 +11,6 @@ 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; diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 486e04f..23a8d72 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -452,5 +452,5 @@ void __stack_chk_fail( void ) void handle_network_event( network_event_t *event, void *context ) { - puts( "NETWORK EVENT" ); + printf( "NETWORK DATA: len: %d\n", event->length ); } -- cgit v1.2.3-54-g00ecf