]> git.llucax.com Git - z.facultad/66.09/etherled.git/blobdiff - pruebas/keil/red_test_anda/etherdev.c
Implementa el protocolo ELP sobre UDP. Tiene problemas cuando los leds estan
[z.facultad/66.09/etherled.git] / pruebas / keil / red_test_anda / etherdev.c
index c3a342e5588f0fcb0bc9c28266105ffc637ca094..93abcbf4198b9e38999ad673d520a5094296c521 100644 (file)
@@ -1,34 +1,28 @@
+// vim: set et sw=4 sts=4 :    
+
+#include "types.h"
 #include "etherdev.h"
 
 void sleep(unsigned char);
 
 #include "etherdev.h"
 
 void sleep(unsigned char);
 
-static xdata leds1 _at_ 0x0080;
-static xdata leds2 _at_ 0x00c0;
+#ifdef SDCC
+static xdata at 0x0080 byte leds1;
+static xdata at 0x00c0 byte leds2;
+#else
+static byte xdata leds1 _at_ 0x0080;
+static byte xdata leds2 _at_ 0x00c0;
+#endif
 
 
-unsigned char uip_buf[64] =
+unsigned char uip_buf[80] =
 {
 {
-       //0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino
-       0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino
+       0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino
+       //0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino
        0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente
        0x00, 0x00, // Type
 };
 
 unsigned int uip_len = 14;
 
        0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente
        0x00, 0x00, // Type
 };
 
 unsigned int uip_len = 14;
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                            Private defines.                         º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-#define ETH_CPU_CLOCK      ETH_CPU_XTAL / 12    // 8051 clock rate (X1 mode)
-
-// Delay routine timing parameters
-#define ETH_DELAY_CONST    9.114584e-5          // Delay routine constant
-#define ETH_DELAY_MULTPLR  (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)
-
-// X1 CPU mode timing parameters
-#define ETH_T0_CLOCK             ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate
-#define ETH_T0_INT_RATE          24                // Timer 0 intrupt rate (Hz)
-#define ETH_T0_RELOAD            65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)
-
 // Packet transmit & receive buffer configuration
 #define ETH_TX_PAGE_START  0x40    // 0x4000 Tx buffer is  6 * 256 = 1536 bytes
 #define ETH_RX_PAGE_START  0x46    // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
 // Packet transmit & receive buffer configuration
 #define ETH_TX_PAGE_START  0x40    // 0x4000 Tx buffer is  6 * 256 = 1536 bytes
 #define ETH_RX_PAGE_START  0x46    // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
@@ -37,22 +31,12 @@ unsigned int uip_len = 14;
 #define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y
 #define ETH_DATA_PORT_MASK 0xFF                 // 11111111y
 
 #define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y
 #define ETH_DATA_PORT_MASK 0xFF                 // 11111111y
 
-#define ETH_MIN_PACKET_LEN 0x3C
+#define ETH_MIN_PACKET_LEN 0x3C                 // 60 bytes
 
 
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                       Private Function Prototypes                   º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
 static unsigned char etherdev_reg_read(unsigned char reg);
 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
 static unsigned char etherdev_reg_read(unsigned char reg);
-static void etherdev_delay_ms(unsigned int count);
-static unsigned int etherdev_poll(void);
-//static void etherdev_timer0_isr(void) interrupt 1 using 1;
 
 
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                          Private Macro Defines                      º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page. 
 #define ETHERDEV_SELECT_REG_PAGE(page)                                      \
           do                                                                \
 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page. 
 #define ETHERDEV_SELECT_REG_PAGE(page)                                      \
           do                                                                \
