]> git.sur5r.net Git - freertos/blob - Demo/uIP_Demo_Rowley_ARM7/uip/cs8900a.c
Renamed the CORTEX_M4_ATSAM4S_AVR_Studio directory to the correct CORTEX_M4_ATSAM4S_A...
[freertos] / Demo / uIP_Demo_Rowley_ARM7 / uip / cs8900a.c
1 // cs8900a.c: device driver for the CS8900a chip in 8-bit mode.\r
2 \r
3 #include <LPC210x.h>\r
4 \r
5 #include "cs8900a.h"\r
6 #include "uip.h"\r
7 #include "uip_arp.h"\r
8 \r
9 #define IOR                  (1<<12)          // CS8900's ISA-bus interface pins\r
10 #define IOW                  (1<<13)\r
11 \r
12 // definitions for Crystal CS8900 ethernet-controller\r
13 // based on linux-header by Russel Nelson\r
14 \r
15 #define PP_ChipID            0x0000          // offset 0h -> Corp-ID\r
16                      \r
17                                                                                          // offset 2h -> Model/Product Number\r
18 #define LED_RED (1<<8)\r
19 #define LED_GREEN (1<<10)\r
20 #define LED_YELLOW (1<<11)\r
21 \r
22 #define PP_ISAIOB            0x0020          // IO base address\r
23 #define PP_CS8900_ISAINT     0x0022          // ISA interrupt select\r
24 #define PP_CS8900_ISADMA     0x0024          // ISA Rec DMA channel\r
25 #define PP_ISASOF            0x0026          // ISA DMA offset\r
26 #define PP_DmaFrameCnt       0x0028          // ISA DMA Frame count\r
27 #define PP_DmaByteCnt        0x002A          // ISA DMA Byte count\r
28 #define PP_CS8900_ISAMemB    0x002C          // Memory base\r
29 #define PP_ISABootBase       0x0030          // Boot Prom base\r
30 #define PP_ISABootMask       0x0034          // Boot Prom Mask\r
31 \r
32 // EEPROM data and command registers\r
33 #define PP_EECMD             0x0040          // NVR Interface Command register\r
34 #define PP_EEData            0x0042          // NVR Interface Data Register\r
35 \r
36 // Configuration and control registers\r
37 #define PP_RxCFG             0x0102          // Rx Bus config\r
38 #define PP_RxCTL             0x0104          // Receive Control Register\r
39 #define PP_TxCFG             0x0106          // Transmit Config Register\r
40 #define PP_TxCMD             0x0108          // Transmit Command Register\r
41 #define PP_BufCFG            0x010A          // Bus configuration Register\r
42 #define PP_LineCTL           0x0112          // Line Config Register\r
43 #define PP_SelfCTL           0x0114          // Self Command Register\r
44 #define PP_BusCTL            0x0116          // ISA bus control Register\r
45 #define PP_TestCTL           0x0118          // Test Register\r
46 \r
47 // Status and Event Registers\r
48 #define PP_ISQ               0x0120          // Interrupt Status\r
49 #define PP_RxEvent           0x0124          // Rx Event Register\r
50 #define PP_TxEvent           0x0128          // Tx Event Register\r
51 #define PP_BufEvent          0x012C          // Bus Event Register\r
52 #define PP_RxMiss            0x0130          // Receive Miss Count\r
53 #define PP_TxCol             0x0132          // Transmit Collision Count\r
54 #define PP_LineST            0x0134          // Line State Register\r
55 #define PP_SelfST            0x0136          // Self State register\r
56 #define PP_BusST             0x0138          // Bus Status\r
57 #define PP_TDR               0x013C          // Time Domain Reflectometry\r
58 \r
59 // Initiate Transmit Registers\r
60 #define PP_TxCommand         0x0144          // Tx Command\r
61 #define PP_TxLength          0x0146          // Tx Length\r
62 \r
63 // Adress Filter Registers\r
64 #define PP_LAF               0x0150          // Hash Table\r
65 #define PP_IA                0x0158          // Physical Address Register\r
66 \r
67 // Frame Location\r
68 #define PP_RxStatus          0x0400          // Receive start of frame\r
69 #define PP_RxLength          0x0402          // Receive Length of frame\r
70 #define PP_RxFrame           0x0404          // Receive frame pointer\r
71 #define PP_TxFrame           0x0A00          // Transmit frame pointer\r
72 \r
73 // Primary I/O Base Address. If no I/O base is supplied by the user, then this\r
74 // can be used as the default I/O base to access the PacketPage Area.\r
75 #define DEFAULTIOBASE        0x0300\r
76 \r
77 // PP_RxCFG - Receive  Configuration and Interrupt Mask bit definition - Read/write\r
78 #define SKIP_1               0x0040\r
79 #define RX_STREAM_ENBL       0x0080\r
80 #define RX_OK_ENBL           0x0100\r
81 #define RX_DMA_ONLY          0x0200\r
82 #define AUTO_RX_DMA          0x0400\r
83 #define BUFFER_CRC           0x0800\r
84 #define RX_CRC_ERROR_ENBL    0x1000\r
85 #define RX_RUNT_ENBL         0x2000\r
86 #define RX_EXTRA_DATA_ENBL   0x4000\r
87 \r
88 // PP_RxCTL - Receive Control bit definition - Read/write\r
89 #define RX_IA_HASH_ACCEPT    0x0040\r
90 #define RX_PROM_ACCEPT       0x0080\r
91 #define RX_OK_ACCEPT         0x0100\r
92 #define RX_MULTCAST_ACCEPT   0x0200\r
93 #define RX_IA_ACCEPT         0x0400\r
94 #define RX_BROADCAST_ACCEPT  0x0800\r
95 #define RX_BAD_CRC_ACCEPT    0x1000\r
96 #define RX_RUNT_ACCEPT       0x2000\r
97 #define RX_EXTRA_DATA_ACCEPT 0x4000\r
98 \r
99 // PP_TxCFG - Transmit Configuration Interrupt Mask bit definition - Read/write\r
100 #define TX_LOST_CRS_ENBL     0x0040\r
101 #define TX_SQE_ERROR_ENBL    0x0080\r
102 #define TX_OK_ENBL           0x0100\r
103 #define TX_LATE_COL_ENBL     0x0200\r
104 #define TX_JBR_ENBL          0x0400\r
105 #define TX_ANY_COL_ENBL      0x0800\r
106 #define TX_16_COL_ENBL       0x8000\r
107 \r
108 // PP_TxCMD - Transmit Command bit definition - Read-only and\r
109 // PP_TxCommand - Write-only\r
110 #define TX_START_5_BYTES     0x0000\r
111 #define TX_START_381_BYTES   0x0040\r
112 #define TX_START_1021_BYTES  0x0080\r
113 #define TX_START_ALL_BYTES   0x00C0\r
114 #define TX_FORCE             0x0100\r
115 #define TX_ONE_COL           0x0200\r
116 #define TX_NO_CRC            0x1000\r
117 #define TX_RUNT              0x2000\r
118 \r
119 // PP_BufCFG - Buffer Configuration Interrupt Mask bit definition - Read/write\r
120 #define GENERATE_SW_INTERRUPT      0x0040\r
121 #define RX_DMA_ENBL                0x0080\r
122 #define READY_FOR_TX_ENBL          0x0100\r
123 #define TX_UNDERRUN_ENBL           0x0200\r
124 #define RX_MISS_ENBL               0x0400\r
125 #define RX_128_BYTE_ENBL           0x0800\r
126 #define TX_COL_COUNT_OVRFLOW_ENBL  0x1000\r
127 #define RX_MISS_COUNT_OVRFLOW_ENBL 0x2000\r
128 #define RX_DEST_MATCH_ENBL         0x8000\r
129 \r
130 // PP_LineCTL - Line Control bit definition - Read/write\r
131 #define SERIAL_RX_ON         0x0040\r
132 #define SERIAL_TX_ON         0x0080\r
133 #define AUI_ONLY             0x0100\r
134 #define AUTO_AUI_10BASET     0x0200\r
135 #define MODIFIED_BACKOFF     0x0800\r
136 #define NO_AUTO_POLARITY     0x1000\r
137 #define TWO_PART_DEFDIS      0x2000\r
138 #define LOW_RX_SQUELCH       0x4000\r
139 \r
140 // PP_SelfCTL - Software Self Control bit definition - Read/write\r
141 #define POWER_ON_RESET       0x0040\r
142 #define SW_STOP              0x0100\r
143 #define SLEEP_ON             0x0200\r
144 #define AUTO_WAKEUP          0x0400\r
145 #define HCB0_ENBL            0x1000\r
146 #define HCB1_ENBL            0x2000\r
147 #define HCB0                 0x4000\r
148 #define HCB1                 0x8000\r
149 \r
150 // PP_BusCTL - ISA Bus Control bit definition - Read/write\r
151 #define RESET_RX_DMA         0x0040\r
152 #define MEMORY_ON            0x0400\r
153 #define DMA_BURST_MODE       0x0800\r
154 #define IO_CHANNEL_READY_ON  0x1000\r
155 #define RX_DMA_SIZE_64K      0x2000\r
156 #define ENABLE_IRQ           0x8000\r
157 \r
158 // PP_TestCTL - Test Control bit definition - Read/write\r
159 #define LINK_OFF             0x0080\r
160 #define ENDEC_LOOPBACK       0x0200\r
161 #define AUI_LOOPBACK         0x0400\r
162 #define BACKOFF_OFF          0x0800\r
163 #define FDX_8900             0x4000\r
164 \r
165 // PP_RxEvent - Receive Event Bit definition - Read-only\r
166 #define RX_IA_HASHED         0x0040\r
167 #define RX_DRIBBLE           0x0080\r
168 #define RX_OK                0x0100\r
169 #define RX_HASHED            0x0200\r
170 #define RX_IA                0x0400\r
171 #define RX_BROADCAST         0x0800\r
172 #define RX_CRC_ERROR         0x1000\r
173 #define RX_RUNT              0x2000\r
174 #define RX_EXTRA_DATA        0x4000\r
175 #define HASH_INDEX_MASK      0xFC00          // Hash-Table Index Mask (6 Bit)\r
176 \r
177 // PP_TxEvent - Transmit Event Bit definition - Read-only\r
178 #define TX_LOST_CRS          0x0040\r
179 #define TX_SQE_ERROR         0x0080\r
180 #define TX_OK                0x0100\r
181 #define TX_LATE_COL          0x0200\r
182 #define TX_JBR               0x0400\r
183 #define TX_16_COL            0x8000\r
184 #define TX_COL_COUNT_MASK    0x7800\r
185 \r
186 // PP_BufEvent - Buffer Event Bit definition - Read-only\r
187 #define SW_INTERRUPT         0x0040\r
188 #define RX_DMA               0x0080\r
189 #define READY_FOR_TX         0x0100\r
190 #define TX_UNDERRUN          0x0200\r
191 #define RX_MISS              0x0400\r
192 #define RX_128_BYTE          0x0800\r
193 #define TX_COL_OVRFLW        0x1000\r
194 #define RX_MISS_OVRFLW       0x2000\r
195 #define RX_DEST_MATCH        0x8000\r
196 \r
197 // PP_LineST - Ethernet Line Status bit definition - Read-only\r
198 #define LINK_OK              0x0080\r
199 #define AUI_ON               0x0100\r
200 #define TENBASET_ON          0x0200\r
201 #define POLARITY_OK          0x1000\r
202 #define CRS_OK               0x4000\r
203 \r
204 // PP_SelfST - Chip Software Status bit definition\r
205 #define ACTIVE_33V           0x0040\r
206 #define INIT_DONE            0x0080\r
207 #define SI_BUSY              0x0100\r
208 #define EEPROM_PRESENT       0x0200\r
209 #define EEPROM_OK            0x0400\r
210 #define EL_PRESENT           0x0800\r
211 #define EE_SIZE_64           0x1000\r
212 \r
213 // PP_BusST - ISA Bus Status bit definition\r
214 #define TX_BID_ERROR         0x0080\r
215 #define READY_FOR_TX_NOW     0x0100\r
216 \r
217 // The following block defines the ISQ event types\r
218 #define ISQ_RX_EVENT         0x0004\r
219 #define ISQ_TX_EVENT         0x0008\r
220 #define ISQ_BUFFER_EVENT     0x000C\r
221 #define ISQ_RX_MISS_EVENT    0x0010\r
222 #define ISQ_TX_COL_EVENT     0x0012\r
223 \r
224 #define ISQ_EVENT_MASK       0x003F          // ISQ mask to find out type of event\r
225 \r
226 // Ports for I/O-Mode\r
227 #define RX_FRAME_PORT        0x0000\r
228 #define TX_FRAME_PORT        0x0000\r
229 #define TX_CMD_PORT          0x0004\r
230 #define TX_LEN_PORT          0x0006\r
231 #define ISQ_PORT             0x0008\r
232 #define ADD_PORT             0x000A\r
233 #define DATA_PORT            0x000C\r
234 \r
235 #define AUTOINCREMENT        0x8000          // Bit mask to set Bit-15 for autoincrement\r
236 \r
237 // EEProm Commands\r
238 #define EEPROM_WRITE_EN      0x00F0\r
239 #define EEPROM_WRITE_DIS     0x0000\r
240 #define EEPROM_WRITE_CMD     0x0100\r
241 #define EEPROM_READ_CMD      0x0200\r
242 \r
243 // Receive Header of each packet in receive area of memory for DMA-Mode\r
244 #define RBUF_EVENT_LOW       0x0000          // Low byte of RxEvent\r
245 #define RBUF_EVENT_HIGH      0x0001          // High byte of RxEvent\r
246 #define RBUF_LEN_LOW         0x0002          // Length of received data - low byte\r
247 #define RBUF_LEN_HI          0x0003          // Length of received data - high byte\r
248 #define RBUF_HEAD_LEN        0x0004          // Length of this header\r
249 \r
250 // typedefs\r
251 typedef struct {                             // struct to store CS8900's\r
252   unsigned int Addr;                         // init-sequence\r
253   unsigned int Data;\r
254 } TInitSeq;\r
255 \r
256 unsigned short ticks;\r
257 \r
258 static void skip_frame(void);\r
259 \r
260 const TInitSeq InitSeq[] =\r
261 {\r
262   PP_IA,       UIP_ETHADDR0 + (UIP_ETHADDR1 << 8),     // set our MAC as Individual Address\r
263   PP_IA + 2,   UIP_ETHADDR2 + (UIP_ETHADDR3 << 8),\r
264   PP_IA + 4,   UIP_ETHADDR4 + (UIP_ETHADDR5 << 8),\r
265   PP_LineCTL,  SERIAL_RX_ON | SERIAL_TX_ON,           // configure the Physical Interface\r
266   PP_RxCTL,    RX_OK_ACCEPT | RX_IA_ACCEPT | RX_BROADCAST_ACCEPT\r
267 };\r
268 \r
269 // Writes a word in little-endian byte order to a specified port-address\r
270 void\r
271 cs8900a_write(unsigned addr, unsigned int data)\r
272 {\r
273   GPIO_IODIR |= 0xff << 16;                           // Data port to output\r
274 \r
275   GPIO_IOCLR = 0xf << 4;                              // Put address on bus\r
276   GPIO_IOSET = addr << 4;\r
277   \r
278   GPIO_IOCLR = 0xff << 16;                            // Write low order byte to data bus\r
279   GPIO_IOSET = data << 16;\r
280 \r
281   asm volatile ( "NOP" );\r
282   GPIO_IOCLR = IOW;                                   // Toggle IOW-signal\r
283   asm volatile ( "NOP" );\r
284   GPIO_IOSET = IOW;\r
285   asm volatile ( "NOP" );\r
286 \r
287   GPIO_IOCLR = 0xf << 4;\r
288   GPIO_IOSET = ((addr | 1) << 4);                     // And put next address on bus\r
289 \r
290   GPIO_IOCLR = 0xff << 16;                            // Write high order byte to data bus\r
291   GPIO_IOSET = data >> 8 << 16;\r
292 \r
293   asm volatile ( "NOP" );\r
294   GPIO_IOCLR = IOW;                                   // Toggle IOW-signal\r
295   asm volatile ( "NOP" );\r
296   GPIO_IOSET = IOW;\r
297   asm volatile ( "NOP" );\r
298 }\r
299 \r
300 // Reads a word in little-endian byte order from a specified port-address\r
301 unsigned\r
302 cs8900a_read(unsigned addr)\r
303 {\r
304   unsigned int value;\r
305 \r
306   GPIO_IODIR &= ~(0xff << 16);                        // Data port to input\r
307 \r
308   GPIO_IOCLR = 0xf << 4;                              // Put address on bus\r
309   GPIO_IOSET = addr << 4;\r
310 \r
311   asm volatile ( "NOP" );\r
312   GPIO_IOCLR = IOR;                                   // IOR-signal low\r
313   asm volatile ( "NOP" );\r
314   value = (GPIO_IOPIN >> 16) & 0xff;                  // get low order byte from data bus\r
315   GPIO_IOSET = IOR;\r
316 \r
317   GPIO_IOSET = 1 << 4;                                // IOR high and put next address on bus\r
318 \r
319   asm volatile ( "NOP" );\r
320   GPIO_IOCLR = IOR;                                   // IOR-signal low\r
321   asm volatile ( "NOP" );\r
322   value |= ((GPIO_IOPIN >> 8) & 0xff00);              // get high order byte from data bus\r
323   GPIO_IOSET = IOR;                                   // IOR-signal low\r
324   \r
325   return value;\r
326 }\r
327 \r
328 // Reads a word in little-endian byte order from a specified port-address\r
329 unsigned\r
330 cs8900a_read_addr_high_first(unsigned addr)\r
331 {\r
332   unsigned int value;\r
333 \r
334   GPIO_IODIR &= ~(0xff << 16);                        // Data port to input\r
335 \r
336   GPIO_IOCLR = 0xf << 4;                              // Put address on bus\r
337   GPIO_IOSET = (addr+1) << 4;\r
338 \r
339   asm volatile ( "NOP" );\r
340   GPIO_IOCLR = IOR;                                   // IOR-signal low\r
341   asm volatile ( "NOP" );\r
342   value = ((GPIO_IOPIN >> 8) & 0xff00);               // get high order byte from data bus\r
343   GPIO_IOSET = IOR;                                   // IOR-signal high\r
344 \r
345   GPIO_IOCLR = 1 << 4;                                // Put low address on bus\r
346 \r
347   asm volatile ( "NOP" );\r
348   GPIO_IOCLR = IOR;                                   // IOR-signal low\r
349   asm volatile ( "NOP" );\r
350   value |= (GPIO_IOPIN >> 16) & 0xff;                 // get low order byte from data bus\r
351   GPIO_IOSET = IOR;\r
352 \r
353   return value;\r
354 }\r
355 \r
356 void\r
357 cs8900a_init(void)\r
358 {\r
359   int i;\r
360 \r
361   // Reset outputs, control lines high\r
362   GPIO_IOSET = IOR | IOW;\r
363 \r
364   // No LEDs on.\r
365   GPIO_IOSET = LED_RED | LED_YELLOW | LED_GREEN;\r
366 \r
367   // Port 3 as output (all pins but RS232)\r
368   GPIO_IODIR = ~0U; // everything to output.\r
369 \r
370   // Reset outputs\r
371   GPIO_IOCLR = 0xff << 16;  // clear data outputs\r
372 \r
373   // Reset the CS8900A\r
374   cs8900a_write(ADD_PORT, PP_SelfCTL);\r
375   cs8900a_write(DATA_PORT, POWER_ON_RESET);\r
376 \r
377   // Wait until chip-reset is done\r
378   cs8900a_write(ADD_PORT, PP_SelfST);\r
379   while ((cs8900a_read(DATA_PORT) & INIT_DONE) == 0)\r
380     ;\r
381 \r
382   // Configure the CS8900A\r
383   for (i = 0; i < sizeof InitSeq / sizeof (TInitSeq); ++i)\r
384     {\r
385       cs8900a_write(ADD_PORT, InitSeq[i].Addr);\r
386       cs8900a_write(DATA_PORT, InitSeq[i].Data);\r
387     }\r
388 }\r
389 \r
390 void\r
391 cs8900a_send(void)\r
392 {\r
393   unsigned u;\r
394 \r
395   GPIO_IOCLR = LED_RED;  // Light RED LED when frame starting\r
396 \r
397   // Transmit command\r
398   cs8900a_write(TX_CMD_PORT, TX_START_ALL_BYTES);\r
399   cs8900a_write(TX_LEN_PORT, uip_len);\r
400 \r
401   // Maximum number of retries\r
402   u = 8;\r
403   for (;;)\r
404     {\r
405       // Check for avaliable buffer space\r
406       cs8900a_write(ADD_PORT, PP_BusST);\r
407       if (cs8900a_read(DATA_PORT) & READY_FOR_TX_NOW)\r
408         break;\r
409       if (u -- == 0)\r
410         {\r
411           GPIO_IOSET = LED_RED;  // Extinguish RED LED on end of frame\r
412           return;\r
413         }\r
414 \r
415       // No space avaliable, skip a received frame and try again\r
416       skip_frame();\r
417     }\r
418 \r
419   GPIO_IODIR |= 0xff << 16;                           // Data port to output\r
420 \r
421   // Send 40+14=54 bytes of header\r
422   for (u = 0; u < 54; u += 2)\r
423     {\r
424       GPIO_IOCLR = 0xf << 4;                              // Put address on bus\r
425       GPIO_IOSET = TX_FRAME_PORT << 4;\r
426 \r
427       GPIO_IOCLR = 0xff << 16;                            // Write low order byte to data bus\r
428       GPIO_IOSET = uip_buf[u] << 16;                      // write low order byte to data bus\r
429 \r
430       asm volatile ( "NOP" );\r
431       GPIO_IOCLR = IOW;                                   // Toggle IOW-signal\r
432       asm volatile ( "NOP" );\r
433       GPIO_IOSET = IOW;\r
434 \r
435       GPIO_IOCLR = 0xf << 4;                              // Put address on bus\r
436       GPIO_IOSET = (TX_FRAME_PORT | 1) << 4;              // and put next address on bus\r
437 \r
438       GPIO_IOCLR = 0xff << 16;                            // Write low order byte to data bus\r
439       GPIO_IOSET = uip_buf[u+1] << 16;                    // write low order byte to data bus\r
440 \r
441       asm volatile ( "NOP" );\r
442           GPIO_IOCLR = IOW;                                   // Toggle IOW-signal\r
443       asm volatile ( "NOP" );\r
444       GPIO_IOSET = IOW;\r
445     }\r
446 \r
447   if (uip_len <= 54)\r
448     {\r
449       GPIO_IOSET = LED_RED;  // Extinguish RED LED on end of frame\r
450       return;\r
451     }\r
452 \r
453   // Send remainder of packet, the application data\r
454   uip_len -= 54;\r
455   for (u = 0; u < uip_len; u += 2)\r
456     {\r
457 \r
458       GPIO_IOCLR = 0xf << 4;                          // Put address on bus\r
459       GPIO_IOSET = TX_FRAME_PORT << 4;\r
460 \r
461       GPIO_IOCLR = 0xff << 16;                        // Write low order byte to data bus\r
462       GPIO_IOSET = uip_appdata[u] << 16;              // write low order byte to data bus\r
463 \r
464       asm volatile ( "NOP" );\r
465           GPIO_IOCLR = IOW;                               // Toggle IOW-signal\r
466       asm volatile ( "NOP" );\r
467       GPIO_IOSET = IOW;\r
468 \r
469       GPIO_IOCLR = 0xf << 4;                          // Put address on bus\r
470       GPIO_IOSET = (TX_FRAME_PORT | 1) << 4;          // and put next address on bus\r
471 \r
472       GPIO_IOCLR = 0xff << 16;                        // Write low order byte to data bus\r
473       GPIO_IOSET = uip_appdata[u+1] << 16;            // write low order byte to data bus\r
474 \r
475       asm volatile ( "NOP" );\r
476           GPIO_IOCLR = IOW;                               // Toggle IOW-signal\r
477       asm volatile ( "NOP" );\r
478       GPIO_IOSET = IOW;\r
479     }\r
480 \r
481   GPIO_IOSET = LED_RED;  // Extinguish RED LED on end of frame\r
482 }\r
483 \r
484 static void\r
485 skip_frame(void)\r
486 {\r
487   // No space avaliable, skip a received frame and try again\r
488   cs8900a_write(ADD_PORT, PP_RxCFG);\r
489   cs8900a_write(DATA_PORT, cs8900a_read(DATA_PORT) | SKIP_1);\r
490 }\r
491 \r
492 u8_t\r
493 cs8900a_poll(void)\r
494 {\r
495   u16_t len, u;\r
496 \r
497   // Check receiver event register to see if there are any valid frames avaliable\r
498   cs8900a_write(ADD_PORT, PP_RxEvent);\r
499   if ((cs8900a_read(DATA_PORT) & 0xd00) == 0)\r
500     return 0;\r
501 \r
502   GPIO_IOCLR = LED_GREEN;  // Light GREED LED when frame coming in.\r
503 \r
504   // Read receiver status and discard it.\r
505   cs8900a_read_addr_high_first(RX_FRAME_PORT);\r
506 \r
507   // Read frame length\r
508   len = cs8900a_read_addr_high_first(RX_FRAME_PORT);\r
509 \r
510   // If the frame is too big to handle, throw it away\r
511   if (len > UIP_BUFSIZE)\r
512     {\r
513       skip_frame();\r
514       return 0;\r
515     }\r
516 \r
517   // Data port to input\r
518   GPIO_IODIR &= ~(0xff << 16);\r
519 \r
520   GPIO_IOCLR = 0xf << 4;                          // put address on bus\r
521   GPIO_IOSET = RX_FRAME_PORT << 4; \r
522 \r
523   // Read bytes into uip_buf\r
524   u = 0;\r
525   while (u < len)\r
526     {\r
527       GPIO_IOCLR = 1 << 4;                            // put address on bus\r
528 \r
529       GPIO_IOCLR = IOR;                               // IOR-signal low\r
530       uip_buf[u] = GPIO_IOPIN >> 16;                // get high order byte from data bus\r
531       asm volatile ( "NOP" );\r
532       GPIO_IOSET = IOR;                               // IOR-signal high\r
533 \r
534       GPIO_IOSET = 1 << 4;                            // put address on bus\r
535 \r
536       GPIO_IOCLR = IOR;                               // IOR-signal low\r
537       asm volatile ( "NOP" );\r
538       uip_buf[u+1] = GPIO_IOPIN >> 16;                  // get high order byte from data bus\r
539       GPIO_IOSET = IOR;                               // IOR-signal high\r
540       u += 2;\r
541     }\r
542 \r
543   GPIO_IOSET = LED_GREEN;  // Extinguish GREED LED when frame finished.\r
544   return len;\r
545 }\r
546 \r