summaryrefslogtreecommitdiff
path: root/src/drivers/net/rtl8139.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/drivers/net/rtl8139.c')
-rw-r--r--src/drivers/net/rtl8139.c117
1 files changed, 51 insertions, 66 deletions
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;
}