1 | #include "mac.h"
|
2 |
|
3 | #include "lpc2468.h"
|
4 |
|
5 | #include "ucos_ii.h"
|
6 | #include "os_cpu.h"
|
7 |
|
8 | #include "packet.h"
|
9 |
|
10 |
|
11 | static void mac_init_rx_descriptors(void);
|
12 |
|
13 | static void mac_init_tx_descriptors(void);
|
14 |
|
15 | static void mac_phy_interrupt(void);
|
16 |
|
17 | static void mac_interrupt(void);
|
18 |
|
19 | static void mac_write_phy(INT16U reg, INT16U val);
|
20 |
|
21 | static INT16U mac_read_phy(INT16U reg);
|
22 |
|
23 |
|
24 | EMAC_DMA_RAM ALIGN static char rx_buffer[MAC_RX_FRAGMENTS][ETH_FRAG_SIZE];
|
25 |
|
26 | EMAC_DMA_RAM ALIGN static char tx_buffer[MAC_TX_FRAGMENTS][ETH_FRAG_SIZE];
|
27 |
|
28 | OS_EVENT *tx_pkt_cnt;
|
29 |
|
30 | EMAC_DMA_RAM static rx_tx_descriptor rx_desc[MAC_RX_FRAGMENTS];
|
31 |
|
32 | EMAC_DMA_RAM static tstRxStatusDescriptor rx_status_desc[MAC_RX_FRAGMENTS];
|
33 |
|
34 | EMAC_DMA_RAM static rx_tx_descriptor tx_desc[MAC_TX_FRAGMENTS];
|
35 |
|
36 | EMAC_DMA_RAM static INT32U tx_status_desc[MAC_TX_FRAGMENTS];
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | void mac_init(void)
|
42 | {
|
43 | INT32U dwID;
|
44 |
|
45 | tx_pkt_cnt = OSSemCreate(1);
|
46 |
|
47 | AHBCFG2 |= (BIT_17 | BIT_12);
|
48 |
|
49 | PCONP |= BIT_30; /* power up the mac */
|
50 | PINSEL2 |= (BIT_00 | BIT_02 | BIT_08 | /* select the rmii pins */
|
51 | BIT_16 | BIT_18 | BIT_20 | BIT_28 | BIT_30);
|
52 | PINSEL3 |= (BIT_00 | BIT_02); /* select the mdio and clk pins */
|
53 | MAC1 = (BIT_08 | BIT_09 | BIT_10 | BIT_11 | BIT_14 | BIT_15); /* reset mac */
|
54 | Command = (BIT_03 | BIT_04 | BIT_05); /* reset the mac */
|
55 | MAC1 = 0; /* deassert the soft resets */
|
56 | MAC2 = (BIT_04 | BIT_05); /* enable crc and padding */
|
57 | IPGR = IPGR_DEFAULT; /* set the back-to-back inter packet gap */
|
58 | CLRT = CLRT_DEFAULT; /* set the collision window and retransmission count */
|
59 | MAXF = MAX_FRAME; /* maximum frame length */
|
60 | MCFG = (BIT_02 | BIT_04 | BIT_15); /* divide host clk by 20 and reset mii */
|
61 | MCFG ^= BIT_15; /* deassert the reset from the mii hardware */
|
62 | MCMD = 0;
|
63 | Command = (BIT_09 | BIT_06); /* enable the rmii and pass runt frames */
|
64 | SUPP = BIT_08; /* enable 100MBit mode */
|
65 | mac_write_phy(PHY_BCR, BIT_15); /* reset the phy */
|
66 | while(mac_read_phy(PHY_BCR) & (BIT_15 | BIT_11)); /* wait until reset done */
|
67 | dwID = (mac_read_phy(PHY_ID1) << 16); /* get PHY manufacturer and revision */
|
68 | dwID |= (mac_read_phy(PHY_ID2) & 0xFFF0);
|
69 | if(dwID != KSZ8001_ID) /* check if this is a KSZ8001L PHY */
|
70 | {
|
71 | return; /* abort if it's not */
|
72 | }
|
73 | mac_write_phy(PHY_ICS, BIT_08 | BIT_10); /* enable link interrupt */
|
74 | mac_write_phy(PHY_CTL, BIT_14); /* enable the link and act LEDs */
|
75 | mac_write_phy(PHY_BCR, BIT_12 | BIT_09); /* enable & start autonegotiation*/
|
76 | PINSEL4 |= BIT_22; /* enable EINT1 interrupt */
|
77 |
|
78 | VICVectPriority15 = 0; /* set up the phy interrupt */
|
79 | VICVectAddr15 = (INT32U)mac_phy_interrupt;
|
80 | VICIntEnable |= BIT_15; /* enable the link up/down interrupt */
|
81 |
|
82 | SA0 = (MAC_ADDRESS1 << 8) | MAC_ADDRESS2; /* set up the station address */
|
83 | SA1 = (MAC_ADDRESS3 << 8) | MAC_ADDRESS4;
|
84 | SA2 = (MAC_ADDRESS5 << 8) | MAC_ADDRESS6;
|
85 | RxFilterCtrl = (BIT_02 | BIT_05); /* allow broadcast and perfect */
|
86 |
|
87 | mac_init_rx_descriptors(); /* initialize rx descriptor table */
|
88 | mac_init_tx_descriptors(); /* initialize tx descriptor table */
|
89 |
|
90 | VICVectPriority21 = 0; /* set up the mac interrupt */
|
91 | VICVectAddr21 = (INT32U)mac_interrupt;
|
92 | VICIntEnable |= BIT_21; /* enable the mac interrupt */
|
93 | IntClear = 0xFFFFFFFF;
|
94 | IntEnable = BIT_03 | BIT_07;
|
95 |
|
96 | return;
|
97 | }
|
98 |
|
99 | void mac_tx_enable(void)
|
100 | {
|
101 | Command |= BIT_01;
|
102 | }
|
103 |
|
104 | void mac_tx_disable(void)
|
105 | {
|
106 | Command &= ~BIT_01;
|
107 | }
|
108 |
|
109 | void mac_rx_enable(void)
|
110 | {
|
111 | Command |= BIT_00;
|
112 | MAC1 |=BIT_00;
|
113 | }
|
114 |
|
115 | void mac_rx_disable(void)
|
116 | {
|
117 | Command &= ~BIT_00;
|
118 | MAC1 &= ~BIT_00;
|
119 | }
|
120 |
|
121 | char* mac_new_packet(void)
|
122 | {
|
123 | INT8U err;
|
124 | INT16U idx;
|
125 | OSSemPend(tx_pkt_cnt, 0, &err); /* wait until memory is available */
|
126 | idx = TxProduceIndex;
|
127 | return tx_desc[idx].packet;
|
128 | }
|
129 |
|
130 |
|
131 | void mac_send_packet(INT16U size)
|
132 | {
|
133 | INT16U idx = TxProduceIndex;
|
134 | tx_desc[idx].control = (BIT_31 | BIT_30 | (size - 1));
|
135 | idx++;
|
136 | if(idx == MAC_TX_FRAGMENTS)
|
137 | {
|
138 | idx = 0;
|
139 | }
|
140 | TxProduceIndex = idx;
|
141 | }
|
142 |
|
143 |
|
144 | static void mac_init_rx_descriptors(void)
|
145 | {
|
146 | INT16U idx;
|
147 | for(idx = 0; idx < MAC_RX_FRAGMENTS; idx++) /* loop for each element */
|
148 | {
|
149 | rx_desc[idx].packet = &rx_buffer[idx][0]; /* set the buffer pointer */
|
150 | rx_desc[idx].control = (BIT_31 | (ETH_FRAG_SIZE - 1)); /* enable rx int */
|
151 | rx_status_desc[idx].status = 0; /* zero-out the status and hash fields */
|
152 | rx_status_desc[idx].hash = 0;
|
153 | }
|
154 | RxDescriptor = (INT32U)rx_desc; /* rx descriptor base */
|
155 | RxStatus = (INT32U)rx_status_desc; /* status descriptor base */
|
156 | RxDescriptorNumber = MAC_RX_FRAGMENTS - 1; /* number of rx descriptors */
|
157 | RxConsumeIndex = 0; /* begin at the first rx descriptor */
|
158 | }
|
159 |
|
160 |
|
161 | static void mac_init_tx_descriptors(void)
|
162 | {
|
163 | INT16U idx;
|
164 | for(idx = 0; idx < MAC_TX_FRAGMENTS; idx++)
|
165 | {
|
166 | tx_desc[idx].packet = &tx_buffer[idx][0];
|
167 | tx_desc[idx].control = 0;
|
168 | }
|
169 | TxDescriptor = (INT32U)tx_desc;
|
170 | TxStatus = (INT32U)tx_status_desc;
|
171 | TxDescriptorNumber = MAC_TX_FRAGMENTS - 1; /* number of tx descriptors */
|
172 | TxProduceIndex = 0; /* begin at the first tx descriptor */
|
173 | } /* end mac_init_tx_descriptors */
|
174 |
|
175 |
|
176 | /* the phy calls this via external interrupt 1 every time a cable is plugged in or out. */
|
177 | static void mac_phy_interrupt(void)
|
178 | {
|
179 | INT16U interrupt = mac_read_phy(PHY_ICS); /* get the interrupt source */
|
180 | if(interrupt & BIT_00)
|
181 | {
|
182 | INT16U mode = (mac_read_phy(PHY_100BTX) & (BIT_04 | BIT_03 | BIT_02));
|
183 | switch(mode)
|
184 | {
|
185 | case MODE_10M_HALF_DUPLEX:
|
186 | {
|
187 | MAC2 = (BIT_04 | BIT_05 | BIT_07); /* crc, padding, half duplex */
|
188 | SUPP = 0; /* 10MBit mode */
|
189 | Command &= ~BIT_10; /* issue half duplex command */
|
190 | IPGT = 0x12; /* default setting for 10 MBits, half duplex */
|
191 | break;
|
192 | }
|
193 | case MODE_10M_FULL_DUPLEX:
|
194 | {
|
195 | MAC2 = (BIT_00 | BIT_04 | BIT_05 | BIT_07); /* crc, padding, full duplex */
|
196 | SUPP = 0; /* 10MBit mode */
|
197 | Command |= BIT_10; /* issue full-duplex command */
|
198 | IPGT = 0x15; /* default setting for 10 MBits, full duplex */
|
199 | break;
|
200 | }
|
201 | case MODE_100M_HALF_DUPLEX:
|
202 | {
|
203 | MAC2 = (BIT_04 | BIT_05 | BIT_07); /* crc, padding, half duplex */
|
204 | SUPP = BIT_08; /* enable 100MBit mode */
|
205 | Command &= ~BIT_10; /* issue half-duplex command */
|
206 | IPGT = 0x12; /* default setting for 100 MBits, half duplex */
|
207 | break;
|
208 | }
|
209 | case MODE_100M_FULL_DUPLEX:
|
210 | {
|
211 | MAC2 = (BIT_00 | BIT_04 | BIT_05 | BIT_07); /* crc, padding, full duplex */
|
212 | SUPP = BIT_08; /* enable 100MBit mode */
|
213 | Command |= BIT_10; /* issue full-duplex command */
|
214 | IPGT = 0x15; /* default setting for 100 MBits, full duplex */
|
215 | break;
|
216 | }
|
217 | }
|
218 | mac_rx_enable(); /* enable the receiver */
|
219 | mac_tx_enable(); /* enable the transmitter */
|
220 | }
|
221 | else if(interrupt & BIT_02)
|
222 | {
|
223 | mac_rx_disable(); /* disable the receiver */
|
224 | mac_tx_disable(); /* disable the transmitter */
|
225 | }
|
226 | EXTINT |= BIT_01;
|
227 | }
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | static void mac_interrupt(void)
|
234 | {
|
235 | INT32U int_status = IntStatus; /* get the interrupt source */
|
236 | IntClear = int_status; /* acknowledge interrupt */
|
237 | int_status &= IntEnable; /* mask out unwanted irq's */
|
238 | if(int_status)
|
239 | {
|
240 | if(int_status & BIT_00) /* rx overrun */
|
241 | {
|
242 | Command |= BIT_05; /* rx reset */
|
243 | }
|
244 | if(int_status & BIT_01) /* rx error */
|
245 | {
|
246 | }
|
247 | if(int_status & BIT_02) /* rx finished */
|
248 | {
|
249 | }
|
250 | if(int_status & BIT_03) /* rx done */
|
251 | {
|
252 |
|
253 |
|
254 | /* HIER STÜRZT DER KRAM AB */
|
255 |
|
256 | /*INT16U idx = RxConsumeIndex;
|
257 | packet_add(rx_desc[idx].packet, (rx_status_desc[idx].status & 0x7FF));
|
258 | idx++;
|
259 | if(idx == MAC_RX_FRAGMENTS)
|
260 | {
|
261 | idx = 0;
|
262 | }
|
263 | RxConsumeIndex = idx;*/
|
264 | }
|
265 | if(int_status & BIT_04) /* tx underrun */
|
266 | {
|
267 | Command |= BIT_04; /* tx reset */
|
268 | }
|
269 | if(int_status & BIT_05) /* tx error */
|
270 | {
|
271 | }
|
272 | if(int_status & BIT_06) /* tx finished */
|
273 | {
|
274 | }
|
275 | if(int_status & BIT_07) /* tx done */
|
276 | {
|
277 | OSSemPost(tx_pkt_cnt); /* increase the number of available tx buffers */
|
278 | }
|
279 | if(int_status & BIT_12) /* software interrupt */
|
280 | {
|
281 | }
|
282 | if(int_status & BIT_13) /* wakeup */
|
283 | {
|
284 | }
|
285 | }
|
286 | }
|
287 |
|
288 | static void mac_write_phy(INT16U reg, INT16U val)
|
289 | {
|
290 | MADR = (reg & 0x1F); /* the register address. only bits 0..5 are valid. */
|
291 | MWTD = val; /* write data */
|
292 | while(MIND & BIT_00); /* wait until write cycle is complete */
|
293 | }
|
294 |
|
295 | static INT16U mac_read_phy(INT16U reg)
|
296 | {
|
297 | MADR = (reg & 0x1F); /* the register address. only bits 0..5 are valid. */
|
298 | MCMD = BIT_00; /* issue a read command */
|
299 | while(MIND & BIT_00); /* wait until read operation is complete */
|
300 | MCMD = 0;
|
301 | return MRDD;
|
302 | }
|