]> 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 623a05ad39d393d071a28a4bae2ef01f09650067..93abcbf4198b9e38999ad673d520a5094296c521 100644 (file)
-/*       ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-         º    TITLE:  RTL8019AS ethernet routines for 8051 and      º\r
-         º            Keil C51 v7.00 port of Adam Dunkels' uIP v0.9 º\r
-         º FILENAME:  etherdev.c                                    º\r
-         º REVISION:  VER 0.0                                       º\r
-         º REV.DATE:  21-01-05                                      º\r
-         º  ARCHIVE:                                                º\r
-         º   AUTHOR:  Copyright (c) 2005, Murray R. Van Luyn.       º\r
-         º   Refer to National Semiconductor DP8390 App Note 874.   º\r
-         ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ        */\r
-\r
-/*  ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿\r
-    ³  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS  ³ \r
-    ³  OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  ³ \r
-    ³  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ³ \r
-    ³  ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY    ³ \r
-    ³  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ³ \r
-    ³  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE  ³ \r
-    ³  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS      ³ \r
-    ³  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,       ³ \r
-    ³  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING          ³ \r
-    ³  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ³ \r
-    ³  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.       ³ \r
-    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ  */\r
-\r
-\r
-#include "etherdev.h"\r
-\r
-void sleep(unsigned char);\r
-\r
-static xdata leds1 _at_ 0x0080;\r
-static xdata leds2 _at_ 0x00c0;\r
-\r
-unsigned char uip_buf[64] =\r
-{\r
-       //0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino\r
-       0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino\r
-       0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente\r
-       0x00, 0x00, // Type\r
-};\r
-\r
-unsigned int uip_len = 14;\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                            Private defines.                         º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-#define ETH_CPU_CLOCK      ETH_CPU_XTAL / 12    // 8051 clock rate (X1 mode)\r
-\r
-// Delay routine timing parameters\r
-#define ETH_DELAY_CONST    9.114584e-5          // Delay routine constant\r
-#define ETH_DELAY_MULTPLR  (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)\r
-\r
-// X1 CPU mode timing parameters\r
-#define ETH_T0_CLOCK             ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate\r
-#define ETH_T0_INT_RATE          24                // Timer 0 intrupt rate (Hz)\r
-#define ETH_T0_RELOAD            65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)\r
-\r
-// Packet transmit & receive buffer configuration\r
-#define ETH_TX_PAGE_START  0x40    // 0x4000 Tx buffer is  6 * 256 = 1536 bytes\r
-#define ETH_RX_PAGE_START  0x46    // 0x4600 Rx buffer is 26 * 256 = 6656 bytes\r
-#define ETH_RX_PAGE_STOP   0x60    // 0x6000\r
-\r
-#define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y\r
-#define ETH_DATA_PORT_MASK 0xFF                 // 11111111y\r
-\r
-#define ETH_MIN_PACKET_LEN 0x3C\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                       Private Function Prototypes                   º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);\r
-static unsigned char etherdev_reg_read(unsigned char reg);\r
-static void etherdev_delay_ms(unsigned int count);\r
-static unsigned int etherdev_poll(void);\r
-//static void etherdev_timer0_isr(void) interrupt 1 using 1;\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                          Private Macro Defines                      º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-// Manipulate PS1 & PS0 in CR to select RTL8019AS register page. \r
-#define ETHERDEV_SELECT_REG_PAGE(page)                                      \\r
-          do                                                                \\r
-          {                                                                 \\r
-              etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \\r
-              etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6));  \\r
-          } while(0)\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                              Global Variables                       º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static unsigned char tick_count = 0;\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                     Private Function Implementation                 º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                          etherdev_reg_write()                       º\r
-    º                                                                     º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)\r
-{\r
-    // Select register address.\r
-    ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK; \r
-    ETH_ADDR_PORT |= reg;\r
-\r
-    // Output register data to port.\r
-    ETH_DATA_PORT = wr_data;\r
-\r
-    // Clock register data into RTL8019AS.\r
-    // IOR & IOW are both active low.\r
-       NICE = 0;\r
-    IOW = 0;\r
-    IOW = 1;\r
-       NICE = 1;\r
-\r
-    // Set register data port as input again.\r
-    ETH_DATA_PORT = ETH_DATA_PORT_MASK;\r
-\r
-    return;\r
-} \r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                          etherdev_reg_read()                        º\r
-    º                                                                     º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static unsigned char etherdev_reg_read(unsigned char reg)\r
-{\r
-    unsigned char rd_data;\r
-\r
-    // Select register address.\r
-    ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;\r
-    ETH_ADDR_PORT |= reg;\r
-\r
-    // Enable register data output from RTL8019AS.\r
-       NICE = 0;\r
-    IOR = 0;\r
-\r
-    // Read register data from port.\r
-    rd_data = ETH_DATA_PORT;\r
-\r
-    // Disable register data output from RTL8019AS.\r
-    IOR = 1; \r
-       NICE = 1;   \r
-\r
-    return rd_data;\r
-} \r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                          etherdev_delay_ms()                        º\r
-    º                                                                     º\r
-    º  1 to 255+ ms delay.                                                º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static void etherdev_delay_ms(unsigned int count)\r
-{\r
-\r
-    for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;\r
-\r
-    return;\r
-}\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                           etherdev_timer0_isr()                     º\r
-    º                                                                     º\r
-    º This function is invoked each 1/24th of a second and updates a      º\r
-    º 1/24th of a second tick counter.                                    º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static void etherdev_timer0_isr(void) interrupt 1 using 1\r
-{\r
-    // Reload timer/ counter 0 for 24Hz periodic interrupt.   \r
-    TH0 = ETH_T0_RELOAD >> 8;\r
-    TL0 = ETH_T0_RELOAD;\r
-\r
-    // Increment 24ths of a second counter.\r
-    tick_count++;\r
-\r
-    return;\r
-}\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                     Public Function Implementation                  º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                            etherdev_init()                          º\r
-    º                                                                     º\r
-    º  Returns: 1 on success, 0 on failure.                               º\r
-    º  Refer to National Semiconductor DP8390 App Note 874, July 1993.    º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-bit etherdev_init(void)\r
-{\r
-    // Set IOR & IOW as they're active low.\r
-    IOR = 1;\r
-    IOW = 1;\r
-       NICE = 1;\r
-\r
-    // Set register data port as input.\r
-    ETH_DATA_PORT = ETH_DATA_PORT_MASK;\r
-\r
-#ifdef ETH_DEBUG\r
-    init_sio_poll();\r
-#endif /* ETH_DEBUG */\r
-\r
-    // Configure RTL8019AS ethernet controller.\r
-\r
-    // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).\r
-    // That leaves plenty of time for the RTL8019AS to read it's\r
-    // configuration in from the 9346 EEPROM before we get here.\r
-\r
-    // Select RTL8019AS register page 0.\r
-    ETHERDEV_SELECT_REG_PAGE(0);\r
-\r
-    // Check if RTL8019AS fully reset.\r
-    if(!(etherdev_reg_read(ISR) & RST))\r
-    {\r
-leds1 = ~0xff;\r
-leds2 = ~0xff;\r
-while(1);\r
-        return 0;\r
-    }\r
-/*\r
-    // Select RTL8019AS register page 3.\r
-    ETHERDEV_SELECT_REG_PAGE(3);\r
-\r
-    // Temporarily disable config register write protection.\r
-    etherdev_reg_write(_9346CR, EEM1 | EEM0);\r
-\r
-    // Disable boot ROM & select 10BaseT with TP/CX auto-detect.\r
-    etherdev_reg_write(CONFIG2, BSELB);\r
-\r
-    // Select half-duplex, awake, power-up & LED_TX/ LED_RX/ LED_LNK behaviour.\r
-    etherdev_reg_write(CONFIG3, LEDS0);\r
-\r
-    // Re-enable config register write protection.\r
-    etherdev_reg_write(_9346CR, 0x00);\r
-*/\r
-    // Select RTL8019AS register page 0.\r
-    ETHERDEV_SELECT_REG_PAGE(0);\r
-\r
-    // Stop RTL8019AS, select page 0 and abort DMA operation.\r
-    etherdev_reg_write(CR, RD2 | STP);\r
-\r
-    // Initialise data configuration register. \r
-    // FIFO threshold 8 bytes, no loopback, don't use auto send packet.\r
-    etherdev_reg_write(DCR, FT1 | LS);\r
-\r
-    // Reset remote byte count registers.\r
-    etherdev_reg_write(RBCR0, 0x00);\r
-    etherdev_reg_write(RBCR1, 0x00);\r
-\r
-    // Receive configuration register to monitor mode.\r
-    etherdev_reg_write(RCR, MON);\r
-\r
-    // Initialise transmit configuration register to loopback internally.\r
-    etherdev_reg_write(TCR, LB0);\r
-\r
-    // Clear interrupt status register bits by writing 1 to each.\r
-    etherdev_reg_write(ISR, 0xFF);\r
-\r
-    // Mask all interrupts in mask register.\r
-    etherdev_reg_write(IMR, 0x00);\r
-\r
-       // Obtengo MAC de la placa\r
-    //etherdev_reg_write(CR, 0x21);\r
-\r
-\r
-    // Set transmit page start.\r
-    etherdev_reg_write(TPSR, ETH_TX_PAGE_START);\r
-\r
-    // Set receive buffer page start.\r
-    etherdev_reg_write(PSTART, ETH_RX_PAGE_START);\r
-\r
-    // Initialise last receive buffer read pointer.\r
-    etherdev_reg_write(BNRY, ETH_RX_PAGE_START);\r
-\r
-    // Set receive buffer page stop.\r
-    etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);\r
-\r
-    // Select RTL8019AS register page 1.\r
-    etherdev_reg_write(CR, RD2 | PS0 | STP);\r
-\r
-    // Initialise current packet receive buffer page pointer\r
-    etherdev_reg_write(CURR, ETH_RX_PAGE_START);\r
-\r
-    // Set physical address\r
-    etherdev_reg_write(PAR0, 0x00);\r
-    etherdev_reg_write(PAR1, 0x0c);\r
-    etherdev_reg_write(PAR2, 0x6e);\r
-    etherdev_reg_write(PAR3, 0x37);\r
-    etherdev_reg_write(PAR4, 0x19);\r
-    etherdev_reg_write(PAR5, 0xbe);\r
-\r
-    // Select RTL8019AS register page 0 and abort DMA operation.\r
-    etherdev_reg_write(CR, RD2 | STP);\r
-\r
-    // Restart RTL8019AS. \r
-    etherdev_reg_write(CR, RD2 | STA);\r
-\r
-    // Initialise transmit configuration register for normal operation.\r
-    etherdev_reg_write(TCR, 0x00);\r
-\r
-    // Receive configuration register to accept broadcast packets.\r
-    etherdev_reg_write(RCR, AB);\r
-\r
-\r
-    // Initialize Timer 0 to generate a periodic 24Hz interrupt. \r
-\r
-    // Stop timer/ counter 0.                                         \r
-    TR0  = 0;          \r
-\r
-    // Set timer/ counter 0 as mode 1 16 bit timer.      \r
-    TMOD &= 0xF0;\r
-    TMOD |= 0x01;\r
-\r
-    // Preload for 24Hz periodic interrupt.    \r
-    TH0 = ETH_T0_RELOAD >> 8; \r
-    TL0 = ETH_T0_RELOAD;\r
-\r
-    // Restart timer/ counter 0 running.\r
-    TR0 = 1;\r
-\r
-    // Enable timer/ counter 0 overflow interrupt.            \r
-    ET0 = 1;\r
-\r
-    // Enable global interrupt.\r
-    EA = 1;\r
-\r
-    return 1;\r
-}\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                           etherdev_send()                           º\r
-    º                                                                     º\r
-    º Send the packet in the uip_buf and uip_appdata buffers using the    º\r
-    º RTL8019AS ethernet card.                                            º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-void etherdev_send(void)\r
-{\r
-    unsigned int i;\r
-    unsigned char *ptr;\r
-\r
-    ptr = uip_buf;\r
-\r
-    // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.\r
-\r
-    // Select RTL8019AS register page 0 and abort DMA operation.\r
-    etherdev_reg_write(CR, RD2 | STA);\r
-\r
-leds1 = ~0x01;\r
-i = etherdev_reg_read(CR);\r
-leds2 = ~i;\r
-    // Wait until pending transmit operation completes.\r
-    while(etherdev_reg_read(CR) & TXP) continue;\r
-\r
-    // Clear remote DMA complete interrupt status register bit.\r
-    etherdev_reg_write(ISR, RDC);\r
-\r
-    // Set remote DMA start address registers to indicate where to load packet.\r
-    etherdev_reg_write(RSAR0, 0x00);\r
-    etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);\r
-\r
-    // Set remote DMA byte count registers to indicate length of packet load.\r
-    etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));\r
-    etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));\r
-\r
-    // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.\r
-    etherdev_reg_write(CR, RD1 | STA);\r
-\r
-    // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local\r
-    // transmit buffer memory.\r
-    for(i = 0; i < uip_len; i++)\r
-    {\r
-        etherdev_reg_write(RDMA, *ptr++);\r
-    }\r
-\r
-    // Wait until remote DMA operation complete.\r
-leds1 = ~0x02;\r
-leds2 = ~etherdev_reg_read(ISR);\r
-    while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
-\r
-    // Abort/ complete DMA operation.\r
-    etherdev_reg_write(CR, RD2 | STA);\r
-\r
-    // Set transmit page start to indicate packet start.\r
-    etherdev_reg_write(TPSR, ETH_TX_PAGE_START);\r
-\r
-    // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.\r
-    if(uip_len < ETH_MIN_PACKET_LEN)\r
-    {\r
-        uip_len = ETH_MIN_PACKET_LEN;\r
-    }\r
-\r
-    // Set transmit byte count registers to indicate packet length.\r
-    etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));\r
-    etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));\r
-\r
-    // Issue command for RTL8019AS to transmit packet from it's local buffer.\r
-    etherdev_reg_write(CR, RD2 | TXP | STA);\r
-\r
-    return;\r
-}\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                           etherdev_read()                           º\r
-    º                                                                     º\r
-    º This function will read an entire IP packet into the uip_buf.       º\r
-    º If it must wait for more than 0.5 seconds, it will return with      º\r
-    º the return value 0. Otherwise, when a full packet has been read     º\r
-    º into the uip_buf buffer, the length of the packet is returned.      º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-unsigned int etherdev_read(void)\r
-{    \r
-    unsigned int bytes_read;\r
-\r
-    /* tick_count threshold should be 12 for 0.5 sec bail-out\r
-       One second (24) worked better for me, but socket recycling\r
-       is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h\r
-       to counter this. Retransmission timing etc. is affected also. */\r
-    while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;\r
-\r
-    tick_count = 0;\r
-\r
-    return bytes_read;\r
-}\r
-\r
-\r
-/*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
-    º                                                                     º\r
-    º                           etherdev_poll()                           º\r
-    º                                                                     º\r
-    º Poll the RTL8019AS ethernet device for an available packet.         º\r
-    º                                                                     º\r
-    ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
-static unsigned int etherdev_poll(void)\r
-{\r
-    unsigned int len = 0;\r
-\r
-    // Check if there is a packet in the rx buffer.\r
-    if(etherdev_reg_read(ISR) & PRX)\r
-    {\r
-        // Check if the rx buffer has overflowed.\r
-        if(etherdev_reg_read(ISR) & OVW)\r
-        {\r
-            bit retransmit = 0;\r
-\r
-            // If the receive buffer ring has overflowed we dump the whole\r
-            // thing and start over. There is no way of knowing whether the\r
-            // data it contains is uncorrupted, or will cause us grief.\r
-\r
-            // Stop RTL8019AS and abort DMA operation.\r
-            etherdev_reg_write(CR, RD2 | STP);\r
-\r
-            // Reset remote byte count registers.\r
-            etherdev_reg_write(RBCR0, 0x00);\r
-            etherdev_reg_write(RBCR1, 0x00);\r
-\r
-            // Wait for controller to halt after any current tx completes.\r
-            while(!(etherdev_reg_read(ISR) & RST)) continue;\r
-\r
-            // Check whether currently transmitting a packet.\r
-            if(etherdev_reg_read(CR) & TXP)\r
-            {\r
-                // If neither a successful transmission nor a tx abort error \r
-                // has occured, then flag current tx packet for resend.\r
-                if(!((etherdev_reg_read(ISR) & PTX)\r
-                                          || (etherdev_reg_read(ISR) & TXE)))\r
-                {\r
-                    retransmit = 1;\r
-                }\r
-            }\r
-\r
-            // Set transmit configuration register to loopback internally.\r
-            etherdev_reg_write(TCR, LB0);\r
-\r
-            // Restart the RTL8019AS.\r
-            etherdev_reg_write(CR, RD2 | STA);\r
-\r
-            // Re-initialise last receive buffer read pointer.\r
-            etherdev_reg_write(BNRY, ETH_RX_PAGE_START);\r
-\r
-            // Select RTL8019AS register page 1.\r
-            ETHERDEV_SELECT_REG_PAGE(1);\r
-\r
-            // Re-initialise current packet receive buffer page pointer.\r
-            etherdev_reg_write(CURR, ETH_RX_PAGE_START);\r
-\r
-            // Select RTL8019AS register page 0.\r
-            ETHERDEV_SELECT_REG_PAGE(0);\r
-\r
-            // Clear rx buffer overflow & packet received interrupt flags.\r
-            etherdev_reg_write(ISR, PRX | OVW);\r
-\r
-            // Re-itialise transmit configuration reg for normal operation.\r
-            etherdev_reg_write(TCR, 0x00);\r
-        \r
-            if(retransmit)\r
-            {\r
-                // Retransmit packet in RTL8019AS local tx buffer.\r
-                etherdev_reg_write(CR, RD2 | TXP | STA);\r
-            }\r
-        }\r
-        else // Rx buffer has not overflowed, so read a packet into uip_buf.\r
-        {\r
-            unsigned int i;\r
-            unsigned char next_rx_packet;\r
-            unsigned char current;\r
-\r
-            // Retrieve packet header. (status, next_ptr, length_l, length_h)\r
-\r
-            // Clear remote DMA complete interrupt status register bit.\r
-            etherdev_reg_write(ISR, RDC);\r
-\r
-            // Set remote DMA start address registers to packet header.\r
-            etherdev_reg_write(RSAR0, 0x00);\r
-            etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));\r
-\r
-            // Set remote DMA byte count registers to packet header length.\r
-            etherdev_reg_write(RBCR0, 0x04);\r
-            etherdev_reg_write(RBCR1, 0x00);\r
-\r
-            // Initiate DMA transfer of packet header.\r
-            etherdev_reg_write(CR, RD0 | STA);\r
-\r
-            // Drop packet status. We don't use it.\r
-            etherdev_reg_read(RDMA);\r
-\r
-            // Save next packet pointer.\r
-            next_rx_packet = etherdev_reg_read(RDMA);\r
-\r
-            // Retrieve packet data length and subtract CRC bytes.\r
-            len =  etherdev_reg_read(RDMA);\r
-            len += etherdev_reg_read(RDMA) << 8;\r
-            len -= 4;\r
-\r
-            // Wait until remote DMA operation completes.\r
-            while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
-\r
-            // Abort/ complete DMA operation.\r
-            etherdev_reg_write(CR, RD2 | STA);\r
-\r
-\r
-            // Retrieve packet data.\r
-\r
-            // Check if incoming packet will fit into rx buffer.\r
-            if(len <= sizeof(uip_buf))\r
-            {\r
-                // Clear remote DMA complete interrupt status register bit.\r
-                etherdev_reg_write(ISR, RDC);\r
-\r
-                // Set remote DMA start address registers to packet data.\r
-                etherdev_reg_write(RSAR0, 0x04);\r
-                etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));\r
-\r
-                // Set remote DMA byte count registers to packet data length.\r
-                etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));\r
-                etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));\r
-\r
-                // Initiate DMA transfer of packet data.\r
-                etherdev_reg_write(CR, RD0 | STA);\r
-\r
-                // Read packet data directly into uip_buf.\r
-                for(i = 0; i < len; i++)\r
-                {\r
-                    *(uip_buf + i) = etherdev_reg_read(RDMA);\r
-                }\r
-\r
-                // Wait until remote DMA operation complete.\r
-                while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
-\r
-                // Abort/ complete DMA operation.\r
-                etherdev_reg_write(CR, RD2 | STA);\r
-\r
-            }\r
-            else\r
-            {\r
-                // Incoming packet too big, so dump it.\r
-                len = 0;\r
-            }\r
-\r
-            // Advance boundary pointer to next packet start.\r
-            etherdev_reg_write(BNRY, next_rx_packet);\r
-\r
-            // Select RTL8019AS register page 1.\r
-            ETHERDEV_SELECT_REG_PAGE(1);\r
-\r
-            // Retrieve current receive buffer page\r
-            current = etherdev_reg_read(CURR);\r
-\r
-            // Select RTL8019AS register page 0.\r
-            ETHERDEV_SELECT_REG_PAGE(0);\r
-\r
-            // Check if last packet has been removed from rx buffer.\r
-            if(next_rx_packet == current)\r
-            {\r
-                // Clear packet received interrupt flag.\r
-                etherdev_reg_write(ISR, PRX);\r
-            }\r
-        }\r
-    }\r
-\r
-    return len;\r
-}\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
-\r
+// vim: set et sw=4 sts=4 :    
+
+#include "types.h"
+#include "etherdev.h"
+
+void sleep(unsigned char);
+
+#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[80] =
+{
+       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;
+
+// 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
+#define ETH_RX_PAGE_STOP   0x60    // 0x6000
+
+#define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y
+#define ETH_DATA_PORT_MASK 0xFF                 // 11111111y
+
+#define ETH_MIN_PACKET_LEN 0x3C                 // 60 bytes
+
+
+static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
+static unsigned char etherdev_reg_read(unsigned char reg);
+
+// Manipulate PS1 & PS0 in CR to select RTL8019AS register page. 
+#define ETHERDEV_SELECT_REG_PAGE(page)                                      \
+          do                                                                \
+          {                                                                 \
+              etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \
+              etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6));  \
+          } while(0)
+
+
+static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
+{
+    // Select register address.
+    ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK; 
+    ETH_ADDR_PORT |= reg;
+
+    // Output register data to port.
+    ETH_DATA_PORT = wr_data;
+
+    // Clock register data into RTL8019AS.
+    // IOR & IOW are both active low.
+    NICE = 0;
+    IOW = 0;
+    IOW = 1;
+    NICE = 1;
+
+    return;
+} 
+
+
+static unsigned char etherdev_reg_read(unsigned char reg)
+{
+    unsigned char rd_data;
+
+    // Select register address.
+    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.
+    NICE = 0;
+    IOR = 0;
+
+    // Read register data from port.
+    rd_data = ETH_DATA_PORT;
+
+    // Disable register data output from RTL8019AS.
+    IOR = 1; 
+    NICE = 1;   
+
+    return rd_data;
+} 
+
+
+/*
+                                                                     
+                            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;
+    NICE = 1;
+
+    // Set register data port as input.
+    ETH_DATA_PORT = ETH_DATA_PORT_MASK;
+
+    // Configure RTL8019AS ethernet controller.
+
+    // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
+    // That leaves plenty of time for the RTL8019AS to read it's
+    // configuration in from the 9346 EEPROM before we get here.
+
+    // Select RTL8019AS register page 0.
+    ETHERDEV_SELECT_REG_PAGE(0);
+
+    // Check if RTL8019AS fully reset.
+    if(!(etherdev_reg_read(ISR) & RST))
+    {
+        return 0;
+    }
+
+    // Stop RTL8019AS, select page 0 and abort DMA operation.
+    etherdev_reg_write(CR, ABORT | STP);
+
+    // Initialise data configuration register. 
+    // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
+    etherdev_reg_write(DCR, FT1 | LS);
+
+    // Reset remote byte count registers.
+    etherdev_reg_write(RBCR0, 0x00);
+    etherdev_reg_write(RBCR1, 0x00);
+
+    // Receive configuration register to monitor mode.
+    etherdev_reg_write(RCR, MON);
+
+    // Initialise transmit configuration register to loopback internally.
+    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);
+    
+    // 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;
+
+    // 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 receive buffer page start.
+    etherdev_reg_write(PSTART, ETH_RX_PAGE_START);
+
+    // Initialise last receive buffer read pointer.
+    etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
+
+    // Set receive buffer page stop.
+    etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
+
+    // Select RTL8019AS register page 1.
+    etherdev_reg_write(CR, ABORT | PAGE1 | STP);
+
+    // Initialise current packet receive buffer page pointer
+    etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
+
+    // Set physical address
+    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.
+    etherdev_reg_write(CR, ABORT | STP);
+
+    // Restart RTL8019AS. 
+    etherdev_reg_write(CR, ABORT | STA);
+
+    // Initialise transmit configuration register for normal operation.
+    etherdev_reg_write(TCR, MODE0);
+
+    // Receive configuration register to accept broadcast packets.
+    etherdev_reg_write(RCR, AB);
+
+    return 1;
+}
+
+
+/*
+                                                                     
+                           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;
+
+    // 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, ABORT | STA);
+
+    // Wait until pending transmit operation completes.
+    while(etherdev_reg_read(CR) & TXP) continue;
+
+    // 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 byte count registers to indicate length of packet load.
+    etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));
+    etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
+
+    // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
+    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++)
+    {
+        etherdev_reg_write(RDMA, uip_buf[i]);
+    }
+
+    // Wait until remote DMA operation complete.
+    while(!(etherdev_reg_read(ISR) & RDC)) continue;
+
+    // Clear remote DMA complete interrupt status register bit.
+    etherdev_reg_write(ISR, RDC);
+
+    // Abort/ complete DMA operation.
+    etherdev_reg_write(CR, ABORT | STA);
+
+    // Set transmit page start to indicate packet start.
+    etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
+
+    // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
+    if(uip_len < ETH_MIN_PACKET_LEN)
+    {
+        uip_len = ETH_MIN_PACKET_LEN;
+    }
+
+    // Set transmit byte count registers to indicate packet length.
+    etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));
+    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, ABORT | TXP | STA);
+
+    return;
+}
+
+
+static void etherdev_reset()
+{
+    bit retransmit = etherdev_reg_read(CR) & TXP;
+
+    // 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.
+
+    // 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;
+
+    // Reset remote byte count registers.
+    etherdev_reg_write(RBCR0, 0x00);
+    etherdev_reg_write(RBCR1, 0x00);
+
+    // Check whether currently transmitting a packet.
+    if(retransmit)
+    {
+        // 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))
+        {
+            retransmit = 0;
+        }
+    }
+
+    // Set transmit configuration register to loopback internally.
+    etherdev_reg_write(TCR, MODE1);
+
+    // Restart the RTL8019AS.
+    etherdev_reg_write(CR, ABORT | STA);
+
+    // Re-initialise last receive buffer read pointer.
+    etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
+
+    // Select RTL8019AS register page 1.
+    ETHERDEV_SELECT_REG_PAGE(1);
+
+    // Re-initialise current packet receive buffer page pointer.
+    etherdev_reg_write(CURR, ETH_RX_PAGE_START + 1);
+
+    // Select RTL8019AS register page 0.
+    ETHERDEV_SELECT_REG_PAGE(0);
+
+    // Clear rx buffer overflow & packet received interrupt flags.
+    etherdev_reg_write(ISR, PRX | OVW);
+
+    // Re-itialise transmit configuration reg for normal operation.
+    etherdev_reg_write(TCR, MODE0);
+
+    if(retransmit)
+    {
+        // Retransmit packet in RTL8019AS local tx buffer.
+        etherdev_reg_write(CR, ABORT | TXP | STA);
+    }
+}
+
+
+unsigned int etherdev_read(void)
+{    
+    unsigned int len = 0;
+
+    // Check if the rx buffer has overflowed.
+    if (etherdev_reg_read(ISR) & OVW)
+    {
+        unsigned char current;
+
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(1);
+
+        // Retrieve current receive buffer page
+        current = etherdev_reg_read(CURR);
+
+        // 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;
+
+        // Retrieve packet header. (status, next_ptr, length_l, length_h)
+
+        // 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);
+
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(1);
+
+        // Retrieve current receive buffer page
+        current = etherdev_reg_read(CURR);
+
+        // Select RTL8019AS register page 1.
+        ETHERDEV_SELECT_REG_PAGE(0);
+
+        // 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;
+        }
+
+        // Set remote DMA byte count registers to packet header length.
+        etherdev_reg_write(RBCR0, 0x04);
+        etherdev_reg_write(RBCR1, 0x00);
+
+        // 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);
+
+        // Packet status.
+        status = etherdev_reg_read(RDMA);
+
+        // Save next packet pointer.
+        next_rx_packet = etherdev_reg_read(RDMA);
+
+        // Retrieve packet data length and subtract CRC bytes.
+        len =  etherdev_reg_read(RDMA);
+        len += etherdev_reg_read(RDMA) << 8;
+        len -= 4;
+
+        // Wait until remote DMA operation completes.
+        while(!(etherdev_reg_read(ISR) & RDC)) continue;
+
+        // Abort/ complete DMA operation.
+        etherdev_reg_write(CR, ABORT | STA);
+
+        // Limpia ISR
+        etherdev_reg_write(ISR, RDC);
+
+        // Si es un paquete inválido, lo dropeamos
+        if (len < 60 || len > 1518)
+        {
+            len = 0;
+            goto drop;
+        }
+
+        // Si hubo un error, también lo dropeamos
+        if ((status & 0x0F) != RXSOK)
+        {
+            len = 0;
+            goto drop;
+        }
+
+        // Retrieve packet data.
+
+        // Check if incoming packet will fit into rx buffer.
+        if(len <= sizeof(uip_buf))
+        {
+
+            // Set remote DMA start address registers to packet data.
+            etherdev_reg_write(RSAR0, 0x04);
+            etherdev_reg_write(RSAR1, bnry);
+
+            // 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));
+
+            // Initiate DMA transfer of packet data.
+            etherdev_reg_write(CR, READ | STA);
+
+            // Read packet data directly into uip_buf.
+            uip_len = len;
+            for(i = 0; i < 14; i++)
+            {
+                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
+            }
+
+            // 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;
+}
+