@@ -62,22 +46,6 @@ static unsigned int etherdev_poll(void);
           } while(0)
 
 
           } while(0)
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                              Global Variables                       º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-static unsigned char tick_count = 0;
-
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                     Private Function Implementation                 º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                          etherdev_reg_write()                       º
-    º                                                                     º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
 {
     // Select register address.
 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
 {
     // Select register address.
@@ -89,24 +57,15 @@ static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
 
     // Clock register data into RTL8019AS.
     // IOR & IOW are both active low.
 
     // Clock register data into RTL8019AS.
     // IOR & IOW are both active low.
-       NICE = 0;
+    NICE = 0;
     IOW = 0;
     IOW = 1;
     IOW = 0;
     IOW = 1;
-       NICE = 1;
-
-    // Set register data port as input again.
-    ETH_DATA_PORT = ETH_DATA_PORT_MASK;
+    NICE = 1;
 
     return;
 } 
 
 
 
     return;
 } 
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                          etherdev_reg_read()                        º
-    º                                                                     º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
 static unsigned char etherdev_reg_read(unsigned char reg)
 {
     unsigned char rd_data;
 static unsigned char etherdev_reg_read(unsigned char reg)
 {
     unsigned char rd_data;
@@ -115,8 +74,11 @@ static unsigned char etherdev_reg_read(unsigned char reg)
     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
     ETH_ADDR_PORT |= reg;
 
     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
     ETH_ADDR_PORT |= reg;
 
+    // Set register data port as input.
+    ETH_DATA_PORT = ETH_DATA_PORT_MASK;
+
     // Enable register data output from RTL8019AS.
     // Enable register data output from RTL8019AS.
-       NICE = 0;
+    NICE = 0;
     IOR = 0;
 
     // Read register data from port.
     IOR = 0;
 
     // Read register data from port.
@@ -124,75 +86,30 @@ static unsigned char etherdev_reg_read(unsigned char reg)
 
     // Disable register data output from RTL8019AS.
     IOR = 1; 
 
     // Disable register data output from RTL8019AS.
     IOR = 1; 
-       NICE = 1;   
+    NICE = 1;   
 
     return rd_data;
 } 
 
 
 
     return rd_data;
 } 
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                          etherdev_delay_ms()                        º
-    º                                                                     º
-    º  1 to 255+ ms delay.                                                º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-static void etherdev_delay_ms(unsigned int count)
-{
-
-    for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;
-
-    return;
-}
-
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                           etherdev_timer0_isr()                     º
-    º                                                                     º
-    º This function is invoked each 1/24th of a second and updates a      º
-    º 1/24th of a second tick counter.                                    º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-static void etherdev_timer0_isr(void) interrupt 1 using 1
-{
-    // Reload timer/ counter 0 for 24Hz periodic interrupt.   
-    TH0 = ETH_T0_RELOAD >> 8;
-    TL0 = ETH_T0_RELOAD;
-
-    // Increment 24ths of a second counter.
-    tick_count++;
-
-    return;
-}
-
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                     Public Function Implementation                  º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                            etherdev_init()                          º
-    º                                                                     º
-    º  Returns: 1 on success, 0 on failure.                               º
-    º  Refer to National Semiconductor DP8390 App Note 874, July 1993.    º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-bit etherdev_init(void)
+/*
+                                                                     
+                            etherdev_init()                          
+                                                                     
+  Returns: 1 on success, 0 on failure.                               
+  Refer to National Semiconductor DP8390 App Note 874, July 1993.    
+                                                                     
+ */
+bool etherdev_init(void)
 {
     // Set IOR & IOW as they're active low.
     IOR = 1;
     IOW = 1;
 {
     // Set IOR & IOW as they're active low.
     IOR = 1;
     IOW = 1;
-       NICE = 1;
+    NICE = 1;
 
     // Set register data port as input.
     ETH_DATA_PORT = ETH_DATA_PORT_MASK;
 
 
     // Set register data port as input.
     ETH_DATA_PORT = ETH_DATA_PORT_MASK;
 
-#ifdef ETH_DEBUG
-    init_sio_poll();
-#endif /* ETH_DEBUG */
-
     // Configure RTL8019AS ethernet controller.
 
     // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
     // Configure RTL8019AS ethernet controller.
 
     // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
@@ -205,32 +122,11 @@ bit etherdev_init(void)
     // Check if RTL8019AS fully reset.
     if(!(etherdev_reg_read(ISR) & RST))
     {
     // Check if RTL8019AS fully reset.
     if(!(etherdev_reg_read(ISR) & RST))
     {
-leds1 = ~0xff;
-leds2 = ~0xff;
-while(1);
         return 0;
     }
         return 0;
     }
-/*
-    // Select RTL8019AS register page 3.
-    ETHERDEV_SELECT_REG_PAGE(3);
-
-    // Temporarily disable config register write protection.
-    etherdev_reg_write(_9346CR, EEM1 | EEM0);
-
-    // Disable boot ROM & select 10BaseT with TP/CX auto-detect.
-    etherdev_reg_write(CONFIG2, BSELB);
-
-    // Select half-duplex, awake, power-up & LED_TX/ LED_RX/ LED_LNK behaviour.
-    etherdev_reg_write(CONFIG3, LEDS0);
-
-    // Re-enable config register write protection.
-    etherdev_reg_write(_9346CR, 0x00);
-*/
-    // Select RTL8019AS register page 0.
-    ETHERDEV_SELECT_REG_PAGE(0);
 
     // Stop RTL8019AS, select page 0 and abort DMA operation.
 
     // Stop RTL8019AS, select page 0 and abort DMA operation.
-    etherdev_reg_write(CR, RD2 | STP);
+    etherdev_reg_write(CR, ABORT | STP);
 
     // Initialise data configuration register. 
     // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
 
     // Initialise data configuration register. 
     // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
@@ -244,17 +140,41 @@ while(1);
     etherdev_reg_write(RCR, MON);
 
     // Initialise transmit configuration register to loopback internally.
     etherdev_reg_write(RCR, MON);
 
     // Initialise transmit configuration register to loopback internally.
-    etherdev_reg_write(TCR, LB0);
+    etherdev_reg_write(TCR, MODE1);
 
     // Clear interrupt status register bits by writing 1 to each.
     etherdev_reg_write(ISR, 0xFF);
 
     // Mask all interrupts in mask register.
     etherdev_reg_write(IMR, 0x00);
 
     // Clear interrupt status register bits by writing 1 to each.
     etherdev_reg_write(ISR, 0xFF);
 
     // Mask all interrupts in mask register.
     etherdev_reg_write(IMR, 0x00);
+    
+    // Obtengo MAC de la placa
+    etherdev_reg_write(RBCR0, 0x0c); // Vamos a leer 12 bytes (2 x 6)
+    etherdev_reg_write(RBCR1, 0x00); 
+    etherdev_reg_write(RSAR0, 0x00); // En la dirección 0x0000
+    etherdev_reg_write(RSAR1, 0x00);
+    etherdev_reg_write(CR, READ | STA); // Comienza lectura
+    uip_buf[6] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+    uip_buf[7] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+    uip_buf[8] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+    uip_buf[9] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+    uip_buf[10] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+    uip_buf[11] = etherdev_reg_read(RDMA);
+    etherdev_reg_read(RDMA); // Ignoramos porque viene como un word
+
+    // Wait until remote DMA operation completes.
+    while(!(etherdev_reg_read(ISR) & RDC)) continue;
 
 
-       // Obtengo MAC de la placa
-    //etherdev_reg_write(CR, 0x21);
+    // Abort/ complete DMA operation.
+    etherdev_reg_write(CR, ABORT | STP);
 
 
+    // Limpia ISR
+    etherdev_reg_write(ISR, RDC);
 
     // Set transmit page start.
     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
 
     // Set transmit page start.
     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
@@ -269,87 +189,55 @@ while(1);
     etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
 
     // Select RTL8019AS register page 1.
     etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
 
     // Select RTL8019AS register page 1.
-    etherdev_reg_write(CR, RD2 | PS0 | STP);
+    etherdev_reg_write(CR, ABORT | PAGE1 | STP);
 
     // Initialise current packet receive buffer page pointer
 
     // Initialise current packet receive buffer page pointer
-    etherdev_reg_write(CURR, ETH_RX_PAGE_START);
+    etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
 
     // Set physical address
 
     // Set physical address
-    etherdev_reg_write(PAR0, 0x00);
-    etherdev_reg_write(PAR1, 0x0c);
-    etherdev_reg_write(PAR2, 0x6e);
-    etherdev_reg_write(PAR3, 0x37);
-    etherdev_reg_write(PAR4, 0x19);
-    etherdev_reg_write(PAR5, 0xbe);
+    etherdev_reg_write(PAR0, uip_buf[6]);
+    etherdev_reg_write(PAR1, uip_buf[7]);
+    etherdev_reg_write(PAR2, uip_buf[8]);
+    etherdev_reg_write(PAR3, uip_buf[9]);
+    etherdev_reg_write(PAR4, uip_buf[10]);
+    etherdev_reg_write(PAR5, uip_buf[11]);
 
     // Select RTL8019AS register page 0 and abort DMA operation.
 
     // Select RTL8019AS register page 0 and abort DMA operation.
-    etherdev_reg_write(CR, RD2 | STP);
+    etherdev_reg_write(CR, ABORT | STP);
 
     // Restart RTL8019AS. 
 
     // Restart RTL8019AS. 
-    etherdev_reg_write(CR, RD2 | STA);
+    etherdev_reg_write(CR, ABORT | STA);
 
     // Initialise transmit configuration register for normal operation.
 
     // Initialise transmit configuration register for normal operation.
-    etherdev_reg_write(TCR, 0x00);
+    etherdev_reg_write(TCR, MODE0);
 
     // Receive configuration register to accept broadcast packets.
     etherdev_reg_write(RCR, AB);
 
 
     // Receive configuration register to accept broadcast packets.
     etherdev_reg_write(RCR, AB);
 
-
-    // Initialize Timer 0 to generate a periodic 24Hz interrupt. 
-
-    // Stop timer/ counter 0.                                         
-    TR0  = 0;          
-
-    // Set timer/ counter 0 as mode 1 16 bit timer.      
-    TMOD &= 0xF0;
-    TMOD |= 0x01;
-
-    // Preload for 24Hz periodic interrupt.    
-    TH0 = ETH_T0_RELOAD >> 8; 
-    TL0 = ETH_T0_RELOAD;
-
-    // Restart timer/ counter 0 running.
-    TR0 = 1;
-
-    // Enable timer/ counter 0 overflow interrupt.            
-    ET0 = 1;
-
-    // Enable global interrupt.
-    EA = 1;
-
     return 1;
 }
 
 
     return 1;
 }
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                           etherdev_send()                           º
-    º                                                                     º
-    º Send the packet in the uip_buf and uip_appdata buffers using the    º
-    º RTL8019AS ethernet card.                                            º
-    º                                                                     º
   ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
