2009-05-08 Kate Feng <feng1@bnl.gov>

PR1395/bsps
	* Updated the changes from RTEMS-4.8.0, which were made since Oct. 2007.
	* network/if_1GHz/if_wm.c: fixed some bugs in the 1GHz driver.
	* pci/pci_interface.c:
	  + Enabled PCI "Read", "Read Line", and "Read Multiple"
	  +  Agressive Prefetch to improve the performance of the PCI based
	     applications (e.g. 1GHz NIC).
	* irq/BSP_irq.c : Replaced the irq/irq.c, and used GT_GPP_Value
	register to monitor the cause of the level sensitive interrupts.
	This unique solution solves various bugs in the 1GHz network drivers
	Fixed bugs in compute_pic_masks_from_prio()
	* pci/pci.c : Updated it to be consistent with the original pci.c
	* written by Eric Valette.  There is no change in its function.
	* irq/irq_init.c : set defaultIrq->next_handler to be 0
	* for BSP_SHARED_HANDLER_SUPPORT.
This commit is contained in:
Joel Sherrill
2009-05-08 18:22:51 +00:00
parent ef3a82f655
commit cf599996ba
18 changed files with 635 additions and 462 deletions

View File

@@ -1,3 +1,21 @@
2009-05-08 Kate Feng <feng1@bnl.gov>
PR1395/bsps
* Updated the changes from RTEMS-4.8.0, which were made since Oct. 2007.
* network/if_1GHz/if_wm.c: fixed some bugs in the 1GHz driver.
* pci/pci_interface.c:
+ Enabled PCI "Read", "Read Line", and "Read Multiple"
+ Agressive Prefetch to improve the performance of the PCI based
applications (e.g. 1GHz NIC).
* irq/BSP_irq.c : Replaced the irq/irq.c, and used GT_GPP_Value
register to monitor the cause of the level sensitive interrupts.
This unique solution solves various bugs in the 1GHz network drivers
Fixed bugs in compute_pic_masks_from_prio()
* pci/pci.c : Updated it to be consistent with the original pci.c
* written by Eric Valette. There is no change in its function.
* irq/irq_init.c : set defaultIrq->next_handler to be 0
* for BSP_SHARED_HANDLER_SUPPORT.
2008-12-08 Ralf Corsépius <ralf.corsepius@rtems.org>
* bsp_specs: Backport from CVS-HEAD.

View File

@@ -5,7 +5,5 @@
*
*/
extern unsigned char ConfVPD_buff[200];
#define VPD_ENET0_OFFSET 0x3c
#define VPD_ENET1_OFFSET 0x45

View File

@@ -190,7 +190,7 @@
#define GT_MPP_Control2 0xf008
#define GT_MPP_Control3 0xf00c
/* <skf> added */
/* <skf> added for GT64260 */
#define GT_MPP_SerialPortMultiplex 0xf010
#define GT_GPP_IO_Control 0xf100
@@ -789,14 +789,13 @@
#define TWSI_BAUDE_RATE 0xc00c
#define TWSI_SFT_RST 0xc01c
/* Interrupt Controller - Interrupt Controller Registers */
/* Section 25.2 : Table 734 <skf> */
#define GT_MAIN_INT_CAUSE_LO 0xc18 /* read Only */
#define GT_MAIN_INT_CAUSE_HI 0xc68 /* read Only */
#define GT_CPU_INT_MASK_LO 0xc1c
#define GT_CPU_INT_MASK_HI 0xc6c
#define GT_CPU_SEL_CAUSE 0xc70 /* read Only */
#define GT64260_MAIN_INT_CAUSE_LO 0xc18 /* read Only */
#define GT64260_MAIN_INT_CAUSE_HI 0xc68 /* read Only */
#define GT64260_CPU_INT_MASK_LO 0xc1c
#define GT64260_CPU_INT_MASK_HI 0xc6c
#define GT64260_CPU_SEL_CAUSE 0xc70 /* read Only */
#define GT_PCI0_INT_MASK_LO 0xc24
#define GT_PCI0_INT_MASK_HI 0xc64
#define GT_PCI0_SEL_CAUSE 0xc74 /* read Only */

View File

@@ -32,7 +32,9 @@ startup_SOURCES = startup/bspstart.c \
../../powerpc/shared/startup/sbrk.c ../../shared/bootcard.c \
../../shared/bsppredriverhook.c startup/bspclean.c \
../../shared/bsplibc.c ../../shared/bsppost.c \
../../shared/gnatinstallhandler.c startup/reboot.c
../../shared/gnatinstallhandler.c startup/reboot.c \
../../powerpc/shared/startup/probeMemEnd.c
pclock_SOURCES = ../../powerpc/shared/clock/p_clock.c
include_bsp_HEADERS = ../../powerpc/shared/console/uart.h
@@ -45,7 +47,7 @@ pci_SOURCES = pci/pci.c pci/pci_interface.c pci/detect_host_bridge.c \
pci/pcifinddevice.c
include_bsp_HEADERS += irq/irq.h
irq_SOURCES = irq/irq_init.c irq/irq.c
irq_SOURCES = irq/irq_init.c irq/BSP_irq.c
nodist_include_HEADERS += ../../shared/tod.h
tod_SOURCES = ../../shared/tod.c tod/todcfg.c

View File

@@ -1,5 +1,5 @@
#
# $Id: README,v 1.3.1 Shuchen Kate Feng, NSLS, BNL (08/27/07)
# $Id: README,v 1.4.1 Shuchen Kate Feng, NSLS, BNL (03/16/2009)
#
Please reference README.booting for the boot/load process.
@@ -7,7 +7,10 @@ Please reference README.booting for the boot/load process.
For the priority setting of the Interrupt Requests (IRQs), please
reference README.irq
The BSP is built and tested on the 4.7.1 and 4.7.99.2 CVS RTEMS release.
The BSP is built and tested on the RTEMS 4.9.1 release. The
PR1385 patch for c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S
is not needed for the mvme5500 BSP because the PowerPC BSPs
use the shared exception framework in the RTEMS 4.9 release.
I believe in valuable real-time programming, where technical neatness,
performance and truth are. I hope I still believe. Any suggestion,

View File

@@ -1,8 +1,9 @@
README.booting: written by S. Kate Feng <feng1@bnl.gov>, Aug. 28, 2007
README.booting: written by S. Kate Feng <feng1@bnl.gov>, March 16, 2009
The bootloader is adapted from Till Straumann's Generic Mini-loader,
which he wrote originally for the SVGM powerpc board.
The BSP is built and tested on the 4.7 CVS RTEMS release.
The BSP is built and tested on the RTEMS 4.9.1 release. The
PR1385 patch for c/src/lib/libbsp/powerpc/shared/irq/irq_asm.S
is not needed for the mvme5500 BSP because the PowerPC BSPs
use the shared exception framework in the RTEMS 4.9 release.
Booting requirement :
-------------------------
@@ -11,12 +12,7 @@ Booting requirement :
or /etc/dhcpd.conf (DHCP) properly to boot the system.
(Note : EPICS needs a NTP server).
2) Please copy the prebuilt RTEMS binary (e.g. misc/rtems5500-cexp.bin)
and perhaps others (e.g. misc/st.sys) to the /tftpboot/epics/hostname/bin/
directory or the TFTPBOOT one you specified in the 'tftpGet'
command of the boot script (as shown in the following example).
3) Example of the boot script setup carried out on the MOTLoad
2) Example of the boot script setup carried out on the MOTLoad
command line :
MVME5500> gevEdit mot-script-boot
@@ -32,23 +28,14 @@ MVME5500>
Note : (cxx.xx.xx.xx is the client IP address and
sxx.xx.xx.xx is the server IP address)
4) Other reference web sites for mvme5500 BSP:
http://lansce.lanl.gov/EPICS/presentations/KateFeng%20RTEMS-mvme55001.ppt
3) Other reference web sites for mvme5500 BSP:
http://www.nsls.bnl.gov/facility/expsys/software/EPICS/
http://www.nsls.bnl.gov/facility/expsys/software/EPICS/FAQ.txt
5) When generating code (especially C++) for this system, one should
use at least gcc-3.2 (preferrably a copy downloaded from the RTEMS
site [snapshot area] )
6) To reboot the RTEMS-MVME5500 (board reset), one can invoke the
4) To reboot the RTEMS-MVME5500 (board reset), one can invoke the
rtemsReboot() command at Cexp> prompt.
7) Please reference http://www.slac.stanford.edu/~strauman/rtems
for the source code and installation guidance of cexp, GeSys and
other useful utilities such as telnet, nfs, and so on.
8) To get started with RTEMS/EPICS and to build development
5) To get started with RTEMS/EPICS and to build development
tools and BSP, I would recommend one to reference
http://www.aps.anl.gov/epics/base/RTEMS/tutorial/
in additional to the RTEMS document.

View File

