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