source: rtems/c/src/lib/libcpu/m68k/mcf5225x/network/fec.c @ 14782ec0

4.104.115
Last change on this file since 14782ec0 was 14782ec0, checked in by Joel Sherrill <joel.sherrill@…>, on Apr 5, 2010 at 5:11:48 PM

2010-04-05 Thomas Znidar <t.znidar@…>

  • Makefile.am, configure.ac, preinstall.am: Add mcf5225x support.
  • mcf5225x/include/fec.h, mcf5225x/include/mcf5225x.h, mcf5225x/network/fec.c: New files.
  • Property mode set to 100644
File size: 8.7 KB
Line 
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
12static void mcf5225xif_status(struct netif*);
13#endif
14
15
16#if LWIP_NETIF_LINK_CALLBACK
17static void mcf5225xif_link(struct netif*);
18#endif
19
20static u8_t __attribute__((aligned (16))) rx_buf[MAX_FRAME_LEN];
21static u8_t __attribute__((aligned (16))) tx_buf[MAX_FRAME_LEN];
22
23struct __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
29struct 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
35static rtems_id net_task_id;
36
37rtems_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
47void 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 */
92static err_t
93low_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 */
147err_t
148mcf5225xif_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
227void smi_init(u32_t clk_speed)
228{
229        MCF_FEC_MSCR = MSCR_MII_SPEED(clk_speed);
230}
231
232void 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
241u16_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
253static void
254mcf5225xif_status(struct netif* netif)
255{
256       
257  return;
258}
259#endif
260
261#if LWIP_NETIF_LINK_CALLBACK
262static void
263mcf5225xif_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
Note: See TracBrowser for help on using the repository browser.