netarm_eth_drv.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 711 行 · 第 1/2 页
C
711 行
static void
dma_rx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
eth_drv_dsr( vector, count, data );
HAL_WRITE_UINT32(DMA1A_SR, 0x80000000); // acknowledge and mask interrupts
HAL_WRITE_UINT32(DMA1B_SR, 0x80000000);
HAL_WRITE_UINT32(DMA1C_SR, 0x80000000);
cyg_drv_interrupt_unmask(vector);
}
static cyg_uint32
dma_tx_isr(cyg_vector_t vector, cyg_addrword_t data)
{
// block this interrupt until the dsr completes
cyg_drv_interrupt_mask(vector);
// tell ecos to allow further interrupt processing
cyg_drv_interrupt_acknowledge(vector);
return CYG_ISR_CALL_DSR; // invoke the dsr
}
static void
dma_tx_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
eth_drv_dsr( vector, count, data );
HAL_OR_UINT32(DMA2_SR, 0x80000000); // acknowledge interrupt
cyg_drv_interrupt_unmask(vector);
}
static void
setupDMA(void)
{
int i;
/* map DMA shared data to non-cached ram */
#ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBufferA, pRxBufferA, unsigned char *);
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBufferB, pRxBufferB, unsigned char *);
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBufferC, pRxBufferC, unsigned char *);
HAL_CACHED_TO_UNCACHED_ADDRESS(TxBuffer, pTxBuffer, unsigned char *);
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBDP_A, pRxBDP_A, BDP_t *);
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBDP_B, pRxBDP_B, BDP_t *);
HAL_CACHED_TO_UNCACHED_ADDRESS(RxBDP_C, pRxBDP_C, BDP_t *);
HAL_CACHED_TO_UNCACHED_ADDRESS(TxBDP, pTxBDP, BDP_t * );
#endif
HAL_OR_UINT32(SYSCON, 0x40); // reset DMA module
for(i = 0; i < NumA; i++)
{
pRxBDP_A[i].lo = ((unsigned)(pRxBufferA + i*BufferSizeA)) & 0x3fffffff;
pRxBDP_A[i].hi = BufferSizeA;
}
pRxBDP_A[i - 1].lo |= 0x80000000; // set W bit
for(i = 0; i < NumB; i++)
{
pRxBDP_B[i].lo = ((unsigned)(pRxBufferB + i*BufferSizeB)) & 0x3fffffff;
pRxBDP_B[i].hi = BufferSizeB;
}
pRxBDP_B[i - 1].lo |= 0x80000000;
for(i = 0; i < NumC; i++)
{
pRxBDP_C[i].lo = ((unsigned)(pRxBufferC + i*BufferSizeC)) & 0x3fffffff;
pRxBDP_C[i].hi = BufferSizeC;
}
pRxBDP_C[i - 1].lo |= 0x80000000;
HAL_AND_UINT32(SYSCON, ~0x40);
HAL_WRITE_UINT32(DMA1A_BDP, (unsigned)pRxBDP_A);
HAL_WRITE_UINT32(DMA1A_CR, 0x82000000); //burst transfer
HAL_WRITE_UINT32(DMA1A_SR, 0xa00000);
HAL_WRITE_UINT32(DMA1B_BDP, (unsigned)pRxBDP_B);
HAL_WRITE_UINT32(DMA1B_CR, 0x82000000); //burst transfer
HAL_WRITE_UINT32(DMA1B_SR, 0xa00000);
HAL_WRITE_UINT32(DMA1C_BDP, (unsigned)pRxBDP_C);
HAL_WRITE_UINT32(DMA1C_CR, 0x82000000); //burst transfer
HAL_WRITE_UINT32(DMA1C_SR, 0xa00000);
pTxBDP->lo = ((unsigned)pTxBuffer) & 0x3fffffff;
pTxBDP->lo |= 0xa0000000; // set W and L bit
HAL_WRITE_UINT32(DMA2_BDP, (unsigned)pTxBDP);
HAL_WRITE_UINT32(DMA2_CR, 0x86000000); //burst transfer
HAL_WRITE_UINT32(DMA2_SR, 0x800000);
}
static bool
netarm_init(struct cyg_netdevtab_entry *tab)
{
struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
cyg_bool duplex;
static cyg_interrupt dma_rx_int_object, dma_tx_int_object;
static cyg_handle_t dma_rx_int_handle, dma_tx_int_handle;
#ifdef CYGSEM_DEVS_ETH_ARM_NETARM_ETH0_SET_ESA
unsigned char esa[6] = CYGDAT_DEVS_ETH_ARM_NETARM_ETH0_ESA;
#else
unsigned char esa[6];
cyg_netarm_initI2C();
cyg_netarm_eepromRead(0x50, EEPROM_MAC, esa, 6);
#endif
// setup dma receiver
setupDMA();
cyg_netarm_mii_reset();
cyg_netarm_mii_negotiate(); // initialize PHY
duplex = cyg_netarm_mii_check_duplex();
// Ethernet Controller Initializatition
// auto CRC, late collision retry
HAL_WRITE_UINT32(MACCR, 0x1c | (duplex << 1));
// insert MAC source address into ethernet frame
HAL_WRITE_UINT32(STLCR, 0x3);
HAL_WRITE_UINT32(BtBIPGGapTimerR, 0x14); // standard values
HAL_WRITE_UINT32(NonBtBIPGGapTimerR, (0x9 << 7) | 0x11);// standard values
HAL_WRITE_UINT32(CollWinR, (0x37 << 8) | 0xf); // standard values
HAL_WRITE_UINT32(SAFR, 0x1); // broadcast mode
// dma mode, full duplex, enable pNA mode(needed for alignment)
HAL_WRITE_UINT32(EthGenCR, 0x40400400 | (duplex << 16));
cyg_drv_interrupt_create(
CYGNUM_HAL_INTERRUPT_DMA1, // Interrupt Vector
0, // Interrupt Priority
(cyg_addrword_t)&netarm_sc, // Reference to Driver Instance
dma_rx_isr,
dma_rx_dsr,
&dma_rx_int_handle,
&dma_rx_int_object);
cyg_drv_interrupt_create(
CYGNUM_HAL_INTERRUPT_DMA2, // Interrupt Vector
0, // Interrupt Priority
(cyg_addrword_t)&netarm_sc, // Reference to Driver Instance
dma_tx_isr,
dma_tx_dsr,
&dma_tx_int_handle,
&dma_tx_int_object);
cyg_drv_interrupt_attach(dma_rx_int_handle);
cyg_drv_interrupt_attach(dma_tx_int_handle);
cyg_mutex_init(&Key_Mutex);
sc->funs->eth_drv->init(sc, esa);
return true;
}
static void
netarm_recv(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len)
{
int i, len;
private_data_t *pd = (private_data_t *)(sc->driver_private);
unsigned char *data, *buf = pd->RxBuffer;
for (i = 0; i < sg_len; i++) {
data = (unsigned char *)(sg_list[i].buf);
len = sg_list[i].len;
if(len)
{
if(i == 1)
{
buf += 2;
}
fastcopy(data, buf, len);
buf += len;
}
}
}
static void
netarm_deliver(struct eth_drv_sc *sc)
{
static int a = 0, b = 0, c = 0;
unsigned key, rega, regb, regc;
private_data_t *pd = (private_data_t *)(sc->driver_private);
while((key = GetKey(pd)))
{
sc->funs->eth_drv->tx_done(sc, key, 0);
}
while(pRxBDP_A[a].hi & 0x8000)
{
pd->RxBuffer = (unsigned char *)(pRxBDP_A[a].lo & 0x1FFFFFFF);
HAL_REORDER_BARRIER();
sc->funs->eth_drv->recv(sc, pRxBDP_A[a].hi & 0x7FFF);
HAL_REORDER_BARRIER();
pRxBDP_A[a].hi = BufferSizeA;
HAL_REORDER_BARRIER();
a = (a + 1) % NumA;
}
while(pRxBDP_B[b].hi & 0x8000)
{
pd->RxBuffer = (unsigned char *)(pRxBDP_B[b].lo & 0x1FFFFFFF);
HAL_REORDER_BARRIER();
sc->funs->eth_drv->recv(sc, pRxBDP_B[b].hi & 0x7FFF);
HAL_REORDER_BARRIER();
pRxBDP_B[b].hi = BufferSizeB;
HAL_REORDER_BARRIER();
b = (b + 1) % NumB;
}
while(pRxBDP_C[c].hi & 0x8000)
{
pd->RxBuffer = (unsigned char *)(pRxBDP_C[c].lo & 0x1FFFFFFF);
HAL_REORDER_BARRIER();
sc->funs->eth_drv->recv(sc, pRxBDP_C[c].hi & 0x7FFF);
HAL_REORDER_BARRIER();
pRxBDP_C[c].hi = BufferSizeC;
HAL_REORDER_BARRIER();
c = (c + 1) % NumC;
}
HAL_READ_UINT32(DMA1A_SR, rega);
HAL_READ_UINT32(DMA1B_SR, regb);
HAL_READ_UINT32(DMA1C_SR, regc);
if((rega & 0x20000000) || (regb & 0x20000000) || (regc & 0x20000000))
{
HAL_AND_UINT32(EthGenCR, ~0xc0000000); // reset Rx FIFO
HAL_OR_UINT32(EthGenCR, 0xc0000000);
}
HAL_WRITE_UINT32(DMA1A_SR, 0x20a00000);
HAL_WRITE_UINT32(DMA1B_SR, 0x20a00000);
HAL_WRITE_UINT32(DMA1C_SR, 0x20a00000);
}
static int
netarm_can_send(struct eth_drv_sc *sc)
{
private_data_t *pd = (private_data_t *)(sc->driver_private);
if((pTxBDP->hi & 0x8000) || KeyBufferFull(pd))
return 0;
return 1;
}
static void
netarm_send(struct eth_drv_sc *sc, struct eth_drv_sg *sg_list,
int sg_len, int total_len, unsigned long key)
{
private_data_t *pd = (private_data_t *)(sc->driver_private);
int i, len;
unsigned char *data, *buf = pTxBuffer;
AddKey(key, pd);
// Put data into buffer
for(i = 0; i < sg_len; i++) {
data = (unsigned char *)sg_list[i].buf;
len = sg_list[i].len;
if(len)
{
if(((unsigned)buf & 0x3) != ((unsigned)data & 0x3))
{
memcpy(buf, data, len);
}
else
{
fastcopy(buf, data, len);
}
buf += len;
}
}
cyg_drv_dsr_lock();
pTxBDP->hi = total_len | 0x8000;
HAL_REORDER_BARRIER();
HAL_OR_UINT32(DMA2_SR, 0xf0000000);
cyg_drv_dsr_unlock();
}
static void
netarm_start(struct eth_drv_sc *sc, unsigned char *enaddr, int flags)
{
setMAC(enaddr); // set MAC address
HAL_REORDER_BARRIER();
HAL_OR_UINT32(EthGenCR, 0x80800000); // enable Rx und Tx FIFO
HAL_REORDER_BARRIER();
cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_DMA1);
cyg_drv_interrupt_unmask(CYGNUM_HAL_INTERRUPT_DMA2);
}
static void
netarm_stop(struct eth_drv_sc *sc)
{
HAL_AND_UINT32(EthGenCR, 0x7f7fffff);
HAL_REORDER_BARRIER();
cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_DMA1);
cyg_drv_interrupt_mask(CYGNUM_HAL_INTERRUPT_DMA2);
}
static int
netarm_control(struct eth_drv_sc *sc, unsigned long key, void *data, int len)
{
return -1;
}
static void
netarm_poll(struct eth_drv_sc *sc)
{
}
static int
netarm_int_vector(struct eth_drv_sc *sc)
{
return CYGNUM_HAL_INTERRUPT_DMA1;
}
static void
setMAC(unsigned char *esa)
{
HAL_WRITE_UINT32(SAR1, (esa[1] << 8) | esa[0]); // set MAC address
HAL_WRITE_UINT32(SAR2, (esa[3] << 8) | esa[2]);
HAL_WRITE_UINT32(SAR3, (esa[5] << 8) | esa[4]);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?