@@ -7,7 +7,8 @@
* found in found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* S. Kate Feng 2003-2007 : Modified it to support the mvme5500 BSP.
* (C) S. Kate Feng 2003-2007 : Modified it to support the mvme5500 BSP.
*
*
*/
@@ -22,10 +23,57 @@
#include <libcpu/io.h>
#include <bsp/vectors.h>
#include <bsp/bspMvme5500.h>
/* Board type */
typedef enum {
undefined = 0,
MVME5500,
MVME6100
} BSP_BoardTypes;
BSP_BoardTypes BSP_getBoardType();
/* Board type */
typedef enum {
Undefined,
UNIVERSE2,
TSI148,
} BSP_VMEchipTypes;
BSP_VMEchipTypes BSP_getVMEchipType();
/* The version of Discovery system controller */
typedef enum {
notdefined,
GT64260A,
GT64260B,
MV64360,
} DiscoveryChipVersion;
DiscoveryChipVersion BSP_getDiscoveryChipVersion();
#define _256M 0x10000000
#define _512M 0x20000000
#define GT64x60_REG_BASE 0xf1000000 /* Base of GT64260 Reg Space */
#define GT64x60_REG_SPACE_SIZE 0x10000 /* 64Kb Internal Reg Space */
#define GT64x60_DEV1_BASE 0xf1100000 /* Device bank1(chip select 1) base
*/
#define GT64260_DEV1_SIZE 0x00100000 /* Device bank size */
/* fundamental addresses for this BSP (PREPxxx are from libcpu/io.h) */
#define _IO_BASE GT64260_REG_BASE
#define _IO_BASE GT64x60_REG_BASE
#define BSP_NVRAM_BASE_ADDR 0xf1110000
#define BSP_RTC_INTA_REG 0x7ff0
#define BSP_RTC_SECOND 0x7ff2
#define BSP_RTC_MINUTE 0x7ff3
#define BSP_RTC_HOUR 0x7ff4
#define BSP_RTC_DATE 0x7ff5
#define BSP_RTC_INTERRUPTS 0x7ff6
#define BSP_RTC_WATCHDOG 0x7ff7
/* PCI0 Domain I/O space */
#define PCI0_IO_BASE 0xf0000000
@@ -69,17 +117,15 @@
*/
#define CONFIGURE_NUMBER_OF_TERMIOS_PORTS 2
#define BSP_INTERRUPT_STACK_SIZE (16 * 1024) /* <skf> 2/09 wants it to be adjustable by BSP */
/* uart.c uses out_8 instead of outb */
#define BSP_UART_IOBASE_COM1 GT64260_DEV1_BASE + 0x20000
#define BSP_UART_IOBASE_COM2 GT64260_DEV1_BASE + 0x21000
#define BSP_UART_IOBASE_COM1 GT64x60_DEV1_BASE + 0x20000
#define BSP_UART_IOBASE_COM2 GT64x60_DEV1_BASE + 0x21000
#define BSP_CONSOLE_PORT BSP_UART_COM1 /* console */
#define BSP_UART_BAUD_BASE 115200
/*
* Vital Board data Start using DATA RESIDUAL
*/
/*
* Total memory using RESIDUAL DATA
*/
@@ -100,6 +146,7 @@ extern unsigned int BSP_time_base_divisor;
#define BSP_Convert_decrementer( _value ) \
((unsigned long long) ((((unsigned long long)BSP_time_base_divisor) * 1000000ULL) /((unsigned long long) BSP_bus_frequency)) * ((unsigned long long) (_value)))
extern rtems_configuration_table BSP_Configuration;
extern void BSP_panic(char *s);
extern void bsp_reset(void);
/* extern int printk(const char *, ...) __attribute__((format(printf, 1, 2))); */
@@ -118,24 +165,31 @@ extern unsigned int BSP_heap_start;
#define RTEMS_BSP_NETWORK_DRIVER_ATTACH rtems_i82544EI_driver_attach
#endif
extern int
RTEMS_BSP_NETWORK_DRIVER_ATTACH(/* struct rtems_bsdnet_ifconfig * */);
extern int RTEMS_BSP_NETWORK_DRIVER_ATTACH();
/*
* BSP Configuration Default Overrides
*/
#define BSP_ZERO_WORKSPACE_AUTOMATICALLY TRUE
/* As per Linux, This should be in the ppc/system.h */
#define gccMemBar() RTEMS_COMPILER_MEMORY_BARRIER()
static inline void lwmemBar()
{
asm volatile("lwsync":::"memory");
}
static inline void io_flush()
{
asm volatile("isync":::"memory");
}
static inline void memBar()
{
asm volatile("sync":::"memory");
}
static inline void ioBar()
{
asm volatile("eieio");
asm volatile("eieio":::"memory");
}
#endif

View File

@@ -36,10 +36,18 @@ static int connected(void) {return 1;}
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
static rtems_irq_global_settings initial_config;
#ifdef BSP_SHARED_HANDLER_SUPPORT
static rtems_irq_connect_data defaultIrq = {
/* vectorIdex, hdl ,handle , on , off , isOn ,next_handler, */
0, nop_func , NULL , nop_func , nop_func , not_connected, 0
};
#else
static rtems_irq_connect_data defaultIrq = {
/* vectorIdex, hdl , handle , on , off , isOn */
0, nop_func , NULL , nop_func , nop_func , not_connected
};
#endif
rtems_irq_prio BSPirqPrioTable[BSP_PIC_IRQ_NUMBER]={
/*
@@ -135,12 +143,6 @@ void BSP_rtems_irq_mng_init(unsigned cpuId)
#ifdef TRACE_IRQ_INIT
printk("Done setup irq mngt configuration\n");
#endif
/* I don't really understand why all sources are enable here... (T.S) */
for (i= BSP_MAIN_GPP7_0_IRQ; i <= BSP_MAIN_GPP31_24_IRQ; i++)
BSP_enable_pic_irq(i);
rtems_interrupt_enable(l);
#ifdef TRACE_IRQ_INIT
printk("RTEMS IRQ management is now operationnal\n");

View File

@@ -7,12 +7,6 @@
* Acknowledgements:
* netBSD : Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.
* Marvell : NDA document for the discovery system controller
* The author referenced two RTEMS network drivers of other NICs.
* rtems : 1) dec21140.c, a network driver for for TULIP based Ethernet Controller
* (C) 1999 Emmanuel Raguet. raguet@crf.canon.fr
*
* 2) yellowfin.c, a network driver for the SVGM5 BSP.
* Stanford Linear Accelerator Center, Till Straumann
*
* Some notes from the author, S. Kate Feng :
*
@@ -366,8 +360,7 @@ int rtems_GT64260eth_driver_attach(struct rtems_bsdnet_ifconfig *config, int att
if (unit < 0) return 0;
printk("\nEthernet driver name %s unit %d \n",name, unit);
printk("(c) 2004, Brookhaven National Lab. <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
printk("RTEMS-mvme5500 BSP Copyright (c) 2004, Brookhaven National Lab., Shuchen Kate Feng \n");
/* Make certain elements e.g. descriptor lists are aligned. */
softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
@@ -393,7 +386,7 @@ int rtems_GT64260eth_driver_attach(struct rtems_bsdnet_ifconfig *config, int att
} else {
printk("Read EEPROM ");
for (i = 0; i < 6; i++)
hwaddr[i] = ConfVPD_buff[VPD_ENET0_OFFSET+i];
hwaddr[i] = ReadConfVPD_buff(VPD_ENET0_OFFSET+i);
}
#ifdef GT_DEBUG
@@ -1137,7 +1130,6 @@ static void GTeth_tx_stop(struct GTeth_softc *sc)
sc->arpcom.ac_if.if_timer = 0;
}
/* TOCHECK : Should it be about rx or tx ? */
static void GTeth_ifchange(struct GTeth_softc *sc)
{
if (GTeth_debug>0) printk("GTeth_ifchange(");
@@ -1445,6 +1437,7 @@ static void GTeth_hash_init(struct GTeth_softc *sc)
#endif
}
#ifdef GT64260eth_DEBUG
static void GT64260eth_error(struct GTeth_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
@@ -1474,7 +1467,7 @@ static void GT64260eth_error(struct GTeth_softc *sc)
sc->intr_errsts[sc->intr_err_ptr1++]=0;
sc->intr_err_ptr1 %= INTR_ERR_SIZE; /* Till Straumann */
}
#endif
/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */
static void GT64260eth_daemon(void *arg)
@@ -1548,7 +1541,9 @@ static void GT64260eth_daemon(void *arg)
ifp->if_flags &= ~IFF_OACTIVE;
/* Log errors and other uncommon events. */
#ifdef GT64260eth_DEBUG
if (events & ERR_EVENT) GT64260eth_error(sc);
#endif
} /* end for(;;) { rtems_bsdnet_event_receive() .....*/
ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE);

View File

