?? ethernetif.c
字號:
struct pbuf *
low_level_input(struct netif *netif)
{
struct EtherDev *dev = netif->state;
struct pbuf *skb = NULL;
u16_t rxbyte, *rdptr;
u16_t i, RxStatus, RxLen, GoodPacket, tmplen;
/* Check packet ready or not */
ior(0xf0); /* Dummy read */
rxbyte = inb(DM9KDATA); /* Got most updated data */
/* Status check: this byte must be 0 or 1 */
/* packet ready to receive check */
if (rxbyte == DM9K_PKT_RDY) {
/* A packet ready now & Get status/length */
GoodPacket = TRUE;
outb(0xf2, DM9KADDR);
#if 0
if (dev->io_mode == DM9K_BYTE_MODE) {
/* Byte mode */
RxStatus = inb(DM9KDATA)+(inb(DM9KDATA) << 8);
RxLen = inb(DM9KDATA)+(inb(DM9KDATA) << 8);
} else
#endif
if (dev->io_mode == DM9K_WORD_MODE) {
/* Word mode */
RxStatus = inw(DM9KDATA);
RxLen = inw(DM9KDATA);
}
/* Packet Status check */
if (RxLen < 0x40) {
GoodPacket = FALSE;
//dev->runt_length_counter++;
}
if (RxLen > DM9K_PKT_MAX) {
DEBUGF(DM9K_DEBUG | DBG_TRACE, ("<DM9K> RST: RX Len:%x\n", RxLen));
//dev->long_length_counter++;
}
if (RxStatus & 0xbf00) {
GoodPacket = FALSE;
if (RxStatus & 0x100)
//dev->rx_fifo_errors++;
;
if (RxStatus & 0x200)
//dev->rx_crc_errors++;
;
if (RxStatus & 0x8000)
//dev->rx_length_errors++;
;
}
/* Move data from DM9K */
if ( GoodPacket && ((skb = pbuf_alloc(PBUF_LINK,RxLen, PBUF_POOL)) != NULL ) ) {
rdptr = skb->payload;
/* Read received packet from RX SARM */
#if 0
if (dev->io_mode == DM9K_BYTE_MODE) {
/* Byte mode */
for (i=0; i<RxLen; i++)
rdptr[i]=inb(DM9KDATA);
} else
#endif
if (dev->io_mode == DM9K_WORD_MODE) {
/* Word mode */
tmplen = (RxLen + 1) / 2;
r_pack(tmplen, rdptr);
//for (i=0;i<tmplen;i++)
//*((u16_t *)rdptr++) = inw(DM9KDATA);
}
/* Pass to upper layer */
dev->rx_packets++;
return(skb);
} else {
if (skb!=NULL) pbuf_free(skb);
tmplen = (RxLen + 1) / 2;
drop(tmplen);
//dev->drop_packets++;
return(NULL);
}
}
return (NULL);
}
/*
Read a word data from SROM
*/
/*
Set DM9K multicast address
*/
#if 0
static u16_t read_srom_word( int offset)
{
iow( 0xc, offset);
iow( 0xb, 0x4);
delay(200);
iow( 0xb, 0x0);
return (ior( 0xd) + (ior( 0xe) << 8) );
}
void DM9K_hash_table(struct net_device *dev)
{
//EtherDev_t *db = (EtherDev_t *)dev->priv;
struct dev_mc_list *mcptr = dev->mc_list;
int mc_cnt = dev->mc_count;
u16_t hash_val;
u16_t i, oft, hash_table[4];
DMFE_DBUG(0, "DM9K_hash_table()", 0);
/* Set Node address */
for (i = 0, oft = 0x10; i < 6; i++, oft++)
iow( oft, GETMAC(dev->dev_addr, i));
/* Clear Hash Table */
for (i = 0; i < 4; i++)
hash_table[i] = 0x0;
/* broadcast address */
hash_table[3] = 0x8000;
/* the multicast address in Hash Table : 64 bits */
for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
hash_val = cal_CRC((u8_t *)mcptr->dmi_addr, 6, 0) & 0x3f;
hash_table[hash_val / 16] |=(u16_t) 1 << (hash_val % 16);
}
/* Write the hash table to MAC MD table */
for (i = 0, oft = 0x16; i < 4; i++)
{
iow( oft++, hash_table[i] & 0xff);
iow( oft++, (hash_table[i] >> 8) & 0xff);
}
}
/*
Calculate the CRC valude of the Rx packet
flag = 1 : return the reverse CRC (for the received packet CRC)
0 : return the normal CRC (for Hash Table index)
*/
static unsigned long cal_CRC(u8_t * Data, unsigned int Len, u8_t flag)
{
u32_t crc = CRC_32(Data,Len);
if (flag)
return ~crc;
return crc;
}
/* CRC_32 運算 */
u32_t CRC_32(u8_t *CRC_Data , u16_t Data_len)
{
u32_t crc ,carry ;
u16_t iTemp;
u16_t iTemp1;
/* 將輸入的資料,進行 crc-32 運算 */
crc = 0xffffffff;
for(iTemp = 0 ; iTemp < Data_len ; iTemp++)
{
carry = (crc ^ *CRC_Data++) & 0xff;
for(iTemp1 = 0 ; iTemp1 < 8 ; iTemp1++)
{
if(carry & 1)
carry = (carry >> 1) ^ 0xedb88320;
else
carry >>= 1;
}
crc = ((crc >> 8) & 0x00ffffff) ^ carry;
}
return(crc);
}
#endif
/*
Read a byte from I/O port
*/
volatile static u8_t ior(int reg)
{
outb(reg, DM9KADDR);
return inb(DM9KDATA);
}
/*
Write a byte to I/O port
*/
static void iow(int reg, u8_t value)
{
outb(reg, DM9KADDR);
outb(value, DM9KDATA);
}
/*
Read a word from phyxcer
*/
volatile static u16_t phy_read(int reg)
{
/* Fill the phyxcer register into REG_0C */
iow(0xc, DM9K_PHY | reg);
iow(0xb, 0xc); /* Issue phyxcer read command */
delay(100); /* Wait read complete */
while((ior(EPCR) & 0x01) == 0x01);
iow( 0xb, 0x0); /* Clear phyxcer read command */
/* The read data keeps on REG_0D & REG_0E */
return ( ior(0xe) << 8 ) | ior(0xd);
}
/*
Write a word to phyxcer
*/
static void phy_write(int reg, u16_t value)
{
/* Fill the phyxcer register into REG_0C */
iow(0xc, DM9K_PHY | reg);
/* Fill the written data into REG_0D & REG_0E */
iow(0xd, (value & 0xff));
iow(0xe, ( (value >> 8) & 0xff));
iow(0xb, 0xa); /* Issue phyxcer write command */
delay(200); /* Wait write complete */
while((ior(EPCR) & 0x01) == 0x01);
iow(0xb, 0x0); /* Clear phyxcer write command */
}
/*-----------------------------------------------------------------------------------*/
/*
* ethernetif_output():
*
* This function is called by the TCP/IP stack when an IP packet
* should be sent. It calls the function called low_level_output() to
* do the actuall transmission of the packet.
*
*/
/*-----------------------------------------------------------------------------------*/
static err_t
ethernetif_output(struct netif *netif, struct pbuf *p,
struct ip_addr *ipaddr)
{
struct EtherDev *dev;
struct pbuf *q;
struct eth_hdr *ethhdr;
struct eth_addr *dest;
struct ip_addr *queryaddr;
err_t err;
u8_t i;
DMFE_DBUG(1, "ethernetif_output()\n", p);
dev = netif->state;
/* Make room for Ethernet header. */
if (pbuf_header(p, 14) != 0) {
/* The pbuf_header() call shouldn't fail, but we allocate an extra
pbuf just in case. */
q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
if (q == NULL) {
#ifdef LINK_STATS
lwip_stats.link.drop++;
lwip_stats.link.memerr++;
#endif /* LINK_STATS */
return ERR_MEM;
}
pbuf_chain(q, p);
p = q;
}
/* Construct Ethernet header. Start with looking up deciding which
MAC address to use as a destination address. Broadcasts and
multicasts are special, all other addresses are looked up in the
ARP table. */
queryaddr = ipaddr;
if (ip_addr_isany(ipaddr) ||
ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
dest = (struct eth_addr *)ðbroadcast;
} else if (ip_addr_ismulticast(ipaddr)) {
/* Hash IP multicast address to MAC address. */
/*to do : */
} else {
if (ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
/* Use destination IP address if the destination is on the same
subnet as we are. */
queryaddr = ipaddr;
} else {
/* Otherwise we use the default router as the address to send
the Ethernet frame to. */
queryaddr = &(netif->gw);
}
dest = etharp_lookup(queryaddr);
}
/* If the etharp_lookup() didn't find an address, we send out an ARP
query for the IP address. */
if (dest == NULL) {
err = etharp_query(netif, queryaddr, p);
return err;
}
ethhdr = p->payload;
for(i = 0; i < 3; i++) {
ethhdr->dest.addr[i] = dest->addr[i];
ethhdr->src.addr[i] = dev->dev_addr.addr[i];
}
ethhdr->type = htons(ETHTYPE_IP);
#ifdef LINK_STATS
lwip_stats.link.xmit++;
#endif /* LINK_STATS */
return low_level_output(netif, p);
}
/*-----------------------------------------------------------------------------------*/
static void
ethernetif_input(struct netif *netif)
{
struct EtherDev *dev;
struct eth_hdr *ethhdr;
struct pbuf *p;
dev = netif->state;
p = low_level_input(netif);
if (p != NULL) {
#ifdef LINK_STATS
lwip_stats.link.recv++;
#endif /* LINK_STATS */
ethhdr = p->payload;
switch (htons(ethhdr->type)) {
case ETHTYPE_IP:
etharp_ip_input(netif, p);
pbuf_header(p, -14);
netif->input(p, netif);
break;
case ETHTYPE_ARP:
p = etharp_arp_input(netif, &(dev->dev_addr), p);
if (p != NULL) {
low_level_output(netif, p);
pbuf_free(p);
}
break;
default:
pbuf_free(p);
break;
}
}
}
/*-----------------------------------------------------------------------------------*/
void
etharp_timer(void *arg)
{
struct EtherDev *dev = arg;
if (!(ior(NSR) & 1<<6))
dev->link_mode = DM9K_DISCONN;
else dev->link_mode = dev->op_mode;
etharp_tmr();
sys_timeout(etharp_TMR_INTERVAL, etharp_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)
{
int i;
if (dmfe_probe(dmfe_dev)!=0)
{
DEBUGF(DM9K_DEBUG | DBG_TRACE, ("device not found!\n"));
return ERR_IF;
};
netif->state = dmfe_dev;
netif->name[0] = IFNAME0;
netif->name[1] = IFNAME1;
netif->hwaddr_len = 3;
netif->output = ethernetif_output;
netif->linkoutput = low_level_output;
for (i = 0; i < netif->hwaddr_len; ++i) {
netif->hwaddr[i] = dmfe_dev->dev_addr.addr[i];
}
low_level_init(netif);
etharp_init();
return ERR_OK;
sys_timeout(etharp_TMR_INTERVAL, etharp_timer, NULL);
}
/*-----------------------------------------------------------------------------------*/
/* 檢查 DM9K 接收內存是否還有新的封包 */
u8_t CheckNetPack(struct EtherDev *dev)
{
u16_t temp;
ior(MRCMDX);
switch(ior(MRCMDX))//DM9KREG_r(MRCMDX)) /* 檢查是否有新的封包進入 */
{
case 0x00 :
{
return(0); /* 尚無封包進入 */
}
case 0x01 : return(1); /* 有封包進入 */
default :
temp = ior(0xF4) + ior(0xF5)*256;
DEBUGF(DM9K_DEBUG | DBG_TRACE,("%02x",ior(MRCMDX)));
dev->reset_rx_status++;
dmfe_stop(dev);
delay(200);
dmfe_init_DM9K(dev); /* 內存出錯,重置 DM9K */
return(0);
}
}
void Ethernet_poll(struct netif *netif)
{
if (((struct EtherDev *)(netif->state))->link_mode == DM9K_DISCONN)
{
DEBUGF(DM9K_DEBUG | DBG_TRACE,
("Hardware error!No Active network connected.\n \
Please check your network interface.\n"));
return;
}
if(CheckNetPack((struct EtherDev *)(netif->state)))
ethernetif_input(netif);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -