This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Ethernet device driver for ARM NET+50
- From: "Brandl Harald" <Harald dot Brandl at fh-joanneum dot at>
- To: <ecos-patches at sources dot redhat dot com>
- Date: Mon, 6 Dec 2004 18:01:10 +0100
- Subject: Ethernet device driver for ARM NET+50
This patch contains an ethernet device driver for the ARM NET+50.
Regards
Harald
diff -Naur
ecos/packages/devs/eth/arm/netarm/current/cdl/netarm_eth_driver.cdl
my_ecos/packages/devs/eth/arm/netarm/current/cdl/netarm_eth_driver.cdl
--- ecos/packages/devs/eth/arm/netarm/current/cdl/netarm_eth_driver.cdl
1970-01-01 01:00:00.000000000 +0100
+++
my_ecos/packages/devs/eth/arm/netarm/current/cdl/netarm_eth_driver.cdl
2004-11-30 10:45:17.405241500 +0100
@@ -0,0 +1,124 @@
+# ====================================================================
+#
+# netarm_eth_driver.cdl
+#
+# Ethernet driver
+# NET+ARM ethernet interface
+#
+# ====================================================================
+#####ECOSGPLCOPYRIGHTBEGIN####
+## -------------------------------------------
+## This file is part of eCos, the Embedded Configurable Operating
System.
+## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+##
+## 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.
+##
+## Alternative licenses for eCos may be arranged by contacting Red Hat,
Inc.
+## at http://sources.redhat.com/ecos/ecos-license/
+## -------------------------------------------
+#####ECOSGPLCOPYRIGHTEND####
+# ====================================================================
+######DESCRIPTIONBEGIN####
+#
+# Author(s): Harald Brandl (harald.brandl@fh-joanneum.at)
+# Original data:
+# Contributors:
+# Date: 01.08.2004
+#
+#####DESCRIPTIONEND####
+#
+# ====================================================================
+
+cdl_package CYGPKG_DEVS_ETH_ARM_NETARM {
+ display "NetSilicon board ethernet driver"
+ description "Ethernet driver for NET+ARM."
+
+ parent CYGPKG_IO_ETH_DRIVERS
+ active_if CYGPKG_IO_ETH_DRIVERS
+
+ include_dir cyg/io/eth
+
+ compile -library=libextras.a MII.c netarm_eth_drv.c
+
+ define_proc {
+ puts $::cdl_system_header "/***** ethernet driver proc output
start *****/"
+ puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_NETARM_CFG
<pkgconf/devs_eth_arm_netarm.h>"
+ puts $::cdl_system_header "/***** ethernet driver proc output
end *****/"
+ }
+
+ cdl_component CYGPKG_DEVS_ETH_ARM_NETARM_ETH0 {
+ display "Ethernet port 0 driver"
+ flavor bool
+ default_value 1
+
+ implements CYGHWR_NET_DRIVERS
+ implements CYGHWR_NET_DRIVER_ETH0
+
+ cdl_option CYGDAT_DEVS_ETH_ARM_NETARM_ETH0_NAME {
+ display "Device name for the ETH0 ethernet port 0
driver"
+ flavor data
+ default_value {"\"eth0\""}
+ description "
+ This option sets the name of the ethernet device for
the
+ netarm ethernet port 0."
+ }
+
+ cdl_component CYGSEM_DEVS_ETH_ARM_NETARM_ETH0_SET_ESA {
+ display "Set the ethernet station address"
+ flavor bool
+ default_value 0
+ description "Enabling this option will allow the ethernet
+ station address to be forced to the value set by the
+ configuration. This may be required if the hardware does
+ not include a serial EEPROM for the ESA."
+
+ cdl_option CYGDAT_DEVS_ETH_ARM_NETARM_ETH0_ESA {
+ display "The ethernet station address"
+ flavor data
+ default_value {"{0x00, 0x40, 0xaf, 0x77, 0xe0, 0x80}"}
+ description "The ethernet station address"
+ }
+ }
+
+ cdl_component CYGPKG_DEVS_ETH_ARM_NETARM_OPTIONS {
+ display "NETARM ethernet driver build options"
+ flavor none
+ no_define
+
+ cdl_option CYGPKG_DEVS_ETH_ARM_NETARM_CFLAGS_ADD {
+ display "Additional compiler flags"
+ flavor data
+ no_define
+ default_value { "-D_KERNEL -D__ECOS" }
+ description "
+ This option modifies the set of compiler flags for
+ building the NETARM ethernet driver
+ package. These flags are used in addition to the set
of
+ global flags."
+ }
+ }
+ }
+}
+
+# EOF netarm_eth_driver.cdl
diff -Naur ecos/packages/devs/eth/arm/netarm/current/include/MII.h
my_ecos/packages/devs/eth/arm/netarm/current/include/MII.h
--- ecos/packages/devs/eth/arm/netarm/current/include/MII.h
1970-01-01 01:00:00.000000000 +0100
+++ my_ecos/packages/devs/eth/arm/netarm/current/include/MII.h
2004-11-27 16:04:57.797795200 +0100
@@ -0,0 +1,31 @@
+#ifndef __MII__
+#define __MII__
+
+// ====================================================================
+//
+// MII.h
+//
+// PHY chip configuration
+//
+// ====================================================================
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Harald Brandl (harald.brandl@fh-joanneum.at)
+// Contributors: Harald Brandl
+// Date: 01.08.2004
+// Purpose: Functions for PHY control
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+void mii_reset(void);
+void mii_set_speed (cyg_bool speed, cyg_bool duplex);
+cyg_bool mii_check_speed(void);
+cyg_bool mii_check_duplex(void);
+cyg_bool mii_negotiate(void);
+
+#endif
diff -Naur ecos/packages/devs/eth/arm/netarm/current/include/eth_regs.h
my_ecos/packages/devs/eth/arm/netarm/current/include/eth_regs.h
--- ecos/packages/devs/eth/arm/netarm/current/include/eth_regs.h
1970-01-01 01:00:00.000000000 +0100
+++ my_ecos/packages/devs/eth/arm/netarm/current/include/eth_regs.h
2004-11-27 16:19:34.738774400 +0100
@@ -0,0 +1,94 @@
+#ifndef __ethregs__
+#define __ethregs__
+
+// ====================================================================
+//
+// eth_regs.h
+//
+// Address mappings for ethernet and DMA controller registers
+//
+// ====================================================================
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Harald Brandl (harald.brandl@fh-joanneum.at)
+// Contributors: Harald Brandl
+// Date: 01.08.2004
+// Purpose: Ethernet and DMA controller registers
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+// Ethernet
+
+#define EthGenCR *(unsigned long *)0xff800000
+#define EthGenSR *(unsigned long *)0xff800004
+#define EthFIFODR *(unsigned long *)0xff800008
+#define EthFIFODRkickoff *(unsigned long *)0xff80000c
+#define EthTxSR *(unsigned long *)0xff800010
+#define EthRxSR *(unsigned long *)0xff800014
+#define MACCR *(unsigned long *)0xff800400
+#define MACTR *(unsigned long *)0xff800404
+#define PCSCR *(unsigned long *)0xff800408
+#define PCSTR *(unsigned long *)0xff80040c
+#define STLCR *(unsigned long *)0xff800410
+#define STLTR *(unsigned long *)0xff800414
+#define BtBIPGGapTimerR *(unsigned long *)0xff800440
+#define NonBtBIPGGapTimerR *(unsigned long *)0xff800444
+#define CollWinR *(unsigned long *)0xff800448
+#define TxPNCR *(unsigned long
*)0xff800460
+#define TxBCR *(unsigned long *)0xff800464
+#define ReTxBCR *(unsigned long *)0xff800468
+#define TxRNG *(unsigned long *)0xff80046c
+#define TxMRN *(unsigned long *)0xff800470
+#define TxCDec *(unsigned long
*)0xff800474
+#define TOTxC *(unsigned long *)0xff800478
+#define RxBC *(unsigned long *)0xff800480
+#define RxCDec *(unsigned long
*)0xff800484
+#define TORxC *(unsigned long *)0xff800488
+#define LnFC *(unsigned long *)0xff8004c0
+#define JC10M *(unsigned long *)0xff800500
+#define LoCC10M *(unsigned long *)0xff800504
+#define MIICR *(unsigned long *)0xff800540
+#define MIIAR *(unsigned long *)0xff800544
+#define MIIWDR *(unsigned long
*)0xff800548
+#define MIIRDR *(unsigned long
*)0xff80054c
+#define MIIIR *(unsigned long *)0xff800550
+#define CRCEC *(unsigned long *)0xff800580
+#define AEC *(unsigned long *)0xff800584
+#define CEC *(unsigned long *)0xff800588
+#define LFC *(unsigned long *)0xff80058c
+#define SFC *(unsigned long *)0xff800590
+#define LCC *(unsigned long *)0xff800594
+#define EDC *(unsigned long *)0xff800598
+#define MCC *(unsigned long *)0xff80059c
+#define SAFR *(unsigned long *)0xff8005c0
+#define SAR1 *(unsigned long *)0xff8005c4
+#define SAR2 *(unsigned long *)0xff8005c8
+#define SAR3 *(unsigned long *)0xff8005cc
+#define SAMHT1 *(unsigned long
*)0xff8005d0
+#define SAMHT2 *(unsigned long
*)0xff8005d4
+#define SAMHT3 *(unsigned long
*)0xff8005d8
+#define SAMHT4 *(unsigned long
*)0xff8005dc
+
+// DMA
+
+#define DMA1A_BDP *(unsigned long *)0xff900000
+#define DMA1A_CR *(unsigned long *)0xff900010
+#define DMA1A_SR *(unsigned long *)0xff900014
+#define DMA1B_BDP *(unsigned long *)0xff900020
+#define DMA1B_CR *(unsigned long *)0xff900030
+#define DMA1B_SR *(unsigned long *)0xff900034
+#define DMA1C_BDP *(unsigned long *)0xff900040
+#define DMA1C_CR *(unsigned long *)0xff900050
+#define DMA1C_SR *(unsigned long *)0xff900054
+#define DMA1D_BDP *(unsigned long *)0xff900060
+#define DMA1D_CR *(unsigned long *)0xff900070
+#define DMA1D_SR *(unsigned long *)0xff900074
+#define DMA2_BDP *(unsigned long *)0xff900080
+#define DMA2_CR *(unsigned long *)0xff900090
+#define DMA2_SR *(unsigned long *)0xff900094
+
+#endif
diff -Naur
ecos/packages/devs/eth/arm/netarm/current/include/netarm_eth_drv.h
my_ecos/packages/devs/eth/arm/netarm/current/include/netarm_eth_drv.h
--- ecos/packages/devs/eth/arm/netarm/current/include/netarm_eth_drv.h
1970-01-01 01:00:00.000000000 +0100
+++
my_ecos/packages/devs/eth/arm/netarm/current/include/netarm_eth_drv.h
2004-11-27 16:03:01.019876800 +0100
@@ -0,0 +1,62 @@
+#ifndef __netarm__
+#define __netarm__
+
+// ====================================================================
+//
+// netarm_eth_drv.h
+//
+// Device I/O - Description of NET+ARM ethernet hardware functions
+// and data structures
+//
+// ====================================================================
+// ====================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Harald Brandl (harald.brandl@fh-joanneum.at)
+// Contributors: Harald Brandl
+// Date: 01.08.2004
+// Purpose: Internal interfaces and data structures
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+// ====================================================================
+
+
+#define MaxKeys 20
+
+typedef struct
+{
+ unsigned char *RxBuffer;
+ unsigned short key_head, key_tail;
+ unsigned long KeyBuffer[MaxKeys];
+}private_data_t;
+
+typedef struct
+{
+ unsigned W: 1;
+ unsigned I: 1;
+ unsigned L: 1;
+ unsigned BufferPointer: 29;
+ unsigned : 16;
+ unsigned F: 1;
+ unsigned BufferLen: 15;
+}BDP_t;
+
+
+static bool netarm_init(struct cyg_netdevtab_entry *tab);
+
+static void netarm_recv(struct eth_drv_sc *sc, struct eth_drv_sg
*sg_list, int sg_len);
+static void netarm_deliver(struct eth_drv_sc *sc);
+static int netarm_can_send(struct eth_drv_sc *sc);
+static void netarm_send(
+ struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len,
int total_len, unsigned long key);
+static void netarm_start(struct eth_drv_sc *sc, unsigned char *enaddr,
int flags);
+static void netarm_stop(struct eth_drv_sc *sc);
+static int netarm_control(struct eth_drv_sc *sc, unsigned long key,
void *data, int len);
+static void netarm_poll(struct eth_drv_sc *sc);
+static int netarm_int_vector(struct eth_drv_sc *sc);
+
+static void SetMAC(unsigned char *esa);
+
+#endif
diff -Naur ecos/packages/devs/eth/arm/netarm/current/src/MII.c
my_ecos/packages/devs/eth/arm/netarm/current/src/MII.c
--- ecos/packages/devs/eth/arm/netarm/current/src/MII.c 1970-01-01
01:00:00.000000000 +0100
+++ my_ecos/packages/devs/eth/arm/netarm/current/src/MII.c
2004-11-27 16:13:14.031344000 +0100
@@ -0,0 +1,201 @@
+//=====================================================================
=====
+//
+// MII.c
+//
+// NetSilion NET+ARM PHY chip configuration
+//
+//=====================================================================
=====
+//=====================================================================
=====
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): Harald Brandl (harald.brandl@fh-joanneum.at)
+// Contributors: Harald Brandl
+// Date: 01.08.2004
+// Purpose: PHY chip configuration
+// Description:
+//
+//####DESCRIPTIONEND####
+//
+//=====================================================================
=====
+
+#include <stdio.h>
+#include <cyg/io/eth/eth_regs.h>
+#include <pkgconf/devs_eth_arm_netarm.h>
+#include <cyg/hal/hal_diag.h>
+
+
+#define PHYS(_i_) (0x800 | _i_)
+
+#define SysReg (unsigned int*)0xffb00004 // System Status
Register
+
+
+
+/* Function: void mii_poll_busy (void)
+ *
+ * Description:
+ * This routine is responsible for waiting for the current PHY
+ * operation to complete.
+ *
+ * Parameters:
+ * none
+ */
+
+void mii_poll_busy(void)
+{
+ /* check to see if PHY is busy with read or write */
+ while (MIIIR & 1)
+ HAL_DELAY_US(1);
+}
+
+/* Function: void mii_reset (void)
+ *
+ * Description:
+ *
+ * This routine resets the PHY.
+ *
+ * Return Values:
+ * none
+ */
+
+void mii_reset(void)
+{
+ MIIAR = PHYS(0); // select command register
+ MIIWDR = 0x8000; // reset
+ mii_poll_busy();
+}
+
+/* Function: cyg_bool mii_negotiate (void)
+ *
+ * Description:
+ * This routine is responsible for causing the external Ethernet
PHY
+ * to begin the negotatiation process.
+ *
+ * Parameters:
+ * none
+ *
+ * Return Value:
+ * 0: SUCCESS
+ * 1: ERROR
+ */
+
+cyg_bool mii_negotiate(void)
+{
+ int rev, timeout = 100000;
+
+ MIIAR = PHYS(4);
+
+ rev = *SysReg >> 24;
+ if(rev == 0) // Full duplex 100Mbps must be
disabled on NCC chip Revision 0 and 1.
+ MIIWDR = 0x61;
+ else if(rev < 4)
+ MIIWDR = 0xe1;
+ else
+ MIIWDR = 0x1e1;
+
+ mii_poll_busy();
+
+ MIIAR = PHYS(0);
+ MIIWDR |= 0x1200;
+
+ mii_poll_busy();
+
+ while(timeout)
+ {
+ MIIAR = PHYS(1);
+ MIICR = 1;
+
+ mii_poll_busy();
+
+ if(0x24 == (MIIRDR & 0x24))
+ return 0;
+ else
+ timeout--;
+ }
+
+ return 1;
+}
+
+
+/* Function: void mii_set_speed (cyg_bool speed, cyg_bool duplex)
+ *
+ * Description:
+ *
+ * This routine will set the speed and duplex of the external
PHY.
+ *
+ * Parameters:
+ * Speed
+ * 0: 10Mbit
+ * 1: 100Mbit
+ * Duplex
+ * 0: Half
+ * 1: Full
+ *
+ * Return Values:
+ * none
+ */
+
+void mii_set_speed(cyg_bool speed, cyg_bool duplex)
+{
+ unsigned long int timeout = 1000000;
+
+ MIIAR = PHYS(0); // select command register
+ MIIWDR = (speed << 13) | (duplex << 8); // set speed and duplex
+ mii_poll_busy();
+
+
+ while(timeout)
+ {
+ MIIAR = PHYS(1); // select status register
+ MIICR = 1;
+ mii_poll_busy();
+ if((MIIRDR) & 0x4)
+ break;
+ timeout--;
+ }
+}
+
+/* Function: cyg_bool mii_check_speed
+ *
+ * Description:
+ *
+ * This routine will check the operating speed of the ethernet
+ * interface.
+ *
+ * Parameters:
+ * none
+ *
+ * Return Values:
+ * 0: 10Mbit Speed
+ * 1: 100Mbit Speed
+ */
+
+cyg_bool mii_check_speed(void)
+{
+ MIIAR = PHYS(17);
+ MIICR = 1;
+ mii_poll_busy();
+ return (MIIRDR >> 14) & 1;
+}
+
+/* Function: void mii_check_duplex
+ *
+ * Description:
+ *
+ * This routine will check the operating duplex of the ethernet
+ * interface.
+ *
+ * Parameters:
+ * none
+ *
+ * Return Values:
+ * 0: Half Duplex
+ * 1: Full Duplex
+ */
+
+cyg_bool mii_check_duplex(void)
+{
+ MIIAR = PHYS(17);
+ MIICR = 1;
+ mii_poll_busy();
+ return (MIIRDR >> 9) & 1;
+}
diff -Naur
ecos/packages/devs/eth/arm/netarm/current/src/netarm_eth_drv.c
my_ecos/packages/devs/eth/arm/netarm/current/src/netarm_eth_drv.c
--- ecos/packages/devs/eth/arm/netarm/current/src/netarm_eth_drv.c
1970-01-01 01:00:00.000000000 +0100
+++ my_ecos/packages/devs/eth/arm/netarm/current/src/netarm_eth_drv.c
2004-11-27 16:10:49.062889600 +0100
@@ -0,0 +1,628 @@
+//=====================================================================
=====
+//
+// netarm_eth_drv.c
+//
+// NetSilion NET+ARM Ethernet Driver (DMA driven)
+//
+//=====================================================================
=====
+//=====================================================================
=====
+//#####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/io/eth/eth_regs.h>
+#include <cyg/io/eth/MII.h>
+#include <cyg/io/eth/netarm_eth_drv.h>
+
+
+#define CYGNUM_HAL_INTERRUPT_DMA2 31
+#define CYGNUM_HAL_INTERRUPT_DMA1 32
+
+
+#define BufferSizeA 128
+#define BufferSizeB 512
+#define BufferSizeC 1500
+
+#define NumA 10
+#define NumB 5
+#define NumC 10
+
+static cyg_mutex_t Key_Mutex;
+
+private_data_t driver_private = {NULL, 0, 0};
+
+unsigned char esa[6] = CYGDAT_DEVS_ETH_ARM_NETARM_ETH0_ESA;
+
+unsigned char RxBufferA[NumA][BufferSizeA];
+unsigned char RxBufferB[NumB][BufferSizeB];
+unsigned char RxBufferC[NumC][BufferSizeC];
+
+unsigned char TxBuffer[1500];
+unsigned char TxHeader[14];
+
+BDP_t RxBDP_A[NumA];
+BDP_t RxBDP_B[NumB];
+BDP_t RxBDP_C[NumC];
+
+BDP_t TxBDP[2];
+
+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);
+
+
+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:"
+ "LDR R3, [R1]!;"
+ "STR R3, [R0]!;"
+ "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"
+ );
+}
+
+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;
+}
+
+
+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);
+}
+
+unsigned long GetKey(private_data_t *pd)
+{
+ unsigned long 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
+}
+
+static void dma_rx_dsr(cyg_vector_t vector, cyg_ucount32 count,
cyg_addrword_t data)
+{
+
+ eth_drv_dsr( vector, count, data );
+
+ DMA1A_SR |= 0x80000000; // acknowledge normal completion
interrupt
+ DMA1B_SR |= 0x80000000;
+ 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 );
+
+ DMA2_SR |= 0x80000000; // acknowledge interrupt
+
+ cyg_drv_interrupt_unmask(vector);
+}
+
+static void SetupDMA(void)
+{
+ int i;
+
+ for(i = 0; i < NumA; i++)
+ {
+ RxBDP_A[i].BufferPointer = ((unsigned long)RxBufferA[i])
& 0x3fffffff;
+ RxBDP_A[i].BufferLen = BufferSizeA;
+ }
+
+ RxBDP_A[i - 1].W = 1;
+
+ for(i = 0; i < NumB; i++)
+ {
+ RxBDP_B[i].BufferPointer = ((unsigned long)RxBufferB[i])
& 0x3fffffff;
+ RxBDP_B[i].BufferLen = BufferSizeB;
+ }
+
+ RxBDP_B[i - 1].W = 1;
+
+ for(i = 0; i < NumC; i++)
+ {
+ RxBDP_C[i].BufferPointer = ((unsigned long)RxBufferC[i])
& 0x3fffffff;
+ RxBDP_C[i].BufferLen = BufferSizeC;
+ }
+
+ RxBDP_C[i - 1].W = 1;
+
+ DMA1A_BDP = (unsigned long)RxBDP_A;
+ DMA1A_CR = 0x82000000; //burst transfer
+ DMA1A_SR |= 0xa00000;
+
+ DMA1B_BDP = (unsigned long)RxBDP_B;
+ DMA1B_CR = 0x82000000; //burst transfer
+ DMA1B_SR |= 0xa00000;
+
+ DMA1C_BDP = (unsigned long)RxBDP_C;
+ DMA1C_CR = 0x82000000; //burst transfer
+ DMA1C_SR |= 0xa00000;
+
+
+ // setup dma transmitter
+
+ TxBDP[0].BufferPointer = ((unsigned long)TxHeader) & 0x3fffffff;
+ TxBDP[1].BufferPointer = ((unsigned long)TxBuffer) & 0x3fffffff;
+ TxBDP[1].L = 1;
+ TxBDP[1].W = 1;
+
+ DMA2_BDP = (unsigned long)TxBDP;
+ DMA2_CR = 0x86000000; //burst transfer
+ 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;
+
+ // setup dma receiver
+ SetupDMA();
+
+ mii_reset();
+ mii_negotiate(); // initialize
PHY
+ duplex = mii_check_duplex();
+
+ // Ethernet Controller Initializatition
+
+ MACCR = (0x1c | (duplex << 1));
// auto CRC, late collision retry
+ STLCR = 0x3;
// insert MAC source address into ethernet frame
+ BtBIPGGapTimerR = 0x14;
// standard values
+ NonBtBIPGGapTimerR = ((0x9 << 7) | 0x11);
// standard values
+ CollWinR = ((0x37 << 8) | 0xf);
// standard values
+ SAFR = 0x1;
// broadcast mode
+ EthGenCR = (0x40400400 | (duplex <<
16));// dma mode, full duplex, enable pNA mode(needed for alignment)
+
+ 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 long key;
+ private_data_t *pd = (private_data_t *)(sc->driver_private);
+
+ while((key = GetKey(pd)))
+ {
+ sc->funs->eth_drv->tx_done(sc, key, 0);
+ }
+
+ while(RxBDP_A[a].F)
+ {
+ pd->RxBuffer = (unsigned char
*)RxBDP_A[a].BufferPointer;
+ sc->funs->eth_drv->recv(sc, RxBDP_A[a].BufferLen);
+ RxBDP_A[a].BufferLen = BufferSizeA;
+ RxBDP_A[a].F = 0;
+ a = (a + 1) % NumA;
+ }
+
+ while(RxBDP_B[b].F)
+ {
+ pd->RxBuffer = (unsigned char
*)RxBDP_B[b].BufferPointer;
+ sc->funs->eth_drv->recv(sc, RxBDP_B[b].BufferLen);
+ RxBDP_B[b].BufferLen = BufferSizeB;
+ RxBDP_B[b].F = 0;
+ b = (b + 1) % NumB;
+ }
+
+ while(RxBDP_C[c].F)
+ {
+ pd->RxBuffer = (unsigned char
*)RxBDP_C[c].BufferPointer;
+ sc->funs->eth_drv->recv(sc, RxBDP_C[c].BufferLen);
+ RxBDP_C[c].BufferLen = BufferSizeC;
+ RxBDP_C[c].F = 0;
+ c = (c + 1) % NumC;
+ }
+
+ cyg_drv_dsr_lock();
+ DMA1A_SR |= 0x20000000;
+ DMA1B_SR |= 0x20000000;
+ DMA1C_SR |= 0x20000000;
+ cyg_drv_dsr_unlock();
+}
+
+
+static int netarm_can_send(struct eth_drv_sc *sc)
+{
+ private_data_t *pd = (private_data_t *)(sc->driver_private);
+
+ if(TxBDP[0].F || TxBDP[1].F || 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);
+ register int i, len;
+ register unsigned char *data, *buf = TxBuffer;
+
+ 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(i == 0)
+ {
+ if((unsigned long)data & 0x3)
+ {
+ memcpy(TxHeader, data, 0xe);
+ }
+ else
+ {
+ fastcopy(TxHeader, data, 0xe);
+ }
+
+ len -= 0xe;
+ data += 0xe;
+ }
+
+ if (len)
+ {
+ fastcopy(buf, data, len);
+ buf += len;
+ }
+ }
+
+ TxBDP[0].BufferLen = 0xe;
+ TxBDP[0].F = 1;
+ TxBDP[1].BufferLen = total_len - 0xe;
+ TxBDP[1].F = 1;
+
+ cyg_drv_dsr_lock();
+ 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
+ EthGenCR |= 0x80800000; // enable Rx und Tx FIFO
+ 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)
+{
+ EthGenCR &= 0x7f7fffff;
+ 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)
+{
+ switch (key)
+ {
+ case ETH_DRV_SET_MAC_ADDRESS:
+ return 0;
+ break;
+ case ETH_DRV_SET_MC_LIST:
+ case ETH_DRV_SET_MC_ALL:
+ return 0;
+ default:
+ return 1;
+ break;
+ }
+}
+
+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 *MAC)
+{
+ strcpy(esa, MAC);
+ SAR1 = (esa[1] << 8) | esa[0]; // set MAC address
+ SAR2 = (esa[3] << 8) | esa[2];
+ SAR3 = (esa[5] << 8) | esa[4];
+}
diff -Naur ecos/packages/ecos.db my_ecos/packages/ecos.db
--- ecos/packages/ecos.db 2004-11-30 13:31:59.917055700 +0100
+++ my_ecos/packages/ecos.db 2004-11-30 11:08:40.112772800 +0100
@@ -2333,6 +2333,16 @@
The NetARM HAL package provides the support needed to
run
eCos on an NetSilicon NetARM evaluation board."
}
+
+package CYGPKG_DEVS_ETH_ARM_NETARM {
+ alias { "ARM NET+50 ethernet driver"
+ devs_eth_arm_netarm netarm_eth_driver }
+ hardware
+ directory devs/eth/arm/netarm
+ script netarm_eth_driver.cdl
+ description "Ethernet driver for NET+50 ethernet
interfaces."
+}
+
#
------------------------------------------------------------------------
--
# ARM packages
package CYGPKG_HAL_ARM {
@@ -3793,8 +3803,10 @@
target netarm {
alias { "NetSilicon NetARM board" netarm }
packages { CYGPKG_HAL_ARM
- CYGPKG_HAL_ARM_NETARM
- }
+ CYGPKG_HAL_ARM_NETARM
+ CYGPKG_IO_SERIAL_ARM_NETARM
+ CYGPKG_DEVS_ETH_ARM_NETARM
+ }
description "
The netarm target provides the packages needed to run eCos on a
NetSilicon
NET+ARM evaluation board."