@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004,2005 RTEMS/Mvme5500 port by S. Kate Feng <feng1@bnl.gov>
* under the Deaprtment of Energy contract DE-AC02-98CH10886
* Brookhaven National Laboratory, All rights reserved
*
* Acknowledgements:
@@ -25,8 +26,7 @@
* hardware auto-neg. state machine disabled. PCI control "snoop
* to WB region", MII mode (PHY) instead of TBI mode.
* 6) We currently only use 32-bit (instead of 64-bit) DMA addressing.
* 7) Support for checksum offloading and TCP segmentation offload will
* be available for releasing in 2008, upon request, if I still believe.
* 7) Implementation for Jumbo Frame and TCP checksum is not completed yet.
*
*/
@@ -34,8 +34,11 @@
#define INET
/*#define RTEMS_ETHERMTU_JUMBO*/
#include <rtems.h>
#include <rtems/bspIo.h> /* printk */
#include <stdio.h> /* printf for statistics */
#include <string.h>
@@ -64,6 +67,7 @@
#include <net/if_dl.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <net/ethernet.h>
#ifdef INET
#include <netinet/in_var.h>
@@ -75,14 +79,12 @@
#include <bsp/if_wmreg.h>
#define WMREG_RADV 0x282c /* Receive Interrupt Absolute Delay Timer */
/*#define CKSUM_OFFLOAD*/
#define ETHERTYPE_FLOWCONTROL 0x8808 /* 802.3x flow control packet */
#define i82544EI_TASK_NAME "IGHZ"
#define i82544EI_TASK_NAME "IGHz"
#define SOFTC_ALIGN 4095
#define INTR_ERR_SIZE 16
#define IF_ERR_BUFSZE 16
/*#define WM_DEBUG*/
#ifdef WM_DEBUG
@@ -90,7 +92,7 @@
#define WM_DEBUG_TX 0x02
#define WM_DEBUG_RX 0x04
#define WM_DEBUG_GMII 0x08
int wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
static int wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK; /* May 7, 2009 */
#define DPRINTF(x, y) if (wm_debug & (x)) printk y
#else
@@ -109,12 +111,12 @@ int wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT|INIT_EVENT)
#define NTXDESC 128
/* <skf> used 64 in 4.8.0, TOD; try 4096 */
#define NTXDESC 256
#define NTXDESC_MASK (NTXDESC - 1)
#define WM_NEXTTX(x) (((x) + 1) & NTXDESC_MASK)
#define NRXDESC 64
#define NRXDESC 256
#define NRXDESC_MASK (NRXDESC - 1)
#define WM_NEXTRX(x) (((x) + 1) & NRXDESC_MASK)
#define WM_PREVRX(x) (((x) - 1) & NRXDESC_MASK)
@@ -123,9 +125,10 @@ int wm_debug = WM_DEBUG_TX|WM_DEBUG_RX|WM_DEBUG_LINK;
#define WM_CDTXOFF(x) WM_CDOFF(sc_txdescs[(x)])
#define WM_CDRXOFF(x) WM_CDOFF(sc_rxdescs[(x)])
#define TXQ_HiLmt_OFF 64
#define TXQ_HiLmt_OFF 32
static uint32_t TxDescCmd;
static unsigned BSP_1GHz_membase;
/*
* Software state per device.
@@ -136,9 +139,9 @@ struct wm_softc {
struct mbuf *txs_mbuf[NTXDESC]; /* transmit buffer memory */
struct mbuf *rxs_mbuf[NRXDESC]; /* receive buffer memory */
struct wm_softc *next_module;
volatile unsigned int intr_errsts[INTR_ERR_SIZE]; /* intr_status */
unsigned int intr_err_ptr1; /* ptr used in i82544EI_error() */
unsigned int intr_err_ptr2; /* ptr used in ISR */
volatile unsigned int if_errsts[IF_ERR_BUFSZE]; /* intr_status */
unsigned int if_err_ptr1; /* ptr used in i82544EI_error() */
unsigned int if_err_ptr2; /* ptr used in ISR */
int txs_firstdesc; /* first descriptor in packet */
int txs_lastdesc; /* last descriptor in packet */
int txs_ndesc; /* # of descriptors used */
@@ -168,15 +171,16 @@ struct wm_softc {
int sc_rxptr; /* next ready Rx descriptor/queue ent */
int sc_rxdiscard;
int sc_rxlen;
uint32_t sc_ctrl; /* prototype CTRL register */
#if 0
uint32_t sc_ctrl_ext; /* prototype CTRL_EXT register */
#endif
uint32_t sc_icr; /* prototype interrupt bits */
uint32_t sc_tctl; /* prototype TCTL register */
uint32_t sc_rctl; /* prototype RCTL register */
uint32_t sc_tipg; /* prototype TIPG register */
uint32_t sc_fcrtl; /* prototype FCRTL register */
uint32_t sc_pba; /* prototype PBA register */
int sc_mchash_type; /* multicast filter offset */
@@ -184,11 +188,6 @@ struct wm_softc {
struct {
volatile unsigned long rxInterrupts;
volatile unsigned long txInterrupts;
unsigned long txMultiBuffPacket;
unsigned long txMultiMaxLen;
unsigned long txSinglMaxLen;
unsigned long txMultiMaxLoop;
unsigned long txBuffMaxLen;
unsigned long linkInterrupts;
unsigned long length_errors;
unsigned long frame_errors;
@@ -224,22 +223,20 @@ struct wm_softc {
static struct wm_softc *root_i82544EI_dev = NULL;
static void i82544EI_ifstart(struct ifnet *ifp);
static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data);
static int wm_ioctl(struct ifnet *ifp, ioctl_command_t cmd,caddr_t data);
static void i82544EI_ifinit(void *arg);
static void wm_stop(struct ifnet *ifp, int disable);
static void wm_gmii_mediainit(struct wm_softc *sc);
static void wm_rxdrain(struct wm_softc *sc);
static int wm_add_rxbuf(struct wm_softc *sc, int idx);
static int wm_read_eeprom(struct wm_softc *sc,int word,int wordcnt, uint16_t *data);
static void i82544EI_daemon(void *arg);
static void wm_set_filter(struct wm_softc *sc);
static void i82544EI_isr(void);
static void i82544EI_rx(struct wm_softc *sc);
static void i82544EI_isr(rtems_irq_hdl_param handle);
static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m);
extern int pci_mem_find(int b, int d, int f, int reg, unsigned *basep,unsigned *sizep);
extern int pci_io_find(int b, int d, int f, int reg,unsigned *basep,unsigned *sizep);
extern int pci_get_capability(int b, int d, int f, int capid,int *offset,uint32_t *value);
extern char * ether_sprintf1(void);
extern int pci_mem_find(), pci_io_find(), pci_get_capability();
static void i82544EI_irq_on(const rtems_irq_connect_data *irq)
{
@@ -271,6 +268,7 @@ static int i82544EI_irq_is_on(const rtems_irq_connect_data *irq)
static rtems_irq_connect_data i82544IrqData={
BSP_GPP_82544_IRQ,
(rtems_irq_hdl) i82544EI_isr,
(rtems_irq_hdl_param) NULL,
(rtems_irq_enable) i82544EI_irq_on,
(rtems_irq_disable) i82544EI_irq_off,
(rtems_irq_is_enabled) i82544EI_irq_is_on,
@@ -290,9 +288,12 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
unit = rtems_bsdnet_parse_driver_name(config, &name);
if (unit < 0) return 0;
printk("\nEthernet driver name %s unit %d \n",name, unit);
printk("Copyright (c) 2004,2005 S. Kate Feng <feng1@bnl.gov> (RTEMS/mvme5500 port)\n");
if ( !strncmp((const char *)name,"autoz",5))
memcpy(name,"gtGHz",5);
printk("\nAttaching MVME5500 1GHz NIC%d\n", unit);
printk("RTEMS-mvme5500 BSP Copyright (c) 2004,2005,2008, Brookhaven National Lab., Shuchen Kate Feng \n");
/* Make sure certain elements e.g. descriptor lists are aligned.*/
softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT);
@@ -310,7 +311,7 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
unit-1,&b, &d, &f))
rtems_panic("i82544EI device ID not found\n");
#if WM_DEBUG
#ifdef WM_DEBUG
printk("82544EI:b%d, d%d, f%d\n", b, d,f);
#endif
@@ -318,13 +319,18 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
if ( pci_mem_find(b,d,f,PCI_MAPREG_START, &sc->sc_membase, &sc->sc_memsize))
rtems_panic("i82544EI: unable to map memory space\n");
#ifdef WM_DEBUG
printk("Memory base addr 0x%x\n", sc->sc_membase);
#endif
BSP_1GHz_membase= sc->sc_membase;
#ifdef WM_DEBUG
printk("Memory base addr 0x%x\n", sc->sc_membase);
printk("txdesc[0] addr:0x%x, rxdesc[0] addr:0x%x, sizeof sc %d\n",&sc->sc_txdescs[0], &sc->sc_rxdescs[0], sizeof(*sc));
#endif
sc->sc_ctrl |=CSR_READ(sc,WMREG_CTRL);
sc->sc_ctrl=CSR_READ(sc,WMREG_CTRL);
/*
* Determine a few things about the bus we're connected to.
*/
@@ -362,11 +368,10 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
enaddr[4] = myea[2] & 0xff;
enaddr[5] = myea[2] >> 8;
memcpy(sc->arpcom.ac_enaddr, enaddr, ETHER_ADDR_LEN);
#ifdef WM_DEBUG
printk("%s: Ethernet address %s\n", sc->dv_xname,
ether_sprintf1(enaddr));
ether_sprintf(enaddr));
#endif
/*
@@ -397,13 +402,39 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
#endif
/*
* Determine if we're TBI or GMII mode, and initialize the
* media structures accordingly.
*/
if ((CSR_READ(sc, WMREG_STATUS) & STATUS_TBIMODE) != 0) {
/* 1000BASE-X : fiber (TBI mode)
wm_tbi_mediainit(sc); */
} else { /* 1000BASE-T : copper (internal PHY mode), for the mvme5500 */
wm_gmii_mediainit(sc);
}
ifp = &sc->arpcom.ac_if;
/* set this interface's name and unit */
ifp->if_unit = unit;
ifp->if_name = name;
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
#ifdef RTEMS_ETHERMTU_JUMBO
sc->arpcom.ec_capabilities |= ETHERCAP_JUMBO_MTU;
ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU_JUMBO;
#else
ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU;
#endif
#ifdef RTEMS_CKSUM_OFFLOAD
/* < skf> The following is really not related to jumbo frame
sc->arpcom.ec_capabilities |= ETHERCAP_VLAN_MTU;*/
ifp->if_capabilities |= IFCAP_CSUM_IPv4_Tx | IFCAP_CSUM_IPv4_Rx |
IFCAP_CSUM_TCPv4_Tx | IFCAP_CSUM_TCPv4_Rx |
IFCAP_CSUM_UDPv4_Tx | IFCAP_CSUM_UDPv4_Rx |
IFCAP_CSUM_TCPv6_Tx | IFCAP_CSUM_UDPv6_Tx |
IFCAP_TSOv4; /* TCP segmentation offload. */
#endif
ifp->if_ioctl = wm_ioctl;
ifp->if_start = i82544EI_ifstart;
/* ifp->if_watchdog = wm_watchdog;*/
@@ -418,7 +449,8 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
rtems_build_name('I','G','H','Z'),0,0,0,&sc->daemonSync))
rtems_panic("i82544EI: semaphore creation failed");
sc->next_module = root_i82544EI_dev;
i82544IrqData.handle= (rtems_irq_hdl_param) sc;
/* sc->next_module = root_i82544EI_dev;*/
root_i82544EI_dev = sc;
/* Attach the interface. */
@@ -431,6 +463,47 @@ int rtems_i82544EI_driver_attach(struct rtems_bsdnet_ifconfig *config, int attac
return(1);
}
/*
* wm_reset:
*
* Reset the i82544 chip.
*/
static void wm_reset(struct wm_softc *sc)
{
int i;
/* Packet Buffer Allocation (PBA)
* Writing PBA sets the receive portion of the buffer.
* the remainder is used for the transmit buffer.
*
* 82544 has a Packet Buffer of 64K.
* Default allocation : PBA=40K for Rx, leaving 24K for Tx.
* Default for jumbo: PBA=48K for Rx, leaving 16K for Tx.
*/
sc->sc_pba = sc->arpcom.ac_if.if_mtu > 8192 ? PBA_40K : PBA_48K;
CSR_WRITE(sc, WMREG_PBA, sc->sc_pba);
/* device reset */
CSR_WRITE(sc, WMREG_CTRL, CTRL_RST);
rtems_bsp_delay(10000);
for (i = 0; i < 1000; i++) {
if ((CSR_READ(sc, WMREG_CTRL) & CTRL_RST) == 0)
break;
rtems_bsp_delay(20);
}
if (CSR_READ(sc, WMREG_CTRL) & CTRL_RST)
printk("Intel 82544 1GHz reset failed to complete\n");
sc->sc_ctrl_ext = CSR_READ(sc,WMREG_CTRL_EXT);
sc->sc_ctrl_ext |= CTRL_EXT_EE_RST;
CSR_WRITE(sc, WMREG_CTRL_EXT, sc->sc_ctrl_ext);
CSR_READ(sc, WMREG_STATUS);
/* Wait for EEPROM reload */
rtems_bsp_delay(2000);
sc->sc_ctrl= CSR_READ(sc, WMREG_CTRL);
}
/*
* i82544EI_ifstart: [ifnet interface function]
*
@@ -463,27 +536,21 @@ static void i82544EI_stats(struct wm_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
printf(" Rx Interrupts:%-8u\n", sc->stats.rxInterrupts);
printf(" Ghost Interrupts:%-8lu\n", sc->stats.ghostInterrupts);
printf(" Rx Interrupts:%-8lu\n", sc->stats.rxInterrupts);
printf(" Receive Packets:%-8u\n", CSR_READ(sc,WMREG_GPRC));
printf(" Receive Overrun:%-8u\n", sc->stats.rxOvrRunInterrupts);
printf(" Receive Overrun:%-8lu\n", sc->stats.rxOvrRunInterrupts);
printf(" Receive errors:%-8u\n", CSR_READ(sc,WMREG_RXERRC));
printf(" Rx sequence error:%-8u\n", sc->stats.rxSeqErr);
printf(" Rx /C/ ordered:%-8u\n", sc->stats.rxC_ordered);
printf(" Rx sequence error:%-8lu\n", sc->stats.rxSeqErr);
printf(" Rx /C/ ordered:%-8lu\n", sc->stats.rxC_ordered);
printf(" Rx Length Errors:%-8u\n", CSR_READ(sc,WMREG_RLEC));
printf(" Tx Interrupts:%-8u\n", sc->stats.txInterrupts);
#if 0
printf("Multi-BuffTx Packets:%-8u\n", sc->stats.txMultiBuffPacket);
printf("Multi-BuffTx max len:%-8u\n", sc->stats.txMultiMaxLen);
printf("SingleBuffTx max len:%-8u\n", sc->stats.txSinglMaxLen);
printf("Multi-BuffTx maxloop:%-8u\n", sc->stats.txMultiMaxLoop);
printf("Tx buffer max len :%-8u\n", sc->stats.txBuffMaxLen);
#endif
printf(" Tx Interrupts:%-8lu\n", sc->stats.txInterrupts);
printf(" Transmitt Packets:%-8u\n", CSR_READ(sc,WMREG_GPTC));
printf(" Transmitt errors:%-8u\n", ifp->if_oerrors);
printf(" Active Txqs:%-8u\n", sc->txq_nactive);
printf(" Transmitt errors:%-8lu\n", ifp->if_oerrors);
printf(" Active Txqs:%-8lu\n", sc->txq_nactive);
printf(" collisions:%-8u\n", CSR_READ(sc,WMREG_COLC));
printf(" Crc Errors:%-8u\n", CSR_READ(sc,WMREG_CRCERRS));
printf(" Link Status Change:%-8u\n", sc->stats.linkStatusChng);
printf(" Link Status Change:%-8lu\n", sc->stats.linkStatusChng);
}
/*
@@ -491,7 +558,7 @@ static void i82544EI_stats(struct wm_softc *sc)
*
* Handle control requests from the operator.
*/
static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data)
static int wm_ioctl(struct ifnet *ifp, ioctl_command_t cmd,caddr_t data)
{
struct wm_softc *sc = ifp->if_softc;
int error=0;
@@ -523,9 +590,9 @@ static int wm_ioctl(struct ifnet *ifp, u_long cmd,uint32_t data)
*
* Interrupt service routine.
*/
static void i82544EI_isr()
static void i82544EI_isr(rtems_irq_hdl_param handle)
{
volatile struct wm_softc *sc = root_i82544EI_dev;
volatile struct wm_softc *sc = (struct wm_softc *) handle;
uint32_t icr;
rtems_event_set events=0;
@@ -549,8 +616,8 @@ static void i82544EI_isr()
events |= INIT_EVENT;
}
if (icr & ICR_RXSEQ) /* framing error */ {
sc->intr_errsts[sc->intr_err_ptr2++]=icr;
sc->intr_err_ptr2 %=INTR_ERR_SIZE; /* Till Straumann */
sc->if_errsts[sc->if_err_ptr2++]=icr;
if ( sc->if_err_ptr2 ==IF_ERR_BUFSZE) sc->if_err_ptr2=0;
events |= ERR_EVENT;
sc->stats.rxSeqErr++;
}
@@ -608,15 +675,12 @@ static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m)
* The other way is effective for packets < 2K
*/
if ( ((y=(len+mtp->m_len)) > sizeof(union mcluster))) {
printk(">2048, use next descriptor\n");
printk(" >%d, use next descriptor\n", sizeof(union mcluster));
break;
}
memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len);
pt += mtp->m_len;
len += mtp->m_len;
#if 0
sc->stats.txSinglMaxLen= MAX(mtp->m_len, sc->stats.txSinglMaxLen);
#endif
} /* end for loop */
mdest->m_len=len;
sc->txs_mbuf[sc->txq_next] = mdest;
@@ -630,15 +694,8 @@ static void i82544EI_sendpacket(struct wm_softc *sc, struct mbuf *m)
sc->txq_free--;
else
rtems_panic("i8254EI : no more free descriptors");
#if 0
sc->stats.txMultiMaxLen= MAX(mdest->m_len, sc->stats.txMultiMaxLen);
sc->stats.txMultiBuffPacket++;
#endif
} /* end for while */
/* free old mbuf chain */
#if 0
sc->stats.txMultiMaxLoop=MAX(loop, sc->stats.txMultiMaxLoop);
#endif
m_freem(m);
m=0;
} /* end multiple mbufs */
@@ -744,12 +801,11 @@ static void i82544EI_rx(struct wm_softc *sc)
sc->dv_xname, i));
status = sc->sc_rxdescs[i].wrx_status;
if ((status & WRX_ST_DD) == 0) break; /* descriptor not done */
errors = sc->sc_rxdescs[i].wrx_errors;
len = le16toh(sc->sc_rxdescs[i].wrx_len);
m = sc->rxs_mbuf[i];
if ((status & WRX_ST_DD) == 0) break; /* descriptor not done */
if (sc->sc_rxdiscard) {
printk("RX: discarding contents of descriptor %d\n", i);
wm_init_rxdesc(sc, i);
@@ -821,16 +877,46 @@ static int i82544EI_init_hw(struct wm_softc *sc)
int i,error;
uint8_t cksumfields;
#if 0
/* KATETODO : sc_align_tweak */
/*
* *_HDR_ALIGNED_P is constant 1 if __NO_STRICT_ALIGMENT is set.
* There is a small but measurable benefit to avoiding the adjusment
* of the descriptor so that the headers are aligned, for normal mtu,
* on such platforms. One possibility is that the DMA itself is
* slightly more efficient if the front of the entire packet (instead
* of the front of the headers) is aligned.
*
* Note we must always set align_tweak to 0 if we are using
* jumbo frames.
*/
#ifdef __NO_STRICT_ALIGNMENT
sc->sc_align_tweak = 0;
#else
if ((ifp->if_mtu + ETHER_HDR_LEN + ETHER_CRC_LEN) > (MCLBYTES - 2))
sc->sc_align_tweak = 0;
else
sc->sc_align_tweak = 2;
#endif /* __NO_STRICT_ALIGNMENT */
#endif
/* Cancel any pending I/O. */
wm_stop(ifp, 0);
/* update statistics before reset */
ifp->if_collisions += CSR_READ(sc, WMREG_COLC);
ifp->if_ierrors += CSR_READ(sc, WMREG_RXERRC);
/* Reset the chip to a known state. */
wm_reset(sc);
/* Initialize the error buffer ring */
sc->intr_err_ptr1=0;
sc->intr_err_ptr2=0;
for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0;
sc->if_err_ptr1=0;
sc->if_err_ptr2=0;
for (i=0; i< IF_ERR_BUFSZE; i++) sc->if_errsts[i]=0;
/* Initialize the transmit descriptor ring. */
memset(sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
memset( (void *) sc->sc_txdescs, 0, sizeof(sc->sc_txdescs));
sc->txq_free = NTXDESC;
sc->txq_next = 0;
sc->txs_lastdesc = 0;
@@ -849,8 +935,8 @@ static int i82544EI_init_hw(struct wm_softc *sc)
CSR_WRITE(sc,WMREG_TDLEN, sizeof(sc->sc_txdescs));
CSR_WRITE(sc,WMREG_TDH, 0);
CSR_WRITE(sc,WMREG_TDT, 0);
CSR_WRITE(sc,WMREG_TIDV, 64 );
CSR_WRITE(sc,WMREG_TADV, 128);
CSR_WRITE(sc,WMREG_TIDV, 0 );
/* CSR_WRITE(sc,WMREG_TADV, 128); not for 82544 */
CSR_WRITE(sc,WMREG_TXDCTL, TXDCTL_PTHRESH(0) |
TXDCTL_HTHRESH(0) | TXDCTL_WTHRESH(0));
@@ -864,10 +950,11 @@ static int i82544EI_init_hw(struct wm_softc *sc)
* Set up checksum offload parameters for
* this packet.
*/
#ifdef CKSUM_OFFLOAD
if (m0->m_pkthdr.csum_flags &
(M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4)) {
if (wm_tx_cksum(sc, txs, &TxDescCmd,&cksumfields) != 0) {
#ifdef RTEMS_CKSUM_OFFLOAD
if (m0->m_pkthdr.csum_flags & (M_CSUM_TSOv4|M_CSUM_TSOv6|
M_CSUM_IPv4|M_CSUM_TCPv4|M_CSUM_UDPv4|
M_CSUM_TCPv6|M_CSUM_UDPv6)) {
if (wm_tx_offload(sc, txs, &TxDescCmd,&cksumfields) != 0) {
/* Error message already displayed. */
continue;
}
@@ -875,7 +962,7 @@ static int i82544EI_init_hw(struct wm_softc *sc)
#endif
TxDescCmd = 0;
cksumfields = 0;
#ifdef CKSUM_OFFLOAD
#ifdef RTEMS_CKSUM_OFFLOAD
}
#endif
@@ -894,14 +981,14 @@ static int i82544EI_init_hw(struct wm_softc *sc)
* Initialize the receive descriptor and receive job
* descriptor rings.
*/
memset(sc->sc_rxdescs, 0, sizeof(sc->sc_rxdescs));
memset( (void *) sc->sc_rxdescs, 0, sizeof(sc->sc_rxdescs));
CSR_WRITE(sc,WMREG_RDBAH, 0);
CSR_WRITE(sc,WMREG_RDBAL, WM_CDRXADDR(sc));
CSR_WRITE(sc,WMREG_RDLEN, sizeof(sc->sc_rxdescs));
CSR_WRITE(sc,WMREG_RDH, 0);
CSR_WRITE(sc,WMREG_RDT, 0);
CSR_WRITE(sc,WMREG_RDTR, 0 |RDTR_FPD);
CSR_WRITE(sc, WMREG_RADV, 256);
/* CSR_WRITE(sc, WMREG_RADV, 256); not for 82544. */
for (i = 0; i < NRXDESC; i++) {
if (sc->rxs_mbuf[i] == NULL) {
@@ -930,14 +1017,14 @@ static int i82544EI_init_hw(struct wm_softc *sc)
for (i = 0; i < WM_VLAN_TABSIZE; i++)
CSR_WRITE(sc,WMREG_VFTA + (i << 2), 0);
#if 0
/* Use MOTLoad default
/*
* Set up flow-control parameters.
*
* XXX Values could probably stand some tuning.
*/
CSR_WRITE(sc,WMREG_FCAL, FCAL_CONST);/*safe,even though MOTLOAD 0x00c28001 */
CSR_WRITE(sc,WMREG_FCAH, FCAH_CONST);/*safe,even though MOTLOAD 0x00000100 */
CSR_WRITE(sc,WMREG_FCT, ETHERTYPE_FLOWCONTROL);/*safe,even though MOTLoad 0x8808 */
CSR_WRITE(sc,WMREG_FCAL, FCAL_CONST);/* same as MOTLOAD 0x00c28001 */
CSR_WRITE(sc,WMREG_FCAH, FCAH_CONST);/* same as MOTLOAD 0x00000100 */
CSR_WRITE(sc,WMREG_FCT, ETHERTYPE_FLOWCONTROL);/* same as MOTLoad 0x8808 */
/* safe,even though MOTLoad default all 0 */
@@ -945,12 +1032,14 @@ static int i82544EI_init_hw(struct wm_softc *sc)
CSR_WRITE(sc,WMREG_FCRTH, FCRTH_DFLT);
CSR_WRITE(sc,WMREG_FCRTL, sc->sc_fcrtl);
CSR_WRITE(sc,WMREG_FCTTV, FCTTV_DFLT);
/*KATETO CSR_WRITE(sc,WMREG_FCTTV, FCTTV_DFLT);*/
CSR_WRITE(sc,WMREG_FCTTV, 0x100);
#endif
sc->sc_ctrl &= ~CTRL_VME;
/*sc->sc_ctrl |= CTRL_TFCE | CTRL_RFCE;*/
/* enable Big Endian Mode for the powerPC
sc->sc_ctrl |= CTRL_BEM;*/
/* TODO : not here.
Configures flow control settings after link is established
sc->sc_ctrl |= CTRL_TFCE | CTRL_RFCE; */
/* Write the control registers. */
CSR_WRITE(sc,WMREG_CTRL, sc->sc_ctrl);
@@ -958,12 +1047,27 @@ static int i82544EI_init_hw(struct wm_softc *sc)
CSR_WRITE(sc,WMREG_CTRL_EXT, sc->sc_ctrl_ext);
#endif
/* MOTLoad : WMREG_RXCSUM (0x5000)= 0, no Rx checksum offloading */
/* MOTLoad : WMREG_RXCSUM (0x5000)= 0, no Rx checksum offloading */
#ifdef RTEMS_CKSUM_OFFLOAD
/*
* Set up checksum offload parameters.
*/
reg = CSR_READ(sc, WMREG_RXCSUM);
reg &= ~(RXCSUM_IPOFL | RXCSUM_IPV6OFL | RXCSUM_TUOFL);
if (ifp->if_capenable & IFCAP_CSUM_IPv4_Rx)
reg |= RXCSUM_IPOFL;
if (ifp->if_capenable & (IFCAP_CSUM_TCPv4_Rx | IFCAP_CSUM_UDPv4_Rx))
reg |= RXCSUM_IPOFL | RXCSUM_TUOFL;
if (ifp->if_capenable & (IFCAP_CSUM_TCPv6_Rx | IFCAP_CSUM_UDPv6_Rx))
reg |= RXCSUM_IPV6OFL | RXCSUM_TUOFL;
CSR_WRITE(sc, WMREG_RXCSUM, reg);
#endif
/*
* Set up the interrupt registers.
*/
CSR_WRITE(sc,WMREG_IMC, 0xffffffffU);
/* Reading the WMREG_ICR clears the interrupt bits */
CSR_READ(sc,WMREG_ICR);
@@ -987,7 +1091,8 @@ static int i82544EI_init_hw(struct wm_softc *sc)
* we resolve the media type.
*/
sc->sc_tctl = TCTL_EN | TCTL_PSP | TCTL_CT(TX_COLLISION_THRESHOLD) |
TCTL_COLD(TX_COLLISION_DISTANCE_FDX) | TCTL_RTLC; /*transmitter enable*/
TCTL_COLD(TX_COLLISION_DISTANCE_FDX) |
TCTL_RTLC /* retransmit on late collision */;
/*
* Set up the receive control register; we actually program
@@ -995,14 +1100,31 @@ static int i82544EI_init_hw(struct wm_softc *sc)
* address offset type 0.
*
* Only the i82544 has the ability to strip the incoming
* CRC, so we don't enable that feature. (TODO)
* CRC (RCTL_SECRC).
*/
sc->sc_mchash_type = 0;
sc->sc_rctl = RCTL_EN | RCTL_LBM_NONE | RCTL_RDMTS_1_2 | RCTL_LPE |
RCTL_DPF | RCTL_MO(sc->sc_mchash_type);
RCTL_DPF | RCTL_MO(sc->sc_mchash_type)|RCTL_SECRC;
/* (MCLBYTES == 2048) */
sc->sc_rctl |= RCTL_2k;
if (MCLBYTES == 2048) {
sc->sc_rctl |= RCTL_2k;
} else {
switch(MCLBYTES) {
case 4096:
sc->sc_rctl |= RCTL_BSEX | RCTL_BSEX_4k;
break;
case 8192:
sc->sc_rctl |= RCTL_BSEX | RCTL_BSEX_8k;
break;
case 16384:
sc->sc_rctl |= RCTL_BSEX | RCTL_BSEX_16k;
break;
default:
rtems_panic("wm_init: MCLBYTES %d unsupported",
MCLBYTES);
break;
}
}
#ifdef WM_DEBUG
printk("RDBAL 0x%x,RDLEN %d, RDT %d\n",CSR_READ(sc,WMREG_RDBAL),CSR_READ(sc,WMREG_RDLEN), CSR_READ(sc,WMREG_RDT));
@@ -1020,6 +1142,24 @@ static int i82544EI_init_hw(struct wm_softc *sc)
return(0);
}
void BSP_rdTIDV()
{
printf("Reg TIDV: 0x%x\n", in_le32((volatile unsigned *) (BSP_1GHz_membase+WMREG_TIDV)));
}
void BSP_rdRDTR()
{
printf("Reg RDTR: 0x%x\n", in_le32((volatile unsigned *) (BSP_1GHz_membase+WMREG_RDTR)));
}
void BSP_setTIDV(int val)
{
out_le32((volatile unsigned *) (BSP_1GHz_membase+WMREG_TIDV), val);
}
void BSP_setRDTR(int val)
{
out_le32((volatile unsigned *) (BSP_1GHz_membase+WMREG_RDTR), val);
}
/*
* i82544EI_ifinit: [ifnet interface function]
*
@@ -1235,6 +1375,7 @@ static int wm_read_eeprom_uwire(struct wm_softc *sc, int word, int wordcnt, uint
return (0);
}
#if 0
/*
* wm_acquire_eeprom:
*
@@ -1266,6 +1407,7 @@ static int wm_acquire_eeprom(struct wm_softc *sc)
return (0);
}
#endif
/*
* wm_read_eeprom:
@@ -1370,7 +1512,7 @@ static void wm_set_filter(struct wm_softc *sc)
mta_reg = WMREG_CORDOVA_MTA;
sc->sc_rctl &= ~(RCTL_BAM | RCTL_UPE | RCTL_MPE);
/* if (ifp->if_flags & IFF_BROADCAST)*/
if (ifp->if_flags & IFF_BROADCAST)
sc->sc_rctl |= RCTL_BAM;
if (ifp->if_flags & IFF_PROMISC) {
sc->sc_rctl |= RCTL_UPE;
@@ -1440,12 +1582,11 @@ static void wm_set_filter(struct wm_softc *sc)
static void i82544EI_error(struct wm_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
unsigned long intr_status= sc->intr_errsts[sc->intr_err_ptr1++];
unsigned long intr_status= sc->if_errsts[sc->if_err_ptr1];
/* read and reset the status; because this is written
* by the ISR, we must disable interrupts here
*/
sc->intr_err_ptr1 %=INTR_ERR_SIZE; /* Till Straumann */
if (intr_status) {
printk("Error %s%d:", ifp->if_name, ifp->if_unit);
if (intr_status & ICR_RXSEQ) {
@@ -1455,6 +1596,8 @@ static void i82544EI_error(struct wm_softc *sc)
}
else
printk("%s%d: Ghost interrupt ?\n",ifp->if_name,ifp->if_unit);
sc->if_errsts[sc->if_err_ptr1]=0;
if ((++sc->if_err_ptr1)==IF_ERR_BUFSZE) sc->if_err_ptr1=0; /* Till Straumann */
}
void i82544EI_printStats()
@@ -1495,7 +1638,7 @@ static void i82544EI_daemon(void *arg)
&events);
if (KILL_EVENT & events) break;
if (events & RX_EVENT) i82544EI_rx(sc);
if (events & RX_EVENT) i82544EI_rx(sc); /* in ISR instead */
/* clean up and try sending packets */
do {
@@ -1503,6 +1646,7 @@ static void i82544EI_daemon(void *arg)
while (sc->txq_free>0) {
if (sc->txq_free>TXQ_HiLmt_OFF) {
m=0;
IF_DEQUEUE(&ifp->if_snd,m);
if (m==0) break;
i82544EI_sendpacket(sc, m);
@@ -1511,7 +1655,6 @@ static void i82544EI_daemon(void *arg)
i82544EI_txq_done(sc);
break;
}
if (events & RX_EVENT) i82544EI_rx(sc);
}
/* we leave this loop
* - either because there's no free buffer
@@ -1519,7 +1662,7 @@ static void i82544EI_daemon(void *arg)
* - or there's nothing to send (IF_DEQUEUE
* returned 0
*/
} while (m && sc->txq_free);
} while (m);
ifp->if_flags &= ~IFF_OACTIVE;
@@ -1556,3 +1699,70 @@ static void i82544EI_daemon(void *arg)
*/
rtems_task_delete(RTEMS_SELF);
}
/*
* wm_gmii_reset:
*
* Reset the PHY.
*/
static void wm_gmii_reset(struct wm_softc *sc)
{
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl | CTRL_PHY_RESET);
rtems_bsp_delay(20000);
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
rtems_bsp_delay(20000);
}
/*
* wm_gmii_mediainit:
*
* Initialize media for use on 1000BASE-T devices.
*/
static void wm_gmii_mediainit(struct wm_softc *sc)
{
/* struct ifnet *ifp = &sc->arpcom.ac_if;*/
/* We have MII. */
sc->sc_flags |= WM_F_HAS_MII;
#if 1
/* <skf> May 2009 : The value that should be programmed into IPGT is 10 */
sc->sc_tipg = TIPG_IPGT(10)+TIPG_IPGR1(8)+TIPG_IPGR2(6);
#else
sc->sc_tipg = TIPG_1000T_DFLT; /* 0x602008 */
#endif
/*
* Let the chip set speed/duplex on its own based on
* signals from the PHY.
* XXXbouyer - I'm not sure this is right for the 80003,
* the em driver only sets CTRL_SLU here - but it seems to work.
*/
sc->sc_ctrl |= CTRL_SLU;
CSR_WRITE(sc, WMREG_CTRL, sc->sc_ctrl);
wm_gmii_reset(sc);
#if 0
/* Initialize our media structures and probe the GMII. */
sc->sc_mii.mii_ifp = ifp;
sc->sc_mii.mii_readreg = wm_gmii_i82544_readreg;
sc->sc_mii.mii_writereg = wm_gmii_i82544_writereg;
sc->sc_mii.mii_statchg = wm_gmii_statchg;
ifmedia_init(&sc->sc_mii.mii_media, IFM_IMASK, wm_gmii_mediachange,
wm_gmii_mediastatus);
mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
MII_OFFSET_ANY, MIIF_DOPAUSE);
if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_NONE);
} else
ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER|IFM_AUTO);
#endif
}

