⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ethif_jz4730.c

📁 君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图片解码,浏览,电子书,录音,想学ucos,识货的人就下吧 russblock fmradio explore set
💻 C
字号:
/* Jz ethernet support * *  Copyright (c) 2005 *  Ingenic Semiconductor, <lhhuang@ingenic.cn> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA *//* ********************************************************************* */#include "regs.h"#include "ops.h"  // for __intc_mask_irq(n)#include "lwip/debug.h"#include "lwip/opt.h"#include "lwip/def.h"#include "lwip/mem.h"#include "lwip/pbuf.h"#include "lwip/stats.h"#include "lwip/sys.h"#include "netif/etharp.h"#include "jz_eth.h"#include "ethif_jz4730.h"/* ********************************************************************* *//* File local definitions *//* Define those to better describe your network interface. */#define IFNAME0 'e'#define IFNAME1 'n'/* ********************************************************************* */#define MAX_WAIT      1000#define PKTSIZE_ALIGN 1536#define PKTALIGN      32#define PKTBUFSRX     16volatile u8_t  PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];volatile u8_t *NetTxPacket = 0; volatile u8_t *NetRxPackets[PKTBUFSRX];/* Tx and Rx Descriptor */typedef struct {    u32_t status;    u32_t ctrl;    u32_t addr;    u32_t next;} eth_desc_t;#define NUM_RX_DESCS PKTBUFSRX#define NUM_TX_DESCS 4static eth_desc_t rx_desc[NUM_RX_DESCS];static eth_desc_t tx_desc[NUM_TX_DESCS];static int next_rx;static int next_tx;static u32_t full_duplex, phy_mode;/* ********************************************************************* */static inline void reset_eth(void){    int i;    jz_writel(ETH_BMR, jz_readl(ETH_BMR) | BMR_SWR);    for (i = 0; i < MAX_WAIT; i++) {	if(!(jz_readl(ETH_BMR) & BMR_SWR))	    break;	udelay(1);    }    if (i == MAX_WAIT)	printf("Reset eth timeout\n");}static inline void enable_eth(void){    jz_writel(ETH_OMR, jz_readl(ETH_OMR) | OMR_ST | OMR_SR);}	static inline void disable_eth(void){    jz_writel(ETH_OMR, jz_readl(ETH_OMR) & ~(OMR_ST | OMR_SR));}#define MII_CMD_ADDR(id, offset) (((id) << 11) | ((offset) << 6))#define MII_CMD_READ(id, offset) (MII_CMD_ADDR(id, offset))#define MII_CMD_WRITE(id, offset) (MII_CMD_ADDR(id, offset) | 0x2)static u32_t mii_read(int phy_id, int offset){    int i;    u32_t mii_cmd = MII_CMD_READ(phy_id, offset);    jz_writel(ETH_MIAR, mii_cmd);    /* wait for completion */    for (i = 0; i < MAX_WAIT; i++) {	if (!(jz_readl(ETH_MIAR) & 0x1))	    break;	udelay(1);    }        if (i == MAX_WAIT) {	printf("MII wait timeout\n");	return 0;    }        return jz_readl(ETH_MIDR) & 0x0000ffff;}static int autonet_complete(int phy_id){    int i;    for (i = 0; i < MAX_WAIT; i++) {	if (mii_read(phy_id, MII_SR) & 0x0020) 	    break;  //auto negotiation completed	udelay(500);    }    if (i == MAX_WAIT)	return -1;     //auto negotiation  error    else	return 0;}static int search_phy(int phy_id){    unsigned int r;    r = mii_read(phy_id, 1);    if (r!=0 && r!=0xffff)	return 1;    return 0;}static void config_phy(int phy_id){    u32_t mii_reg5;    full_duplex = 0;    mii_reg5 = mii_read(phy_id, MII_ANLPA);    if (mii_reg5 != 0xffff) {	mii_reg5 = mii_read(phy_id, MII_ANLPA);	if ((mii_reg5 & 0x0100) || (mii_reg5 & 0x01C0) == 0x0040)	    full_duplex = 1;	phy_mode = mii_reg5 >> 5;	printf("ETH: setting %s %s-duplex based on MII tranceiver #%d\n",	       (phy_mode & MII_ANLPA_100M) ? "100Mbps" : "10Mbps",	       full_duplex ? "full" : "half", phy_id);    }}static void config_mac(struct netif *netif){    u32_t omr, mcr;    /* Set MAC address */#define ea netif->hwaddr    jz_writel(ETH_MALR, (ea[3] << 24) | (ea[2] << 16) | (ea[1] <<  8) | ea[0]);    jz_writel(ETH_MAHR, (ea[5] <<  8) | ea[4]);    jz_writel(ETH_HTLR, 0);    jz_writel(ETH_HTHR, 0);    /* Assert the MCR_PS bit in CSR */    if (phy_mode & MII_ANLPA_100M)	omr = OMR_SF;    else	omr = OMR_TTM | OMR_SF;    mcr = MCR_TE | MCR_RE | MCR_DBF | MCR_LCC;         if (full_duplex)	mcr |= MCR_FDX;    /* Set the Operation Mode (OMR) and Mac Control (MCR) registers */    jz_writel(ETH_OMR, omr);    jz_writel(ETH_MCR, mcr);	    /* Set the Programmable Burst Length (BMR.PBL, value 1 or 4 is validate) */    jz_writel(ETH_BMR, DMA_BURST << 8);    /* Reset csr8 */    jz_readl(ETH_MFCR); // missed frams counter}/*--------------------------------------------------------------------------- * ETH interface routines *--------------------------------------------------------------------------*/static err_t ETH_output(struct netif *netif, struct pbuf *p){    // q traverses through linked list of pbuf's    struct pbuf *q;		    volatile u8_t *ptr = NetTxPacket;     u16_t length = p->tot_len;     for(q = p; q != NULL; q = q->next){	memcpy((void *)ptr,q->payload, q->len); 	ptr += q->len;		#if (ETHIF_STATS > 0)		((struct ETHIF *)netif->state)->sentbytes += q->len;#endif		#if (ETHIF_STATS > 0)		((struct ETHIF *)netif->state)->sentpackets++;#endif    }	    volatile eth_desc_t *desc = 	(volatile eth_desc_t *)((unsigned int)(tx_desc + next_tx) | 0xa0000000);    int i;    /* tx fifo should always be idle */    desc->addr = virt_to_phys(NetTxPacket);    desc->ctrl |= TD_LS | TD_FS | length;    desc->status = T_OWN;    jz_flush_dcache();    jz_sync();    /* Start the tx */    jz_writel(ETH_TPDR, 1);    i = 0;    while (desc->status & T_OWN) {	if(i > MAX_WAIT) {	    printf("ETH TX timeout\n");	    break;	}	udelay(1);	i++;    }    /* Clear done bits */    jz_writel(ETH_SR,  DMA_TX_DEFAULT);        desc->status = 0;    desc->addr = 0;    desc->ctrl &= ~(TD_LS | TD_FS);    next_tx++;    if (next_tx >= NUM_TX_DESCS){	next_tx=0;    }    return ERR_OK;}/*** Writing an IP packet (to be transmitted) to the ethif of jz4730.** Before writing a frame to the ethif of jz4730, the ARP module is asked to resolve the* Ethernet MAC address. The ARP module might undertake actions to resolve the* address first, and queue this packet for later transmission.** @param netif The lwIP network interface data structure belonging to this device.* @param p pbuf to be transmitted (or the first pbuf of a chained list of pbufs).* @param ipaddr destination IP address.*/static err_t ETHIF_output(struct netif *netif, struct pbuf *p, struct ip_addr *ipaddr){     /* resolve hardware address, then send (or queue) packet */    return etharp_output(netif, ipaddr, p);}/*** Move a received packet from the ethif of jz4730 into a new pbuf.** This function copies a frame from the ethif of jz4730.* It is designed failsafe:* - It does not assume a frame is actually present.* - It checks for non-zero length* - It does not overflow the frame buffer*/static struct pbuf *ETH_Input(struct netif *netif){     struct pbuf *p = NULL, *q = NULL;	           volatile eth_desc_t *desc;    int length;    u32_t status;    volatile u8_t *ptr = NetRxPackets[next_rx];    //for(;;) {    desc = (volatile eth_desc_t *)((unsigned int)(rx_desc + next_rx) | 0xa0000000);    status = desc->status;    if (status & R_OWN) {	return 0;    }        length = ((status & RD_FL) >> 16); /* with 4-byte CRC value */        if (status & RD_ES) {	return 0;    }    else {	if (length > 0)	    {		// allocate a pbuf chain with total length 'len' 		p = pbuf_alloc(PBUF_RAW, length - 4, PBUF_POOL);  //length - 4		if (p != 0) {		    for (q = p; q != 0; q = q->next) {			memcpy(q->payload,(void *)ptr, q->len); 			ptr += q->len;		    }		}		else { 		    // could not allocate a pbuf		    // skip received frame		    // TODO: maybe do not skip the frame at this point in time?#if (ETHIF_STATS > 0)		    ((struct ETHIF *)netif->state)->dropped++;#endif		    /* ------------------------------------- Add stats >>>>>>>>>>>>>>>>>>>>>>>>>>>> no pbuf */		    return 0;		}	    }	// length was zero	else {	    /* ----------------------------------------- Add stats >>>>>>>>>>>>>>>>>>>>>>>>>>>>*/	}	    }// if(status & RD_E)    /* Clear done bits */    jz_writel(ETH_SR,  DMA_RX_DEFAULT| DMA_INT_NI); //DMA_INT_NI must be clear by software!    desc->status = R_OWN;    jz_flush_dcache();    jz_sync();    next_rx++;    if (next_rx >= NUM_RX_DESCS) {	next_rx = 0;    }    //} /* for */    return p;}/** Read a received packet from the jz4730.** This function should be called when a packet is received by the  jz4730* and is fully available to read. It moves the received packet to a pbuf* which is forwarded to the IP network layer or ARP module. It transmits* a resulting ARP reply or queued packet.** @param netif The lwIP network interface to read from.**/static void ETHIF_input(struct netif *netif){    struct ETHIF *ETHIF = netif->state;    struct eth_hdr *ethhdr = NULL;    struct pbuf *p;    while(1) {        p = ETH_Input(netif);    	/* no packet could be read */	if(p == NULL) {	    /* silently ignore this */	    return;	}	/* points to packet payload, which starts with an Ethernet header */	ethhdr = p->payload;#ifdef Print_Header	printf("#ETH packet src addr: %x.%x.%x.%x.%x.%x \n",ethhdr->src.addr[0],ethhdr->src.addr[1],ethhdr->src.addr[2],ethhdr->src.addr[3],ethhdr->src.addr[4],ethhdr->src.addr[5]);	printf("#ETH packet dest addr: %x.%x.%x.%x.%x.%x \n",ethhdr->dest.addr[0],ethhdr->dest.addr[1],ethhdr->dest.addr[2],ethhdr->dest.addr[3],ethhdr->dest.addr[4],ethhdr->dest.addr[5]);	printf("#ETH packet type: %x \n",htons(ethhdr->type));#endif	struct etharp_hdr *arphdr = p->payload;	switch(htons(ethhdr->type)) {	case ETHTYPE_IP: 	/* IP packet? */	    etharp_ip_input(netif, p); /* update ARP table, obtain first queued packet */	    pbuf_header(p, -14); /* skip Ethernet header */	    netif->input(p, netif); /* pass to network layer */	    break;			case ETHTYPE_ARP:	/* ARP packet? */#ifdef Print_Header        printf("#ARP packet proto: %x. hwtype %x \n",htons(arphdr->proto),arphdr->hwtype);        printf("#ARP packet src ip: %lu. %lu \n",arphdr->sipaddr.addrw[0],arphdr->sipaddr.addrw[1]);        printf("#ARP packet dest ip: %lu. %lu \n",arphdr->dipaddr.addrw[0],arphdr->dipaddr.addrw[1]);	printf("#ARP packet src hwaddr: %x.%x.%x.%x.%x.%x \n",arphdr->shwaddr.addr[0],arphdr->shwaddr.addr[1],arphdr->shwaddr.addr[2],arphdr->shwaddr.addr[3],arphdr->shwaddr.addr[4],arphdr->shwaddr.addr[5]);	printf("#ARP packet dest hwaddr: %x.%x.%x.%x.%x.%x \n",arphdr->dhwaddr.addr[0],arphdr->dhwaddr.addr[1],arphdr->dhwaddr.addr[2],arphdr->dhwaddr.addr[3],arphdr->dhwaddr.addr[4],arphdr->dhwaddr.addr[5]);#endif	etharp_arp_input(netif, ((struct ETHIF *)netif->state)->ethaddr, p);	break;			default:			/* unsupported Ethernet packet type */	    pbuf_free(p);	    break;	}    } //while(1)}static voidlow_level_init(struct netif *netif){    int i, phyid = -1;	    /*Setup packet buffers, aligned correctly.    //net.c */    NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);    NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;    for (i = 0; i < PKTBUFSRX; i++) {	NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;    }        /* Reset ethernet unit */    reset_eth();    /*set bit 16 NI and bit 6 RI */    jz_writel(ETH_IER, 0x00010040);     for (i=0;i<32;i++)	if (search_phy(i)) {	    phyid = i;	    break;	}    if (phyid == -1)	printf("Can't locate any PHY\n");    /* Start Auto Negotiation of PHY 0 and check it */    if (autonet_complete(phyid))	printf("ETH Auto-Negotiation failed\n");    /* Configure PHY */    config_phy(phyid);    /* Configure MAC */    config_mac(netif);    /* Setup the Rx&Tx descriptors */    for (i = 0; i < NUM_RX_DESCS; i++) {	rx_desc[i].status  = R_OWN;	rx_desc[i].ctrl    = PKTSIZE_ALIGN | RD_RCH;	rx_desc[i].addr    = virt_to_phys(NetRxPackets[i]);	rx_desc[i].next    = virt_to_phys(rx_desc + i + 1);		//printf("rx_desc[i].addr=%lx  NetRxPackets[i]=%lx\n", rx_desc[i].addr,(unsigned long)(NetRxPackets[i]));	}    //	rx_desc[NUM_RX_DESCS - 1].next = virt_to_phys(rx_desc); // The last links to the first	    rx_desc[NUM_RX_DESCS - 1].ctrl |=  RD_RER;        for (i = 0; i < NUM_TX_DESCS; i++) {	tx_desc[i].status  = 0;	tx_desc[i].ctrl    = TD_TCH;	tx_desc[i].addr    = 0;	tx_desc[i].next    = virt_to_phys(tx_desc + i + 1);    }    //	tx_desc[NUM_TX_DESCS - 1].next = virt_to_phys(tx_desc); // The last links to the first    tx_desc[NUM_TX_DESCS - 1].ctrl |= TD_TER;  // Set the Transmit End Of Ring flag    jz_flush_dcache();        jz_writel(ETH_RAR, virt_to_phys(rx_desc));    jz_writel(ETH_TAR, virt_to_phys(tx_desc));    next_rx = next_tx = 0;    /* Enable ETH */    enable_eth();}static voidarp_timer(void *arg){    etharp_tmr();    sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);}void ETH_Handler(unsigned int arg){    __intc_mask_irq(IRQ_ETH);    ETHIF_input((struct netif *)arg);    __intc_unmask_irq(IRQ_ETH);}err_tETHIF_Init(struct netif *netif){    struct ETHIF *ETHIF;	    ETHIF = mem_malloc(sizeof(struct ETHIF));    if (ETHIF == NULL) return ERR_MEM;	    netif->name[0] = IFNAME0;    netif->name[1] = IFNAME1;    netif->output = ETHIF_output;    netif->linkoutput = ETH_output;	    // initialize ETH specific interface structure    netif->state = ETHIF;	#if 0    /* maximum transfer unit */    netif->mtu = 1500;	    /* broadcast capability */    netif->flags = NETIF_FLAG_BROADCAST;#endif	    /* hardware address length */    netif->hwaddr_len = 6;    int i;    for(i=0; i < netif->hwaddr_len; i++)	netif->hwaddr[i]=0x68;    /* mike not needed*/ ETHIF->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]);    ETHIF->needs_service = 1;    ETHIF->use_polling = 0;	#if (ETHIF_STATS > 0)    // number of interrupts (vector calls)    ETHIF->interrupts = 0;    ETHIF->missed = 0;    ETHIF->dropped = 0;    ETHIF->sentpackets = 0;    ETHIF->sentbytes = 0;#endif    low_level_init(netif);    request_irq(IRQ_ETH, ETH_Handler,netif);    sys_timeout(ARP_TMR_INTERVAL, arp_timer, NULL);    return ERR_OK;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -