]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - pruebas/keil/red_test_anda/etherdev.c
c3a342e5588f0fcb0bc9c28266105ffc637ca094
[z.facultad/66.09/etherled.git] / pruebas / keil / red_test_anda / etherdev.c
1 #include "etherdev.h"
2
3 void sleep(unsigned char);
4
5 static xdata leds1 _at_ 0x0080;
6 static xdata leds2 _at_ 0x00c0;
7
8 unsigned char uip_buf[64] =
9 {
10         //0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbf, // MAC destino
11         0x00, 0x80, 0xc7, 0x42, 0x8d, 0x27, // MAC destino
12         0x00, 0x0c, 0x6e, 0x37, 0x19, 0xbe, // MAC fuente
13         0x00, 0x00, // Type
14 };
15
16 unsigned int uip_len = 14;
17
18 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
19     º                            Private defines.                         º
20     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
21 #define ETH_CPU_CLOCK      ETH_CPU_XTAL / 12    // 8051 clock rate (X1 mode)
22
23 // Delay routine timing parameters
24 #define ETH_DELAY_CONST    9.114584e-5          // Delay routine constant
25 #define ETH_DELAY_MULTPLR  (unsigned char)(ETH_DELAY_CONST * ETH_CPU_CLOCK)
26
27 // X1 CPU mode timing parameters
28 #define ETH_T0_CLOCK             ETH_CPU_XTAL / 12 // Timer 0 mode 1 clock rate
29 #define ETH_T0_INT_RATE          24                // Timer 0 intrupt rate (Hz)
30 #define ETH_T0_RELOAD            65536 - (ETH_T0_CLOCK / ETH_T0_INT_RATE)
31
32 // Packet transmit & receive buffer configuration
33 #define ETH_TX_PAGE_START  0x40    // 0x4000 Tx buffer is  6 * 256 = 1536 bytes
34 #define ETH_RX_PAGE_START  0x46    // 0x4600 Rx buffer is 26 * 256 = 6656 bytes
35 #define ETH_RX_PAGE_STOP   0x60    // 0x6000
36
37 #define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y
38 #define ETH_DATA_PORT_MASK 0xFF                 // 11111111y
39
40 #define ETH_MIN_PACKET_LEN 0x3C
41
42
43 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
44     º                       Private Function Prototypes                   º
45     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
46 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data);
47 static unsigned char etherdev_reg_read(unsigned char reg);
48 static void etherdev_delay_ms(unsigned int count);
49 static unsigned int etherdev_poll(void);
50 //static void etherdev_timer0_isr(void) interrupt 1 using 1;
51
52
53 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
54     º                          Private Macro Defines                      º
55     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
56 // Manipulate PS1 & PS0 in CR to select RTL8019AS register page. 
57 #define ETHERDEV_SELECT_REG_PAGE(page)                                      \
58           do                                                                \
59           {                                                                 \
60               etherdev_reg_write(CR, etherdev_reg_read(CR) & ~(PS1 | PS0)); \
61               etherdev_reg_write(CR, etherdev_reg_read(CR) | (page << 6));  \
62           } while(0)
63
64
65 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
66     º                              Global Variables                       º
67     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
68 static unsigned char tick_count = 0;
69
70
71 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
72     º                     Private Function Implementation                 º
73     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
74
75 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
76     º                                                                     º
77     º                          etherdev_reg_write()                       º
78     º                                                                     º
79     º                                                                     º
80     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
81 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)
82 {
83     // Select register address.
84     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK; 
85     ETH_ADDR_PORT |= reg;
86
87     // Output register data to port.
88     ETH_DATA_PORT = wr_data;
89
90     // Clock register data into RTL8019AS.
91     // IOR & IOW are both active low.
92         NICE = 0;
93     IOW = 0;
94     IOW = 1;
95         NICE = 1;
96
97     // Set register data port as input again.
98     ETH_DATA_PORT = ETH_DATA_PORT_MASK;
99
100     return;
101
102
103
104 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
105     º                                                                     º
106     º                          etherdev_reg_read()                        º
107     º                                                                     º
108     º                                                                     º
109     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
110 static unsigned char etherdev_reg_read(unsigned char reg)
111 {
112     unsigned char rd_data;
113
114     // Select register address.
115     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;
116     ETH_ADDR_PORT |= reg;
117
118     // Enable register data output from RTL8019AS.
119         NICE = 0;
120     IOR = 0;
121
122     // Read register data from port.
123     rd_data = ETH_DATA_PORT;
124
125     // Disable register data output from RTL8019AS.
126     IOR = 1; 
127         NICE = 1;   
128
129     return rd_data;
130
131
132
133 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
134     º                                                                     º
135     º                          etherdev_delay_ms()                        º
136     º                                                                     º
137     º  1 to 255+ ms delay.                                                º
138     º                                                                     º
139     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
140 static void etherdev_delay_ms(unsigned int count)
141 {
142
143     for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;
144
145     return;
146 }
147
148
149 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
150     º                                                                     º
151     º                           etherdev_timer0_isr()                     º
152     º                                                                     º
153     º This function is invoked each 1/24th of a second and updates a      º
154     º 1/24th of a second tick counter.                                    º
155     º                                                                     º
156     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
157 static void etherdev_timer0_isr(void) interrupt 1 using 1
158 {
159     // Reload timer/ counter 0 for 24Hz periodic interrupt.   
160     TH0 = ETH_T0_RELOAD >> 8;
161     TL0 = ETH_T0_RELOAD;
162
163     // Increment 24ths of a second counter.
164     tick_count++;
165
166     return;
167 }
168
169
170 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
171     º                     Public Function Implementation                  º
172     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
173
174 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
175     º                                                                     º
176     º                            etherdev_init()                          º
177     º                                                                     º
178     º  Returns: 1 on success, 0 on failure.                               º
179     º  Refer to National Semiconductor DP8390 App Note 874, July 1993.    º
180     º                                                                     º
181     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
182 bit etherdev_init(void)
183 {
184     // Set IOR & IOW as they're active low.
185     IOR = 1;
186     IOW = 1;
187         NICE = 1;
188
189     // Set register data port as input.
190     ETH_DATA_PORT = ETH_DATA_PORT_MASK;
191
192 #ifdef ETH_DEBUG
193     init_sio_poll();
194 #endif /* ETH_DEBUG */
195
196     // Configure RTL8019AS ethernet controller.
197
198     // Keil startup code takes 4ms to execute (18.432MHz, X1 mode).
199     // That leaves plenty of time for the RTL8019AS to read it's
200     // configuration in from the 9346 EEPROM before we get here.
201
202     // Select RTL8019AS register page 0.
203     ETHERDEV_SELECT_REG_PAGE(0);
204
205     // Check if RTL8019AS fully reset.
206     if(!(etherdev_reg_read(ISR) & RST))
207     {
208 leds1 = ~0xff;
209 leds2 = ~0xff;
210 while(1);
211         return 0;
212     }
213 /*
214     // Select RTL8019AS register page 3.
215     ETHERDEV_SELECT_REG_PAGE(3);
216
217     // Temporarily disable config register write protection.
218     etherdev_reg_write(_9346CR, EEM1 | EEM0);
219
220     // Disable boot ROM & select 10BaseT with TP/CX auto-detect.
221     etherdev_reg_write(CONFIG2, BSELB);
222
223     // Select half-duplex, awake, power-up & LED_TX/ LED_RX/ LED_LNK behaviour.
224     etherdev_reg_write(CONFIG3, LEDS0);
225
226     // Re-enable config register write protection.
227     etherdev_reg_write(_9346CR, 0x00);
228 */
229     // Select RTL8019AS register page 0.
230     ETHERDEV_SELECT_REG_PAGE(0);
231
232     // Stop RTL8019AS, select page 0 and abort DMA operation.
233     etherdev_reg_write(CR, RD2 | STP);
234
235     // Initialise data configuration register. 
236     // FIFO threshold 8 bytes, no loopback, don't use auto send packet.
237     etherdev_reg_write(DCR, FT1 | LS);
238
239     // Reset remote byte count registers.
240     etherdev_reg_write(RBCR0, 0x00);
241     etherdev_reg_write(RBCR1, 0x00);
242
243     // Receive configuration register to monitor mode.
244     etherdev_reg_write(RCR, MON);
245
246     // Initialise transmit configuration register to loopback internally.
247     etherdev_reg_write(TCR, LB0);
248
249     // Clear interrupt status register bits by writing 1 to each.
250     etherdev_reg_write(ISR, 0xFF);
251
252     // Mask all interrupts in mask register.
253     etherdev_reg_write(IMR, 0x00);
254
255         // Obtengo MAC de la placa
256     //etherdev_reg_write(CR, 0x21);
257
258
259     // Set transmit page start.
260     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
261
262     // Set receive buffer page start.
263     etherdev_reg_write(PSTART, ETH_RX_PAGE_START);
264
265     // Initialise last receive buffer read pointer.
266     etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
267
268     // Set receive buffer page stop.
269     etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);
270
271     // Select RTL8019AS register page 1.
272     etherdev_reg_write(CR, RD2 | PS0 | STP);
273
274     // Initialise current packet receive buffer page pointer
275     etherdev_reg_write(CURR, ETH_RX_PAGE_START);
276
277     // Set physical address
278     etherdev_reg_write(PAR0, 0x00);
279     etherdev_reg_write(PAR1, 0x0c);
280     etherdev_reg_write(PAR2, 0x6e);
281     etherdev_reg_write(PAR3, 0x37);
282     etherdev_reg_write(PAR4, 0x19);
283     etherdev_reg_write(PAR5, 0xbe);
284
285     // Select RTL8019AS register page 0 and abort DMA operation.
286     etherdev_reg_write(CR, RD2 | STP);
287
288     // Restart RTL8019AS. 
289     etherdev_reg_write(CR, RD2 | STA);
290
291     // Initialise transmit configuration register for normal operation.
292     etherdev_reg_write(TCR, 0x00);
293
294     // Receive configuration register to accept broadcast packets.
295     etherdev_reg_write(RCR, AB);
296
297
298     // Initialize Timer 0 to generate a periodic 24Hz interrupt. 
299
300     // Stop timer/ counter 0.                                         
301     TR0  = 0;          
302
303     // Set timer/ counter 0 as mode 1 16 bit timer.      
304     TMOD &= 0xF0;
305     TMOD |= 0x01;
306
307     // Preload for 24Hz periodic interrupt.    
308     TH0 = ETH_T0_RELOAD >> 8; 
309     TL0 = ETH_T0_RELOAD;
310
311     // Restart timer/ counter 0 running.
312     TR0 = 1;
313
314     // Enable timer/ counter 0 overflow interrupt.            
315     ET0 = 1;
316
317     // Enable global interrupt.
318     EA = 1;
319
320     return 1;
321 }
322
323
324 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
325     º                                                                     º
326     º                           etherdev_send()                           º
327     º                                                                     º
328     º Send the packet in the uip_buf and uip_appdata buffers using the    º
329     º RTL8019AS ethernet card.                                            º
330     º                                                                     º
331     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
332 void etherdev_send(void)
333 {
334     unsigned int i;
335     unsigned char *ptr;
336
337     ptr = uip_buf;
338
339     // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.
340
341     // Select RTL8019AS register page 0 and abort DMA operation.
342     etherdev_reg_write(CR, RD2 | STA);
343
344 leds1 = ~0x01;
345 i = etherdev_reg_read(CR);
346 leds2 = ~i;
347     // Wait until pending transmit operation completes.
348     while(etherdev_reg_read(CR) & TXP) continue;
349
350     // Clear remote DMA complete interrupt status register bit.
351     etherdev_reg_write(ISR, RDC);
352
353     // Set remote DMA start address registers to indicate where to load packet.
354     etherdev_reg_write(RSAR0, 0x00);
355     etherdev_reg_write(RSAR1, ETH_TX_PAGE_START);
356
357     // Set remote DMA byte count registers to indicate length of packet load.
358     etherdev_reg_write(RBCR0, (unsigned char)(uip_len & 0xFF));
359     etherdev_reg_write(RBCR1, (unsigned char)(uip_len >> 8));
360
361     // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.
362     etherdev_reg_write(CR, RD1 | STA);
363
364     // DMA transfer packet from uip_buf & uip_appdata to RTL8019AS local
365     // transmit buffer memory.
366     for(i = 0; i < uip_len; i++)
367     {
368         etherdev_reg_write(RDMA, *ptr++);
369     }
370
371     // Wait until remote DMA operation complete.
372 leds1 = ~0x02;
373 leds2 = ~etherdev_reg_read(ISR);
374     while(!(etherdev_reg_read(ISR) & RDC)) continue;
375
376     // Abort/ complete DMA operation.
377     etherdev_reg_write(CR, RD2 | STA);
378
379     // Set transmit page start to indicate packet start.
380     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);
381
382     // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.
383     if(uip_len < ETH_MIN_PACKET_LEN)
384     {
385         uip_len = ETH_MIN_PACKET_LEN;
386     }
387
388     // Set transmit byte count registers to indicate packet length.
389     etherdev_reg_write(TBCR0, (unsigned char)(uip_len & 0xFF));
390     etherdev_reg_write(TBCR1, (unsigned char)(uip_len >> 8));
391
392     // Issue command for RTL8019AS to transmit packet from it's local buffer.
393     etherdev_reg_write(CR, RD2 | TXP | STA);
394
395     return;
396 }
397
398
399 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
400     º                                                                     º
401     º                           etherdev_read()                           º
402     º                                                                     º
403     º This function will read an entire IP packet into the uip_buf.       º
404     º If it must wait for more than 0.5 seconds, it will return with      º
405     º the return value 0. Otherwise, when a full packet has been read     º
406     º into the uip_buf buffer, the length of the packet is returned.      º
407     º                                                                     º
408     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
409 unsigned int etherdev_read(void)
410 {    
411     unsigned int bytes_read;
412
413     /* tick_count threshold should be 12 for 0.5 sec bail-out
414        One second (24) worked better for me, but socket recycling
415        is then slower. I set UIP_TIME_WAIT_TIMEOUT 60 in uipopt.h
416        to counter this. Retransmission timing etc. is affected also. */
417     while ((!(bytes_read = etherdev_poll())) && (tick_count < 12)) continue;
418
419     tick_count = 0;
420
421     return bytes_read;
422 }
423
424
425 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
426     º                                                                     º
427     º                           etherdev_poll()                           º
428     º                                                                     º
429     º Poll the RTL8019AS ethernet device for an available packet.         º
430     º                                                                     º
431     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */
432 static unsigned int etherdev_poll(void)
433 {
434     unsigned int len = 0;
435
436     // Check if there is a packet in the rx buffer.
437     if(etherdev_reg_read(ISR) & PRX)
438     {
439         // Check if the rx buffer has overflowed.
440         if(etherdev_reg_read(ISR) & OVW)
441         {
442             bit retransmit = 0;
443
444             // If the receive buffer ring has overflowed we dump the whole
445             // thing and start over. There is no way of knowing whether the
446             // data it contains is uncorrupted, or will cause us grief.
447
448             // Stop RTL8019AS and abort DMA operation.
449             etherdev_reg_write(CR, RD2 | STP);
450
451             // Reset remote byte count registers.
452             etherdev_reg_write(RBCR0, 0x00);
453             etherdev_reg_write(RBCR1, 0x00);
454
455             // Wait for controller to halt after any current tx completes.
456             while(!(etherdev_reg_read(ISR) & RST)) continue;
457
458             // Check whether currently transmitting a packet.
459             if(etherdev_reg_read(CR) & TXP)
460             {
461                 // If neither a successful transmission nor a tx abort error 
462                 // has occured, then flag current tx packet for resend.
463                 if(!((etherdev_reg_read(ISR) & PTX)
464                                           || (etherdev_reg_read(ISR) & TXE)))
465                 {
466                     retransmit = 1;
467                 }
468             }
469
470             // Set transmit configuration register to loopback internally.
471             etherdev_reg_write(TCR, LB0);
472
473             // Restart the RTL8019AS.
474             etherdev_reg_write(CR, RD2 | STA);
475
476             // Re-initialise last receive buffer read pointer.
477             etherdev_reg_write(BNRY, ETH_RX_PAGE_START);
478
479             // Select RTL8019AS register page 1.
480             ETHERDEV_SELECT_REG_PAGE(1);
481
482             // Re-initialise current packet receive buffer page pointer.
483             etherdev_reg_write(CURR, ETH_RX_PAGE_START);
484
485             // Select RTL8019AS register page 0.
486             ETHERDEV_SELECT_REG_PAGE(0);
487
488             // Clear rx buffer overflow & packet received interrupt flags.
489             etherdev_reg_write(ISR, PRX | OVW);
490
491             // Re-itialise transmit configuration reg for normal operation.
492             etherdev_reg_write(TCR, 0x00);
493         
494             if(retransmit)
495             {
496                 // Retransmit packet in RTL8019AS local tx buffer.
497                 etherdev_reg_write(CR, RD2 | TXP | STA);
498             }
499         }
500         else // Rx buffer has not overflowed, so read a packet into uip_buf.
501         {
502             unsigned int i;
503             unsigned char next_rx_packet;
504             unsigned char current;
505
506             // Retrieve packet header. (status, next_ptr, length_l, length_h)
507
508             // Clear remote DMA complete interrupt status register bit.
509             etherdev_reg_write(ISR, RDC);
510
511             // Set remote DMA start address registers to packet header.
512             etherdev_reg_write(RSAR0, 0x00);
513             etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
514
515             // Set remote DMA byte count registers to packet header length.
516             etherdev_reg_write(RBCR0, 0x04);
517             etherdev_reg_write(RBCR1, 0x00);
518
519             // Initiate DMA transfer of packet header.
520             etherdev_reg_write(CR, RD0 | STA);
521
522             // Drop packet status. We don't use it.
523             etherdev_reg_read(RDMA);
524
525             // Save next packet pointer.
526             next_rx_packet = etherdev_reg_read(RDMA);
527
528             // Retrieve packet data length and subtract CRC bytes.
529             len =  etherdev_reg_read(RDMA);
530             len += etherdev_reg_read(RDMA) << 8;
531             len -= 4;
532
533             // Wait until remote DMA operation completes.
534             while(!(etherdev_reg_read(ISR) & RDC)) continue;
535
536             // Abort/ complete DMA operation.
537             etherdev_reg_write(CR, RD2 | STA);
538
539
540             // Retrieve packet data.
541
542             // Check if incoming packet will fit into rx buffer.
543             if(len <= sizeof(uip_buf))
544             {
545                 // Clear remote DMA complete interrupt status register bit.
546                 etherdev_reg_write(ISR, RDC);
547
548                 // Set remote DMA start address registers to packet data.
549                 etherdev_reg_write(RSAR0, 0x04);
550                 etherdev_reg_write(RSAR1, etherdev_reg_read(BNRY));
551
552                 // Set remote DMA byte count registers to packet data length.
553                 etherdev_reg_write(RBCR0, (unsigned char)(len & 0xFF));
554                 etherdev_reg_write(RBCR1, (unsigned char)(len >> 8));
555
556                 // Initiate DMA transfer of packet data.
557                 etherdev_reg_write(CR, RD0 | STA);
558
559                 // Read packet data directly into uip_buf.
560                 for(i = 0; i < len; i++)
561                 {
562                     *(uip_buf + i) = etherdev_reg_read(RDMA);
563                 }
564
565                 // Wait until remote DMA operation complete.
566                 while(!(etherdev_reg_read(ISR) & RDC)) continue;
567
568                 // Abort/ complete DMA operation.
569                 etherdev_reg_write(CR, RD2 | STA);
570
571             }
572             else
573             {
574                 // Incoming packet too big, so dump it.
575                 len = 0;
576             }
577
578             // Advance boundary pointer to next packet start.
579             etherdev_reg_write(BNRY, next_rx_packet);
580
581             // Select RTL8019AS register page 1.
582             ETHERDEV_SELECT_REG_PAGE(1);
583
584             // Retrieve current receive buffer page
585             current = etherdev_reg_read(CURR);
586
587             // Select RTL8019AS register page 0.
588             ETHERDEV_SELECT_REG_PAGE(0);
589
590             // Check if last packet has been removed from rx buffer.
591             if(next_rx_packet == current)
592             {
593                 // Clear packet received interrupt flag.
594                 etherdev_reg_write(ISR, PRX);
595             }
596         }
597     }
598
599     return len;
600 }
601
602
603
604
605
606
607