View File

@@ -5,6 +5,9 @@
* All rights reserved.
*
* Written by Jason R. Thorpe for Wasabi Systems, Inc.
* Some are added by Shuchen Kate Feng <feng1@bnl.gov>,
* NSLS, Brookhaven National Laboratory. All rights reserved.
* under the Deaprtment of Energy contract DE-AC02-98CH10886
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -56,7 +59,7 @@ typedef struct wiseman_addr {
* The receive descriptor ring must be aligned to a 4K boundary,
* and there must be an even multiple of 8 descriptors in the ring.
*/
typedef struct wiseman_rxdesc {
typedef volatile struct wiseman_rxdesc {
wiseman_addr_t wrx_addr; /* buffer address */
uint16_t wrx_len; /* buffer length */
@@ -103,7 +106,7 @@ typedef struct wiseman_tx_fields {
uint8_t wtxu_options; /* options */
uint16_t wtxu_vlan; /* VLAN info */
} __attribute__((__packed__)) wiseman_txfields_t;
typedef struct wiseman_txdesc {
typedef volatile struct wiseman_txdesc {
wiseman_addr_t wtx_addr; /* buffer address */
uint32_t wtx_cmdlen; /* command and length */
wiseman_txfields_t wtx_fields; /* fields; see below */

View File

@@ -4,6 +4,7 @@
* Copyright (c) 1995, 1996, 1999, 2000
* Christopher G. Demetriou. All rights reserved.
* Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved.
* Copyright (C) 2007 Brookhaven National Laboratory, Shuchen Kate Feng
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,6 +31,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <bsp.h>
/*
* PCI Class and Revision Register; defines type and revision of device.
@@ -305,7 +307,7 @@
#define PCI_MAPREG_MEM64_ADDR_MASK 0xfffffffffffffff0ULL
#define PCI_MAPREG_IO_ADDR(mr) \
((mr) & PCI_MAPREG_IO_ADDR_MASK)
((mr+PCI0_IO_BASE) & PCI_MAPREG_IO_ADDR_MASK)
#define PCI_MAPREG_IO_SIZE(mr) \
(PCI_MAPREG_IO_ADDR(mr) & -PCI_MAPREG_IO_ADDR(mr))
#define PCI_MAPREG_IO_ADDR_MASK 0xfffffffc

View File

@@ -13,29 +13,31 @@
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/rtems/license.html.
*
* Copyright 2004, Brookhaven National Laboratory and
* Shuchen K. Feng, <feng1@bnl.gov>, 2004
* - modified and added support for MVME5500 board
* - added 2nd PCI support for the mvme5500/GT64260 PCI bridge
* - added bus support for the expansion of PMCSpan, thanks to
* Peter Dufault (dufault@hda.com) for inputs.
* pci.c,v 1.2 2002/05/14 17:10:16 joel Exp
*
* $Id$
* Copyright 2004, 2008 Brookhaven National Laboratory and
* Shuchen K. Feng, <feng1@bnl.gov>
*
* - to be consistent with the original pci.c written by Eric Valette
* - added 2nd PCI support for discovery based PCI bridge (e.g. mvme5500/mvme6100)
* - added bus support for the expansion of PMCSpan as per request by Peter
*/
#define PCI_MAIN
#include <libcpu/io.h>
#include <rtems/bspIo.h> /* printk */
#include <bsp/irq.h>
#include <bsp/pci.h>
#include <bsp/gtreg.h>
#include <bsp/gtpcireg.h>
#include <bsp.h>
#include <stdio.h>
#include <string.h>
#define PCI_DEBUG 0
#define PCI_PRINT 0
#define PCI_PRINT 1
/* allow for overriding these definitions */
#ifndef PCI_CONFIG_ADDR
@@ -56,17 +58,31 @@
#define PCI_MULTI_FUNCTION 0x80
#define HOSTBRIDGET_ERROR 0xf0000000
/* define a shortcut */
#define pci BSP_pci_configuration
#define GT64x60_PCI_CONFIG_ADDR GT64x60_REG_BASE + PCI_CONFIG_ADDR
#define GT64x60_PCI_CONFIG_DATA GT64x60_REG_BASE + PCI_CONFIG_DATA
#define GT64x60_PCI1_CONFIG_ADDR GT64x60_REG_BASE + PCI1_CONFIG_ADDR
#define GT64x60_PCI1_CONFIG_DATA GT64x60_REG_BASE + PCI1_CONFIG_DATA
static int numPCIDevs=0;
static DiscoveryChipVersion BSP_sysControllerVersion = 0;
static BSP_VMEchipTypes BSP_VMEinterface = 0;
static pci_config BSP_pci[2]={
{(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
(volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
0 /* defined at BSP_pci_configuration */},
{(volatile unsigned char*) (GT64x60_PCI1_CONFIG_ADDR),
(volatile unsigned char*) (GT64x60_PCI1_CONFIG_DATA),
0 /* defined at BSP_pci_configuration */}
};
static int numPCIDevs=0;
extern void pci_interface(void);
/* Pack RegNum,FuncNum,DevNum,BusNum,and ConfigEnable for
* PCI Configuration Address Register
*/
#define pciConfigPack(bus,dev,func,offset)\
(((func&7)<<8)|((dev&0x1f )<<11)|(( bus&0xff)<<16)|(offset&0xfc))|0x80000000
((offset&~3)<<24)|(PCI_DEVFN(dev,func)<<16)|(bus<<8)|0x80
/*
* Bit encode for PCI_CONFIG_HEADER_TYPE register
@@ -75,44 +91,36 @@ unsigned char ucMaxPCIBus=0;
/* Please note that PCI0 and PCI1 does not correlate with the busNum 0 and 1.
*/
static int direct_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
static int indirect_pci_read_config_byte(unsigned char bus,unsigned char dev,unsigned char func,
unsigned char offset,unsigned char *val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
}
else {
config_addr = pci.pci_config_addr;
config_data = pci.pci_config_data;
n=1;
}
*val = 0xff;
if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
#if 0
printk("addr %x, data %x, pack %x \n", config_addr,
config_data,pciConfigPack(bus,dev,func,offset));
printk("addr %x, data %x, pack %x \n", BSP_pci[n].pci_config_addr),
BSP_pci[n].config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset),config_addr);
*val = inb(config_data + (offset&3));
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
*val = in_8(BSP_pci[n].pci_config_data + (offset&3));
return PCIBIOS_SUCCESSFUL;
}
static int direct_pci_read_config_word(unsigned char bus, unsigned char dev,
static int indirect_pci_read_config_word(unsigned char bus, unsigned char dev,
unsigned char func, unsigned char offset, unsigned short *val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
}
else {
config_addr = (volatile unsigned char*) pci.pci_config_addr;
config_data = (volatile unsigned char*) pci.pci_config_data;
n=1;
}
*val = 0xffff;
@@ -121,123 +129,101 @@ unsigned char func, unsigned char offset, unsigned short *val)
printk("addr %x, data %x, pack %x \n", config_addr,
config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset),config_addr);
*val = inw(config_data + (offset&2));
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
*val = in_le16(BSP_pci[n].pci_config_data + (offset&2));
return PCIBIOS_SUCCESSFUL;
}
static int direct_pci_read_config_dword(unsigned char bus, unsigned char dev,
static int indirect_pci_read_config_dword(unsigned char bus, unsigned char dev,
unsigned char func, unsigned char offset, unsigned int *val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
}
else {
config_addr = (volatile unsigned char*) pci.pci_config_addr;
config_data = (volatile unsigned char*) pci.pci_config_data;
n=1;
}
*val = 0xffffffff;
if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
#if 0
printk("addr %x, data %x, pack %x \n", config_addr,
pci.pci_config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset),config_addr);
*val = inl(config_data);
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
*val = in_le32(BSP_pci[n].pci_config_data);
return PCIBIOS_SUCCESSFUL;
}
static int direct_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned char val)
static int indirect_pci_write_config_byte(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned char val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
}
else {
config_addr = pci.pci_config_addr;
config_data = pci.pci_config_data;
n=1;
}
if (offset & ~0xff) return PCIBIOS_BAD_REGISTER_NUMBER;
#if 0
printk("addr %x, data %x, pack %x \n", config_addr,
config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset), config_addr);
outb(val, config_data + (offset&3));
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
out_8(BSP_pci[n].pci_config_data + (offset&3), val);
return PCIBIOS_SUCCESSFUL;
}
static int direct_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned short val)
static int indirect_pci_write_config_word(unsigned char bus, unsigned char dev,unsigned char func, unsigned char offset, unsigned short val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char*) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char*) PCI1_CONFIG_DATA;
}
else {
config_addr = (volatile unsigned char*) pci.pci_config_addr;
config_data = (volatile unsigned char*) pci.pci_config_data;
n=1;
}
if ((offset&1)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
#if 0
printk("addr %x, data %x, pack %x \n", config_addr,
config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset),config_addr);
outw(val, config_data + (offset&3));
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
out_le16(BSP_pci[n].pci_config_data + (offset&3), val);
return PCIBIOS_SUCCESSFUL;
}
static int direct_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, unsigned int val)
static int indirect_pci_write_config_dword(unsigned char bus,unsigned char dev,unsigned char func, unsigned char offset, unsigned int val)
{
volatile unsigned char *config_addr, *config_data;
int n=0;
if (bus>= BSP_MAX_PCI_BUS_ON_PCI0) {
bus-=BSP_MAX_PCI_BUS_ON_PCI0;
config_addr = (volatile unsigned char *) PCI1_CONFIG_ADDR;
config_data = (volatile unsigned char *) PCI1_CONFIG_DATA;
}
else {
config_addr = (volatile unsigned char*) pci.pci_config_addr;
config_data = (volatile unsigned char*) pci.pci_config_data;
n=1;
}
if ((offset&3)|| (offset & ~0xff)) return PCIBIOS_BAD_REGISTER_NUMBER;
#if 0
printk("addr %x, data %x, pack %x \n", config_addr,
config_data,pciConfigPack(bus,dev,func,offset));
#endif
outl(pciConfigPack(bus,dev,func,offset),config_addr);
outl(val,config_data);
out_be32(BSP_pci[n].pci_config_addr, pciConfigPack(bus,dev,func,offset));
out_le32(BSP_pci[n].pci_config_data, val);
return PCIBIOS_SUCCESSFUL;
}
const pci_config_access_functions pci_direct_functions = {
direct_pci_read_config_byte,
direct_pci_read_config_word,
direct_pci_read_config_dword,
direct_pci_write_config_byte,
direct_pci_write_config_word,
direct_pci_write_config_dword
const pci_config_access_functions pci_indirect_functions = {
indirect_pci_read_config_byte,
indirect_pci_read_config_word,
indirect_pci_read_config_dword,
indirect_pci_write_config_byte,
indirect_pci_write_config_word,
indirect_pci_write_config_dword
};
pci_config BSP_pci_configuration = {(volatile unsigned char*) PCI_CONFIG_ADDR,
(volatile unsigned char*)PCI_CONFIG_DATA,
&pci_direct_functions};
pci_config BSP_pci_configuration = {
(volatile unsigned char*) (GT64x60_PCI_CONFIG_ADDR),
(volatile unsigned char*) (GT64x60_PCI_CONFIG_DATA),
&pci_indirect_functions};
DiscoveryChipVersion BSP_getDiscoveryChipVersion(void)
{
return(BSP_sysControllerVersion);
}
BSP_VMEchipTypes BSP_getVMEchipType(void)
{
return(BSP_VMEinterface);
}
/*
* This routine determines the maximum bus number in the system.
@@ -248,12 +234,12 @@ pci_config BSP_pci_configuration = {(volatile unsigned char*) PCI_CONFIG_ADDR,
int pci_initialize(void)
{
int deviceFound;
unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs;
unsigned int ulHeader;
unsigned int pcidata, ulClass, ulDeviceID;
unsigned char ucBusNumber, ucSlotNumber, ucFnNumber, ucNumFuncs, data8;
uint32_t ulHeader, ulClass, ulDeviceID;
#if PCI_DEBUG
uint32_t pcidata;
#endif
pci_interface();
/*
* Scan PCI0 and PCI1 buses
*/
@@ -279,38 +265,49 @@ int pci_initialize(void)
if (!deviceFound) deviceFound=1;
switch(ulDeviceID) {
case (PCI_VENDOR_ID_MARVELL+(PCI_DEVICE_ID_MARVELL_GT6426xAB<<16)):
pci_read_config_byte(0,0,0,PCI_REVISION_ID, &data8);
switch(data8) {
case 0x10:
BSP_sysControllerVersion = GT64260A;
#if PCI_PRINT
printk("Marvell GT6426xA/B hostbridge detected at bus%d slot%d\n",
printk("Marvell GT64260A (Discovery I) hostbridge detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
case 0x20:
BSP_sysControllerVersion = GT64260B;
#if PCI_PRINT
printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
default:
printk("Undefined revsion of GT64260 chip\n");
break;
}
break;
case (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)):
#if PCI_PRINT
printk("PLX PCI6154 PCI-PCI bridge detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
case PCI_VENDOR_ID_TUNDRA:
#if PCI_PRINT
printk("TUNDRA PCI-VME bridge detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
case (PCI_VENDOR_ID_INTEL+(PCI_DEVICE_INTEL_82544EI_COPPER<<16)):
#if PCI_PRINT
printk("INTEL 82544EI COPPER network controller detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
case (PCI_VENDOR_ID_DEC+(PCI_DEVICE_ID_DEC_21150<<16)):
#if PCI_PRINT
#if PCI_PRINT
printk("DEC21150 PCI-PCI bridge detected at bus%d slot%d\n",
ucBusNumber,ucSlotNumber);
#endif
break;
default :
#if PCI_PRINT
printk("BSP unlisted vendor, Bus%d Slot%d DeviceID 0x%x \n",
ucBusNumber,ucSlotNumber, ulDeviceID);
#endif
/* Kate Feng : device not supported by BSP needs to remap the IRQ line on mvme5500/mvme6100 */
pci_read_config_byte(ucBusNumber,ucSlotNumber,0,PCI_INTERRUPT_LINE,&data8);
if (data8 < BSP_GPP_IRQ_LOWEST_OFFSET) pci_write_config_byte(ucBusNumber,
ucSlotNumber,0,PCI_INTERRUPT_LINE,BSP_GPP_IRQ_LOWEST_OFFSET+data8);
break;
}
@@ -403,34 +400,6 @@ int pci_initialize(void)
#endif
}
pci_read_config_dword(ucBusNumber,
ucSlotNumber,
0,
PCI_COMMAND,
&pcidata);
#if PCI_DEBUG
printk("MOTLoad command staus 0x%x, ", pcidata);
#endif
/* Clear the error on the host bridge */
if ( (ucBusNumber==0) && (ucSlotNumber==0))
pcidata |= PCI_STATUS_CLRERR_MASK;
/* Enable bus,I/O and memory master access. */
pcidata |= (PCI_COMMAND_MASTER|PCI_COMMAND_IO|PCI_COMMAND_MEMORY);
pci_write_config_dword(ucBusNumber,
ucSlotNumber,
0,
PCI_COMMAND,
pcidata);
pci_read_config_dword(ucBusNumber,
ucSlotNumber,
0,
PCI_COMMAND,
&pcidata);
#if PCI_DEBUG
printk("Now command/staus 0x%x\n", pcidata);
#endif
}
if (deviceFound) ucMaxPCIBus++;
} /* for (ucBusNumber=0; ucBusNumber<BSP_MAX_PCI_BUS; ... */
@@ -438,6 +407,7 @@ int pci_initialize(void)
printk("number of PCI buses: %d, numPCIDevs %d\n",
pci_bus_count(), numPCIDevs);
#endif
pci_interface();
return(0);
}

View File

@@ -7,10 +7,14 @@
* found in the file LICENSE in this distribution.
*
* 8/17/2006 : S. Kate Feng
* uses in_le32()/out_le32(), instead of inl()/outl() so that
* it is easier to be ported.
* uses in_le32()/out_le32(), instead of inl()/outl() for compatibility.
*
* 11/2008 : Enable "PCI Read Agressive Prefetch",
* "PCI Read Line Agressive Prefetch", and
* "PCI Read Multiple Agressive Prefetch" to improve the
* performance of the PCI based applications (e.g. 1GHz NIC).
*/
#include <libcpu/io.h>
#include <rtems/bspIo.h> /* printk */
@@ -19,55 +23,29 @@
#include <bsp/gtreg.h>
#include <bsp/gtpcireg.h>
#define REG32_READ(reg) in_le32((volatile unsigned int *)(GT64260_REG_BASE+reg))
#define REG32_WRITE(data, reg) out_le32((volatile unsigned int *)(GT64260_REG_BASE+reg), data)
#define PCI_DEBUG 0
/* Please reference the GT64260B datasheet, for the PCI interface,
* Synchronization Barriers and PCI ordering.
*
* Some PCI devices require Synchronization Barriers or PCI ordering
* for synchronization (only one mechanism allowed. See section 11.1.2).
* To use the former mechanism(default), one needs to call
* CPU0_PciEnhanceSync() or CPU1_PciEnhanceSync() to perform software
* synchronization between the CPU and PCI activities.
*
* To use the PCI-ordering, one can call pciToCpuSync() to trigger
* the PCI-to-CPU sync barrier after the out_xx(). In this mode,
* PCI configuration reads suffer sync barrier latency. Please reference
* the datasheet to explore other options.
*
* Note : If PCI_ORDERING is needed for the PCI0, while disabling the
* deadlock for the PCI0, one should keep the CommDLEn bit enabled
* for the deadlock mechanism so that the 10/100 MB ethernet will
* function correctly.
*
*/
/*#define PCI_ORDERING*/
#define EN_SYN_BAR /* take MOTLoad default for enhanced SYN Barrier mode */
/*#define PCI_DEADLOCK*/
#ifdef PCI_ORDERING
#define PCI_ACCCTLBASEL_VALUE 0x01009000
#else
#define PCI_ACCCTLBASEL_VALUE 0x01001000
#if 0
#define CPU2PCI_ORDER
#define PCI2CPU_ORDER
#endif
/* PCI Read Agressive Prefetch Enable (1<<16 ),
* PCI Read Line Agressive Prefetch Enable( 1<<17),
* PCI Read Multiple Agressive Prefetch Enable (1<<18).
*/
#ifdef PCI2CPU_ORDER
#define PCI_ACCCTLBASEL_VALUE 0x01079000
#else
#define PCI_ACCCTLBASEL_VALUE 0x01071000
#endif
#define ConfSBDis 0x10000000 /* 1: disable, 0: enable */
#define IOSBDis 0x20000000 /* 1: disable, 0: enable */
#define ConfIOSBDis 0x30000000
#define CpuPipeline 0x00002000 /* optional, 1:enable, 0:disable */
#define CPU0_SYNC_TRIGGER 0xD0 /* CPU0 Sync Barrier trigger */
#define CPU0_SYNC_VIRTUAL 0xC0 /* CPU0 Sync Barrier Virtual */
#define CPU1_SYNC_TRIGGER 0xD8 /* CPU1 Sync Barrier trigger */
#define CPU1_SYNC_VIRTUAL 0xC8 /* CPU1 Sync Barrier Virtual */
/* CPU to PCI ordering register */
#define DLOCK_ORDER_REG 0x2D0 /* Deadlock and Ordering register */
#define PCI0OrEn 0x00000001
@@ -91,69 +69,30 @@ void pciAccessInit(void);
void pci_interface(void)
{
#ifdef PCI_DEADLOCK
REG32_WRITE(0x07fff600, CNT_SYNC_REG);
#ifdef CPU2PCI_ORDER
/* MOTLOad deafult : 0x07ff8600 */
out_le32((volatile unsigned int *)(GT64x60_REG_BASE+CNT_SYNC_REG), 0x07fff600);
#endif
#ifdef PCI_ORDERING
/* Let's leave this to be MOTLOad deafult : 0x80070000
REG32_WRITE(0xc0070000, DLOCK_ORDER_REG);*/
/* Leave the CNT_SYNC_REG b/c MOTload default had the SyncBarMode set to 1 */
#endif
/* asserts SERR upon various detection */
REG32_WRITE(0x3fffff, 0xc28);
pciAccessInit();
/* asserts SERR upon various detection */
out_le32((volatile unsigned int *)(GT64x60_REG_BASE+0xc28), 0x3fffff);
pciAccessInit();
}
/* Use MOTLoad default for Writeback Priority and Buffer Depth
*/
void pciAccessInit(void)
{
unsigned int PciLocal, data;
for (PciLocal=0; PciLocal < 2; PciLocal++) {
/* MOTLoad combines the two banks of SDRAM into
* one PCI access control because the top = 0x1ff
*/
data = REG32_READ(GT_SCS0_Low_Decode) & 0xfff;
data = in_le32((volatile unsigned int *)(GT64x60_REG_BASE+PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80)));
#if 0
printk("PCI%d_ACCESS_CNTL_BASE0_LOW was 0x%x\n",PciLocal,data);
#endif
data |= PCI_ACCCTLBASEL_VALUE;
data &= ~0x300000;
REG32_WRITE(data, PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80));
#if PCI_DEBUG
printk("PCI%d_ACCESS_CNTL_BASE0_LOW 0x%x\n",PciLocal,REG32_READ(PCI_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80)));
out_le32((volatile unsigned int *)(GT64x60_REG_BASE+PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80)), data);
#if 0
printf("PCI%d_ACCESS_CNTL_BASE0_LOW now 0x%x\n",PciLocal,in_le32((volatile unsigned int *)(GT64x60_REG_BASE+PCI0_ACCESS_CNTL_BASE0_LOW+(PciLocal * 0x80))));
#endif
}
}
/* Sync Barrier Trigger. A write to the CPU_SYNC_TRIGGER register triggers
* the sync barrier process. The three bits, define which buffers should
* be flushed.
* Bit 0 = PCI0 slave write buffer.
* Bit 1 = PCI1 slave write buffer.
* Bit 2 = SDRAM snoop queue.
*/
void CPU0_PciEnhanceSync(unsigned int syncVal)
{
REG32_WRITE(syncVal,CPU0_SYNC_TRIGGER);
while (REG32_READ(CPU0_SYNC_VIRTUAL));
}
void CPU1_PciEnhanceSync(unsigned int syncVal)
{
REG32_WRITE(syncVal,CPU1_SYNC_TRIGGER);
while (REG32_READ(CPU1_SYNC_VIRTUAL));
}
/* Currently, if PCI_ordering is used for synchronization, configuration
* reads is programmed to be the PCI slave "synchronization barrier"
* cycles.
*/
void pciToCpuSync(int pci_num)
{
unsigned char data;
unsigned char bus=0;
if (pci_num) bus += BSP_MAX_PCI_BUS_ON_PCI0;
pci_read_config_byte(bus,0,0,4, &data);
}

