📄 at91_ether.c
字号:
* 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 + -