netarm_eth_drv.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 711 行 · 第 1/2 页

C
711
字号
//==========================================================================
//
//      netarm_eth_drv.c
//
//      NetSilion NET+ARM Ethernet Driver (DMA driven)
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System
// Copyright (C) 2005 eCosCentric Ltd.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):           Harald Brandl (harald.brandl@fh-joanneum.at)
// Contributors:        Harald Brandl
// Date:                01.08.2004
// Purpose:             NET+ARM Ethernet Driver (DMA driven)
// Description:
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <cyg/infra/cyg_type.h>
#include <cyg/hal/hal_arch.h>
#include <cyg/infra/diag.h>
#include <cyg/hal/drv_api.h>
#include <cyg/io/eth/netdev.h>
#include <cyg/io/eth/eth_drv.h>

#include <pkgconf/devs_eth_arm_netarm.h>
#include <cyg/hal/hal_platform_ints.h>
#include <cyg/hal/plf_mmap.h>
#include "eth_regs.h"
#include "MII.h"
#include "netarm_eth_drv.h"
#include "eeprom.h"


#define BufferSizeA 128
#define BufferSizeB 512
#define BufferSizeC 1524

#define NumA 16
#define NumB 8
#define NumC 8

#define EEPROM_MAC 0	// location of MAC address inside eeprom


static cyg_mutex_t Key_Mutex;
static private_data_t driver_private;

static unsigned char RxBufferA[NumA][BufferSizeA] __attribute__ ((aligned (4)));
static unsigned char RxBufferB[NumB][BufferSizeB] __attribute__ ((aligned (4)));
static unsigned char RxBufferC[NumC][BufferSizeC] __attribute__ ((aligned (4)));

static unsigned char TxBuffer[1518] __attribute__ ((aligned (4)));

static BDP_t RxBDP_A[NumA];
static BDP_t RxBDP_B[NumB];
static BDP_t RxBDP_C[NumC];

static BDP_t TxBDP;

// relocation pointer for data accessed by DMA to enable caching
static unsigned char *pRxBufferA = (unsigned char *)RxBufferA,
					 *pRxBufferB = (unsigned char *)RxBufferB,
					 *pRxBufferC = (unsigned char *)RxBufferC;
static unsigned char *pTxBuffer = TxBuffer;

static BDP_t *pRxBDP_A = RxBDP_A, *pRxBDP_B = RxBDP_B, *pRxBDP_C = RxBDP_C;
static BDP_t *pTxBDP = &TxBDP;


ETH_DRV_SC(netarm_sc,
           (void *)&driver_private,	// driver specific data
           "eth0",        			// name for this interface
           netarm_start,
           netarm_stop,
           netarm_control,
           netarm_can_send,
           netarm_send,
           netarm_recv,
           netarm_deliver,
           netarm_poll,
           netarm_int_vector);


NETDEVTAB_ENTRY(netarm_netdev,
                "ETH_DRV",
                netarm_init,
                &netarm_sc);


#ifdef __thumb__
	#define fastcopy memcpy
#else
static void
fastcopy(void *buf, void *data, unsigned long len)
{
	asm volatile(

		"STMDB SP!, {R11};"

		"TST R1, #2;"			// test if aligned
		"LDRNEH R3, [R1], #2;"
		"STRNEH R3, [R0], #2;"
		"SUBNE R2, R2, #2;"
		"TST R1, #1;"
		"LDRNEB R3, [R1], #1;"
		"STRNEB R3, [R0], #1;"
		"SUBNE R2, R2, #1;"

		".START%=:"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"CMP R2, #44;"
		"BLT .LASTBYTES%=;"
		"LDMIA R1!, {R3 - R12, R14};"
		"STMIA R0!, {R3 - R12, R14};"
		"SUB R2, R2, #44;"

		"BGE .START%=;"


		".LASTBYTES%=:"

		"AND R14, R2, #0xfffffffc;"
		"LDR PC, [PC, R14];"
		"NOP;"

		".SWITCH%=:"
		".word	.CASE0%=;"
		".word	.CASE1%=;"
		".word	.CASE2%=;"
		".word	.CASE3%=;"
		".word	.CASE4%=;"
		".word	.CASE5%=;"
		".word	.CASE6%=;"
		".word	.CASE7%=;"
		".word	.CASE8%=;"
		".word	.CASE9%=;"
		".word	.CASE10%=;"

		".CASE0%=:"
		"B .END%=;"

		".CASE1%=:"
		"LDMIA R1!, {R3};"
		"STMIA R0!, {R3};"
		"B .END%=;"

		".CASE2%=:"
		"LDMIA R1!, {R3, R4};"
		"STMIA R0!, {R3, R4};"
		"B .END%=;"

		".CASE3%=:"
		"LDMIA R1!, {R3 - R5};"
		"STMIA R0!, {R3 - R5};"
		"B .END%=;"

		".CASE4%=:"
		"LDMIA R1!, {R3 - R6};"
		"STMIA R0!, {R3 - R6};"
		"B .END%=;"

		".CASE5%=:"
		"LDMIA R1!, {R3 - R7};"
		"STMIA R0!, {R3 - R7};"
		"B .END%=;"

		".CASE6%=:"
		"LDMIA R1!, {R3 - R8};"
		"STMIA R0!, {R3 - R8};"
		"B .END%=;"

		".CASE7%=:"
		"LDMIA R1!, {R3 - R9};"
		"STMIA R0!, {R3 - R9};"
		"B .END%=;"

		".CASE8%=:"
		"LDMIA R1!, {R3 - R10};"
		"STMIA R0!, {R3 - R10};"
		"B .END%=;"

		".CASE9%=:"
		"LDMIA R1!, {R3 - R11};"
		"STMIA R0!, {R3 - R11};"
		"B .END%=;"

		".CASE10%=:"
		"LDMIA R1!, {R3 - R12};"
		"STMIA R0!, {R3 - R12};"

		".END%=:"
		"TST R2, #2;"
		"LDRNEH R3, [R1], #2;"
		"STRNEH R3, [R0], #2;"
		"TST R2, #1;"
		"LDRNEB R3, [R1], #1;"
		"STRNEB R3, [R0], #1;"

		"LDMIA SP!, {R11};"

		:
		: "r" (buf), "r" (data), "r" (len)
		: "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14"
		);
}
#endif

static bool
KeyBufferFull(private_data_t *pd)
{
	int tmp = 0;

	cyg_drv_mutex_lock(&Key_Mutex);

	if((pd->key_head + 1) % MaxKeys == pd->key_tail)
	{
		tmp = 1;
	}

	cyg_drv_mutex_unlock(&Key_Mutex);

	return tmp;
}


static void
AddKey(unsigned long key, private_data_t *pd)
{

	cyg_drv_mutex_lock(&Key_Mutex);

	pd->KeyBuffer[pd->key_head] = key;
	pd->key_head = (pd->key_head + 1) % MaxKeys;

	cyg_drv_mutex_unlock(&Key_Mutex);
}

static unsigned
GetKey(private_data_t *pd)
{
	unsigned key = 0;

	cyg_drv_mutex_lock(&Key_Mutex);

	if(pd->key_tail != pd->key_head)
	{
		key = pd->KeyBuffer[pd->key_tail];
		pd->key_tail = (pd->key_tail + 1) % MaxKeys;
	}

	cyg_drv_mutex_unlock(&Key_Mutex);

	return key;
}


static cyg_uint32
dma_rx_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;	// call the dsr
}

⌨️ 快捷键说明

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