View File

@@ -1,3 +1,6 @@
/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>,
* NSLS,Brookhaven National Laboratory
*/
#include <bsp.h>
#include <rtems/bspIo.h>
#include <libcpu/stackTrace.h>

View File

@@ -24,8 +24,6 @@
* $Id$
*/
#warning The interrupt disable mask is now stored in SPRG0, please verify that this is compatible to this BSP (see also bootcard.c).
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
@@ -52,12 +50,12 @@
#undef __RTEMS_APPLICATION__
#endif
/*
#define SHOW_MORE_INIT_SETTINGS
/*#define SHOW_MORE_INIT_SETTINGS
#define CONF_VPD
#define SHOW_LCR1_REGISTER
#define SHOW_LCR2_REGISTER
#define SHOW_LCR3_REGISTER
#define CONF_VPD
*/
/* there is no public Workspace_Free() variant :-( */
@@ -73,6 +71,7 @@ extern Triv121PgTbl BSP_pgtbl_setup(unsigned long);
extern void BSP_pgtbl_activate(Triv121PgTbl);
extern int I2Cread_eeprom(unsigned char I2cBusAddr, uint32_t devA2A1A0, uint32_t AddrBytes, unsigned char *pBuff, uint32_t numBytes);
extern void BSP_vme_config(void);
extern uint32_t probeMemoryEnd();
uint32_t bsp_clicks_per_usec;
@@ -267,12 +266,10 @@ void bsp_start( void )
setdbat(2, PCI0_MEM_BASE, PCI0_MEM_BASE, 0x10000000, IO_PAGE);
/* Till Straumann: 2004
* map the PCI 0, 1 Domain I/O space, GT64260B registers
* and the reserved area so that the size is the power of 2.
*
* map the PCI 0, 1 Domain I/O space, GT64260B registers,
* Flash Bank 0 and Flash Bank 2.
*/
setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x2000000, IO_PAGE);
setdbat(3,PCI0_IO_BASE, PCI0_IO_BASE, 0x10000000, IO_PAGE);
/*
* Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
@@ -327,29 +324,7 @@ void bsp_start( void )
printk("Welcome to %s on MVME5500-0163\n", _RTEMS_version );
printk("-----------------------------------------\n");
#ifdef TEST_RETURN_TO_PPCBUG
printk("Hit <Enter> to return to PPCBUG monitor\n");
printk("When Finished hit GO. It should print <Back from monitor>\n");
debug_getc();
_return_to_ppcbug();
printk("Back from monitor\n");
_return_to_ppcbug();
#endif /* TEST_RETURN_TO_PPCBUG */
#ifdef TEST_RAW_EXCEPTION_CODE
printk("Testing exception handling Part 1\n");
/*
* Cause a software exception
*/
__asm__ __volatile ("sc");
/*
* Check we can still catch exceptions and returned coorectly.
*/
printk("Testing exception handling Part 2\n");
__asm__ __volatile ("sc");
#endif
BSP_mem_size = _512M;
BSP_mem_size = probeMemoryEnd();
/* TODO: calculate the BSP_bus_frequency using the REF_CLK bit
* of System Status register
*/
@@ -421,6 +396,19 @@ void bsp_start( void )
#endif
BSP_pgtbl_activate(pt);
}
/* Read Configuration Vital Product Data (VPD) */
if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
printk("I2Cread_eeprom() error \n");
else {
#ifdef CONF_VPD
printk("\n");
for (i=0; i<150; i++) {
printk("%2x ", ConfVPD_buff[i]);
if ((i % 20)==0 ) printk("\n");
}
printk("\n");
#endif
}
/*
* PCI 1 domain memory space
@@ -444,23 +432,14 @@ void bsp_start( void )
*/
_BSP_clear_hostbridge_errors(0, 1 /*quiet*/);
/* Read Configuration Vital Product Data (VPD) */
if ( I2Cread_eeprom(0xa8, 4,2, &ConfVPD_buff[0], 150))
printk("I2Cread_eeprom() error \n");
else {
#ifdef CONF_VPD
printk("\n");
for (i=0; i<150; i++) {
printk("%2x ", ConfVPD_buff[i]);
if ((i % 20)==0 ) printk("\n");
}
printk("\n");
#endif
}
#ifdef SHOW_MORE_INIT_SETTINGS
printk("MSR %x \n", _read_MSR());
printk("Exit from bspstart\n");
#endif
}
unsigned char ReadConfVPD_buff(int offset)
{
return(ConfVPD_buff[offset]);
}

