From 8b868a11d919c746f699dfe45da04214dfae147d Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 14 Dec 2000 17:53:53 +0000 Subject: 2000-12-11 Joel Sherrill * Makefile.am, configure.in, include/Makefile.am, wrapup/Makefile.am: Updated to reflect addition of network driver by Franck Julien . * include/m302_int.h, network/.cvsignore, network/Makefile.am, network/network.c: New file. --- c/src/lib/libbsp/m68k/gen68302/ChangeLog | 8 + c/src/lib/libbsp/m68k/gen68302/Makefile.am | 2 +- c/src/lib/libbsp/m68k/gen68302/configure.in | 4 + c/src/lib/libbsp/m68k/gen68302/include/Makefile.am | 9 +- c/src/lib/libbsp/m68k/gen68302/include/m302_int.h | 545 ++++++++++++ c/src/lib/libbsp/m68k/gen68302/network/.cvsignore | 2 + c/src/lib/libbsp/m68k/gen68302/network/Makefile.am | 37 + c/src/lib/libbsp/m68k/gen68302/network/network.c | 985 +++++++++++++++++++++ c/src/lib/libbsp/m68k/gen68302/wrapup/Makefile.am | 7 +- 9 files changed, 1594 insertions(+), 5 deletions(-) create mode 100644 c/src/lib/libbsp/m68k/gen68302/include/m302_int.h create mode 100644 c/src/lib/libbsp/m68k/gen68302/network/.cvsignore create mode 100644 c/src/lib/libbsp/m68k/gen68302/network/Makefile.am create mode 100644 c/src/lib/libbsp/m68k/gen68302/network/network.c (limited to 'c/src/lib/libbsp') diff --git a/c/src/lib/libbsp/m68k/gen68302/ChangeLog b/c/src/lib/libbsp/m68k/gen68302/ChangeLog index 46012daa3c..f990ef2173 100644 --- a/c/src/lib/libbsp/m68k/gen68302/ChangeLog +++ b/c/src/lib/libbsp/m68k/gen68302/ChangeLog @@ -1,3 +1,11 @@ +2000-12-11 Joel Sherrill + + * Makefile.am, configure.in, include/Makefile.am, + wrapup/Makefile.am: Updated to reflect addition of network driver + by Franck Julien . + * include/m302_int.h, network/.cvsignore, network/Makefile.am, + network/network.c: New file. + 2000-11-09 Ralf Corsepius * Makefile.am: Use ... instead of RTEMS_TOPdir in ACLOCAL_AMFLAGS. diff --git a/c/src/lib/libbsp/m68k/gen68302/Makefile.am b/c/src/lib/libbsp/m68k/gen68302/Makefile.am index f61c77f6c1..fcb8bc99d5 100644 --- a/c/src/lib/libbsp/m68k/gen68302/Makefile.am +++ b/c/src/lib/libbsp/m68k/gen68302/Makefile.am @@ -7,7 +7,7 @@ ACLOCAL_AMFLAGS = -I ../../../../../../aclocal # wrapup is the one that actually builds and installs the library # from the individual .rel files built in other directories -SUBDIRS = . include start startup clock console timer wrapup +SUBDIRS = . include start startup clock console timer network wrapup include $(top_srcdir)/../../bsp.am diff --git a/c/src/lib/libbsp/m68k/gen68302/configure.in b/c/src/lib/libbsp/m68k/gen68302/configure.in index f5daf792a6..f214286644 100644 --- a/c/src/lib/libbsp/m68k/gen68302/configure.in +++ b/c/src/lib/libbsp/m68k/gen68302/configure.in @@ -17,8 +17,11 @@ RTEMS_CANONICALIZE_TOOLS RTEMS_ENV_RTEMSBSP RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP) RTEMS_CHECK_BSP_CACHE(RTEMS_BSP) +RTEMS_CHECK_NETWORKING RTEMS_CANONICAL_HOST +AM_CONDITIONAL(HAS_NETWORKING,test "$HAS_NETWORKING" = "yes") + RTEMS_PROJECT_ROOT # Explicitly list all Makefiles here @@ -27,6 +30,7 @@ Makefile clock/Makefile console/Makefile include/Makefile +network/Makefile start/Makefile startup/Makefile timer/Makefile diff --git a/c/src/lib/libbsp/m68k/gen68302/include/Makefile.am b/c/src/lib/libbsp/m68k/gen68302/include/Makefile.am index 2b8181354c..fd41652289 100644 --- a/c/src/lib/libbsp/m68k/gen68302/include/Makefile.am +++ b/c/src/lib/libbsp/m68k/gen68302/include/Makefile.am @@ -4,7 +4,7 @@ AUTOMAKE_OPTIONS = foreign 1.4 -H_FILES = bsp.h coverhd.h +H_FILES = bsp.h coverhd.h m302_int.h $(PROJECT_INCLUDE): $(mkinstalldirs) $@ @@ -12,14 +12,17 @@ $(PROJECT_INCLUDE): $(PROJECT_INCLUDE)/bsp.h: bsp.h $(INSTALL_DATA) $< $@ +$(PROJECT_INCLUDE)/m302_int.h: m302_int.h + $(INSTALL_DATA) $< $@ + $(PROJECT_INCLUDE)/coverhd.h: coverhd.h $(INSTALL_DATA) $< $@ TMPINSTALL_FILES += $(PROJECT_INCLUDE) $(PROJECT_INCLUDE)/bsp.h \ - $(PROJECT_INCLUDE)/coverhd.h + $(PROJECT_INCLUDE)/coverhd.h $(PROJECT_INCLUDE)/m302_int.h all-local: $(TMPINSTALL_FILES) -EXTRA_DIST = bsp.h coverhd.h +EXTRA_DIST = bsp.h coverhd.h m302_int.h include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/m68k/gen68302/include/m302_int.h b/c/src/lib/libbsp/m68k/gen68302/include/m302_int.h new file mode 100644 index 0000000000..0bbe9515bc --- /dev/null +++ b/c/src/lib/libbsp/m68k/gen68302/include/m302_int.h @@ -0,0 +1,545 @@ +/* + * Implements the Motorola 68302 multi-protocol chip parameter + * definition header. + * + * $Id$ + */ + +#ifndef __M302_INT_h +#define __M302_INT_h + +#ifndef uchar +#define uchar unsigned char +#endif +#ifndef ushort +#define ushort unsigned short +#endif +#ifndef ulong +#define ulong unsigned long +#endif + +/* Ethernet Control Register ECNTRL */ +#define ECNTRL_BIT_RESET 0x0001 +#define ECNTRL_BIT_ETHER_EN 0x0002 +#define ECNTRL_BIT_GTS 0x0004 + +/* Ethernet DMA Configuration Status Register EDMA */ +#define EDMA_BDERR_MASK 0xFE00 + +#define EDMA_BDSIZE_MASK 0x00C0 +#define EDMA_BDSIZE_8T_120R 0x0000 +#define EDMA_BDSIZE_16T_112R 0x0040 +#define EDMA_BDSIZE_32T_96R 0x0080 +#define EDMA_BDSIZE_64T_64R 0x00C0 + +#define EDMA_BIT_TSRLY 0x0020 + +#define EDMA_WMRK_MASK 0x0018 +#define EDMA_WMRK_8FIFO 0x0000 +#define EDMA_WMRK_16FIFO 0x0008 +#define EDMA_WMRK_24FIFO 0x0010 +#define EDMA_WMRK_32FIFO 0x0018 + +#define EDMA_BLIM_MASK 0x0007 +#define EDMA_BLIM_8ACCESS 0x0003 + + +/* Ethernet Maximum Receive Buffer Length EMRBLR */ +#define EMRBLR_MASK 0x07FFE + +/* Interrupt Vector Register IVEC */ +#define IVEC_BIT_VG 0x0100 +#define IVEC_INV_MASK 0x00FF + +/* Interrupt Event Register INTR_EVENT */ +#define INTR_EVENT_BIT_RXB 0x0001 +#define INTR_EVENT_BIT_TXB 0x0002 +#define INTR_EVENT_BIT_BSY 0x0004 +#define INTR_EVENT_BIT_RFINT 0x0008 +#define INTR_EVENT_BIT_TFINT 0x0010 +#define INTR_EVENT_BIT_EBERR 0x0020 +#define INTR_EVENT_BIT_BOD 0x0040 +#define INTR_EVENT_BIT_GRA 0x0080 +#define INTR_EVENT_BIT_BABT 0x0100 +#define INTR_EVENT_BIT_BABR 0x0200 +#define INTR_EVENT_BIT_HBERR 0x0400 + +/* Interrupt Mask Register INTR_MASK */ +#define INTR_MASK_BIT_RXIEN 0x0001 +#define INTR_MASK_BIT_TXIEN 0x0002 +#define INTR_MASK_BIT_BSYEN 0x0004 +#define INTR_MASK_BIT_RFIEN 0x0008 +#define INTR_MASK_BIT_TFIEN 0x0010 +#define INTR_MASK_BIT_EBERREN 0x0020 +#define INTR_MASK_BIT_BODEN 0x0040 +#define INTR_MASK_BIT_GRAEN 0x0080 +#define INTR_MASK_BIT_BTEN 0x0100 +#define INTR_MASK_BIT_BREN 0x0200 +#define INTR_MASK_BIT_HBEEN 0x0400 + +/* Ethernet Configuration ECNFIG */ +#define ECNFIG_BIT_LOOP 0x0001 +#define ECNFIG_BIT_FDEN 0x0002 +#define ECNFIG_BIT_HBC 0x0004 +#define ECNFIG_BIT_RDT 0x0008 + +/* Ethernet Test ETHER_TEST */ +#define ETHER_TEST_BIT_TWS 0x0001 +#define ETHER_TEST_BIT_RWS 0x0002 +#define ETHER_TEST_BIT_DRTY 0x0004 +#define ETHER_TEST_BIT_COLL 0x0008 +#define ETHER_TEST_BIT_SLOT 0x0010 +#define ETHER_TEST_BIT_TRND 0x0020 +#define ETHER_TEST_BIT_TBO 0x0040 +#define ETHER_TEST_BIT_RNGT 0x0080 +#define ETHER_TEST_REV_MASK 0xF000 + +/* Ethernet AR Control Registere AR_CNTRL */ +#define AR_CNTRL_BIT_PROM 0x0400 +#define AR_CNTRL_BIT_PA_REJ 0x0800 +#define AR_CNTRL_BIT_NO_BROADCAST 0x1000 +#define AR_CNTRL_BIT_MULTI1 0x2000 +#define AR_CNTRL_BIT_INDEX_EN 0x4000 +#define AR_CNTRL_BIT_HASH_EN 0x8000 + +#define AR_CNTRL_MULTI_MASK (AR_CNTRL_BIT_MULTI0 | AR_CNTRL_BIT_MULTI1) + + +/* Ethernet buffer Status TX */ +#define BUF_STAT_CARRIER_LOST 0x0001 +#define BUF_STAT_UNDERRUN 0x0002 +#define BUF_STAT_RETRANS_COUNT 0x003C +#define BUF_STAT_RETRY_LIMIT 0x0040 +#define BUF_STAT_LATE_COLLISION 0x0080 +#define BUF_STAT_HEARTBIT 0x0100 +#define BUF_STAT_DEFER 0x0200 +#define BUF_STAT_TX_CRC 0x0400 +#define BUF_STAT_LAST 0x0800 +#define BUF_STAT_INTERRUPT 0x1000 +#define BUF_STAT_WRAP 0x2000 +#define BUF_STAT_TO 0x4000 +#define BUF_STAT_READY 0x8000 + + +/* Ethernet buffer Status RX */ +#define BUF_STAT_COLLISION 0x0001 +#define BUF_STAT_OVERRUN 0x0002 +#define BUF_STAT_CRC_ERROR 0x0004 +#define BUF_STAT_SHORT 0x0008 +#define BUF_STAT_NONALIGNED 0x0010 +#define BUF_STAT_LONG 0x0020 +#define BUF_STAT_FIRST_IN_FRAME 0x0400 +#define BUF_STAT_EMPTY 0x8000 + + /* SCC Buffer Descriptor structure + ----------------------------------*/ + +struct m68302_scc_bd { + ushort stat_ctrl; + ushort data_lgth; + uchar *p_buffer; +}; + +#define M68302_scc_bd_stat_ctrl(p) \ + (((struct m68302_scc_bd *)(p)) -> stat_ctrl) +#define M68302_scc_bd_data_lgth(p) \ + (((struct m68302_scc_bd *)(p)) -> data_lgth) +#define M68302_scc_bd_p_buffer(p) \ + (((struct m68302_scc_bd *)(p)) -> p_buffer) + +struct m68302_imp { + +/* BASE : user data memory */ + + uchar user_data[0x240]; /* 0x240 bytes user data */ + uchar user_reserved[0x1c0]; /* empty till 0x400 */ + +/* BASE + 400H: PARAMETER RAM */ + struct { + struct m68302_scc_bd scc_bd_rx[8]; /* Rx buffer descriptors */ + struct m68302_scc_bd scc_bd_tx[8]; /* Tx buffer descriptors */ + + uchar rfcr; /* Rx function code */ + uchar tfcr; /* Tx function code */ + ushort mrblr; /* maximum Rx buffer length */ + ushort rist; /* internal state */ + uchar res1; + uchar rbdn; /* Rx internal buffer number */ + ulong ridp; + ushort ribc; + ushort rtmp; + ushort tist; + uchar res2; + uchar tbdn; /* Tx internal buffer number */ + ulong tidp; + ushort tibc; + ushort ttmp; + + unsigned char scc_spp [0x64]; /* SCC specific parameters */ + } parm_ram [3]; + + uchar reserved_1 [0x100]; + +/* BASE + 800H: INTERNAL REGISTERS */ + + /* DMA */ + + ushort dma_res1; /* reserved */ + ushort dma_mode; /* dma mode reg */ + ulong dma_src; /* dma source */ + ulong dma_dest; /* dma destination */ + ushort dma_count; /* dma byte count */ + uchar dma_status; /* dma status */ + uchar dma_res2; /* reserved */ + uchar dma_fct_code; /* dma function code */ + uchar dma_res3; /* reserved */ + + /* Interrupt Controller */ + + ushort it_mode; /* interrupt mode register */ + ushort it_pending; /* interrupt pending register */ + ushort it_mask; /* interrupt mask register */ + ushort it_inservice; /* interrupt in service register */ + ulong it_reserved; /* reserved */ + + /* Parallel I/O */ + + struct { + ushort control; /* port control register */ + ushort direction; /* port data direction register */ + ushort data; /* port data value register */ + } port[2]; + + ushort p_reserved; /* reserved */ + + /* Chip Select */ + + ulong cs_reserved; + + struct { + ushort base; /* chip select base register */ + ushort option; /* chip select option register */ + } cs[4]; + + /* Timer */ + + ushort t1_mode; /* timer 1 mode register */ + ushort t1_reference; /* timer 1 reference register */ + ushort t1_capture; /* timer 1 capture register */ + ushort t1_counter; /* timer 1 counter */ + uchar tim_res1; /* reserved */ + uchar t1_event; /* timer 1 event */ + + ushort t3_reference; /* timer 3 reference register */ + ushort t3_counter; /* timer 3 counter */ + ushort tim_res2; /* reserved */ + + ushort t2_mode; /* timer 2 mode register */ + ushort t2_reference; /* timer 2 reference register */ + ushort t2_capture; /* timer 2 capture register */ + ushort t2_counter; /* timer 2 counter */ + uchar tim_res3; /* reserved */ + uchar t2_event; /* timer 2 event */ + ushort tim_res4[3]; /* reserved */ + + /* command register */ + + uchar cp_cmd; /* communication processor command register */ + uchar cp_cmd_res; /* reserved */ + + /* reserved */ + + uchar reserved_2[0x1e]; + + /* SCC registers */ + + struct scc_regs { + ushort resvd; /* reserved */ + ushort scon; /* SCC configuration register */ + ushort scm; /* SCC mode register */ + ushort dsr; /* SCC sync register */ + uchar scce; /* SCC event register */ + uchar res1; /* reserved */ + uchar sccm; /* SCC mask register */ + uchar res2; /* reserved */ + uchar sccs; /* SCC status register */ + uchar res3; /* reserved */ + ushort res4; /* reserved */ + } scc_regs[3]; + + /* SP (SCP + SMI) */ + + ushort scc_mode_reg; /* scp, smi mode + clock control */ + + /* Serial Interface */ + + ushort serial_int_mask; /* mask register */ + ushort serial_int_mode; /* mode register */ + + /* reserved */ + + uchar reserved_3[0x74A]; + + + +/****************** 68 EN 302 specific registers **********************/ +/** only available here if + M68302_INTERNAL_RAM_BASE_ADD+0x1000=M68EN302_INTERNAL_RAM_BASE_ADD*/ + + /* Module Bus Control Registers */ + + ushort mbc; /* module bus control register MBC */ + ushort ier; /* interrupt extension register IER */ + ushort cser[4]; /* Chip Select extension registers CSERx */ + ushort pcsr; /* parity control & status register PCSR */ + + ushort mbc_reserved; + + /* DRAM Controller Registers */ + + ushort dcr; /* DRAM Configuration register DCR */ + ushort drfrsh; /* DRAM Refresh register DRFRSH */ + ushort dba[2]; /* DRAM Bank Base Address Register */ + + uchar dram_reserved[0x7E8]; + + + /* Ethernet Controller Registers */ + + ushort ecntrl; /* Ethernet Control Register */ + ushort edma; /* Ethernet DMA Configuration Register */ + ushort emrblr; /* Ethernet Max receive buffer length */ + ushort intr_vect; /* Interruppt vector register */ + ushort intr_event; /* Interruppt event register */ + ushort intr_mask; /* Interruppt mask register */ + ushort ecnfig; /* Ethernet Configuration */ + ushort ether_test; /* Ethernet Test register */ + ushort ar_cntrl; /* Address Recognition Control register */ + + uchar eth_reserved[0x1EE]; + + uchar cet[0x200]; /* CAM Entry Table */ + struct m68302_scc_bd eth_bd[128]; /* Ethernet Buffer Descriptors Table */ + +}; + +#define M68302imp_ a_m68302_imp -> + +#define M68302imp_a_scc_bd_rx(scc,bd) \ + (struct m68302_scc_bd FAR *)(&(M68302imp_ parm_ram[scc].scc_bd_rx[bd])) +#define M68302imp_a_scc_bd_tx(scc,bd) \ + (struct m68302_scc_bd FAR *)(&(M68302imp_ parm_ram[scc].scc_bd_tx[bd])) + +#define M68302imp_scc_rfcr(scc) (M68302imp_ parm_ram[scc].rfcr) +#define M68302imp_scc_tfcr(scc) (M68302imp_ parm_ram[scc].tfcr) +#define M68302imp_scc_mrblr(scc) (M68302imp_ parm_ram[scc].mrblr) +#define M68302imp_scc_rbdn(scc) (M68302imp_ parm_ram[scc].rbdn) +#define M68302imp_scc_tbdn(scc) (M68302imp_ parm_ram[scc].tbdn) + +#define M68302imp_a_scc_spp(scc) ((struct m68302_scc_spp FAR *)(M68302imp_ parm_ram[scc].scc_spp)) + +#define M68302imp_dma_res1 (M68302imp_ dma_res1) +#define M68302imp_dma_mode (M68302imp_ dma_mode) +#define M68302imp_dma_src (M68302imp_ dma_src) +#define M68302imp_dma_dest (M68302imp_ dma_dest) +#define M68302imp_dma_count (M68302imp_ dma_count) +#define M68302imp_dma_status (M68302imp_ dma_status) +#define M68302imp_dma_fct_code (M68302imp_ dma_fct_code) + +#define M68302imp_it_mode (M68302imp_ it_mode) +#define M68302imp_it_pending (M68302imp_ it_pending) +#define M68302imp_it_mask (M68302imp_ it_mask) +#define M68302imp_it_inservice (M68302imp_ it_inservice) + +#define M68302imp_cs_base(i) (M68302imp_ cs[i].base) +#define M68302imp_cs_option(i) (M68302imp_ cs[i].option) + +#define M68302imp_port_control(i) (M68302imp_ port[i].control) +#define M68302imp_port_direction(i) (M68302imp_ port[i].direction) +#define M68302imp_port_data(i) (M68302imp_ port[i].data) + +#define M68302imp_timer1_mode (M68302imp_ t1_mode) +#define M68302imp_timer1_reference (M68302imp_ t1_reference) +#define M68302imp_timer1_capture (M68302imp_ t1_capture) +#define M68302imp_timer1_counter (M68302imp_ t1_counter) +#define M68302imp_timer1_event (M68302imp_ t1_event) +#define M68302imp_timer3_reference (M68302imp_ t3_reference) +#define M68302imp_timer3_counter (M68302imp_ t3_counter) +#define M68302imp_timer2_mode (M68302imp_ t2_mode) +#define M68302imp_timer2_reference (M68302imp_ t2_reference) +#define M68302imp_timer2_capture (M68302imp_ t2_capture) +#define M68302imp_timer2_counter (M68302imp_ t2_counter) +#define M68302imp_timer2_event (M68302imp_ t2_event) + +#define M68302imp_cp_cmd (M68302imp_ cp_cmd) + +#define M68302imp_scc_mode_reg (M68302imp_ scc_mode_reg) + +#define M68302imp_serial_int_mask (M68302imp_ serial_int_mask) +#define M68302imp_serial_int_mode (M68302imp_ serial_int_mode) +#define M68302imp_simask (M68302imp_serial_int_mask) +#define M68302imp_simode (M68302imp_serial_int_mode) + +#define M68302imp_scon(i) (M68302imp_ scc_regs[i].scon) +#define M68302imp_scm(i) (M68302imp_ scc_regs[i].scm) +#define M68302imp_dsr(i) (M68302imp_ scc_regs[i].dsr) +#define M68302imp_scce(i) (M68302imp_ scc_regs[i].scce) +#define M68302imp_sccm(i) (M68302imp_ scc_regs[i].sccm) +#define M68302imp_sccs(i) (M68302imp_ scc_regs[i].sccs) + + +/*----------------------------------------------------------------------------*/ + +#define M68en302imp_mbc (M68302imp_ mbc) +#define M68en302imp_ier (M68302imp_ ier) +#define M68en302imp_cser(i) (M68302imp_ cser[i]) +#define M68en302imp_pcsr (M68302imp_ pcsr) + +#define M68en302imp_dcr (M68302imp_ dcr) +#define M68en302imp_drfrsh (M68302imp_ drfrsh) +#define M68en302imp_dba(i) (M68302imp_ dba[i]) + + +#define M68en302imp_ecntrl (M68302imp_ ecntrl) +#define M68en302imp_edma (M68302imp_ edma) +#define M68en302imp_emrblr (M68302imp_ emrblr) +#define M68en302imp_intr_vect (M68302imp_ intr_vect) +#define M68en302imp_intr_event (M68302imp_ intr_event) +#define M68en302imp_intr_mask (M68302imp_ intr_mask) +#define M68en302imp_ecnfig (M68302imp_ ecnfig) +#define M68en302imp_ether_test (M68302imp_ ether_test) +#define M68en302imp_ar_cntrl (M68302imp_ ar_cntrl) + +#define M68en302imp_cet (M68302imp_ cet) + +#define M68302imp_a_eth_bd(bd) \ + (struct m68302_scc_bd *)(&(M68302imp_ eth_bd[bd])) + +/* PORTS */ + +#define PA0 0x0001 /* PORT A bit 0 */ +#define PA1 0x0002 /* PORT A bit 1 */ +#define PA2 0x0004 /* PORT A bit 2 */ +#define PA3 0x0008 /* PORT A bit 3 */ +#define PA4 0x0010 /* PORT A bit 4 */ +#define PA5 0x0020 /* PORT A bit 5 */ +#define PA6 0x0040 /* PORT A bit 6 */ +#define PA7 0x0080 /* PORT A bit 7 */ +#define PA8 0x0100 /* PORT A bit 8 */ +#define PA9 0x0200 /* PORT A bit 9 */ +#define PA10 0x0400 /* PORT A bit 10 */ +#define PA11 0x0800 /* PORT A bit 11 */ +#define PA12 0x1000 /* PORT A bit 12 */ +#define PA13 0x2000 /* PORT A bit 13 */ +#define PA14 0x4000 /* PORT A bit 14 */ +#define PA15 0x8000 /* PORT A bit 15 */ + +#define PB0 0x0001 /* PORT B bit 0 */ +#define PB1 0x0002 /* PORT B bit 1 */ +#define PB2 0x0004 /* PORT B bit 2 */ +#define PB3 0x0008 /* PORT B bit 3 */ +#define PB4 0x0010 /* PORT B bit 4 */ +#define PB5 0x0020 /* PORT B bit 5 */ +#define PB6 0x0040 /* PORT B bit 6 */ +#define PB7 0x0080 /* PORT B bit 7 */ +#define PB8 0x0100 /* PORT B bit 8 */ +#define PB9 0x0200 /* PORT B bit 9 */ +#define PB10 0x0400 /* PORT B bit 10 */ + +#define PB11 0x0800 /* PORT B bit 11 */ + +/* MODULE BUS CONTROL (MBCTL) */ + +#define MBC_BCE 0x8000 +#define MBC_MFC2 0x4000 +#define MBC_MFC1 0x2000 +#define MBC_MFC0 0x1000 +#define MBC_BB 0x0800 +#define MBC_PPE 0x0400 +#define MBC_PM9 0x0200 +#define MBC_PM8 0x0100 +#define MBC_PM7 0x0080 +#define MBC_PM6 0x0040 +#define MBC_PM5 0x0020 +#define MBC_PM4 0x0010 +#define MBC_PM3 0x0008 +#define MBC_PM2 0x0004 +#define MBC_PM1 0x0002 +#define MBC_PM0 0x0001 + + /* DRAM CONFIGURATION REG (DCR) */ + +#define DCR_SU0 0x0001 +#define DCR_SU1 0x0002 +#define DCR_WP0 0x0004 +#define DCR_WP1 0x0008 +#define DCR_W0 0x0010 +#define DCR_W1 0x0020 +#define DCR_P0 0x0040 +#define DCR_P1 0x0080 +#define DCR_PE0 0x0100 +#define DCR_PE1 0x0200 +#define DCR_E0 0x0400 +#define DCR_E1 0x0800 + +/* M68302 INTERNAL RAM BASE ADDRESS INSTALLATION */ + +#define M68302_ram_base_add_install(base_reg_add,ram_base_add) \ + do { \ + *((ushort *)base_reg_add) = (ushort)(ram_base_add >> 12); \ + a_m68302_imp = (struct m68302_imp *)ram_base_add; \ + } while (0) + +#define M68302_system_ctrl_reg_install(val) (*((ulong *)M68302_SCR_ADD) = val) + + /* INTERRUPTION */ + + /* Interrupt mode selection */ + +#define M68302_it_mode_install(mode,vector_bank, \ + extvect1,extvect6,extvect7,edgetrig1,edgetrig6,edgetrig7) \ + M68302imp_it_mode = 0 | (mode << 15) | (vector_bank << 5) | \ + (extvect7 << 14) | (extvect6 << 13) | (extvect1 <<12) | \ + (edgetrig7 << 10) | (edgetrig6 << 9)|(edgetrig1 << 8) + + /* CHIP SELECTION */ + + /* 'read_write' support values : + * + * M68302_CS_READ_ONLY for read only memory access chip select + * M68302_CS_READ_WRITE_ONLY for write only memory access chip select + * M68302_CS_READ_AND_WRITE for read & write memory access chip select + * + * 'nb_wait_state' : number of wait-state(s) from 0 to 6, 7 for external + * + */ +#define M68302_CS_READ_ONLY 0x02 /* read only memory access */ +#define M68302_CS_WRITE_ONLY 0x22 /* write only memory access */ +#define M68302_CS_READ_AND_WRITE 0x00 /* read and write memory access */ + + +#define M68302_cs_install(cs_nb,base_add,range,nb_wait_state,read_write) \ + do { \ + M68302imp_cs_option(cs_nb) = (((~(range - 1)) >> 11) & 0x1FFC) | \ + (nb_wait_state << 13) | (read_write & 0x2); \ + M68302imp_cs_base(cs_nb) = (((base_add >> 11) & 0x1FFC) | \ + ((read_write >> 4) & 0x2) | 1); \ + } while (0) + +#define M68302_set_cs_br(base_add, read_write) \ + ((((base_add) >> 11) & 0x1FFC) | (((read_write) >> 4) & 0x2) | 1) + +#define M68302_set_cs_or(range, nb_wait_state, read_write) \ + ((((~(range - 1)) >> 11) & 0x1FFC) | \ + ((nb_wait_state) << 13) | ((read_write) & 0x2)) + +#define M68302_get_cs_br(cs) \ + (((ulong)((M68302imp_cs_base(cs)) & 0x1FFC)) << 11 ) + +/* DRAM */ + +#define M68en302_dram_install(bank,base_add,range) \ + M68en302imp_dba (bank) = \ + (((base_add >> 8) & 0xFE00) | (((~(range-1))>>16) & 0x007E) | 1) + +#endif diff --git a/c/src/lib/libbsp/m68k/gen68302/network/.cvsignore b/c/src/lib/libbsp/m68k/gen68302/network/.cvsignore new file mode 100644 index 0000000000..282522db03 --- /dev/null +++ b/c/src/lib/libbsp/m68k/gen68302/network/.cvsignore @@ -0,0 +1,2 @@ +Makefile +Makefile.in diff --git a/c/src/lib/libbsp/m68k/gen68302/network/Makefile.am b/c/src/lib/libbsp/m68k/gen68302/network/Makefile.am new file mode 100644 index 0000000000..82809cccf9 --- /dev/null +++ b/c/src/lib/libbsp/m68k/gen68302/network/Makefile.am @@ -0,0 +1,37 @@ +## +## $Id$ +## + +AUTOMAKE_OPTIONS = foreign 1.4 + +PGM = $(ARCH)/network.rel + +C_FILES = network.c +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o) + +OBJS = $(C_O_FILES) + +include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +AM_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__ + +$(PGM): $(OBJS) + $(make-rel) + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile + +if HAS_NETWORKING +all-local: $(ARCH) $(OBJS) $(PGM) +endif + +.PRECIOUS: $(PGM) + +EXTRA_DIST = network.c + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/m68k/gen68302/network/network.c b/c/src/lib/libbsp/m68k/gen68302/network/network.c new file mode 100644 index 0000000000..9a058d8003 --- /dev/null +++ b/c/src/lib/libbsp/m68k/gen68302/network/network.c @@ -0,0 +1,985 @@ +/* + * RTEMS driver for M68360 SCC1 Ethernet + * W. Eric Norum + * Saskatchewan Accelerator Laboratory + * University of Saskatchewan + * Saskatoon, Saskatchewan, CANADA + * eric@skatter.usask.ca + * + * $Id$ + * + * Modify for Motorola 68en320 Ethernet Controller + * CXR S.A. France - 2000/09/14 - franckj@cxr.fr + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* + * Number of SCCs supported by this driver + */ +#define NSCCDRIVER 1 + +/* + * Default number of buffer descriptors set aside for this driver. + * The number of transmit buffer descriptors has to be quite large + * since a single frame often uses four or more buffer descriptors. + */ +#define RX_BUF_COUNT 64 +#define TX_BUF_COUNT 64 + +/* + * RTEMS event used by interrupt handler to signal driver tasks. + * This must not be any of the events used by the network task synchronization. + */ +#define INTERRUPT_EVENT RTEMS_EVENT_1 + +/* + * RTEMS event used to start transmit daemon. + * This must not be the same as INTERRUPT_EVENT. + */ +#define START_TRANSMIT_EVENT RTEMS_EVENT_2 + +/* + * Receive buffer size -- Allow for a full ethernet packet including CRC + */ +#define RBUF_SIZE 1520 + +#if (MCLBYTES < RBUF_SIZE) +# error "Driver must have MCLBYTES > RBUF_SIZE" +#endif + +static struct m68302_imp * a_m68302_imp; + +#define M302_ETHER_IVECTOR 0x40 + +/* + * Per-device data + */ +struct scc_softc { + struct arpcom arpcom; + struct mbuf **rxMbuf; + struct mbuf **txMbuf; + int acceptBroadcast; + int rxBdCount; + int txBdCount; + int txBdHead; + int txBdTail; + int txBdActiveCount; + + struct m68302_scc_bd *rxBdBase; + struct m68302_scc_bd *txBdBase; + + rtems_id rxDaemonTid; + rtems_id txDaemonTid; + + /* + * Statistics + */ + unsigned long rxInterrupts; + unsigned long rxNotFirst; + unsigned long rxNotLast; + unsigned long rxGiant; + unsigned long rxNonOctet; + unsigned long rxRunt; + unsigned long rxBadCRC; + unsigned long rxOverrun; + unsigned long rxCollision; + + unsigned long txInterrupts; + unsigned long txDeferred; + unsigned long txHeartbeat; + unsigned long txLateCollision; + unsigned long txRetryLimit; + unsigned long txUnderrun; + unsigned long txLostCarrier; + unsigned long txRawWait; + unsigned long txCoalesced; + unsigned long txCoalesceFailed; + unsigned long txRetry; +}; +static struct scc_softc scc_softc[NSCCDRIVER]; + +/* + * interrupt handler + */ +static rtems_isr +m302Enet_interrupt_handler (rtems_vector_number v) +{ + + /* + * Frame received? + */ + if (M68en302imp_intr_event & INTR_EVENT_BIT_RFINT) { + M68en302imp_intr_event = INTR_EVENT_BIT_RFINT; + M68en302imp_intr_mask &= ~INTR_MASK_BIT_RFIEN; + scc_softc[0].rxInterrupts++; + rtems_event_send (scc_softc[0].rxDaemonTid, INTERRUPT_EVENT); + } + + /* + * Buffer transmitted or transmitter error? + */ + if ((M68en302imp_intr_event & INTR_EVENT_BIT_TFINT) || + ((M68en302imp_intr_event & INTR_EVENT_BIT_TXB))){ + M68en302imp_intr_event = INTR_EVENT_BIT_TFINT | INTR_EVENT_BIT_TXB; + M68en302imp_intr_mask &= ~(INTR_MASK_BIT_TFIEN | INTR_MASK_BIT_TXIEN); + scc_softc[0].txInterrupts++; + rtems_event_send (scc_softc[0].txDaemonTid, INTERRUPT_EVENT); + } +} + +/* + * Initialize the ethernet hardware + */ +static void +m302Enet_initialize_hardware (struct scc_softc *sc) +{ + int i; + unsigned char *hwaddr; + rtems_status_code status; + rtems_isr_entry old_handler; + struct m68302_scc_bd *a_bd; /* Buffer Descriptor pointer */ + ushort *cam; + void **p; + ushort tmp; +#define LBK 0x0008 +#define DSQE 0x0010 +#define FDE 0x0020 + + + + /* + * standard loopback + */ + M68302imp_port_data (1) &= ~(LBK); + M68302imp_port_data (1) |= (FDE); + + + M68en302imp_ecntrl=0x0001; + /* + * Set dma configuration status register EDMA + */ + i = (sc->txBdCount == 16) ? EDMA_BDSIZE_16T_112R : + (sc->txBdCount == 32) ? EDMA_BDSIZE_32T_96R : + (sc->txBdCount == 64) ? EDMA_BDSIZE_64T_64R : + EDMA_BDSIZE_8T_120R; + + M68en302imp_edma = EDMA_BLIM_8ACCESS | EDMA_WMRK_16FIFO | EDMA_BIT_TSRLY | (ushort)i; + + /* + * Set maximum receive buffer length + */ + + M68en302imp_emrblr = RBUF_SIZE; /* 1520 */ + + /* + * Set interrupt vector + */ + M68en302imp_intr_vect = M302_ETHER_IVECTOR; + + + M68en302imp_intr_mask=0x0; + + /* + * Set ethernet Configuration + */ + M68en302imp_ecnfig=0x0000; + + /* + * Set ETHER_TEST + */ + M68en302imp_ether_test=0x0000; + + /* + * Set AR control Register + * Ignore/accept broadcast packets as specified + */ + M68en302imp_ar_cntrl = ((sc->acceptBroadcast) ? 0 : AR_CNTRL_BIT_NO_BROADCAST) ; + + /* + * Allocate mbuf pointers + */ + sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, M_MBUF, M_NOWAIT); + sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, M_MBUF, M_NOWAIT); + if (!sc->rxMbuf || !sc->txMbuf) + rtems_panic ("No memory for mbuf pointers"); + + /* + * Set our physical address + */ + hwaddr = sc->arpcom.ac_enaddr; + + cam=(ushort *)(M68en302imp_cet); + for (i=0;i<64;i++){ + cam[(4*i)]=0x00ff; + cam[(4*i)+1]=0x00ff; + cam[(4*i)+2]=0x00ff; + } + + cam[4] = (hwaddr[0] << 8) | hwaddr[1]; + cam[5] = (hwaddr[2] << 8) | hwaddr[3]; + cam[6] = (hwaddr[4] << 8) | hwaddr[5]; + + + /* + * Set receiver and transmitter buffer descriptor bases + */ + a_bd = M68302imp_a_eth_bd (0); /* point to first BD */ + + + for (i=0;i<128;i++){ + + M68302_scc_bd_stat_ctrl (a_bd + i) = 0; + M68302_scc_bd_data_lgth (a_bd + i) = 0; + M68302_scc_bd_p_buffer (a_bd + i) = NULL; + } + + + sc->txBdBase = M68302imp_a_eth_bd ( 0 ); /* point to first BD */ + sc->rxBdBase = M68302imp_a_eth_bd ( sc->txBdCount); /* point to first RX BD atfer all TX*/ + + /* + * Set up transmit buffer descriptors + */ + for (i = 0 ; i < sc->txBdCount ; i++) { + sc->txMbuf[i] = NULL; + } + sc->txBdHead = sc->txBdTail = 0; + sc->txBdActiveCount = 0; + + /* + * Clear any outstanding events + */ + M68en302imp_intr_event = 0x07FF; + /* + * Set up interrupts + */ + + status = rtems_interrupt_catch (m302Enet_interrupt_handler, + M302_ETHER_IVECTOR, + &old_handler); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't attach M302 ether interrupt handler: %s\r\n", + rtems_status_text (status)); +} + +/* + * Soak up buffer descriptors that have been sent + * Note that a buffer descriptor can't be retired as soon as it becomes + * ready. The MC68360 Errata (May 96) says that, "If an Ethernet frame is + * made up of multiple buffers, the user should not reuse the first buffer + * descriptor until the last buffer descriptor of the frame has had its + * ready bit cleared by the CPM". + */ +static void +m302Enet_retire_tx_bd (struct scc_softc *sc) +{ + + rtems_unsigned16 status; + int i; + int nRetired; + struct mbuf *m, *n; + int retries = 0; + int saveStatus = 0; + + i = sc->txBdTail; + nRetired = 0; + while ((sc->txBdActiveCount != 0) + && (((status = (sc->txBdBase + i)->stat_ctrl) & BUF_STAT_READY) == 0)) { + /* + * Check for errors which stop the transmitter. + */ + if (status & (BUF_STAT_LATE_COLLISION | + BUF_STAT_RETRY_LIMIT | + BUF_STAT_UNDERRUN)) { + int j; + + + if (status & BUF_STAT_LATE_COLLISION) + sc->txLateCollision++; + if (status & BUF_STAT_RETRY_LIMIT) + sc->txRetryLimit++; + if (status & BUF_STAT_UNDERRUN) + sc->txUnderrun++; + + /* + * Reenable buffer descriptors + */ + j = sc->txBdTail; + for (;;) { + status = (sc->txBdBase + j)->stat_ctrl; + if (status & BUF_STAT_READY) + break; + (sc->txBdBase + j)->stat_ctrl = BUF_STAT_READY | + (status & ( BUF_STAT_WRAP | + BUF_STAT_INTERRUPT | + BUF_STAT_LAST | + BUF_STAT_TX_CRC)); + if (status & BUF_STAT_LAST) + break; + if (++j == sc->txBdCount) + j = 0; + } + + /* + * Move transmitter back to the first + * buffer descriptor in the frame. + */ +/* m360.scc1p._tbptr = m360.scc1p.tbase + + sc->txBdTail * sizeof (m360BufferDescriptor_t); +*/ + /* + * Restart the transmitter + */ +/* M360ExecuteRISC (M360_CR_OP_RESTART_TX | M360_CR_CHAN_SCC1);*/ + continue; + } + saveStatus |= status; + retries += (status >> 2) & 0xF; + nRetired++; + if (status & BUF_STAT_LAST) { + /* + * A full frame has been transmitted. + * Free all the associated buffer descriptors. + */ + if (saveStatus & BUF_STAT_DEFER) + sc->txDeferred++; + if (saveStatus & BUF_STAT_HEARTBIT) + sc->txHeartbeat++; + if (saveStatus & BUF_STAT_CARRIER_LOST) + sc->txLostCarrier++; + saveStatus = 0; + sc->txRetry += retries; + retries = 0; + sc->txBdActiveCount -= nRetired; + while (nRetired) { + nRetired--; + m = sc->txMbuf[sc->txBdTail]; + MFREE (m, n); + if (++sc->txBdTail == sc->txBdCount) + sc->txBdTail = 0; + } + } + if (++i == sc->txBdCount) + i = 0; + } + +} + +/* + * SCC reader task + */ +static void +scc_rxDaemon (void *arg) +{ + + struct scc_softc *sc = (struct scc_softc *)arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mbuf *m; + rtems_unsigned16 status; + volatile struct m68302_scc_bd *rxBd; + int rxBdIndex; + + /* + * Allocate space for incoming packets and start reception + */ + for (rxBdIndex = 0 ; ;) { + rxBd = sc->rxBdBase + rxBdIndex; + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->p_buffer = mtod (m, void *); + + + if (++rxBdIndex == sc->rxBdCount) { + rxBd->stat_ctrl = BUF_STAT_EMPTY | BUF_STAT_INTERRUPT | BUF_STAT_WRAP; + break; + } + rxBd->stat_ctrl = BUF_STAT_EMPTY | BUF_STAT_INTERRUPT; + } + + /* + * Input packet handling loop + */ + rxBdIndex = 0; + for (;;) { + rxBd = sc->rxBdBase + rxBdIndex; + + /* + * Wait for packet if there's not one ready + */ + if ((status = rxBd->stat_ctrl) & BUF_STAT_EMPTY) { + /* + * Clear old events + */ + M68en302imp_intr_event = INTR_EVENT_BIT_RFINT; + + /* + * Wait for packet + * Note that the buffer descriptor is checked + * *before* the event wait -- this catches the + * possibility that a packet arrived between the + * `if' above, and the clearing of the event register. + */ + while ((status = rxBd->stat_ctrl) & BUF_STAT_EMPTY) { + rtems_interrupt_level level; + rtems_event_set events; + + /* + * Unmask RXF (Full frame received) event + */ + rtems_interrupt_disable (level); + M68en302imp_intr_mask |= INTR_MASK_BIT_RFIEN; + + rtems_interrupt_enable (level); + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + } + } + + + /* + * Check that packet is valid + */ + if ((status & (BUF_STAT_LAST | + BUF_STAT_FIRST_IN_FRAME | + BUF_STAT_LONG | + BUF_STAT_NONALIGNED | + BUF_STAT_SHORT | + BUF_STAT_CRC_ERROR | + BUF_STAT_OVERRUN | + BUF_STAT_COLLISION)) == + (BUF_STAT_LAST | + BUF_STAT_FIRST_IN_FRAME)) { + /* + * Pass the packet up the chain. + * FIXME: Packet filtering hook could be done here. + */ + struct ether_header *eh; + + m = sc->rxMbuf[rxBdIndex]; + m->m_len = m->m_pkthdr.len = rxBd->data_lgth - + sizeof(rtems_unsigned32) - + sizeof(struct ether_header); + eh = mtod (m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + + ether_input (ifp, eh, m); + + /* + * Allocate a new mbuf + */ + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxMbuf[rxBdIndex] = m; + rxBd->p_buffer = mtod (m, void *); + } + else { + /* + * Something went wrong with the reception + */ + if (!(status & BUF_STAT_LAST)) + sc->rxNotLast++; + if (!(status & BUF_STAT_FIRST_IN_FRAME)) + sc->rxNotFirst++; + if (status & BUF_STAT_LONG) + sc->rxGiant++; + if (status & BUF_STAT_NONALIGNED) + sc->rxNonOctet++; + if (status & BUF_STAT_SHORT) + sc->rxRunt++; + if (status & BUF_STAT_CRC_ERROR) + sc->rxBadCRC++; + if (status & BUF_STAT_OVERRUN) + sc->rxOverrun++; + if (status & BUF_STAT_COLLISION) + sc->rxCollision++; + } + + /* + * Reenable the buffer descriptor + */ + rxBd->stat_ctrl = (status & (BUF_STAT_WRAP | BUF_STAT_INTERRUPT)) | BUF_STAT_EMPTY; + + /* + * Move to next buffer descriptor + */ + if (++rxBdIndex == sc->rxBdCount) + rxBdIndex = 0; + } + +} + +static void +sendpacket (struct ifnet *ifp, struct mbuf *m) +{ + + struct scc_softc *sc = ifp->if_softc; + volatile struct m68302_scc_bd *firstTxBd, *txBd; + struct mbuf *l = NULL; + rtems_unsigned16 status; + int nAdded; + char buf[20]; + + /* + * Free up buffer descriptors + */ + m302Enet_retire_tx_bd (sc); + /* + * Set up the transmit buffer descriptors. + * No need to pad out short packets since the + * hardware takes care of that automatically. + * No need to copy the packet to a contiguous buffer + * since the hardware is capable of scatter/gather DMA. + */ + status = 0; + nAdded = 0; + txBd = firstTxBd = sc->txBdBase + sc->txBdHead; + while (m) { + /* + * There are more mbufs in the packet than there + * are transmit buffer descriptors. + * Coalesce into a single buffer. + */ + if (nAdded == sc->txBdCount) { + struct mbuf *nm; + int j; + char *dest; + + /* + * Get the pointer to the first mbuf of the packet + */ + if (sc->txBdTail != sc->txBdHead) + rtems_panic ("sendpacket coalesce"); + m = sc->txMbuf[sc->txBdTail]; + + /* + * Rescind the buffer descriptor READY bits + */ + for (j = 0 ; j < sc->txBdCount ; j++) + (sc->txBdBase + j)->stat_ctrl = 0; + + /* + * Allocate an mbuf cluster + * Toss the packet if allocation fails + */ + MGETHDR (nm, M_DONTWAIT, MT_DATA); + if (nm == NULL) { + sc->txCoalesceFailed++; + m_freem (m); + + return; + } + MCLGET (nm, M_DONTWAIT); + if (nm->m_ext.ext_buf == NULL) { + sc->txCoalesceFailed++; + m_freem (m); + m_free (nm); + + return; + } + nm->m_pkthdr = m->m_pkthdr; + nm->m_len = nm->m_pkthdr.len; + + /* + * Copy data from packet chain to mbuf cluster + */ + sc->txCoalesced++; + dest = nm->m_ext.ext_buf; + while (m) { + struct mbuf *n; + + if (m->m_len) { + memcpy (dest, mtod(m, caddr_t), m->m_len); + dest += m->m_len; + } + MFREE (m, n); + m = n; + } + + /* + * Redo the send with the new mbuf cluster + */ + m = nm; + nAdded = 0; + status = 0; + + continue; + } + + /* + * Wait for buffer descriptor to become available. + */ + if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + /* + * Clear old events + */ + M68en302imp_intr_event = INTR_EVENT_BIT_TFINT | INTR_EVENT_BIT_TXB; + + /* + * Wait for buffer descriptor to become available. + * Note that the buffer descriptors are checked + * *before* entering the wait loop -- this catches + * the possibility that a buffer descriptor became + * available between the `if' above, and the clearing + * of the event register. + * This is to catch the case where the transmitter + * stops in the middle of a frame -- and only the + * last buffer descriptor in a frame can generate + * an interrupt. + */ + m302Enet_retire_tx_bd (sc); + while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { + rtems_interrupt_level level; + rtems_event_set events; + + /* + * Unmask TXB (buffer transmitted) and + * TXE (transmitter error) events. + */ + rtems_interrupt_disable (level); + M68en302imp_intr_mask |= INTR_MASK_BIT_TFIEN | INTR_MASK_BIT_TXIEN; + rtems_interrupt_enable (level); + + rtems_bsdnet_event_receive (INTERRUPT_EVENT, + RTEMS_WAIT|RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + m302Enet_retire_tx_bd (sc); + } + } + + /* + * The IP fragmentation routine in ip_output + * can produce packet fragments with zero length. + */ + if (m->m_len) { + /* + * Fill in the buffer descriptor. + * Don't set the READY flag in the first buffer + * descriptor till the whole packet has been readied. + */ + txBd = sc->txBdBase + sc->txBdHead; + txBd->p_buffer = mtod (m, void *); + txBd->data_lgth = m->m_len; + + sc->txMbuf[sc->txBdHead] = m; + status = nAdded ? BUF_STAT_READY : 0; + if (++sc->txBdHead == sc->txBdCount) { + status |= BUF_STAT_WRAP; + sc->txBdHead = 0; + } + txBd->stat_ctrl = status; + l = m; + m = m->m_next; + nAdded++; + + } + else { + /* + * Just toss empty mbufs + */ + struct mbuf *n; + MFREE (m, n); + m = n; + if (l != NULL) + l->m_next = m; + + } + } + if (nAdded) { + /* + * Send the packet + */ + txBd->stat_ctrl = status | BUF_STAT_LAST | BUF_STAT_TX_CRC | BUF_STAT_INTERRUPT; + firstTxBd->stat_ctrl |= BUF_STAT_READY; + sc->txBdActiveCount += nAdded; + + } + +} + +/* + * Driver transmit daemon + */ +void +scc_txDaemon (void *arg) +{ + + struct scc_softc *sc = (struct scc_softc *)arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mbuf *m; + rtems_event_set events; + + for (;;) { + /* + * Wait for packet + */ + rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); + + /* + * Send packets till queue is empty + */ + for (;;) { + /* + * Get the next mbuf chain to transmit. + */ + IF_DEQUEUE(&ifp->if_snd, m); + if (!m) + break; + sendpacket (ifp, m); + } + ifp->if_flags &= ~IFF_OACTIVE; + } + +} + +/* + * Send packet (caller provides header). + */ +static void +scc_start (struct ifnet *ifp) +{ + struct scc_softc *sc = ifp->if_softc; + + rtems_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); + ifp->if_flags |= IFF_OACTIVE; +} + +/* + * Initialize and start the device + */ +static void +scc_init (void *arg) +{ + struct scc_softc *sc = arg; + struct ifnet *ifp = &sc->arpcom.ac_if; + + if (sc->txDaemonTid == 0) { + + /* + * Set up SCC hardware + */ + m302Enet_initialize_hardware (sc); + + + sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); + sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); + + } + + /* + * Set flags appropriately + */ +/* if (ifp->if_flags & IFF_PROMISC) + m360.scc1.psmr |= 0x200; + else + m360.scc1.psmr &= ~0x200; +*/ + /* + * Tell the world that we're running. + */ + ifp->if_flags |= IFF_RUNNING; + + /* + * Enable receiver and transmitter + */ + M68en302imp_ecntrl = ECNTRL_BIT_RESET | ECNTRL_BIT_ETHER_EN; + +} + +/* + * Stop the device + */ +static void +scc_stop (struct scc_softc *sc) +{ + + struct ifnet *ifp = &sc->arpcom.ac_if; + + ifp->if_flags &= ~IFF_RUNNING; + + /* + * Shut down receiver and transmitter + */ + M68en302imp_ecntrl &= ~(ECNTRL_BIT_RESET | ECNTRL_BIT_ETHER_EN); + +} + + +/* + * Show interface statistics + */ +static void +scc_stats (struct scc_softc *sc) +{ + printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); + printf (" Not First:%-8lu", sc->rxNotFirst); + printf (" Not Last:%-8lu\r\n", sc->rxNotLast); + printf (" Giant:%-8lu", sc->rxGiant); + printf (" Runt:%-8lu", sc->rxRunt); + printf (" Non-octet:%-8lu\r\n", sc->rxNonOctet); + printf (" Bad CRC:%-8lu", sc->rxBadCRC); + printf (" Overrun:%-8lu", sc->rxOverrun); + printf (" Collision:%-8lu\r\n", sc->rxCollision); +/* printf (" Discarded:%-8lu\r\n", (unsigned long)m360.scc1p.un.ethernet.disfc); +*/ + printf (" Tx Interrupts:%-8lu", sc->txInterrupts); + printf (" Deferred:%-8lu", sc->txDeferred); + printf (" Missed Hearbeat:%-8lu\r\n", sc->txHeartbeat); + printf (" No Carrier:%-8lu", sc->txLostCarrier); + printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); + printf (" Late Collision:%-8lu\r\n", sc->txLateCollision); + printf (" Underrun:%-8lu", sc->txUnderrun); + printf (" Raw output wait:%-8lu", sc->txRawWait); + printf (" Coalesced:%-8lu\r\n", sc->txCoalesced); + printf (" Coalesce failed:%-8lu", sc->txCoalesceFailed); + printf (" Retries:%-8lu\r\n", sc->txRetry); +} + +/* + * Driver ioctl handler + */ +static int +scc_ioctl (struct ifnet *ifp, int command, caddr_t data) +{ + + struct scc_softc *sc = ifp->if_softc; + int error = 0; + + switch (command) { + case SIOCGIFADDR: + case SIOCSIFADDR: + ether_ioctl (ifp, command, data); + break; + + case SIOCSIFFLAGS: + switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { + case IFF_RUNNING: + scc_stop (sc); + break; + + case IFF_UP: + scc_init (sc); + break; + + case IFF_UP | IFF_RUNNING: + scc_stop (sc); + scc_init (sc); + break; + + default: + break; + } + break; + + case SIO_RTEMS_SHOW_STATS: + scc_stats (sc); + break; + + /* + * FIXME: All sorts of multicast commands need to be added here! + */ + default: + error = EINVAL; + break; + } + return error; + +} + + +/* + * Attach an SCC driver to the system + */ +int +rtems_ether1_driver_attach (struct rtems_bsdnet_ifconfig *config) +{ + struct scc_softc *sc; + struct ifnet *ifp; + int mtu; + int unitNumber; + char *unitName; + + a_m68302_imp = (struct m68302_imp *)0x700000L; + /* + * Parse driver name + */ + if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) + return 0; + + /* + * Is driver free? + */ + if ((unitNumber <= 0) || (unitNumber > NSCCDRIVER)) { + printf ("Bad SCC unit number.\r\n"); + return 0; + } + sc = &scc_softc[unitNumber - 1]; + ifp = &sc->arpcom.ac_if; + if (ifp->if_softc != NULL) { + printf ("Driver already in use.\r\n"); + return 0; + } + + /* + * Process options + */ + if (config->hardware_address) { + memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); + } + + if (config->mtu) + mtu = config->mtu; + else + mtu = ETHERMTU; + if (config->rbuf_count) + sc->rxBdCount = config->rbuf_count; + else + sc->rxBdCount = RX_BUF_COUNT; + if (config->xbuf_count) + sc->txBdCount = config->xbuf_count; + else + sc->txBdCount = TX_BUF_COUNT; + sc->acceptBroadcast = !config->ignore_broadcast; + + /* + * Set up network interface values + */ + ifp->if_softc = sc; + ifp->if_unit = unitNumber; + ifp->if_name = unitName; + ifp->if_mtu = mtu; + ifp->if_init = scc_init; + ifp->if_ioctl = scc_ioctl; + ifp->if_start = scc_start; + ifp->if_output = ether_output; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* + * Attach the interface + */ + if_attach (ifp); + ether_ifattach (ifp); + return 1; +}; diff --git a/c/src/lib/libbsp/m68k/gen68302/wrapup/Makefile.am b/c/src/lib/libbsp/m68k/gen68302/wrapup/Makefile.am index 7d63c33815..872aac7ac9 100644 --- a/c/src/lib/libbsp/m68k/gen68302/wrapup/Makefile.am +++ b/c/src/lib/libbsp/m68k/gen68302/wrapup/Makefile.am @@ -4,7 +4,12 @@ AUTOMAKE_OPTIONS = foreign 1.4 -BSP_PIECES = startup clock console timer +# We only build the networking device driver if HAS_NETWORKING was defined +if HAS_NETWORKING +NETWORKING_DRIVER = network +endif + +BSP_PIECES = startup clock console timer $(NETWORKING_DRIVER) # bummer; have to use $foreach since % pattern subst rules only replace 1x OBJS = $(foreach piece, $(BSP_PIECES), $(wildcard ../$(piece)/$(ARCH)/*.o)) -- cgit v1.2.3