📄 nifce_driver.c
字号:
}
// No need of data maipulation as we are directly getting from pbufs.
if (Trace_Function) Trace_Function('T',p->tot_len,((unsigned char *)p->payload)+2);
// see whether we've got a free transmit buffer
old_level = sys_arch_protect();
tx = (ADI_ETHER_BUFFER*)nip->x;
if (tx == NULL)
{
#ifdef LINK_STATS
lwip_stats.link.memerr++;
#endif
sys_arch_unprotect(old_level);
return ERR_MEM;
}
// remove first free one from the list
nip->x = tx->pNext;
tx->pNext = NULL;
// copy data from pbuf(s) into our buffer
q = p;
//data = (char*)tx->Data;
//
// first two bytes reserved for length
data = (char*)tx->Data+2;
// ... first pbuf: skip field unused1 in struct eth_hdr
memcpy(data, ((u8_t*)q->payload) + 2, q->len - 2);
data += (q->len - 2);
len = q->len - 2;
q = q->next;
// copy any subsequent pbufs
while (q) {
memcpy(data, q->payload, q->len);
data += q->len;
len += q->len;
q = q->next;
}
LWIP_ASSERT("low_level_output: data length correct", len == (p->tot_len - 2));
//tx->ElementCount = p->tot_len - 2;
tx->ElementCount = p->tot_len; // total element count including 2 byte header
// see whether we need to shuffle etharp frame up to account for
// the alignment fields unused2 and unused3
//ethhdr = (struct hw_eth_hdr*)tx->Data;
//
ethhdr = (struct hw_eth_hdr*)((char*)tx->Data+2);//skip the header
if (htons(ethhdr->type) == ETHTYPE_ARP)
{
u8_t* pdst = (u8_t*)tx->Data + 28 +2;
u8_t* psrc = pdst + 2; // skip unused2 field
memmove(pdst, psrc, 10);
pdst += 10;
psrc += 12; // skip unused3 field
memmove(pdst, psrc, 4);
//tx->num_elements -= 4;
tx->ElementCount -= 4;
}
ps = (unsigned short*)tx->Data;
*ps = tx->ElementCount-2; // only the frame size excluding 2 byte header
tx->PayLoad = 0; // payload is part of the packet
tx->StatusWord = 0; // changes from 0 to the status info
// give it to the physical driver
adi_dev_Write(nip->handle,ADI_DEV_1D,(ADI_DEV_BUFFER*)tx);
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif
sys_arch_unprotect(old_level);
return ERR_OK;
}
/*##########################################################################
*
* Called by the TCP/IP stack when an IP packet should be sent.
* It calls the function called low_level_output() to actually transmit the
* packet.
*#########################################################################*/
static err_t
nifce_driver_output(struct netif* netif, struct pbuf* p, struct ip_addr* ipaddr)
{
p = etharp_output(netif, ipaddr, p);
if (p != NULL)
low_level_output(netif, p);
return ERR_OK;
}
/*##########################################################################
*
* Sends an incoming Ethernet frame up the stack to a function that will
* understand it (or just drops the frame).
*
*#########################################################################*/
static void
eth_input(struct pbuf* p, struct netif* netif)
{
// Ethernet protocol layer
struct eth_hdr* ethhdr;
struct pbuf* q = NULL;
ethhdr = p->payload;
switch (htons(ethhdr->type))
{
case ETHTYPE_IP:
//q = etharp_ip_input(netif, p);
pbuf_header(p, -(s16_t)sizeof(struct eth_hdr));
netif->input(p, netif);
break;
case ETHTYPE_ARP:
q = etharp_arp_input(netif, (struct eth_addr*)&(netif->hwaddr[0]), p);
break;
default:
pbuf_free(p);
break;
}
if (q != NULL)
{
low_level_output(netif, q);
pbuf_free(q);
}
}
/*##########################################################################
*
* low_level_init
*
*#########################################################################*/
static void
low_level_init(struct netif *netif)
{
ADI_ETHER_BUFFER* p;
struct nifce_info* nip = (struct nifce_info*)netif->state;
struct buffer_info* bip;
int rx_len, tx_len, count;
int i;
ADI_ETHER_BUFFER* rx_head = NULL;
ADI_ETHER_BUFFER* tx_head = NULL;
unsigned int *mangle_ptr;
LWIP_ASSERT("low_level_init: nfice info supply failed", nip != NULL);
LWIP_ASSERT("low_level_init: buffer area supply failed",
nip->buff_area != NULL && nip->buff_area_size > 0);
// copy individual (MAC) address into netif struct
for (i = 0; i < 6; i += 1)
netif->hwaddr[i] = nip->ia[i];
netif->hwaddr_len = 6;
// calculate total requirement for each rx and tx buffer
rx_len = sizeof(ADI_ETHER_BUFFER) + sizeof(struct buffer_info);
tx_len = rx_len;
rx_len += nip->rx_buff_datalen + nip->buff_overhead;
tx_len += nip->tx_buff_datalen + nip->buff_overhead;
rx_len = ((rx_len + 3) / 4) * 4;
tx_len = ((tx_len + 3) / 4) * 4;
// allocate buffers in required ratio from supplied memory area
while (nip->buff_area_size > rx_len || nip->buff_area_size > tx_len)
{
int n;
for (n = 0; n < nip->rx_buffs; n += 1) {
if (nip->buff_area_size < rx_len)
break;
p = (ADI_ETHER_BUFFER*)nip->buff_area;
nip->buff_area += rx_len;
nip->buff_area_size -= rx_len;
p->pNext = rx_head;
rx_head = p;
}
for (n = 0; n < nip->tx_buffs; n += 1) {
if (nip->buff_area_size < tx_len)
break;
p = (ADI_ETHER_BUFFER*)nip->buff_area;
nip->buff_area += tx_len;
nip->buff_area_size -= tx_len;
p->pNext = tx_head;
tx_head = p;
}
}
// initialise each buffer's ADI_ETHER_BUFFER descriptor
p = rx_head;
count = 0;
while (p)
{
p->Data = (char*)p + sizeof(ADI_ETHER_BUFFER) + nip->buff_overhead;
p->ElementCount = nip->rx_buff_datalen;
p->ElementWidth = 1;
p->CallbackParameter =p;
p->ProcessedElementCount=0;
p->ProcessedFlag =0;
mangle_ptr = ((unsigned int*)&p->Reserved)+4;
*((unsigned int*)mangle_ptr)= (unsigned int)((char*)p->Data + p->ElementCount);
bip = (struct buffer_info*)(*(unsigned int*)mangle_ptr);
bip->netif = netif;
bip->max_buf_len = nip->rx_buff_datalen;
// memset(p->data_start, 0x80 + netif->num, p->num_elements);
memset(p->Data, 0x80 + netif->num, p->ElementCount);
count += 1;
p = p->pNext;
}
nip->rx_buffs = count;
p = tx_head;
count = 0;
while (p)
{
p->Data = (char*)p + sizeof(ADI_ETHER_BUFFER) + nip->buff_overhead;
p->ElementCount = nip->tx_buff_datalen;
p->ElementWidth = 1;
p->CallbackParameter =p;
mangle_ptr = ((unsigned int*)&p->Reserved)+4;
*((unsigned int*)mangle_ptr)= (unsigned int)((char*)p->Data + p->ElementCount);
bip = (struct buffer_info*)(*(unsigned int*)mangle_ptr);
bip->netif = netif;
bip->max_buf_len = nip->tx_buff_datalen;
//memset(p->data_start, 0x90 + netif->num, p->num_elements);
memset(p->Data, 0x90 + netif->num, p->ElementCount);
count += 1;
p = p->pNext;
}
nip->tx_buffs = count;
// give all the rx buffers to the IDataPort instance
adi_dev_Read(nip->handle,ADI_DEV_1D,(ADI_DEV_BUFFER*)rx_head);
// save the list of tx buffers until they are needed
nip->x = tx_head;
}
/*##########################################################################
*
* nifce_driver_init(struct netif *netif):
*
* Should be called at the beginning of the program to set up a
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware. It expects the 'status' member of netif
* to be holding a pointer to a nifce_info struct.
*
*#########################################################################*/
err_t
nifce_driver_init(struct netif *netif)
{
sys_sem_t sem;
// set up base part of this interface's name
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
// install function that TCP should call to output packets
netif->output = nifce_driver_output;
// install function that actually queues output for transmission
netif->linkoutput = low_level_output;
// set up this interface's maximum transfer unit and address length
netif->mtu = MTU - 18; // MTU without ethernet header and crc
// carry out lowest level initialisation and enable the interface
low_level_init(netif);
return ERR_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -