Lwip在UCOS-II上的移植(三)

移植网络驱动程序。在netif文件夹下有ethernetif.c,就是网络芯片的驱动程序,需要对照实际使用的网络芯片修改。下面是DM9000A的在lwip下的驱动的程序。

/* Define those to better describe your network interface. */

#define IFNAME0 ‘d’

#define IFNAME1 ‘m’

#define NIC_BASE 0x82000000

#define NIC_REG_ADDR (*(volatile u8_t *) 0x82000000)

/* if cmd link to system bus A2 */

#define NIC_REG_DATA_byte (*(volatile u8_t *) 0x82000004)

#define NIC_REG_DATA_word (*(volatile u16_t *) 0x82000004)

/* for dm9000a function setting */

#define Fix_Note_Address

#define DM9000A_FLOW_CONTROL

#define Rx_Int_enable

static void low_level_init(struct netif * netif);

static err_t low_level_output(struct netif * netif,struct pbuf *p);

static void ethernetif_input(struct netif *netif);

struct pbuf * low_level_input(struct netif *netif);

u16_t DM9000A_Phy_Read (u8_t offset);

void udelay(u32_t time)

{

//wait_1us(time);

while (–time > 0);

}

u8_t ior(u8_t reg_addr)

{

NIC_REG_ADDR = reg_addr;

return (NIC_REG_DATA_byte);

}

Void iow(u8_t reg_addr, u8_t reg_data)

{

NIC_REG_ADDR = reg_addr;

NIC_REG_DATA_byte = reg_data;

}

/*

* 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)

{

IO0SET = (1 << DM9000A_RST); //硬件复位

udelay(30);

IO0CLR = (1 << DM9000A_RST);

udelay(30000);

IO0SET = (1 << DM9000A_RST);

udelay(1000);

if(!dm9k_found())

{

LWIP_DEBUGF(NETIF_DEBUG,(“ethernetif_init: no device can use !\n”));

return ERR_MEM;

}

netif->name[0] = IFNAME0;

netif->name[1] = IFNAME1;

netif->output = etharp_output;

netif->linkoutput = low_level_output;

netif->hwaddr[0] = my_mac[0];

netif->hwaddr[1] = my_mac[1];

netif->hwaddr[2] = my_mac[2];

netif->hwaddr[3] = my_mac[3];

netif->hwaddr[4] = my_mac[4];

netif->hwaddr[5] = my_mac[5];

netif->hwaddr_len = 6;

netif->mtu = 1500;

netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;

low_level_init(netif);

return ERR_OK;

}

/**

* dm9k ethernet chip found

*/

u8_t dm9k_found(void)

{

u32_t check_id;

check_id = ior(DM9000_REG_VID_L);

check_id |= ior(DM9000_REG_VID_H) << 8;

check_id |= ior(DM9000_REG_PID_L) << 16;

check_id |= ior(DM9000_REG_PID_H) << 24;

LWIP_DEBUGF(NETIF_DEBUG,(“dm9k_debug : check_id = %0x , vid = %0x !\n”, check_id , DM9000_ID));

if(check_id != DM9000_ID)

{

LWIP_DEBUGF(NETIF_DEBUG,(“dm9k_found: not found device !\n”));

return 0;

}

else

{

LWIP_DEBUGF(NETIF_DEBUG,(“dm9k_found: found device !!\n”));

return 1;

}

}

/**

* Initialize the dm9k ethernet chip, resetting the interface and getting the ethernet

* address.

*/

static void low_level_init(struct netif * netif)

{

u8_t i;

u16_t reg_val,j;

/* soft reset device 2 time*/

iow(DM9000_REG_NCR, DM9000_REG_RESET);

udelay(20); /* delay 10us */

iow(DM9000_REG_NCR, DM9000_REG_RESET);

udelay(20); /* delay 10us */

for(i = 0; i < 6; i++)

{

iow(DM9000_REG_PAR + i, my_mac[i]);

}

for(i = 0; i < 8; i++)

{

if(i < 7)

iow(DM9000_REG_MAR + i, 0x00);

else

iow(DM9000_REG_MAR + i, 0x80);

}

dm9k_reset();

iow(DM9000_REG_GPCR, 0x01);

iow(DM9000_REG_GPR, DM9000_PHY_OFF);

udelay(500000); /* dealy 0.5s */

iow(DM9000_REG_GPR, DM9000_PHY_ON);

udelay(500000); /* delay 0.5s */

dm9k_phy_write(0x00, 0x8000);

#ifdef DM9000A_FLOW_CONTROL

dm9k_phy_write(0x04, 0x01e1 | 0x0400);

#else

dm9k_phy_write(0x04, 0x01e1);

#endif

dm9k_phy_write(0x00, 0x1200);

iow(DM9000_REG_GPR, DM9000_PHY_ON);

}

