1 | #include <stdint.h> |
---|
2 | #include <stddef.h> |
---|
3 | |
---|
4 | #include <fec.h> |
---|
5 | #include <lwip/pbuf.h> |
---|
6 | #include <netif/etharp.h> |
---|
7 | |
---|
8 | #include <rtems.h> |
---|
9 | #include <bsp.h> |
---|
10 | |
---|
11 | #if LWIP_NETIF_STATUS_CALLBACK |
---|
12 | static void mcf5225xif_status(struct netif*); |
---|
13 | #endif |
---|
14 | |
---|
15 | |
---|
16 | #if LWIP_NETIF_LINK_CALLBACK |
---|
17 | static void mcf5225xif_link(struct netif*); |
---|
18 | #endif |
---|
19 | |
---|
20 | static u8_t __attribute__((aligned (16))) rx_buf[MAX_FRAME_LEN]; |
---|
21 | static u8_t __attribute__((aligned (16))) tx_buf[MAX_FRAME_LEN]; |
---|
22 | |
---|
23 | struct __attribute__((aligned(16))) rx_desc { |
---|
24 | u16_t ctl; |
---|
25 | u16_t len; |
---|
26 | u8_t* ptr; |
---|
27 | } rx_bd = { MCF_FEC_RXBD_E | MCF_FEC_RXBD_W ,0,rx_buf}; |
---|
28 | |
---|
29 | struct tx_desc { |
---|
30 | u16_t ctl; |
---|
31 | u16_t len; |
---|
32 | u8_t* buf; |
---|
33 | } tx_bd[2] ={{MCF_FEC_TXBD_R | MCF_FEC_TXBD_L | MCF_FEC_TXBD_TC ,0,tx_buf},{MCF_FEC_TXBD_L | MCF_FEC_TXBD_TC | MCF_FEC_TXBD_W ,0,tx_buf}}; |
---|
34 | |
---|
35 | static rtems_id net_task_id; |
---|
36 | |
---|
37 | rtems_isr rx_frame_handler(rtems_vector_number vector) |
---|
38 | { |
---|
39 | MCF_INTC0_IMRL |= MCF_INTC_IMRL_MASK27; /* disable FEC RX_INTF interrupt */ |
---|
40 | MCF_FEC_EIR |= MCF_FEC_EIR_RXF; /* clear pending interrupt event */ |
---|
41 | |
---|
42 | rtems_event_send(net_task_id,RTEMS_EVENT_0); |
---|
43 | |
---|
44 | MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASK27; /* enable FEC RX_INTF interrupt */ |
---|
45 | } |
---|
46 | |
---|
47 | void handle_rx_frame(struct netif* netif) |
---|
48 | { |
---|
49 | /* Scan the Rx buffer rescriptor ring */ |
---|
50 | if (rx_bd.ctl & (MCF_FEC_RXBD_RO1 | MCF_FEC_RXBD_E | MCF_FEC_RXBD_TR)) rx_bd.ctl = MCF_FEC_RXBD_E | MCF_FEC_RXBD_W; /* 1: receive process pending, pbuf still allocated, 2: Buffer empty, quit, 3: frame too long */ |
---|
51 | else if (rx_bd.ctl & MCF_FEC_RXBD_L) { /* Last buffer in frame, finalize */ |
---|
52 | if (rx_bd.ctl & (MCF_FEC_RXBD_LG | MCF_FEC_RXBD_NO | MCF_FEC_RXBD_CR | MCF_FEC_RXBD_OV)) rx_bd.ctl = MCF_FEC_RXBD_E | MCF_FEC_RXBD_W; /* Reception error */ |
---|
53 | else { //pass_frame_to_upper_layer(&rx_bd); |
---|
54 | register struct pbuf* lwip_buf=pbuf_alloc(PBUF_RAW,rx_bd.len,PBUF_RAM); |
---|
55 | |
---|
56 | if (lwip_buf) { |
---|
57 | memcpy(lwip_buf->payload,rx_bd.ptr,lwip_buf->tot_len); |
---|
58 | switch (htons(((struct eth_hdr *)lwip_buf->payload)->type)) { |
---|
59 | /* IP or ARP packet? */ |
---|
60 | case ETHTYPE_IP: |
---|
61 | /* full packet send to tcpip_thread to process */ |
---|
62 | /* skip Ethernet header */ |
---|
63 | if (netif->input(lwip_buf, netif) != ERR_OK) pbuf_free(lwip_buf); |
---|
64 | break; |
---|
65 | case ETHTYPE_ARP: |
---|
66 | /* pass p to ARP module */ |
---|
67 | etharp_arp_input(netif, (struct eth_addr *)&netif->hwaddr, lwip_buf); |
---|
68 | break; |
---|
69 | default: |
---|
70 | pbuf_free(lwip_buf); |
---|
71 | break; |
---|
72 | } |
---|
73 | lwip_buf = NULL; |
---|
74 | rx_bd.ctl = MCF_FEC_RXBD_E | MCF_FEC_RXBD_W; |
---|
75 | } |
---|
76 | } |
---|
77 | } |
---|
78 | MCF_FEC_RDAR=0; |
---|
79 | } |
---|
80 | |
---|
81 | /** |
---|
82 | * This function does the actual transmission of the packet. The packet is |
---|
83 | * contained in the pbuf that is passed to the function. This pbuf |
---|
84 | * might be chained. |
---|
85 | * |
---|
86 | * @param netif the lwip network interface structure for this ethernetif |
---|
87 | * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type) |
---|
88 | * @return ERR_OK if the packet could be sent |
---|
89 | * an err_t value if the packet couldn't be sent |
---|
90 | * |
---|
91 | */ |
---|
92 | static err_t |
---|
93 | low_level_output(struct netif *netif, struct pbuf *p) |
---|
94 | { |
---|
95 | struct pbuf *q; |
---|
96 | u8_t *ptr; |
---|
97 | static u8_t txbd_index; |
---|
98 | |
---|
99 | /* Suppress 'argument not used' warning */ |
---|
100 | netif = netif; |
---|
101 | |
---|
102 | if (p->tot_len > MAX_FRAME_LEN) |
---|
103 | /* Frame too long, drop it */ |
---|
104 | return ERR_MEM; |
---|
105 | |
---|
106 | tx_bd[txbd_index].len = p->tot_len; // < 64 ? p->tot_len+(64-p->tot_len) : p->tot_len; |
---|
107 | |
---|
108 | /* Walk the pbuf chain, fill the Tx packet buffer */ |
---|
109 | q = p; |
---|
110 | ptr=tx_bd[txbd_index].buf; |
---|
111 | while (q != NULL) { |
---|
112 | memcpy(ptr, q->payload, q->len); |
---|
113 | ptr += q->len; |
---|
114 | q = q->next; |
---|
115 | } |
---|
116 | tx_bd[txbd_index].ctl |= MCF_FEC_TXBD_R; |
---|
117 | |
---|
118 | MCF_FEC_TDAR = 0; /* Start transmission */ |
---|
119 | |
---|
120 | while (MCF_FEC_TDAR != 0); /* wait for transmission complete */ |
---|
121 | |
---|
122 | MCF_FEC_EIR |= MCF_FEC_EIR_TXF | MCF_FEC_EIR_TXB; |
---|
123 | |
---|
124 | /* JUST debugging stuff */ |
---|
125 | //~ unsigned int my_q_len=0; |
---|
126 | //~ while (my_q_len<tx_bd[txbd_index].len) |
---|
127 | //~ printf("%02x ",tx_bd[txbd_index].buf[my_q_len++]); |
---|
128 | |
---|
129 | //~ printf("buf.len: %d, buf.ctl: 0x%x, tx_bd.buf: 0x%x\n",tx_bd[txbd_index].len,tx_bd[txbd_index].ctl,tx_bd[txbd_index].buf); |
---|
130 | |
---|
131 | txbd_index=!txbd_index; |
---|
132 | |
---|
133 | return ERR_OK; |
---|
134 | } |
---|
135 | |
---|
136 | /** |
---|
137 | * Should be called at the beginning of the program to set up the |
---|
138 | * network interface. It does the |
---|
139 | * actual setup of the hardware. |
---|
140 | * |
---|
141 | * This function should be passed as a parameter to netif_add(). |
---|
142 | * |
---|
143 | * @param netif the lwip network interface structure for this ethernetif |
---|
144 | * @return ERR_OK if the interface is initialized |
---|
145 | * We always return ERR_OK |
---|
146 | */ |
---|
147 | err_t |
---|
148 | mcf5225xif_init(struct netif *netif) |
---|
149 | { |
---|
150 | rtems_isr_entry old_isr_handler; |
---|
151 | struct if_config* if_config=netif->state; |
---|
152 | |
---|
153 | net_task_id=if_config->net_task; |
---|
154 | |
---|
155 | /* We directly use etharp_output() here to save a function call. |
---|
156 | * You can instead declare your own function an call etharp_output() |
---|
157 | * from it if you have to do some checks before sending (e.g. if link |
---|
158 | * is available...) */ |
---|
159 | netif->output = etharp_output; |
---|
160 | netif->linkoutput = low_level_output; |
---|
161 | #if LWIP_NETIF_STATUS_CALLBACK |
---|
162 | netif->status_callback = mcf5225xif_status; |
---|
163 | #endif |
---|
164 | #if LWIP_NETIF_LINK_CALLBACK |
---|
165 | netif->link_callback = mcf5225xif_link; |
---|
166 | #endif |
---|
167 | |
---|
168 | netif->name[0]=if_config->name[0]; |
---|
169 | netif->name[1]=if_config->name[1]; |
---|
170 | netif->hwaddr_len = if_config->hwaddr_len; |
---|
171 | memcpy(netif->hwaddr,if_config->hwaddr,ETHARP_HWADDR_LEN); /* set the mac address configured by the application */ |
---|
172 | netif->mtu = if_config->mtu ; /* maximum transfer unit, configured by application */ |
---|
173 | netif->flags = if_config->flags; /* device capabilities, configured by application */ |
---|
174 | |
---|
175 | |
---|
176 | MCF_FEC_ECR |= MCF_FEC_ECR_RESET; |
---|
177 | |
---|
178 | while (MCF_FEC_ECR&MCF_FEC_ECR_RESET) asm("nop"); |
---|
179 | |
---|
180 | if (if_config->phy_init) if_config->phy_init(); /* call application specific optional extern phy initialization function */ |
---|
181 | |
---|
182 | MCF_FEC_EIMR = 0; |
---|
183 | MCF_FEC_EIR= 0xFFFFFFFF; |
---|
184 | |
---|
185 | //~ Set MAC hardware address: |
---|
186 | MCF_FEC_PALR = (u32_t)( (netif->hwaddr[0] << 24) |
---|
187 | | (netif->hwaddr[1] << 16) |
---|
188 | | (netif->hwaddr[2] << 8 ) |
---|
189 | | (netif->hwaddr[3] << 0 ) ); |
---|
190 | MCF_FEC_PAUR = (u32_t)( (netif->hwaddr[4] << 24) |
---|
191 | | (netif->hwaddr[5] << 16) ); |
---|
192 | |
---|
193 | /* Do whatever else is needed to initialize interface. */ |
---|
194 | MCF_FEC_OPD |= MCF_FEC_OPD_PAUSE_DUR(2); /* pause duration: send 2 pause frames */ |
---|
195 | MCF_FEC_IAUR = 0; |
---|
196 | MCF_FEC_IALR = 0; |
---|
197 | MCF_FEC_GAUR = 0; |
---|
198 | MCF_FEC_GALR = 0; |
---|
199 | MCF_FEC_EMRBR = ((MAX_FRAME_LEN+15)&~15); //<<4; //RX_RING_SIZE*PBUF_POOL_BUFSIZE; //1536; |
---|
200 | MCF_FEC_ERDSR = (uint32_t)&rx_bd; |
---|
201 | MCF_FEC_ETDSR = (uint32_t)&tx_bd; |
---|
202 | MCF_FEC_RCR = (MAX_FRAME_LEN << 16) | MCF_FEC_RCR_MII_MODE; |
---|
203 | MCF_FEC_FRSR = 0x48<<2; /* avoid address clashing of receive and transmit data in FEC fifo */ |
---|
204 | |
---|
205 | MCF_FEC_TCR = MCF_FEC_TCR_FDEN | MCF_FEC_TCR_HBC; |
---|
206 | |
---|
207 | MCF_FEC_MIBC = MCF_FEC_MIBC_MIB_DISABLE; |
---|
208 | /* TODO: clear MIB RAM??? */ |
---|
209 | MCF_FEC_MIBC =~MCF_FEC_MIBC_MIB_DISABLE; /* enable MIBC */ |
---|
210 | |
---|
211 | MCF_FEC_EIMR = 0; |
---|
212 | |
---|
213 | rtems_interrupt_catch(rx_frame_handler,91,&old_isr_handler); /* register ISR for RX_INTF interrupt*/ |
---|
214 | MCF_INTC0_ICR27=0x10; /* set interrupt level */ |
---|
215 | MCF_FEC_EIR= 0xFFFFFFFF; /* clear all pending interrupts */ |
---|
216 | MCF_FEC_EIMR |= MCF_FEC_EIR_RXF; /* enable RX_INTF interrupt */ |
---|
217 | MCF_INTC0_IMRL &= ~MCF_INTC_IMRL_MASK27; /* enable FEC RX_INTF interrupt */ |
---|
218 | |
---|
219 | /* enable FEC */ |
---|
220 | MCF_FEC_ECR |= MCF_FEC_ECR_ETHER_EN; |
---|
221 | /* Start reception, if it's not started already */ |
---|
222 | MCF_FEC_RDAR = 0; |
---|
223 | |
---|
224 | return ERR_OK; |
---|
225 | } |
---|
226 | |
---|
227 | void smi_init(u32_t clk_speed) |
---|
228 | { |
---|
229 | MCF_FEC_MSCR = MSCR_MII_SPEED(clk_speed); |
---|
230 | } |
---|
231 | |
---|
232 | void smi_write(u8_t phy_addr,u8_t reg_addr,u16_t data) |
---|
233 | { |
---|
234 | MCF_FEC_MMFR = MCF_FEC_MMFR_ST(0x1) | MCF_FEC_MMFR_OP_WRITE | (MCF_FEC_MMFR_PA(phy_addr)) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10 | data; |
---|
235 | smi_init(bsp_get_CPU_clock_speed()); /* enable MII clock speed after MMFR is written */ |
---|
236 | while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) { asm("nop"); } |
---|
237 | smi_init(0); /* MII frame sent, disable clock until next operation */ |
---|
238 | MCF_FEC_EIR |= MCF_FEC_EIR_MII; |
---|
239 | } |
---|
240 | |
---|
241 | u16_t smi_read(u8_t phy_addr,u8_t reg_addr) |
---|
242 | { |
---|
243 | MCF_FEC_MMFR = MCF_FEC_MMFR_ST(0x1) | MCF_FEC_MMFR_OP_READ | (MCF_FEC_MMFR_PA(phy_addr)) | MCF_FEC_MMFR_RA(reg_addr) | MCF_FEC_MMFR_TA_10; |
---|
244 | smi_init(bsp_get_CPU_clock_speed()); /* enable MII clock speed after MMFR is written */ |
---|
245 | while ((MCF_FEC_EIR & MCF_FEC_EIR_MII) == 0) { asm("nop"); } |
---|
246 | smi_init(0); /* MII frame sent, disable clock until next operation */ |
---|
247 | MCF_FEC_EIR |= MCF_FEC_EIR_MII; |
---|
248 | |
---|
249 | return MCF_FEC_MMFR&0xFFFF; |
---|
250 | } |
---|
251 | |
---|
252 | #if LWIP_NETIF_STATUS_CALLBACK |
---|
253 | static void |
---|
254 | mcf5225xif_status(struct netif* netif) |
---|
255 | { |
---|
256 | |
---|
257 | return; |
---|
258 | } |
---|
259 | #endif |
---|
260 | |
---|
261 | #if LWIP_NETIF_LINK_CALLBACK |
---|
262 | static void |
---|
263 | mcf5225xif_link(struct netif* net_if) |
---|
264 | { |
---|
265 | u16_t phy_status=smi_read(1,1); /* get phy status */ |
---|
266 | |
---|
267 | printf("received status: 0x%x\n",phy_status); |
---|
268 | |
---|
269 | if (!(phy_status&0x4)) |
---|
270 | phy_status=smi_read(1,1); |
---|
271 | |
---|
272 | printf("received status: 0x%x\n",phy_status); |
---|
273 | |
---|
274 | if (phy_status&0x4) |
---|
275 | MCF_GPIO_PORTTC |= MCF_GPIO_PORTTC_PORTTC1; |
---|
276 | else |
---|
277 | MCF_GPIO_PORTTC &=~MCF_GPIO_PORTTC_PORTTC1; |
---|
278 | } |
---|
279 | #endif |
---|