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 + -
显示快捷键?