/**

* dm9k ethernet chip soft_reset

*/

Void dm9k_reset(void)

{

LWIP_DEBUGF(NETIF_DEBUG,(“dm9k_reset: dm9k ethernet chip soft_reset !\n”));

/* soft reset device 2 time*/

iow(DM9000_REG_NCR, DM9000_REG_RESET);

udelay(20); /* delay 10us */

iow(DM9000_REG_NCR, DM9000_REG_RESET);

udelay(20); /* delay 10us */

/* Program operating register */

iow(DM9000_REG_TCR, 0x00); /* TX Polling clear */

iow(DM9000_REG_SMCR, 0x00); /* Special Mode */

iow(DM9000_REG_NSR, 0x2c); /* clear TX status */

iow(DM9000_REG_ISR, 0x0f); /* Clear interrupt status */

iow(DM9000_REG_TCR2, DM9000_TCR2_SET); /* LED mode */

iow(0x31, 0x07);

#ifdef DM9000A_FLOW_CONTROL

iow(DM9000_REG_BPTR, DM9000_BPTR_SET); /* Less 3Kb, 200us */

iow(DM9000_REG_FCTR, DM9000_FCTR_SET); /* Flow Control : High/Low Water */

iow(DM9000_REG_FCR, DM9000_FCR_SET); /* Flow Control */

#endif

/* Activate DM9000 */

iow(DM9000_REG_IMR, DM9000_IMR_OFF); /* Set FIFO AUTO_RETURN */

iow(DM9000_REG_RCR, DM9000_RCR_SET); /* RX enable */

#ifdef Rx_Int_enable

iow(DM9000_REG_IMR, DM9000_IMR_SET); /* Enable TX/RX interrupt mask */

#endif

}

/**

* phy write regisger data

*

*/

void dm9k_phy_write(u8_t phy_reg, u16_t reg_data)

{

u8_t t = 0;

iow(DM9000_REG_EPAR, phy_reg | DM9000_PHY);

/* 设置写入PHY寄存器的值 */

iow(DM9000_REG_EPDRH, (reg_data >> 8) & 0xff);

iow(DM9000_REG_EPDRL, reg_data & 0xff);

iow(DM9000_REG_EPCR, 0x0a);

while(ior(DM9000_REG_EPCR) & 0x01)

{

if( t++ > 200)

{

break;

}

udelay(100);

};

iow(DM9000_REG_EPCR, 0x08);

}

/*

* low_level_output():

*

* Should do the actual transmission of the packet. The packet is

* contained in the pbuf that is passed to the function. This pbuf

* might be chained.

*

*/

static err_t low_level_output(struct netif * netif, struct pbuf *p)

{

struct pbuf *q;

u16_t packetLength;

u8_t *tx_buf;

u16_t tx_count,calc_MWR;

u8_t mwrl,mwrh,mwrl1,mwrh1;

/* Disable all interrupt*/

iow(DM9000_REG_IMR, DM9000_IMR_OFF);

while(ior(DM9000_REG_TCR) & DM9000_TCR_SET)

{

LWIP_DEBUGF(NETIF_DEBUG,(“low_level_output: wait to TX complete !\n”));

udelay(10);

};

packetLength = p->tot_len – ETH_PAD_SIZE;

for (q = p; q != NULL; q = q->next)

{

/* Send the data from the pbuf to the interface, one pbuf at a

time. The size of the data in each pbuf is kept in the ->len

variable.*/

tx_buf = q->payload;

tx_count = q->len;

if (ETH_PAD_SIZE)

{

if(q == p)

{

tx_buf += ETH_PAD_SIZE;

tx_count -= ETH_PAD_SIZE;

}

}

outsw((u16_t *)tx_buf, tx_count);

}

/* Set TX length to DM9000 */

iow(DM9000_REG_TXPLH, (packetLength >> 8) & 0xff);

iow(DM9000_REG_TXPLL, packetLength & 0xff);

iow(DM9000_REG_TCR, DM9000_TCR_SET); /* Cleared after TX complete */

/* Enable interrupt*/

iow(DM9000_REG_IMR, DM9000_IMR_SET);

return ERR_OK;

}

