193 lines
5.9 KiB
C
193 lines
5.9 KiB
C
|
#include "lwip/opt.h"
|
||
|
#include "lwip/tcpip.h"
|
||
|
#include "netif/etharp.h"
|
||
|
#include "mbed_interface.h"
|
||
|
#include "ethernet_api.h"
|
||
|
#include "ethernetext_api.h"
|
||
|
|
||
|
#define RECV_TASK_PRI (osPriorityNormal)
|
||
|
#define PHY_TASK_PRI (osPriorityNormal)
|
||
|
#define PHY_TASK_WAIT (200)
|
||
|
|
||
|
/* memory */
|
||
|
static sys_sem_t recv_ready_sem; /* receive ready semaphore */
|
||
|
|
||
|
/* function */
|
||
|
static void rza1_recv_task(void *arg);
|
||
|
static void rza1_phy_task(void *arg);
|
||
|
static err_t rza1_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr);
|
||
|
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p);
|
||
|
static void rza1_recv_callback(void);
|
||
|
|
||
|
static void rza1_recv_task(void *arg) {
|
||
|
struct netif *netif = (struct netif*)arg;
|
||
|
struct eth_hdr *ethhdr;
|
||
|
u16_t recv_size;
|
||
|
struct pbuf *p;
|
||
|
struct pbuf *q;
|
||
|
|
||
|
while (1) {
|
||
|
sys_arch_sem_wait(&recv_ready_sem, 0);
|
||
|
recv_size = ethernet_receive();
|
||
|
if (recv_size != 0) {
|
||
|
p = pbuf_alloc(PBUF_RAW, recv_size, PBUF_POOL);
|
||
|
if (p != NULL) {
|
||
|
for (q = p; q != NULL; q = q->next) {
|
||
|
(void)ethernet_read((char *)q->payload, q->len);
|
||
|
}
|
||
|
ethhdr = p->payload;
|
||
|
switch (htons(ethhdr->type)) {
|
||
|
case ETHTYPE_IP:
|
||
|
case ETHTYPE_ARP:
|
||
|
#if PPPOE_SUPPORT
|
||
|
case ETHTYPE_PPPOEDISC:
|
||
|
case ETHTYPE_PPPOE:
|
||
|
#endif /* PPPOE_SUPPORT */
|
||
|
/* full packet send to tcpip_thread to process */
|
||
|
if (netif->input(p, netif) != ERR_OK) {
|
||
|
/* Free buffer */
|
||
|
pbuf_free(p);
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
/* Return buffer */
|
||
|
pbuf_free(p);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void rza1_phy_task(void *arg) {
|
||
|
struct netif *netif = (struct netif*)arg;
|
||
|
s32_t connect_sts = 0; /* 0: disconnect, 1:connect */
|
||
|
s32_t link_sts;
|
||
|
s32_t link_mode_new = NEGO_FAIL;
|
||
|
s32_t link_mode_old = NEGO_FAIL;
|
||
|
|
||
|
while (1) {
|
||
|
link_sts = ethernet_link();
|
||
|
if (link_sts == 1) {
|
||
|
link_mode_new = ethernetext_chk_link_mode();
|
||
|
if (link_mode_new != link_mode_old) {
|
||
|
if (connect_sts == 1) {
|
||
|
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||
|
}
|
||
|
if (link_mode_new != NEGO_FAIL) {
|
||
|
ethernetext_set_link_mode(link_mode_new);
|
||
|
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_up, (void*) netif, 1);
|
||
|
connect_sts = 1;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
if (connect_sts != 0) {
|
||
|
tcpip_callback_with_block((tcpip_callback_fn)netif_set_link_down, (void*) netif, 1);
|
||
|
link_mode_new = NEGO_FAIL;
|
||
|
connect_sts = 0;
|
||
|
}
|
||
|
}
|
||
|
link_mode_old = link_mode_new;
|
||
|
osDelay(PHY_TASK_WAIT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static err_t rza1_etharp_output(struct netif *netif, struct pbuf *q, ip_addr_t *ipaddr) {
|
||
|
/* Only send packet is link is up */
|
||
|
if (netif->flags & NETIF_FLAG_LINK_UP) {
|
||
|
return etharp_output(netif, q, ipaddr);
|
||
|
}
|
||
|
|
||
|
return ERR_CONN;
|
||
|
}
|
||
|
|
||
|
static err_t rza1_low_level_output(struct netif *netif, struct pbuf *p) {
|
||
|
struct pbuf *q;
|
||
|
s32_t cnt;
|
||
|
err_t err = ERR_MEM;
|
||
|
s32_t write_size = 0;
|
||
|
|
||
|
if ((p->payload != NULL) && (p->len != 0)) {
|
||
|
/* If the first data can't be written, transmit descriptor is full. */
|
||
|
for (cnt = 0; cnt < 100; cnt++) {
|
||
|
write_size = ethernet_write((char *)p->payload, p->len);
|
||
|
if (write_size != 0) {
|
||
|
break;
|
||
|
}
|
||
|
osDelay(1);
|
||
|
}
|
||
|
if (write_size != 0) {
|
||
|
for (q = p->next; q != NULL; q = q->next) {
|
||
|
(void)ethernet_write((char *)q->payload, q->len);
|
||
|
}
|
||
|
if (ethernet_send() == 1) {
|
||
|
err = ERR_OK;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
static void rza1_recv_callback(void) {
|
||
|
sys_sem_signal(&recv_ready_sem);
|
||
|
}
|
||
|
|
||
|
err_t eth_arch_enetif_init(struct netif *netif)
|
||
|
{
|
||
|
ethernet_cfg_t ethcfg;
|
||
|
|
||
|
/* set MAC hardware address */
|
||
|
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
|
||
|
netif->hwaddr[0] = MBED_MAC_ADDR_0;
|
||
|
netif->hwaddr[1] = MBED_MAC_ADDR_1;
|
||
|
netif->hwaddr[2] = MBED_MAC_ADDR_2;
|
||
|
netif->hwaddr[3] = MBED_MAC_ADDR_3;
|
||
|
netif->hwaddr[4] = MBED_MAC_ADDR_4;
|
||
|
netif->hwaddr[5] = MBED_MAC_ADDR_5;
|
||
|
#else
|
||
|
mbed_mac_address((char *)netif->hwaddr);
|
||
|
#endif
|
||
|
netif->hwaddr_len = ETHARP_HWADDR_LEN;
|
||
|
|
||
|
/* maximum transfer unit */
|
||
|
netif->mtu = 1500;
|
||
|
|
||
|
/* device capabilities */
|
||
|
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP;
|
||
|
|
||
|
#if LWIP_NETIF_HOSTNAME
|
||
|
/* Initialize interface hostname */
|
||
|
netif->hostname = "lwiprza1";
|
||
|
#endif /* LWIP_NETIF_HOSTNAME */
|
||
|
|
||
|
netif->name[0] = 'e';
|
||
|
netif->name[1] = 'n';
|
||
|
|
||
|
netif->output = rza1_etharp_output;
|
||
|
netif->linkoutput = rza1_low_level_output;
|
||
|
|
||
|
/* Initialize the hardware */
|
||
|
ethcfg.int_priority = 6;
|
||
|
ethcfg.recv_cb = &rza1_recv_callback;
|
||
|
ethcfg.ether_mac = (char *)netif->hwaddr;
|
||
|
ethernetext_init(ðcfg);
|
||
|
|
||
|
/* semaphore */
|
||
|
sys_sem_new(&recv_ready_sem, 0);
|
||
|
|
||
|
/* task */
|
||
|
sys_thread_new("rza1_recv_task", rza1_recv_task, netif, DEFAULT_THREAD_STACKSIZE, RECV_TASK_PRI);
|
||
|
sys_thread_new("rza1_phy_task", rza1_phy_task, netif, DEFAULT_THREAD_STACKSIZE, PHY_TASK_PRI);
|
||
|
|
||
|
return ERR_OK;
|
||
|
}
|
||
|
|
||
|
void eth_arch_enable_interrupts(void) {
|
||
|
ethernetext_start_stop(1);
|
||
|
}
|
||
|
|
||
|
void eth_arch_disable_interrupts(void) {
|
||
|
ethernetext_start_stop(0);
|
||
|
}
|