pktif.c
来自「picoos源码。The RTOS and the TCP/IP stack 」· C语言 代码 · 共 572 行 · 第 1/2 页
C
572 行
* ethernetif_input():
*
* This function should be called when a packet is ready to be read
* from the interface. It uses the function low_level_input() that
* should handle the actual reception of bytes from the network
* interface.
*
*/
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
struct ethernetif *ethernetif;
struct eth_hdr *ethhdr;
struct pbuf *p;
ethernetif = netif->state;
p = low_level_input(netif);
if (p != NULL) {
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
/* changed by DK, 2005-01-22 : */
#ifndef ETHARP_OLDSTYLE
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
posSemaGet(arpsem_g);
etharp_ip_input(netif, p);
posSemaSignal(arpsem_g);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
posSemaGet(arpsem_g);
etharp_arp_input(netif, ethernetif->ethaddr, p);
posSemaSignal(arpsem_g);
break;
default:
pbuf_free(p);
break;
}
#else
/* old code: */
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
posSemaGet(arpsem_g);
etharp_ip_input(netif, p);
posSemaSignal(arpsem_g);
pbuf_header(p, -14);
/* if (ip_lookup(p->payload, netif)) */
netif->input(p, netif);
break;
case ETHTYPE_ARP:
posSemaGet(arpsem_g);
p = etharp_arp_input(netif, ethernetif->ethaddr, p);
posSemaSignal(arpsem_g);
if (p != NULL) {
low_level_output(netif, p);
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
#endif
}
}
/*-----------------------------------------------------------------------------------*/
static void
arp_timer(void *arg)
{
posSemaGet(arpsem_g);
etharp_tmr();
posSemaSignal(arpsem_g);
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*/
/*-----------------------------------------------------------------------------------*/
err_t
ethernetif_init(struct netif *netif)
{
struct ethernetif *ethernetif;
/* IMPORTANT: We are not allowed to use a lwIP sys semaphore here!!! */
arpsem_g = posSemaCreate(1);
LWIP_ASSERT("pktif.c: failed to allocate a semaphore", arpsem_g != NULL);
POS_SETEVENTNAME(arpsem_g, "lwip-pktif-arp");
if (arpsem_g == NULL)
return ERR_MEM;
ethernetif = mem_malloc(sizeof(struct ethernetif));
if (ethernetif == NULL)
return ERR_MEM;
netif->state = ethernetif;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->linkoutput = low_level_output;
netif->output = ethernetif_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST;
netif->hwaddr_len = 6;
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);
low_level_init(netif);
etharp_init();
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
return ERR_OK;
}
/*-----------------------------------------------------------------------------------*/
/*
* pktif_update():
*
* Needs to be called periodically to get new packets. This could
* be done inside a thread.
*/
/*-----------------------------------------------------------------------------------*/
void process_input(void)
{
ethernetif_input(pktif_netif);
}
/*-----------------------------------------------------------------------------------
* Hardware Emulation:
* Interface through simulated hardware registers to the NIC
*---------------------------------------------------------------------------------*/
#ifdef NIC_EMU
#include "pktdrv.h"
#define NICADR_TO_LOCALADR(x) ((void*)(x))
#define DISABLE_INTERRUPTS() singleThreadEnter()
#define ENABLE_INTERRUPTS() singleThreadExit()
static sys_sem_t rxsem_g;
static POSSEMA_t txsem_g;
static POSSEMA_t txsyncsem_g;
void nic_interrupt(void)
{
unsigned long is = PK_READREG(PK_REG_ISTATUS);
if (is & PK_ISTATUS_RX)
{
sys_sem_signal(rxsem_g);
}
if (is & PK_ISTATUS_TX)
{
PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX);
posSemaSignal(txsem_g);
}
}
static int packet_send(void *buffer, int len)
{
unsigned long r;
void *txbuf;
posSemaGet(txsyncsem_g);
/* wait until a buffer is free in the tx fifo */
if ((PK_READREG(PK_REG_FSTATUS) & PK_FSTATUS_TXBFREE) == 0)
{
DISABLE_INTERRUPTS();
while ((PK_READREG(PK_REG_FSTATUS) & PK_FSTATUS_TXBFREE) == 0)
{
PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX | PK_IMASK_TX);
ENABLE_INTERRUPTS();
posSemaGet(txsem_g);
DISABLE_INTERRUPTS();
}
ENABLE_INTERRUPTS();
}
/* copy the packet to the NIC and transmit it */
r = PK_READREG(PK_REG_TXBUF);
txbuf = NICADR_TO_LOCALADR(r);
memcpy(txbuf, buffer, len);
PK_WRITEREG(PK_REG_PSIZE, len);
PK_WRITEREG(PK_REG_NOTIFY, PK_NFLAG_TRANSMITNOW);
posSemaSignal(txsyncsem_g);
return 0;
}
static void nic_thread(void *arg)
{
struct netif *netif = (struct netif*) arg;
unsigned long r, fs, rxlen;
void *rxbuf;
err_t rc;
u8_t temp[4];
/* read MAC address from nic */
*((u32_t*)temp) = PK_READREG(PK_REG_MACHI);
ethaddr[0] = temp[0];
ethaddr[1] = temp[1];
*((u32_t*)temp) = PK_READREG(PK_REG_MACLO);
ethaddr[2] = temp[0];
ethaddr[3] = temp[1];
ethaddr[4] = temp[2];
ethaddr[5] = temp[3];
/* Note: We generally use pico]OS semaphores. Exceptions are the
semaphores, that are used in lwip threads that are doing
timeouts. In our case, that is only the nic-thread that
needs to pend on a lwip semaphore. */
rxsem_g = sys_sem_new(1);
LWIP_ASSERT("pktif.c: failed to allocate a semaphore", rxsem_g != NULL);
txsem_g = posSemaCreate(0);
LWIP_ASSERT("pktif.c: failed to allocate a semaphore", txsem_g != NULL);
POS_SETEVENTNAME(txsem_g, "lwip-pktif-tx1");
txsyncsem_g = posSemaCreate(1);
LWIP_ASSERT("pktif.c: failed to allocate a semaphore", txsyncsem_g != NULL);
POS_SETEVENTNAME(txsyncsem_g, "lwip-pktif-tx2");
rc = ethernetif_init(netif);
LWIP_ASSERT("pktif.c: ethernetif_init() failed", rc == ERR_OK);
/* enable interrupts */
(void) PK_READREG(PK_REG_ISTATUS);
PK_WRITEREG(PK_REG_IMASK, PK_IMASK_RX);
/* receiver loop */
for(;;)
{
/* wait for next packet */
sys_sem_wait(rxsem_g);
/* poll the receiver FIFO */
fs = PK_READREG(PK_REG_FSTATUS);
while (fs & PK_FSTATUS_RECEIVED)
{
r = PK_READREG(PK_REG_RXBUF);
rxbuf = NICADR_TO_LOCALADR(r);
rxlen = PK_READREG(PK_REG_PSIZE);
cur_packet = (unsigned char*) rxbuf;
cur_length = (unsigned int) rxlen;
ethernetif_input(netif);
PK_WRITEREG(PK_REG_NOTIFY, PK_NFLAG_RECEIVENEXT);
fs = PK_READREG(PK_REG_FSTATUS);
}
}
}
err_t
pktif_init(struct netif *netif)
{
sys_thread_t th;
th = sys_thread_new(nic_thread, netif, TCPIP_THREAD_PRIO + 1);
return (th == NULL) ? ERR_IF : ERR_OK;
}
#endif /* NIC_EMU */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?