+/*
+                                                                     
+                           etherdev_send()                           
+                                                                     
+ Send the packet in the uip_buf and uip_appdata buffers using the    
+ RTL8019AS ethernet card.                                            
+                                                                     
+ */
 void etherdev_send(void)
 {
     unsigned int i;
 void etherdev_send(void)
 {
     unsigned int i;
-    unsigned char *ptr;
-
-    ptr = uip_buf;
 
     // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
 
     // Select RTL8019AS register page 0 and abort DMA operation.
 
     // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
 
     // Select RTL8019AS register page 0 and abort DMA operation.
-    etherdev_reg_write(CR, RD2 | STA);
+    etherdev_reg_write(CR, ABORT | STA);
 
 
-leds1 = ~0x01;
-i = etherdev_reg_read(CR);
-leds2 = ~i;
     // Wait until pending transmit operation completes.
     while(etherdev_reg_read(CR) & TXP) continue;
 
     // Wait until pending transmit operation completes.
     while(etherdev_reg_read(CR) & TXP) continue;
 
-    // Clear remote DMA complete interrupt status register bit.
-    etherdev_reg_write(ISR, RDC);
-
     // Set remote DMA start address registers to indicate where to load packet.
     etherdev_reg_write(RSAR0, 0x00);
     etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
     // Set remote DMA start address registers to indicate where to load packet.
     etherdev_reg_write(RSAR0, 0x00);
     etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
@@ -359,22 +247,23 @@ leds2 = ~i;
     etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
 
     // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
     etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
 
     // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
-    etherdev_reg_write(CR, RD1 | STA);
+    etherdev_reg_write(CR, WRITE | STA);
 
     // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
     // transmit buffer memory.
     for(i = 0; i < uip_len; i++)
     {
 
     // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
     // transmit buffer memory.
     for(i = 0; i < uip_len; i++)
     {
-        etherdev_reg_write(RDMA, *ptr++);
+        etherdev_reg_write(RDMA, uip_buf[i]);
     }
 
     // Wait until remote DMA operation complete.
     }
 
     // Wait until remote DMA operation complete.
-leds1 = ~0x02;
-leds2 = ~etherdev_reg_read(ISR);
     while(!(etherdev_reg_read(ISR) & RDC)) continue;
 
     while(!(etherdev_reg_read(ISR) & RDC)) continue;
 
+    // Clear remote DMA complete interrupt status register bit.
+    etherdev_reg_write(ISR, RDC);
+
     // Abort/ complete DMA operation.
     // Abort/ complete DMA operation.
-    etherdev_reg_write(CR, RD2 | STA);
+    etherdev_reg_write(CR, ABORT | STA);
 
     // Set transmit page start to indicate packet start.
     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
 
     // Set transmit page start to indicate packet start.
     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
@@ -390,218 +279,236 @@ leds2 = ~etherdev_reg_read(ISR);
     etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
 
     // Issue command for RTL8019AS to transmit packet from it's local buffer.
     etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
 
     // Issue command for RTL8019AS to transmit packet from it's local buffer.
-    etherdev_reg_write(CR, RD2 | TXP | STA);
+    etherdev_reg_write(CR, ABORT | TXP | STA);
 
     return;
 }
 
 
 
     return;
 }
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                           etherdev_read()                           º
-    º                                                                     º
-    º This function will read an entire IP packet into the uip_buf.       º
-    º If it must wait for more than 0.5 seconds, it will return with      º
-    º the return value 0. Otherwise, when a full packet has been read     º
-    º into the uip_buf buffer, the length of the packet is returned.      º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-unsigned int etherdev_read(void)
-{    
-    unsigned int bytes_read;
-
-    /* tick_count threshold should be 12 for 0.5 sec bail-out
-       One second (24) worked better for me, but socket recycling
-       is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
-       to counter this. Retransmission timing etc. is affected also. */
-    while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;
+static void etherdev_reset()
+{
+    bit retransmit = etherdev_reg_read(CR) & TXP;
 
 
-    tick_count = 0;
+    // If the receive buffer ring has overflowed we dump the whole
+    // thing and start over. There is no way of knowing whether the
+    // data it contains is uncorrupted, or will cause us grief.
 
 
-    return bytes_read;
-}
+    // Stop RTL8019AS and abort DMA operation.
+    etherdev_reg_write(CR, ABORT | STP);
 
 
+    // Wait for controller to halt after any current tx completes.
+    while(!(etherdev_reg_read(ISR) & RST)) continue;
 
 
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
-    º                                                                     º
-    º                           etherdev_poll()                           º
-    º                                                                     º
-    º Poll the RTL8019AS ethernet device for an available packet.         º
-    º                                                                     º
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
-static unsigned int etherdev_poll(void)
-{
-    unsigned int len = 0;
+    // Reset remote byte count registers.
+    etherdev_reg_write(RBCR0, 0x00);
+    etherdev_reg_write(RBCR1, 0x00);
 
 
-    // Check if there is a packet in the rx buffer.
-    if(etherdev_reg_read(ISR) & PRX)
+    // Check whether currently transmitting a packet.
+    if(retransmit)
     {
     {
-        // Check if the rx buffer has overflowed.
-        if(etherdev_reg_read(ISR) & OVW)
+        // If neither a successful transmission nor a tx abort error 
+        // has occured, then flag current tx packet for resend.
+        if(etherdev_reg_read(ISR) & (PTX | TXE))
         {
         {
-            bit retransmit = 0;
+            retransmit = 0;
+        }
+    }
 
 
-            // If the receive buffer ring has overflowed we dump the whole
-            // thing and start over. There is no way of knowing whether the
-            // data it contains is uncorrupted, or will cause us grief.
+    // Set transmit configuration register to loopback internally.
+    etherdev_reg_write(TCR, MODE1);
 
 
-            // Stop RTL8019AS and abort DMA operation.
-            etherdev_reg_write(CR, RD2 | STP);
+    // Restart the RTL8019AS.
+    etherdev_reg_write(CR, ABORT | STA);
 
 
-            // Reset remote byte count registers.
-            etherdev_reg_write(RBCR0, 0x00);
-            etherdev_reg_write(RBCR1, 0x00);
+    // Re-initialise last receive buffer read pointer.
+    etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
 
 
-            // Wait for controller to halt after any current tx completes.
-            while(!(etherdev_reg_read(ISR) & RST)) continue;
+    // Select RTL8019AS register page 1.
+    ETHERDEV_SELECT_REG_PAGE(1);
 
 
-            // Check whether currently transmitting a packet.
-            if(etherdev_reg_read(CR) & TXP)
-            {
-                // If neither a successful transmission nor a tx abort error 
-                // has occured, then flag current tx packet for resend.
-                if(!((etherdev_reg_read(ISR) & PTX)
-                                          || (etherdev_reg_read(ISR) & TXE)))
-                {
-                    retransmit = 1;
-                }
-            }
+    // Re-initialise current packet receive buffer page pointer.
+    etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
 
 
-            // Set transmit configuration register to loopback internally.
-            etherdev_reg_write(TCR, LB0);
+    // Select RTL8019AS register page 0.
+    ETHERDEV_SELECT_REG_PAGE(0);
 
 
-            // Restart the RTL8019AS.
-            etherdev_reg_write(CR, RD2 | STA);
+    // Clear rx buffer overflow & packet received interrupt flags.
+    etherdev_reg_write(ISR, PRX | OVW);
 
 
-            // Re-initialise last receive buffer read pointer.
-            etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
+    // Re-itialise transmit configuration reg for normal operation.
+    etherdev_reg_write(TCR, MODE0);
 
 
-            // Select RTL8019AS register page 1.
-            ETHERDEV_SELECT_REG_PAGE(1);
+    if(retransmit)
+    {
+        // Retransmit packet in RTL8019AS local tx buffer.
+        etherdev_reg_write(CR, ABORT | TXP | STA);
+    }
+}
 
 
-            // Re-initialise current packet receive buffer page pointer.
-            etherdev_reg_write(CURR, ETH_RX_PAGE_START);
 
 
-            // Select RTL8019AS register page 0.
-            ETHERDEV_SELECT_REG_PAGE(0);
+unsigned int etherdev_read(void)
+{    
+    unsigned int len = 0;
 
 
-            // Clear rx buffer overflow & packet received interrupt flags.
-            etherdev_reg_write(ISR, PRX | OVW);
+    // Check if the rx buffer has overflowed.
+    if (etherdev_reg_read(ISR) & OVW)
+    {
+        unsigned char current;
 
 
-            // Re-itialise transmit configuration reg for normal operation.
-            etherdev_reg_write(TCR, 0x00);
-        
-            if(retransmit)
-            {
-                // Retransmit packet in RTL8019AS local tx buffer.
-                etherdev_reg_write(CR, RD2 | TXP | STA);
-            }
-        }
-        else // Rx buffer has not overflowed, so read a packet into uip_buf.
-        {
-            unsigned int i;
-            unsigned char next_rx_packet;
-            unsigned char current;
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(1);
 
 
-            // Retrieve packet header. (status, next_ptr, length_l, length_h)
+        // Retrieve current receive buffer page
+        current = etherdev_reg_read(CURR);
 
 
-            // Clear remote DMA complete interrupt status register bit.
-            etherdev_reg_write(ISR, RDC);
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(0);
+
+        if (etherdev_reg_read(BNRY) == current)
+        {
+
+            leds1 = ~0x01;
+            leds2 = ~etherdev_reg_read(ISR);
+            sleep(5);
+            leds1 = ~0x02;
+            leds2 = ~etherdev_reg_read(BNRY);
+            sleep(5);
+            leds1 = ~0x04;
+            leds2 = ~current;
+            sleep(5);
+
+            etherdev_reset();
+        }
+    }
+    // Check if there is a packet in the rx buffer.
+    else if (etherdev_reg_read(ISR) & PRX)
+    {
+        unsigned int i;
+        unsigned char next_rx_packet;
+        unsigned char current;
+        unsigned char bnry;
+        unsigned char status;
 
 
-            // Set remote DMA start address registers to packet header.
-            etherdev_reg_write(RSAR0, 0x00);
-            etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
+        // Retrieve packet header. (status, next_ptr, length_l, length_h)
 
 
-            // Set remote DMA byte count registers to packet header length.
-            etherdev_reg_write(RBCR0, 0x04);
-            etherdev_reg_write(RBCR1, 0x00);
+        // Set remote DMA start address registers to packet header.
+        bnry = etherdev_reg_read(BNRY) + 1;
+        if (bnry >= ETH_RX_PAGE_STOP)
+            bnry = ETH_RX_PAGE_START;
+        etherdev_reg_write(RSAR0, 0x00);
+        etherdev_reg_write(RSAR1, bnry);
 
 
-            // Initiate DMA transfer of packet header.
-            etherdev_reg_write(CR, RD0 | STA);
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(1);
 
 
-            // Drop packet status. We don't use it.
-            etherdev_reg_read(RDMA);
+        // Retrieve current receive buffer page
+        current = etherdev_reg_read(CURR);
 
 
-            // Save next packet pointer.
-            next_rx_packet = etherdev_reg_read(RDMA);
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(0);
 
 
-            // Retrieve packet data length and subtract CRC bytes.
-            len =  etherdev_reg_read(RDMA);
-            len += etherdev_reg_read(RDMA) << 8;
-            len -= 4;
+        // Check if last packet has been removed from rx buffer.
+        if(bnry == current)
+        {
+            // Clear packet received interrupt flag.
+            etherdev_reg_write(ISR, PRX | RXE);
+            return 0;
+        }
 
 
-            // Wait until remote DMA operation completes.
-            while(!(etherdev_reg_read(ISR) & RDC)) continue;
+        // Set remote DMA byte count registers to packet header length.
+        etherdev_reg_write(RBCR0, 0x04);
+        etherdev_reg_write(RBCR1, 0x00);
 
 
-            // Abort/ complete DMA operation.
-            etherdev_reg_write(CR, RD2 | STA);
+        // Clear remote DMA complete interrupt status register bit.
+        etherdev_reg_write(ISR, RDC);
 
 
+        // Initiate DMA transfer of packet header.
+        etherdev_reg_write(CR, READ | STA);
 
 
-            // Retrieve packet data.
+        // Packet status.
+        status = etherdev_reg_read(RDMA);
 
 
-            // Check if incoming packet will fit into rx buffer.
-            if(len <= sizeof(uip_buf))
-            {
-                // Clear remote DMA complete interrupt status register bit.
-                etherdev_reg_write(ISR, RDC);
+        // Save next packet pointer.
+        next_rx_packet = etherdev_reg_read(RDMA);
 
 
-                // Set remote DMA start address registers to packet data.
-                etherdev_reg_write(RSAR0, 0x04);
-                etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
+        // Retrieve packet data length and subtract CRC bytes.
+        len =  etherdev_reg_read(RDMA);
+        len += etherdev_reg_read(RDMA) << 8;
+        len -= 4;
 
 
-                // Set remote DMA byte count registers to packet data length.
-                etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
-                etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
+        // Wait until remote DMA operation completes.
+        while(!(etherdev_reg_read(ISR) & RDC)) continue;
 
 
-                // Initiate DMA transfer of packet data.
-                etherdev_reg_write(CR, RD0 | STA);
+        // Abort/ complete DMA operation.
+        etherdev_reg_write(CR, ABORT | STA);
 
 
-                // Read packet data directly into uip_buf.
-                for(i = 0; i < len; i++)
-                {
-                    *(uip_buf + i) = etherdev_reg_read(RDMA);
-                }
+        // Limpia ISR
+        etherdev_reg_write(ISR, RDC);
 
 
-                // Wait until remote DMA operation complete.
-                while(!(etherdev_reg_read(ISR) & RDC)) continue;
+        // Si es un paquete inválido, lo dropeamos
+        if (len < 60 || len > 1518)
+        {
+            len = 0;
+            goto drop;
+        }
 
 
-                // Abort/ complete DMA operation.
-                etherdev_reg_write(CR, RD2 | STA);
+        // Si hubo un error, también lo dropeamos
+        if ((status & 0x0F) != RXSOK)
+        {
+            len = 0;
+            goto drop;
+        }
 
 
-            }
-            else
-            {
-                // Incoming packet too big, so dump it.
-                len = 0;
-            }
+        // Retrieve packet data.
 
 
-            // Advance boundary pointer to next packet start.
-            etherdev_reg_write(BNRY, next_rx_packet);
+        // Check if incoming packet will fit into rx buffer.
+        if(len <= sizeof(uip_buf))
+        {
 
 
-            // Select RTL8019AS register page 1.
-            ETHERDEV_SELECT_REG_PAGE(1);
+            // Set remote DMA start address registers to packet data.
+            etherdev_reg_write(RSAR0, 0x04);
+            etherdev_reg_write(RSAR1, bnry);
 
 
-            // Retrieve current receive buffer page
-            current = etherdev_reg_read(CURR);
+            // Set remote DMA byte count registers to packet data length.
+            etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
+            etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
 
 
-            // Select RTL8019AS register page 0.
-            ETHERDEV_SELECT_REG_PAGE(0);
+            // Initiate DMA transfer of packet data.
+            etherdev_reg_write(CR, READ | STA);
 
 
-            // Check if last packet has been removed from rx buffer.
-            if(next_rx_packet == current)
+            // Read packet data directly into uip_buf.
+            uip_len = len;
+            for(i = 0; i < 14; i++)
             {
             {
-                // Clear packet received interrupt flag.
-                etherdev_reg_write(ISR, PRX);
+                etherdev_reg_read(RDMA); // XXX descarto cabecera eth
+            }
+            for(i = 14; i < len; i++)
+            {
+                uip_buf[i] = etherdev_reg_read(RDMA); // XXX copio el resto
             }
             }
-        }
-    }
 
 
-    return len;
-}
+            // Wait until remote DMA operation complete.
+            while(!(etherdev_reg_read(ISR) & RDC)) continue;
 
 
+            // Abort/ complete DMA operation.
+            etherdev_reg_write(CR, ABORT | STA);
 
 
+            // Clear remote DMA complete interrupt status register bit.
+            etherdev_reg_write(ISR, RDC);
 
 
+        }
+        else
+        {
+            // Incoming packet too big, so dump it.
+            len = 0;
+        }
 
 
+drop:
+        // Advance boundary pointer to next packet start.
+        etherdev_reg_write(BNRY, next_rx_packet - 1);
 
 
+    }
 
 
+    return len;
+}