/**

* outsw

*/

void outsw(u16_t* p, u16_t len)

{

u16_t i, j;

len = (len + 1) >> 1;

NIC_REG_ADDR = DM9000_REG_MWCMD;

for (i = 0; i < len; i++)

{

j = *p++;

NIC_REG_DATA_word = j;

// udelay(10);

}

}

/*

* low_level_input():

*

* Should allocate a pbuf and transfer the bytes of the incoming

* packet from the interface into the pbuf.

*

*/

struct pbuf * low_level_input(struct netif *netif)

{

u8_t rx_checkbyte;

u16_t rx_status, rx_len;

u8_t mrrh, mrrl;

u16_t calc_mrr;

struct pbuf *p, *q;

u8_t *rx_buf;

u16_t rx_count;

/* Disable all interrupt*/

iow(DM9000_REG_IMR, DM9000_IMR_OFF);

ior(DM9000_REG_MRCMDX);

mrrh = ior(DM9000_REG_MRRH);

mrrl = ior(DM9000_REG_MRRL);

rx_checkbyte = ior(DM9000_REG_MRCMDX);

if(rx_checkbyte == DM9000_PKT_RDY)

{

NIC_REG_ADDR = DM9000_REG_MRCMD;

rx_status = NIC_REG_DATA_word;

rx_len = NIC_REG_DATA_word;

if(rx_len > DM9000_PKT_MAX || rx_status & 0xbf00)

{

dm9k_reset();

iow(DM9000_REG_IMR, DM9000_IMR_SET);

return NULL;

}

calc_mrr = (mrrh << 8) | mrrl;

calc_mrr += (rx_len + 4);

if(rx_len & 0x01) calc_mrr++;

if(calc_mrr > 0x3fff) calc_mrr -= 0x3400;

p = pbuf_alloc(PBUF_RAW, rx_len +ETH_PAD_SIZE, PBUF_POOL);

if(p == NULL)

{

/* 将指针移到下一个包的包头位置 */

iow (DM9000_REG_MRRH, (calc_mrr >> 8) & 0xff);

iow (DM9000_REG_MRRL, calc_mrr & 0xff );

iow(DM9000_REG_IMR, DM9000_IMR_SET);

return NULL;

}

else

{

for (q = p; q != NULL; q = q->next)

{

/*

Read enough bytes to fill this pbuf in the chain.

The avaliable data in the pbuf is given by the q->len variable.

*/

rx_buf = q->payload;

if (rx_len < q->len)

rx_count = rx_len;

else

rx_count = q->len;

if (ETH_PAD_SIZE)

{

if (q == p)

{

rx_buf += ETH_PAD_SIZE;

if (q->next != NULL) rx_count -= ETH_PAD_SIZE;

}

}

insw((u16_t *)rx_buf, rx_count); // 从DM9008A中读入数据包

rx_len -= rx_count;

}

iow(DM9000_REG_IMR, DM9000_IMR_SET);

return p;

}

}

else

{

if(rx_checkbyte == DM9000_PKT_NORDY)

{

iow(DM9000_REG_ISR, 0x3f); /* Clear ISR status */

}

else

{

dm9k_reset();

}

iow(DM9000_REG_IMR, DM9000_IMR_SET);

return NULL;

}

}

/**

* insw

*/

Void insw(u16_t* p, u16_t len)

{

u16_t i, j;

len = (len + 1) >> 1;

NIC_REG_ADDR = DM9000_REG_MRCMD;

for (i = 0; i < len; i++)

{

j = NIC_REG_DATA_word;

*p++ = j;

}

}

/*

* dm9k_Interrupt():

*

*/

void dm9000a_Interrupt(void)

{

u8_t isr_status, savedReg;

/* Save previous register address*/

savedReg = NIC_REG_ADDR;

/* Disable all interrupt*/

iow(DM9000_REG_IMR, DM9000_IMR_OFF);

/* Got DM9000 interrupt status*/

isr_status = ior(DM9000_REG_ISR); /* Got ISR*/

iow(DM9000_REG_ISR, isr_status); /* Clear ISR status */

/* Received the coming packet*/

if (isr_status & DM9000_RX_INTR)

{

OSSemPost(SemEthernetInt); //接收到中断,发送信号量

}

iow(DM9000_REG_IMR, DM9000_IMR_SET);

NIC_REG_ADDR = savedReg;

}

© 版权声明
THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发