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