root/webserver/example/EasyWEB/EMAC.c

Revision 9, 10.2 kB (checked in by phil, 15 years ago)

EasyWEB example for uVision (original from CD)

Line 
1 /******************************************************************
2  *****                                                        *****
3  *****  Name: cs8900.c                                        *****
4  *****  Ver.: 1.0                                             *****
5  *****  Date: 07/05/2001                                      *****
6  *****  Auth: Andreas Dannenberg                              *****
7  *****        HTWK Leipzig                                    *****
8  *****        university of applied sciences                  *****
9  *****        Germany                                         *****
10  *****  Func: ethernet packet-driver for use with LAN-        *****
11  *****        controller CS8900 from Crystal/Cirrus Logic     *****
12  *****                                                        *****
13  *****  Keil: Module modified for use with Philips            *****
14  *****        LPC2378 EMAC Ethernet controller                *****
15  *****                                                        *****
16  ******************************************************************/
17
18 #include "EMAC.h"
19 #include "tcpip.h"
20 #include <LPC23xx.h>
21
22 static unsigned short *rptr;
23 static unsigned short *tptr;
24
25 // Keil: function added to write PHY
26 void write_PHY (int PhyReg, int Value)
27 {
28   unsigned int tout;
29
30   MAC_MADR = DP83848C_DEF_ADR | PhyReg;
31   MAC_MWTD = Value;
32
33   /* Wait utill operation completed */
34   tout = 0;
35   for (tout = 0; tout < MII_WR_TOUT; tout++) {
36     if ((MAC_MIND & MIND_BUSY) == 0) {
37       break;
38     }
39   }
40 }
41
42
43 // Keil: function added to read PHY
44 unsigned short read_PHY (unsigned char PhyReg)
45 {
46   unsigned int tout;
47
48   MAC_MADR = DP83848C_DEF_ADR | PhyReg;
49   MAC_MCMD = MCMD_READ;
50
51   /* Wait until operation completed */
52   tout = 0;
53   for (tout = 0; tout < MII_RD_TOUT; tout++) {
54     if ((MAC_MIND & MIND_BUSY) == 0) {
55       break;
56     }
57   }
58   MAC_MCMD = 0;
59   return (MAC_MRDD);
60 }
61
62
63 // Keil: function added to initialize Rx Descriptors
64 void rx_descr_init (void)
65 {
66   unsigned int i;
67
68   for (i = 0; i < NUM_RX_FRAG; i++) {
69     RX_DESC_PACKET(i)  = RX_BUF(i);
70     RX_DESC_CTRL(i)    = RCTRL_INT | (ETH_FRAG_SIZE-1);
71     RX_STAT_INFO(i)    = 0;
72     RX_STAT_HASHCRC(i) = 0;
73   }
74
75   /* Set EMAC Receive Descriptor Registers. */
76   MAC_RXDESCRIPTOR    = RX_DESC_BASE;
77   MAC_RXSTATUS        = RX_STAT_BASE;
78   MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1;
79
80   /* Rx Descriptors Point to 0 */
81   MAC_RXCONSUMEINDEX  = 0;
82 }
83
84
85 // Keil: function added to initialize Tx Descriptors
86 void tx_descr_init (void) {
87   unsigned int i;
88
89   for (i = 0; i < NUM_TX_FRAG; i++) {
90     TX_DESC_PACKET(i) = TX_BUF(i);
91     TX_DESC_CTRL(i)   = 0;
92     TX_STAT_INFO(i)   = 0;
93   }
94
95   /* Set EMAC Transmit Descriptor Registers. */
96   MAC_TXDESCRIPTOR    = TX_DESC_BASE;
97   MAC_TXSTATUS        = TX_STAT_BASE;
98   MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1;
99
100   /* Tx Descriptors Point to 0 */
101   MAC_TXPRODUCEINDEX  = 0;
102 }
103
104
105 // configure port-pins for use with LAN-controller,
106 // reset it and send the configuration-sequence
107
108 void Init_EMAC(void)
109 {
110 // Keil: function modified to access the EMAC
111 // Initializes the EMAC ethernet controller
112   unsigned int regv,tout,id1,id2;
113
114   /* Power Up the EMAC controller. */
115   PCONP |= 0x40000000;                  // PCENET Enable
116
117   /* Enable P1 Ethernet Pins. */
118   if (MAC_MODULEID == OLD_EMAC_MODULE_ID)
119   {
120     /* For the first silicon rev.'-' ID P1.6 should be set. */
121         //    5    0    1    5    1    1    0    5
122         // 0101 xxxx xx01 0101 xx01 xx01 xxxx 0101
123         // P1[15,14,10,9,8,6,4,1,0]
124     PINSEL2 = 0x50151105;         
125   }
126
127   else
128   {
129     /* on rev. 'A' and later, P1.6 should NOT be set. */
130         //    5    0    1    5    0    1    0    5
131         // 0101 xxxx xx01 0101 xxxx xx01 xxxx 0101
132         // P1[15,14,10,9,8,4,1,0]
133     PINSEL2 = 0x50150105;
134   }
135
136   // Config P1.[17:16] = ENET_MDIO:ENET_MDC
137   PINSEL3 = (PINSEL3 & ~0x0000000F) | 0x00000005;
138
139   /* Reset all EMAC internal modules. */
140   MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
141              MAC1_SIM_RES | MAC1_SOFT_RES;
142   MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;
143
144   /* A short delay after reset. */
145   for (tout = 100; tout; tout--);
146
147   /* Initialize MAC control registers. */
148   MAC_MAC1 = MAC1_PASS_ALL;
149   MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
150   MAC_MAXF = ETH_MAX_FLEN;
151   MAC_CLRT = CLRT_DEF;
152   MAC_IPGR = IPGR_DEF;
153
154   /* Enable Reduced MII interface. */
155   MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM;
156
157   /* Reset Reduced MII Logic. */
158   MAC_SUPP = SUPP_RES_RMII;
159   for (tout = 100; tout; tout--);
160   MAC_SUPP = 0;
161
162   /* Put the DP83848C in reset mode */
163   write_PHY (PHY_REG_BMCR, 0x8000);
164
165   /* Wait for hardware reset to end. */
166   for (tout = 0; tout < 0x100000; tout++) {
167     regv = read_PHY (PHY_REG_BMCR);
168     if (!(regv & 0x8000)) {
169       /* Reset complete */
170       break;
171     }
172   }
173
174   /* Check if this is a DP83848C PHY. */
175   id1 = read_PHY (PHY_REG_IDR1);
176   id2 = read_PHY (PHY_REG_IDR2);
177   if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) {
178     /* Configure the PHY device */
179
180     /* Use autonegotiation about the link speed. */
181     write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG);
182
183     /* Wait to complete Auto_Negotiation. */
184     for (tout = 0; tout < 0x100000; tout++) {
185       regv = read_PHY (PHY_REG_BMSR);
186       if (regv & 0x0020) {
187         /* Autonegotiation Complete. */
188         break;
189       }
190     }
191   }
192
193   /* Check the link status. */
194   for (tout = 0; tout < 0x10000; tout++) {
195     regv = read_PHY (PHY_REG_STS);
196     if (regv & 0x0001) {
197       /* Link is on. */
198       break;
199     }
200   }
201
202   /* Configure Full/Half Duplex mode. */
203   if (regv & 0x0004) {
204     /* Full duplex is enabled. */
205     MAC_MAC2    |= MAC2_FULL_DUP;
206     MAC_COMMAND |= CR_FULL_DUP;
207     MAC_IPGT     = IPGT_FULL_DUP;
208   }
209   else {
210     /* Half duplex mode. */
211     MAC_IPGT = IPGT_HALF_DUP;
212   }
213
214   /* Configure 100MBit/10MBit mode. */
215   if (regv & 0x0002) {
216     /* 10MBit mode. */
217     MAC_SUPP = 0;
218   }
219   else {
220     /* 100MBit mode. */
221     MAC_SUPP = SUPP_SPEED;
222   }
223
224   /* Set the Ethernet MAC Address registers */
225   MAC_SA0 = (MYMAC_1 << 8) | MYMAC_2;
226   MAC_SA1 = (MYMAC_3 << 8) | MYMAC_4;
227   MAC_SA2 = (MYMAC_5 << 8) | MYMAC_6;
228
229   /* Initialize Tx and Rx DMA Descriptors */
230   rx_descr_init ();
231   tx_descr_init ();
232
233   /* Receive Broadcast and Perfect Match Packets */
234   MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN;
235
236   /* Enable EMAC interrupts. */
237   MAC_INTENABLE = INT_RX_DONE | INT_TX_DONE;
238
239   /* Reset all interrupts */
240   MAC_INTCLEAR  = 0xFFFF;
241
242   /* Enable receive and transmit mode of MAC Ethernet core */
243   MAC_COMMAND  |= (CR_RX_EN | CR_TX_EN);
244   MAC_MAC1     |= MAC1_REC_EN;
245 }
246
247
248 // reads a word in little-endian byte order from RX_BUFFER
249
250 unsigned short ReadFrame_EMAC(void)
251 {
252   return (*rptr++);
253 }
254
255 // reads a word in big-endian byte order from RX_FRAME_PORT
256 // (useful to avoid permanent byte-swapping while reading
257 // TCP/IP-data)
258
259 unsigned short ReadFrameBE_EMAC(void)
260 {
261   unsigned short ReturnValue;
262  
263   ReturnValue = SwapBytes (*rptr++);
264   return (ReturnValue);
265 }
266
267
268 // copies bytes from frame port to MCU-memory
269 // NOTES: * an odd number of byte may only be transfered
270 //          if the frame is read to the end!
271 //        * MCU-memory MUST start at word-boundary
272
273 void CopyFromFrame_EMAC(void *Dest, unsigned short Size)
274 {
275   unsigned short * piDest;                       // Keil: Pointer added to correct expression
276
277   piDest = Dest;                                 // Keil: Line added
278   while (Size > 1) {
279     *piDest++ = ReadFrame_EMAC();
280     Size -= 2;
281   }
282  
283   if (Size) {                                         // check for leftover byte...
284     *(unsigned char *)piDest = (char)ReadFrame_EMAC();// the LAN-Controller will return 0
285   }                                                   // for the highbyte
286 }
287
288 // does a dummy read on frame-I/O-port
289 // NOTE: only an even number of bytes is read!
290
291 void DummyReadFrame_EMAC(unsigned short Size)    // discards an EVEN number of bytes
292 {                                                // from RX-fifo
293   while (Size > 1) {
294     ReadFrame_EMAC();
295     Size -= 2;
296   }
297 }
298
299 // Reads the length of the received ethernet frame and checks if the
300 // destination address is a broadcast message or not
301 // returns the frame length
302 unsigned short StartReadFrame(void) {
303   unsigned short RxLen;
304   unsigned int idx;
305
306   idx = MAC_RXCONSUMEINDEX;
307   RxLen = (RX_STAT_INFO(idx) & RINFO_SIZE) - 3;
308   rptr = (unsigned short *)RX_DESC_PACKET(idx);
309   return(RxLen);
310 }
311
312 void EndReadFrame(void) {
313   unsigned int idx;
314
315   /* DMA free packet. */
316   idx = MAC_RXCONSUMEINDEX;
317   if (++idx == NUM_RX_FRAG) idx = 0;
318   MAC_RXCONSUMEINDEX = idx;
319 }
320
321 unsigned int CheckFrameReceived(void) {             // Packet received ?
322   //unsigned int i;
323   // /* A short delay after reset. */
324   //for (i = 10; i; i--);
325   //FIO3CLR = 0x04000000;                                                       // ON LED2      = Status Frame Receive
326
327   if (MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX)     // more packets received ? 
328   return(1);
329
330   else
331   return(0);
332 }
333
334 // requests space in EMAC memory for storing an outgoing frame
335
336 void RequestSend(unsigned short FrameSize)
337 {
338   unsigned int idx;
339
340   idx  = MAC_TXPRODUCEINDEX;
341   tptr = (unsigned short *)TX_DESC_PACKET(idx);
342   TX_DESC_CTRL(idx) = FrameSize | TCTRL_LAST;
343 }
344
345 // check if ethernet controller is ready to accept the
346 // frame we want to send
347
348 unsigned int Rdy4Tx(void)
349 {
350   return (1);   // the ethernet controller transmits much faster
351 }               // than the CPU can load its buffers
352
353
354 // writes a word in little-endian byte order to TX_BUFFER
355 void WriteFrame_EMAC(unsigned short Data)
356 {
357   *tptr++ = Data;
358 }
359
360 // copies bytes from MCU-memory to frame port
361 // NOTES: * an odd number of byte may only be transfered
362 //          if the frame is written to the end!
363 //        * MCU-memory MUST start at word-boundary
364
365 void CopyToFrame_EMAC(void *Source, unsigned int Size)
366 {
367   unsigned short * piSource;
368   unsigned int idx;
369
370   piSource = Source;
371   Size = (Size + 1) & 0xFFFE;    // round Size up to next even number
372   while (Size > 0) {
373     WriteFrame_EMAC(*piSource++);
374     Size -= 2;
375   }
376
377   idx = MAC_TXPRODUCEINDEX;
378   if (++idx == NUM_TX_FRAG) idx = 0;
379   MAC_TXPRODUCEINDEX = idx;
380 }
381
Note: See TracBrowser for help on using the browser.