View File

@@ -1,3 +1,10 @@
/* Copyright 2003, Shuchen Kate Feng <feng1@bnl.gov>,
* NSLS,Brookhaven National Laboratory
*
* Ported it from powerpc/shared/console/reboot.c for mvme5500
*
*/
#include <rtems.h>
#include <bsp.h>
#include <rtems/bspIo.h>
@@ -12,5 +19,5 @@ void bsp_reset()
printk("RTEMS terminated; Rebooting ...\n");
/* Mvme5500 board reset : 2004 S. Kate Feng <feng1@bnl.gov> */
out_8((volatile unsigned char*) (GT64260_DEV1_BASE +2), 0x80);
out_8((volatile unsigned char*) (GT64x60_DEV1_BASE +2), 0x80);
}

View File

@@ -134,6 +134,8 @@ int quiet=0;
/* register dump */
printk("\t Next PC or Address of fault = %x, ", excPtr->EXC_SRR0);
printk("Mvme5500 Saved MSR = %x\n", excPtr->EXC_SRR1);
printk("The Interrupt mask (e.g. MSR_EE) stored in SPRG0= 0x%x\n",
ppc_interrupt_get_disable_mask());
printk("\t R0 = %08x", excPtr->GPR0);
printk(" R1 = %08x", excPtr->GPR1);
printk(" R2 = %08x", excPtr->GPR2);