-/* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\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;
+}
+