From cf599996ba514dafe6f3520c5d64028bb7787cce Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Fri, 8 May 2009 18:22:51 +0000 Subject: 2009-05-08 Kate Feng 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. --- c/src/lib/libbsp/powerpc/mvme5500/ChangeLog | 18 + c/src/lib/libbsp/powerpc/mvme5500/GT64260/VPD.h | 2 - c/src/lib/libbsp/powerpc/mvme5500/GT64260/gtreg.h | 13 +- c/src/lib/libbsp/powerpc/mvme5500/Makefile.am | 6 +- c/src/lib/libbsp/powerpc/mvme5500/README | 7 +- c/src/lib/libbsp/powerpc/mvme5500/README.booting | 31 +- c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h | 80 +++- c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c | 14 +- .../mvme5500/network/if_100MHz/GT64260eth.c | 17 +- .../powerpc/mvme5500/network/if_1GHz/if_wm.c | 418 ++++++++++++++++----- .../powerpc/mvme5500/network/if_1GHz/if_wmreg.h | 7 +- .../powerpc/mvme5500/network/if_1GHz/pcireg.h | 4 +- c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c | 260 ++++++------- .../libbsp/powerpc/mvme5500/pci/pci_interface.c | 125 ++---- .../lib/libbsp/powerpc/mvme5500/startup/bspclean.c | 3 + .../lib/libbsp/powerpc/mvme5500/startup/bspstart.c | 73 ++-- c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c | 9 +- .../powerpc/mvme5500/vectors/exceptionhandler.c | 2 + 18 files changed, 631 insertions(+), 458 deletions(-) (limited to 'c/src') diff --git a/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog b/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog index 5b1b15fd3f..490348c311 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog +++ b/c/src/lib/libbsp/powerpc/mvme5500/ChangeLog @@ -1,3 +1,21 @@ +2009-05-08 Kate Feng + + 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 * bsp_specs: Backport from CVS-HEAD. diff --git a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/VPD.h b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/VPD.h index 4b37de6927..33aec8b74c 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/VPD.h +++ b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/VPD.h @@ -5,7 +5,5 @@ * */ -extern unsigned char ConfVPD_buff[200]; - #define VPD_ENET0_OFFSET 0x3c #define VPD_ENET1_OFFSET 0x45 diff --git a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/gtreg.h b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/gtreg.h index b58b086565..1c2b7b24d3 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/GT64260/gtreg.h +++ b/c/src/lib/libbsp/powerpc/mvme5500/GT64260/gtreg.h @@ -190,7 +190,7 @@ #define GT_MPP_Control2 0xf008 #define GT_MPP_Control3 0xf00c -/* added */ +/* 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 */ -#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 */ diff --git a/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am b/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am index d44e1d8b21..7af78a0186 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mvme5500/Makefile.am @@ -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 diff --git a/c/src/lib/libbsp/powerpc/mvme5500/README b/c/src/lib/libbsp/powerpc/mvme5500/README index 53986d4bac..c5b21fc44a 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/README +++ b/c/src/lib/libbsp/powerpc/mvme5500/README @@ -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, diff --git a/c/src/lib/libbsp/powerpc/mvme5500/README.booting b/c/src/lib/libbsp/powerpc/mvme5500/README.booting index 19e9567908..66586854c3 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/README.booting +++ b/c/src/lib/libbsp/powerpc/mvme5500/README.booting @@ -1,8 +1,9 @@ -README.booting: written by S. Kate Feng , Aug. 28, 2007 +README.booting: written by S. Kate Feng , 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. diff --git a/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h b/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h index d7436af42a..02ca04d243 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h +++ b/c/src/lib/libbsp/powerpc/mvme5500/include/bsp.h @@ -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 #include -#include +/* 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) /* 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 diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c index 700f7c2464..d01b5541a2 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c @@ -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"); diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c index 4f7b76bb30..3ed43638b1 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_100MHz/GT64260eth.c @@ -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. (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); diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c index f4c2edab2d..1224ddaa4f 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wm.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2004,2005 RTEMS/Mvme5500 port by S. Kate Feng + * 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 #include /* printk */ + #include /* printf for statistics */ #include @@ -64,6 +67,7 @@ #include #include #include +#include #ifdef INET #include @@ -75,14 +79,12 @@ #include #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 +/* 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 (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 + /* 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 +} diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h index d0fd42f1ce..f1615e8cb7 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/if_wmreg.h @@ -5,6 +5,9 @@ * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * Some are added by Shuchen Kate Feng , + * 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 */ diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h index 4a31bbe621..2b8b10d853 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/if_1GHz/pcireg.h @@ -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 /* * 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 diff --git a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c index 5a129aea84..0bc243cfa0 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/pci/pci.c @@ -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, , 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, + * + * - 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 #include /* printk */ +#include #include #include #include +#include #include #include #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 (PCI_VENDOR_ID_PLX2+(PCI_DEVICE_ID_PLX2_PCI6154_HB2<<16)): + break; + case 0x20: + BSP_sysControllerVersion = GT64260B; #if PCI_PRINT - printk("PLX PCI6154 PCI-PCI bridge detected at bus%d slot%d\n", + printk("Marvell GT64260B (Discovery I) hostbridge detected at bus%d slot%d\n", ucBusNumber,ucSlotNumber); #endif - break; + break; + default: + printk("Undefined revsion of GT64260 chip\n"); + break; + } + 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 #include /* printk */ @@ -19,55 +23,29 @@ #include #include -#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*/ +#if 0 +#define CPU2PCI_ORDER +#define PCI2CPU_ORDER +#endif -#ifdef PCI_ORDERING -#define PCI_ACCCTLBASEL_VALUE 0x01009000 +/* 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 0x01001000 +#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); -} diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c index c1485a856c..84528828e8 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspclean.c @@ -1,3 +1,6 @@ +/* Copyright 2003, Shuchen Kate Feng , + * NSLS,Brookhaven National Laboratory + */ #include #include #include diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c index ae5fdc3723..73ad4ab2de 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/bspstart.c @@ -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 #include #include @@ -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 to return to PPCBUG monitor\n"); - printk("When Finished hit GO. It should print \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]); +} diff --git a/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c b/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c index eb32cadbb6..d04d1290ae 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/startup/reboot.c @@ -1,3 +1,10 @@ +/* Copyright 2003, Shuchen Kate Feng , + * NSLS,Brookhaven National Laboratory + * + * Ported it from powerpc/shared/console/reboot.c for mvme5500 + * + */ + #include #include #include @@ -12,5 +19,5 @@ void bsp_reset() printk("RTEMS terminated; Rebooting ...\n"); /* Mvme5500 board reset : 2004 S. Kate Feng */ - out_8((volatile unsigned char*) (GT64260_DEV1_BASE +2), 0x80); + out_8((volatile unsigned char*) (GT64x60_DEV1_BASE +2), 0x80); } diff --git a/c/src/lib/libbsp/powerpc/mvme5500/vectors/exceptionhandler.c b/c/src/lib/libbsp/powerpc/mvme5500/vectors/exceptionhandler.c index 393d9d992f..efb11487e9 100644 --- a/c/src/lib/libbsp/powerpc/mvme5500/vectors/exceptionhandler.c +++ b/c/src/lib/libbsp/powerpc/mvme5500/vectors/exceptionhandler.c @@ -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); -- cgit v1.2.3