]> git.llucax.com Git - z.facultad/66.09/etherled.git/blob - pruebas/keil/red_test_anda/etherdev.c
Primer ejemplo con la red funcionando.
[z.facultad/66.09/etherled.git] / pruebas / keil / red_test_anda / etherdev.c
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
7          º  ARCHIVE:                                                º\r
8          º   AUTHOR:  Copyright (c) 2005, Murray R. Van Luyn.       º\r
9          º   Refer to National Semiconductor DP8390 App Note 874.   º\r
10          ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ        */\r
11 \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
25 \r
26 \r
27 #include "etherdev.h"\r
28 \r
29 void sleep(unsigned char);\r
30 \r
31 static xdata leds1 _at_ 0x0080;\r
32 static xdata leds2 _at_ 0x00c0;\r
33 \r
34 unsigned char uip_buf[64] =\r
35 {\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
39         0x00, 0x00, // Type\r
40 };\r
41 \r
42 unsigned int uip_len = 14;\r
43 \r
44 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
45     º                            Private defines.                         º\r
46     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
47 #define ETH_CPU_CLOCK      ETH_CPU_XTAL / 12    // 8051 clock rate (X1 mode)\r
48 \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
52 \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
57 \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
62 \r
63 #define ETH_ADDR_PORT_MASK 0x1F                 // 00011111y\r
64 #define ETH_DATA_PORT_MASK 0xFF                 // 11111111y\r
65 \r
66 #define ETH_MIN_PACKET_LEN 0x3C\r
67 \r
68 \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
77 \r
78 \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
84           do                                                                \\r
85           {                                                                 \\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
88           } while(0)\r
89 \r
90 \r
91 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
92     º                              Global Variables                       º\r
93     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
94 static unsigned char tick_count = 0;\r
95 \r
96 \r
97 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
98     º                     Private Function Implementation                 º\r
99     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
100 \r
101 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
102     º                                                                     º\r
103     º                          etherdev_reg_write()                       º\r
104     º                                                                     º\r
105     º                                                                     º\r
106     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
107 static void etherdev_reg_write(unsigned char reg, unsigned char wr_data)\r
108 {\r
109     // Select register address.\r
110     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK; \r
111     ETH_ADDR_PORT |= reg;\r
112 \r
113     // Output register data to port.\r
114     ETH_DATA_PORT = wr_data;\r
115 \r
116     // Clock register data into RTL8019AS.\r
117     // IOR & IOW are both active low.\r
118         NICE = 0;\r
119     IOW = 0;\r
120     IOW = 1;\r
121         NICE = 1;\r
122 \r
123     // Set register data port as input again.\r
124     ETH_DATA_PORT = ETH_DATA_PORT_MASK;\r
125 \r
126     return;\r
127\r
128 \r
129 \r
130 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
131     º                                                                     º\r
132     º                          etherdev_reg_read()                        º\r
133     º                                                                     º\r
134     º                                                                     º\r
135     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
136 static unsigned char etherdev_reg_read(unsigned char reg)\r
137 {\r
138     unsigned char rd_data;\r
139 \r
140     // Select register address.\r
141     ETH_ADDR_PORT &= ~ETH_ADDR_PORT_MASK;\r
142     ETH_ADDR_PORT |= reg;\r
143 \r
144     // Enable register data output from RTL8019AS.\r
145         NICE = 0;\r
146     IOR = 0;\r
147 \r
148     // Read register data from port.\r
149     rd_data = ETH_DATA_PORT;\r
150 \r
151     // Disable register data output from RTL8019AS.\r
152     IOR = 1; \r
153         NICE = 1;   \r
154 \r
155     return rd_data;\r
156\r
157 \r
158 \r
159 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
160     º                                                                     º\r
161     º                          etherdev_delay_ms()                        º\r
162     º                                                                     º\r
163     º  1 to 255+ ms delay.                                                º\r
164     º                                                                     º\r
165     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
166 static void etherdev_delay_ms(unsigned int count)\r
167 {\r
168 \r
169     for(count *= ETH_DELAY_MULTPLR; count > 0; count--) continue;\r
170 \r
171     return;\r
172 }\r
173 \r
174 \r
175 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
176     º                                                                     º\r
177     º                           etherdev_timer0_isr()                     º\r
178     º                                                                     º\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
181     º                                                                     º\r
182     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
183 static void etherdev_timer0_isr(void) interrupt 1 using 1\r
184 {\r
185     // Reload timer/ counter 0 for 24Hz periodic interrupt.   \r
186     TH0 = ETH_T0_RELOAD >> 8;\r
187     TL0 = ETH_T0_RELOAD;\r
188 \r
189     // Increment 24ths of a second counter.\r
190     tick_count++;\r
191 \r
192     return;\r
193 }\r
194 \r
195 \r
196 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
197     º                     Public Function Implementation                  º\r
198     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
199 \r
200 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
201     º                                                                     º\r
202     º                            etherdev_init()                          º\r
203     º                                                                     º\r
204     º  Returns: 1 on success, 0 on failure.                               º\r
205     º  Refer to National Semiconductor DP8390 App Note 874, July 1993.    º\r
206     º                                                                     º\r
207     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
208 bit etherdev_init(void)\r
209 {\r
210     // Set IOR & IOW as they're active low.\r
211     IOR = 1;\r
212     IOW = 1;\r
213         NICE = 1;\r
214 \r
215     // Set register data port as input.\r
216     ETH_DATA_PORT = ETH_DATA_PORT_MASK;\r
217 \r
218 #ifdef ETH_DEBUG\r
219     init_sio_poll();\r
220 #endif /* ETH_DEBUG */\r
221 \r
222     // Configure RTL8019AS ethernet controller.\r
223 \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
227 \r
228     // Select RTL8019AS register page 0.\r
229     ETHERDEV_SELECT_REG_PAGE(0);\r
230 \r
231     // Check if RTL8019AS fully reset.\r
232     if(!(etherdev_reg_read(ISR) & RST))\r
233     {\r
234 leds1 = ~0xff;\r
235 leds2 = ~0xff;\r
236 while(1);\r
237         return 0;\r
238     }\r
239 /*\r
240     // Select RTL8019AS register page 3.\r
241     ETHERDEV_SELECT_REG_PAGE(3);\r
242 \r
243     // Temporarily disable config register write protection.\r
244     etherdev_reg_write(_9346CR, EEM1 | EEM0);\r
245 \r
246     // Disable boot ROM & select 10BaseT with TP/CX auto-detect.\r
247     etherdev_reg_write(CONFIG2, BSELB);\r
248 \r
249     // Select half-duplex, awake, power-up & LED_TX/ LED_RX/ LED_LNK behaviour.\r
250     etherdev_reg_write(CONFIG3, LEDS0);\r
251 \r
252     // Re-enable config register write protection.\r
253     etherdev_reg_write(_9346CR, 0x00);\r
254 */\r
255     // Select RTL8019AS register page 0.\r
256     ETHERDEV_SELECT_REG_PAGE(0);\r
257 \r
258     // Stop RTL8019AS, select page 0 and abort DMA operation.\r
259     etherdev_reg_write(CR, RD2 | STP);\r
260 \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
264 \r
265     // Reset remote byte count registers.\r
266     etherdev_reg_write(RBCR0, 0x00);\r
267     etherdev_reg_write(RBCR1, 0x00);\r
268 \r
269     // Receive configuration register to monitor mode.\r
270     etherdev_reg_write(RCR, MON);\r
271 \r
272     // Initialise transmit configuration register to loopback internally.\r
273     etherdev_reg_write(TCR, LB0);\r
274 \r
275     // Clear interrupt status register bits by writing 1 to each.\r
276     etherdev_reg_write(ISR, 0xFF);\r
277 \r
278     // Mask all interrupts in mask register.\r
279     etherdev_reg_write(IMR, 0x00);\r
280 \r
281         // Obtengo MAC de la placa\r
282     //etherdev_reg_write(CR, 0x21);\r
283 \r
284 \r
285     // Set transmit page start.\r
286     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);\r
287 \r
288     // Set receive buffer page start.\r
289     etherdev_reg_write(PSTART, ETH_RX_PAGE_START);\r
290 \r
291     // Initialise last receive buffer read pointer.\r
292     etherdev_reg_write(BNRY, ETH_RX_PAGE_START);\r
293 \r
294     // Set receive buffer page stop.\r
295     etherdev_reg_write(PSTOP, ETH_RX_PAGE_STOP);\r
296 \r
297     // Select RTL8019AS register page 1.\r
298     etherdev_reg_write(CR, RD2 | PS0 | STP);\r
299 \r
300     // Initialise current packet receive buffer page pointer\r
301     etherdev_reg_write(CURR, ETH_RX_PAGE_START);\r
302 \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
310 \r
311     // Select RTL8019AS register page 0 and abort DMA operation.\r
312     etherdev_reg_write(CR, RD2 | STP);\r
313 \r
314     // Restart RTL8019AS. \r
315     etherdev_reg_write(CR, RD2 | STA);\r
316 \r
317     // Initialise transmit configuration register for normal operation.\r
318     etherdev_reg_write(TCR, 0x00);\r
319 \r
320     // Receive configuration register to accept broadcast packets.\r
321     etherdev_reg_write(RCR, AB);\r
322 \r
323 \r
324     // Initialize Timer 0 to generate a periodic 24Hz interrupt. \r
325 \r
326     // Stop timer/ counter 0.                                         \r
327     TR0  = 0;          \r
328 \r
329     // Set timer/ counter 0 as mode 1 16 bit timer.      \r
330     TMOD &= 0xF0;\r
331     TMOD |= 0x01;\r
332 \r
333     // Preload for 24Hz periodic interrupt.    \r
334     TH0 = ETH_T0_RELOAD >> 8; \r
335     TL0 = ETH_T0_RELOAD;\r
336 \r
337     // Restart timer/ counter 0 running.\r
338     TR0 = 1;\r
339 \r
340     // Enable timer/ counter 0 overflow interrupt.            \r
341     ET0 = 1;\r
342 \r
343     // Enable global interrupt.\r
344     EA = 1;\r
345 \r
346     return 1;\r
347 }\r
348 \r
349 \r
350 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
351     º                                                                     º\r
352     º                           etherdev_send()                           º\r
353     º                                                                     º\r
354     º Send the packet in the uip_buf and uip_appdata buffers using the    º\r
355     º RTL8019AS ethernet card.                                            º\r
356     º                                                                     º\r
357     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
358 void etherdev_send(void)\r
359 {\r
360     unsigned int i;\r
361     unsigned char *ptr;\r
362 \r
363     ptr = uip_buf;\r
364 \r
365     // Setup for DMA transfer from uip_buf & uip_appdata buffers to RTL8019AS.\r
366 \r
367     // Select RTL8019AS register page 0 and abort DMA operation.\r
368     etherdev_reg_write(CR, RD2 | STA);\r
369 \r
370 leds1 = ~0x01;\r
371 i = etherdev_reg_read(CR);\r
372 leds2 = ~i;\r
373     // Wait until pending transmit operation completes.\r
374     while(etherdev_reg_read(CR) & TXP) continue;\r
375 \r
376     // Clear remote DMA complete interrupt status register bit.\r
377     etherdev_reg_write(ISR, RDC);\r
378 \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
382 \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
386 \r
387     // Initiate DMA transfer of uip_buf & uip_appdata buffers to RTL8019AS.\r
388     etherdev_reg_write(CR, RD1 | STA);\r
389 \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
393     {\r
394         etherdev_reg_write(RDMA, *ptr++);\r
395     }\r
396 \r
397     // Wait until remote DMA operation complete.\r
398 leds1 = ~0x02;\r
399 leds2 = ~etherdev_reg_read(ISR);\r
400     while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
401 \r
402     // Abort/ complete DMA operation.\r
403     etherdev_reg_write(CR, RD2 | STA);\r
404 \r
405     // Set transmit page start to indicate packet start.\r
406     etherdev_reg_write(TPSR, ETH_TX_PAGE_START);\r
407 \r
408     // Ethernet packets must be > 60 bytes, otherwise are rejected as runts.\r
409     if(uip_len < ETH_MIN_PACKET_LEN)\r
410     {\r
411         uip_len = ETH_MIN_PACKET_LEN;\r
412     }\r
413 \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
417 \r
418     // Issue command for RTL8019AS to transmit packet from it's local buffer.\r
419     etherdev_reg_write(CR, RD2 | TXP | STA);\r
420 \r
421     return;\r
422 }\r
423 \r
424 \r
425 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
426     º                                                                     º\r
427     º                           etherdev_read()                           º\r
428     º                                                                     º\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
433     º                                                                     º\r
434     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
435 unsigned int etherdev_read(void)\r
436 {    \r
437     unsigned int bytes_read;\r
438 \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
444 \r
445     tick_count = 0;\r
446 \r
447     return bytes_read;\r
448 }\r
449 \r
450 \r
451 /*  ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»\r
452     º                                                                     º\r
453     º                           etherdev_poll()                           º\r
454     º                                                                     º\r
455     º Poll the RTL8019AS ethernet device for an available packet.         º\r
456     º                                                                     º\r
457     ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ  */\r
458 static unsigned int etherdev_poll(void)\r
459 {\r
460     unsigned int len = 0;\r
461 \r
462     // Check if there is a packet in the rx buffer.\r
463     if(etherdev_reg_read(ISR) & PRX)\r
464     {\r
465         // Check if the rx buffer has overflowed.\r
466         if(etherdev_reg_read(ISR) & OVW)\r
467         {\r
468             bit retransmit = 0;\r
469 \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
473 \r
474             // Stop RTL8019AS and abort DMA operation.\r
475             etherdev_reg_write(CR, RD2 | STP);\r
476 \r
477             // Reset remote byte count registers.\r
478             etherdev_reg_write(RBCR0, 0x00);\r
479             etherdev_reg_write(RBCR1, 0x00);\r
480 \r
481             // Wait for controller to halt after any current tx completes.\r
482             while(!(etherdev_reg_read(ISR) & RST)) continue;\r
483 \r
484             // Check whether currently transmitting a packet.\r
485             if(etherdev_reg_read(CR) & TXP)\r
486             {\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
491                 {\r
492                     retransmit = 1;\r
493                 }\r
494             }\r
495 \r
496             // Set transmit configuration register to loopback internally.\r
497             etherdev_reg_write(TCR, LB0);\r
498 \r
499             // Restart the RTL8019AS.\r
500             etherdev_reg_write(CR, RD2 | STA);\r
501 \r
502             // Re-initialise last receive buffer read pointer.\r
503             etherdev_reg_write(BNRY, ETH_RX_PAGE_START);\r
504 \r
505             // Select RTL8019AS register page 1.\r
506             ETHERDEV_SELECT_REG_PAGE(1);\r
507 \r
508             // Re-initialise current packet receive buffer page pointer.\r
509             etherdev_reg_write(CURR, ETH_RX_PAGE_START);\r
510 \r
511             // Select RTL8019AS register page 0.\r
512             ETHERDEV_SELECT_REG_PAGE(0);\r
513 \r
514             // Clear rx buffer overflow & packet received interrupt flags.\r
515             etherdev_reg_write(ISR, PRX | OVW);\r
516 \r
517             // Re-itialise transmit configuration reg for normal operation.\r
518             etherdev_reg_write(TCR, 0x00);\r
519         \r
520             if(retransmit)\r
521             {\r
522                 // Retransmit packet in RTL8019AS local tx buffer.\r
523                 etherdev_reg_write(CR, RD2 | TXP | STA);\r
524             }\r
525         }\r
526         else // Rx buffer has not overflowed, so read a packet into uip_buf.\r
527         {\r
528             unsigned int i;\r
529             unsigned char next_rx_packet;\r
530             unsigned char current;\r
531 \r
532             // Retrieve packet header. (status, next_ptr, length_l, length_h)\r
533 \r
534             // Clear remote DMA complete interrupt status register bit.\r
535             etherdev_reg_write(ISR, RDC);\r
536 \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
540 \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
544 \r
545             // Initiate DMA transfer of packet header.\r
546             etherdev_reg_write(CR, RD0 | STA);\r
547 \r
548             // Drop packet status. We don't use it.\r
549             etherdev_reg_read(RDMA);\r
550 \r
551             // Save next packet pointer.\r
552             next_rx_packet = etherdev_reg_read(RDMA);\r
553 \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
557             len -= 4;\r
558 \r
559             // Wait until remote DMA operation completes.\r
560             while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
561 \r
562             // Abort/ complete DMA operation.\r
563             etherdev_reg_write(CR, RD2 | STA);\r
564 \r
565 \r
566             // Retrieve packet data.\r
567 \r
568             // Check if incoming packet will fit into rx buffer.\r
569             if(len <= sizeof(uip_buf))\r
570             {\r
571                 // Clear remote DMA complete interrupt status register bit.\r
572                 etherdev_reg_write(ISR, RDC);\r
573 \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
577 \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
581 \r
582                 // Initiate DMA transfer of packet data.\r
583                 etherdev_reg_write(CR, RD0 | STA);\r
584 \r
585                 // Read packet data directly into uip_buf.\r
586                 for(i = 0; i < len; i++)\r
587                 {\r
588                     *(uip_buf + i) = etherdev_reg_read(RDMA);\r
589                 }\r
590 \r
591                 // Wait until remote DMA operation complete.\r
592                 while(!(etherdev_reg_read(ISR) & RDC)) continue;\r
593 \r
594                 // Abort/ complete DMA operation.\r
595                 etherdev_reg_write(CR, RD2 | STA);\r
596 \r
597             }\r
598             else\r
599             {\r
600                 // Incoming packet too big, so dump it.\r
601                 len = 0;\r
602             }\r
603 \r
604             // Advance boundary pointer to next packet start.\r
605             etherdev_reg_write(BNRY, next_rx_packet);\r
606 \r
607             // Select RTL8019AS register page 1.\r
608             ETHERDEV_SELECT_REG_PAGE(1);\r
609 \r
610             // Retrieve current receive buffer page\r
611             current = etherdev_reg_read(CURR);\r
612 \r
613             // Select RTL8019AS register page 0.\r
614             ETHERDEV_SELECT_REG_PAGE(0);\r
615 \r
616             // Check if last packet has been removed from rx buffer.\r
617             if(next_rx_packet == current)\r
618             {\r
619                 // Clear packet received interrupt flag.\r
620                 etherdev_reg_write(ISR, PRX);\r
621             }\r
622         }\r
623     }\r
624 \r
625     return len;\r
626 }\r
627 \r
628 \r
629 \r
630 \r
631 \r
632 \r
633 \r
634 \r