[14782ec0] | 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 |
---|