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

📄 at91_ether.c

📁 RT-Thread是发展中的下一代微内核嵌入式实时操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
 * Program the hardware MAC address from dev->dev_addr. */static void update_mac_address(struct net_device *dev){	AT91_EMAC->EMAC_SA1L = (dev->dev_addr[3] << 24) | (dev->dev_addr[2] << 16) | (dev->dev_addr[1] << 8) | (dev->dev_addr[0]);	AT91_EMAC->EMAC_SA1H = (dev->dev_addr[5] << 8) | (dev->dev_addr[4]);}/* ................................ Driver Interface............................. *//* * User-space ioctl interface. */rt_err_t at91ether_control(rt_device_t dev, rt_uint8_t cmd, void *args){	switch(cmd)	{		case NIOCTL_GADDR:    		/* get mac address */    		if(args) rt_memcpy(args, at91_dev_entry.dev_addr, 6);			else return -RT_ERROR;			break;		default :			break;	}	return RT_EOK;}/* * Open the ethernet interface */rt_err_t at91ether_open(rt_device_t dev){	return RT_EOK;}/* * Close the interface */rt_err_t at91ether_close(rt_device_t dev){	return RT_EOK;}/* * Read */rt_err_t at91ether_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size){	return -RT_ENOSYS;}/* * Transmit packet. */rt_err_t  at91ether_tx( rt_device_t dev, struct pbuf* p){	struct pbuf* q;	if (AT91_EMAC->EMAC_TSR & AT91C_EMAC_BNQ)	{		rt_uint8_t *ptr;		/* check length */		if(p->tot_len >= MAX_RBUFF_SZ) return -RT_ERROR;		ptr = &at91_dev->tx_buf[0];		for (q = p; q != NULL; q = q->next)		{			rt_memcpy(ptr, q->payload, q->len);			ptr += q->len;		}		/* Set address of the data in the Transmit Address register */		AT91_EMAC->EMAC_TAR = (AT91_REG)&at91_dev->tx_buf;		/* Set length of the packet in the Transmit Control register */		AT91_EMAC->EMAC_TCR = p->tot_len;	}	else	{		rt_kprintf("at91_ether.c: at91ether_tx() called, but device is busy!\n");		return -RT_ERROR;	}	return 0;}/* * Write */rt_err_t at91ether_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size){	return -RT_ENOSYS;}/* * Extract received frame from buffer descriptors and sent to upper layers. * (Called in Eth Thread) */struct pbuf *at91ether_rx(rt_device_t dev){	struct pbuf *p = RT_NULL;	if ((at91_dev->descriptors[at91_dev->current_rb_index].addr & EMAC_DESC_DONE))	{		struct pbuf* q;		rt_uint32_t pkt_len;		rt_uint8_t* recv_buff;		recv_buff = &(at91_dev->rx_buf[at91_dev->current_rb_index][0]);		pkt_len   = at91_dev->descriptors[at91_dev->current_rb_index].size & 0x7ff;	/* Length of frame including FCS */		/* allocate pbuf from lwip mem pool */		p = pbuf_alloc(PBUF_LINK, pkt_len, PBUF_POOL);		if(p != RT_NULL)		{			for(q = p; q != RT_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.				 */				rt_memcpy(q->payload, recv_buff, q->len);				recv_buff += q->len;			}		}		else		{			rt_kprintf("no memory in pbuf\n");			/* enable rx */			AT91_EMAC->EMAC_CTL |= AT91C_EMAC_RE;		}	}	else	{		struct rbf_t* rb = (struct rbf_t*)AT91_EMAC->EMAC_RBQP;		/* reset address */		if (at91_dev->descriptors[at91_dev->current_rb_index].addr != 			(unsigned int) &(at91_dev->rx_buf[at91_dev->current_rb_index]))		{			rt_kprintf("bad descriptor: 0x%08x\n", at91_dev->descriptors[at91_dev->current_rb_index].addr);		}				at91_dev->descriptors[at91_dev->current_rb_index].addr = (unsigned int) &(at91_dev->rx_buf[at91_dev->current_rb_index]);		if (at91_dev->current_rb_index == MAX_RX_DESCR-1)		{			/* set wrap */			at91_dev->descriptors[at91_dev->current_rb_index].addr |= EMAC_DESC_WRAP;		}		/* reset buffer index */		at91_dev->current_rb_index = ((rt_uint32_t)rb - (rt_uint32_t)&at91_dev->descriptors[0])/ sizeof(struct rbf_t);		if (at91_dev->current_rb_index < 0 || at91_dev->current_rb_index > MAX_RX_DESCR - 1)		{			/* Program address of descriptor list in Rx Buffer Queue register */			AT91_EMAC->EMAC_RBQP = (AT91_REG) &at91_dev->descriptors;			at91_dev->current_rb_index = 0;		}		/* enable rx */		AT91_EMAC->EMAC_CTL |= AT91C_EMAC_RE;		return RT_NULL;	}	/* reset address */	at91_dev->descriptors[at91_dev->current_rb_index].addr = (unsigned int) &(at91_dev->rx_buf[at91_dev->current_rb_index]);	if (at91_dev->current_rb_index == MAX_RX_DESCR-1)	{		/* set wrap */		at91_dev->descriptors[at91_dev->current_rb_index].addr |= EMAC_DESC_WRAP;		at91_dev->current_rb_index = 0;			/* wrap after last buffer */	}	else at91_dev->current_rb_index++;	return p;}/* * MAC interrupt handler */static void at91ether_isr(int irq){	rt_uint32_t intstatus;	/* MAC Interrupt Status register indicates what interrupts are pending.	   It is automatically cleared once read. */	intstatus = AT91_EMAC->EMAC_ISR;	if (intstatus & (AT91C_EMAC_RCOM | AT91C_EMAC_ROVR | AT91C_EMAC_RBNA))	{		/* Receive complete */		/* disable rx */		AT91_EMAC->EMAC_CTL &= ~AT91C_EMAC_RE;		eth_device_ready((struct eth_device*)&(at91_dev->parent));	}	if (intstatus & AT91C_EMAC_TCOM)	{		/* Transmit complete */		/* The TCOM bit is set even if the transmission failed. */		if (intstatus & (AT91C_EMAC_TUND | AT91C_EMAC_RTRY));	}}rt_err_t at91ether_init(rt_device_t dev){	int i, phy_address = 0;	/* reset current rb index */	at91_dev->current_rb_index = 0;	/* Configure the hardware - RMII vs MII mode */#ifdef CONFIG_AT91_ETHER_RMII	AT91_CfgPIO_EMAC_RMII();#else	AT91_CfgPIO_EMAC_MII();#endif	/* enable Peripheral clock */	AT91_SYS->PMC_PCER = 1 << AT91C_ID_EMAC;#ifdef CONFIG_AT91_ETHER_RMII	AT91_EMAC->EMAC_CFG = AT91C_EMAC_RMII|AT91C_EMAC_CLK_HCLK_32|AT91C_EMAC_BIG|AT91C_EMAC_CAF;#else	AT91_EMAC->EMAC_CFG = AT91C_EMAC_CLK_HCLK_32|AT91C_EMAC_BIG|AT91C_EMAC_CAF;#endif	/* Disable all multicast mode */	AT91_EMAC->EMAC_HSH = 0;	AT91_EMAC->EMAC_HSL = 0;	/* detect phy address */	while (phy_address < 32)	{		rt_uint32_t phyid1, phyid2;		AT91_EMAC->EMAC_CTL |= AT91C_EMAC_MPE;	/* enable management port */		read_phy(phy_address, MII_PHYSID1, &phyid1);		read_phy(phy_address, MII_PHYSID2, &phyid2);		AT91_EMAC->EMAC_CTL &= ~AT91C_EMAC_MPE;	/* disable management port */		if (((phyid1 << 16) | (phyid2 &0xfff0)) == MII_DM9161_ID)		{			at91_dev->phy_addr = phy_address;			break;		}		phy_address ++;	}	if (phy_address == 32)	{		rt_kprintf("no DM9161 found, AT91 EMAC init failed\n");		return -RT_ERROR;	}	/* enable PHY interrupt */	enable_phyirq(at91_dev);	/* initialize and start the Receiver and Transmit subsystems */	for (i = 0; i < MAX_RX_DESCR; i++)	{		at91_dev->descriptors[i].addr = (unsigned int) &(at91_dev->rx_buf[i]);		at91_dev->descriptors[i].size = 0;	}	/* set wrap */	at91_dev->descriptors[i-1].addr |= EMAC_DESC_WRAP;	/* program address of descriptor list in Rx Buffer Queue register */	AT91_EMAC->EMAC_RBQP = (AT91_REG) &at91_dev->descriptors;	/* setup phy */	/* Determine current link speed */	AT91_EMAC->EMAC_CTL |= AT91C_EMAC_MPE;	/* enable management port */	update_linkspeed(at91_dev);	AT91_EMAC->EMAC_CTL &= ~AT91C_EMAC_MPE;	/* disable management port */	/* Enable receive, transmit and clear  statistics*/	AT91_EMAC->EMAC_CTL |= (AT91C_EMAC_RE | AT91C_EMAC_TE | AT91C_EMAC_CSR);	/* set interrupt */	AT91_SYS->AIC_SMR[AT91C_ID_EMAC] = (0x03| AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE);	/* interrupt enable */	AT91_EMAC->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_RBNA |		AT91C_EMAC_TCOM | AT91C_EMAC_ROVR;	/* Install the interrupt handler */	rt_hw_interrupt_install(AT91C_ID_EMAC, at91ether_isr, 0);	rt_hw_interrupt_umask(AT91C_ID_EMAC);	return RT_EOK;}int at91ether_register(char *name){	rt_err_t result;	/* init rt-thread device interface */	at91_dev_entry.parent.parent.init		= at91ether_init;	at91_dev_entry.parent.parent.open		= at91ether_open;	at91_dev_entry.parent.parent.close		= at91ether_close;	at91_dev_entry.parent.parent.read		= at91ether_read;	at91_dev_entry.parent.parent.write		= at91ether_write;	at91_dev_entry.parent.parent.control	= at91ether_control;	at91_dev_entry.parent.eth_rx			= at91ether_rx;	at91_dev_entry.parent.eth_tx			= at91ether_tx;	/* Update MAC address */	get_mac_address(at91_dev);		/* Get ethernet address and store it in dev->dev_addr */	update_mac_address(at91_dev);	/* Program ethernet address into MAC */	result = eth_device_init(&(at91_dev->parent), (char*)name);	RT_ASSERT(result == RT_EOK);	return RT_EOK;}

⌨️ 快捷键说明

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