1 | /******************************************************************************
|
2 | * Company:
|
3 | *
|
4 | * Project:
|
5 | *
|
6 | * Target:
|
7 | *
|
8 | * Type:
|
9 | *
|
10 | * Description:
|
11 | *
|
12 | * Compiler:
|
13 | *
|
14 | * Filename:
|
15 | *
|
16 | * Version:
|
17 | *
|
18 | * Author:
|
19 | *
|
20 | * Creation-Date: 16.09.2010
|
21 | ******************************************************************************
|
22 | *****************************************************************************/
|
23 |
|
24 | /******************************************************************************
|
25 | * INCLUDE FILES
|
26 | *****************************************************************************/
|
27 |
|
28 | #include "mac.h"
|
29 |
|
30 | /******************************************************************************
|
31 | * PRIVATE FUNCTION PROTOTYPES (STATIC)
|
32 | *****************************************************************************/
|
33 |
|
34 | static void MAC_fInitRxDescriptors(void);
|
35 |
|
36 | static void MAC_fInitTxDescriptors(void);
|
37 |
|
38 | static void MAC_fWritePHY(tWord wReg, tWord wValue);
|
39 |
|
40 | static tWord MAC_fReadPHY(tWord wReg);
|
41 |
|
42 | static void MAC_fLinkInterrupt(void);
|
43 |
|
44 | static void MAC_fEthernetInterrupt(void);
|
45 |
|
46 | /******************************************************************************
|
47 | * PRIVATE VARIABLES
|
48 | *****************************************************************************/
|
49 |
|
50 | #pragma data_alignment = 4
|
51 | static tByte bRxBuffer[MAC_RX_FRAGMENTS * ETH_FRAG_SIZE];
|
52 |
|
53 | #pragma data_alignment = 4
|
54 | static tByte bTxBuffer[MAC_TX_FRAGMENTS * ETH_FRAG_SIZE];
|
55 |
|
56 | /******************************************************************************
|
57 | * OTHER DEFINITIONS
|
58 | *****************************************************************************/
|
59 |
|
60 | /******************************************************************************
|
61 | * MODULE FUNCTIONS (PUBLIC)
|
62 | *****************************************************************************/
|
63 |
|
64 | /*===========================================================================*/
|
65 | tenBool MAC_fInitMAC(void)
|
66 | /*-----------------------------------------------------------------------------
|
67 | Function:
|
68 | basic initialization of the ethernet mac and the phy. this routine
|
69 | will work only with the micrel KSZ8001L phy.
|
70 | in: none
|
71 | out: enTrue if the mac and phy are working, enFalse if there was an error.
|
72 | =============================================================================*/
|
73 | {
|
74 | tDWord dwID;
|
75 | PCONP |= BIT_30; /* power up the mac */
|
76 | PINSEL2 |= (BIT_00 | BIT_02 | BIT_08 | BIT_16 | BIT_18 | BIT_20 |
|
77 | BIT_28 | BIT_30); /* select the rmii pins */
|
78 | PINSEL3 |= (BIT_00 | BIT_02); /* select the mdio and clk pins */
|
79 | MAC1 = (BIT_08 | BIT_09 | BIT_10 | BIT_11 | BIT_14 | BIT_15); /* reset mac */
|
80 | Command = (BIT_03 | BIT_04 | BIT_05); /* reset the mac */
|
81 | MAC1 = BIT_01; /* pass all frames */
|
82 | MAC2 = (BIT_04 | BIT_05 | BIT_07); /* enable crc and padding */
|
83 | MAXF = MAX_FRAME; /* maximum frame length */
|
84 | CLRT = CLRT_DEFAULT; /* set the collision window and retransmission count */
|
85 | IPGR = IPGR_DEFAULT; /* set the back-to-back inter packet gap */
|
86 | MCFG = (BIT_02 | BIT_03 | BIT_04 | BIT_15); /* divide host clk by 20 and reset mii */
|
87 | MCFG ^= BIT_15; /* release the reset from the mii hardware */
|
88 | Command = (BIT_09 | BIT_06 /*| BIT_07*/); /* enable the rmii */
|
89 | SUPP = BIT_08; /* enable 100MBit mode */
|
90 | MAC_fWritePHY(PHY_BCR, BIT_15); /* reset the phy */
|
91 | while(MAC_fReadPHY(PHY_BCR) & (BIT_15 | BIT_11)); /* wait until reset done */
|
92 | MAC_fWritePHY(PHY_CTL, BIT_14); /* enable the link and act LEDs */
|
93 | dwID = (MAC_fReadPHY(PHY_ID1) << 16); /* get PHY manufacturer and revision */
|
94 | dwID |= (MAC_fReadPHY(PHY_ID2) & 0xFFF0);
|
95 | if(dwID != KSZ8001_ID) /* check if this is a KSZ8001L PHY */
|
96 | return enFalse; /* abort */
|
97 | MAC_fWritePHY(PHY_BCR, BIT_12); /* enable auto-negotiation */
|
98 | MAC_fWritePHY(PHY_ICS, BIT_08 | BIT_10); /* enable link up / down interrupt */
|
99 | PINSEL4 |= BIT_22; /* enable EINT1 interrupt */
|
100 | VICVectPriority15 = 0; /* set up the phy interrupt */
|
101 | VICVectAddr15 = (tDWord)MAC_fLinkInterrupt;
|
102 | VICIntEnable |= BIT_15; /* enable the link up/down interrupt */
|
103 | SA0 = (MAC_ADDRESS1 << 8) | MAC_ADDRESS2; /* set up the mac address */
|
104 | SA1 = (MAC_ADDRESS3 << 8) | MAC_ADDRESS4;
|
105 | SA2 = (MAC_ADDRESS5 << 8) | MAC_ADDRESS6;
|
106 | RxFilterCtrl = (/*BIT_01 | BIT_02 |*/ BIT_05); /* uni-, multi- and broadcast */
|
107 | MAC_fInitRxDescriptors(); /* initialize rx descriptors */
|
108 | MAC_fInitTxDescriptors(); /* initialize tx descriptors */
|
109 | Command |= (BIT_00 | BIT_01); /* enable receiver and transmitter */
|
110 | MAC1 |= BIT_00; /* enable the receiver */
|
111 | VICVectPriority21 = 0; /* set up the mac interrupt */
|
112 | VICVectAddr21 = (tDWord)MAC_fEthernetInterrupt;
|
113 | VICIntEnable |= BIT_21;
|
114 | return enTrue; /* finished initialization */
|
115 |
|
116 | // if (regv & 0x0004) {
|
117 | /* 10MBit mode. */
|
118 | // SUPP = 0;
|
119 | // }
|
120 | // else {
|
121 | /* 100MBit mode. */
|
122 | // SUPP = SUPP_SPEED;
|
123 | // }
|
124 |
|
125 | } /* end MAC_fInitMAC */
|
126 |
|
127 | /*============================================================================*/
|
128 | tenBool MAC_fGetLinkStatus(void)
|
129 | /*-----------------------------------------------------------------------------
|
130 | Function:
|
131 | send a packet.
|
132 | in: pData -> pointer to the packet data to be transmitted.
|
133 | dwSize -> size of the packet data.
|
134 | out: enTrue -> packet sent or is being transmitted, enFalse otherwise
|
135 | =============================================================================*/
|
136 | {
|
137 | tWord wStatus = MAC_fReadPHY(PHY_STATUS); /* get the status word */
|
138 | if(wStatus & BIT_02) /* check the link status bit */
|
139 | return enTrue;
|
140 | else
|
141 | return enFalse;
|
142 | } /* end MAC_fGetLinkStatus */
|
143 |
|
144 | /*============================================================================*/
|
145 | tenBool MAC_fSendPacket(tpByte pData, tDWord dwSize)
|
146 | /*-----------------------------------------------------------------------------
|
147 | Function:
|
148 | send a packet.
|
149 | in: pData -> pointer to the packet data to be transmitted.
|
150 | dwSize -> size of the packet data.
|
151 | out: enTrue -> packet sent or is being transmitted, enFalse otherwise
|
152 | =============================================================================*/
|
153 | {
|
154 | tDWord dwTempSize = dwSize;
|
155 | tWord wIdx = TxProduceIndex; /* get the next tx descriptor index */
|
156 | tpByte pTxBuffer = (tpByte)TxPacketDescriptor(wIdx);
|
157 | if(!dwSize)
|
158 | return enFalse;
|
159 | while(dwTempSize)
|
160 | {
|
161 | *pTxBuffer = *pData;
|
162 | pTxBuffer++;
|
163 | pData++;
|
164 | dwTempSize--;
|
165 | }
|
166 | TxControlDescriptor(wIdx) = ((BIT_30 | BIT_29 | BIT_28 | BIT_26) | (dwSize - 1));
|
167 | if(wIdx)
|
168 | wIdx = 0;
|
169 | else
|
170 | wIdx = 1;
|
171 | TxProduceIndex = wIdx;
|
172 | return enTrue;
|
173 | } /* end MAC_fSendPacket */
|
174 |
|
175 | /*============================================================================*/
|
176 | tDWord MAC_fReceivePacket(tpByte pData)
|
177 | /*-----------------------------------------------------------------------------
|
178 | Function:
|
179 | send a packet.
|
180 | in: pData -> pointer to the packet data to be transmitted.
|
181 | dwSize -> size of the packet data.
|
182 | out: enTrue -> packet sent or is being transmitted, enFalse otherwise
|
183 | =============================================================================*/
|
184 | {
|
185 | tDWord dwSize, dwCopySize;
|
186 | tpByte pRxFrameBuffer;
|
187 | tDWord dwIdx = RxConsumeIndex; /* get the index of the next received frame */
|
188 | if(dwIdx == RxProduceIndex) /* check if new data is available */
|
189 | return 0; /* no new frames have been received */
|
190 | dwSize = (RxStatusDescriptor(dwIdx) & 0x7FF) - 3; /* ignore the frame's crc */
|
191 | dwCopySize = dwSize;
|
192 | pRxFrameBuffer = (tpByte)(RxPacketDescriptor(dwIdx));
|
193 | while(dwCopySize--)
|
194 | {
|
195 | *pData = *pRxFrameBuffer;
|
196 | pData++;
|
197 | pRxFrameBuffer++;
|
198 | }
|
199 | dwIdx++;
|
200 | if(dwIdx == MAC_RX_FRAGMENTS)
|
201 | dwIdx = 0;
|
202 | RxConsumeIndex = dwIdx;
|
203 | return dwSize;
|
204 | } /* end MAC_fReceivePacket */
|
205 |
|
206 | /*============================================================================*/
|
207 | tAddress MAC_fCreatePacket(void)
|
208 | /*-----------------------------------------------------------------------------
|
209 | Function:
|
210 | send a packet.
|
211 | in: pData -> pointer to the packet data to be transmitted.
|
212 | dwSize -> size of the packet data.
|
213 | out: enTrue -> packet sent or is being transmitted, enFalse otherwise
|
214 | =============================================================================*/
|
215 | {
|
216 | tWord wIdx = TxProduceIndex;
|
217 | return (tAddress)TxPacketDescriptor(wIdx);;
|
218 | } /* end MAC_fCreatePacket */
|
219 |
|
220 | /******************************************************************************
|
221 | * PRIVATE FUNCTIONS (STATIC)
|
222 | *****************************************************************************/
|
223 |
|
224 | /*============================================================================*/
|
225 | static void MAC_fInitRxDescriptors(void)
|
226 | /*-----------------------------------------------------------------------------
|
227 | Function:
|
228 | initializes the RxDescriptors.
|
229 | in: none
|
230 | out: none
|
231 |
|
232 | sa 10.00
|
233 | =============================================================================*/
|
234 | {
|
235 | tDWord dwIdx;
|
236 | tpDWord pdwRxDesc = (tpDWord)RX_DESC_BASE; /* rx descriptors are in eth ram */
|
237 | RxDescriptor = RX_DESC_BASE;
|
238 | for(dwIdx = 0; dwIdx < MAC_RX_FRAGMENTS; dwIdx++)
|
239 | {
|
240 | *pdwRxDesc = (tDWord)&bRxBuffer[dwIdx * ETH_FRAG_SIZE]; /* packet */
|
241 | pdwRxDesc++;
|
242 | *pdwRxDesc = BIT_31 | (ETH_FRAG_SIZE - 1); /* control */
|
243 | pdwRxDesc++;
|
244 | }
|
245 | RxStatus = (tDWord)pdwRxDesc; /* rx status immediately follows rx desc */
|
246 | RxDescriptorNumber = MAC_RX_FRAGMENTS - 1; /* number of rx descriptors */
|
247 | RxConsumeIndex = 0; /* begin at the first rx descriptor */
|
248 | } /* end MAC_fInitRxDescriptors */
|
249 |
|
250 | /*============================================================================*/
|
251 | static void MAC_fInitTxDescriptors(void)
|
252 | /*-----------------------------------------------------------------------------
|
253 | Function:
|
254 | initializes the TxDescriptors.
|
255 | in: none
|
256 | out: none
|
257 | =============================================================================*/
|
258 | {
|
259 | tDWord dwIdx;
|
260 | tpDWord pdwTxDesc = (tpDWord)TX_DESC_BASE;
|
261 | TxDescriptor = TX_DESC_BASE;
|
262 | for(dwIdx = 0; dwIdx < MAC_TX_FRAGMENTS; dwIdx++)
|
263 | {
|
264 | *pdwTxDesc = (tDWord)&bTxBuffer[dwIdx * ETH_FRAG_SIZE]; /* packet */
|
265 | pdwTxDesc++;
|
266 | *pdwTxDesc = ((BIT_30 | BIT_29 | BIT_28 | BIT_26) | (ETH_FRAG_SIZE - 1)); /* control */
|
267 | pdwTxDesc++;
|
268 | }
|
269 | TxStatus = (tDWord)pdwTxDesc; /* tx status immediately follows tx desc */
|
270 | TxDescriptorNumber = MAC_TX_FRAGMENTS - 1; /* number of tx descriptors */
|
271 | TxProduceIndex = 0; /* begin at the first tx descriptor */
|
272 | } /* end MAC_fInitTxDescriptors */
|
273 |
|
274 | /*============================================================================*/
|
275 | static void MAC_fWritePHY(tWord wReg, tWord wValue)
|
276 | /*-----------------------------------------------------------------------------
|
277 | Function:
|
278 | writes the given value to a specific register in the phy.
|
279 | in: wReg -> register to write to
|
280 | wValue -> value to write
|
281 | out: none
|
282 | =============================================================================*/
|
283 | {
|
284 | MADR = (wReg & 0x1F); /* the register address. only bits 0..5 are valid. */
|
285 | MWTD = wValue; /* write data */
|
286 | while(MIND & BIT_00); /* wait until write cycle is complete */
|
287 | } /* end MAC_fWritePHY */
|
288 |
|
289 | /*============================================================================*/
|
290 | static tWord MAC_fReadPHY(tWord wReg)
|
291 | /*-----------------------------------------------------------------------------
|
292 | Function:
|
293 | read the value from a specific phy register.
|
294 | in: wReg -> register to read
|
295 | out: read data
|
296 | =============================================================================*/
|
297 | {
|
298 | MADR = (wReg & 0x1F); /* the register address. only bits 0..5 are valid. */
|
299 | MCMD = BIT_00; /* issue a read command */
|
300 | while(MIND & BIT_00); /* wait until read operation is complete */
|
301 | MCMD = 0;
|
302 | return MRDD;
|
303 | } /* end MAC_fReadPHY */
|
304 |
|
305 | /*============================================================================*/
|
306 | static void MAC_fLinkInterrupt(void)
|
307 | /*-----------------------------------------------------------------------------
|
308 | Function:
|
309 | called when the link is up or down.
|
310 | in: none
|
311 | out: none
|
312 | =============================================================================*/
|
313 | {
|
314 | tWord wInterrupt = MAC_fReadPHY(PHY_ICS); /* get the interrupt source */
|
315 | if(wInterrupt & BIT_00)
|
316 | {
|
317 | //(*(tpByte)0x81000000) = 0x02; //FIXME
|
318 | if(MAC_fReadPHY(PHY_STATUS) & BIT_02) /* wait until link is up */
|
319 | {
|
320 | if(MAC_fReadPHY(PHY_100BTX) & BIT_04) /* if full duplex is enabled */
|
321 | {
|
322 | MAC2 |= BIT_00; /* put the mac into full-duplex mode */
|
323 | Command |= BIT_10; /* issue full-duplex command */
|
324 | IPGT = 0x15; /* recommended setting; see LPC2468 User's Manual p. 223 */
|
325 | }
|
326 | else
|
327 | {
|
328 | IPGT = 0x12; /* recommended setting; see LPC2468 User's Manual p. 223 */
|
329 | }
|
330 | }
|
331 | }
|
332 | else if(wInterrupt & BIT_02)
|
333 | {
|
334 | //(*(tpByte)0x81000000) = 0x01; //FIXME
|
335 | }
|
336 | EXTINT |= BIT_01;
|
337 | } /* end MAC_fLinkInterrupt */
|
338 |
|
339 | /*============================================================================*/
|
340 | static void MAC_fEthernetInterrupt(void)
|
341 | /*-----------------------------------------------------------------------------
|
342 | Function:
|
343 | called when the mac raises an interrupt.
|
344 | in: none
|
345 | out: none
|
346 | =============================================================================*/
|
347 | {
|
348 | } /* end MAC_fEthernetInterrupt */
|
349 |
|
350 | /******************************************************************************
|
351 | * END OF CODE
|
352 | *****************************************************************************/
|