1 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
2 º TITLE: RTL8019AS ethernet routines for 8051 and º
\r
3 º Keil C51 v7.00 port of Adam Dunkels' uIP v0.9 º
\r
4 º FILENAME: etherdev.c º
\r
5 º REVISION: VER 0.0 º
\r
6 º REV.DATE: 21-01-05 º
\r
8 º AUTHOR: Copyright (c) 2005, Murray R. Van Luyn. º
\r
9 º Refer to National Semiconductor DP8390 App Note 874. º
\r
10 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
12 /* ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
\r
13 ³ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS ³
\r
14 ³ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ³
\r
15 ³ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ³
\r
16 ³ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY ³
\r
17 ³ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ³
\r
18 ³ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ³
\r
19 ³ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS ³
\r
20 ³ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, ³
\r
21 ³ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING ³
\r
22 ³ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ³
\r
23 ³ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ³
\r
24 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ */
\r
27 #include "etherdev.h"
\r
29 void sleep(unsigned char);
\r
31 static xdata leds1 _at_ 0x0080;
\r
32 static xdata leds2 _at_ 0x00c0;
\r
34 unsigned char uip_buf[64] =
\r
36 //0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino
\r
37 0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino
\r
38 0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente
\r
42 unsigned int uip_len = 14;
\r
44 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
45 º Private defines. º
\r
46 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
47 #define ETH_CPU_CLOCK ETH_CPU_XTAL / 12 // 8051 clock rate (X1 mode)
\r
49 // Delay routine timing parameters
\r
50 #define ETH_DELAY_CONST 9.114584e-5 // Delay routine constant
\r
51 #define ETH_DELAY_MULTPLR (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)
\r
53 // X1 CPU mode timing parameters
\r
54 #define ETH_T0_CLOCK ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate
\r
55 #define ETH_T0_INT_RATE 24 // Timer 0 intrupt rate (Hz)
\r
56 #define ETH_T0_RELOAD 65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)
\r
58 // Packet transmit & receive buffer configuration
\r
59 #define ETH_TX_PAGE_START 0x40 // 0x4000 Tx buffer is 6 * 256 = 1536 bytes
\r
60 #define ETH_RX_PAGE_START 0x46 // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
\r
61 #define ETH_RX_PAGE_STOP 0x60 // 0x6000
\r
63 #define ETH_ADDR_PORT_MASK 0x1F // 00011111y
\r
64 #define ETH_DATA_PORT_MASK 0xFF // 11111111y
\r
66 #define ETH_MIN_PACKET_LEN 0x3C
\r
69 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
70 º Private Function Prototypes º
\r
71 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
72 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
\r
73 static unsigned char etherdev_reg_read(unsigned char reg);
\r
74 static void etherdev_delay_ms(unsigned int count);
\r
75 static unsigned int etherdev_poll(void);
\r
76 //static void etherdev_timer0_isr(void) interrupt 1 using 1;
\r
79 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
80 º Private Macro Defines º
\r
81 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
82 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page.
\r
83 #define ETHERDEV_SELECT_REG_PAGE(page) \
\r
86 etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \
\r
87 etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6)); \
\r
91 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
92 º Global Variables º
\r
93 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
94 static unsigned char tick_count = 0;
\r
97 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
98 º Private Function Implementation º
\r
99 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
101 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
103 º etherdev_reg_write() º
\r
106 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
107 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
\r
109 // Select register address.
\r
110 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
\r
111 ETH_ADDR_PORT |= reg;
\r
113 // Output register data to port.
\r
114 ETH_DATA_PORT = wr_data;
\r
116 // Clock register data into RTL8019AS.
\r
117 // IOR & IOW are both active low.
\r
123 // Set register data port as input again.
\r
124 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
\r
130 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
132 º etherdev_reg_read() º
\r
135 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
136 static unsigned char etherdev_reg_read(unsigned char reg)
\r
138 unsigned char rd_data;
\r
140 // Select register address.
\r
141 ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
\r
142 ETH_ADDR_PORT |= reg;
\r
144 // Enable register data output from RTL8019AS.
\r
148 // Read register data from port.
\r
149 rd_data = ETH_DATA_PORT;
\r
151 // Disable register data output from RTL8019AS.
\r
159 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
161 º etherdev_delay_ms() º
\r
163 º 1 to 255+ ms delay. º
\r
165 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
166 static void etherdev_delay_ms(unsigned int count)
\r
169 for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;
\r
175 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
177 º etherdev_timer0_isr() º
\r
179 º This function is invoked each 1/24th of a second and updates a º
\r
180 º 1/24th of a second tick counter. º
\r
182 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
183 static void etherdev_timer0_isr(void) interrupt 1 using 1
\r
185 // Reload timer/ counter 0 for 24Hz periodic interrupt.
\r
186 TH0 = ETH_T0_RELOAD >> 8;
\r
187 TL0 = ETH_T0_RELOAD;
\r
189 // Increment 24ths of a second counter.
\r
196 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
197 º Public Function Implementation º
\r
198 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
200 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
202 º etherdev_init() º
\r
204 º Returns: 1 on success, 0 on failure. º
\r
205 º Refer to National Semiconductor DP8390 App Note 874, July 1993. º
\r
207 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
208 bit etherdev_init(void)
\r
210 // Set IOR & IOW as they're active low.
\r
215 // Set register data port as input.
\r
216 ETH_DATA_PORT = ETH_DATA_PORT_MASK;
\r
220 #endif /* ETH_DEBUG */
\r
222 // Configure RTL8019AS ethernet controller.
\r
224 // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
\r
225 // That leaves plenty of time for the RTL8019AS to read it's
\r
226 // configuration in from the 9346 EEPROM before we get here.
\r
228 // Select RTL8019AS register page 0.
\r
229 ETHERDEV_SELECT_REG_PAGE(0);
\r
231 // Check if RTL8019AS fully reset.
\r
232 if(!(etherdev_reg_read(ISR) & RST))
\r
240 // Select RTL8019AS register page 3.
\r
241 ETHERDEV_SELECT_REG_PAGE(3);
\r
243 // Temporarily disable config register write protection.
\r
244 etherdev_reg_write(_9346CR, EEM1 | EEM0);
\r
246 // Disable boot ROM & select 10BaseT with TP/CX auto-detect.
\r
247 etherdev_reg_write(CONFIG2, BSELB);
\r
249 // Select half-duplex, awake, power-up & LED_TX/ LED_RX/ LED_LNK behaviour.
\r
250 etherdev_reg_write(CONFIG3, LEDS0);
\r
252 // Re-enable config register write protection.
\r
253 etherdev_reg_write(_9346CR, 0x00);
\r
255 // Select RTL8019AS register page 0.
\r
256 ETHERDEV_SELECT_REG_PAGE(0);
\r
258 // Stop RTL8019AS, select page 0 and abort DMA operation.
\r
259 etherdev_reg_write(CR, RD2 | STP);
\r
261 // Initialise data configuration register.
\r
262 // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
\r
263 etherdev_reg_write(DCR, FT1 | LS);
\r
265 // Reset remote byte count registers.
\r
266 etherdev_reg_write(RBCR0, 0x00);
\r
267 etherdev_reg_write(RBCR1, 0x00);
\r
269 // Receive configuration register to monitor mode.
\r
270 etherdev_reg_write(RCR, MON);
\r
272 // Initialise transmit configuration register to loopback internally.
\r
273 etherdev_reg_write(TCR, LB0);
\r
275 // Clear interrupt status register bits by writing 1 to each.
\r
276 etherdev_reg_write(ISR, 0xFF);
\r
278 // Mask all interrupts in mask register.
\r
279 etherdev_reg_write(IMR, 0x00);
\r
281 // Obtengo MAC de la placa
\r
282 //etherdev_reg_write(CR, 0x21);
\r
285 // Set transmit page start.
\r
286 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
\r
288 // Set receive buffer page start.
\r
289 etherdev_reg_write(PSTART, ETH_RX_PAGE_START);
\r
291 // Initialise last receive buffer read pointer.
\r
292 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
\r
294 // Set receive buffer page stop.
\r
295 etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
\r
297 // Select RTL8019AS register page 1.
\r
298 etherdev_reg_write(CR, RD2 | PS0 | STP);
\r
300 // Initialise current packet receive buffer page pointer
\r
301 etherdev_reg_write(CURR, ETH_RX_PAGE_START);
\r
303 // Set physical address
\r
304 etherdev_reg_write(PAR0, 0x00);
\r
305 etherdev_reg_write(PAR1, 0x0c);
\r
306 etherdev_reg_write(PAR2, 0x6e);
\r
307 etherdev_reg_write(PAR3, 0x37);
\r
308 etherdev_reg_write(PAR4, 0x19);
\r
309 etherdev_reg_write(PAR5, 0xbe);
\r
311 // Select RTL8019AS register page 0 and abort DMA operation.
\r
312 etherdev_reg_write(CR, RD2 | STP);
\r
314 // Restart RTL8019AS.
\r
315 etherdev_reg_write(CR, RD2 | STA);
\r
317 // Initialise transmit configuration register for normal operation.
\r
318 etherdev_reg_write(TCR, 0x00);
\r
320 // Receive configuration register to accept broadcast packets.
\r
321 etherdev_reg_write(RCR, AB);
\r
324 // Initialize Timer 0 to generate a periodic 24Hz interrupt.
\r
326 // Stop timer/ counter 0.
\r
329 // Set timer/ counter 0 as mode 1 16 bit timer.
\r
333 // Preload for 24Hz periodic interrupt.
\r
334 TH0 = ETH_T0_RELOAD >> 8;
\r
335 TL0 = ETH_T0_RELOAD;
\r
337 // Restart timer/ counter 0 running.
\r
340 // Enable timer/ counter 0 overflow interrupt.
\r
343 // Enable global interrupt.
\r
350 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
352 º etherdev_send() º
\r
354 º Send the packet in the uip_buf and uip_appdata buffers using the º
\r
355 º RTL8019AS ethernet card. º
\r
357 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
358 void etherdev_send(void)
\r
361 unsigned char *ptr;
\r
365 // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
\r
367 // Select RTL8019AS register page 0 and abort DMA operation.
\r
368 etherdev_reg_write(CR, RD2 | STA);
\r
371 i = etherdev_reg_read(CR);
\r
373 // Wait until pending transmit operation completes.
\r
374 while(etherdev_reg_read(CR) & TXP) continue;
\r
376 // Clear remote DMA complete interrupt status register bit.
\r
377 etherdev_reg_write(ISR, RDC);
\r
379 // Set remote DMA start address registers to indicate where to load packet.
\r
380 etherdev_reg_write(RSAR0, 0x00);
\r
381 etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
\r
383 // Set remote DMA byte count registers to indicate length of packet load.
\r
384 etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));
\r
385 etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
\r
387 // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
\r
388 etherdev_reg_write(CR, RD1 | STA);
\r
390 // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
\r
391 // transmit buffer memory.
\r
392 for(i = 0; i < uip_len; i++)
\r
394 etherdev_reg_write(RDMA, *ptr++);
\r
397 // Wait until remote DMA operation complete.
\r
399 leds2 = ~etherdev_reg_read(ISR);
\r
400 while(!(etherdev_reg_read(ISR) & RDC)) continue;
\r
402 // Abort/ complete DMA operation.
\r
403 etherdev_reg_write(CR, RD2 | STA);
\r
405 // Set transmit page start to indicate packet start.
\r
406 etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
\r
408 // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
\r
409 if(uip_len < ETH_MIN_PACKET_LEN)
\r
411 uip_len = ETH_MIN_PACKET_LEN;
\r
414 // Set transmit byte count registers to indicate packet length.
\r
415 etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));
\r
416 etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
\r
418 // Issue command for RTL8019AS to transmit packet from it's local buffer.
\r
419 etherdev_reg_write(CR, RD2 | TXP | STA);
\r
425 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
427 º etherdev_read() º
\r
429 º This function will read an entire IP packet into the uip_buf. º
\r
430 º If it must wait for more than 0.5 seconds, it will return with º
\r
431 º the return value 0. Otherwise, when a full packet has been read º
\r
432 º into the uip_buf buffer, the length of the packet is returned. º
\r
434 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
435 unsigned int etherdev_read(void)
\r
437 unsigned int bytes_read;
\r
439 /* tick_count threshold should be 12 for 0.5 sec bail-out
\r
440 One second (24) worked better for me, but socket recycling
\r
441 is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
\r
442 to counter this. Retransmission timing etc. is affected also. */
\r
443 while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;
\r
451 /* ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
\r
453 º etherdev_poll() º
\r
455 º Poll the RTL8019AS ethernet device for an available packet. º
\r
457 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ */
\r
458 static unsigned int etherdev_poll(void)
\r
460 unsigned int len = 0;
\r
462 // Check if there is a packet in the rx buffer.
\r
463 if(etherdev_reg_read(ISR) & PRX)
\r
465 // Check if the rx buffer has overflowed.
\r
466 if(etherdev_reg_read(ISR) & OVW)
\r
468 bit retransmit = 0;
\r
470 // If the receive buffer ring has overflowed we dump the whole
\r
471 // thing and start over. There is no way of knowing whether the
\r
472 // data it contains is uncorrupted, or will cause us grief.
\r
474 // Stop RTL8019AS and abort DMA operation.
\r
475 etherdev_reg_write(CR, RD2 | STP);
\r
477 // Reset remote byte count registers.
\r
478 etherdev_reg_write(RBCR0, 0x00);
\r
479 etherdev_reg_write(RBCR1, 0x00);
\r
481 // Wait for controller to halt after any current tx completes.
\r
482 while(!(etherdev_reg_read(ISR) & RST)) continue;
\r
484 // Check whether currently transmitting a packet.
\r
485 if(etherdev_reg_read(CR) & TXP)
\r
487 // If neither a successful transmission nor a tx abort error
\r
488 // has occured, then flag current tx packet for resend.
\r
489 if(!((etherdev_reg_read(ISR) & PTX)
\r
490 || (etherdev_reg_read(ISR) & TXE)))
\r
496 // Set transmit configuration register to loopback internally.
\r
497 etherdev_reg_write(TCR, LB0);
\r
499 // Restart the RTL8019AS.
\r
500 etherdev_reg_write(CR, RD2 | STA);
\r
502 // Re-initialise last receive buffer read pointer.
\r
503 etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
\r
505 // Select RTL8019AS register page 1.
\r
506 ETHERDEV_SELECT_REG_PAGE(1);
\r
508 // Re-initialise current packet receive buffer page pointer.
\r
509 etherdev_reg_write(CURR, ETH_RX_PAGE_START);
\r
511 // Select RTL8019AS register page 0.
\r
512 ETHERDEV_SELECT_REG_PAGE(0);
\r
514 // Clear rx buffer overflow & packet received interrupt flags.
\r
515 etherdev_reg_write(ISR, PRX | OVW);
\r
517 // Re-itialise transmit configuration reg for normal operation.
\r
518 etherdev_reg_write(TCR, 0x00);
\r
522 // Retransmit packet in RTL8019AS local tx buffer.
\r
523 etherdev_reg_write(CR, RD2 | TXP | STA);
\r
526 else // Rx buffer has not overflowed, so read a packet into uip_buf.
\r
529 unsigned char next_rx_packet;
\r
530 unsigned char current;
\r
532 // Retrieve packet header. (status, next_ptr, length_l, length_h)
\r
534 // Clear remote DMA complete interrupt status register bit.
\r
535 etherdev_reg_write(ISR, RDC);
\r
537 // Set remote DMA start address registers to packet header.
\r
538 etherdev_reg_write(RSAR0, 0x00);
\r
539 etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
\r
541 // Set remote DMA byte count registers to packet header length.
\r
542 etherdev_reg_write(RBCR0, 0x04);
\r
543 etherdev_reg_write(RBCR1, 0x00);
\r
545 // Initiate DMA transfer of packet header.
\r
546 etherdev_reg_write(CR, RD0 | STA);
\r
548 // Drop packet status. We don't use it.
\r
549 etherdev_reg_read(RDMA);
\r
551 // Save next packet pointer.
\r
552 next_rx_packet = etherdev_reg_read(RDMA);
\r
554 // Retrieve packet data length and subtract CRC bytes.
\r
555 len = etherdev_reg_read(RDMA);
\r
556 len += etherdev_reg_read(RDMA) << 8;
\r
559 // Wait until remote DMA operation completes.
\r
560 while(!(etherdev_reg_read(ISR) & RDC)) continue;
\r
562 // Abort/ complete DMA operation.
\r
563 etherdev_reg_write(CR, RD2 | STA);
\r
566 // Retrieve packet data.
\r
568 // Check if incoming packet will fit into rx buffer.
\r
569 if(len <= sizeof(uip_buf))
\r
571 // Clear remote DMA complete interrupt status register bit.
\r
572 etherdev_reg_write(ISR, RDC);
\r
574 // Set remote DMA start address registers to packet data.
\r
575 etherdev_reg_write(RSAR0, 0x04);
\r
576 etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
\r
578 // Set remote DMA byte count registers to packet data length.
\r
579 etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
\r
580 etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
\r
582 // Initiate DMA transfer of packet data.
\r
583 etherdev_reg_write(CR, RD0 | STA);
\r
585 // Read packet data directly into uip_buf.
\r
586 for(i = 0; i < len; i++)
\r
588 *(uip_buf + i) = etherdev_reg_read(RDMA);
\r
591 // Wait until remote DMA operation complete.
\r
592 while(!(etherdev_reg_read(ISR) & RDC)) continue;
\r
594 // Abort/ complete DMA operation.
\r
595 etherdev_reg_write(CR, RD2 | STA);
\r
600 // Incoming packet too big, so dump it.
\r
604 // Advance boundary pointer to next packet start.
\r
605 etherdev_reg_write(BNRY, next_rx_packet);
\r
607 // Select RTL8019AS register page 1.
\r
608 ETHERDEV_SELECT_REG_PAGE(1);
\r
610 // Retrieve current receive buffer page
\r
611 current = etherdev_reg_read(CURR);
\r
613 // Select RTL8019AS register page 0.
\r
614 ETHERDEV_SELECT_REG_PAGE(0);
\r
616 // Check if last packet has been removed from rx buffer.
\r
617 if(next_rx_packet == current)
\r
619 // Clear packet received interrupt flag.
\r
620 etherdev_reg_write(ISR, PRX);
\r