add emac driver for at91sam9260
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1384 bbd45198-f89e-11dd-88c7-29a3b14d5316
This commit is contained in:
parent
ea009132a2
commit
fd963d847a
|
@ -0,0 +1,686 @@
|
|||
/*
|
||||
* File : macb.c
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006, RT-Thread Develop Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-03-18 weety first version
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
#include <netif/ethernetif.h>
|
||||
#include "lwipopts.h"
|
||||
#include <at91sam926x.h>
|
||||
#include "macb.h"
|
||||
|
||||
#define CONFIG_RMII
|
||||
|
||||
#define MACB_RX_BUFFER_SIZE 4096*4
|
||||
#define MACB_RX_RING_SIZE (MACB_RX_BUFFER_SIZE / 128)
|
||||
#define MACB_TX_RING_SIZE 16
|
||||
#define MACB_TX_TIMEOUT 1000
|
||||
#define MACB_AUTONEG_TIMEOUT 5000000
|
||||
#define MACB_LINK_TIMEOUT 500000
|
||||
|
||||
|
||||
struct macb_dma_desc {
|
||||
rt_uint32_t addr;
|
||||
rt_uint32_t ctrl;
|
||||
};
|
||||
|
||||
#define RXADDR_USED 0x00000001
|
||||
#define RXADDR_WRAP 0x00000002
|
||||
|
||||
#define RXBUF_FRMLEN_MASK 0x00000fff
|
||||
#define RXBUF_FRAME_START 0x00004000
|
||||
#define RXBUF_FRAME_END 0x00008000
|
||||
#define RXBUF_TYPEID_MATCH 0x00400000
|
||||
#define RXBUF_ADDR4_MATCH 0x00800000
|
||||
#define RXBUF_ADDR3_MATCH 0x01000000
|
||||
#define RXBUF_ADDR2_MATCH 0x02000000
|
||||
#define RXBUF_ADDR1_MATCH 0x04000000
|
||||
#define RXBUF_BROADCAST 0x80000000
|
||||
|
||||
#define TXBUF_FRMLEN_MASK 0x000007ff
|
||||
#define TXBUF_FRAME_END 0x00008000
|
||||
#define TXBUF_NOCRC 0x00010000
|
||||
#define TXBUF_EXHAUSTED 0x08000000
|
||||
#define TXBUF_UNDERRUN 0x10000000
|
||||
#define TXBUF_MAXRETRY 0x20000000
|
||||
#define TXBUF_WRAP 0x40000000
|
||||
#define TXBUF_USED 0x80000000
|
||||
|
||||
#define MACB_RX_INT_FLAGS (MACB_BIT(RCOMP) | MACB_BIT(RXUBR) \
|
||||
| MACB_BIT(ISR_ROVR))
|
||||
|
||||
|
||||
#define MAX_ADDR_LEN 6
|
||||
struct rt_macb_eth
|
||||
{
|
||||
/* inherit from ethernet device */
|
||||
struct eth_device parent;
|
||||
|
||||
void *regs;
|
||||
|
||||
unsigned int rx_tail;
|
||||
unsigned int tx_head;
|
||||
unsigned int tx_tail;
|
||||
|
||||
void *rx_buffer;
|
||||
void *tx_buffer;
|
||||
struct macb_dma_desc *rx_ring;
|
||||
struct macb_dma_desc *tx_ring;
|
||||
|
||||
unsigned long rx_buffer_dma;
|
||||
unsigned long rx_ring_dma;
|
||||
unsigned long tx_ring_dma;
|
||||
|
||||
/* interface address info. */
|
||||
rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
|
||||
unsigned short phy_addr;
|
||||
};
|
||||
static struct rt_macb_eth macb_device;
|
||||
static struct rt_semaphore sem_ack, sem_lock;
|
||||
|
||||
static void udelay(rt_uint32_t us)
|
||||
{
|
||||
rt_uint32_t len;
|
||||
for (;us > 0; us --)
|
||||
for (len = 0; len < 10; len++ );
|
||||
}
|
||||
|
||||
static void rt_macb_isr(int irq)
|
||||
{
|
||||
struct rt_macb_eth *macb = &macb_device;
|
||||
rt_device_t dev = &(macb->parent.parent);
|
||||
rt_uint32_t status, rsr, tsr;
|
||||
|
||||
//rt_kprintf("%s:irq enter\n", __func__);
|
||||
status = macb_readl(macb, ISR);
|
||||
|
||||
while (status) {
|
||||
|
||||
if (status & MACB_RX_INT_FLAGS) {
|
||||
//rt_kprintf("macb recv isr\n");
|
||||
//macb_writel(macb, IDR, MACB_RX_INT_FLAGS);
|
||||
rsr = macb_readl(macb, RSR);
|
||||
macb_writel(macb, RSR, rsr);
|
||||
/* a frame has been received */
|
||||
eth_device_ready(&(macb_device.parent));
|
||||
|
||||
}
|
||||
|
||||
if (status & (MACB_BIT(TCOMP) | MACB_BIT(ISR_TUND) |
|
||||
MACB_BIT(ISR_RLE)))
|
||||
{
|
||||
//rt_kprintf("macb tx complete\n");
|
||||
tsr = macb_readl(macb, TSR);
|
||||
macb_writel(macb, TSR, tsr);
|
||||
/* One packet sent complete */
|
||||
rt_sem_release(&sem_ack);
|
||||
}
|
||||
//macb_tx(bp);
|
||||
|
||||
/*
|
||||
* Link change detection isn't possible with RMII, so we'll
|
||||
* add that if/when we get our hands on a full-blown MII PHY.
|
||||
*/
|
||||
|
||||
if (status & MACB_BIT(HRESP)) {
|
||||
/*
|
||||
* TODO: Reset the hardware, and maybe move the printk
|
||||
* to a lower-priority context as well (work queue?)
|
||||
*/
|
||||
rt_kprintf("%s: DMA bus error: HRESP not OK\n",
|
||||
dev->parent.name);
|
||||
}
|
||||
|
||||
status = macb_readl(macb, ISR);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
static void macb_mdio_write(struct rt_macb_eth *macb, rt_uint8_t reg, rt_uint16_t value)
|
||||
{
|
||||
unsigned long netctl;
|
||||
unsigned long netstat;
|
||||
unsigned long frame;
|
||||
|
||||
netctl = macb_readl(macb, NCR);
|
||||
netctl |= MACB_BIT(MPE);
|
||||
macb_writel(macb, NCR, netctl);
|
||||
|
||||
frame = (MACB_BF(SOF, 1)
|
||||
| MACB_BF(RW, 1)
|
||||
| MACB_BF(PHYA, macb->phy_addr)
|
||||
| MACB_BF(REGA, reg)
|
||||
| MACB_BF(CODE, 2)
|
||||
| MACB_BF(DATA, value));
|
||||
macb_writel(macb, MAN, frame);
|
||||
|
||||
do {
|
||||
netstat = macb_readl(macb, NSR);
|
||||
} while (!(netstat & MACB_BIT(IDLE)));
|
||||
|
||||
netctl = macb_readl(macb, NCR);
|
||||
netctl &= ~MACB_BIT(MPE);
|
||||
macb_writel(macb, NCR, netctl);
|
||||
}
|
||||
|
||||
static rt_uint16_t macb_mdio_read(struct rt_macb_eth *macb, rt_uint8_t reg)
|
||||
{
|
||||
unsigned long netctl;
|
||||
unsigned long netstat;
|
||||
unsigned long frame;
|
||||
|
||||
netctl = macb_readl(macb, NCR);
|
||||
netctl |= MACB_BIT(MPE);
|
||||
macb_writel(macb, NCR, netctl);
|
||||
|
||||
frame = (MACB_BF(SOF, 1)
|
||||
| MACB_BF(RW, 2)
|
||||
| MACB_BF(PHYA, macb->phy_addr)
|
||||
| MACB_BF(REGA, reg)
|
||||
| MACB_BF(CODE, 2));
|
||||
macb_writel(macb, MAN, frame);
|
||||
|
||||
do {
|
||||
netstat = macb_readl(macb, NSR);
|
||||
} while (!(netstat & MACB_BIT(IDLE)));
|
||||
|
||||
frame = macb_readl(macb, MAN);
|
||||
|
||||
netctl = macb_readl(macb, NCR);
|
||||
netctl &= ~MACB_BIT(MPE);
|
||||
macb_writel(macb, NCR, netctl);
|
||||
|
||||
return MACB_BFEXT(DATA, frame);
|
||||
}
|
||||
|
||||
static void macb_phy_reset(rt_device_t dev)
|
||||
{
|
||||
struct rt_macb_eth *macb = dev->user_data;;
|
||||
int i;
|
||||
rt_uint16_t status, adv;
|
||||
|
||||
adv = ADVERTISE_CSMA | ADVERTISE_ALL;
|
||||
macb_mdio_write(macb, MII_ADVERTISE, adv);
|
||||
rt_kprintf("%s: Starting autonegotiation...\n", dev->parent.name);
|
||||
macb_mdio_write(macb, MII_BMCR, (BMCR_ANENABLE
|
||||
| BMCR_ANRESTART));
|
||||
|
||||
for (i = 0; i < MACB_AUTONEG_TIMEOUT / 100; i++) {
|
||||
status = macb_mdio_read(macb, MII_BMSR);
|
||||
if (status & BMSR_ANEGCOMPLETE)
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (status & BMSR_ANEGCOMPLETE)
|
||||
rt_kprintf("%s: Autonegotiation complete\n", dev->parent.name);
|
||||
else
|
||||
rt_kprintf("%s: Autonegotiation timed out (status=0x%04x)\n",
|
||||
dev->parent.name, status);
|
||||
}
|
||||
|
||||
|
||||
static int macb_phy_init(rt_device_t dev)
|
||||
{
|
||||
//struct eth_device *netdev = &macb->netdev;
|
||||
struct rt_macb_eth *macb = dev->user_data;
|
||||
rt_uint32_t ncfgr;
|
||||
rt_uint16_t phy_id, status, adv, lpa;
|
||||
int media, speed, duplex;
|
||||
int i;
|
||||
|
||||
/* Check if the PHY is up to snuff... */
|
||||
phy_id = macb_mdio_read(macb, MII_PHYSID1);
|
||||
if (phy_id == 0xffff) {
|
||||
rt_kprintf("%s: No PHY present\n", dev->parent.name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = macb_mdio_read(macb, MII_BMSR);
|
||||
if (!(status & BMSR_LSTATUS)) {
|
||||
/* Try to re-negotiate if we don't have link already. */
|
||||
macb_phy_reset(dev);
|
||||
|
||||
for (i = 0; i < MACB_LINK_TIMEOUT / 100; i++) { //modified by luohui@2009-11-27 CFG_MACB_AUTONEG_TIMEOUT
|
||||
status = macb_mdio_read(macb, MII_BMSR);
|
||||
if (status & BMSR_LSTATUS)
|
||||
break;
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(status & BMSR_LSTATUS)) {
|
||||
rt_kprintf("%s: link down (status: 0x%04x)\n",
|
||||
dev->parent.name, status);
|
||||
return 0;
|
||||
} else {
|
||||
adv = macb_mdio_read(macb, MII_ADVERTISE);
|
||||
lpa = macb_mdio_read(macb, MII_LPA);
|
||||
media = mii_nway_result(lpa & adv);
|
||||
speed = (media & (ADVERTISE_100FULL | ADVERTISE_100HALF)
|
||||
? 1 : 0);
|
||||
duplex = (media & ADVERTISE_FULL) ? 1 : 0;
|
||||
rt_kprintf("%s: link up, %sMbps %s-duplex (lpa: 0x%04x)\n",
|
||||
dev->parent.name,
|
||||
speed ? "100" : "10",
|
||||
duplex ? "full" : "half",
|
||||
lpa);
|
||||
|
||||
ncfgr = macb_readl(macb, NCFGR);
|
||||
ncfgr &= ~(MACB_BIT(SPD) | MACB_BIT(FD));
|
||||
if (speed)
|
||||
ncfgr |= MACB_BIT(SPD);
|
||||
if (duplex)
|
||||
ncfgr |= MACB_BIT(FD);
|
||||
macb_writel(macb, NCFGR, ncfgr);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* RT-Thread Device Interface */
|
||||
/* initialize the interface */
|
||||
|
||||
static rt_err_t rt_macb_init(rt_device_t dev)
|
||||
{
|
||||
struct rt_macb_eth *macb = dev->user_data;
|
||||
unsigned long paddr;
|
||||
rt_uint32_t hwaddr_bottom;
|
||||
rt_uint16_t hwaddr_top;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* macb_halt should have been called at some point before now,
|
||||
* so we'll assume the controller is idle.
|
||||
*/
|
||||
|
||||
/* initialize DMA descriptors */
|
||||
paddr = macb->rx_buffer_dma;
|
||||
for (i = 0; i < MACB_RX_RING_SIZE; i++) {
|
||||
if (i == (MACB_RX_RING_SIZE - 1))
|
||||
paddr |= RXADDR_WRAP;
|
||||
macb->rx_ring[i].addr = paddr;
|
||||
macb->rx_ring[i].ctrl = 0;
|
||||
paddr += 128;
|
||||
}
|
||||
for (i = 0; i < MACB_TX_RING_SIZE; i++) {
|
||||
macb->tx_ring[i].addr = 0;
|
||||
if (i == (MACB_TX_RING_SIZE - 1))
|
||||
macb->tx_ring[i].ctrl = TXBUF_USED | TXBUF_WRAP;
|
||||
else
|
||||
macb->tx_ring[i].ctrl = TXBUF_USED;
|
||||
}
|
||||
macb->rx_tail = macb->tx_head = macb->tx_tail = 0;
|
||||
|
||||
macb_writel(macb, RBQP, macb->rx_ring_dma);
|
||||
macb_writel(macb, TBQP, macb->tx_ring_dma);
|
||||
|
||||
/* set hardware address */
|
||||
//hwaddr_bottom = cpu_to_le32(*((u32 *)netdev->enetaddr));
|
||||
hwaddr_bottom = (*((rt_uint32_t *)macb->dev_addr));
|
||||
macb_writel(macb, SA1B, hwaddr_bottom);
|
||||
//hwaddr_top = cpu_to_le16(*((u16 *)(netdev->enetaddr + 4)));
|
||||
hwaddr_top = (*((rt_uint16_t *)(macb->dev_addr + 4)));
|
||||
macb_writel(macb, SA1T, hwaddr_top);
|
||||
|
||||
|
||||
/* choose RMII or MII mode. This depends on the board */
|
||||
#ifdef CONFIG_RMII
|
||||
#if defined(CONFIG_AVR32)
|
||||
macb_writel(macb, USRIO, 0);
|
||||
#else
|
||||
macb_writel(macb, USRIO, MACB_BIT(RMII) | MACB_BIT(CLKEN));
|
||||
#endif
|
||||
#else
|
||||
#if defined(CONFIG_AVR32)
|
||||
macb_writel(macb, USRIO, MACB_BIT(MII));
|
||||
#else
|
||||
macb_writel(macb, USRIO, MACB_BIT(CLKEN));
|
||||
#endif
|
||||
#endif /* CONFIG_RMII */
|
||||
|
||||
if (!macb_phy_init(dev))
|
||||
return -RT_ERROR;
|
||||
|
||||
/* Enable TX and RX */
|
||||
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(MPE));
|
||||
|
||||
/* Enable interrupts */
|
||||
macb_writel(macb, IER, (MACB_BIT(RCOMP)
|
||||
| MACB_BIT(RXUBR)
|
||||
| MACB_BIT(ISR_TUND)
|
||||
| MACB_BIT(ISR_RLE)
|
||||
| MACB_BIT(TXERR)
|
||||
| MACB_BIT(TCOMP)
|
||||
| MACB_BIT(ISR_ROVR)
|
||||
| MACB_BIT(HRESP)));
|
||||
|
||||
/* instal interrupt */
|
||||
rt_hw_interrupt_install(AT91SAM9260_ID_EMAC, rt_macb_isr, RT_NULL);
|
||||
rt_hw_interrupt_umask(AT91SAM9260_ID_EMAC);
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_macb_open(rt_device_t dev, rt_uint16_t oflag)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_err_t rt_macb_close(rt_device_t dev)
|
||||
{
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static rt_size_t rt_macb_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
|
||||
{
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_size_t rt_macb_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
|
||||
{
|
||||
rt_set_errno(-RT_ENOSYS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rt_err_t rt_macb_control(rt_device_t dev, rt_uint8_t cmd, void *args)
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case NIOCTL_GADDR:
|
||||
/* get mac address */
|
||||
if(args) rt_memcpy(args, macb_device.dev_addr, 6);
|
||||
else return -RT_ERROR;
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
/* ethernet device interface */
|
||||
/* transmit packet. */
|
||||
rt_err_t rt_macb_tx( rt_device_t dev, struct pbuf* p)
|
||||
{
|
||||
struct rt_macb_eth *macb = dev->user_data;
|
||||
struct pbuf* q;
|
||||
rt_uint32_t len;
|
||||
rt_uint8_t* bufptr, *buf = RT_NULL;
|
||||
unsigned long paddr, ctrl;
|
||||
unsigned int tx_head = macb->tx_head;
|
||||
int i;
|
||||
|
||||
/* lock macb device */
|
||||
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
|
||||
//rt_kprintf("macb tx enter, packetlen=%d\n", p->tot_len);
|
||||
buf = rt_malloc(p->tot_len);
|
||||
if (!buf) {
|
||||
rt_kprintf("%s:alloc buf failed\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
bufptr = buf;
|
||||
|
||||
|
||||
for (q = p; q != NULL; q = q->next)
|
||||
{
|
||||
//len = q->len;
|
||||
//paddr = (unsigned long)q->payload;
|
||||
memcpy(bufptr, q->payload, q->len);
|
||||
bufptr += q->len;
|
||||
|
||||
/* write data to device */
|
||||
/*ctrl = len & TXBUF_FRMLEN_MASK;
|
||||
ctrl |= TXBUF_FRAME_END;
|
||||
if (tx_head == (MACB_TX_RING_SIZE - 1)) {
|
||||
ctrl |= TXBUF_WRAP;
|
||||
macb->tx_head = 0;
|
||||
} else
|
||||
macb->tx_head++;
|
||||
|
||||
macb->tx_ring[tx_head].ctrl = ctrl;
|
||||
macb->tx_ring[tx_head].addr = paddr;
|
||||
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));*/
|
||||
|
||||
/*
|
||||
* I guess this is necessary because the networking core may
|
||||
* re-use the transmit buffer as soon as we return...
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
ctrl = p->tot_len & TXBUF_FRMLEN_MASK;
|
||||
ctrl |= TXBUF_FRAME_END;
|
||||
if (tx_head == (MACB_TX_RING_SIZE - 1)) {
|
||||
ctrl |= TXBUF_WRAP;
|
||||
macb->tx_head = 0;
|
||||
} else
|
||||
macb->tx_head++;
|
||||
|
||||
macb->tx_ring[tx_head].ctrl = ctrl;
|
||||
macb->tx_ring[tx_head].addr = (rt_uint32_t)buf;
|
||||
macb_writel(macb, NCR, MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
|
||||
//rt_uint32_t netcr = macb_readl(macb, NCR); //e0: DMA bus error: HRESP not OK
|
||||
//rt_kprintf("NCR = 0x%08x\n");
|
||||
//macb_writel(macb, NCR, netcr | MACB_BIT(TE) | MACB_BIT(RE) | MACB_BIT(TSTART));
|
||||
|
||||
|
||||
/* unlock macb device */
|
||||
rt_sem_release(&sem_lock);
|
||||
|
||||
/* wait ack */
|
||||
rt_sem_take(&sem_ack, RT_WAITING_FOREVER);
|
||||
rt_free(buf);
|
||||
buf == RT_NULL;
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
|
||||
static void reclaim_rx_buffers(struct rt_macb_eth *macb,
|
||||
unsigned int new_tail)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
i = macb->rx_tail;
|
||||
while (i > new_tail) {
|
||||
macb->rx_ring[i].addr &= ~RXADDR_USED;
|
||||
i++;
|
||||
if (i > MACB_RX_RING_SIZE)
|
||||
i = 0;
|
||||
}
|
||||
|
||||
while (i < new_tail) {
|
||||
macb->rx_ring[i].addr &= ~RXADDR_USED;
|
||||
i++;
|
||||
}
|
||||
|
||||
//barrier();
|
||||
macb->rx_tail = new_tail;
|
||||
}
|
||||
|
||||
/* reception packet. */
|
||||
struct pbuf *rt_macb_rx(rt_device_t dev)
|
||||
{
|
||||
struct rt_macb_eth *macb = dev->user_data;
|
||||
struct pbuf* p = RT_NULL;
|
||||
rt_uint32_t len;
|
||||
unsigned int rx_tail = macb->rx_tail;
|
||||
void *buffer;
|
||||
//int length;
|
||||
int wrapped = 0;
|
||||
rt_uint32_t status;
|
||||
|
||||
//rt_uint8_t* data;
|
||||
struct pbuf* q;
|
||||
rt_uint8_t *buf = RT_NULL;
|
||||
//rt_kprintf("macb rx enter\n");
|
||||
|
||||
/* lock macb device */
|
||||
rt_sem_take(&sem_lock, RT_WAITING_FOREVER);
|
||||
//rt_kprintf("macb rx enter2\n");
|
||||
|
||||
for (;;) {
|
||||
if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED))
|
||||
break;
|
||||
|
||||
status = macb->rx_ring[rx_tail].ctrl;
|
||||
if (status & RXBUF_FRAME_START) {
|
||||
if (rx_tail != macb->rx_tail)
|
||||
reclaim_rx_buffers(macb, rx_tail);
|
||||
wrapped = 0;
|
||||
}
|
||||
|
||||
if (status & RXBUF_FRAME_END) {
|
||||
buffer = macb->rx_buffer + 128 * macb->rx_tail;
|
||||
len = status & RXBUF_FRMLEN_MASK;
|
||||
//rt_kprintf("%s:recv %d bytes\n", __func__, len);
|
||||
p = pbuf_alloc(PBUF_LINK, len, PBUF_RAM);
|
||||
if (!p)
|
||||
{
|
||||
rt_kprintf("alloc pbuf failed\n");
|
||||
break;
|
||||
}
|
||||
if (wrapped) {
|
||||
unsigned int headlen, taillen;
|
||||
buf = rt_malloc(len);
|
||||
if (!buf)
|
||||
{
|
||||
rt_kprintf("%s:alloc memory failed\n", __func__);
|
||||
pbuf_free(p);
|
||||
p = RT_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
headlen = 128 * (MACB_RX_RING_SIZE
|
||||
- macb->rx_tail);
|
||||
taillen = len - headlen;
|
||||
memcpy((void *)buf,
|
||||
buffer, headlen);
|
||||
memcpy((void *)buf + headlen,
|
||||
macb->rx_buffer, taillen);
|
||||
buffer = (void *)buf;
|
||||
for (q = p; q != RT_NULL; q= q->next)
|
||||
{
|
||||
/* read data from device */
|
||||
memcpy((void *)q->payload, buffer, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
rt_free(buf);
|
||||
buf = RT_NULL;
|
||||
} else {
|
||||
for (q = p; q != RT_NULL; q= q->next)
|
||||
{
|
||||
/* read data from device */
|
||||
memcpy((void *)q->payload, buffer, q->len);
|
||||
buffer += q->len;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//NetReceive(buffer, length);
|
||||
/* allocate buffer */
|
||||
|
||||
if (++rx_tail >= MACB_RX_RING_SIZE)
|
||||
rx_tail = 0;
|
||||
reclaim_rx_buffers(macb, rx_tail);
|
||||
break;
|
||||
} else {
|
||||
if (++rx_tail >= MACB_RX_RING_SIZE) {
|
||||
wrapped = 1;
|
||||
rx_tail = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unlock macb device */
|
||||
rt_sem_release(&sem_lock);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void macb_gpio_init()
|
||||
{
|
||||
/* Pins used for MII and RMII */
|
||||
at91_sys_write(AT91_PIOA + PIO_PDR, (1 << 19)|(1 << 17)|(1 << 14)|(1 << 15)|(1 << 18)|(1 << 16)|(1 << 12)|(1 << 13)|(1 << 21)|(1 << 20));
|
||||
at91_sys_write(AT91_PIOA + PIO_ASR, (1 << 19)|(1 << 17)|(1 << 14)|(1 << 15)|(1 << 18)|(1 << 16)|(1 << 12)|(1 << 13)|(1 << 21)|(1 << 20));
|
||||
}
|
||||
|
||||
void macb_initialize()
|
||||
{
|
||||
struct rt_macb_eth *macb = &macb_device;
|
||||
unsigned long macb_hz;
|
||||
rt_uint32_t ncfgr;
|
||||
|
||||
macb->rx_buffer = rt_malloc(MACB_RX_BUFFER_SIZE);
|
||||
macb->rx_ring = rt_malloc(MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc));
|
||||
macb->tx_ring = rt_malloc(MACB_TX_RING_SIZE * sizeof(struct macb_dma_desc));
|
||||
|
||||
macb->rx_buffer_dma = (unsigned long)macb->rx_buffer;
|
||||
macb->rx_ring_dma = (unsigned long)macb->rx_ring;
|
||||
macb->tx_ring_dma = (unsigned long)macb->tx_ring;
|
||||
|
||||
macb->regs = (void *)AT91SAM9260_BASE_EMAC;
|
||||
macb->phy_addr = 0x00;
|
||||
|
||||
/*
|
||||
* Do some basic initialization so that we at least can talk
|
||||
* to the PHY
|
||||
*/
|
||||
macb_hz = clk_get_rate(clk_get("mck"));
|
||||
if (macb_hz < 20000000)
|
||||
ncfgr = MACB_BF(CLK, MACB_CLK_DIV8);
|
||||
else if (macb_hz < 40000000)
|
||||
ncfgr = MACB_BF(CLK, MACB_CLK_DIV16);
|
||||
else if (macb_hz < 80000000)
|
||||
ncfgr = MACB_BF(CLK, MACB_CLK_DIV32);
|
||||
else
|
||||
ncfgr = MACB_BF(CLK, MACB_CLK_DIV64);
|
||||
|
||||
macb_writel(macb, NCFGR, ncfgr);
|
||||
}
|
||||
|
||||
void rt_hw_macb_init()
|
||||
{
|
||||
at91_sys_write(AT91_PMC + AT91_PMC_PCER, 1 << AT91SAM9260_ID_EMAC); //enable macb clock
|
||||
macb_gpio_init();
|
||||
macb_initialize();
|
||||
rt_sem_init(&sem_ack, "tx_ack", 1, RT_IPC_FLAG_FIFO);
|
||||
rt_sem_init(&sem_lock, "eth_lock", 1, RT_IPC_FLAG_FIFO);
|
||||
|
||||
macb_device.dev_addr[0] = 0x00;
|
||||
macb_device.dev_addr[1] = 0x60;
|
||||
macb_device.dev_addr[2] = 0x6E;
|
||||
macb_device.dev_addr[3] = 0x11;
|
||||
macb_device.dev_addr[4] = 0x22;
|
||||
macb_device.dev_addr[5] = 0x33;
|
||||
|
||||
macb_device.parent.parent.init = rt_macb_init;
|
||||
macb_device.parent.parent.open = rt_macb_open;
|
||||
macb_device.parent.parent.close = rt_macb_close;
|
||||
macb_device.parent.parent.read = rt_macb_read;
|
||||
macb_device.parent.parent.write = rt_macb_write;
|
||||
macb_device.parent.parent.control = rt_macb_control;
|
||||
macb_device.parent.parent.user_data = &macb_device;
|
||||
|
||||
macb_device.parent.eth_rx = rt_macb_rx;
|
||||
macb_device.parent.eth_tx = rt_macb_tx;
|
||||
|
||||
eth_device_init(&(macb_device.parent), "e0");
|
||||
//eth_system_device_init();
|
||||
//set_if("192.168.1.30", "192.168.1.1", "255.255.255.0");
|
||||
/* instal interrupt */
|
||||
//rt_hw_interrupt_install(AT91SAM9260_ID_EMAC, rt_macb_isr, RT_NULL);
|
||||
//rt_hw_interrupt_umask(AT91SAM9260_ID_EMAC);
|
||||
}
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* File : macb.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006, RT-Thread Develop Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-03-18 weety first version
|
||||
*/
|
||||
#ifndef _MACB_H
|
||||
#define _MACB_H
|
||||
#include <mii.h>
|
||||
|
||||
/* MACB register offsets */
|
||||
#define MACB_NCR 0x0000
|
||||
#define MACB_NCFGR 0x0004
|
||||
#define MACB_NSR 0x0008
|
||||
#define MACB_TSR 0x0014
|
||||
#define MACB_RBQP 0x0018
|
||||
#define MACB_TBQP 0x001c
|
||||
#define MACB_RSR 0x0020
|
||||
#define MACB_ISR 0x0024
|
||||
#define MACB_IER 0x0028
|
||||
#define MACB_IDR 0x002c
|
||||
#define MACB_IMR 0x0030
|
||||
#define MACB_MAN 0x0034
|
||||
#define MACB_PTR 0x0038
|
||||
#define MACB_PFR 0x003c
|
||||
#define MACB_FTO 0x0040
|
||||
#define MACB_SCF 0x0044
|
||||
#define MACB_MCF 0x0048
|
||||
#define MACB_FRO 0x004c
|
||||
#define MACB_FCSE 0x0050
|
||||
#define MACB_ALE 0x0054
|
||||
#define MACB_DTF 0x0058
|
||||
#define MACB_LCOL 0x005c
|
||||
#define MACB_EXCOL 0x0060
|
||||
#define MACB_TUND 0x0064
|
||||
#define MACB_CSE 0x0068
|
||||
#define MACB_RRE 0x006c
|
||||
#define MACB_ROVR 0x0070
|
||||
#define MACB_RSE 0x0074
|
||||
#define MACB_ELE 0x0078
|
||||
#define MACB_RJA 0x007c
|
||||
#define MACB_USF 0x0080
|
||||
#define MACB_STE 0x0084
|
||||
#define MACB_RLE 0x0088
|
||||
#define MACB_TPF 0x008c
|
||||
#define MACB_HRB 0x0090
|
||||
#define MACB_HRT 0x0094
|
||||
#define MACB_SA1B 0x0098
|
||||
#define MACB_SA1T 0x009c
|
||||
#define MACB_SA2B 0x00a0
|
||||
#define MACB_SA2T 0x00a4
|
||||
#define MACB_SA3B 0x00a8
|
||||
#define MACB_SA3T 0x00ac
|
||||
#define MACB_SA4B 0x00b0
|
||||
#define MACB_SA4T 0x00b4
|
||||
#define MACB_TID 0x00b8
|
||||
#define MACB_TPQ 0x00bc
|
||||
#define MACB_USRIO 0x00c0
|
||||
#define MACB_WOL 0x00c4
|
||||
|
||||
/* Bitfields in NCR */
|
||||
#define MACB_LB_OFFSET 0
|
||||
#define MACB_LB_SIZE 1
|
||||
#define MACB_LLB_OFFSET 1
|
||||
#define MACB_LLB_SIZE 1
|
||||
#define MACB_RE_OFFSET 2
|
||||
#define MACB_RE_SIZE 1
|
||||
#define MACB_TE_OFFSET 3
|
||||
#define MACB_TE_SIZE 1
|
||||
#define MACB_MPE_OFFSET 4
|
||||
#define MACB_MPE_SIZE 1
|
||||
#define MACB_CLRSTAT_OFFSET 5
|
||||
#define MACB_CLRSTAT_SIZE 1
|
||||
#define MACB_INCSTAT_OFFSET 6
|
||||
#define MACB_INCSTAT_SIZE 1
|
||||
#define MACB_WESTAT_OFFSET 7
|
||||
#define MACB_WESTAT_SIZE 1
|
||||
#define MACB_BP_OFFSET 8
|
||||
#define MACB_BP_SIZE 1
|
||||
#define MACB_TSTART_OFFSET 9
|
||||
#define MACB_TSTART_SIZE 1
|
||||
#define MACB_THALT_OFFSET 10
|
||||
#define MACB_THALT_SIZE 1
|
||||
#define MACB_NCR_TPF_OFFSET 11
|
||||
#define MACB_NCR_TPF_SIZE 1
|
||||
#define MACB_TZQ_OFFSET 12
|
||||
#define MACB_TZQ_SIZE 1
|
||||
|
||||
/* Bitfields in NCFGR */
|
||||
#define MACB_SPD_OFFSET 0
|
||||
#define MACB_SPD_SIZE 1
|
||||
#define MACB_FD_OFFSET 1
|
||||
#define MACB_FD_SIZE 1
|
||||
#define MACB_BIT_RATE_OFFSET 2
|
||||
#define MACB_BIT_RATE_SIZE 1
|
||||
#define MACB_JFRAME_OFFSET 3
|
||||
#define MACB_JFRAME_SIZE 1
|
||||
#define MACB_CAF_OFFSET 4
|
||||
#define MACB_CAF_SIZE 1
|
||||
#define MACB_NBC_OFFSET 5
|
||||
#define MACB_NBC_SIZE 1
|
||||
#define MACB_NCFGR_MTI_OFFSET 6
|
||||
#define MACB_NCFGR_MTI_SIZE 1
|
||||
#define MACB_UNI_OFFSET 7
|
||||
#define MACB_UNI_SIZE 1
|
||||
#define MACB_BIG_OFFSET 8
|
||||
#define MACB_BIG_SIZE 1
|
||||
#define MACB_EAE_OFFSET 9
|
||||
#define MACB_EAE_SIZE 1
|
||||
#define MACB_CLK_OFFSET 10
|
||||
#define MACB_CLK_SIZE 2
|
||||
#define MACB_RTY_OFFSET 12
|
||||
#define MACB_RTY_SIZE 1
|
||||
#define MACB_PAE_OFFSET 13
|
||||
#define MACB_PAE_SIZE 1
|
||||
#define MACB_RBOF_OFFSET 14
|
||||
#define MACB_RBOF_SIZE 2
|
||||
#define MACB_RLCE_OFFSET 16
|
||||
#define MACB_RLCE_SIZE 1
|
||||
#define MACB_DRFCS_OFFSET 17
|
||||
#define MACB_DRFCS_SIZE 1
|
||||
#define MACB_EFRHD_OFFSET 18
|
||||
#define MACB_EFRHD_SIZE 1
|
||||
#define MACB_IRXFCS_OFFSET 19
|
||||
#define MACB_IRXFCS_SIZE 1
|
||||
|
||||
/* Bitfields in NSR */
|
||||
#define MACB_NSR_LINK_OFFSET 0
|
||||
#define MACB_NSR_LINK_SIZE 1
|
||||
#define MACB_MDIO_OFFSET 1
|
||||
#define MACB_MDIO_SIZE 1
|
||||
#define MACB_IDLE_OFFSET 2
|
||||
#define MACB_IDLE_SIZE 1
|
||||
|
||||
/* Bitfields in TSR */
|
||||
#define MACB_UBR_OFFSET 0
|
||||
#define MACB_UBR_SIZE 1
|
||||
#define MACB_COL_OFFSET 1
|
||||
#define MACB_COL_SIZE 1
|
||||
#define MACB_TSR_RLE_OFFSET 2
|
||||
#define MACB_TSR_RLE_SIZE 1
|
||||
#define MACB_TGO_OFFSET 3
|
||||
#define MACB_TGO_SIZE 1
|
||||
#define MACB_BEX_OFFSET 4
|
||||
#define MACB_BEX_SIZE 1
|
||||
#define MACB_COMP_OFFSET 5
|
||||
#define MACB_COMP_SIZE 1
|
||||
#define MACB_UND_OFFSET 6
|
||||
#define MACB_UND_SIZE 1
|
||||
|
||||
/* Bitfields in RSR */
|
||||
#define MACB_BNA_OFFSET 0
|
||||
#define MACB_BNA_SIZE 1
|
||||
#define MACB_REC_OFFSET 1
|
||||
#define MACB_REC_SIZE 1
|
||||
#define MACB_OVR_OFFSET 2
|
||||
#define MACB_OVR_SIZE 1
|
||||
|
||||
/* Bitfields in ISR/IER/IDR/IMR */
|
||||
#define MACB_MFD_OFFSET 0
|
||||
#define MACB_MFD_SIZE 1
|
||||
#define MACB_RCOMP_OFFSET 1
|
||||
#define MACB_RCOMP_SIZE 1
|
||||
#define MACB_RXUBR_OFFSET 2
|
||||
#define MACB_RXUBR_SIZE 1
|
||||
#define MACB_TXUBR_OFFSET 3
|
||||
#define MACB_TXUBR_SIZE 1
|
||||
#define MACB_ISR_TUND_OFFSET 4
|
||||
#define MACB_ISR_TUND_SIZE 1
|
||||
#define MACB_ISR_RLE_OFFSET 5
|
||||
#define MACB_ISR_RLE_SIZE 1
|
||||
#define MACB_TXERR_OFFSET 6
|
||||
#define MACB_TXERR_SIZE 1
|
||||
#define MACB_TCOMP_OFFSET 7
|
||||
#define MACB_TCOMP_SIZE 1
|
||||
#define MACB_ISR_LINK_OFFSET 9
|
||||
#define MACB_ISR_LINK_SIZE 1
|
||||
#define MACB_ISR_ROVR_OFFSET 10
|
||||
#define MACB_ISR_ROVR_SIZE 1
|
||||
#define MACB_HRESP_OFFSET 11
|
||||
#define MACB_HRESP_SIZE 1
|
||||
#define MACB_PFR_OFFSET 12
|
||||
#define MACB_PFR_SIZE 1
|
||||
#define MACB_PTZ_OFFSET 13
|
||||
#define MACB_PTZ_SIZE 1
|
||||
|
||||
/* Bitfields in MAN */
|
||||
#define MACB_DATA_OFFSET 0
|
||||
#define MACB_DATA_SIZE 16
|
||||
#define MACB_CODE_OFFSET 16
|
||||
#define MACB_CODE_SIZE 2
|
||||
#define MACB_REGA_OFFSET 18
|
||||
#define MACB_REGA_SIZE 5
|
||||
#define MACB_PHYA_OFFSET 23
|
||||
#define MACB_PHYA_SIZE 5
|
||||
#define MACB_RW_OFFSET 28
|
||||
#define MACB_RW_SIZE 2
|
||||
#define MACB_SOF_OFFSET 30
|
||||
#define MACB_SOF_SIZE 2
|
||||
|
||||
/* Bitfields in USRIO (AVR32) */
|
||||
#define MACB_MII_OFFSET 0
|
||||
#define MACB_MII_SIZE 1
|
||||
#define MACB_EAM_OFFSET 1
|
||||
#define MACB_EAM_SIZE 1
|
||||
#define MACB_TX_PAUSE_OFFSET 2
|
||||
#define MACB_TX_PAUSE_SIZE 1
|
||||
#define MACB_TX_PAUSE_ZERO_OFFSET 3
|
||||
#define MACB_TX_PAUSE_ZERO_SIZE 1
|
||||
|
||||
/* Bitfields in USRIO (AT91) */
|
||||
#define MACB_RMII_OFFSET 0
|
||||
#define MACB_RMII_SIZE 1
|
||||
#define MACB_CLKEN_OFFSET 1
|
||||
#define MACB_CLKEN_SIZE 1
|
||||
|
||||
/* Bitfields in WOL */
|
||||
#define MACB_IP_OFFSET 0
|
||||
#define MACB_IP_SIZE 16
|
||||
#define MACB_MAG_OFFSET 16
|
||||
#define MACB_MAG_SIZE 1
|
||||
#define MACB_ARP_OFFSET 17
|
||||
#define MACB_ARP_SIZE 1
|
||||
#define MACB_SA1_OFFSET 18
|
||||
#define MACB_SA1_SIZE 1
|
||||
#define MACB_WOL_MTI_OFFSET 19
|
||||
#define MACB_WOL_MTI_SIZE 1
|
||||
|
||||
/* Constants for CLK */
|
||||
#define MACB_CLK_DIV8 0
|
||||
#define MACB_CLK_DIV16 1
|
||||
#define MACB_CLK_DIV32 2
|
||||
#define MACB_CLK_DIV64 3
|
||||
|
||||
/* Constants for MAN register */
|
||||
#define MACB_MAN_SOF 1
|
||||
#define MACB_MAN_WRITE 1
|
||||
#define MACB_MAN_READ 2
|
||||
#define MACB_MAN_CODE 2
|
||||
|
||||
/* Bit manipulation macros */
|
||||
#define MACB_BIT(name) \
|
||||
(1 << MACB_##name##_OFFSET)
|
||||
#define MACB_BF(name,value) \
|
||||
(((value) & ((1 << MACB_##name##_SIZE) - 1)) \
|
||||
<< MACB_##name##_OFFSET)
|
||||
#define MACB_BFEXT(name,value)\
|
||||
(((value) >> MACB_##name##_OFFSET) \
|
||||
& ((1 << MACB_##name##_SIZE) - 1))
|
||||
#define MACB_BFINS(name,value,old) \
|
||||
(((old) & ~(((1 << MACB_##name##_SIZE) - 1) \
|
||||
<< MACB_##name##_OFFSET)) \
|
||||
| MACB_BF(name,value))
|
||||
|
||||
/* Register access macros */
|
||||
#define macb_readl(port,reg) \
|
||||
readl((port)->regs + MACB_##reg)
|
||||
#define macb_writel(port,reg,value) \
|
||||
writel((value), (port)->regs + MACB_##reg)
|
||||
|
||||
struct dma_desc {
|
||||
rt_uint32_t addr;
|
||||
rt_uint32_t ctrl;
|
||||
};
|
||||
|
||||
/* DMA descriptor bitfields */
|
||||
#define MACB_RX_USED_OFFSET 0
|
||||
#define MACB_RX_USED_SIZE 1
|
||||
#define MACB_RX_WRAP_OFFSET 1
|
||||
#define MACB_RX_WRAP_SIZE 1
|
||||
#define MACB_RX_WADDR_OFFSET 2
|
||||
#define MACB_RX_WADDR_SIZE 30
|
||||
|
||||
#define MACB_RX_FRMLEN_OFFSET 0
|
||||
#define MACB_RX_FRMLEN_SIZE 12
|
||||
#define MACB_RX_OFFSET_OFFSET 12
|
||||
#define MACB_RX_OFFSET_SIZE 2
|
||||
#define MACB_RX_SOF_OFFSET 14
|
||||
#define MACB_RX_SOF_SIZE 1
|
||||
#define MACB_RX_EOF_OFFSET 15
|
||||
#define MACB_RX_EOF_SIZE 1
|
||||
#define MACB_RX_CFI_OFFSET 16
|
||||
#define MACB_RX_CFI_SIZE 1
|
||||
#define MACB_RX_VLAN_PRI_OFFSET 17
|
||||
#define MACB_RX_VLAN_PRI_SIZE 3
|
||||
#define MACB_RX_PRI_TAG_OFFSET 20
|
||||
#define MACB_RX_PRI_TAG_SIZE 1
|
||||
#define MACB_RX_VLAN_TAG_OFFSET 21
|
||||
#define MACB_RX_VLAN_TAG_SIZE 1
|
||||
#define MACB_RX_TYPEID_MATCH_OFFSET 22
|
||||
#define MACB_RX_TYPEID_MATCH_SIZE 1
|
||||
#define MACB_RX_SA4_MATCH_OFFSET 23
|
||||
#define MACB_RX_SA4_MATCH_SIZE 1
|
||||
#define MACB_RX_SA3_MATCH_OFFSET 24
|
||||
#define MACB_RX_SA3_MATCH_SIZE 1
|
||||
#define MACB_RX_SA2_MATCH_OFFSET 25
|
||||
#define MACB_RX_SA2_MATCH_SIZE 1
|
||||
#define MACB_RX_SA1_MATCH_OFFSET 26
|
||||
#define MACB_RX_SA1_MATCH_SIZE 1
|
||||
#define MACB_RX_EXT_MATCH_OFFSET 28
|
||||
#define MACB_RX_EXT_MATCH_SIZE 1
|
||||
#define MACB_RX_UHASH_MATCH_OFFSET 29
|
||||
#define MACB_RX_UHASH_MATCH_SIZE 1
|
||||
#define MACB_RX_MHASH_MATCH_OFFSET 30
|
||||
#define MACB_RX_MHASH_MATCH_SIZE 1
|
||||
#define MACB_RX_BROADCAST_OFFSET 31
|
||||
#define MACB_RX_BROADCAST_SIZE 1
|
||||
|
||||
#define MACB_TX_FRMLEN_OFFSET 0
|
||||
#define MACB_TX_FRMLEN_SIZE 11
|
||||
#define MACB_TX_LAST_OFFSET 15
|
||||
#define MACB_TX_LAST_SIZE 1
|
||||
#define MACB_TX_NOCRC_OFFSET 16
|
||||
#define MACB_TX_NOCRC_SIZE 1
|
||||
#define MACB_TX_BUF_EXHAUSTED_OFFSET 27
|
||||
#define MACB_TX_BUF_EXHAUSTED_SIZE 1
|
||||
#define MACB_TX_UNDERRUN_OFFSET 28
|
||||
#define MACB_TX_UNDERRUN_SIZE 1
|
||||
#define MACB_TX_ERROR_OFFSET 29
|
||||
#define MACB_TX_ERROR_SIZE 1
|
||||
#define MACB_TX_WRAP_OFFSET 30
|
||||
#define MACB_TX_WRAP_SIZE 1
|
||||
#define MACB_TX_USED_OFFSET 31
|
||||
#define MACB_TX_USED_SIZE 1
|
||||
|
||||
|
||||
#endif /* _MACB_H */
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
/*
|
||||
* File : mii.h
|
||||
* This file is part of RT-Thread RTOS
|
||||
* COPYRIGHT (C) 2006, RT-Thread Develop Team
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rt-thread.org/license/LICENSE
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2011-03-18 weety first version
|
||||
*/
|
||||
|
||||
#ifndef __MII_H__
|
||||
#define __MII_H__
|
||||
|
||||
/* Generic MII registers. */
|
||||
|
||||
#define MII_BMCR 0x00 /* Basic mode control register */
|
||||
#define MII_BMSR 0x01 /* Basic mode status register */
|
||||
#define MII_PHYSID1 0x02 /* PHYS ID 1 */
|
||||
#define MII_PHYSID2 0x03 /* PHYS ID 2 */
|
||||
#define MII_ADVERTISE 0x04 /* Advertisement control reg */
|
||||
#define MII_LPA 0x05 /* Link partner ability reg */
|
||||
#define MII_EXPANSION 0x06 /* Expansion register */
|
||||
#define MII_CTRL1000 0x09 /* 1000BASE-T control */
|
||||
#define MII_STAT1000 0x0a /* 1000BASE-T status */
|
||||
#define MII_ESTATUS 0x0f /* Extended Status */
|
||||
#define MII_DCOUNTER 0x12 /* Disconnect counter */
|
||||
#define MII_FCSCOUNTER 0x13 /* False carrier counter */
|
||||
#define MII_NWAYTEST 0x14 /* N-way auto-neg test reg */
|
||||
#define MII_RERRCOUNTER 0x15 /* Receive error counter */
|
||||
#define MII_SREVISION 0x16 /* Silicon revision */
|
||||
#define MII_RESV1 0x17 /* Reserved... */
|
||||
#define MII_LBRERROR 0x18 /* Lpback, rx, bypass error */
|
||||
#define MII_PHYADDR 0x19 /* PHY address */
|
||||
#define MII_RESV2 0x1a /* Reserved... */
|
||||
#define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
|
||||
#define MII_NCONFIG 0x1c /* Network interface config */
|
||||
|
||||
/* Basic mode control register. */
|
||||
#define BMCR_RESV 0x003f /* Unused... */
|
||||
#define BMCR_SPEED1000 0x0040 /* MSB of Speed (1000) */
|
||||
#define BMCR_CTST 0x0080 /* Collision test */
|
||||
#define BMCR_FULLDPLX 0x0100 /* Full duplex */
|
||||
#define BMCR_ANRESTART 0x0200 /* Auto negotiation restart */
|
||||
#define BMCR_ISOLATE 0x0400 /* Disconnect DP83840 from MII */
|
||||
#define BMCR_PDOWN 0x0800 /* Powerdown the DP83840 */
|
||||
#define BMCR_ANENABLE 0x1000 /* Enable auto negotiation */
|
||||
#define BMCR_SPEED100 0x2000 /* Select 100Mbps */
|
||||
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
|
||||
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
|
||||
|
||||
/* Basic mode status register. */
|
||||
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
|
||||
#define BMSR_JCD 0x0002 /* Jabber detected */
|
||||
#define BMSR_LSTATUS 0x0004 /* Link status */
|
||||
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
|
||||
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
|
||||
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
|
||||
#define BMSR_RESV 0x00c0 /* Unused... */
|
||||
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
|
||||
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
|
||||
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
|
||||
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
|
||||
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
|
||||
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
|
||||
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
|
||||
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
|
||||
|
||||
/* Advertisement control register. */
|
||||
#define ADVERTISE_SLCT 0x001f /* Selector bits */
|
||||
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */
|
||||
#define ADVERTISE_10HALF 0x0020 /* Try for 10mbps half-duplex */
|
||||
#define ADVERTISE_1000XFULL 0x0020 /* Try for 1000BASE-X full-duplex */
|
||||
#define ADVERTISE_10FULL 0x0040 /* Try for 10mbps full-duplex */
|
||||
#define ADVERTISE_1000XHALF 0x0040 /* Try for 1000BASE-X half-duplex */
|
||||
#define ADVERTISE_100HALF 0x0080 /* Try for 100mbps half-duplex */
|
||||
#define ADVERTISE_1000XPAUSE 0x0080 /* Try for 1000BASE-X pause */
|
||||
#define ADVERTISE_100FULL 0x0100 /* Try for 100mbps full-duplex */
|
||||
#define ADVERTISE_1000XPSE_ASYM 0x0100 /* Try for 1000BASE-X asym pause */
|
||||
#define ADVERTISE_100BASE4 0x0200 /* Try for 100mbps 4k packets */
|
||||
#define ADVERTISE_PAUSE_CAP 0x0400 /* Try for pause */
|
||||
#define ADVERTISE_PAUSE_ASYM 0x0800 /* Try for asymetric pause */
|
||||
#define ADVERTISE_RESV 0x1000 /* Unused... */
|
||||
#define ADVERTISE_RFAULT 0x2000 /* Say we can detect faults */
|
||||
#define ADVERTISE_LPACK 0x4000 /* Ack link partners response */
|
||||
#define ADVERTISE_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | \
|
||||
ADVERTISE_CSMA)
|
||||
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
|
||||
ADVERTISE_100HALF | ADVERTISE_100FULL)
|
||||
|
||||
/* Link partner ability register. */
|
||||
#define LPA_SLCT 0x001f /* Same as advertise selector */
|
||||
#define LPA_10HALF 0x0020 /* Can do 10mbps half-duplex */
|
||||
#define LPA_1000XFULL 0x0020 /* Can do 1000BASE-X full-duplex */
|
||||
#define LPA_10FULL 0x0040 /* Can do 10mbps full-duplex */
|
||||
#define LPA_1000XHALF 0x0040 /* Can do 1000BASE-X half-duplex */
|
||||
#define LPA_100HALF 0x0080 /* Can do 100mbps half-duplex */
|
||||
#define LPA_1000XPAUSE 0x0080 /* Can do 1000BASE-X pause */
|
||||
#define LPA_100FULL 0x0100 /* Can do 100mbps full-duplex */
|
||||
#define LPA_1000XPAUSE_ASYM 0x0100 /* Can do 1000BASE-X pause asym*/
|
||||
#define LPA_100BASE4 0x0200 /* Can do 100mbps 4k packets */
|
||||
#define LPA_PAUSE_CAP 0x0400 /* Can pause */
|
||||
#define LPA_PAUSE_ASYM 0x0800 /* Can pause asymetrically */
|
||||
#define LPA_RESV 0x1000 /* Unused... */
|
||||
#define LPA_RFAULT 0x2000 /* Link partner faulted */
|
||||
#define LPA_LPACK 0x4000 /* Link partner acked us */
|
||||
#define LPA_NPAGE 0x8000 /* Next page bit */
|
||||
|
||||
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
|
||||
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
|
||||
|
||||
/* Expansion register for auto-negotiation. */
|
||||
#define EXPANSION_NWAY 0x0001 /* Can do N-way auto-nego */
|
||||
#define EXPANSION_LCWP 0x0002 /* Got new RX page code word */
|
||||
#define EXPANSION_ENABLENPAGE 0x0004 /* This enables npage words */
|
||||
#define EXPANSION_NPCAPABLE 0x0008 /* Link partner supports npage */
|
||||
#define EXPANSION_MFAULTS 0x0010 /* Multiple faults detected */
|
||||
#define EXPANSION_RESV 0xffe0 /* Unused... */
|
||||
|
||||
#define ESTATUS_1000_TFULL 0x2000 /* Can do 1000BT Full */
|
||||
#define ESTATUS_1000_THALF 0x1000 /* Can do 1000BT Half */
|
||||
|
||||
/* N-way test register. */
|
||||
#define NWAYTEST_RESV1 0x00ff /* Unused... */
|
||||
#define NWAYTEST_LOOPBACK 0x0100 /* Enable loopback for N-way */
|
||||
#define NWAYTEST_RESV2 0xfe00 /* Unused... */
|
||||
|
||||
/* 1000BASE-T Control register */
|
||||
#define ADVERTISE_1000FULL 0x0200 /* Advertise 1000BASE-T full duplex */
|
||||
#define ADVERTISE_1000HALF 0x0100 /* Advertise 1000BASE-T half duplex */
|
||||
|
||||
/* 1000BASE-T Status register */
|
||||
#define LPA_1000LOCALRXOK 0x2000 /* Link partner local receiver status */
|
||||
#define LPA_1000REMRXOK 0x1000 /* Link partner remote receiver status */
|
||||
#define LPA_1000FULL 0x0800 /* Link partner 1000BASE-T full duplex */
|
||||
#define LPA_1000HALF 0x0400 /* Link partner 1000BASE-T half duplex */
|
||||
|
||||
/* Flow control flags */
|
||||
#define FLOW_CTRL_TX 0x01
|
||||
#define FLOW_CTRL_RX 0x02
|
||||
|
||||
/**
|
||||
* mii_nway_result
|
||||
* @negotiated: value of MII ANAR and'd with ANLPAR
|
||||
*
|
||||
* Given a set of MII abilities, check each bit and returns the
|
||||
* currently supported media, in the priority order defined by
|
||||
* IEEE 802.3u. We use LPA_xxx constants but note this is not the
|
||||
* value of LPA solely, as described above.
|
||||
*
|
||||
* The one exception to IEEE 802.3u is that 100baseT4 is placed
|
||||
* between 100T-full and 100T-half. If your phy does not support
|
||||
* 100T4 this is fine. If your phy places 100T4 elsewhere in the
|
||||
* priority order, you will need to roll your own function.
|
||||
*/
|
||||
static inline unsigned int mii_nway_result (unsigned int negotiated)
|
||||
{
|
||||
unsigned int ret;
|
||||
|
||||
if (negotiated & LPA_100FULL)
|
||||
ret = LPA_100FULL;
|
||||
else if (negotiated & LPA_100BASE4)
|
||||
ret = LPA_100BASE4;
|
||||
else if (negotiated & LPA_100HALF)
|
||||
ret = LPA_100HALF;
|
||||
else if (negotiated & LPA_10FULL)
|
||||
ret = LPA_10FULL;
|
||||
else
|
||||
ret = LPA_10HALF;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __MII_H__ */
|
||||
|
|
@ -120,7 +120,7 @@
|
|||
|
||||
/* SECTION: lwip, a lightweight TCP/IP protocol stack */
|
||||
/* Using lightweight TCP/IP protocol stack */
|
||||
//#define RT_USING_LWIP
|
||||
#define RT_USING_LWIP
|
||||
#define RT_LWIP_DNS
|
||||
|
||||
/* Trace LwIP protocol */
|
||||
|
|
|
@ -116,7 +116,12 @@ void rtthread_startup(void)
|
|||
#endif
|
||||
|
||||
#ifdef RT_USING_LWIP
|
||||
/* register ethernetif device */
|
||||
eth_system_device_init();
|
||||
rt_hw_macb_init();
|
||||
/* init lwip system */
|
||||
lwip_sys_init();
|
||||
rt_kprintf("TCP/IP initialized!\n");
|
||||
#endif
|
||||
|
||||
/*init all registed devices */
|
||||
|
|
Loading…
Reference in New Issue