diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/greth/current/cdl/greth_drivers.cdl ecos-rep/packages/devs/eth/greth/current/cdl/greth_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/greth/current/cdl/greth_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/greth/current/cdl/greth_drivers.cdl 2005-12-14 11:27:31.000000000 +0100 @@ -0,0 +1,141 @@ +# ==================================================================== +# +# greth_drivers.cdl +# +# Ethernet drivers - support for Gaisler Research's GRETH ethernet MAC +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2004 Andrew Lunn +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Gaisler Research, (Kristoffer Carlsson ) +# Contributors: +# Date: 2005-11-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_GRETH { + display "Gaisler Research's GRETH driver" + description "Ethernet driver for GRETH MAC." + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + + active_if CYGINT_DEVS_ETH_GRETH_REQUIRED + + include_dir . + include_files ; # none _exported_ whatsoever + compile -library=libextras.a if_greth.c + + include_files include/if_greth.h + + define_proc { + puts $::cdl_header "#include "; + puts $::cdl_header "#include CYGDAT_DEVS_ETH_GRETH_CFG"; + } + + cdl_option CYGNUM_DEVS_ETH_GRETH_DEV_COUNT { + display "Number of supported interfaces." + calculated { CYGINT_DEVS_ETH_GRETH_REQUIRED } + flavor data + description " + This option selects the number of ethernet interfaces to + be supported by the driver." + } + + cdl_interface CYGINT_DEVS_ETH_GRETH_STATIC_ESA { + display "ESA is statically configured" + description " + If this is nonzero, then the ESA (MAC address) is statically + configured in the platform-specific package which instantiates + this driver with all its details. + + Note that use of this option is deprecated in favor of a + CYGSEM_DEVS_ETH_..._SET_ESA option in the platform specific + driver." + } + + cdl_option CYGINT_DEVS_ETH_GRETH_TxNUM { + display "Number of output buffers" + flavor data + legal_values 2 to 64 + default_value 4 + description " + This option specifies the number of output buffer packets + to be used for the GRETH ethernet mac in multiples of 2." + } + + cdl_option CYGINT_DEVS_ETH_GRETH_RxNUM { + display "Number of input buffers" + flavor data + legal_values 2 to 64 + default_value 8 + description " + This option specifies the number of input buffer packets + to be used for the GRETH ethernet mac in multiples of 2." + } + + cdl_component CYGPKG_DEVS_ETH_GRETH_OPTIONS { + display "GRETH driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_GRETH_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the GRETH driver package. + These flags are used in addition + to the set of global flags." + } + } + + cdl_component CYGPKG_DEVS_ETH_GRETH_FLUSH { + display "Cache flushing" + flavor bool + default_value 1 + description "Flush cache before copying packets from/to the + ethermac dma transfer buffers. If you have cache snooping enabled + you can disable this option." + + } + +} diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/greth/current/include/if_greth.h ecos-rep/packages/devs/eth/greth/current/include/if_greth.h --- ecos-cvs-2005-09-06/packages/devs/eth/greth/current/include/if_greth.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/greth/current/include/if_greth.h 2005-12-14 15:05:45.000000000 +0100 @@ -0,0 +1,141 @@ +#ifndef CYGONCE_DEVS_ETH_GRETH_IF_GRETH_H +#define CYGONCE_DEVS_ETH_GRETH_IF_GRETH_H + +/*========================================================================== +// +// if_greth.h +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Kristoffer Carlsson ) +// Contributors: +// Date: 2005-11-29 +// Description: +// +//####DESCRIPTIONEND#### +*/ + +#include +#define GRETH_FD 0x10 +#define GRETH_RESET 0x40 +#define PHY_ADDR 0 +#define GRETH_MII_BUSY 0x8 +#define GRETH_MII_NVALID 0x10 + +#define GRETH_BD_EN 0x800 +#define GRETH_BD_WR 0x1000 +#define GRETH_BD_IE 0x2000 +#define GRETH_BD_LEN 0x7FF + +#define GRETH_INT_TX 0x8 +#define GRETH_TXEN 0x1 +#define GRETH_TXI 0x4 +#define GRETH_TXBD_STATUS 0xFFFFC000 +#define GRETH_TXBD_ERR_UE 0x4000 +#define GRETH_TXBD_ERR_AL 0x8000 +#define GRETH_TXBD_NUM CYGINT_DEVS_ETH_GRETH_TxNUM +#define GRETH_TXBD_NUM_MASK GRETH_TXBD_NUM-1 +#define GRETH_TX_BUF_SIZE 1516 + +#define GRETH_INT_RX 0x4 +#define GRETH_RXEN 0x2 +#define GRETH_RXI 0x8 +#define GRETH_RXBD_STATUS 0xFFFFC000 +#define GRETH_RXBD_ERR_AE 0x4000 +#define GRETH_RXBD_ERR_FT 0x8000 +#define GRETH_RXBD_ERR_CRC 0x10000 +#define GRETH_RXBD_ERR_OE 0x20000 +#define GRETH_RXBD_NUM CYGINT_DEVS_ETH_GRETH_RxNUM +#define GRETH_RXBD_NUM_MASK GRETH_RXBD_NUM-1 +#define GRETH_RX_BUF_SIZE 1516 + +/* Ethernet configuration registers */ +typedef struct _greth_regs { + volatile cyg_uint32 control; + volatile cyg_uint32 status; + volatile cyg_uint32 esa_msb; + volatile cyg_uint32 esa_lsb; + volatile cyg_uint32 mdio; + volatile cyg_uint32 tx_desc_p; + volatile cyg_uint32 rx_desc_p; +} greth_regs; + +/* Ethernet buffer descriptor */ +typedef struct _greth_bd { + cyg_uint32 stat; + cyg_uint32 addr; /* Buffer address */ +} greth_bd; + + +/* The buffer descriptors track the ring buffers. */ +struct bd_info { + + volatile greth_bd *tx_ring; /* Address of Tx BDs. */ + cyg_uint32 tx_next; /* Next buffer to be sent */ + cyg_uint32 tx_last; /* Next buffer to be checked if packet sent */ + cyg_uint32 tx_free; /* Number of free tx descriptors */ + cyg_uint32 tx_keys[GRETH_TXBD_NUM]; /* remember tx keys */ + + volatile greth_bd *rx_ring; /* Address of Rx BDs. */ + cyg_uint32 rx_cur; /* Next buffer to be checked if packet received */ +}; + + +typedef struct _greth_info { + greth_regs *regs; /* Address of controller registers. */ + + struct bd_info bdi; + + cyg_uint8 esa[6]; + struct eth_drv_sc *sc; + cyg_uint32 idx; + cyg_uint32 active; + + // Interrupt handling stuff + cyg_uint32 irq; + cyg_vector_t vector; // interrupt vector + cyg_handle_t interrupt_handle; // handle for int.handler + cyg_interrupt interrupt_object; + +} greth_info; + + + +#endif + + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/greth/current/src/if_greth.c ecos-rep/packages/devs/eth/greth/current/src/if_greth.c --- ecos-cvs-2005-09-06/packages/devs/eth/greth/current/src/if_greth.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/greth/current/src/if_greth.c 2006-05-15 09:37:59.000000000 +0200 @@ -0,0 +1,745 @@ +//========================================================================== +// +// dev/if_greth.c +// +// Ethernet device driver for Gaisler Research's ethernet mac +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Nick Garnett +// Copyright (C) 2004 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Kristoffer Carlsson ) +// Contributors: +// Date: 2005-12-06 +// Purpose: +// Description: +// Notes: +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include +#ifdef CYGPKG_IO_ETH_DRIVERS +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CYGPKG_NET +#include +#include +#include +#endif + +#ifdef CYGPKG_KERNEL +#include +#endif + +#if CYGNUM_DEVS_ETH_GRETH_DEV_COUNT > 1 +#error Only 1 mac at a time supported yet +#endif + +//#define DEBUG_GRETH + +#ifdef DEBUG_GRETH + +#define DEBUG_RX_PACKETS 0 +#define DEBUG_TX_PACKETS 0 +#define os_printf diag_printf +#define db_printf diag_printf + +#else + +#define DEBUG_RX_PACKETS 0 +#define DEBUG_TX_PACKETS 0 +#define os_printf(fmt,...) +#define db_printf(fmt,...) + +#endif + +#define MACADDR0 macaddr[0] +#define MACADDR1 macaddr[1] +#define MACADDR2 macaddr[2] +#define MACADDR3 macaddr[3] +#define MACADDR4 macaddr[4] +#define MACADDR5 macaddr[5] + +#include +#include CYGDAT_DEVS_ETH_GRETH_INL + +cyg_uint8 macaddr[6] = CYGPKG_DEVS_ETH_GRETH_ETH0_ESA; + +#define LOAD(a,v) HAL_READ_UINT32(&(a),v); +#define SAVE(a,v) HAL_WRITE_UINT32(&(a),v); +#define REGORIN(a,v) \ + { cyg_uint32 va; \ + LOAD(a,va); \ + va |= v; \ + SAVE(a,va); \ + } +#define REGANDIN(a,v) \ + { cyg_uint32 va; \ + LOAD(a,va); \ + va &= v; \ + SAVE(a,va); \ + } + +static void greth_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ); +static void greth_stop( struct eth_drv_sc *sc ); +static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data); +static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); + +static void greth_tx(struct eth_drv_sc *sc); +static void greth_rx(struct eth_drv_sc *sc); + +static cyg_uint8 rxbuf[GRETH_RXBD_NUM*GRETH_RX_BUF_SIZE]; +static cyg_uint8 txbuf[GRETH_TXBD_NUM*GRETH_TX_BUF_SIZE]; + +static char rxbufr[1024*2]; +static char txbufr[1024*2]; + +static char *almalloc(int sz) +{ + char *tmp; + tmp = calloc(1,2*sz); + tmp = (char *) (((int)tmp+sz) & ~(sz -1)); + return(tmp); +} + +static void greth_print_packet(unsigned long addr, int len) +{ + int i; + diag_printf("packet: addr = %x len = %d\n", (unsigned int)addr, len); + for(i = 0; i < len; i++) { + if(!(i % 16)) + diag_printf("\n"); + diag_printf(" %.2x", *(((unsigned char *)addr) + i)); + } + diag_printf("\n"); + diag_printf("\n"); +} + +static int read_mii(int addr, volatile greth_regs *regs) +{ + cyg_uint32 tmp; + + do { + LOAD(regs->mdio, tmp); + } while (tmp & GRETH_MII_BUSY); + + tmp = (PHY_ADDR << 11) | ((addr&0x1F) << 6) | 2; + SAVE(regs->mdio, tmp); + + do { + LOAD(regs->mdio, tmp); + } while (tmp & GRETH_MII_BUSY); + + if (!(tmp & GRETH_MII_NVALID)) { + LOAD(regs->mdio, tmp); + return (tmp>>16)&0xFFFF; + } + else { + diag_printf("GRETH: failed to read mii\n"); + return (0); + } +} + +static void write_mii(int addr, int data, volatile greth_regs *regs) +{ + cyg_uint32 tmp; + do { + LOAD(regs->mdio, tmp); + } while (tmp & GRETH_MII_BUSY); + + tmp = ((data&0xFFFF)<<16) | (PHY_ADDR << 11) | ((addr&0x1F) << 6) | 1; + + SAVE(regs->mdio, tmp); + + do { + LOAD(regs->mdio, tmp); + } while (tmp & GRETH_MII_BUSY); + +} + +#ifdef ETH_DRV_GET_MAC_ADDRESS +static int eth_get_mac_address(struct eth_drv_sc *sc, char *addr) +{ + greth_info *gi = (greth_info *)sc->driver_private; + cyg_uint32 m0,m1; + + db_printf("eth_get_mac_address\n"); + + LOAD(gi->regs->esa_msb, m1); + LOAD(gi->regs->esa_lsb, m0); + + addr[0] = (m1 >> 8) & 0xff; + addr[1] = (m1 >> 0) & 0xff; + addr[2] = (m0 >>24) & 0xff; + addr[3] = (m0 >>16) & 0xff; + addr[4] = (m0 >> 8) & 0xff; + addr[5] = (m0 >> 0) & 0xff; + return 0; +} +#endif + +#ifdef ETH_DRV_SET_MAC_ADDRESS +static int eth_set_mac_address(struct eth_drv_sc *sc, cyg_uint8 *addr) +{ + greth_info *gi = (greth_info *)sc->driver_private; + + db_printf("eth_set_mac_address\n"); + + gi->esa[0] = addr[0]; + gi->esa[1] = addr[1]; + gi->esa[2] = addr[2]; + gi->esa[3] = addr[3]; + gi->esa[4] = addr[4]; + gi->esa[5] = addr[5]; + SAVE(gi->regs->esa_msb, addr[0] << 8 | addr[1]); + SAVE(gi->regs->esa_lsb, addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5]); + return 1; +} +#endif + +/* Calls leon eth init */ +bool greth_init(struct cyg_netdevtab_entry *ndp) { + return CYGPKG_DEVS_ETH_GRETH_INITFN(ndp); +} + +/* Called from leon eth init */ +void greth_device_init(struct eth_drv_sc *sc, cyg_uint32 idx, cyg_uint32 base, cyg_uint32 irq) { + + greth_info *gi = (greth_info *)sc->driver_private; + struct bd_info *bdi = &greth_priv_array[idx]->bdi; + + int i, tmp; + + /* Set default ethernet station address. */ + gi->esa[0] = MACADDR0; + gi->esa[1] = MACADDR1; + gi->esa[2] = MACADDR2; + gi->esa[3] = MACADDR3; + gi->esa[4] = MACADDR4; + gi->esa[5] = MACADDR5; + + gi->sc = sc; + gi->idx = idx; + + gi->regs = (greth_regs *) base; + gi->irq = irq; + + /* Reset the controller. */ + SAVE(gi->regs->control, GRETH_RESET); + + do { + LOAD(gi->regs->control, tmp); + } while (tmp & GRETH_RESET); + + bdi->tx_ring = (((unsigned int)&txbufr) + (1024-1)) & ~(1024-1) ; + bdi->rx_ring = (((unsigned int)&rxbufr) + (1024-1)) & ~(1024-1) ; + SAVE(gi->regs->tx_desc_p, (cyg_uint32) bdi->tx_ring); + SAVE(gi->regs->rx_desc_p, (cyg_uint32) bdi->rx_ring); + + /* Configure PHY */ + + write_mii(0, 0x8000, gi->regs); /* reset phy */ + while ( (tmp=read_mii(0, gi->regs)) & 0x8000) + ; + + i = 0; + if (tmp & 0x1000) { /* augo neg */ + while ( !(read_mii(1, regs) & 0x20 ) ) { + i++; + if (i>50000) { + printk("Auto-negotiation failed\n"); + break; + } + } + } + + tmp = read_mii(0, gi->regs); + + diag_printf("GRETH(%d) Ethernet MAC at [0x%x] irq %d. Running %d Mbps %s duplex\n", idx, (unsigned int)(gi->regs), (unsigned int)(gi->irq), \ + ((tmp&0x2040) == 0x2000) ? 100:10, (tmp&0x0100) ? "full":"half"); + if (tmp & 0x0100) { + /* set full duplex */ + SAVE(gi->regs->control, GRETH_FD); + + } + + + /* Initialize descriptor buffer addresses. */ + for(i = 0; i < GRETH_TXBD_NUM; i++) { + SAVE(bdi->tx_ring[i].addr , &txbuf[i*GRETH_TX_BUF_SIZE]); + } + for(i = 0; i < GRETH_RXBD_NUM; i++) { + SAVE(bdi->rx_ring[i].addr, &rxbuf[i*GRETH_RX_BUF_SIZE]); + } + + SAVE(gi->regs->esa_msb , MACADDR0 << 8 | MACADDR1); + SAVE(gi->regs->esa_lsb , MACADDR2 << 24 | MACADDR3 << 16 | MACADDR4 << 8 | MACADDR5); + + + // Initialize upper level driver + (sc->funs->eth_drv->init)(sc, gi->esa); +} + +static void greth_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ) { + + greth_info *gi = (greth_info *) sc->driver_private; + struct bd_info *bdi = (struct bd_info *) &(gi->bdi); + + int i; + + if ( gi->active ) + greth_stop( sc ); + + db_printf("greth_start: irq %d\n",gi->irq); + + bdi->rx_cur = 0; + bdi->tx_next = 0; + bdi->tx_last = 0; + bdi->tx_free = GRETH_TXBD_NUM; + SAVE(gi->regs->tx_desc_p, (cyg_uint32) bdi->tx_ring); + SAVE(gi->regs->rx_desc_p, (cyg_uint32) bdi->rx_ring); + + for (i = 0; i < GRETH_RXBD_NUM; i++) { + REGORIN(bdi->rx_ring[i].stat, GRETH_BD_EN | GRETH_BD_IE); + } + REGORIN(bdi->rx_ring[GRETH_RXBD_NUM-1].stat, GRETH_BD_WR); + + /* Install our interrupt handler. */ + cyg_drv_interrupt_create(gi->irq, + 0, // Priority - unused + (CYG_ADDRWORD)sc, // Data item passed to ISR & DSR + eth_isr, // ISR +#ifdef CYGPKG_DEVS_ETH_GRETH_FLUSH + eth_dsr, // Custom DSR which invalidates DCACHE +#else + eth_drv_dsr, // Kernel DSR +#endif + &gi->interrupt_handle, // handle to intr obj + &gi->interrupt_object ); // space for int obj + cyg_drv_interrupt_attach(gi->interrupt_handle); + cyg_drv_interrupt_acknowledge(gi->irq); + cyg_drv_interrupt_unmask(gi->irq); + + // Enable device + gi->active = 1; + + /* Enable receiver and transmiter and interrupts */ + REGORIN(gi->regs->control , GRETH_RXEN | GRETH_TXEN | GRETH_TXI | GRETH_RXI); +} + + +static void greth_stop( struct eth_drv_sc *sc ) { + + greth_info *gi = (greth_info *) sc->driver_private; + struct bd_info *bdi = (struct bd_info *) &(gi->bdi); + int i; + + db_printf("greth_stop\n"); + + /* Free interrupt hadler */ + cyg_interrupt_delete(gi->interrupt_handle); + + /* Disable receiver and transmitesr */ + REGANDIN(gi->regs->control , ~(GRETH_RXEN | GRETH_TXEN | GRETH_TXI | GRETH_RXI)); + + for (i = 0; i < GRETH_RXBD_NUM; i++) { + SAVE(bdi->rx_ring[i].stat, 0); + } + + for (i = 0; i < GRETH_TXBD_NUM; i++) { + SAVE(bdi->tx_ring[i].stat, 0); + } + + memset(bdi->tx_keys, 0, sizeof(bdi->tx_keys)); + + gi->active = 0; + +} + +static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + greth_info *gi = (greth_info *)sc->driver_private; + + cyg_uint32 int_events, calldsr = 0; + + cyg_drv_interrupt_acknowledge(gi->irq); + + cyg_drv_interrupt_mask(gi->irq); + + + /* schedule dsr */ + return (CYG_ISR_HANDLED|CYG_ISR_CALL_DSR); +} + +/* This dsr is only used if CYGPKG_DEVS_ETH_GRETH_FLUSH is defined */ +static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + HAL_DCACHE_INVALIDATE_ALL(); + eth_drv_dsr( vector, count, (cyg_addrword_t)sc ); +} + +static void greth_deliver(struct eth_drv_sc *sc) { + greth_info *gi = (greth_info *)sc->driver_private; + volatile greth_bd *bdp; + + cyg_uint32 status, pkt_len; + + /* Handle received packets */ + while (1) { + + bdp = gi->bdi.rx_ring + gi->bdi.rx_cur; + + LOAD(bdp->stat, status); + + if ((status & GRETH_BD_EN) == 0) { /* packet received */ + + if (status & GRETH_RXBD_STATUS) { + if (status & GRETH_RXBD_ERR_AE) { + diag_printf("GRETH(%d): Rx alignment error.\n", gi->idx); + } + if (status & GRETH_RXBD_ERR_FT) { + diag_printf("GRETH(%d): Rx frame to long error.\n", gi->idx); + } + if (status & GRETH_RXBD_ERR_CRC) { + diag_printf("GRETH(%d): Rx crc error.\n", gi->idx); + } + if (status & GRETH_RXBD_ERR_OE) { + diag_printf("GRETH(%d): Rx fifo overrun error.\n", gi->idx); + } + + /* enable descriptor for new packet */ + REGORIN(bdp->stat, GRETH_BD_EN | GRETH_BD_IE | ((gi->bdi.rx_cur == GRETH_RXBD_NUM_MASK) ? GRETH_BD_WR : 0) ); + REGORIN(gi->regs->control, GRETH_RXEN); + + gi->bdi.rx_cur = ((gi->bdi.rx_cur + 1) & GRETH_RXBD_NUM_MASK); + continue; + + } + + pkt_len = status & GRETH_BD_LEN; + + /* notify stack */ + (sc->funs->eth_drv->recv)( sc, pkt_len ); + + /* clear descriptor */ + SAVE(bdp->stat, 0); + + /* enable descriptor for new packet */ + REGORIN(bdp->stat, GRETH_BD_EN | GRETH_BD_IE | ((gi->bdi.rx_cur == GRETH_RXBD_NUM_MASK) ? GRETH_BD_WR : 0) ); + REGORIN(gi->regs->control, GRETH_RXEN); + + gi->bdi.rx_cur = ((gi->bdi.rx_cur + 1) & GRETH_RXBD_NUM_MASK); + } + else break; + + } + + /* handle sent packets */ + while (gi->bdi.tx_free != GRETH_TXBD_NUM) { + + bdp = gi->bdi.tx_ring + gi->bdi.tx_last; + + LOAD(bdp->stat, status); + + if (status & GRETH_BD_EN) break; /* packet not sent */ + + if (status & GRETH_TXBD_STATUS) { + (sc->funs->eth_drv->tx_done)( sc, gi->bdi.tx_keys[gi->bdi.tx_last], 1 ); /*indicate error */ + + if (status & GRETH_TXBD_ERR_UE) { + diag_printf("GRETH(%d): Tx fifo underrun error.\n", gi->idx); + } + if (status & GRETH_TXBD_ERR_AL) { + diag_printf("GRETH(%d): Tx attempt limit error.\n", gi->idx); + } + } + else { + (sc->funs->eth_drv->tx_done)( sc, gi->bdi.tx_keys[gi->bdi.tx_last], 0 ); + + } + + gi->bdi.tx_last = ((gi->bdi.tx_last + 1) & GRETH_TXBD_NUM_MASK); + gi->bdi.tx_free++; + } + + cyg_drv_interrupt_unmask(gi->irq); + +} + + +/* /\* Notifies stack about received packets *\/ */ +/* static void greth_rx(struct eth_drv_sc *sc) { */ + +/* greth_info *gi = (greth_info *)sc->driver_private; */ +/* volatile greth_bd *bdp; */ + +/* cyg_uint32 status; */ +/* int pkt_len; */ + +/* /\* Handle received packets *\/ */ +/* while (1) { */ + +/* bdp = gi->bdi.rx_ring + gi->bdi.rx_cur; */ + +/* LOAD(bdp->stat, status); */ + +/* if ((status & GRETH_BD_EN) == 0) { /\* packet received *\/ */ + +/* if (status & GRETH_RXBD_STATUS) { */ +/* if (status & GRETH_RXBD_ERR_AE) { */ +/* diag_printf("GRETH(%d): Rx alignment error.\n", gi->idx); */ +/* continue; */ +/* } */ +/* if (status & GRETH_RXBD_ERR_FT) { */ +/* diag_printf("GRETH(%d): Rx frame to long error.\n", gi->idx); */ +/* continue; */ +/* } */ +/* if (status & GRETH_RXBD_ERR_CRC) { */ +/* diag_printf("GRETH(%d): Rx crc error.\n", gi->idx); */ +/* continue; */ +/* } */ +/* if (status & GRETH_RXBD_ERR_OE) { */ +/* diag_printf("GRETH(%d): Rx fifo overrun error.\n", gi->idx); */ +/* continue; */ +/* } */ +/* } */ + +/* pkt_len = status & GRETH_BD_LEN; */ + +/* /\* notify stack *\/ */ +/* (sc->funs->eth_drv->recv)( sc, pkt_len ); */ + +/* /\* clear descriptor *\/ */ +/* SAVE(bdp->stat, 0); */ + +/* /\* enable descriptor for new packet *\/ */ +/* REGORIN(bdp->stat, GRETH_BD_EN | GRETH_BD_IE | ((gi->bdi.rx_cur == GRETH_RXBD_NUM_MASK) ? GRETH_BD_WR : 0) ); */ +/* REGORIN(gi->regs->control, GRETH_RXEN); */ + +/* gi->bdi.rx_cur = ((gi->bdi.rx_cur + 1) & GRETH_RXBD_NUM_MASK); */ +/* } */ +/* else break; */ + +/* } */ +/* } */ + + +/* /\* Checks for sent packets and passes tx-keys up the stack when packets are transmitted, called from can_send() and deliver() *\/ */ +/* static void greth_tx(struct eth_drv_sc *sc) { */ +/* greth_info *gi = (greth_info *)sc->driver_private; */ +/* volatile greth_bd *bdp; */ +/* cyg_uint32 status; */ + +/* while (gi->bdi.tx_free != GRETH_TXBD_NUM) { */ + +/* bdp = gi->bdi.tx_ring + gi->bdi.tx_last; */ + +/* LOAD(bdp->stat, status); */ + +/* if (status & GRETH_BD_EN) break; /\* packet not sent *\/ */ + +/* if (status & GRETH_TXBD_STATUS) { */ +/* (sc->funs->eth_drv->tx_done)( sc, gi->bdi.tx_keys[gi->bdi.tx_last], 1 ); /\*indicate error *\/ */ +/* diag_printf("Error in transfer.\n"); */ +/* } */ +/* else { */ +/* (sc->funs->eth_drv->tx_done)( sc, gi->bdi.tx_keys[gi->bdi.tx_last], 0 ); */ +/* // db_printf("Descriptor %d sent successfully\n", bdi->tx_last); */ +/* } */ + +/* gi->bdi.tx_last = ((gi->bdi.tx_last + 1) & GRETH_TXBD_NUM_MASK); */ +/* gi->bdi.tx_free++; */ +/* } */ +/* } */ + + +static int greth_can_send(struct eth_drv_sc *sc) { + greth_info *gi = (greth_info *)sc->driver_private; + + db_printf("can_send - tx_free: %d\n", bdi->tx_free); + + return gi->bdi.tx_free; +} + +static void greth_send(struct eth_drv_sc *sc, + struct eth_drv_sg *sg_list, int sg_len, int total_len, + unsigned long key) { + + greth_info *gi = (greth_info *)sc->driver_private; + struct bd_info *bdi = (struct bd_info *)&(gi->bdi); + + cyg_uint32 status, addr; + int len, i; + cyg_uint8 *to_addr; + + db_printf("greth_send(): tx_next: %d\n", bdi->tx_next); + + if (bdi->tx_free == 0) { + diag_printf("greth_send called but no free descriptors!\n"); + return; + } + /* Fill in a Tx key */ + bdi->tx_keys[bdi->tx_next] = key; + + if (total_len > GRETH_TX_BUF_SIZE) { + diag_printf("greth: tx frame too long!.\n"); + return; + } + + LOAD(bdi->tx_ring[bdi->tx_next].addr, addr); + to_addr = (cyg_uint8 *) addr; + + for (i = 0; i < sg_len; i++) { + len = sg_list[i].len; + memcpy(to_addr, (void*)sg_list[i].buf, len); + to_addr += len; + } + +#if DEBUG_TX_PACKETS + diag_printf("TX\n"); + greth_print_packet((unsigned long)addr, total_len); +#endif + + SAVE(bdi->tx_ring[bdi->tx_next].stat, GRETH_BD_IE | (total_len & GRETH_BD_LEN) | ((bdi->tx_next == GRETH_TXBD_NUM_MASK) ? GRETH_BD_WR : 0) ); + + REGORIN(bdi->tx_ring[bdi->tx_next].stat, GRETH_BD_EN); /* set enable */ + REGORIN(gi->regs->control, GRETH_TXEN); /* enable transmitter */ + + bdi->tx_next = (bdi->tx_next + 1) & GRETH_TXBD_NUM_MASK; + bdi->tx_free--; + + return; +} + +static void greth_recv( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len ) { + greth_info *gi = (greth_info *)sc->driver_private; + struct bd_info *bdi = (struct bd_info *) &(gi->bdi); + + cyg_uint8 *from_addr; + cyg_uint32 from, status, i; + int pkt_len; + + db_printf ("greth_recv() - rx_cur: %d\n", bdi->rx_cur); + + LOAD(bdi->rx_ring[bdi->rx_cur].stat, status); + pkt_len = status & GRETH_BD_LEN; + + LOAD(bdi->rx_ring[bdi->rx_cur].addr, from); + from_addr = (cyg_uint8 *) from; + +#if DEBUG_RX_PACKETS + greth_print_packet((unsigned long)from, pkt_len); +#endif + + for ( i = 0; i < sg_len; i++ ) { + cyg_uint8 *to_addr; + int len; + to_addr = (cyg_uint8 *)(sg_list[i].buf); + len = sg_list[i].len; + + if (to_addr == 0 || len <= 0) + return; // out of mbufs + + if ( len > pkt_len ) + len = pkt_len; + + memcpy( to_addr, (void *)from_addr, len ); + from_addr += len; + pkt_len -= len; + + } + + if (pkt_len > 0) { + diag_printf("GRETH(%d): Receive sg_list to small.\n", gi->idx); + } +} + +static void greth_poll(struct eth_drv_sc *sc) { + greth_info *gi = (greth_info *)sc->driver_private; + + eth_isr(gi->irq, (cyg_addrword_t) sc); + greth_deliver(sc); +} + +static int greth_int_vector(struct eth_drv_sc *sc) { + greth_info *gi = (greth_info *)sc->driver_private; + return gi->irq; +} + +static int greth_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length) { + + switch ( key ) { +#ifdef ETH_DRV_SET_MAC_ADDRESS + case ETH_DRV_SET_MAC_ADDRESS: + if ( 6 != data_length ) + return -2; + return eth_set_mac_address( sc, data ); +#endif +#ifdef ETH_DRV_GET_MAC_ADDRESS + case ETH_DRV_GET_MAC_ADDRESS: + return eth_get_mac_address( sc, data ); +#endif + +#ifdef ETH_DRV_SET_MC_LIST + case ETH_DRV_SET_MC_LIST: + /* Get rid of warnings about no multicast support .. doesn't do anything. + */ + return 0; +#endif + + default: + break; + } + return -1; +} + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/cdl/opencores_ethermac_drivers.cdl ecos-rep/packages/devs/eth/opencores/ethermac/current/cdl/opencores_ethermac_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/cdl/opencores_ethermac_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/opencores/ethermac/current/cdl/opencores_ethermac_drivers.cdl 2005-12-14 15:05:45.000000000 +0100 @@ -0,0 +1,149 @@ +# ==================================================================== +# +# opencores_ethermac_eth_drivers.cdl +# +# Ethernet drivers - support for Opencores ethermac controllers +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## Copyright (C) 2004 Andrew Lunn +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Gaisler Research, (Konrad Eisele) +# Contributors: +# Date: 2005-01-22 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC { + display "Opencores ethermac driver" + description "Ethernet driver for Opencores ethermac driver." + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + + active_if CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_REQUIRED + + include_dir . + include_files ; # none _exported_ whatsoever + compile -library=libextras.a if_oeth.c + + include_files include/oeth_info.h + + define_proc { + puts $::cdl_header "#include "; + puts $::cdl_header "#include CYGDAT_DEVS_ETH_OPENCORES_ETHERMAC_CFG"; + } + + cdl_option CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT { + display "Number of supported interfaces." + calculated { CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_REQUIRED } + flavor data + description " + This option selects the number of ethernet interfaces to + be supported by the driver." + } + + cdl_interface CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_STATIC_ESA { + display "ESA is statically configured" + description " + If this is nonzero, then the ESA (MAC address) is statically + configured in the platform-specific package which instantiates + this driver with all its details. + + Note that use of this option is deprecated in favor of a + CYGSEM_DEVS_ETH_..._SET_ESA option in the platform specific + driver." + } + + cdl_option CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_TxNUM { + display "Number of output buffers" + flavor data + legal_values 2 to 64 + default_value 4 + description " + This option specifies the number of output buffer packets + to be used for the opencores ethernet device in multiples of 2." + } + + cdl_option CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_RxNUM { + display "Number of input buffers" + flavor data + legal_values 2 to 64 + default_value 4 + description " + This option specifies the number of input buffer packets + to be used for the opencores ethernet device in multiples of 2." + } + + cdl_component CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_OPTIONS { + display "Opencores ethermac driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the opencores ethermac driver package. + These flags are used in addition + to the set of global flags." + } + } + + cdl_component CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_FLUSH { + display "Cache flushing" + flavor bool + default_value 1 + description "Flush cache before copying packets from/to the + ethermac dma transfer buffers. If you have cache snooping enabled + you can disable this option." + + } + + cdl_component CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_ETH100 { + display "Initialize MII to 100mbit" + flavor bool + default_value 1 + description "Issue a MII sequence that enables a 100mbit link " + + } + +} diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/include/oeth_info.h ecos-rep/packages/devs/eth/opencores/ethermac/current/include/oeth_info.h --- ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/include/oeth_info.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/opencores/ethermac/current/include/oeth_info.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,324 @@ +#ifndef CYGONCE_DEVS_ETH_OPENCORES_ETHERMAC_INFO_H +#define CYGONCE_DEVS_ETH_OPENCORES_ETHERMAC_INFO_H +/*========================================================================== +// +// oeth_info.h +// +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: +// Date: 2004-01-20 +// Description: +// +//####DESCRIPTIONEND#### +*/ + +#include + + +/* Ethernet configuration registers */ +typedef struct _oeth_regs { + cyg_uint32 moder; /* Mode Register */ + cyg_uint32 int_src; /* Interrupt Source Register */ + cyg_uint32 int_mask; /* Interrupt Mask Register */ + cyg_uint32 ipgt; /* Back to Bak Inter Packet Gap Register */ + cyg_uint32 ipgr1; /* Non Back to Back Inter Packet Gap Register 1 */ + cyg_uint32 ipgr2; /* Non Back to Back Inter Packet Gap Register 2 */ + cyg_uint32 packet_len; /* Packet Length Register (min. and max.) */ + cyg_uint32 collconf; /* Collision and Retry Configuration Register */ + cyg_uint32 tx_bd_num; /* Transmit Buffer Descriptor Number Register */ + cyg_uint32 ctrlmoder; /* Control Module Mode Register */ + cyg_uint32 miimoder; /* MII Mode Register */ + cyg_uint32 miicommand; /* MII Command Register */ + cyg_uint32 miiaddress; /* MII Address Register */ + cyg_uint32 miitx_data; /* MII Transmit Data Register */ + cyg_uint32 miirx_data; /* MII Receive Data Register */ + cyg_uint32 miistatus; /* MII Status Register */ + cyg_uint32 mac_addr0; /* MAC Individual Address Register 0 */ + cyg_uint32 mac_addr1; /* MAC Individual Address Register 1 */ + cyg_uint32 hash_addr0; /* Hash Register 0 */ + cyg_uint32 hash_addr1; /* Hash Register 1 */ +} oeth_regs; + +/* Ethernet buffer descriptor */ +typedef struct _oeth_bd { + cyg_uint32 len_status; + cyg_uint32 addr; /* Buffer address */ +} oeth_bd; + +#define OETH_REG_BASE(b) (b) +#define OETH_BD_BASE(b) ((b) + 0x400) +#define OETH_TOTAL_BD 128 +#define OETH_MAXBUF_LEN 0x600 + +/* Tx BD */ +#define OETH_TX_BD_READY 0x8000 /* Tx BD Ready */ +#define OETH_TX_BD_IRQ 0x4000 /* Tx BD IRQ Enable */ +#define OETH_TX_BD_WRAP 0x2000 /* Tx BD Wrap (last BD) */ +#define OETH_TX_BD_PAD 0x1000 /* Tx BD Pad Enable */ +#define OETH_TX_BD_CRC 0x0800 /* Tx BD CRC Enable */ + +#define OETH_TX_BD_UNDERRUN 0x0100 /* Tx BD Underrun Status */ +#define OETH_TX_BD_RETRY 0x00F0 /* Tx BD Retry Status */ +#define OETH_TX_BD_RETLIM 0x0008 /* Tx BD Retransmission Limit Status */ +#define OETH_TX_BD_LATECOL 0x0004 /* Tx BD Late Collision Status */ +#define OETH_TX_BD_DEFER 0x0002 /* Tx BD Defer Status */ +#define OETH_TX_BD_CARRIER 0x0001 /* Tx BD Carrier Sense Lost Status */ +#define OETH_TX_BD_STATS (OETH_TX_BD_UNDERRUN | \ + OETH_TX_BD_RETRY | \ + OETH_TX_BD_RETLIM | \ + OETH_TX_BD_LATECOL | \ + OETH_TX_BD_DEFER | \ + OETH_TX_BD_CARRIER) + +/* Rx BD */ +#define OETH_RX_BD_EMPTY 0x8000 /* Rx BD Empty */ +#define OETH_RX_BD_IRQ 0x4000 /* Rx BD IRQ Enable */ +#define OETH_RX_BD_WRAP 0x2000 /* Rx BD Wrap (last BD) */ + +#define OETH_RX_BD_MISS 0x0080 /* Rx BD Miss Status */ +#define OETH_RX_BD_OVERRUN 0x0040 /* Rx BD Overrun Status */ +#define OETH_RX_BD_INVSIMB 0x0020 /* Rx BD Invalid Symbol Status */ +#define OETH_RX_BD_DRIBBLE 0x0010 /* Rx BD Dribble Nibble Status */ +#define OETH_RX_BD_TOOLONG 0x0008 /* Rx BD Too Long Status */ +#define OETH_RX_BD_SHORT 0x0004 /* Rx BD Too Short Frame Status */ +#define OETH_RX_BD_CRCERR 0x0002 /* Rx BD CRC Error Status */ +#define OETH_RX_BD_LATECOL 0x0001 /* Rx BD Late Collision Status */ +#define OETH_RX_BD_STATS (OETH_RX_BD_MISS | \ + OETH_RX_BD_OVERRUN | \ + OETH_RX_BD_INVSIMB | \ + OETH_RX_BD_DRIBBLE | \ + OETH_RX_BD_TOOLONG | \ + OETH_RX_BD_SHORT | \ + OETH_RX_BD_CRCERR | \ + OETH_RX_BD_LATECOL) + +/* MODER Register */ +#define OETH_MODER_RXEN 0x00000001 /* Receive Enable */ +#define OETH_MODER_TXEN 0x00000002 /* Transmit Enable */ +#define OETH_MODER_NOPRE 0x00000004 /* No Preamble */ +#define OETH_MODER_BRO 0x00000008 /* Reject Broadcast */ +#define OETH_MODER_IAM 0x00000010 /* Use Individual Hash */ +#define OETH_MODER_PRO 0x00000020 /* Promiscuous (receive all) */ +#define OETH_MODER_IFG 0x00000040 /* Min. IFG not required */ +#define OETH_MODER_LOOPBCK 0x00000080 /* Loop Back */ +#define OETH_MODER_NOBCKOF 0x00000100 /* No Backoff */ +#define OETH_MODER_EXDFREN 0x00000200 /* Excess Defer */ +#define OETH_MODER_FULLD 0x00000400 /* Full Duplex */ +#define OETH_MODER_RST 0x00000800 /* Reset MAC */ +#define OETH_MODER_DLYCRCEN 0x00001000 /* Delayed CRC Enable */ +#define OETH_MODER_CRCEN 0x00002000 /* CRC Enable */ +#define OETH_MODER_HUGEN 0x00004000 /* Huge Enable */ +#define OETH_MODER_PAD 0x00008000 /* Pad Enable */ +#define OETH_MODER_RECSMALL 0x00010000 /* Receive Small */ + +/* Interrupt Source Register */ +#define OETH_INT_TXB 0x00000001 /* Transmit Buffer IRQ */ +#define OETH_INT_TXE 0x00000002 /* Transmit Error IRQ */ +#define OETH_INT_RXF 0x00000004 /* Receive Frame IRQ */ +#define OETH_INT_RXE 0x00000008 /* Receive Error IRQ */ +#define OETH_INT_BUSY 0x00000010 /* Busy IRQ */ +#define OETH_INT_TXC 0x00000020 /* Transmit Control Frame IRQ */ +#define OETH_INT_RXC 0x00000040 /* Received Control Frame IRQ */ + +/* Interrupt Mask Register */ +#define OETH_INT_MASK_TXB 0x00000001 /* Transmit Buffer IRQ Mask */ +#define OETH_INT_MASK_TXE 0x00000002 /* Transmit Error IRQ Mask */ +#define OETH_INT_MASK_RXF 0x00000004 /* Receive Frame IRQ Mask */ +#define OETH_INT_MASK_RXE 0x00000008 /* Receive Error IRQ Mask */ +#define OETH_INT_MASK_BUSY 0x00000010 /* Busy IRQ Mask */ +#define OETH_INT_MASK_TXC 0x00000020 /* Transmit Control Frame IRQ Mask */ +#define OETH_INT_MASK_RXC 0x00000040 /* Received Control Frame IRQ Mask */ + +/* Control Module Mode Register */ +#define OETH_CTRLMODER_PASSALL 0x00000001 /* Pass Control Frames */ +#define OETH_CTRLMODER_RXFLOW 0x00000002 /* Receive Control Flow Enable */ +#define OETH_CTRLMODER_TXFLOW 0x00000004 /* Transmit Control Flow Enable */ + +/* MII Mode Register */ +#define OETH_MIIMODER_CLKDIV 0x000000FF /* Clock Divider */ +#define OETH_MIIMODER_NOPRE 0x00000100 /* No Preamble */ +#define OETH_MIIMODER_RST 0x00000200 /* MIIM Reset */ + +/* MII Command Register */ +#define OETH_MIICOMMAND_SCANSTAT 0x00000001 /* Scan Status */ +#define OETH_MIICOMMAND_RSTAT 0x00000002 /* Read Status */ +#define OETH_MIICOMMAND_WCTRLDATA 0x00000004 /* Write Control Data */ + +/* MII Address Register */ +#define OETH_MIIADDRESS_FIAD 0x0000001F /* PHY Address */ +#define OETH_MIIADDRESS_RGAD 0x00001F00 /* RGAD Address */ + +/* MII Status Register */ +#define OETH_MIISTATUS_LINKFAIL 0x00000001 /* Link Fail */ +#define OETH_MIISTATUS_BUSY 0x00000002 /* MII Busy */ +#define OETH_MIISTATUS_NVALID 0x00000004 /* Data in MII Status Register is invalid */ + +/* Buffer number (must be 2^n) */ +#define OETH_RXBD_NUM CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_RxNUM +#define OETH_TXBD_NUM CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_TxNUM +#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) +#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) + +/* Buffer size (if not XXBUF_PREALLOC */ +#define OETH_MAX_FRAME_SIZE ((1518 + 7) & ~7) + +/* Buffer size */ +#define OETH_RX_BUFF_SIZE OETH_MAX_FRAME_SIZE +#define OETH_TX_BUFF_SIZE OETH_MAX_FRAME_SIZE + +struct net_device_stats +{ + unsigned long rx_packets; /* total packets received */ + unsigned long tx_packets; /* total packets transmitted */ + unsigned long rx_bytes; /* total bytes received */ + unsigned long tx_bytes; /* total bytes transmitted */ + unsigned long rx_errors; /* bad packets received */ + unsigned long tx_errors; /* packet transmit problems */ + unsigned long rx_dropped; /* no space in linux buffers */ + unsigned long tx_dropped; /* no space available in linux */ + unsigned long multicast; /* multicast packets received */ + unsigned long collisions; + + /* detailed rx_errors: */ + unsigned long rx_length_errors; + unsigned long rx_over_errors; /* receiver ring buff overflow */ + unsigned long rx_crc_errors; /* recved pkt with crc error */ + unsigned long rx_frame_errors; /* recv'd frame alignment error */ + unsigned long rx_fifo_errors; /* recv'r fifo overrun */ + unsigned long rx_missed_errors; /* receiver missed packet */ + + /* detailed tx_errors */ + unsigned long tx_aborted_errors; + unsigned long tx_carrier_errors; + unsigned long tx_fifo_errors; + unsigned long tx_heartbeat_errors; + unsigned long tx_window_errors; + + /* for cslip etc */ + unsigned long rx_compressed; + unsigned long tx_compressed; +}; + +/* The buffer descriptors track the ring buffers. */ +struct oeth_private { + + cyg_uint32 tx_next; /* Next buffer to be sent */ + cyg_uint32 tx_last; /* Next buffer to be checked if packet sent */ + cyg_uint32 tx_full; /* Buffer ring fuul indicator */ + cyg_uint32 rx_cur; /* Next buffer to be checked if packet received */ + + oeth_regs *regs; /* Address of controller registers. */ + oeth_bd *rx_bd_base; /* Address of Rx BDs. */ + oeth_bd *tx_bd_base; /* Address of Tx BDs. */ + cyg_uint32 irq; + + cyg_uint32 tx_keys[OETH_TXBD_NUM]; /* remember tx keys */ + + + struct net_device_stats stats; +}; + +// ------------------------------------------------------------------------ +// +// STATISTICAL COUNTER STRUCTURE +// +// ------------------------------------------------------------------------ +#ifdef KEEP_STATISTICS + +typedef struct { + cyg_uint32 interrupts; + cyg_uint32 rx_count; + cyg_uint32 rx_deliver; + cyg_uint32 rx_resource; + cyg_uint32 rx_restart; + cyg_uint32 tx_count; + cyg_uint32 tx_complete; + cyg_uint32 tx_dropped; +} STATISTICS; + +extern STATISTICS statistics[CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT]; + +#endif // KEEP_STATISTICS + +// ------------------------------------------------------------------------ +// +// DEVICES AND PACKET QUEUES +// +// ------------------------------------------------------------------------ +// The system seems to work OK with as few as 8 of RX and TX descriptors. +// It limps very painfully with only 4. +// Performance is better with more than 8. +// But the size of non-cached (so useless for anything else) +// memory window is 1Mb, so we might as well use it all. +// +// 128 for these uses the whole 1Mb, near enough. + +typedef struct _oeth_info { + struct oeth_private cep; + + cyg_uint8 found:1; // was hardware discovered? + cyg_uint8 mac_addr_ok:1; // can we bring up? + cyg_uint8 active:1; // has this if been brung up? + + cyg_uint8 multicast_all:1; + cyg_uint8 promisc:1; + + + cyg_uint8 dev_addr[6]; + struct eth_drv_sc *sc; + cyg_uint32 idx; + + // Interrupt handling stuff + cyg_vector_t vector; // interrupt vector + cyg_handle_t interrupt_handle; // handle for int.handler + cyg_interrupt interrupt_object; + +#ifdef KEEP_STATISTICS + void *p_statistics; // pointer to statistical counters +#endif + +} oeth_info; + + + +#endif + +/* EOF oeth_info.h */ + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/src/if_oeth.c ecos-rep/packages/devs/eth/opencores/ethermac/current/src/if_oeth.c --- ecos-cvs-2005-09-06/packages/devs/eth/opencores/ethermac/current/src/if_oeth.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/opencores/ethermac/current/src/if_oeth.c 2005-12-14 15:05:45.000000000 +0100 @@ -0,0 +1,944 @@ +//========================================================================== +// +// dev/if_oeth.c +// +// Ethernet device driver for Opencores ethermac +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2003 Nick Garnett +// Copyright (C) 2004 Andrew Lunn +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Konrad Eisele) +// Contributors: +// Date: 2005-01-22 +// Purpose: +// Description: +// Notes: +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include +#ifdef CYGPKG_IO_ETH_DRIVERS +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CYGPKG_NET +#include +#include +#include /* Needed for struct ifnet */ +#endif + +#ifdef CYGPKG_KERNEL +#include +#endif + +#if CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT > 1 +#error Only 1 ethermac at a time supported yet +#endif + +//#define DEBUG_OPENETH + +#ifdef DEBUG_OPENETH +#define DEBUG_RX_PACKETS 0 +#define DEBUG_TX_PACKETS 0 +#define os_printf diag_printf +#define db_printf diag_printf +#else +#define DEBUG_RX_PACKETS 0 +#define DEBUG_TX_PACKETS 0 +#define os_printf(fmt,...) +#define db_printf(fmt,...) +#endif + +#define MACADDR0 macaddr[0] +#define MACADDR1 macaddr[1] +#define MACADDR2 macaddr[2] +#define MACADDR3 macaddr[3] +#define MACADDR4 macaddr[4] +#define MACADDR5 macaddr[5] + +/* The transmitter timeout */ +#define TX_TIMEOUT (2*HZ) + +#define ETH_ALEN 6 /* Octets in one ethernet addr */ +#define ETH_HLEN 14 /* Total octets in header. */ +#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ + +#include +#include CYGDAT_DEVS_ETH_OPENCORES_ETHERMAC_INL + +cyg_uint8 macaddr[6] = CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_ETH0_ESA; + + +#define OETH_REGLOAD(a,v) HAL_READ_UINT32(&(a),v); +#define OETH_REGSAVE(a,v) HAL_WRITE_UINT32(&(a),v); +#define OETH_REGORIN(a,v) \ + { cyg_uint32 va; \ + OETH_REGLOAD(a,va); \ + va |= v; \ + OETH_REGSAVE(a,va); \ + } +#define OETH_REGANDIN(a,v) \ + { cyg_uint32 va; \ + OETH_REGLOAD(a,va); \ + va &= v; \ + OETH_REGSAVE(a,va); \ + } + +static void openeth_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ); +static void openeth_stop( struct eth_drv_sc *sc ); +static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data); +static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); +static void oeth_tx(struct eth_drv_sc *sc); +static void openeth_rxready(struct eth_drv_sc *sc); +static void oeth_txdone(struct eth_drv_sc *sc); + + + + +static cyg_uint8 rxbuff[OETH_RXBD_NUM*OETH_RX_BUFF_SIZE]; +static cyg_uint8 txbuff[OETH_TXBD_NUM*OETH_TX_BUFF_SIZE]; + +bool openeth_init(struct cyg_netdevtab_entry *ndp) { + CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_INITFN(ndp); +} + +#if !defined(DEBUG_RX_PACKETS) && !defined(DEBUG_TX_PACKETS) +static void oeth_print_packet(unsigned long add, int len) +{ + int i; + diag_printf("ipacket: add = %x len = %d\n", (unsigned int)add, len); + for(i = 0; i < len; i++) { + if(!(i % 16)) + diag_printf("\n"); + diag_printf(" %.2x", *(((unsigned char *)add) + i)); + } + diag_printf("\n"); + diag_printf("\n"); +} +#endif + +static void openeth_start( struct eth_drv_sc *sc, unsigned char *enaddr, int flags ) { + + oeth_info *oi = (oeth_info *)sc->driver_private; + oeth_regs *regs = oi->cep.regs; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + int i; + + if ( oi->active ) + openeth_stop( sc ); + + db_printf("openeth_start: irq %d\n",cep ->irq); + + /* Install our interrupt handler. */ + cyg_drv_interrupt_create(cep ->irq, + 0, // Priority - unused + (CYG_ADDRWORD)sc, // Data item passed to ISR & DSR + eth_isr, // ISR + eth_dsr, // DSR + &oi->interrupt_handle, // handle to intr obj + &oi->interrupt_object ); // space for int obj + cyg_drv_interrupt_attach(oi->interrupt_handle); + cyg_drv_interrupt_acknowledge(cep->irq); + cyg_drv_interrupt_unmask(cep ->irq); + + // Enable device + oi->active = 1; + + /* Initialize transmit pointers. */ + cep->rx_cur = 0; + cep->tx_next = 0; + cep->tx_last = 0; + cep->tx_full = 0; + + bdp = cep->rx_bd_base; + for (i = 0; i < OETH_RXBD_NUM; i++) { + OETH_REGORIN(bdp->len_status , OETH_RX_BD_EMPTY); //bdp->len_status |= OETH_RX_BD_EMPTY; + bdp++; + } + + /* Enable receiver and transmiter */ + OETH_REGORIN(regs->moder , OETH_MODER_RXEN | OETH_MODER_TXEN); //regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; +} + + +static void openeth_stop( struct eth_drv_sc *sc ) { + + oeth_info *oi = (oeth_info *)sc->driver_private; + oeth_regs *regs = oi->cep.regs; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + int i; + + db_printf("openeth_stop\n"); + + /* Free interrupt hadler */ + cyg_interrupt_delete(oi->interrupt_handle); + + /* Disable receiver and transmitesr */ + OETH_REGANDIN(regs->moder , ~(OETH_MODER_RXEN | OETH_MODER_TXEN)); //regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); + + bdp = cep->rx_bd_base; + for (i = 0; i < OETH_RXBD_NUM; i++) { + OETH_REGANDIN(bdp->len_status , ~(OETH_RX_BD_STATS | OETH_RX_BD_EMPTY)); //bdp->len_status &= ~(OETH_RX_BD_STATS | OETH_RX_BD_EMPTY); + bdp++; + } + + bdp = cep->tx_bd_base; + for (i = 0; i < OETH_TXBD_NUM; i++) { + OETH_REGANDIN(bdp->len_status, ~(OETH_TX_BD_STATS | OETH_TX_BD_READY)); //bdp->len_status &= ~(OETH_TX_BD_STATS | OETH_TX_BD_READY); + bdp++; + } + + memset(cep->tx_keys,0,sizeof(cep->tx_keys)); + + oi->active = 0; // stop people tormenting it + +} + +static cyg_uint32 eth_isr(cyg_vector_t vector, cyg_addrword_t data) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + oeth_regs *regs = oi->cep.regs; + cyg_uint32 int_events, calldsr = 0; + //cyg_uint32 cpu = sparc_leon3_get_cpuid(); + + /* Get the interrupt events that caused us to be here. */ + OETH_REGLOAD(regs->int_src, int_events); //int_events = cep->regs->int_src; + OETH_REGSAVE(regs->int_src, int_events); //cep->regs->int_src = int_events; + + /* + diag_printf("isr %x(cpu:%d,irq:%d)\n",int_events,cpu,cep->irq); + diag_printf("mask(0):0x%x\n",LEON3_IrqCtrl_Regs->mask[0]); + diag_printf("mask(1):0x%x\n",LEON3_IrqCtrl_Regs->mask[1]); + diag_printf("ipend:0x%x\n",LEON3_IrqCtrl_Regs->ipend); + diag_printf("force:0x%x\n",LEON3_IrqCtrl_Regs->iforce); + */ + + /* Handle receive event . */ + if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { + calldsr = CYG_ISR_CALL_DSR; + } + + /* Handle transmit event in its own function. */ + if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { + calldsr = CYG_ISR_CALL_DSR; + } + + /* Check for receive busy, i.e. packets coming but no place to put them. */ + if (int_events & OETH_INT_BUSY) { + if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) { + db_printf("openeth: RX buffer dumped!.\n"); /* All transmit buffers are full. Bail out.*/ + } + calldsr = CYG_ISR_CALL_DSR; + } + + cyg_drv_interrupt_acknowledge(cep ->irq); + if (calldsr) { + //cyg_drv_interrupt_mask(cep ->irq); + } + + if (!calldsr) { + //diag_printf("dsr not called \n"); + } + + return (CYG_ISR_HANDLED|calldsr); // schedule DSR +} + +static void eth_dsr(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data) { + struct eth_drv_sc *sc = (struct eth_drv_sc *)data; + //diag_printf("eth_dsr\n"); +#ifdef CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_FLUSH + HAL_DCACHE_INVALIDATE_ALL(); +#endif + eth_drv_dsr( vector, count, (cyg_addrword_t)sc ); +} + +static void openeth_deliver(struct eth_drv_sc *sc) { + //oeth_info *oi = (oeth_info *)sc->driver_private; + //struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + //cyg_drv_dsr_lock(); + //cyg_drv_isr_lock(); + openeth_rxready(sc); + oeth_txdone(sc); + //cyg_drv_isr_unlock(); + //cyg_drv_dsr_unlock(); + //cyg_drv_interrupt_unmask(cep->irq); + +} + +static void oeth_tx(struct eth_drv_sc *sc) +{ + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + cyg_uint32 status; + + //db_printf ("oeth_tx()\n"); + + for (;; cep->tx_last = (cep->tx_last + 1) & OETH_TXBD_NUM_MASK) { + + bdp = cep->tx_bd_base + cep->tx_last; + OETH_REGLOAD(bdp->len_status,status); + + if ((status & OETH_TX_BD_READY) || ((cep->tx_last == cep->tx_next) && !cep->tx_full)) + break; + + /* Check status for errors */ + if (status & OETH_TX_BD_LATECOL) + cep->stats.tx_window_errors++; + if (status & OETH_TX_BD_RETLIM) + cep->stats.tx_aborted_errors++; + if (status & OETH_TX_BD_UNDERRUN) + cep->stats.tx_fifo_errors++; + if (status & OETH_TX_BD_CARRIER) + cep->stats.tx_carrier_errors++; + if (status & (OETH_TX_BD_LATECOL | OETH_TX_BD_RETLIM | OETH_TX_BD_UNDERRUN)) + cep->stats.tx_errors++; + + cep->stats.tx_packets++; + cep->stats.collisions += (status >> 4) & 0x000f; + + if (cep->tx_full) + cep->tx_full = 0; + } +} + +//pass tx-keys up the stack when packets are transmitted, called from can_send() and deliver() +static void oeth_txdone(struct eth_drv_sc *sc) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + cyg_uint32 status, i; + + oeth_tx(sc); + + //db_printf ("oeth_txdone()\n"); + for (i = 0; i < OETH_TXBD_NUM; i++) { + bdp = cep->tx_bd_base + i; + OETH_REGLOAD(bdp->len_status,status); + if (cep->tx_keys[i] && !(status & OETH_TX_BD_READY)) { + unsigned long k = cep->tx_keys[i]; + cep->tx_keys[i] = 0; + //diag_printf ("%i: key 0x%x, ready: %d\n",k ,status & OETH_TX_BD_READY ? 1 : 0); + //db_printf("tx=%d\n",i); + (sc->funs->eth_drv->tx_done)( sc, k, 0 ); + } + } +} + +#ifdef ETH_DRV_GET_MAC_ADDRESS +static int eth_get_mac_address(struct eth_drv_sc *sc, char *addr) +{ + oeth_info *oi = (oeth_info *)sc->driver_private; + oeth_regs *regs = oi->cep.regs; + cyg_uint32 m0,m1; + db_printf("eth_get_mac_address\n"); + OETH_REGLOAD(regs->mac_addr1 ,m1); + OETH_REGLOAD(regs->mac_addr0 ,m0); + addr[0] = (m1 >> 8) & 0xff; + addr[1] = (m1 >> 0) & 0xff; + addr[2] = (m0 >>24) & 0xff; + addr[3] = (m0 >>16) & 0xff; + addr[4] = (m0 >> 8) & 0xff; + addr[5] = (m0 >> 0) & 0xff; + return 0; +} +#endif + +#ifdef ETH_DRV_SET_MAC_ADDRESS +static int eth_set_mac_address(struct eth_drv_sc *sc, cyg_uint8 *addr, int eeprom) +{ + oeth_info *oi = (oeth_info *)sc->driver_private; + oeth_regs *regs = oi->cep.regs; + db_printf("eth_set_mac_address\n"); + oi->dev_addr[0] = addr[0]; + oi->dev_addr[1] = addr[1]; + oi->dev_addr[2] = addr[2]; + oi->dev_addr[3] = addr[3]; + oi->dev_addr[4] = addr[4]; + oi->dev_addr[5] = addr[5]; + OETH_REGSAVE(regs->mac_addr1 , + addr[0] << 8 | + addr[1]); + OETH_REGSAVE(regs->mac_addr0 , + addr[2] << 24 | + addr[3] << 16 | + addr[4] << 8 | + addr[5]); + return 1; +} +#endif + +static int calc_crc(unsigned char *mac_addr) +{ + int result = 0; + return (result & 0x3f); +} + +static void oeth_set_multicast_list(struct eth_drv_sc *sc, struct eth_drv_mc_list *mcl) +{ + + + oeth_info *oi = (oeth_info *)sc->driver_private; + /* Get pointer of controller registers. */ + volatile oeth_regs *regs = oi->cep.regs; + int i; + + //db_printf("oeth_set_multicast_list: promisc: %d mc_all: %d (mc_list: %d)\n",oi->promisc,oi->multicast_all,mcl->len); + + + if (oi->promisc) { + /* Log any net taps. */ + db_printf("Promiscuous mode enabled.\n"); + OETH_REGORIN(regs->moder , OETH_MODER_PRO); //regs->moder |= OETH_MODER_PRO; + } else { + OETH_REGANDIN(regs->moder , ~OETH_MODER_PRO); //regs->moder &= ~OETH_MODER_PRO; + if (oi->multicast_all) { + /* Catch all multicast addresses, so set the filter to all 1's. */ + OETH_REGSAVE(regs->hash_addr0 , 0xffffffff); //regs->hash_addr0 = 0xffffffff + OETH_REGSAVE(regs->hash_addr1 , 0xffffffff); //regs->hash_addr0 = 0xffffffff + } + else if (mcl && mcl->len) { + + //db_printf("oeth_set_multicast_list: multicastlist \n"); + OETH_REGORIN(regs->moder , OETH_MODER_IAM); //regs->moder |= OETH_MODER_IAM; + + /* Clear filter and add the addresses in the list. */ + OETH_REGSAVE(regs->hash_addr0 , 0x00000000); //regs->hash_addr0 = 0x00000000 + OETH_REGSAVE(regs->hash_addr0 , 0x00000000); //regs->hash_addr0 = 0x00000000 + + for (i = 0; i < mcl->len; i++) { + + int hash_b; + + /* Only support group multicast for now. */ + if (!(mcl->addrs[i][0] & 1)) + continue; + + //db_printf("%x %x %x %x %x %x\n",mcl->addrs[i][0],mcl->addrs[i][1],mcl->addrs[i][2], + //mcl->addrs[i][3],mcl->addrs[i][4],mcl->addrs[i][5] + //); + + hash_b = calc_crc(mcl->addrs[i]); + if(hash_b >= 32) { + OETH_REGORIN(regs->hash_addr1 , 1 << (hash_b - 32)); //regs->hash_addr1 |= 1 << (hash_b - 32); + } else { + OETH_REGORIN(regs->hash_addr0 , 1 << hash_b); //regs->hash_addr0 |= 1 << hash_b; + } + } + } + } +} + +static int openeth_ioctl(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length) { + oeth_info *oi = (oeth_info *)sc->driver_private; + + //db_printf("openeth_ioctl\n"); + //db_printf( "openeth_ioctl: device eth%d at %x; key is 0x%x, data at %x[%d]\n", + //oi->idx, oi, key, data, data_length ); + + switch ( key ) { +#ifdef ETH_DRV_SET_MC_LIST + case ETH_DRV_SET_MC_LIST: { + struct eth_drv_mc_list *mcl = (struct eth_drv_mc_list *)data; + oi->multicast_all = 0; + oeth_set_multicast_list(sc, mcl); + return 0; + } +#endif // ETH_DRV_SET_MC_LIST +#ifdef ETH_DRV_SET_MC_ALL + case ETH_DRV_SET_MC_ALL: + oi->multicast_all = 1; + oeth_set_multicast_list(sc, 0); + return 0; +#endif // ETH_DRV_SET_MC_ALL + +#ifdef ETH_DRV_SET_MAC_ADDRESS + case ETH_DRV_SET_MAC_ADDRESS: + if ( 6 != data_length ) + return -2; + return eth_set_mac_address( sc, data, 1 /* do write eeprom */ ); +#endif +#ifdef ETH_DRV_GET_MAC_ADDRESS + case ETH_DRV_GET_MAC_ADDRESS: + return eth_get_mac_address( sc, data ); +#endif + default: + break; + } + return -1; +} + + +static int openeth_can_send(struct eth_drv_sc *sc) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + oeth_txdone(sc); + //db_printf("openeth: openeth_can_send: %d\n",!cep->tx_full); + + + + return !cep->tx_full; +} + +static void openeth_send(struct eth_drv_sc *sc, + struct eth_drv_sg *sg_list, int sg_len, int total_len, + unsigned long key) { + + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + cyg_uint32 status, addr; + int len, i, ec = 0; + cyg_uint8 *to_addr; + + /* Fill in a Tx ring entry */ + bdp = cep->tx_bd_base + cep->tx_next; + cep->tx_keys[cep->tx_next] = key; + + OETH_REGLOAD(bdp->len_status,status); + + if (OETH_TX_BD_READY & status) { + diag_printf("openeth: tx counter mismatch!.\n"); + return; + } + if (cep->tx_full) { + diag_printf("openeth: tx queue full!.\n"); /* All transmit buffers are full. Bail out.*/ + return; + } + + /* Clear all of the status flags. */ + OETH_REGANDIN(bdp->len_status , ~OETH_TX_BD_STATS); //bdp->len_status &= ~OETH_TX_BD_STATS; + + /* If the frame is short, tell CPM to pad it. */ + if (total_len <= ETH_ZLEN) { + OETH_REGORIN(bdp->len_status , OETH_TX_BD_PAD); //bdp->len_status |= OETH_TX_BD_PAD; + } else { + OETH_REGANDIN(bdp->len_status , ~OETH_TX_BD_PAD); //bdp->len_status &= ~OETH_TX_BD_PAD; + } + + /* Copy data in preallocated buffer */ + if (total_len > OETH_TX_BUFF_SIZE) { + diag_printf("openeth: tx frame too long!.\n"); + return ; + } + + OETH_REGLOAD(bdp->addr, addr); + to_addr = (cyg_uint8 *)addr; + for (i = 0; i < sg_len; i++) { + len = sg_list[i].len; + memcpy(to_addr, (void*)sg_list[i].buf, len); + to_addr += len; ec += len; + } + + if (ec != total_len) { + diag_printf("openeth: packet length wrong!.\n"); + } + +#if DEBUG_TX_PACKETS + db_printf("TX\n"); + oeth_print_packet((unsigned long)addr, total_len); +#endif + + + OETH_REGLOAD(bdp->len_status,status); + OETH_REGSAVE(bdp->len_status , (status & 0x0000ffff) | (total_len << 16)); //bdp->len_status = (bdp->len_status & 0x0000ffff) | (skb->len << 16); + + cep->tx_next = (cep->tx_next + 1) & OETH_TXBD_NUM_MASK; + + if (cep->tx_next == cep->tx_last) + cep->tx_full = 1; + + /* Send it on its way. Tell controller its ready, interrupt when done, and to put the CRC on the end. */ + OETH_REGORIN(bdp->len_status , (OETH_TX_BD_READY | OETH_TX_BD_IRQ | OETH_TX_BD_CRC)); //bdp->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_IRQ | OETH_TX_BD_CRC); + return; +} + +static void openeth_recv( struct eth_drv_sc *sc, struct eth_drv_sg *sg_list, int sg_len ) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + cyg_uint8 *from_addr; + cyg_uint32 from, status, i; + int pkt_len, total_len; + + //diag_printf ("-recv(%d)",cep->rx_cur); + + bdp = cep->rx_bd_base + cep->rx_cur; + OETH_REGLOAD(bdp->len_status,status); + OETH_REGLOAD(bdp->addr,from); + from_addr = (cyg_uint8 *) from; + + /* Process the incoming frame. */ + total_len = pkt_len = status >> 16; //pkt_len = bdp->len_status >> 16; + + for ( i = 0; i < sg_len; i++ ) { + cyg_uint8 *to_addr; + int len; + to_addr = (cyg_uint8 *)(sg_list[i].buf); + len = sg_list[i].len; + + if (to_addr == 0 || len <= 0) + return; // out of mbufs + + if ( len > pkt_len ) + len = pkt_len; + + //diag_printf("RX %x <- %x (%x)\n",to_addr,from_addr,len); + memcpy( to_addr, (void *)from_addr, len ); + from_addr += len; + pkt_len -= len; + + /* { + + int i; + for(i = 0; i < len; i++) { + if(!(i % 16)) + diag_printf("\n"); + diag_printf(" %.2x", *(((unsigned char *)to_addr) + i)); + } + diag_printf("\n"); + }*/ + + + } + + if (pkt_len > 0) { + diag_printf("oeth: sglist: not all data received\n"); + } + + +#if DEBUG_RX_PACKETS + diag_printf("RX\n"); + oeth_print_packet((unsigned long)from, total_len); +#endif + + cep->stats.rx_packets++; + +} + +static void openeth_rxready(struct eth_drv_sc *sc) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + volatile oeth_bd *bdp; + cyg_uint32 status; + + int pkt_len; + int bad = 0,i = 0; + + //db_printf ("openeth_rxready\n"); + + /* First, grab all of the stats for the incoming packet. + These get messed up if we get called due to a busy condition. */ + for (;;cep->rx_cur = (cep->rx_cur + 1) & OETH_RXBD_NUM_MASK) { + //for (cep->rx_cur = 0;cep->rx_cur < OETH_TXBD_NUM;cep->rx_cur++) { + + bdp = cep->rx_bd_base + cep->rx_cur; + OETH_REGLOAD(bdp->len_status,status); + + if (status & OETH_RX_BD_EMPTY) { + for (i = (cep->rx_cur + 1) & OETH_RXBD_NUM_MASK;i != cep->rx_cur;i = (i + 1) & OETH_RXBD_NUM_MASK) { + bdp = cep->rx_bd_base + i; + OETH_REGLOAD(bdp->len_status,status); + if (!(status & OETH_RX_BD_EMPTY)) { + diag_printf("rx not synced: %d\n",i); + } + } + break; + } + + + /* Check status for errors. */ + if (status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { //if (bdp->len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { + diag_printf ("openeth: length error\n"); + cep->stats.rx_length_errors++; + bad = 1; + } + if (status & OETH_RX_BD_DRIBBLE) { //if (bdp->len_status & OETH_RX_BD_DRIBBLE) { + diag_printf ("openeth: dribble error\n"); + cep->stats.rx_frame_errors++; + bad = 1; + } + if (status & OETH_RX_BD_CRCERR) { //if (bdp->len_status & OETH_RX_BD_CRCERR) { + diag_printf ("openeth: crc error\n"); + cep->stats.rx_crc_errors++; + bad = 1; + } + if (status & OETH_RX_BD_OVERRUN) { //if (bdp->len_status & OETH_RX_BD_OVERRUN) { + diag_printf ("openeth: overrun error\n"); + cep->stats.rx_crc_errors++; + bad = 1; + } + if (status & OETH_RX_BD_MISS) { //if (bdp->len_status & OETH_RX_BD_MISS) { + diag_printf ("openeth: miss error\n"); + } + if (status & OETH_RX_BD_LATECOL) { //if (bdp->len_status & OETH_RX_BD_LATECOL) { + diag_printf ("openeth: latecol error\n"); + cep->stats.rx_frame_errors++; + bad = 1; + } + + if (bad) { + OETH_REGANDIN(bdp->len_status , ~OETH_RX_BD_STATS); //bdp->len_status &= ~OETH_RX_BD_STATS; + OETH_REGORIN(bdp->len_status , OETH_RX_BD_EMPTY); //bdp->len_status |= OETH_RX_BD_EMPTY; + continue; + } + + /* Process the incoming frame. */ + pkt_len = status >> 16; //pkt_len = bdp->len_status >> 16; + + //call up stack + //diag_printf("rx packet %d\n",pkt_len); + + //diag_printf("rx=%d",cep->rx_cur); + (sc->funs->eth_drv->recv)( sc, pkt_len ); + //diag_printf("\n"); + + + OETH_REGANDIN(bdp->len_status , ~OETH_RX_BD_STATS); //bdp->len_status &= ~OETH_RX_BD_STATS; + OETH_REGORIN(bdp->len_status , OETH_RX_BD_EMPTY); //bdp->len_status |= OETH_RX_BD_EMPTY; + } +} + + +static void openeth_poll(struct eth_drv_sc *sc) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + eth_isr(cep->irq,(cyg_addrword_t)sc); + openeth_deliver(sc); +} + +static int openeth_int_vector(struct eth_drv_sc *sc) { + oeth_info *oi = (oeth_info *)sc->driver_private; + struct oeth_private *cep = (struct oeth_private *)&(oi->cep); + return cep->irq; +} + +static int read_mii(int addr, volatile oeth_regs *regs) +{ + int tmp; + + do { + OETH_REGLOAD(regs->miistatus, tmp); + } while (tmp & OETH_MIISTATUS_BUSY); + + OETH_REGSAVE(regs->miiaddress, addr << 8); + OETH_REGSAVE(regs->miicommand, OETH_MIICOMMAND_RSTAT); + + do { + OETH_REGLOAD(regs->miistatus, tmp); + } while (tmp & OETH_MIISTATUS_BUSY); + + OETH_REGLOAD(regs->miistatus, tmp); + if (!(tmp & OETH_MIISTATUS_NVALID)) { + OETH_REGLOAD(regs->miirx_data, tmp); + return tmp; + } + else { + diag_printf("open_eth: failed to read mii\n"); + return (0); + } +} + +static void write_mii(int addr, int data, volatile oeth_regs *regs) +{ + int tmp; + do { + OETH_REGLOAD(regs->miistatus, tmp); + } while (tmp & OETH_MIISTATUS_BUSY); + + OETH_REGSAVE(regs->miiaddress, addr << 8); + OETH_REGSAVE(regs->miitx_data, data); + OETH_REGSAVE(regs->miicommand, OETH_MIICOMMAND_WCTRLDATA); + + do { + OETH_REGLOAD(regs->miistatus, tmp); + } while (tmp & OETH_MIISTATUS_BUSY); + +} + +void openeth_device_init(struct eth_drv_sc *sc, cyg_uint32 idx, cyg_uint32 base, cyg_uint32 irq) { + + struct oeth_private *cep = &openeth_priv_array[idx]->cep; + volatile oeth_regs *regs; + volatile oeth_bd *tx_bd, *rx_bd; + int i, mii_cr; + unsigned long rxmem_addr = (unsigned long)&(rxbuff); + unsigned long txmem_addr = (unsigned long)&(txbuff); + + openeth_priv_array[idx]->found = 1; + /* Set default ethernet station address. */ + openeth_priv_array[idx]->dev_addr[0] = MACADDR0; + openeth_priv_array[idx]->dev_addr[1] = MACADDR1; + openeth_priv_array[idx]->dev_addr[2] = MACADDR2; + openeth_priv_array[idx]->dev_addr[3] = MACADDR3; + openeth_priv_array[idx]->dev_addr[4] = MACADDR4; + openeth_priv_array[idx]->dev_addr[5] = MACADDR5; + openeth_priv_array[idx]->sc = sc; + openeth_priv_array[idx]->idx = idx; + + /* Get pointer ethernet controller configuration registers. */ + cep->regs = (oeth_regs *)(OETH_REG_BASE(base)); + regs = (oeth_regs *)(OETH_REG_BASE(base)); + cep->irq = irq; + + /* Reset the controller. */ + //OETH_REGSAVE(regs->moder , OETH_MODER_RST); //regs->moder = OETH_MODER_RST; /* Reset ON */ + //OETH_REGANDIN(regs->moder , ~OETH_MODER_RST); //regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ + OETH_REGSAVE(regs->ctrlmoder, 0); + OETH_REGSAVE(regs->moder, OETH_MODER_RST); /* Reset ON */ + OETH_REGSAVE(regs->moder, 0); + + + /* Setting TXBD base to OETH_TXBD_NUM. */ + OETH_REGSAVE(regs->tx_bd_num , OETH_TXBD_NUM); //regs->tx_bd_num = OETH_TXBD_NUM; + + /* Initialize TXBD pointer*/ + cep->tx_bd_base = (oeth_bd *)OETH_BD_BASE(base); + tx_bd = (volatile oeth_bd *)OETH_BD_BASE(base); + + /* Initialize RXBD pointer*/ + cep->rx_bd_base = ((oeth_bd *)OETH_BD_BASE(base)) + OETH_TXBD_NUM; + rx_bd = ((volatile oeth_bd *)OETH_BD_BASE(base)) + OETH_TXBD_NUM; + + /* Initialize transmit pointers. */ + cep->rx_cur = 0; + cep->tx_next = 0; + cep->tx_last = 0; + cep->tx_full = 0; + + /* Set min/max packet length */ + OETH_REGSAVE(regs->packet_len , 0x00400600); //regs->packet_len = 0x00400600; + + /* Set IPGT register to recomended value */ + OETH_REGSAVE(regs->ipgt , 0x00000012); //regs->ipgt = 0x00000012; + + /* Set IPGR1 register to recomended value */ + OETH_REGSAVE(regs->ipgr1 , 0x0000000c); //regs->ipgr1 = 0x0000000c; + + /* Set IPGR2 register to recomended value */ + OETH_REGSAVE(regs->ipgr2 , 0x00000012); //regs->ipgr2 = 0x00000012; + + /* Set COLLCONF register to recomended value */ + OETH_REGSAVE(regs->collconf , 0x000f003f); //regs->collconf = 0x000f003f; + + /* Set control module mode */ +#if 0 + OETH_REGSAVE(regs->ctrlmoder , OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW); //regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; +#else + OETH_REGSAVE(regs->ctrlmoder , 0);//regs->ctrlmoder = 0; +#endif + + /* Set PHY to show Tx status, Rx status and Link status */ + /*regs->miiaddress = 20<<8; + regs->miitx_data = 0x1422; + regs->miicommand = OETH_MIICOMMAND_WCTRLDATA;*/ + + // switch to 10 mbit ethernet +#ifdef CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_ETH100 + OETH_REGSAVE(regs->miiaddress , 0); //regs->miiaddress = 0; + OETH_REGSAVE(regs->miitx_data , 0x2000); //regs->miitx_data = 0x2000; + OETH_REGSAVE(regs->miicommand , OETH_MIICOMMAND_WCTRLDATA); //regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; +#else + OETH_REGSAVE(regs->miiaddress , 0); //regs->miiaddress = 0; + OETH_REGSAVE(regs->miitx_data , 0); //regs->miitx_data = 0; + OETH_REGSAVE(regs->miicommand , OETH_MIICOMMAND_WCTRLDATA); //regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; +#endif + + /* Initialize TXBDs. */ + for(i = 0; i < OETH_TXBD_NUM; i++) { + OETH_REGSAVE(tx_bd[i].len_status , OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); //tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; + OETH_REGSAVE(tx_bd[i].addr , txmem_addr); //tx_bd[i].addr = __pa(mem_addr); + txmem_addr += OETH_TX_BUFF_SIZE; + } + OETH_REGORIN(tx_bd[OETH_TXBD_NUM - 1].len_status , OETH_TX_BD_WRAP); //tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; + + for(i = 0; i < OETH_RXBD_NUM; i++) { + OETH_REGSAVE(rx_bd[i].len_status , OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ); //rx_bd[k].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; + OETH_REGSAVE(rx_bd[i].addr , rxmem_addr); //rx_bd[k].addr = __pa(mem_addr); + rxmem_addr += OETH_RX_BUFF_SIZE; + } + OETH_REGORIN(rx_bd[OETH_RXBD_NUM - 1].len_status , OETH_RX_BD_WRAP); //rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; + + + OETH_REGSAVE(regs->mac_addr1 , MACADDR0 << 8 | MACADDR1); //regs->mac_addr1 = MACADDR0 << 8 | MACADDR1; + OETH_REGSAVE(regs->mac_addr0 , MACADDR2 << 24 | MACADDR3 << 16 | MACADDR4 << 8 | MACADDR5); //regs->mac_addr0 = MACADDR2 << 24 | MACADDR3 << 16 | MACADDR4 << 8 | MACADDR5; + + /* Clear all pending interrupts */ + OETH_REGSAVE(regs->int_src , 0xffffffff); //regs->int_src = 0xffffffff; + + /* Promisc, IFG, CRCEn */ + OETH_REGORIN(regs->moder , OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN); //regs->moder |= OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN; + OETH_REGANDIN(regs->moder , ~OETH_MODER_FULLD); // ensure half duplex + + /* Enable interrupt sources. */ + OETH_REGSAVE(regs->int_mask , + OETH_INT_MASK_TXB | /* regs->int_mask = OETH_INT_MASK_TXB | OETH_INT_MASK_TXE | OETH_INT_MASK_RXF | OETH_INT_MASK_RXE | OETH_INT_MASK_BUSY | OETH_INT_MASK_TXC | OETH_INT_MASK_RXC; */ + OETH_INT_MASK_TXE | + OETH_INT_MASK_RXF | + OETH_INT_MASK_RXE | + OETH_INT_MASK_BUSY | + OETH_INT_MASK_TXC | + OETH_INT_MASK_RXC); + + db_printf("%x: Open Ethernet Core Version 1.0 at [0x%x] irq %d\n", idx,(unsigned int)(cep->regs),(unsigned int)(cep->irq)); + + // Initialize upper level driver + (sc->funs->eth_drv->init)(sc, openeth_priv_array[idx]->dev_addr); + + +} + +// EOF if_oeth.c diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c ecos-rep/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c --- ecos-cvs-2005-09-06/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 2005-06-29 22:06:05.000000000 +0200 +++ ecos-rep/packages/devs/eth/smsc/lan91cxx/current/src/if_lan91cxx.c 2005-09-06 16:59:27.000000000 +0200 @@ -302,6 +302,18 @@ cyg_drv_interrupt_unmask(cpd->interrupt); #endif // !CYGPKG_IO_ETH_DRIVERS_STAND_ALONE + // Reset chip + put_reg(sc, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST); + put_reg(sc, LAN91CXX_RCR, 0); +#ifdef LAN91CXX_IS_LAN91C111 + HAL_DELAY_US(100000); + put_reg(sc, LAN91CXX_CONFIG, 0x9000); + put_reg(sc, LAN91CXX_RCR, 0); + put_reg(sc, LAN91CXX_TCR, 0); + put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_reset_mmu); +#endif + + val = get_reg(sc, LAN91CXX_EPH_STATUS); // probe chip by reading the signature in BS register val = get_banksel(sc); #if DEBUG & 9 @@ -332,8 +344,8 @@ (*cpd->config_enaddr)(cpd); // Reset chip - put_reg(sc, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST); - put_reg(sc, LAN91CXX_RCR, 0); + //put_reg(sc, LAN91CXX_RCR, LAN91CXX_RCR_SOFT_RST); + //put_reg(sc, LAN91CXX_RCR, 0); val = get_reg(sc, LAN91CXX_EPH_STATUS); #ifndef LAN91CXX_IS_LAN91C111 @@ -454,6 +466,7 @@ { cyg_uint16 intr; #ifdef LAN91CXX_IS_LAN91C111 + cyg_uint16 phy_ctl; int delay; #endif #ifdef CYGPKG_NET @@ -462,12 +475,16 @@ DEBUG_FUNCTION(); #ifdef LAN91CXX_IS_LAN91C111 + HAL_DELAY_US(100000); // 91C111 Errata. Internal PHY comes up disabled. Must enable here. - lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, LAN91CXX_PHY_CTRL_RST); + phy_ctl = lan91cxx_read_phy(sc, 0, LAN91CXX_PHY_CTRL); + phy_ctl &= ~LAN91CXX_PHY_CTRL_MII_DIS; + lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, phy_ctl); + /* lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, LAN91CXX_PHY_CTRL_RST); HAL_DELAY_US(500000); lan91cxx_write_phy(sc, 0, LAN91CXX_PHY_CTRL, LAN91CXX_PHY_CTRL_ANEG_EN | LAN91CXX_PHY_CTRL_SPEED); - + */ // Start auto-negotiation put_reg(sc, LAN91CXX_RPCR, LAN91CXX_RPCR_LEDA_RX | LAN91CXX_RPCR_LEDB_LINK | LAN91CXX_RPCR_ANEG); @@ -1122,13 +1139,8 @@ #endif int i; short mlen=0, plen; - cyg_uint16 *data=NULL; - unsigned char *cp, cval, odd_even = 0; -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - cyg_uint32 val; -#else - cyg_uint16 val; -#endif + rxd_t *data=NULL, val; + unsigned char *cp, cval; DEBUG_FUNCTION(); @@ -1139,7 +1151,7 @@ val = get_data(sc); // packet length (minus header/footer) -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT +#ifdef LAN91CXX_32BIT_RX val = CYG_LE32_TO_CPU(val); plen = (val >> 16) - 6; #else @@ -1152,67 +1164,64 @@ plen++; for (i = 0; i < sg_len; i++) { - data = (cyg_uint16 *)sg_list[i].buf; +#ifdef LAN91CXX_32BIT_RX + if (mlen == 2) { + val = get_data(sc); + *((unsigned short *) data) = (val >> 16) & 0xffff; + plen -= 2; + data = (rxd_t *)sg_list[i].buf; + mlen = sg_list[i].len; + if ((data) && (mlen > 1)) { + *((unsigned short *) data)++ = (val & 0xffff); + plen -= 2; + mlen -= 2; + } + } else { + data = (rxd_t *)sg_list[i].buf; mlen = sg_list[i].len; + } +#else + data = (rxd_t *)sg_list[i].buf; + mlen = sg_list[i].len; +#endif CYG_ASSERT(0 == (mlen & (sizeof(*data) - 1)) || (i == (sg_len-1)), "odd length"); -#if DEBUG & 1 - db_printf("%s : mlen 0x%04x, plen 0x%04x\n", __FUNCTION__, mlen, plen); -#endif + //db1_printf("%s : mlen %x, plen %x\n", __FUNCTION__, mlen, plen); + if (data) { while (mlen >= sizeof(*data)) { -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - if (!(odd_even)) { // because of the 32bit to 16bit conversion, read only every 2nd word -#endif +#ifdef LAN91CXX_32BIT_RX val = get_data(sc); -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - odd_even = 1; - } - else { - val >>= 16; - odd_even = 0; - } + *((unsigned short *) data)++ = (val >> 16) & 0xffff; + *((unsigned short *) data)++ = (val & 0xffff); +#else + *data++ = get_data(sc); #endif - *data++ = val; mlen -= sizeof(*data); plen -= sizeof(*data); } } else { // must actively discard ie. read it from the chip anyway. while (mlen >= sizeof(*data)) { -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - if (!(odd_even)) { -#endif - val = get_data(sc); -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - odd_even = 1; - } - else { - val >>= 16; - odd_even = 0; - } -#endif + (void)get_data(sc); mlen -= sizeof(*data); plen -= sizeof(*data); } } } - if (!(odd_even)) { // read the control word only if we not already have it because of a 32bit access val = get_data(sc); // Read control word (and potential data) unconditionally -#ifdef CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT - val = CYG_LE32_TO_CPU(val); +#ifdef LAN91CXX_32BIT_RX if (plen & 2) { - if (data) - *(cyg_uint16 *)data = val & 0xffff; - cp = (unsigned char *)data + 2; - val >>= 16; - mlen -= 2; + if (data) { + *((unsigned short *) data)++ = (val >> 16) & 0xffff; + val <<= 16; + } } + if (plen & 1) + *(unsigned char *)data = val >> 24; #else val = CYG_LE16_TO_CPU(val); -#endif - } cp = (unsigned char *)data; CYG_ASSERT(val & LAN91CXX_CONTROLBYTE_RX, @@ -1222,21 +1231,23 @@ if (data && (1 == mlen) && LAN91CXX_CONTROLBYTE_IS_ODD(cpd,val) ) { cval = val & 0x00ff; // last byte contains data *cp = cval; - } +#endif val = get_reg(sc, LAN91CXX_FIFO_PORTS); + #if DEBUG & 4 if ( 0x8000 & val ) // Then the Rx FIFO is empty - db_printf("#####Rx packet NOT freed, stat is 0x%04x (expected 0x%04x)\n", - val, cpd->rxpacket); + db_printf("#####Rx packet NOT freed, stat is %x (expected %x)\n", + val, sc->rxpacket); else - db_printf("#####Rx packet freed 0x%04x (expected 0x%04x)\n", - 0xff & (val >> 8), cpd->rxpacket ); + db_printf("#####Rx packet freed %x (expected %x)\n", + 0xff & (val >> 8), sc->rxpacket ); #endif - CYG_ASSERT( (0xff & (val >> 8)) == cpd->rxpacket, "Unexpected rx packet" ); + CYG_ASSERT( (0xff & (val >> 8)) == sc->rxpacket, "Unexpected rx packet" ); // Free packet put_reg(sc, LAN91CXX_MMU_COMMAND, LAN91CXX_MMU_remrel_rx_frame); + } static void @@ -1421,6 +1432,7 @@ // Turn off all MII Interface bits mii_reg &= ~(LAN91CXX_MGMT_MDOE | LAN91CXX_MGMT_MCLK | LAN91CXX_MGMT_MDI | LAN91CXX_MGMT_MDO); + HAL_DELAY_US(50); // Clock all cycles for (i = 0; i < sizeof(bits); ++i) { diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h ecos-rep/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h --- ecos-cvs-2005-09-06/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 2005-06-29 22:06:05.000000000 +0200 +++ ecos-rep/packages/devs/eth/smsc/lan91cxx/current/src/smsc_lan91cxx.h 2005-09-05 16:06:32.000000000 +0200 @@ -413,7 +413,7 @@ #endif #if DEBUG & 2 - diag_printf("read data 0x%x\n", val); + diag_printf("read data 0x%08x\n", val); #endif return val; } diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/cdl/leon3_greth_drivers.cdl ecos-rep/packages/devs/eth/sparc/greth/leon3/current/cdl/leon3_greth_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/cdl/leon3_greth_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/greth/leon3/current/cdl/leon3_greth_drivers.cdl 2005-12-14 16:10:16.000000000 +0100 @@ -0,0 +1,125 @@ +# ==================================================================== +# +# leon_greth_drivers.cdl +# +# Ethernet drivers - support for Gaisler Research's ethernet mac +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Gaisler Research, (Kristoffer Carlsson ) +# Contributors: +# Date: 2005-11-29 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3 { + + display "LEON3 GRETH ethernet driver" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_SPARC_LEON3 + + requires CYGPKG_DEVS_ETH_GRETH + description "Ethernet driver for GRETH in a LEON3 system." + + include_dir cyg/io + compile if_sparc_greth.c + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_GRETH_INL " + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_GRETH_CFG " + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + + cdl_interface CYGINT_DEVS_ETH_GRETH_REQUIRED { + display "GRETH driver required" + } + + cdl_component CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0 { + display "Ethernet port 0 driver" + flavor bool + default_value 1 + + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGINT_DEVS_ETH_GRETH_REQUIRED + + cdl_option CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0_NAME { + display "Device name for the ethernet driver" + flavor data + default_value {"\"eth0\""} + description " + This option sets the name of the ethernet device for the + ethernet port." + } + + cdl_option CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0_ESA { + display "The ethernet station address (MAC)" + flavor data + default_value {"{0x00, 0x00, 0x5e, 0x00, 0x00, 0x13}"} + description "A static ethernet station address. + Caution: Booting two systems with the same MAC on the same + network, will cause severe conflicts." + } + } + + cdl_component CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_OPTIONS { + display "Gaisler Research's GRETH driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the driver package. + These flags are used in addition + to the set of global flags." + } + } + +} diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/include/devs_eth_sparc_greth_leon3.inl ecos-rep/packages/devs/eth/sparc/greth/leon3/current/include/devs_eth_sparc_greth_leon3.inl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/include/devs_eth_sparc_greth_leon3.inl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/greth/leon3/current/include/devs_eth_sparc_greth_leon3.inl 2005-12-14 16:10:16.000000000 +0100 @@ -0,0 +1,91 @@ +//========================================================================== +// +// devs/eth/sparc/greth/leon3/../include/devs_eth_sparc_greth_leon3.inl +// +// GRETH I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Kristoffer Carlsson ) +// Contributors: +// Date: 2005-11-29 +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +bool greth_leon3_init(struct cyg_netdevtab_entry *ndp); +#define CYGPKG_DEVS_ETH_GRETH_ETH0_ESA CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0_ESA +#define CYGPKG_DEVS_ETH_GRETH_INITFN greth_leon3_init + +#ifdef CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0 + +//structs and tables for eth0 + +static greth_info greth_priv; + +ETH_DRV_SC(greth_sc, + &greth_priv, // Driver specific data + CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0_NAME, // Name for device + greth_start, + greth_stop, + greth_control, + greth_can_send, + greth_send, + greth_recv, + greth_deliver, + greth_poll, + greth_int_vector +); + +NETDEVTAB_ENTRY(greth_netdev, + "greth_" CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0_NAME, + greth_init, + &greth_sc); +#endif + +#if CYGNUM_DEVS_ETH_GRETH_DEV_COUNT > 1 +#error Only 1 ethermac at a time supported yet (eth0) +#endif + +greth_info *greth_priv_array[CYGNUM_DEVS_ETH_GRETH_DEV_COUNT] = { +#ifdef CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3_ETH0 + &greth_priv +#endif +}; + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/src/if_sparc_greth.c ecos-rep/packages/devs/eth/sparc/greth/leon3/current/src/if_sparc_greth.c --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/greth/leon3/current/src/if_sparc_greth.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/greth/leon3/current/src/if_sparc_greth.c 2005-12-14 16:10:16.000000000 +0100 @@ -0,0 +1,117 @@ +//========================================================================== +// +// devs/eth/sparc/greth/leon3/../src/if_sparc_greth.c +// +// Ethernet device driver for GRETH ethernet mac on Leon3 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Kristoffer Carlsson ) +// Contributors: +// Date: 2005-11-29 +// Purpose: +// Description: Driver for Gaisler Research's GRETH ethernet mac +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#ifdef CYGPKG_IO_ETH_DRIVERS +#include +#endif +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CYGPKG_NET +#include +#include +#include /* Needed for struct ifnet */ +#endif + +#include +#include +#include + +externC void greth_device_init(struct eth_drv_sc *sc, cyg_uint32 idx, cyg_uint32 base, cyg_uint32 irq); + +bool greth_leon3_init(struct cyg_netdevtab_entry *ndp) +{ + int i,j; + struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance); + +#if !defined(CYGPKG_DEVS_ETH_GRETH_FLUSH) + { + unsigned long cfg = sparc_leon3_get_dcachecfg(); + if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) { + sparc_leon3_enable_snooping(); + } else { + diag_printf("You have to enable snooping in the vhdl model to use the mac without CYGPKG_DEVS_ETH_GRETH_FLUSH, otherwise enable CYGPKG_DEVS_ETH_GRETH_FLUSH\n"); + } + } +#endif + + amba_apb_device adev[CYGNUM_DEVS_ETH_GRETH_DEV_COUNT]; + j = amba_get_free_apbslv_devices (VENDOR_GAISLER, GAISLER_ETHMAC, adev, CYGNUM_DEVS_ETH_GRETH_DEV_COUNT); + + for (i = 0; i < j; i++) { + greth_device_init(sc,i,adev[i].start, adev[i].irq); + } + return 1; +} diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/ChangeLog ecos-rep/packages/devs/eth/sparc/leon2/current/ChangeLog --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/ChangeLog 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon2/current/ChangeLog 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,41 @@ +2003-02-05 Patrick Doyle + * cdl/innovator_eth_drivers.cdl + * include/devs_eth_innovator.inl + * src/if_innovator.c: New package - support for Texas Instruments + Innovator board. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 2003 Delphi Communication Systems, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/cdl/leon2_eth_drivers.cdl ecos-rep/packages/devs/eth/sparc/leon2/current/cdl/leon2_eth_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/cdl/leon2_eth_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon2/current/cdl/leon2_eth_drivers.cdl 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,140 @@ +# ==================================================================== +# +# innovator_eth_drivers.cdl +# +# Ethernet drivers - support for LAN91CXX ethernet controller +# on the BSE Innovator/SA1110 board. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Jiri Gaisler +# Contributors: +# Date: 2004-07-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_SPARC_LEON { + + display "LEON2 SMC91C111 ethernet driver" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_SPARC_LEON + + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED + implements CYGINT_DEVS_ETH_SMSC_LAN91CXX_STATIC_ESA + + requires CYGPKG_DEVS_ETH_SMSC_LAN91CXX + description "Ethernet driver for LEON2 boards." + + include_dir cyg/io + compile if_leon2.c + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL " + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_CFG " + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + + cdl_interface CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED { + display "SMSC LAN91CXX driver required" + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON_NAME { + display "Device name for the ethernet driver" + flavor data + default_value {"\"eth0\""} + description " + This option sets the name of the ethernet device for the + ethernet port." + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON_ESA { + display "The ethernet station address (MAC)" + flavor data + default_value {"{0x12, 0x13, 0x14, 0x15, 0x16, 0x17}"} + description "A static ethernet station address. + Caution: Booting two systems with the same MAC on the same + network, will cause severe conflicts." + active_if !CYGSEM_DEVS_ETH_SPARC_LEON_REDBOOT_ESA + } + + cdl_option CYGNUM_DEVS_ETH_SPARC_LEON_IRQ_PIO { + display "LEON2 PIO port used for interrupt" + flavor booldata + legal_values 0 to 31 + default_value 4 + description "External interrupt from the 91CXX is routed to + LEON2 through one of the 32 PIO ports." + } + + cdl_option CYGNUM_DEVS_ETH_SPARC_LEON_IRQ { + display "LEON2 PIO interrupt number" + flavor booldata + legal_values 4 to 7 + default_value 4 + description "PIO ports can generate interrupt 4 - 7." + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON_ADDR { + display "Ethernet register's address" + flavor data + default_value {"0x20000000"} + description "Address to where the 91CXX control registers + are mapped." + } + + cdl_option CYGSEM_DEVS_ETH_SPARC_LEON_REDBOOT_ESA { + display "Use the RedBoot ESA (MAC address)" + default_value 0 + flavor bool + description " + Use the ESA that is stored as a RedBoot variable instead of + a static ESA." + } + +} + +# EOF innovator_eth_drivers.cdl diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/include/devs_eth_leon2.inl ecos-rep/packages/devs/eth/sparc/leon2/current/include/devs_eth_leon2.inl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/include/devs_eth_leon2.inl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon2/current/include/devs_eth_leon2.inl 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,123 @@ +//========================================================================== +// +// devs/eth/arm/innovator/..../include/devs_eth_innovator.inl +// +// Innovator ethernet I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jordi Colomer , Patrick Doyle +// Contributors: Patrick Doyle +// Date: 2001-06-18 +// Purpose: Innovator ethernet definitions +//####DESCRIPTIONEND#### +//========================================================================== + +#include +//#include +#include +//#include + +// #define CYGNUM_DEVS_ETH_SMSC_LAN91CXX_SHIFT_ADDR 2 +#define LAN91CXX_32BIT_RX +#define CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT +#define LAN91CXX_IS_LAN91C111 + +// MAC address is stored as a Redboot config option +#ifdef CYGPKG_REDBOOT +#include +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG +#include +#include + +RedBoot_config_option("Network hardware address [MAC]", + leon2_esa, + ALWAYS_ENABLED, true, + CONFIG_ESA, 0 + ); +#endif +#endif + +// ESA address fetch function +static void leon2_get_ESA(struct lan91cxx_priv_data *cpd) +{ + // Fetch hardware address from RedBoot config +#if defined(CYGSEM_DEVS_ETH_SPARC_LEON_REDBOOT_ESA) +#if defined(CYGPKG_REDBOOT) && \ + defined(CYGSEM_REDBOOT_FLASH_CONFIG) + flash_get_config("leon2_esa", cpd->enaddr, CONFIG_ESA); +#else +#error "No RedBoot flash configuration to store ESA" +#endif +#else + unsigned char static_esa[] = CYGDAT_DEVS_ETH_SPARC_LEON_ESA; + memcpy(cpd->enaddr, static_esa, 6); +#endif +} + +static lan91cxx_priv_data lan91cxx_eth0_priv_data = { + + config_enaddr : leon2_get_ESA, +#ifndef CYGSEM_DEVS_ETH_SPARC_LEON_REDBOOT_ESA + enaddr: CYGDAT_DEVS_ETH_SPARC_LEON_ESA, +#endif + base : (unsigned short *) CYGDAT_DEVS_ETH_SPARC_LEON_ADDR, + interrupt : CYGNUM_DEVS_ETH_SPARC_LEON_IRQ +}; + +ETH_DRV_SC(lan91cxx_sc, + &lan91cxx_eth0_priv_data, // Driver specific data + CYGDAT_DEVS_ETH_SPARC_LEON_NAME, // Name for device + lan91cxx_start, + lan91cxx_stop, + lan91cxx_control, + lan91cxx_can_send, + lan91cxx_send, + lan91cxx_recv, + lan91cxx_deliver, + lan91cxx_poll, + lan91cxx_int_vector +); + +NETDEVTAB_ENTRY(lan91cxx_netdev, + "lan91cxx_" CYGDAT_DEVS_ETH_SPARC_LEON_NAME, + smsc_lan91cxx_init, + &lan91cxx_sc); + +//EOF devs_eth_innovator.inl + + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/src/if_leon2.c ecos-rep/packages/devs/eth/sparc/leon2/current/src/if_leon2.c --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon2/current/src/if_leon2.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon2/current/src/if_leon2.c 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,73 @@ +//========================================================================== +// +// devs/eth/arm/innovator/if_innovator.c +// +// Ethernet device driver for Innovator using SMSC LAN91C96 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jordi Colomer , Patrick Doyle +// Contributors: Patrick Doyle +// Date: 2001-07-01 +// Purpose: +// Description: hardware driver for Innovator/SMSC LAN91CXX ethernet +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +//#include +#include + +#if defined(CYGPKG_REDBOOT) +#include +#endif + +#include +#include diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/ChangeLog ecos-rep/packages/devs/eth/sparc/leon3/current/ChangeLog --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/ChangeLog 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon3/current/ChangeLog 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,41 @@ +2003-02-05 Patrick Doyle + * cdl/innovator_eth_drivers.cdl + * include/devs_eth_innovator.inl + * src/if_innovator.c: New package - support for Texas Instruments + Innovator board. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. +// Copyright (C) 2003 Delphi Communication Systems, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/cdl/leon3_eth_drivers.cdl ecos-rep/packages/devs/eth/sparc/leon3/current/cdl/leon3_eth_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/cdl/leon3_eth_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon3/current/cdl/leon3_eth_drivers.cdl 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,140 @@ +# ==================================================================== +# +# innovator_eth_drivers.cdl +# +# Ethernet drivers - support for LAN91CXX ethernet controller +# on Leon3. +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Jiri Gaisler +# Contributors: +# Date: 2004-07-28 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_SPARC_LEON3 { + + display "LEON3 SMC91C111 ethernet driver" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_SPARC_LEON3 + + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED + implements CYGINT_DEVS_ETH_SMSC_LAN91CXX_STATIC_ESA + + requires CYGPKG_DEVS_ETH_SMSC_LAN91CXX + description "Ethernet driver for LEON3 boards." + + include_dir cyg/io + compile if_leon3.c + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_INL " + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_SMSC_LAN91CXX_CFG " + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + + cdl_interface CYGINT_DEVS_ETH_SMSC_LAN91CXX_REQUIRED { + display "SMSC LAN91CXX driver required" + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON3_NAME { + display "Device name for the ethernet driver" + flavor data + default_value {"\"eth0\""} + description " + This option sets the name of the ethernet device for the + ethernet port." + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON3_ESA { + display "The ethernet station address (MAC)" + flavor data + default_value {"{0x12, 0x13, 0x14, 0x15, 0x16, 0x17}"} + description "A static ethernet station address. + Caution: Booting two systems with the same MAC on the same + network, will cause severe conflicts." + active_if !CYGSEM_DEVS_ETH_SPARC_LEON3_REDBOOT_ESA + } + + cdl_option CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO { + display "LEON3 PIO port used for interrupt" + flavor booldata + legal_values 0 to 31 + default_value 4 + description "External interrupt from the 91CXX is routed to + LEON3 through one of the 32 PIO ports." + } + + cdl_option CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ { + display "LEON3 PIO interrupt number" + flavor booldata + legal_values 4 to 7 + default_value 4 + description "PIO ports can generate interrupt 4 - 7." + } + + cdl_option CYGDAT_DEVS_ETH_SPARC_LEON3_ADDR { + display "Ethernet register's address" + flavor data + default_value {"0x20000000"} + description "Address to where the 91CXX control registers + are mapped." + } + + cdl_option CYGSEM_DEVS_ETH_SPARC_LEON3_REDBOOT_ESA { + display "Use the RedBoot ESA (MAC address)" + default_value 0 + flavor bool + description " + Use the ESA that is stored as a RedBoot variable instead of + a static ESA." + } + +} + +# EOF leon3_eth_driver.cdl diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/include/devs_eth_leon3.inl ecos-rep/packages/devs/eth/sparc/leon3/current/include/devs_eth_leon3.inl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/include/devs_eth_leon3.inl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon3/current/include/devs_eth_leon3.inl 2005-09-06 15:05:17.000000000 +0200 @@ -0,0 +1,142 @@ +//========================================================================== +// +// devs/eth/arm/innovator/..../include/devs_eth_innovator.inl +// +// Innovator ethernet I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jordi Colomer , Patrick Doyle +// Contributors: Patrick Doyle +// Date: 2001-06-18 +// Purpose: Innovator ethernet definitions +//####DESCRIPTIONEND#### +//========================================================================== + +#include +//#include +#include +//#include + +// #define CYGNUM_DEVS_ETH_SMSC_LAN91CXX_SHIFT_ADDR 2 +#define LAN91CXX_32BIT_RX +#define CYGSEM_DEVS_ETH_SMSC_LAN91CXX_USE_32BIT +#define LAN91CXX_IS_LAN91C111 + +// MAC address is stored as a Redboot config option +#ifdef CYGPKG_REDBOOT +#include +#ifdef CYGSEM_REDBOOT_FLASH_CONFIG +#include +#include + +RedBoot_config_option("Network hardware address [MAC]", + leon3_esa, + ALWAYS_ENABLED, true, + CONFIG_ESA, 0 + ); +#endif +#endif + +// ESA address fetch function +static void leon3_get_ESA(struct lan91cxx_priv_data *cpd) +{ + // Fetch hardware address from RedBoot config +#if defined(CYGSEM_DEVS_ETH_SPARC_LEON3_REDBOOT_ESA) +#if defined(CYGPKG_REDBOOT) && \ + defined(CYGSEM_REDBOOT_FLASH_CONFIG) + flash_get_config("leon3_esa", cpd->enaddr, CONFIG_ESA); +#else +#error "No RedBoot flash configuration to store ESA" +#endif +#else + unsigned char static_esa[] = CYGDAT_DEVS_ETH_SPARC_LEON3_ESA; + memcpy(cpd->enaddr, static_esa, 6); +#endif +} + +static lan91cxx_priv_data lan91cxx_eth0_priv_data = { + + config_enaddr : leon3_get_ESA, +#ifndef CYGSEM_DEVS_ETH_SPARC_LEON3_REDBOOT_ESA + enaddr: CYGDAT_DEVS_ETH_SPARC_LEON3_ESA, +#endif + base : (unsigned short *) CYGDAT_DEVS_ETH_SPARC_LEON3_ADDR, + interrupt : CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ +}; + +ETH_DRV_SC(lan91cxx_sc, + &lan91cxx_eth0_priv_data, // Driver specific data + CYGDAT_DEVS_ETH_SPARC_LEON3_NAME, // Name for device + lan91cxx_start, + lan91cxx_stop, + lan91cxx_control, + lan91cxx_can_send, + lan91cxx_send, + lan91cxx_recv, + lan91cxx_deliver, + lan91cxx_poll, + lan91cxx_int_vector +); + +NETDEVTAB_ENTRY(lan91cxx_netdev, + "lan91cxx_" CYGDAT_DEVS_ETH_SPARC_LEON3_NAME, + smsc_sparc_leon3_init, + &lan91cxx_sc); + +static bool +smsc_lan91cxx_init(struct cyg_netdevtab_entry *tab); + +bool smsc_sparc_leon3_init(struct cyg_netdevtab_entry *ndp) +{ + int irq_pio,irq_mctrl,addr_pio,addr_mctrl; + if (addr_pio = amba_find_apbslv_addr(VENDOR_GAISLER, GAISLER_PIOPORT, &irq_pio)) { + LEON3_IOPORT_Regs_Map *io = (LEON3_IOPORT_Regs_Map *) addr_pio; + if (addr_mctrl = amba_find_apbslv_addr(VENDOR_ESA, ESA_MCTRL, &irq_mctrl)) { + diag_printf("Activating Leon3 io port for smsc_lan91cxx (pio:%x mctrl:%x)\n",addr_pio,addr_mctrl); + *((volatile cyg_uint32 *) addr_mctrl) |= 0x10f80000; //mctrl ctrl 1 + io->irqmask |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->irqpol |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->irqedge |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->iodir &= ~(1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + return smsc_lan91cxx_init(ndp); + } + } + return 0; +} + +//EOF devs_eth_innovator.inl diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/src/if_leon3.c ecos-rep/packages/devs/eth/sparc/leon3/current/src/if_leon3.c --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/leon3/current/src/if_leon3.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/leon3/current/src/if_leon3.c 2005-09-06 15:05:17.000000000 +0200 @@ -0,0 +1,94 @@ +//========================================================================== +// +// devs/eth/arm/innovator/if_innovator.c +// +// Ethernet device driver for Innovator using SMSC LAN91C96 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Jordi Colomer , Patrick Doyle +// Contributors: Patrick Doyle +// Date: 2001-07-01 +// Purpose: +// Description: hardware driver for Innovator/SMSC LAN91CXX ethernet +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#include +#include + +#if defined(CYGPKG_REDBOOT) +#include +#endif + +#include +#include + +externC bool smsc_lan91cxx_init(struct cyg_netdevtab_entry *tab); + +/* + bool smsc_sparc_leon3_init(struct cyg_netdevtab_entry *ndp) +{ + int irq_pio,irq_mctrl,addr_pio,addr_mctrl; + if (addr_pio = amba_find_apbslv_addr(VENDOR_GAISLER, GAISLER_PIOPORT, &irq_pio)) { + LEON3_IOPORT_Regs_Map *io = (LEON3_IOPORT_Regs_Map *) addr_pio; + if (addr_mctrl = amba_find_apbslv_addr(VENDOR_ESA, ESA_MCTRL, &irq_mctrl)) { + diag_printf("Activating Leon3 io port for smsc_lan91cxx (pio:%x mctrl:%x)\n",addr_pio,addr_mctrl); + *((volatile cyg_uint32 *) addr_mctrl) |= 0x10f80000; //mctrl ctrl 1 + io->irqmask |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->irqpol |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->irqedge |= (1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + io->iodir &= ~(1 << CYGNUM_DEVS_ETH_SPARC_LEON3_IRQ_PIO); + return smsc_lan91cxx_init(ndp); + } + } + return 0; +}*/ diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/cdl/leon3_opencores_ethmac_drivers.cdl ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/cdl/leon3_opencores_ethmac_drivers.cdl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/cdl/leon3_opencores_ethmac_drivers.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/cdl/leon3_opencores_ethmac_drivers.cdl 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,127 @@ +# ==================================================================== +# +# leon_opencores_ethmac_drivers.cdl +# +# Ethernet drivers - support for Opencores ethermac controller +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): Gaisler Research, (Konrad Eisele) +# Contributors: +# Date: 2005-01-20 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3 { + + display "LEON3 opencores ethernet driver" + + parent CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_IO_ETH_DRIVERS + active_if CYGPKG_HAL_SPARC_LEON3 + + requires CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC + description "Ethernet driver for Opencores in a LEON3 system." + + include_dir cyg/io + compile if_opencores.c + + define_proc { + puts $::cdl_system_header "/***** ethernet driver proc output start *****/" + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_OPENCORES_ETHERMAC_INL " + puts $::cdl_system_header "#define CYGDAT_DEVS_ETH_OPENCORES_ETHERMAC_CFG " + puts $::cdl_system_header "/***** ethernet driver proc output end *****/" + } + + # Arguably this should do in the generic package + # but then there is a logic loop so you can never enable it. + + cdl_interface CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_REQUIRED { + display "opencores ethermac driver required" + } + + cdl_component CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0 { + display "Ethernet port 0 driver" + flavor bool + default_value 1 + + implements CYGHWR_NET_DRIVERS + implements CYGHWR_NET_DRIVER_ETH0 + implements CYGINT_DEVS_ETH_OPENCORES_ETHERMAC_REQUIRED + + cdl_option CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0_NAME { + display "Device name for the ethernet driver" + flavor data + default_value {"\"eth0\""} + description " + This option sets the name of the ethernet device for the + ethernet port." + } + + cdl_option CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0_ESA { + display "The ethernet station address (MAC)" + flavor data + default_value {"{0x00, 0x00, 0x5e, 0x00, 0x00, 0x12}"} + description "A static ethernet station address. + Caution: Booting two systems with the same MAC on the same + network, will cause severe conflicts." + } + } + + cdl_component CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_OPTIONS { + display "Opencores ethermac driver build options" + flavor none + no_define + + cdl_option CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "-D_KERNEL -D__ECOS" } + description " + This option modifies the set of compiler flags for + building the opencores ethermac driver package. + These flags are used in addition + to the set of global flags." + } + } + +} + +# EOF leon_opencores_ethmac_drivers.cdl diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/include/devs_eth_sparc_opencores_leon3.inl ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/include/devs_eth_sparc_opencores_leon3.inl --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/include/devs_eth_sparc_opencores_leon3.inl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/include/devs_eth_sparc_opencores_leon3.inl 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,93 @@ +//========================================================================== +// +// devs/eth/sparc/opencores/leon/../include/devs_eth_sparc_opencores_leon.inl +// +// Opencores ethermac I/O definitions. +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Konrad Eisele) +// Contributors: +// Date: 2000-11-22 +//####DESCRIPTIONEND#### +//========================================================================== + +#include +#include + +bool openeth_leon3_init(struct cyg_netdevtab_entry *ndp); +#define CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_ETH0_ESA CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0_ESA +#define CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_INITFN openeth_leon3_init + +#ifdef CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0 + +//structs and tables for eth0 +static oeth_info openeth_priv; +ETH_DRV_SC(oeth_sc, + &openeth_priv, // Driver specific data + CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0_NAME, // Name for device + openeth_start, + openeth_stop, + openeth_ioctl, + openeth_can_send, + openeth_send, + openeth_recv, + openeth_deliver, + openeth_poll, + openeth_int_vector +); + +NETDEVTAB_ENTRY(oeth_netdev, + "openeth_" CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0_NAME, + openeth_init, + &oeth_sc); +#endif + +#if CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT > 1 +#error Only 1 ethermac at a time supported yet (eth0) +#endif + +oeth_info *openeth_priv_array[CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT] = { +#ifdef CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3_ETH0 + &openeth_priv +#endif +}; + + +//EOF devs_eth_sparc_opencorec_leon.inl + + diff -Naurb ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/src/if_opencores.c ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/src/if_opencores.c --- ecos-cvs-2005-09-06/packages/devs/eth/sparc/opencores/leon3/current/src/if_opencores.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/devs/eth/sparc/opencores/leon3/current/src/if_opencores.c 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,116 @@ +//========================================================================== +// +// devs/eth/sparc/opencores/leon/../src/if_opencores.c +// +// Ethernet device driver for Opencore's ethermac on Leon2/3 +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Konrad Eisele) +// Contributors: +// Date: 2005-01-20 +// Purpose: +// Description: hardware driver for Opencores ethernet +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include +#ifdef CYGPKG_IO_ETH_DRIVERS +#include +#endif +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CYGPKG_NET +#include +#include +#include /* Needed for struct ifnet */ +#endif + +#include +#include +#include + +externC void openeth_device_init(struct eth_drv_sc *sc, cyg_uint32 idx, cyg_uint32 base, cyg_uint32 irq); + +bool openeth_leon3_init(struct cyg_netdevtab_entry *ndp) +{ + int i,j; + struct eth_drv_sc *sc = (struct eth_drv_sc *)(ndp->device_instance); + +#if !defined(CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_FLUSH) + { + unsigned long cfg = sparc_leon3_get_dcachecfg(); + if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) { + sparc_leon3_enable_snooping(); + } else { + diag_printf("You have to enable snooping in the vhdl model to use the ethermac without CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_FLUSH, otherwise enable CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC_FLUSH\n"); + } + } +#endif + + amba_ahb_device adev[CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT]; + j = amba_get_free_ahbslv_devices (VENDOR_GAISLER, GAISLER_ETHAHB, adev, CYGNUM_DEVS_ETH_OPENCORES_ETHERMAC_DEV_COUNT); + for (i = 0;i < j;i++) { + openeth_device_init(sc,i,adev[i].start[0],adev[i].irq); + } + return 1; +} diff -Naurb ecos-cvs-2005-09-06/packages/ecos.db ecos-rep/packages/ecos.db --- ecos-cvs-2005-09-06/packages/ecos.db 2005-08-25 15:40:35.000000000 +0200 +++ ecos-rep/packages/ecos.db 2005-12-21 12:28:29.000000000 +0100 @@ -1866,6 +1866,57 @@ description "Ethernet driver for the synthetic target" } +package CYGPKG_DEVS_ETH_SPARC_LEON { + alias { "LEON2 91C111 ethernet support" devs_eth_sparc_leon } + hardware + directory devs/eth/sparc/leon2 + script leon2_eth_drivers.cdl + description "This package contains hardware support for SMC91C111 + ethernet device on various LEON2 boards." +} + +package CYGPKG_DEVS_ETH_SPARC_LEON3 { + alias { "LEON3 91C111 ethernet support" devs_eth_sparc_leo3n } + hardware + directory devs/eth/sparc/leon3 + script leon3_eth_drivers.cdl + description "This package contains hardware support for SMC91C111 + ethernet device running on a LEON3 Soc." +} + +package CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC { + alias { "opencore's ethermac support" devs_eth_opencores_ethermac } + hardware + directory devs/eth/opencores/ethermac + script opencores_ethermac_drivers.cdl + description "This package contains hardware support for Opencores + ethermac." +} + +package CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3 { + alias { "ethernet support for opencores on Leon3 Soc" devs_eth_sparc_opencores_leon3 } + hardware + directory devs/eth/sparc/opencores/leon3 + script leon3_opencores_ethmac_drivers.cdl + description "This package contains hardware support for Opencores Ethermac + ethernet device on Leon3." +} + +package CYGPKG_DEVS_ETH_GRETH { + alias { "Gaisler Research's ethernet mac support" devs_eth_greth } + hardware + directory devs/eth/greth/ + script greth_drivers.cdl + description "This package contains hardware support for Gaisler Research's GRETH ethernet mac." +} + +package CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3 { + alias { "ethernet support for GRETH on Leon3 Soc" devs_eth_sparc_greth_leon3 } + hardware + directory devs/eth/sparc/greth/leon3 + script leon3_greth_drivers.cdl + description "This package contains hardware support for Gaisler Research's ethernet mac for Leon3." +} package CYGPKG_IO_PCI { alias { "PCI configuration library" io_pci } directory io/pci @@ -3264,6 +3315,17 @@ with both real hardware and the TSIM/LEON simulator." } +package CYGPKG_HAL_SPARC_LEON3 { + alias { "LEON3 processor" hal_sparc_leon3 sparc_leon3_hal } + directory hal/sparc/leon3 + script hal_sparc_leon3.cdl + hardware + description " + Grlib's LEON3 processor HAL package is provided for use + with both real hardware and the Grmon simulator." +} + + # -------------------------------------------------------------------------- # PowerPC packages package CYGPKG_HAL_POWERPC { @@ -4936,6 +4998,44 @@ on the LEON processor or TSIM/LEON simulator." } +target sparc_leon3 { + alias { "LEON3 processor" leon } + packages { CYGPKG_HAL_SPARC + CYGPKG_HAL_SPARC_LEON3 + } + description " + The sparc_leon3 target provides the packages need to run eCos + on Grlib's LEON3 processor or the tsim-leon3 simulator." +} + +target sparc_leon3_greth { + alias { "LEON3 processor with GRETH ethermac" leon } + packages { + CYGPKG_HAL_SPARC + CYGPKG_HAL_SPARC_LEON3 + CYGPKG_DEVS_ETH_GRETH + CYGPKG_DEVS_ETH_SPARC_GRETH_LEON3 + } + description " + The sparc_leon3_net target provides the packages need to run eCos + on Grlib's LEON3 processor or the tsim-leon3 simulator. It also adds + the driver for the GRETH ethermac. It should be used together with the net template that is: ecosconfig new sparc_leon3_greth net" +} + +target sparc_leon3_openeth { + alias { "LEON3 processor with OPENETH ethermac" leon } + packages { + CYGPKG_HAL_SPARC + CYGPKG_HAL_SPARC_LEON3 + CYGPKG_DEVS_ETH_OPENCORES_ETHERMAC + CYGPKG_DEVS_ETH_SPARC_OPENCORES_LEON3 + } + description " + The sparc_leon3_net target provides the packages need to run eCos + on Grlib's LEON3 processor or the tsim-leon3 simulator. It also adds + the driver for the Opencores ethermac. It should be used together with the net template that is: ecosconfig new sparc_leon3_openeth net" +} + # -------------------------------------------------------------------------- # PowerPC targets target cme555 { diff -Naurb ecos-cvs-2005-09-06/packages/hal/i386/arch/current/include/hal_smp.h ecos-rep/packages/hal/i386/arch/current/include/hal_smp.h --- ecos-cvs-2005-09-06/packages/hal/i386/arch/current/include/hal_smp.h 2002-05-24 01:03:05.000000000 +0200 +++ ecos-rep/packages/hal/i386/arch/current/include/hal_smp.h 2005-09-06 16:48:02.000000000 +0200 @@ -156,6 +156,12 @@ #define HAL_SMP_CPU_COUNT() cyg_hal_smp_cpu_count +#define HAL_SMP_CPU_START_COUNT() HAL_SMP_CPU_COUNT() + +#define HAL_SMP_CPU_COUNT2IDX(n) (n) + +#define HAL_SMP_CPU_IDX2COUNT(n) (n) + #define HAL_SMP_CPU_THIS() \ ({ \ HAL_SMP_CPU_TYPE __id; \ diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/cdl/hal_sparc.cdl ecos-rep/packages/hal/sparc/arch/current/cdl/hal_sparc.cdl --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/cdl/hal_sparc.cdl 2004-04-22 17:26:52.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/cdl/hal_sparc.cdl 2006-06-19 19:00:28.000000000 +0200 @@ -61,7 +61,7 @@ a specific target platform HAL package." compile vectors.S vec_ivsr.S vec_xvsr.S context.S icontext.c - compile hal_intr.c hal_boot.c + compile hal_intr.c hal_boot.c callcons.S make { /lib/vectors.o : /src/vectors.S @@ -122,6 +122,55 @@ } } + cdl_component CYGHWR_HAL_SPARC_FPU { + display "FPU support" + default_value 0 + description "This component enables support for the + Sparc floating point unit. If disabled -msoft-float issued + floating point emulation is used instead." + + + cdl_option CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH { + display "Use lazy FPU state switching" + flavor bool + default_value 0 + requires { CYGHWR_HAL_SPARC_FPU == 1 } + + description " + This option enables lazy FPU state switching. + When this feature is enabled an FPU context switch + is performed only if the new thread + uses the FPU. This feature can avoid unnecessary FPU + context switching if only few threads are using the FPU. + Must be disabled in an SMP system." + } + } + + cdl_component CYGHWR_HAL_SPARC_FLAT { + display "Use -mflat gcc mode" + default_value 0 + description "This will add the -mflat switch to the gcc command line." + } + + cdl_component CYGPKG_HAL_SPARC_REGISTER_WINDOWS { + display "Number of register windows (2 - 32)." + flavor data + default_value 8 + description "Configure the number of register windows your hardware has. Default is 8." + } + + cdl_component CYGPKG_HAL_SMP_SUPPORT { + display "SMP support" + default_value 0 + requires { CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH == 0 } + + cdl_option CYGPKG_HAL_SMP_CPU_MAX { + display "Max number of CPUs supported" + flavor data + default_value 2 + } + } + cdl_option CYGBLD_LINKER_SCRIPT { display "Linker script" flavor data diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/arch.inc ecos-rep/packages/hal/sparc/arch/current/include/arch.inc --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/arch.inc 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/arch/current/include/arch.inc 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,85 @@ +#ifndef CYGONCE_HAL_ARCH_INC +#define CYGONCE_HAL_ARCH_INC +##============================================================================= +## +## arch.inc +## +## sparc assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +##============================================================================= +#######DESCRIPTIONBEGIN#### +## +## Author(s): Gaisler Research (Konrad Eisele) +## Contributors: +## Date: +## Purpose: Architecture definitions. +## Description: This file contains definitions and macros that are +## useful for writing assembly code for the sparc CPU family. +## Usage: +## #include +## ... +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#define SPARC_PSR_ET_MASK 0x00000020 /* bit 5 */ +#define SPARC_PSR_PS_MASK 0x00000040 /* bit 6 */ +#define SPARC_PSR_S_MASK 0x00000080 /* bit 7 */ +#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */ +#define SPARC_PSR_EF_MASK 0x00001000 /* bit 12 */ +#define SPARC_PSR_EC_MASK 0x00002000 /* bit 13 */ +#define SPARC_PSR_ICC_MASK 0x00F00000 /* bits 20 - 23 */ +#define SPARC_PSR_VER_MASK 0x0F000000 /* bits 24 - 27 */ +#define SPARC_PSR_IMPL_MASK 0xF0000000 /* bits 28 - 31 */ + +#ifdef CYGPKG_HAL_SMP_SUPPORT + +#ifndef CYGPKG_HAL_SPARC_LEON3_OPTIONS +#error SMP only supported for Leon3 +#endif +#include + +#else + + .macro hal_smp_cpu reg + or %g0,%g0,\reg + .endm + +#endif + +#endif // ifndef CYGONCE_HAL_ARCH_INC diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_arch.h ecos-rep/packages/hal/sparc/arch/current/include/hal_arch.h --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_arch.h 2002-05-24 01:05:07.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/include/hal_arch.h 2006-06-21 10:30:57.000000000 +0200 @@ -66,6 +66,12 @@ // All these structures must be doubleword (64 bit) aligned. // The code that creates them on the stack will ensure this is so. +typedef struct +{ + cyg_uint32 f[32]; + cyg_uint32 fsr,_dummy; +} HAL_FPU_Context; + #define HAL_THREAD_CONTEXT_GLOBAL_BASE 0 #define HAL_THREAD_CONTEXT_OUT_BASE 8 #define HAL_THREAD_CONTEXT_LOCAL_BASE 16 @@ -93,6 +99,17 @@ cyg_uint32 o[8] ; /* Outs r8-r15 */ //32 words in size +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + HAL_FPU_Context *fpucontext; + cyg_uint32 _dummy; +//32+2 words in size +#elif defined(CYGHWR_HAL_SPARC_FPU) + cyg_uint32 f[32]; + cyg_uint32 fsr; + cyg_uint32 fdummy; +// 32+32+2 words in size +#endif + // There is no need to save any other state; for example, condition codes, // the PC and NextPC, and Y, are preserved in local registers in the trap // handling window and so preserved in the caller stack frame as viewed @@ -357,7 +374,7 @@ (4 * CYGNUM_HAL_STACK_INTERRUPT_SIZE + 2 * CYGNUM_HAL_STACK_FRAME_SIZE) #define CYGNUM_HAL_STACK_SIZE_TYPICAL \ - (CYGNUM_HAL_STACK_SIZE_MINIMUM + 8 * CYGNUM_HAL_STACK_FRAME_SIZE) + (CYGNUM_HAL_STACK_SIZE_MINIMUM + 60 * CYGNUM_HAL_STACK_FRAME_SIZE) //-------------------------------------------------------------------------- // Macros for switching context between two eCos instances (jump from @@ -365,7 +382,11 @@ #define CYGARC_HAL_SAVE_GP() #define CYGARC_HAL_RESTORE_GP() + //----------------------------------------------------------------------------- +#define __GET_FP(fp) __asm__ __volatile__("mov %%i6, %0" : "=r" (fp)) +#define __GET_SP(sp) __asm__ __volatile__("mov %%o6, %0" : "=r" (sp)) + #endif // CYGONCE_HAL_ARCH_H // End of hal_arch.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_intr.h ecos-rep/packages/hal/sparc/arch/current/include/hal_intr.h --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_intr.h 2002-05-24 01:05:07.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/include/hal_intr.h 2005-09-06 16:59:27.000000000 +0200 @@ -64,6 +64,7 @@ #include #include +#include //--------------------------------------------------------------------------- // SPARC exception vectors. @@ -158,6 +159,10 @@ #define CYGNUM_HAL_ISR_MAX 15 #define CYGNUM_HAL_ISR_COUNT 16 +#ifdef CYGPKG_HAL_SMP_SUPPORT +#define CYGNUM_HAL_SMP_CPU_INTERRUPT_VECTOR(_n_) 14 +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Exception vectors. These are the values used when passed out to an @@ -253,19 +258,6 @@ //--------------------------------------------------------------------------- // Interrupt control macros -// THIS ONE IS NOT A STANDARD HAL ENTRY (HAL_DISABLE_TRAPS) -// (so should be unused externally) -#define HAL_DISABLE_TRAPS(_old_) \ - asm volatile ( \ - "rd %%psr, %0;" \ - "andn %0, 0x20, %%l7;" \ - "wr %%l7, %%psr;" \ - "nop; nop; nop" \ - : "=r"(_old_) \ - : \ - : "l7" \ - ); - // THIS ONE IS NOT A STANDARD HAL ENTRY (HAL_QUERY_TRAPS) // (so should be unused externally) #define HAL_QUERY_TRAPS(_old_) \ @@ -277,41 +269,39 @@ : "l7" \ ); -#define HAL_DISABLE_INTERRUPTS(_old_) \ - asm volatile ( \ - "rd %%psr, %0;" \ - "or %0, 0xf00, %%l7;" \ - "wr %%l7, %%psr;" \ - "nop; nop; nop" \ - : "=r"(_old_) \ - : \ - : "l7" \ - ); -#define HAL_ENABLE_INTERRUPTS() \ - asm volatile ( \ - "rd %%psr, %%l7;" \ - "andn %%l7, 0xf00, %%l7;" \ - "or %%l7, 0x020, %%l7;" \ - "wr %%l7, %%psr;" \ - "nop; nop; nop" \ - : \ - : \ - : "l7" \ +//atomical psr set (inside a syscall trap) +externC inline unsigned long sparc_disable_interrupts(void) { + unsigned long _old_; + asm volatile ( + "mov %1, %%o0\n\t" + "ta 0\n\t" + "mov %%o0,%0\n\t" + : "=r"(_old_) + : "i" (SYS_irqdis) + : "o0", "cc" ); + return _old_; +} -#define HAL_RESTORE_INTERRUPTS(_old_) \ - asm volatile ( \ - "rd %%psr, %%l7;" \ - "andn %%l7, 0xf20, %%l7;" \ - "and %0 , 0xf20, %%l6;" \ - "wr %%l6, %%l7, %%psr;" \ - "nop; nop; nop" \ - : \ - : "r"(_old_) \ - : "l6","l7" \ +//atomical psr set (inside a syscall trap) +externC inline void sparc_enable_interrupts(unsigned long old) { + + asm volatile ( + "mov %1,%%o0\n\t" + "mov %0,%%o1\n\t" + "ta 0\n\t" + : + : "r"(old), "i" (SYS_irqen) + : "o0","o1", "cc" ); +}; + +#define HAL_DISABLE_INTERRUPTS(_old_) _old_ = sparc_disable_interrupts(); +#define HAL_ENABLE_INTERRUPTS() sparc_enable_interrupts(0); +#define HAL_RESTORE_INTERRUPTS(_old_) sparc_enable_interrupts(_old_); + #define HAL_QUERY_INTERRUPTS(_old_) \ asm volatile ( \ "rd %%psr, %%l7;" \ @@ -402,6 +392,8 @@ #include +#define HAL_DELAY_US(n) hal_delay_us(n) + //--------------------------------------------------------------------------- #endif // ifndef CYGONCE_HAL_INTR_H // End of hal_intr.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_smp.h ecos-rep/packages/hal/sparc/arch/current/include/hal_smp.h --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/hal_smp.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/arch/current/include/hal_smp.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,77 @@ +#ifndef SPARC_HAL_SMP_H +#define SPARC_HAL_SMP_H + +//=========================================================================== +// +// hal_smp.h +// +// HAL SMP support +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg +// Contributors: Gaisler Research,(Konrad Eisele) +// Date: 2004 +// Purpose: Define SMP support abstractions +// Description: +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include + +#ifdef CYGPKG_HAL_SMP_SUPPORT + +#include +#include + +#ifndef CYGPKG_HAL_SPARC_LEON3 +#error SMP only supported for Leon3 +#else +#include +#endif + +#endif // CYGPKG_HAL_SMP_SUPPORT + +//--------------------------------------------------------------------------- +#endif // ifndef SPARC_HAL_SMP_H +// End of hal_smp.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/vectors.h ecos-rep/packages/hal/sparc/arch/current/include/vectors.h --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/include/vectors.h 2002-05-24 01:05:07.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/include/vectors.h 2006-06-21 10:30:57.000000000 +0200 @@ -55,12 +55,37 @@ // //============================================================================= -#define __WINSIZE 8 +#include -#if __WINSIZE <= 8 -# define __WINBITS 7 +#define __WINSIZE CYGPKG_HAL_SPARC_REGISTER_WINDOWS + +#if (__WINSIZE < 2 || __WINSIZE > 32) +# error CYGPKG_HAL_SPARC_REGISTER_WINDOWS not supported +#endif +#if (__WINSIZE == 2 && !defined(CYGHWR_HAL_SPARC_FLAT) ) +# error window size of 2 only works with -mflat option +#endif + +#if (__WINSIZE == 2 || __WINSIZE == 4 || __WINSIZE == 8 || __WINSIZE == 16 || __WINSIZE == 32) +#define CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 1 +#endif + +#if (__WINSIZE <= 2) +#define __WINBITS (2-1) #else -# error __WINSIZE window size probably not supported +# if (__WINSIZE <= 4) +# define __WINBITS (4-1) +# else +# if (__WINSIZE <= 8) +# define __WINBITS (8-1) +# else +# if (__WINSIZE <= 16) +# define __WINBITS (16-1) +# else +# define __WINBITS (32-1) +# endif +# endif +# endif #endif // These should be generic to all SPARCs: @@ -68,12 +93,14 @@ #define __WINBITS_MAXIMAL 0x1f #define __WIN_INIT (__WINSIZE - 1) + #define __WIM_INIT (1 << __WIN_INIT) // ------------------------------------------------------------------------ #define TRAP_WUNDER 6 // Window Underflow trap number #define TRAP_WOVER 5 // Window Overflow trap number +#define TRAP_FPDIS 4 // FPU Disabled trap number #define TRAP_INTR_MIN 17 // smallest interrupt trap number #define TRAP_INTR_MAX 31 // largest interrupt trap number @@ -108,11 +135,19 @@ #define SCHED_LOCK_MANGLED_NAME cyg_scheduler_sched_lock - +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH +#define SAVE_REGS_SIZE (4 * (32+2)) // 32 words of 4 bytes each + fpu ctx + align +#define SAVE_FPUSTATE_SIZE (4 * (32+2)) // 32 fregs + fsr + _dummy +#elif defined(CYGHWR_HAL_SPARC_FPU) +#define SAVE_REGS_SIZE (4 * (32+32+2)) // 32 words of 4 bytes each + 32 FP + FSR + align +#else #define SAVE_REGS_SIZE (4 * 32) // 32 words of 4 bytes each +#endif - +#define SYS_exit 1 +#define SYS_irqdis 2 +#define SYS_irqen 3 #endif // CYGONCE_HAL_VECTORS_H // EOF vectors.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/callcons.S ecos-rep/packages/hal/sparc/arch/current/src/callcons.S --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/callcons.S 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/arch/current/src/callcons.S 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,99 @@ +/*=========================================================================== +// +// callcons.S +// +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt, +// Gaisler Research (Konrad Eisele) (fpu support) +// Date: 1999-02-20 +// Purpose: +// Description: callcons.S +// +//####DESCRIPTIONEND#### +// +//=========================================================================*/ + +! special treatment for CYGHWR_HAL_SPARC_FLAT case, otherwise hal_zero_bss will clear return address + + .section ".data" + .balign 4 +save_i7: !avoid .bss (clear) + .long 0x100000 +save_o7: !avoid .bss (clear) + .long 0x100000 + + .text + .global cyg_hal_start + .extern hal_board_prestart + .extern hal_zero_bss + .extern cyg_hal_invoke_constructors + .extern hal_board_poststart + .extern hal_copy_data + +cyg_hal_start: + add %sp, -112, %sp + set save_i7,%g1 + st %i7,[%g1] + set save_o7,%g1 + st %o7,[%g1] + + call hal_board_prestart + nop +#ifdef CYG_HAL_STARTUP_ROM + ! Copy data from ROM to RAM + call hal_copy_data + nop +#endif + call hal_zero_bss + nop + call cyg_hal_invoke_constructors + nop + call hal_board_poststart + nop + + set save_i7,%g1 + ld [%g1],%i7 + set save_o7,%g1 + ld [%g1],%o7 + retl + add %sp, 0x70, %sp + + +// EOF callcons.S diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/context.S ecos-rep/packages/hal/sparc/arch/current/src/context.S --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/context.S 2002-10-19 02:22:50.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/context.S 2006-06-21 10:30:57.000000000 +0200 @@ -56,9 +56,14 @@ #include +#include + #define DELAYS_AFTER_WRPSR_SAME_WINDOW #define DELAYS_AFTER_WRWIM + .extern cyg_hal_fpustate_owner + .extern cyg_hal_fpustate_current + .text ! ------------------------------------------------------------------------------ @@ -77,9 +82,10 @@ ! context. This lets us do this whole piece of work without ! diabling interrupts for too long, since, for example, we can ! lower the stack atomically with one instruction: + sub %sp, SAVE_REGS_SIZE, %sp - st %sp, [ %o1 ] ! return SP for this thread + st %sp, [ %o1 ] ! return SP for this thread std %l0, [%sp + 0 * 4] ! save L & I registers std %l2, [%sp + 2 * 4] std %l4, [%sp + 4 * 4] @@ -106,8 +112,38 @@ #endif // !CYGDBG_HAL_COMMON_CONTEXT_SAVE_MINIMUM ! and save the CWP in %g0 save place rd %psr, %g7 + +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set 0x1000,%g6 + andn %g7,%g6,%g7 !disable floating point +#endif st %g7, [%sp + 16 * 4] + ! push current fpu ctx +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set cyg_hal_fpustate_current,%g6 ! current state table + ld [%g6],%g6 + st %g6,[%sp + 32 * 4] +#elif defined(CYGHWR_HAL_SPARC_FPU) + std %f0, [%sp + 32 * 4] + std %f2, [%sp + 34 * 4] + std %f4, [%sp + 36 * 4] + std %f6, [%sp + 38 * 4] + std %f8, [%sp + 40 * 4] + std %f10, [%sp + 42 * 4] + std %f12, [%sp + 44 * 4] + std %f14, [%sp + 46 * 4] + std %f16, [%sp + 48 * 4] + std %f18, [%sp + 50 * 4] + std %f20, [%sp + 52 * 4] + std %f22, [%sp + 54 * 4] + std %f24, [%sp + 56 * 4] + std %f26, [%sp + 58 * 4] + std %f28, [%sp + 60 * 4] + std %f30, [%sp + 62 * 4] + st %fsr, [%sp + 64 * 4] +#endif + ! Now load the destination thread by dropping through ! to hal_thread_load_context @@ -125,6 +161,13 @@ ! The stack is still the callers at this point but the register ! set is up for grabs. So we can use globals: + !mov %o0,%l0 + ! + !mov %1, %o0 + !ta 0 + !mov %o0,%g6 + !ld [ %l0 ], %g7 ! Get the next saved SP + ld [ %o0 ], %g7 ! Get the next saved SP ! DISABLE INTERRUPTS *ONLY* NOT TRAPS @@ -136,16 +179,14 @@ ! force out all our callers register sets onto the stack ! if necessary: the system will handily take care of this for ! us as follows: - save %sp, -16 * 4, %sp ! need all these to preserve - save %sp, -16 * 4, %sp ! the linked list property... - save %sp, -16 * 4, %sp + ! need all these to preserve + ! the linked list property... +#if !defined(CYGHWR_HAL_SPARC_FLAT) + .rept __WINSIZE-2 save %sp, -16 * 4, %sp -#if 6 < __WINSIZE - save %sp, -16 * 4, %sp -#if 7 < __WINSIZE - save %sp, -16 * 4, %sp -#endif + .endr #endif + ! Fewer saves if fewer register windows. For 8 register windows, ! six of these is correct; a seventh would force out the current ! set that was already saved manually above. Note that minimal @@ -158,13 +199,17 @@ ! from the %g0 save place... ld [%g7 + 16 * 4], %g6 ! %g7 holds the new stack pointer andn %g6, 0x20, %g5 ! clear ET into %g5 +#if (!defined(CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH)) && defined(CYGHWR_HAL_SPARC_FPU) + set 0x01000, %g4 + or %g5, %g4, %g5 +#endif and %g6, __WINBITS, %g4 ! CWP bits only in %g4 ! calculate a new WIM... add %g4, 1, %g3 ! required invalid window number -#if 8 == __WINSIZE - and %g3, __WINBITS, %g3 ! modulo 8 -#else // expect 5 or 6 or 7 windows +#if CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 + and %g3, __WINBITS, %g3 ! modulo rw pow2 +#else // except for rw != pow2 cmp %g3, __WINSIZE bge,a 567f ! taken: do delay slot, handle overflow mov 0, %g3 ! only if .ge. above @@ -175,7 +220,11 @@ ! DISABLE INTERRUPTS (TRAPS) wr %g5, %psr ! set CWP to new window, disable traps +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + wr %g0, %wim +#else wr %g2, %wim ! and WIM to new value +#endif nop nop nop @@ -195,6 +244,32 @@ ldd [%sp + 12 * 4], %i4 ldd [%sp + 14 * 4], %i6 + ! set new current fpu ctx +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + ld [%sp + 32 * 4],%g1 + set cyg_hal_fpustate_current,%g2 ! current state table + st %g1,[%g2] +#elif defined(CYGHWR_HAL_SPARC_FPU) + ldd [%sp + 32 * 4], %f0 + ldd [%sp + 34 * 4], %f2 + ldd [%sp + 36 * 4], %f4 + ldd [%sp + 38 * 4], %f6 + ldd [%sp + 40 * 4], %f8 + ldd [%sp + 42 * 4], %f10 + ldd [%sp + 44 * 4], %f12 + ldd [%sp + 46 * 4], %f14 + ldd [%sp + 48 * 4], %f16 + ldd [%sp + 50 * 4], %f18 + ldd [%sp + 52 * 4], %f20 + ldd [%sp + 54 * 4], %f22 + ldd [%sp + 56 * 4], %f24 + ldd [%sp + 58 * 4], %f26 + ldd [%sp + 60 * 4], %f28 + ldd [%sp + 62 * 4], %f30 + ld [%sp + 64 * 4], %fsr +#endif + + ! RESTORE INTERRUPTS to saved state wr %g6, %psr ! set new CWP and old ET and PIL nop @@ -224,6 +299,7 @@ add %sp, SAVE_REGS_SIZE, %sp ! and set the stack back ! to its entrant value + ! ------------------------------------------------------------------------------ ! HAL longjmp, setjmp implementations @@ -269,16 +345,12 @@ ! force out all our callers register sets onto the stack ! if necessary: the system will handily take care of this for ! us as follows: - save %sp, -16 * 4, %sp ! need all these to preserve - save %sp, -16 * 4, %sp ! the linked list property... - save %sp, -16 * 4, %sp - save %sp, -16 * 4, %sp -#if 6 < __WINSIZE - save %sp, -16 * 4, %sp -#if 7 < __WINSIZE +#if !defined(CYGHWR_HAL_SPARC_FLAT) + .rept __WINSIZE-2 save %sp, -16 * 4, %sp + .endr #endif -#endif + ! Fewer saves if fewer register windows. For 8 register windows, ! six of these is correct; a seventh would force out the current ! set that was already saved manually above. Note that minimal @@ -323,9 +395,9 @@ ! calculate a new WIM... add %g4, 1, %g3 ! required invalid window number -#if 8 == __WINSIZE - and %g3, __WINBITS, %g3 ! modulo 8 -#else // expect 5 or 6 or 7 windows +#if CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 + and %g3, __WINBITS, %g3 ! modulo rw pow2 +#else // except for rw != pow2 cmp %g3, __WINSIZE bge,a 567f ! taken: do delay slot, handle overflow mov 0, %g3 ! only if .ge. above @@ -336,7 +408,11 @@ ! DISABLE INTERRUPTS wr %g5, %g4, %psr ! set CWP to new window, disable traps +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + wr %g0, %wim +#else wr %g2, %wim ! and WIM to new value +#endif nop nop nop diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/hal_boot.c ecos-rep/packages/hal/sparc/arch/current/src/hal_boot.c --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/hal_boot.c 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/hal_boot.c 2005-09-06 16:59:27.000000000 +0200 @@ -75,6 +75,8 @@ } #endif +//note: when compiling with -mflat (CYGHWR_HAL_SPARC_FLAT) this routine +//has to be a leaf routine, otherwise it will clear it's own stack. void hal_zero_bss(void) { extern CYG_ROM_ADDRESS __bss_start; @@ -138,37 +140,27 @@ // This is called with traps enabled, but interrupts masked out: // Be sure to enable them in hal_board_poststart() at the latest. +/* void cyg_hal_start( void ) { - /* Board specific prestart that's best done in C */ + // Board specific prestart that's best done in C hal_board_prestart(); - LED( 0xd0 ); - #ifdef CYG_HAL_STARTUP_ROM - /* Copy data from ROM to RAM */ + // Copy data from ROM to RAM hal_copy_data(); #endif - LED( 0xd4 ); - - /* Zero BSS */ + // Zero BSS hal_zero_bss(); - LED( 0xd8 ); - - /* Call constructors */ + // Call constructors cyg_hal_invoke_constructors(); - LED( 0xdc ); - - /* Board specific late startup that's best done in C */ + // Board specific late startup that's best done in C hal_board_poststart(); - LED( 0xf8 ); +}*/ - /* Call cyg_start */ - cyg_start(); /* does not return */ -} // EOF hal_boot.c diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/hal_intr.c ecos-rep/packages/hal/sparc/arch/current/src/hal_intr.c --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/hal_intr.c 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/hal_intr.c 2005-09-05 16:06:32.000000000 +0200 @@ -159,4 +159,51 @@ 0, }; + + +/*------------------------------------------------------------------------*/ +/* Delay for some number of useconds. */ +void +hal_delay_us(int us) +{ + cyg_uint32 val1, val2; + int diff; + long usticks; + long ticks; + + // Calculate the number of counter register ticks per microsecond. + + usticks = (CYGNUM_HAL_RTC_PERIOD * CYGNUM_HAL_RTC_DENOMINATOR) / 1000000; + + // Make sure that the value is not zero. This will only happen if the + // CPU is running at < 2MHz. + if( usticks == 0 ) usticks = 1; + + while( us > 0 ) + { + int us1 = us; + + // Wait in bursts of less than 10000us to avoid any overflow + // problems in the multiply. + if( us1 > 10000 ) + us1 = 10000; + + us -= us1; + + ticks = us1 * usticks; + + HAL_CLOCK_READ(&val1); + while (ticks > 0) { + do { + HAL_CLOCK_READ(&val2); + } while (val1 == val2); + diff = val2 - val1; + if (diff < 0) diff += CYGNUM_HAL_RTC_PERIOD; + ticks -= diff; + val1 = val2; + } + } +} + + // EOF hal_intr.c diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/icontext.c ecos-rep/packages/hal/sparc/arch/current/src/icontext.c --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/icontext.c 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/icontext.c 2006-06-21 10:30:57.000000000 +0200 @@ -42,6 +42,7 @@ // // Author(s): hmt // Contributors: hmt +// Gaisler Research (Konrad Eisele) (fpu support) // Date: 1998-12-14 // Purpose: HAL context initialization function // Description: Initialize a HAL context for SPARC; this is in C and out @@ -62,6 +63,7 @@ /*---------------------------------------------------------------------------*/ /* We lay out the stack in the manner that the PCS demands: + * fpucontext -----> Allocate fpu spilling region * frame pointer -----> [top of stack] * Argument spill area (6 words) * Return Arg pointer @@ -101,22 +103,35 @@ CYG_WORD entry, CYG_WORD id ) { - register CYG_WORD fp = sparg; + register CYG_WORD fp = 0; register CYG_WORD sp = 0; register HAL_SavedRegisters *regs; register HAL_FrameStructure *frame; +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + register HAL_FPU_Context *fpucontext = (HAL_FPU_Context *)((sparg) & ~15); // round down to double alignment +#endif + int i; if ( 0 == (id & 0xffff0000) ) id <<= 16; - fp &= ~15; // round down to double alignment +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + fpucontext = (HAL_FPU_Context *) // allocate fpu spilling region + (((CYG_WORD)fpucontext) - sizeof(HAL_FPU_Context)); + fp = (CYG_WORD)fpucontext; +#else + fp = sparg & ~15; +#endif frame = (HAL_FrameStructure *)( fp - sizeof( HAL_FrameStructure ) ); regs = (HAL_SavedRegisters *)( ((CYG_WORD)frame) - sizeof(HAL_SavedRegisters) ); +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + regs ->fpucontext = fpucontext; +#endif sp = (CYG_WORD)regs; @@ -134,6 +149,7 @@ regs ->g[i] = id | ( i ); } + // first terminate the linked list on the stack in the initial // (already saved) register window: frame->li.i[6] = regs->li.i[6] = (cyg_uint32)fp; // frame pointer @@ -150,7 +166,17 @@ // this is the initial CWP and interrupt state; CWP is quite arbitrary // really, the WIM is set up accordingly in hal_thread_load_context(). +#if defined(CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH) || (!defined(CYGHWR_HAL_SPARC_FPU)) regs->g[0] = 0x0e0 + __WIN_INIT; // PIL zero, ET, S, PS and CWP set. +#else + regs->g[0] = 0x010e0 + __WIN_INIT; // PIL zero, ET, S, PS, EF and CWP set. +#endif + +#if defined(CYGHWR_HAL_SPARC_FPU) && (!defined(CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH)) + for (i = 0; i < 32; i++) {regs->f[i] = 0;} + regs->fsr = 0; + regs->fdummy = 0; +#endif return (CYG_ADDRESS)sp; } @@ -279,7 +305,7 @@ gdb[ Y ] = trapli->l[4]; scratch = trapli->l[0]; // the PSR in the trap handler -#if 8 == __WINSIZE +#if CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 scratch++; // back to interupted thread's window scratch &=~ 0x38; // clear ET and any __WINSIZE overflow gdb[ PSR ] = scratch; @@ -351,7 +377,7 @@ scratch = eCos_regset->g[ 0 ]; // the PSR in the saved context gdb[ PSR ] = scratch; // return it verbatim. -#if 8 == __WINSIZE +#if CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 gdb[ WIM ] = 1 << ((__WINBITS & (1 + scratch))); #else // 6 or 7 windows only reg = (int)(scratch & __WINBITS); diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/sparc.ld ecos-rep/packages/hal/sparc/arch/current/src/sparc.ld --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/sparc.ld 2003-04-10 20:07:58.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/sparc.ld 2005-09-05 16:06:32.000000000 +0200 @@ -125,7 +125,7 @@ #define SECTION_bss(_region_, _vma_, _lma_) \ .bss _vma_ : _lma_ \ { __bss_start = ABSOLUTE (.); \ - *(.scommon) *(.dynbss) *(.bss) *(COMMON) \ + *(.scommon) *(.dynbss) *(.bss) *(.bss.*) *(COMMON) \ __bss_end = ABSOLUTE (.); } \ > _region_ diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vec_ivsr.S ecos-rep/packages/hal/sparc/arch/current/src/vec_ivsr.S --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vec_ivsr.S 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/vec_ivsr.S 2006-06-21 10:30:57.000000000 +0200 @@ -41,7 +41,8 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): hmt -// Contributors: hmt +// Contributors: hmt, +// Gaisler Research (Konrad Eisele) (fpu support) // Date: 1999-02-20 // Purpose: SPARC vector code // Description: see vectors.S; this is the default vector service routine @@ -67,6 +68,8 @@ # undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT #endif +#include + !------------------------------------------------------------------------ #include @@ -102,12 +105,34 @@ ! the next one will need to be saved before we can use it: ! ie. this one is the invalid register window. + set 0x1000,%l7 +#if defined(CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH) && defined(CYGHWR_HAL_SPARC_FPU) + andn %l0, %l7, %l0 ! fpu off +#endif + ! must establish a safe stack before re-enabling interrupts + traps and %l0, __WINBITS, %l7 ! CWP extracted ! no inc/dec here, so no need for special measures for not-8-windows mov 1, %l6 sll %l6, %l7, %l6 ! 1 << CWP rd %wim, %l5 + +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + ! ----------------------- 2 window case ------------------- + restore + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + save + ! ----------------------- /2 window case ------------------- +#else + ! -----------------------normal case ----------------------- cmp %l5, %l6 ! are they the same? bne 1f ! No, so the stack is OK as is. @@ -138,9 +163,11 @@ restore ! Go back to trap window. mov %l7, %g1 ! Restore %g1 +#endif + ! -----------------------/normal case ----------------------- 1: ! now save away the regs we must preserve - sub %fp, 32 * 4, %sp + sub %fp, SAVE_REGS_SIZE, %sp #ifdef CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT std %g0, [%sp + 16 * 4] ! save G registers std %g2, [%sp + 18 * 4] ! (set %g0 place to 0 to flag special context) @@ -168,6 +195,37 @@ st %l0, [%sp + 16 * 4] #endif // ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT + ! push fpu ctx +#ifdef CYGHWR_HAL_SPARC_FPU +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set cyg_hal_fpustate_current,%g6 ! current state table + ld [%g6],%g6 + st %g6,[%sp + 32 * 4] + + sub %sp,SAVE_FPUSTATE_SIZE,%sp ! allocate fpu flush for irq + + set cyg_hal_fpustate_current,%g2 ! current state table + st %sp,[%g2] +#else + std %f0, [%sp + 32 * 4] + std %f2, [%sp + 34 * 4] + std %f4, [%sp + 36 * 4] + std %f6, [%sp + 38 * 4] + std %f8, [%sp + 40 * 4] + std %f10, [%sp + 42 * 4] + std %f12, [%sp + 44 * 4] + std %f14, [%sp + 46 * 4] + std %f16, [%sp + 48 * 4] + std %f18, [%sp + 50 * 4] + std %f20, [%sp + 52 * 4] + std %f22, [%sp + 54 * 4] + std %f24, [%sp + 56 * 4] + std %f26, [%sp + 58 * 4] + std %f28, [%sp + 60 * 4] + std %f30, [%sp + 62 * 4] + st %fsr, [%sp + 64 * 4] +#endif +#endif sub %sp, 24 * 4, %sp ! fresh frame including ! arg spill area for callees MARKSTACKUSED ! kilroy was here @@ -175,10 +233,20 @@ #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK ! we will switch to the interrupt stack unless already running on it +#if !defined(CYGPKG_HAL_SMP_SUPPORT) .extern cyg_interrupt_stack .extern cyg_interrupt_stack_base set cyg_interrupt_stack, %g1 set cyg_interrupt_stack_base, %g2 +#else + .extern __interrupt_stack_vector + hal_smp_cpu %g1 + sll %g1,2,%g1 + set __interrupt_stack_vector,%l7 + ld [%l7+%g1], %g1 + set CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE,%l7 + sub %g1,%l7,%g2 +#endif cmp %sp, %g2 ! below base? blu 1f ! if so, switch. @@ -194,7 +262,8 @@ ! continue as before, already in the interrupt stack. #endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK -#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT +#if defined(CYGFUN_HAL_COMMON_KERNEL_SUPPORT) && \ + !defined(CYGPKG_HAL_SMP_SUPPORT) ! Lock the scheduler .extern SCHED_LOCK_MANGLED_NAME sethi %hi(SCHED_LOCK_MANGLED_NAME), %l7 @@ -212,10 +281,20 @@ rd %y, %l4 ! Now we can reenable traps and mask off only lower prio interrupts: +#if defined(CYGPKG_HAL_SMP_SUPPORT) + or %l0, 0xf00, %l7 ! disable irq +#if (!defined(CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH)) && defined(CYGHWR_HAL_SPARC_FPU) + or %l7, 0x10e0, %l7 ! and ET (+S,PS,EF) +#else + or %l7, 0x0e0, %l7 ! and ET (+S,PS) +#endif + wr %l7, %psr ! and enable! +#else andn %l0, 0xf00, %l7 ! clear PIL field or %l7, 0x0e0, %l7 ! and ET (+S,PS) sll %l3, 8, %l6 ! trap number (1-15) into PIL bitfield wr %l7, %l6, %psr ! and enable! +#endif #ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW nop nop @@ -260,8 +339,17 @@ nop #endif +#if !defined(CYGPKG_HAL_SMP_SUPPORT) .extern cyg_interrupt_stack set cyg_interrupt_stack - (24 * 4), %g1 +#else + .extern __interrupt_stack_vector + hal_smp_cpu %g1 + sll %g1,2,%g1 + set __interrupt_stack_vector,%l7 + ld [%l7+%g1], %g1 + sub %g1,(24 * 4),%g1 +#endif cmp %sp, %g1 ! is SP less? blu 1f ! if so, do not change back @@ -318,10 +406,39 @@ ! HELP_GDB_WITH_BACKTRACE mov %l5, %i7 ! restore (unused) return link +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + add %sp,SAVE_FPUSTATE_SIZE,%sp ! undo fpu flush area +#endif + ! and restore other saved regs ! (see CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT) add %sp, 24 * 4, %sp ! undo fresh frame + ! pop fpu ctx +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + ld [%sp + 32 * 4],%g5 + set cyg_hal_fpustate_current,%g6 ! current state table + st %g5,[%g6] +#elif defined(CYGHWR_HAL_SPARC_FPU) + ldd [%sp + 32 * 4], %f0 + ldd [%sp + 34 * 4], %f2 + ldd [%sp + 36 * 4], %f4 + ldd [%sp + 38 * 4], %f6 + ldd [%sp + 40 * 4], %f8 + ldd [%sp + 42 * 4], %f10 + ldd [%sp + 44 * 4], %f12 + ldd [%sp + 46 * 4], %f14 + ldd [%sp + 48 * 4], %f16 + ldd [%sp + 50 * 4], %f18 + ldd [%sp + 52 * 4], %f20 + ldd [%sp + 54 * 4], %f22 + ldd [%sp + 56 * 4], %f24 + ldd [%sp + 58 * 4], %f26 + ldd [%sp + 60 * 4], %f28 + ldd [%sp + 62 * 4], %f30 + ld [%sp + 64 * 4], %fsr +#endif + ld [%sp + 17 * 4], %g1 ! restore G registers ldd [%sp + 18 * 4], %g2 ldd [%sp + 20 * 4], %g4 @@ -338,7 +455,7 @@ add %l0, 1, %l7 ! interruptee~s CWP plus noise and %l7, __WINBITS, %l7 ! CWP only -#if 8 == __WINSIZE +#ifdef CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 ! it is in range already #else // expect 5 or 6 or 7 windows cmp %l7, __WINSIZE @@ -349,6 +466,23 @@ mov 1, %l6 sll %l6, %l7, %l6 ! 1 << CWP rd %wim, %l5 + +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + ! ----------------------- 2 window case ------------------- + restore ! Interruptee~s window + ldd [%sp + 0 * 4], %l0 ! restore L & I registers + ldd [%sp + 2 * 4], %l2 + ldd [%sp + 4 * 4], %l4 + ldd [%sp + 6 * 4], %l6 + + ldd [%sp + 8 * 4], %i0 + ldd [%sp + 10 * 4], %i2 + ldd [%sp + 12 * 4], %i4 + ldd [%sp + 14 * 4], %i6 + save ! Back to trap window + ! ----------------------- /2 window case ------------------- +#else + ! -----------------------normal case ----------------------- cmp %l5, %l6 ! are they the same? bne 2f ! No, so the stack is OK as is. @@ -373,6 +507,8 @@ ldd [%sp + 14 * 4], %i6 save ! Back to trap window + ! -----------------------/normal case ----------------------- +#endif 2: ! restore the condition codes, PSR and PIL and return from trap. wr %l0, %psr ! restores flags, disables traps, and old PIL #ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW @@ -394,48 +530,80 @@ .global hal_interrupt_stack_call_pending_DSRs hal_interrupt_stack_call_pending_DSRs: +#if !defined(CYGHWR_HAL_SPARC_FLAT) save %sp, -24 * 4, %sp +#else + add %sp, -24 * 4, %sp + st %i7, [ %sp + 0x0 ] + sub %sp, -24 * 4, %i7 + st %o7, [ %sp + 0x4 ] + std %l0, [ %sp + 0x8 ] + std %l2, [ %sp + 0x10 ] + std %l4, [ %sp + 0x18 ] + std %l6, [ %sp + 0x20 ] + std %i0, [ %sp + 0x28 ] + std %i2, [ %sp + 0x30 ] + std %i4, [ %sp + 0x38 ] +#endif MARKSTACKUSED ! kilroy was here - ! be atomic - rd %psr, %l0 - andn %l0, 0x20, %l1 ! clear ET to disable traps - wr %l1, %psr ! into the PSR - nop - nop - nop + mov %psr,%l0 + + set SYS_irqdis,%o0 + ta 0 mov %sp, %l7 ! save calling stack location ! now switch stack to the interrupt stack, plus some headroom ! for saving a register set if we are interrupted +#if !defined(CYGPKG_HAL_SMP_SUPPORT) .extern cyg_interrupt_stack set cyg_interrupt_stack - 4 * 24, %sp +#else + .extern __interrupt_stack_vector + hal_smp_cpu %l2 + sll %l2,2,%l2 + set __interrupt_stack_vector,%l3 + ld [%l2+%l3], %l2 + sub %l2,(24 * 4),%sp +#endif MARKSTACKUSED ! kilroy was here - ! and enable interrupts unconditionally to call the DSRs - or %l0, 0x0e0, %l2 ! set ET, S, PS - andn %l2, 0xf00, %l2 ! PIL to zero - wr %l2, %psr ! into the PSR - nop - nop - nop + ! enable interrupts unconditionally to call the DSRs + set SYS_irqen,%o0 + mov %g0,%o1 + ta 0 .extern cyg_interrupt_call_pending_DSRs call cyg_interrupt_call_pending_DSRs nop mov %l7, %sp ! restore calling stack - wr %l0, %psr ! restore interrupt status nop nop nop +#if !defined(CYGHWR_HAL_SPARC_FLAT) ret restore +#else + sub %i7, 24 * 4, %sp + ld [ %sp + 0x0 ], %i7 + ld [ %sp + 0x4 ], %o7 + ldd [ %sp + 0x8 ], %l0 + ldd [ %sp + 0x10 ], %l2 + ldd [ %sp + 0x18 ], %l4 + ldd [ %sp + 0x20 ], %l6 + ldd [ %sp + 0x28 ], %i0 + ldd [ %sp + 0x30 ], %i2 + ldd [ %sp + 0x38 ], %i4 + retl + add %sp, 24 * 4, %sp +#endif + #endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK !---------------------------------------------------------------------------- diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vec_xvsr.S ecos-rep/packages/hal/sparc/arch/current/src/vec_xvsr.S --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vec_xvsr.S 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/vec_xvsr.S 2006-06-21 10:30:57.000000000 +0200 @@ -44,6 +44,7 @@ // Contributors: hmt // Date: 1999-02-20 // Purpose: SPARC vector code +// Gaisler Research (Konrad Eisele) (fpu support) // Description: see vectors.S; this is the default vector service routine // for exceptions. // @@ -64,6 +65,8 @@ # include #endif +#include + !------------------------------------------------------------------------ #include @@ -91,12 +94,32 @@ ! the next one will need to be saved before we can use it: ! ie. this one is the invalid register window. + set 0x1000,%l7 + andn %l0, %l7, %l0 ! fpu off + ! must establish a safe stack before re-enabling interrupts + traps and %l0, __WINBITS, %l7 ! CWP extracted ! no inc/dec here, so no need for special measures for not-8-windows mov 1, %l6 sll %l6, %l7, %l6 ! 1 << CWP rd %wim, %l5 + +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + ! ----------------------- 2 window case ------------------- + restore + std %l0, [%sp + 0 * 4] ! save L & I registers + std %l2, [%sp + 2 * 4] + std %l4, [%sp + 4 * 4] + std %l6, [%sp + 6 * 4] + + std %i0, [%sp + 8 * 4] + std %i2, [%sp + 10 * 4] + std %i4, [%sp + 12 * 4] + std %i6, [%sp + 14 * 4] + save + ! ----------------------- /2 window case ------------------- +#else + ! -----------------------normal case ----------------------- cmp %l5, %l6 ! are they the same? bne 1f ! No, so the stack is OK as is. @@ -127,9 +150,13 @@ restore ! Go back to trap window. mov %l7, %g1 ! Restore %g1 + ! -----------------------/normal case ----------------------- +#endif 1: ! now save away the regs we must preserve - sub %fp, 32 * 4, %sp + + sub %fp, SAVE_REGS_SIZE, %sp + ! save a maximal context regardless: see also ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT std %l0, [%sp + 0 * 4] ! save L & I registers @@ -147,6 +174,32 @@ std %g4, [%sp + 20 * 4] std %g6, [%sp + 22 * 4] + ! push fpu ctx +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set cyg_hal_fpustate_current,%g6 ! current state table + ld [%g6],%g6 + st %g6,[%sp + 32 * 4] +#elif defined(CYGHWR_HAL_SPARC_FPU) + std %f0, [%sp + 32 * 4] + std %f2, [%sp + 34 * 4] + std %f4, [%sp + 36 * 4] + std %f6, [%sp + 38 * 4] + std %f8, [%sp + 40 * 4] + std %f10, [%sp + 42 * 4] + std %f12, [%sp + 44 * 4] + std %f14, [%sp + 46 * 4] + std %f16, [%sp + 48 * 4] + std %f18, [%sp + 50 * 4] + std %f20, [%sp + 52 * 4] + std %f22, [%sp + 54 * 4] + std %f24, [%sp + 56 * 4] + std %f26, [%sp + 58 * 4] + std %f28, [%sp + 60 * 4] + std %f30, [%sp + 62 * 4] + st %fsr, [%sp + 64 * 4] +#endif + + ! no point whatsoever in saving O registers ! and save the CWP in %g0 save place @@ -221,6 +274,33 @@ ! and restore other saved regs add %sp, 24 * 4, %sp ! undo fresh frame + + ! pop fpu ctx +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + ld [%sp + 32 * 4],%g5 + set cyg_hal_fpustate_current,%g6 ! current state table + st %g5,[%g6] +#elif defined(CYGHWR_HAL_SPARC_FPU) + !ld [%sp + 32 * 4], %g2 + ldd [%sp + 32 * 4], %f0 + ldd [%sp + 34 * 4], %f2 + ldd [%sp + 36 * 4], %f4 + ldd [%sp + 38 * 4], %f6 + ldd [%sp + 40 * 4], %f8 + ldd [%sp + 42 * 4], %f10 + ldd [%sp + 44 * 4], %f12 + ldd [%sp + 46 * 4], %f14 + ldd [%sp + 48 * 4], %f16 + ldd [%sp + 50 * 4], %f18 + ldd [%sp + 52 * 4], %f20 + ldd [%sp + 54 * 4], %f22 + ldd [%sp + 56 * 4], %f24 + ldd [%sp + 58 * 4], %f26 + ldd [%sp + 60 * 4], %f28 + ldd [%sp + 62 * 4], %f30 + ld [%sp + 64 * 4], %fsr +#endif + ! restore a maximal context regardless: see also ! CYGDBG_HAL_COMMON_INTERRUPTS_SAVE_MINIMUM_CONTEXT ldd [%sp + 0 * 4], %l0 ! restore L & I registers @@ -248,7 +328,7 @@ add %l0, 1, %l7 ! interruptee~s CWP plus noise and %l7, __WINBITS, %l7 ! CWP only -#if 8 == __WINSIZE +#ifdef CYGPKG_HAL_SPARC_REGISTER_WINDOWS_POW2 ! it is in range already #else // expect 5 or 6 or 7 windows cmp %l7, __WINSIZE @@ -259,6 +339,23 @@ mov 1, %l6 sll %l6, %l7, %l6 ! 1 << CWP rd %wim, %l5 + +#if (__WINSIZE == 2) && defined(CYGHWR_HAL_SPARC_FLAT) + ! ----------------------- 2 window case ------------------- + restore ! Interruptee~s window + ldd [%sp + 0 * 4], %l0 ! restore L & I registers + ldd [%sp + 2 * 4], %l2 + ldd [%sp + 4 * 4], %l4 + ldd [%sp + 6 * 4], %l6 + + ldd [%sp + 8 * 4], %i0 + ldd [%sp + 10 * 4], %i2 + ldd [%sp + 12 * 4], %i4 + ldd [%sp + 14 * 4], %i6 + save ! Back to trap window + ! ----------------------- /2 window case ------------------- +#else + ! -----------------------normal case ----------------------- cmp %l5, %l6 ! are they the same? bne 2f ! No, so the stack is OK as is. @@ -283,6 +380,8 @@ ldd [%sp + 14 * 4], %i6 save ! Back to trap window + ! -----------------------/normal case ----------------------- +#endif 2: ! restore the condition codes, PSR and PIL and return from trap. wr %l0, %psr ! restores flags, disables traps, and old PIL #ifdef DELAYS_AFTER_WRPSR_SAME_WINDOW diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vectors.S ecos-rep/packages/hal/sparc/arch/current/src/vectors.S --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/src/vectors.S 2002-10-19 02:22:50.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/src/vectors.S 2006-06-21 10:30:57.000000000 +0200 @@ -41,7 +41,8 @@ //#####DESCRIPTIONBEGIN#### // // Author(s): hmt -// Contributors:hmt +// Contributors:hmt, +// Gaisler Research (Konrad Eisele) (fpu support) // Date: 1998-12-15 // Purpose: SPARC vector code // Description: This file contains the code which hangs off SPARC vectors @@ -59,6 +60,7 @@ !----------------------------------------------------------------------------- + #include #include @@ -72,9 +74,12 @@ # undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT #endif +#include + #if defined( CYGPKG_HAL_SPARCLITE_SIM ) || \ defined( CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK ) || \ defined( CYGPKG_HAL_SPARC_LEON ) || \ + defined( CYGPKG_HAL_SPARC_LEON3 ) || \ defined( CYGPKG_HAL_SPARC_ERC32 ) #define BOOTUPSTACK_IS_INTERRUPTSTACK #endif @@ -87,6 +92,10 @@ #endif #endif +#if !defined(CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING) && !defined(CYGPKG_HAL_SPARC_LEON3) +#error Single Vector Trapping (SVT) demands Leon3 model +#endif + #ifdef CYG_HAL_STARTUP_ROM # ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING @@ -111,6 +120,22 @@ #ifdef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + .macro VECTOR_SYSCALL _vector _handler + .p2align 4 + mov %psr, %l0 + sethi %hi(\_handler), %l4 + jmp %l4+%lo(\_handler) + mov \_vector, %l3 + .endm + + .macro VECTOR_DUMMY + .p2align 4 + jmp %l1 + rett %l2 + nop + nop + .endm + .macro VECTOR_EXCEPTION .p2align 4 rd %tbr, %l3 @@ -133,6 +158,12 @@ rd %wim, %l0 .endm + .macro VECTOR_FPDIS + .p2align 4 + ba __entry_fpdis + rd %psr, %l0 + .endm + #endif // CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING !------------------------------------------------------------------------ @@ -142,21 +173,20 @@ .global rom_vectors rom_vectors: - .global reset_vector -reset_vector: +trap_table: +#ifdef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING ! this code goes to the real reset handler, it will be ! overwritten by the start of vectoring handler... b genuine_reset nop ! usually drop through to: -#ifdef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING ba __entry_exception ! reset becomes an exception and %l3, TT_MASK, %l4 ! once we are running VECTOR_EXCEPTION ! 1 VECTOR_EXCEPTION ! 2 VECTOR_EXCEPTION ! 3 - VECTOR_EXCEPTION ! 4 + VECTOR_FPDIS ! 4 fp disabled VECTOR_CODE_WIM wover ! 5 window overflow VECTOR_CODE_WIM wunder ! 6 window underflow @@ -195,18 +225,30 @@ VECTOR_EXCEPTION ! 34 VECTOR_EXCEPTION ! 35 - VECTOR_EXCEPTION ! 36 + VECTOR_EXCEPTION ! 36 cp disabled VECTOR_EXCEPTION ! 37 VECTOR_EXCEPTION ! 38 VECTOR_EXCEPTION ! 39 - .rept 216 ! 40-255 is 216 of them + .rept 88 ! 40-127 is 88 of them + VECTOR_EXCEPTION ! whichever + .endr + + VECTOR_SYSCALL 0x80 syscall ! 128 syscall + + .rept 127 ! 129-255 is 127 of them VECTOR_EXCEPTION ! whichever .endr + + #endif // CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//_______________________________________________ #ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING real_vector: + rd %tbr, %l3 +real_vector_reset: + rd %psr, %l0 ! here,locals have been set up as follows: ! %l0 = psr ! %l1 = pc @@ -220,6 +262,8 @@ and %l3, 0x0f0, %l4 ! get an interrupt number out srl %l4, 2, %l5 ! to a word address offset #endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//'''''''''''''''''''''''''''''''''''''''''''''''''' + __entry_interrupt: sethi %hi(hal_vsr_table), %l6 or %l6, %lo(hal_vsr_table), %l6 @@ -229,6 +273,7 @@ ! interrupts and exceptions/traps ! have the same API to VSRs +//_______________________________________________ #ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING not_an_interrupt: and %l3, TT_MASK, %l4 @@ -249,10 +294,16 @@ ! the following instructions delay enough; no need for NOPs rd %wim, %l0 ! get the wim #endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//'''''''''''''''''''''''''''''''''''''''''''''''''' + __entry_wunder: sll %l0, 1, %l3 ! Rotate wim left srl %l0, __WINSIZE-1, %l0 +#if __WINSIZE > 3 wr %l0, %l3, %wim ! Install the new wim +#else + wr %g0, %g0, %wim ! we need 2 windows for save,save +#endif #ifdef DELAYS_AFTER_WRWIM nop ! are these delays needed? @@ -275,13 +326,24 @@ save ! Back to trap window save +#if __WINSIZE <= 3 + wr %l0, %l3, %wim ! Install the new wim (current) +#ifdef DELAYS_AFTER_WRWIM + nop ! are these delays needed? + nop ! + nop +#endif +#endif + jmp %l1 rett %l2 +//_______________________________________________ #ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + .global not_window_underflow not_window_underflow: bne,a not_window_overflow - srl %l4, 4, %l4 ! (if taken) + cmp %l4, (TRAP_FPDIS << TT_SHL) ! (if taken) ! here be the window overflow handler: window_overflow: @@ -294,6 +356,8 @@ ! the following instructions delay enough; no need for NOPs rd %wim, %l0 #endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//'''''''''''''''''''''''''''''''''''''''''''''''''' + __entry_wover: mov %g1, %l3 ! Save g1, we use it to hold the wim srl %l0, 1, %g1 ! Rotate wim right @@ -320,12 +384,157 @@ jmpl %l1, %g0 rett %l2 +//_______________________________________________ +#ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + .global not_window_overflow +not_window_overflow: + bne,a not_fpdis + cmp %l4, (0x80 << TT_SHL) ! (if taken) + + ! here be the entryfpdis handler: +entryfpdis: + wr %l0, %psr + nop + nop + nop + ba __entry_fpdis + nop +#endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//'''''''''''''''''''''''''''''''''''''''''''''''''' + +#ifndef CYGPKG_HAL_SMP_CPU_MAX +#define CYGPKG_HAL_SMP_CPU_MAX 1 +#endif + + .data + .global cyg_hal_fpustate_owner +cyg_hal_fpustate_owner: + .long 0 ! pointer to FPU owning context + .global cyg_hal_fpustate_current +cyg_hal_fpustate_current: + .long 0 ! pointer to current threads FPU context + + .section ".vectors","ax" + + .global __entry_fpdis +__entry_fpdis: + +#ifndef CYGHWR_HAL_SPARC_FPU + ta 0 + nop +#else +#ifndef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set 0x1000,%l3 + or %l0,%l3,%l0 + wr %l3,0, %psr ! restore the condition flags, enable fpu + nop + nop + nop + jmpl %l1, %g0 + rett %l2 +#else + set 0x1000,%l3 + or %l0,%l3,%l0 + or %l0,0xf00, %l3 ! PIL up to 15, enable fpu + wr %l3,0, %psr ! restore the condition flags, enable fpu + nop + nop + nop + + set cyg_hal_fpustate_current,%l4 + ld [%l4],%l4 + set cyg_hal_fpustate_owner,%l5 + ld [%l5],%l5 + cmp %l4,%l5 + beq mpfnostore + nop + cmp %g0,%l5 + beq mpfstore + nop + + std %f0, [%l5 + 0x00] + std %f2, [%l5 + 0x08] + std %f4, [%l5 + 0x10] + std %f6, [%l5 + 0x18] + std %f8, [%l5 + 0x20] + std %f10, [%l5 + 0x28] + std %f12, [%l5 + 0x30] + std %f14, [%l5 + 0x38] + std %f16, [%l5 + 0x40] + std %f18, [%l5 + 0x48] + std %f20, [%l5 + 0x50] + std %f22, [%l5 + 0x58] + std %f24, [%l5 + 0x60] + std %f26, [%l5 + 0x68] + std %f28, [%l5 + 0x70] + std %f30, [%l5 + 0x78] + + st %fsr, [%l5 + 0x80] + +mpfstore: + set cyg_hal_fpustate_owner,%l6 + st %l4,[%l6] + cmp %g0,%l4 + beq mpfnostore + nop + + ldd [%l4 + 0x00], %f0 + ldd [%l4 + 0x08], %f2 + ldd [%l4 + 0x10], %f4 + ldd [%l4 + 0x18], %f6 + ldd [%l4 + 0x20], %f8 + ldd [%l4 + 0x28], %f10 + ldd [%l4 + 0x30], %f12 + ldd [%l4 + 0x38], %f14 + ldd [%l4 + 0x40], %f16 + ldd [%l4 + 0x48], %f18 + ldd [%l4 + 0x50], %f20 + ldd [%l4 + 0x58], %f22 + ldd [%l4 + 0x60], %f24 + ldd [%l4 + 0x68], %f26 + ldd [%l4 + 0x70], %f28 + ldd [%l4 + 0x78], %f30 + + !ld [%l4 + 0x80], %fsr +#ifdef GRFPU_NON_STD + ld [%l4 + 0x80], %l5 + set 0x00400000, %l6 + or %l5, %l6, %l5 + st %l5, [%l4 + 0x80] +#endif + ld [%l4 + 0x80], %fsr + +mpfnostore: + wr %l0,0, %psr ! restore the condition flags, enable fpu + nop + nop + nop + + jmpl %l1, %g0 + rett %l2 +#endif +#endif + +//_______________________________________________ +#ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + .global not_fpdis +not_fpdis: + beq,a syscall + srl %l4,TT_SHL, %l3 ! (if taken) + + cmp %l4, (0x0 << TT_SHL) + beq genuine_reset + + srl %l4, 4, %l4 +#endif // CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +//'''''''''''''''''''''''''''''''''''''''''''''''''' + #ifdef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING // ADDITIONAL code to provide an entry point: __entry_exception: srl %l4, 4, %l4 #endif // CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING -not_window_overflow: +not_exception: ! from here on in, %l4 is the trap number in clear cmp %l4, 128 bge 1f @@ -356,7 +565,7 @@ ! and that is the end of the pre-vector trap handler - .global rom_vectors_end + .global rom_vectors_end, real_vector_instructions rom_vectors_end: ! these instructions are copied into the reset vector @@ -366,27 +575,145 @@ rd %psr, %l0 + .global reset_vector +reset_vector: + + ! .global start + .global start_ecos + /* ------- */ + .weak start + .set start,start_ecos + +start_ecos: +#ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + mov %g0,%l3 + b real_vector_reset + nop +#else + b trap_table + nop +#endif ! genuine reset code called from time zero: genuine_reset: ! set psr, mask interrupts & traps - sethi %hi(reset_vector), %g1 + sub %sp, 24 * 4, %fp ! fresh frame including + ! arg spill area for callees + mov %fp,%g5 ! save sp,fp + mov %sp,%g6 + sethi %hi(trap_table), %g1 andn %g1, 0xfff, %g1 ! should not be needed - wr %g1, %tbr ! Traps are at reset_vector - wr %g0, 0xfc0 + __WIN_INIT, %psr ! mode = prevMode = S, CWP=7 + wr %g1, %tbr ! Traps are at trap_table +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set 0x01fc0 + __WIN_INIT, %g1 +#else + set 0x0fc0 + __WIN_INIT, %g1 +#endif + wr %g0, %g1, %psr ! mode = prevMode = S, CWP=7 + !wr %g0, 0xfc0 + __WIN_INIT, %psr ! mode = prevMode = S, CWP=7 wr %g0, 0, %wim ! No invalid windows (yet) -#ifdef CYGHWR_HAL_SPARC_HAS_ASR17 -#ifdef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING - wr %g0, 0, %asr17 ! Multiple vector trapping + nop + nop + nop + mov %g5,%fp ! restore sp,fp after psr write + mov %g6,%sp + +#ifdef CYGPKG_HAL_SPARC_LEON3 +/*__sparc_leon3_cache_flush:*/ +#define ASI_LEON3_IFLUSH 0x11 +#define ASI_LEON3_DFLUSH 0x11 + sta %g0, [%g0] ASI_LEON3_IFLUSH + sta %g0, [%g0] ASI_LEON3_DFLUSH #else - wr %g0, 1, %asr17 ! Single vector trapping -#endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING -#endif // CYGHWR_HAL_SPARC_HAS_ASR17 +/*__sparc_leon2_cache_flush:*/ +#define ASI_LEON2_IFLUSH 0x05 +#define ASI_LEON2_DFLUSH 0x06 + sta %g0, [%g0] ASI_LEON2_IFLUSH + sta %g0, [%g0] ASI_LEON2_DFLUSH +#endif + +#ifndef CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING + set 1<<13,%g1 ! Single vector trapping, Leon3: asr17.bit13==1 + rd %asr17,%g2 + or %g1,%g2,%g2 + wr %g2,%asr17 + nop nop nop + .global single_vector_trapping_not_active +single_vector_trapping_not_active: + rd %asr17,%g2 !you have to enable Single Vector Trapping in the vhdl model + andcc %g2,%g1,%g2 !you have to enable Single Vector Trapping in the vhdl model + be single_vector_trapping_not_active !you have to enable Single Vector Trapping in the vhdl model nop +#endif // !CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING // INCLUDE PLATFORM BOOT +#ifdef CYGPKG_HAL_SMP_SUPPORT + + !smp dbg + !set 0x800000, %g2 + lda [%g0] 2, %g1 ! cache cfg + set 0x800000, %g2 ! snoop enable + or %g2,%g1,%g2 + + !set 0x800000, %g2 ! snooping,disable cache for test + + sta %g2, [%g0] 2 ! cache cfg + + rd %asr17,%g2 + srl %g2,28,%g2 + + ! trap all cpu's except cpu nr 0 +haltsmp: + cmp %g2,%g0 + beq mastergo + nop + + + ! slaves cpus will idle until master cpu (0) will issue a + ! mctrl->mpstatus write to wake them up. They will here branch to + ! cyg_hal_smp_start then + +cyg_hal_smp_start: + ! master called + + sethi %hi(trap_table), %g1 + wr %g1, %tbr ! Traps are at reset_vector + nop + nop + nop + + hal_smp_cpu %fp + sll %fp,2,%fp + set __interrupt_stack_vector,%i0 + ld [%i0+%fp], %fp + + sub %fp, 16 * 4, %sp ! Stack pointer + +#if (__WINSIZE == 2) + wr %g0, 0, %wim ! 2 windows +#else + wr %g0, __WIM_INIT, %wim ! Window 7 (current) is invalid +#endif + + nop + nop + nop + wr %g0, 0xfe0 + __WIN_INIT, %psr + nop ! Enable traps: + nop ! set psr, _do_ mask interrupts + nop ! mode = prevMode = S, CWP=7 + + + call cyg_hal_smp_startup + nop + + +mastergo: + +#endif + // This should set up RAM and caches, and calm down any external interrupt // sources. Also copy two instructions from real_vector_instructions // into reset_vector, then invalidate the instruction cache. @@ -396,18 +723,21 @@ // halboot.si returns with %sp all set, in sleb versions. // (though we override if there is an interrupt stack) - led 0x80 - ! now set up a stack and initial frame linkage ! so as to be able to make C function calls: ! current window is 7, the highest, so we store a ! saved frame thingy that refers to itself in the stack, ! then another which is valid and drop into main from there. -#ifdef BOOTUPSTACK_IS_INTERRUPTSTACK - sethi %hi(cyg_interrupt_stack), %i6 - or %i6, %lo(cyg_interrupt_stack), %i6 + set cyg_hal_stack_top,%i0 + st %fp,[%i0] + + set cyg_interrupt_stack,%fp +#ifdef CYGPKG_HAL_SMP_SUPPORT + set __interrupt_stack_vector,%i0 + st %fp,[%i0] #endif + andn %i6, 7, %i6 ! round fp down to double alignment mov 0, %i7 ! null return address sethi %hi(0xb51ac000), %i0 ! "BStac" pattern @@ -430,22 +760,16 @@ sub %fp, 16 * 4, %sp ! Stack pointer - led 0x90 - std %l0, [%sp + 0 * 4] ! save L & I registers std %l2, [%sp + 2 * 4] ! into new stack frame std %l4, [%sp + 4 * 4] std %l6, [%sp + 6 * 4] - led 0x91 - std %i0, [%sp + 8 * 4] std %i2, [%sp + 10 * 4] std %i4, [%sp + 12 * 4] std %i6, [%sp + 14 * 4] - led 0x92 - sethi %hi(0xb0010000), %o0 ! "Boot" pattern or %o0, 8, %o0 or %o0, 1, %o1 @@ -454,15 +778,15 @@ or %o0, 4, %o4 or %o0, 5, %o5 - led 0x98 - +#if (__WINSIZE == 2) + wr %g0, 0, %wim ! 2 windows +#else wr %g0, __WIM_INIT, %wim ! Window 7 (current) is invalid +#endif nop nop nop - led 0x99 - sethi %hi(0xb0010000), %g1 ! "Boot" pattern or %g1, 2, %g2 or %g1, 3, %g3 @@ -472,30 +796,94 @@ or %g1, 7, %g7 or %g1, 1, %g1 - led 0xa0 - - wr %g0, 0xfe0 + __WIN_INIT, %psr +#ifdef CYGPKG_HAL_SPARC_LAZY_FPU_SWITCH + set 0x0fe0 + __WIN_INIT, %g2 +#else + set 0x1fe0 + __WIN_INIT, %g2 +#endif + wr %g0, %g2, %psr + or %g1, 2, %g2 + !wr %g0, 0x1fe0 + __WIN_INIT, %psr nop ! Enable traps: nop ! set psr, _do_ mask interrupts nop ! mode = prevMode = S, CWP=7 - led 0xb0 + +#if defined(CYGHWR_HAL_SPARC_FLAT) + save %sp, -24 * 4, %sp ! get valid window +#endif ! now we can start calling out and running C code! .extern cyg_hal_start call cyg_hal_start ! puts return address in %o7 or %g1, 1, %g1 +#ifdef CYGPKG_HAL_SMP_SUPPORT + .extern cyg_hal_smp_init + call cyg_hal_smp_init + nop +#endif + + call cyg_start /* does not return */ + nop + + loop_forever: ta 1 b loop_forever ! if it returns nop +#define SYM(n) n +#define PUBLIC(n) .globl SYM(n) + + /* + * system call + * + * On entry: + * + * l0 = psr (from trap table) + * l1 = pc + * l2 = npc + * i0 = system call id + */ + + PUBLIC(syscall) + +SYM(syscall): + + subcc %i0, 2, %g0 ! syscall 2, disable interrupts + bne 3f + or %l0, 0x0f00, %l4 ! set PIL=15 + mov %l4, %psr + or %l0, SPARC_PSR_ET_MASK, %i0 ! return old psr with ET=1 + ba,a 9f +3: + subcc %i0, 3, %g0 ! syscall 3, enable interrupts + bne 1f + and %i1, SPARC_PSR_PIL_MASK, %l4 + andn %l0, SPARC_PSR_PIL_MASK, %l5 + or %l5, %l4, %l4 + mov %l4, %psr + ba,a 9f + +1: + ta 0 ! halt +9: ! leave + jmpl %l2, %g0 + rett %l2 + 4 + + !--------------------------------------------------------------------------- ! hal_vsr_table... .section ".data" + + .balign 4 + .global cyg_hal_stack_top +cyg_hal_stack_top: !avoid .bss (clear) + .long 0x100000 + .balign 4 .global hal_vsr_table hal_vsr_table: @@ -509,12 +897,18 @@ !--------------------------------------------------------------------------- ! Bootup stack (only needed explicitly in sim) -#ifdef BOOTUPSTACK_IS_INTERRUPTSTACK +#if defined(BOOTUPSTACK_IS_INTERRUPTSTACK) || \ + defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK) + .section ".bss" + +#ifndef CYGPKG_HAL_SMP_SUPPORT + #ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE #define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096 #endif + .balign 16 .global cyg_interrupt_stack_base cyg_interrupt_stack_base: @@ -525,14 +919,41 @@ .global cyg_interrupt_stack cyg_interrupt_stack: .long 0,0,0,0,0,0,0,0 ! here be secret state stored + +#else + .global __interrupt_stack_vector +__interrupt_stack_vector: + .rept CYGPKG_HAL_SMP_CPU_MAX + .long 0 + .endr + + .balign 16 + .global cyg_interrupt_stack_base, __interrupt_stack_first +cyg_interrupt_stack_base: +__interrupt_stack_base: +__interrupt_stack_first: + .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE + .byte 0 + .endr + .balign 16 + .global cyg_interrupt_stack +cyg_interrupt_stack: +__interrupt_stack: + .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE*(CYGPKG_HAL_SMP_CPU_MAX-1) + .byte 0 + .endr + .long 0,0,0,0,0,0,0,0 ! here be secret state stored + +#endif + #endif !------------------------------------------------------------------------ ! Define a section that reserves space at the start of RAM for the ! vectors to be copied into, for ROM start only. - .section ".ram_vectors","awx",@nobits #ifdef CYGIMP_HAL_SPARC_COPY_VECTORS_TO_RAM + .section ".ram_vectors","awx",@nobits ! need a space at base of RAM for copied vector/trampoline code .align 0x1000 .space 8 ! for fencepost errors diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/tests/sparc_ex.c ecos-rep/packages/hal/sparc/arch/current/tests/sparc_ex.c --- ecos-cvs-2005-09-06/packages/hal/sparc/arch/current/tests/sparc_ex.c 2002-05-24 01:05:08.000000000 +0200 +++ ecos-rep/packages/hal/sparc/arch/current/tests/sparc_ex.c 2005-09-05 16:06:32.000000000 +0200 @@ -94,8 +94,8 @@ // ------------------------------------------------------------------------- // Some memory to read in more-or-less aligned manners. -#define L1 (0x123456789abcdef0l) -#define L2 (0xfedcba9876543210l) +#define L1 (0x123456789abcdef0ll) +#define L2 (0xfedcba9876543210ll) static cyg_uint64 a[ 2 ] = { L1, L2 diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/cdl/hal_sparc_erc32.cdl ecos-rep/packages/hal/sparc/erc32/current/cdl/hal_sparc_erc32.cdl --- ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/cdl/hal_sparc_erc32.cdl 2003-07-24 22:24:09.000000000 +0200 +++ ecos-rep/packages/hal/sparc/erc32/current/cdl/hal_sparc_erc32.cdl 2005-09-05 16:06:32.000000000 +0200 @@ -115,7 +115,7 @@ display "Global command prefix" flavor data no_define - default_value { "sparc-rtems" } + default_value { "sparc-elf" } description " This option specifies the command prefix used when invoking the build tools." diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/hal_xpic.h ecos-rep/packages/hal/sparc/erc32/current/include/hal_xpic.h --- ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/hal_xpic.h 2002-05-24 01:05:10.000000000 +0200 +++ ecos-rep/packages/hal/sparc/erc32/current/include/hal_xpic.h 2005-09-05 16:06:32.000000000 +0200 @@ -88,7 +88,7 @@ #define HAL_INTERRUPT_MASK( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_, _mask_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_READ_UINT32( SPARC_MEC_INTCON_MASK, _mask_ ); \ _mask_ |= ( 1 << (_vector_) ); \ HAL_WRITE_UINT32(SPARC_MEC_INTCON_MASK, _mask_ ); \ @@ -97,7 +97,7 @@ #define HAL_INTERRUPT_UNMASK( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_, _mask_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_READ_UINT32( SPARC_MEC_INTCON_MASK, _mask_ ); \ _mask_ &=~ ( 1 << (_vector_) ); \ HAL_WRITE_UINT32( SPARC_MEC_INTCON_MASK, _mask_ ); \ @@ -106,7 +106,7 @@ #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_WRITE_UINT32( SPARC_MEC_INTCON_CLEAR, ( 1 << (_vector_) ) ); \ HAL_RESTORE_INTERRUPTS( _traps_ ); \ CYG_MACRO_END diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/halboot.si ecos-rep/packages/hal/sparc/erc32/current/include/halboot.si --- ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/halboot.si 2002-05-24 01:05:10.000000000 +0200 +++ ecos-rep/packages/hal/sparc/erc32/current/include/halboot.si 2005-09-06 16:59:27.000000000 +0200 @@ -119,6 +119,8 @@ 4: + +#ifndef CYGPKG_HAL_SMP_SUPPORT ! then copy the branch instructions into the vector rd %tbr, %g1 andn %g1, 0xfff, %g1 ! clear non-address bits @@ -128,6 +130,7 @@ st %l1, [ %g1 ] ! into the vector ld [ %l0 + 4 ], %l1 st %l1, [ %g1 + 4 ] ! into the vector +#endif #endif /* CYGONCE_HAL_HALBOOT_SI */ /* EOF halboot.si */ diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/pkgconf/mlt_sparc_erc32_ram.ldi ecos-rep/packages/hal/sparc/erc32/current/include/pkgconf/mlt_sparc_erc32_ram.ldi --- ecos-cvs-2005-09-06/packages/hal/sparc/erc32/current/include/pkgconf/mlt_sparc_erc32_ram.ldi 2002-05-21 00:24:06.000000000 +0200 +++ ecos-rep/packages/hal/sparc/erc32/current/include/pkgconf/mlt_sparc_erc32_ram.ldi 2005-11-07 16:37:18.000000000 +0100 @@ -20,7 +20,7 @@ SECTION_fixup (ram, ALIGN (0x1), LMA_EQ_VMA) SECTION_gcc_except_table (ram, ALIGN (0x1), LMA_EQ_VMA) SECTION_data (ram, ALIGN (0x1), LMA_EQ_VMA) - SECTION_bss (ram, ALIGN (0x8), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x8) (NOLOAD), LMA_EQ_VMA) CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); SECTIONS_END } diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/cdl/hal_sparc_leon.cdl ecos-rep/packages/hal/sparc/leon/current/cdl/hal_sparc_leon.cdl --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/cdl/hal_sparc_leon.cdl 2003-07-24 22:24:10.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/cdl/hal_sparc_leon.cdl 2006-06-19 19:00:28.000000000 +0200 @@ -101,6 +101,7 @@ } } + cdl_component CYGBLD_GLOBAL_OPTIONS { display "Global build options" flavor none @@ -115,17 +116,17 @@ display "Global command prefix" flavor data no_define - default_value { "sparc-rtems" } + default_value { "sparc-elf" } description " This option specifies the command prefix used when invoking the build tools." } - cdl_option CYGBLD_GLOBAL_CFLAGS { + cdl_option CYGBLD_GLOBAL_CFLAGS_PRE { display "Global compiler flags" flavor data no_define - default_value { "-msoft-float -Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } description " This option controls the global compiler flags which are used to compile all packages by @@ -133,15 +134,41 @@ options which override these global flags." } - cdl_option CYGBLD_GLOBAL_LDFLAGS { + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Final Global compiler flags" + flavor data + no_define + calculated { + CYGHWR_HAL_SPARC_FPU ? + get_data(CYGBLD_GLOBAL_CFLAGS_PRE) : + "-msoft-float ".get_data(CYGBLD_GLOBAL_CFLAGS_PRE)} + description " + This option append -msoft-float to CFLAGS if no + fpu is present " + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS_PRE { display "Global linker flags" flavor data no_define - default_value { "-msoft-float -g -nostdlib -Wl,--gc-sections -Wl,-static" } + default_value { "-g -nostdlib -fvtable-gc -Wl,--gc-sections -Wl,-static" } description " This option controls the global linker flags. Individual packages may define options which override these global flags." } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Final Global linker flags" + flavor data + no_define + calculated { + CYGHWR_HAL_SPARC_FPU ? + get_data(CYGBLD_GLOBAL_LDFLAGS_PRE) : + "-msoft-float ".get_data(CYGBLD_GLOBAL_LDFLAGS_PRE)} + description " + This option append -msoft-float to LDFLAGS if no + fpu is present " + } } cdl_component CYGPKG_HAL_SPARC_LEON_OPTIONS { diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/hal_xpic.h ecos-rep/packages/hal/sparc/leon/current/include/hal_xpic.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/hal_xpic.h 2002-05-24 01:05:12.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/include/hal_xpic.h 2005-09-06 16:59:27.000000000 +0200 @@ -87,7 +87,7 @@ #define HAL_INTERRUPT_MASK( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_, _mask_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_READ_UINT32( SPARC_LEON_INTCON_MASK, _mask_ ); \ _mask_ &= ~( 1 << (_vector_) ); \ HAL_WRITE_UINT32(SPARC_LEON_INTCON_MASK, _mask_ ); \ @@ -96,7 +96,7 @@ #define HAL_INTERRUPT_UNMASK( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_, _mask_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_READ_UINT32( SPARC_LEON_INTCON_MASK, _mask_ ); \ _mask_ |= ( 1 << (_vector_) ); \ HAL_WRITE_UINT32( SPARC_LEON_INTCON_MASK, _mask_ ); \ @@ -107,7 +107,7 @@ /* Interrupts are automatically acknowledged by hardware, not needed ... #define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) CYG_MACRO_START \ cyg_uint32 _traps_; \ - HAL_DISABLE_TRAPS( _traps_ ); \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ HAL_WRITE_UINT32( SPARC_LEON_INTCON_CLEAR, ( 1 << (_vector_) ) ); \ HAL_RESTORE_INTERRUPTS( _traps_ ); \ CYG_MACRO_END diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.h ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.h 2002-05-21 00:24:06.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.h 2005-09-05 16:06:32.000000000 +0200 @@ -8,12 +8,12 @@ #endif #define CYGMEM_REGION_ram (0x40000000) -#define CYGMEM_REGION_ram_SIZE (0x80000) +#define CYGMEM_REGION_ram_SIZE (0x100000) #define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) #ifndef __ASSEMBLER__ extern char CYG_LABEL_NAME (__heap1) []; #endif #define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) -#define CYGMEM_SECTION_heap1_SIZE (0x40080000 - (size_t) CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x40100000 - (size_t) CYG_LABEL_NAME (__heap1)) #define CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.ldi ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.ldi --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.ldi 2002-05-21 00:24:06.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.ldi 2005-11-07 16:37:18.000000000 +0100 @@ -6,7 +6,7 @@ MEMORY { - ram : ORIGIN = 0x40000000, LENGTH = 0x80000 + ram : ORIGIN = 0x40000000, LENGTH = 0x40000000 } SECTIONS @@ -20,7 +20,7 @@ SECTION_fixup (ram, ALIGN (0x1), LMA_EQ_VMA) SECTION_gcc_except_table (ram, ALIGN (0x1), LMA_EQ_VMA) SECTION_data (ram, ALIGN (0x1), LMA_EQ_VMA) - SECTION_bss (ram, ALIGN (0x8), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x8) (NOLOAD), LMA_EQ_VMA) CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); SECTIONS_END } diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.mlt ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.mlt --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.mlt 2002-05-21 00:24:06.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/include/pkgconf/mlt_sparc_leon_ram.mlt 2005-09-05 16:06:32.000000000 +0200 @@ -1,5 +1,5 @@ version 0 -region ram 40000000 80000 0 ! +region ram 40000000 40000000 0 ! section rom_vectors 0 1 0 1 1 1 1 1 40000000 40000000 text text ! section text 0 1 0 1 0 1 0 1 fini fini ! section fini 0 1 0 1 0 1 0 1 rodata rodata ! diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/src/hal_priv.c ecos-rep/packages/hal/sparc/leon/current/src/hal_priv.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon/current/src/hal_priv.c 2002-05-24 01:05:12.000000000 +0200 +++ ecos-rep/packages/hal/sparc/leon/current/src/hal_priv.c 2005-09-05 16:06:32.000000000 +0200 @@ -63,8 +63,20 @@ extern void hal_board_prestart( void ); extern void hal_board_poststart( void ); +static leon2_eth_init() +{ + *((volatile cyg_uint32 *) 0x80000000) |= 0x10f80000; + *((volatile cyg_uint32 *) 0x800000A8) |= +// (0xe0 | CYGNUM_DEVS_ETH_SPARC_LEON_IRQ_PIO) << (8*(CYGNUM_DEVS_ETH_SPARC_LEON_IRQ-4)); + (0xe0 | 4) << (8*(4-4)); +} + + void hal_board_prestart( void ) { +//#ifdef CYGPKG_DEVS_ETH_SPARC_LEON + leon2_eth_init(); +//#endif } void hal_board_poststart( void ) diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/ChangeLog ecos-rep/packages/hal/sparc/leon3/current/ChangeLog --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/ChangeLog 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/ChangeLog 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,54 @@ +2002-10-19 Jonathan Larmour + + Patch from Jiri Gaisler: + * cdl/hal_sparc_leon.cdl: -msoft-float needn't be used in local package + since it's defined globally. + * include/hal_diag.h: Fix UART TX mask. + +2002-03-15 Hugo Tyson + + * cdl/hal_sparc_leon.cdl: Add -msoft-cloat to CYGBLD_GLOBAL_CFLAGS + (as well as LDFLAGS) - this gives perfect test coverage in minimal + build with the sim. NB pro tem the tools are called + sparc-rtems-gcc et al, but sparc-elf-gcc et al should be OK. + +2002-03-14 Jiri Gaisler + + * Initial version based on the SPARClite SIM HAL. + +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== + +//EOF ChangeLog diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/cdl/hal_sparc_leon3.cdl ecos-rep/packages/hal/sparc/leon3/current/cdl/hal_sparc_leon3.cdl --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/cdl/hal_sparc_leon3.cdl 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/cdl/hal_sparc_leon3.cdl 2006-06-19 19:00:28.000000000 +0200 @@ -0,0 +1,242 @@ +# ==================================================================== +# +# hal_sparc_leon.cdl +# +# SPARC LEON target HAL package configuration data +# +# ==================================================================== +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +# ==================================================================== +######DESCRIPTIONBEGIN#### +# +# Author(s): jskov +# Original data: hmt +# Contributors: +# Date: 2000-02-10 +# +#####DESCRIPTIONEND#### +# +# ==================================================================== + +cdl_package CYGPKG_HAL_SPARC_LEON3 { + display "Grlib's LEON3 processor" + parent CYGPKG_HAL_SPARC + define_header hal_sparc_leon3.h + include_dir cyg/hal + description " + Grlib's LEON3 processor HAL package is provided for use + with both real hardware and the Grmon simulator." + + compile hal_priv.c boot.S hal_amba.c hal_amba_driver.c hal_diag.c hal_clock.c hal_irq.c + compile leon3_smp.c boot_smp.S hal_help.cxx + + define_proc { + puts $::cdl_system_header "#define CYGBLD_HAL_TARGET_H " + puts $::cdl_system_header "#define CYGBLD_HAL_PLATFORM_H " + puts $::cdl_header "//#define CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING /* true for LEON3 */" + puts $::cdl_header "#define CYGHWR_HAL_SPARC_HAS_ASR17 /* true for LEON3 */" + puts $::cdl_header "#define HAL_IDLE_THREAD_ACTION hal_idle_thread_action /* true for LEON3 */" + } + + cdl_component CYG_HAL_STARTUP { + display "Startup type" + flavor data + legal_values {"RAM"} + default_value {"RAM"} + no_define + define -file system.h CYG_HAL_STARTUP + description " + When targetting the LEON3 processor only the RAM startup type + is usable." + } + + # Real-time clock/counter specifics + cdl_component CYGNUM_HAL_RTC_CONSTANTS { + display "Real-time clock constants." + flavor none + + cdl_option CYGNUM_HAL_RTC_NUMERATOR { + display "Real-time clock numerator" + flavor data + calculated 1000000000 + } + cdl_option CYGNUM_HAL_RTC_DENOMINATOR { + display "Real-time clock denominator" + flavor data + calculated 100 + } + cdl_option CYGNUM_HAL_RTC_PERIOD { + display "Real-time clock period" + flavor data + calculated 9999 + } + } + + cdl_component CYGBLD_GLOBAL_OPTIONS { + display "Global build options" + flavor none + description " + Global build options including control over + compiler flags, linker flags and choice of toolchain." + + + parent CYGPKG_NONE + + cdl_option CYGBLD_GLOBAL_COMMAND_PREFIX { + display "Global command prefix" + flavor data + no_define + default_value { "sparc-elf" } + description " + This option specifies the command prefix used when + invoking the build tools." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS_PRE { + display "Global compiler flags" + flavor data + no_define + default_value { "-Wall -Wpointer-arith -Wstrict-prototypes -Winline -Wundef -Woverloaded-virtual -g -O2 -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fvtable-gc -finit-priority" } + description " + This option controls the global compiler flags which + are used to compile all packages by + default. Individual packages may define + options which override these global flags." + } + + cdl_option CYGBLD_GLOBAL_CFLAGS { + display "Final Global compiler flags" + flavor data + no_define + calculated { + (CYGHWR_HAL_SPARC_FLAT ? " -mflat " : " ") . + (CYGHWR_HAL_SPARC_FPU ? get_data(CYGBLD_GLOBAL_CFLAGS_PRE) : "-msoft-float ".get_data(CYGBLD_GLOBAL_CFLAGS_PRE) ) } + description " + This option append -msoft-float to CFLAGS if no + fpu is present " + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS_PRE { + display "Global linker flags" + flavor data + no_define + default_value { "-g -nostdlib -fvtable-gc -Wl,--gc-sections -Wl,-static" } + description " + This option controls the global linker flags. Individual + packages may define options which override these global flags." + } + + cdl_option CYGBLD_GLOBAL_LDFLAGS { + display "Final Global linker flags" + flavor data + no_define + calculated { + (CYGHWR_HAL_SPARC_FLAT ? " -mflat " : " ") . + (CYGHWR_HAL_SPARC_FPU ? get_data(CYGBLD_GLOBAL_LDFLAGS_PRE) : "-msoft-float ".get_data(CYGBLD_GLOBAL_LDFLAGS_PRE)) } + description " + This option append -msoft-float to LDFLAGS if no + fpu is present " + } + } + + cdl_option CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING { + display "Multiple vector trapping (MVT)" + default_value 1 + description " + Use Multiple Vector Trapping (MVT) rather than Single Vector + Trapping (SVT); SVT is a feature of SPARClite CPUs which saves + code RAM at a cost of perhaps slower interrupt and trap dispatch + time, depending on cache behavior. This includes speed of + handling register window underflow and overflow, a feature of + deep function call stacks on SPARC. MVT requires 4kB of code + space for trap vectors; in contrast SVT uses fewer than 20 + instructions for trap decoding." + } + + + cdl_component CYGPKG_HAL_SPARC_LEON3_OPTIONS { + display "LEON processor build options" + flavor none + description " + Package specific build options including control over + compiler flags used only in building this package, + and details of which tests are built." + + + cdl_option CYGPKG_HAL_SPARC_LEON3_CFLAGS_ADD { + display "Additional compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the LEON processor HAL. These flags are + used in addition to the set of global flags." + } + + cdl_option CYGPKG_HAL_SPARC_LEON3_CFLAGS_REMOVE { + display "Suppressed compiler flags" + flavor data + no_define + default_value { "" } + description " + This option modifies the set of compiler flags for + building the LEON processor HAL. These flags are + removed from the set of global flags if present." + } + } + + cdl_component CYGHWR_MEMORY_LAYOUT { + display "Memory layout" + flavor data + no_define + calculated { "sparc_leon3_ram" } + + cdl_option CYGHWR_MEMORY_LAYOUT_LDI { + display "Memory layout linker script fragment" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_LDI + calculated { "" } + } + + cdl_option CYGHWR_MEMORY_LAYOUT_H { + display "Memory layout header file" + flavor data + no_define + define -file system.h CYGHWR_MEMORY_LAYOUT_H + calculated { "" } + } + } +} diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_amba.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_amba.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_amba.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_amba.h 2006-01-31 19:56:12.000000000 +0100 @@ -0,0 +1,235 @@ +#ifndef CYGONCE_HAL_AMBA_H +#define CYGONCE_HAL_AMBA_H + +//============================================================================= +// +// hal_amba.h +// +// HAL AMBA defined +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele ) +// Contributors: +// Date: 2004-01-12 +// Purpose: Define Interrupt support +// Description: +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#define LEON3_IO_AREA 0xfff00000 +#define LEON3_CONF_AREA 0xff000 +#define LEON3_AHB_SLAVE_CONF_AREA (1 << 11) + +#define LEON3_AHB_CONF_WORDS 8 +#define LEON3_APB_CONF_WORDS 2 +#define LEON3_AHB_MASTERS 64 +#define LEON3_AHB_SLAVES 64 +#define LEON3_APB_SLAVES 16 +#define LEON3_APBUARTS 8 + +/* Vendor codes */ +#define VENDOR_GAISLER 1 +#define VENDOR_PENDER 2 +#define VENDOR_ESA 4 +#define VENDOR_OPENCORES 8 + +/* Gaisler Research device id's */ +#define GAISLER_LEON3 0x003 +#define GAISLER_LEON3DSU 0x004 +#define GAISLER_ETHAHB 0x005 +#define GAISLER_APBMST 0x006 +#define GAISLER_AHBUART 0x007 +#define GAISLER_SRCTRL 0x008 +#define GAISLER_SDCTRL 0x009 +#define GAISLER_APBUART 0x00C +#define GAISLER_IRQMP 0x00D +#define GAISLER_AHBRAM 0x00E +#define GAISLER_GPTIMER 0x011 +#define GAISLER_PCITRG 0x012 +#define GAISLER_PCISBRG 0x013 +#define GAISLER_PCIFBRG 0x014 +#define GAISLER_PCITRACE 0x015 +#define GAISLER_PCIDMA 0x016 +#define GAISLER_AHBTRACE 0x017 +#define GAISLER_ETHDSU 0x018 +#define GAISLER_PIOPORT 0x01A +#define GAISLER_ETHMAC 0x01D +#define GAISLER_L2TIME 0xffd /* internal device: leon2 timer */ +#define GAISLER_L2C 0xffe /* internal device: leon2compat */ +#define GAISLER_PLUGPLAY 0xfff /* internal device: plug & play configarea */ + + +#ifndef __ASSEMBLER__ + +extern inline char *gaisler_device_str(int id) { + switch(id) { + case GAISLER_LEON3: return "GAISLER_LEON3"; + case GAISLER_LEON3DSU: return "GAISLER_LEON3DSU"; + case GAISLER_ETHAHB: return "GAISLER_ETHAHB"; + case GAISLER_ETHMAC: return "GAISLER_ETHMAC"; + case GAISLER_APBMST: return "GAISLER_APBMST"; + case GAISLER_AHBUART: return "GAISLER_AHBUART"; + case GAISLER_SRCTRL: return "GAISLER_SRCTRL"; + case GAISLER_SDCTRL: return "GAISLER_SDCTRL"; + case GAISLER_APBUART: return "GAISLER_APBUART"; + case GAISLER_IRQMP: return "GAISLER_IRQMP"; + case GAISLER_AHBRAM: return "GAISLER_AHBRAM"; + case GAISLER_GPTIMER: return "GAISLER_GPTIMER"; + case GAISLER_PCITRG: return "GAISLER_PCITRG"; + case GAISLER_PCISBRG: return "GAISLER_PCISBRG"; + case GAISLER_PCIFBRG: return "GAISLER_PCIFBRG"; + case GAISLER_PCITRACE: return "GAISLER_PCITRACE"; + case GAISLER_AHBTRACE: return "GAISLER_AHBTRACE"; + case GAISLER_ETHDSU: return "GAISLER_ETHDSU"; + case GAISLER_PIOPORT: return "GAISLER_PIOPORT"; + + case GAISLER_L2TIME: return "GAISLER_L2TIME"; + case GAISLER_L2C: return "GAISLER_L2C"; + case GAISLER_PLUGPLAY: return "GAISLER_PLUGPLAY"; + + default: break; + } + return 0; +} + +#endif + +/* European Space Agency device id's */ +#define ESA_LEON2 0x2 +#define ESA_MCTRL 0xF + + +#ifndef __ASSEMBLER__ + +extern inline char *esa_device_str(int id) { + switch(id) { + case ESA_LEON2: return "ESA_LEON2"; + case ESA_MCTRL: return "ESA_MCTRL"; + default: break; + } + return 0; +} + +#endif + +/* Opencores device id's */ +#define OPENCORES_PCIBR 0x4 +#define OPENCORES_ETHMAC 0x5 + + +#ifndef __ASSEMBLER__ + +extern inline char *opencores_device_str(int id) { + switch(id) { + case OPENCORES_PCIBR: return "OPENCORES_PCIBR"; + case OPENCORES_ETHMAC: return "OPENCORES_ETHMAC"; + default: break; + } + return 0; +} + +extern inline char *device_id2str(int vendor, int id) { + switch(vendor) { + case VENDOR_GAISLER: return gaisler_device_str(id); + case VENDOR_ESA: return esa_device_str(id); + case VENDOR_OPENCORES: return opencores_device_str(id); + case VENDOR_PENDER: + default: break; + } + return 0; +} + +extern inline char *vendor_id2str(int vendor) { + switch(vendor) { + case VENDOR_GAISLER: return "VENDOR_GAISLER"; + case VENDOR_ESA: return "VENDOR_ESA"; + case VENDOR_OPENCORES: return "VENDOR_OPENCORES"; + case VENDOR_PENDER: return "VENDOR_PENDER"; + default: break; + } + return 0; +} + +#endif + +/* Vendor codes */ + + + +/* + * + * Macros for manipulating Configuration registers + * + */ + +#define LEON3_BYPASS_LOAD_PA(x) ((unsigned long)*((volatile unsigned long*)(x))) +#define LEON3_BYPASS_STORE_PA(x,v) (*((volatile unsigned long*)(x)) = (unsigned long)(v)) + +#define amba_get_confword(tab, index, word) (LEON3_BYPASS_LOAD_PA((tab).addr[(index)]+(word))) + +#define amba_vendor(x) (((x) >> 24) & 0xff) + +#define amba_device(x) (((x) >> 12) & 0xfff) + +#define amba_ahb_get_membar(tab, index, nr) (LEON3_BYPASS_LOAD_PA((tab).addr[(index)]+4+(nr))) + +#define amba_apb_get_membar(tab, index) (LEON3_BYPASS_LOAD_PA((tab).addr[(index)]+1)) + +#define amba_membar_start(mbar) (((mbar) & 0xfff00000) & (((mbar) & 0xfff0) << 16)) + +#define amba_iobar_start(base, iobar) ((base) | ((((iobar) & 0xfff00000)>>12) & (((iobar) & 0xfff0)<<4)) ) + +#define amba_irq(conf) ((conf) & 0xf) + +#define amba_membar_type(mbar) ((mbar) & 0xf) + +#define AMBA_TYPE_APBIO 0x1 +#define AMBA_TYPE_MEM 0x2 +#define AMBA_TYPE_AHBIO 0x3 + +#define AMBA_TYPE_AHBIO_ADDR(addr) (LEON3_IO_AREA | ((addr) >> 12)) + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_AMBA_H +// End of hal_amba.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_cache.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_cache.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_cache.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_cache.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,214 @@ +#ifndef CYGONCE_HAL_CACHE_H +#define CYGONCE_HAL_CACHE_H + +//============================================================================= +// +// hal_cache.h +// +// HAL Cache control support (such as it is in the simulator) +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, gthomas, hmt +// Contributors: nickg, gthomas, hmt +// Date: 1999-01-28 +// Purpose: Define Interrupt support +// Description: The macros defined here provide the HAL APIs for handling +// the caches. +// +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +#include + +//----------------------------------------------------------------------------- +// LEON cache macros + +//----------------------------------------------------------------------------- +// Cache dimensions + +// Data cache +#define HAL_DCACHE_SIZE 0x4000 // Size of data cache in bytes +#define HAL_DCACHE_LINE_SIZE 16 // Size of a data cache line +#define HAL_DCACHE_WAYS 1 // Associativity of the cache + +// Instruction cache +#define HAL_ICACHE_SIZE 0x4000 // Size of cache in bytes +#define HAL_ICACHE_LINE_SIZE 16 // Size of a cache line +#define HAL_ICACHE_WAYS 1 // Associativity of the cache + +#define HAL_DCACHE_SETS (HAL_DCACHE_SIZE/(HAL_DCACHE_LINE_SIZE*HAL_DCACHE_WAYS)) +#define HAL_ICACHE_SETS (HAL_ICACHE_SIZE/(HAL_ICACHE_LINE_SIZE*HAL_ICACHE_WAYS)) + +//----------------------------------------------------------------------------- +// Global control of data cache + +// Enable the data cache +#define HAL_DCACHE_ENABLE() +// Disable the data cache +#define HAL_DCACHE_DISABLE() +// Invalidate the entire cache +#define HAL_DCACHE_INVALIDATE_ALL() __asm__ __volatile__(" flush "); \ + __asm__ __volatile__("sta %%g0, [%%g0] %0\n\t": : \ + "i" (ASI_LEON3_DFLUSH) : "memory"); +// Synchronize the contents of the cache with memory. +#define HAL_DCACHE_SYNC() + +// Set the data cache refill burst size +//#define HAL_DCACHE_BURST_SIZE(_size_) + +// Set the data cache write mode +//#define HAL_DCACHE_WRITE_MODE( _mode_ ) + +//#define HAL_DCACHE_WRITETHRU_MODE 0 +//#define HAL_DCACHE_WRITEBACK_MODE 1 + +// Load the contents of the given address range into the data cache +// and then lock the cache so that it stays there. +//#define HAL_DCACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_DCACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_DCACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Data cache line control + +// Allocate cache lines for the given address range without reading its +// contents from memory. +//#define HAL_DCACHE_ALLOCATE( _base_ , _size_ ) + +// Write dirty cache lines to memory and invalidate the cache entries +// for the given address range. +//#define HAL_DCACHE_FLUSH( _base_ , _size_ ) + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_DCACHE_INVALIDATE( _base_ , _size_ ) + +// Write dirty cache lines to memory for the given address range. +//#define HAL_DCACHE_STORE( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of reading +// from it later. +//#define HAL_DCACHE_READ_HINT( _base_ , _size_ ) + +// Preread the given range into the cache with the intention of writing +// to it later. +//#define HAL_DCACHE_WRITE_HINT( _base_ , _size_ ) + +// Allocate and zero the cache lines associated with the given range. +//#define HAL_DCACHE_ZERO( _base_ , _size_ ) + +//----------------------------------------------------------------------------- +// Global control of Instruction cache - use Data cache controls since they +// are not separatable. + +// Enable the instruction cache +#define HAL_ICACHE_ENABLE() HAL_DCACHE_ENABLE() + +// Disable the instruction cache +#define HAL_ICACHE_DISABLE() HAL_DCACHE_DISABLE() + +// Invalidate the entire cache +#define HAL_ICACHE_INVALIDATE_ALL() HAL_DCACHE_SYNC(); HAL_DCACHE_INVALIDATE_ALL() + +// Synchronize the contents of the cache with memory. +#define HAL_ICACHE_SYNC() + +// Set the instruction cache refill burst size +//#define HAL_ICACHE_BURST_SIZE(_size_) + +// Load the contents of the given address range into the instruction cache +// and then lock the cache so that it stays there. +//#define HAL_ICACHE_LOCK(_base_, _size_) + +// Undo a previous lock operation +//#define HAL_ICACHE_UNLOCK(_base_, _size_) + +// Unlock entire cache +//#define HAL_ICACHE_UNLOCK_ALL() + +//----------------------------------------------------------------------------- +// Instruction cache line control + +// Invalidate cache lines in the given range without writing to memory. +//#define HAL_ICACHE_INVALIDATE( _base_ , _size_ ) + +//----------------------------------------------------------------------------- + +externC inline unsigned long sparc_leon3_get_dcachecfg(void) { + unsigned int retval; + __asm__ __volatile__("lda [%1] %2, %0\n\t" : + "=r" (retval) : + "r" (ASI_LEON3_SYSCTRL_DCFG), + "i" (ASI_LEON3_SYSCTRL)); + return (retval); +} + +externC inline void sparc_leon3_enable_snooping(void) { + //enable snooping + __asm__ volatile ("lda [%%g0] 2, %%l1\n\t" \ + "set 0x800000, %%l2\n\t" \ + "or %%l2, %%l1, %%l2\n\t" \ + "sta %%l2, [%%g0] 2\n\t" \ + : : : "l1", "l2"); +}; + +externC inline void sparc_leon3_disable_cache(void) { + __asm__ volatile ("lda [%%g0] 2, %%l1\n\t" \ + "set 0x00000f, %%l2\n\t" \ + "andn %%l2, %%l1, %%l2\n\t" \ + "sta %%l2, [%%g0] 2\n\t" \ + : : : "l1", "l2"); +}; + + + +#endif // ifndef CYGONCE_HAL_CACHE_H +// End of hal_cache.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_clock.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_clock.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_clock.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_clock.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,86 @@ +#ifndef CYGONCE_HAL_CLOCK_H +#define CYGONCE_HAL_CLOCK_H + +//============================================================================= +// +// hal_clock.h +// +// HAL clock support +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, gthomas, hmt +// Contributors: nickg, gthomas, hmt +// Date: 1999-01-28 +// Purpose: Define clock support +// Description: The macros defined here provide the HAL APIs for handling +// the clock. +// +// Usage: +// #include // which includes this file +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include + + +//----------------------------------------------------------------------------- +// Clock control + +externC cyg_int32 cyg_hal_sparc_clock_period; +externC void hal_sparc_leon3_clock_init(cyg_uint32 period); +externC cyg_uint32 hal_sparc_leon3_clock_read(void); + +#define HAL_CLOCK_INITIALIZE( _period_ ) hal_sparc_leon3_clock_init(_period_); +#define HAL_CLOCK_RESET( _vector_, _period_ ) +#define HAL_CLOCK_READ( _pvalue_ ) { \ + cyg_uint32 _read_; \ + _read_ = hal_sparc_leon3_clock_read(); \ + *((cyg_uint32 *)(_pvalue_)) = \ + (cyg_hal_sparc_clock_period - _read_ ); } + +#ifdef CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY +#define HAL_CLOCK_LATENCY( _pvalue_ ) HAL_CLOCK_READ( _pvalue_ ) +#endif + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_CLOCK_H +// End of hal_clock.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_diag.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_diag.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_diag.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_diag.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,93 @@ +#ifndef CYGONCE_HAL_HAL_DIAG_H +#define CYGONCE_HAL_HAL_DIAG_H + +/*============================================================================= +// +// hal_diag.h +// +// HAL Support for Kernel Diagnostic Routines +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1999-01-11 +// Purpose: HAL Support for Kernel Diagnostic Routines +// Description: Diagnostic routines for use during kernel development. +// Usage: #include +// +//####DESCRIPTIONEND#### +// +//===========================================================================*/ + +#include + +#include + +/*---------------------------------------------------------------------------*/ + +#define CYG_DIAG_USE_LEON + +/*---------------------------------------------------------------------------*/ + +#ifdef CYG_DIAG_USE_LEON + +#define HAL_DIAG_INIT() + +externC void hal_sparc_leon3_write_char(char c, int wait); +#define HAL_DIAG_WRITE_CHAR(_c_) hal_sparc_leon3_write_char(_c_,1); +#define XHAL_DIAG_WRITE_CHAR(_c_) hal_sparc_leon3_write_char(_c_,0); + +externC char hal_sparc_leon3_read_char(int wait); +#define HAL_DIAG_READ_CHAR(_c_) _c_ = hal_sparc_leon3_read_char(1); +#define XHAL_DIAG_READ_CHAR(_c_) _c_ = = hal_sparc_leon3_read_char(0); + +#else +/*---------------------------------------------------------------------------*/ +/* There is no diagnostic output on LEON processor */ + +#define HAL_DIAG_INIT() + +#define HAL_DIAG_WRITE_CHAR(_c_) + +#define HAL_DIAG_READ_CHAR(_c_) (_c_) = 0 + +#endif + +/*---------------------------------------------------------------------------*/ +/* end of hal_diag.h */ +#endif /* CYGONCE_HAL_HAL_DIAG_H */ diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_leon3.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_leon3.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_leon3.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_leon3.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,229 @@ +#ifndef CYGONCE_HAL_LEON3_H +#define CYGONCE_HAL_LEON3_H + +//============================================================================= +// +// hal_leon3.h +// +// HAL AMBA defined +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele ) +// Contributors: +// Date: 2004-01-12 +// Purpose: Define Interrupt support +// Description: +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + + +#include // Base types +#include +#include + +/* ASI codes */ +#define ASI_LEON_CACHEMISS 0x01 +#define ASI_LEON_PCI 0x04 +#define ASI_LEON_IFLUSH 0x05 +#define ASI_LEON_DFLUSH 0x06 +#define ASI_LEON_ITAG 0x0c +#define ASI_LEON_IDATA 0x0d +#define ASI_LEON_DTAG 0x0e +#define ASI_LEON_DDATA 0x0f +#define ASI_LEON_MMUFLUSH 0x18 +#define ASI_LEON_MMUREGS 0x19 +#define ASI_LEON_BYPASS 0x1c +#define ASI_LEON_FLUSH_PAGE 0x10 +/* +#define ASI_LEON_FLUSH_SEGMENT 0x11 +#define ASI_LEON_FLUSH_REGION 0x12 +*/ +#define ASI_LEON_FLUSH_CTX 0x13 +#define ASI_LEON_DCTX 0x14 +#define ASI_LEON_ICTX 0x15 +#define ASI_MMU_DIAG 0x1d + +#define ASI_LEON3_IFLUSH 0x10 +#define ASI_LEON3_DFLUSH 0x11 + +#define ASI_LEON3_SYSCTRL 0x02 + +#define ASI_LEON3_SYSCTRL_ICFG 0x08 +#define ASI_LEON3_SYSCTRL_DCFG 0x0c +#define ASI_LEON3_SYSCTRL_CFG_SNOOPING (1<<27) + +/* + * The following defines the bits in the LEON UART Status Registers. + */ + +#define LEON_REG_UART_STATUS_DR 0x00000001 /* Data Ready */ +#define LEON_REG_UART_STATUS_TSE 0x00000002 /* TX Send Register Empty */ +#define LEON_REG_UART_STATUS_THE 0x00000004 /* TX Hold Register Empty */ +#define LEON_REG_UART_STATUS_BR 0x00000008 /* Break Error */ +#define LEON_REG_UART_STATUS_OE 0x00000010 /* RX Overrun Error */ +#define LEON_REG_UART_STATUS_PE 0x00000020 /* RX Parity Error */ +#define LEON_REG_UART_STATUS_FE 0x00000040 /* RX Framing Error */ +#define LEON_REG_UART_STATUS_ERR 0x00000078 /* Error Mask */ + + +/* + * The following defines the bits in the LEON UART Ctrl Registers. + */ + +#define LEON_REG_UART_CTRL_RE 0x00000001 /* Receiver enable */ +#define LEON_REG_UART_CTRL_TE 0x00000002 /* Transmitter enable */ +#define LEON_REG_UART_CTRL_RI 0x00000004 /* Receiver interrupt enable */ +#define LEON_REG_UART_CTRL_TI 0x00000008 /* Transmitter interrupt enable */ +#define LEON_REG_UART_CTRL_PS 0x00000010 /* Parity select */ +#define LEON_REG_UART_CTRL_PE 0x00000020 /* Parity enable */ +#define LEON_REG_UART_CTRL_FL 0x00000040 /* Flow control enable */ +#define LEON_REG_UART_CTRL_LB 0x00000080 /* Loop Back enable */ + +#define LEON3_GPTIMER_EN 1 +#define LEON3_GPTIMER_RL 2 +#define LEON3_GPTIMER_LD 4 +#define LEON3_GPTIMER_IRQEN 8 + + +/* irq masks */ +#define LEON_HARD_INT(x) (1 << (x)) /* irq 0-15 */ +#define LEON_IRQMASK_R 0x0000fffe /* bit 15- 1 */ + +#define LEON3_IRQMPSTATUS_CPUNR 28 + +#ifndef __ASSEMBLER__ + +typedef struct { + volatile unsigned int ilevel; + volatile unsigned int ipend; + volatile unsigned int iforce; + volatile unsigned int iclear; + volatile unsigned int mpstatus; + volatile unsigned int notused01; + volatile unsigned int notused02; + volatile unsigned int notused03; + volatile unsigned int notused10; + volatile unsigned int notused11; + volatile unsigned int notused12; + volatile unsigned int notused13; + volatile unsigned int notused20; + volatile unsigned int notused21; + volatile unsigned int notused22; + volatile unsigned int notused23; + volatile unsigned int mask[16]; + volatile unsigned int force[16]; +} LEON3_IrqCtrl_Regs_Map; +externC volatile LEON3_IrqCtrl_Regs_Map *LEON3_IrqCtrl_Regs; + +typedef struct { + volatile unsigned int data; + volatile unsigned int status; + volatile unsigned int ctrl; + volatile unsigned int scaler; +} LEON3_APBUART_Regs_Map; + + +typedef struct { + volatile unsigned int val; + volatile unsigned int rld; + volatile unsigned int ctrl; + volatile unsigned int unused; +} LEON3_GpTimerElem_Regs_Map; + +typedef struct { + volatile unsigned int scalar; + volatile unsigned int scalar_reload; + volatile unsigned int config; + volatile unsigned int unused; + volatile LEON3_GpTimerElem_Regs_Map e[8]; +} LEON3_GpTimer_Regs_Map; + +typedef struct { + volatile unsigned int iodata; + volatile unsigned int ioout; + volatile unsigned int iodir; + volatile unsigned int irqmask; + volatile unsigned int irqpol; + volatile unsigned int irqedge; +} LEON3_IOPORT_Regs_Map; + +/* + * Types and structure used for AMBA Plug & Play bus scanning + */ + +typedef struct amba_device_table { + int devnr; /* numbrer of devices on AHB or APB bus */ + unsigned int *addr[16]; /* addresses to the devices configuration tables */ + unsigned int allocbits[1]; /* 0=unallocated, 1=allocated driver */ +} amba_device_table; + +typedef struct amba_confarea_type { + amba_device_table ahbmst; + amba_device_table ahbslv; + amba_device_table apbslv; + unsigned int apbmst; +} amba_confarea_type; + +extern unsigned long amba_find_apbslv_addr(unsigned long vendor, unsigned long device, unsigned long *irq); + +// collect apb slaves +typedef struct amba_apb_device { + unsigned int start, irq; +} amba_apb_device; +extern int amba_get_free_apbslv_devices (int vendor, int device, amba_apb_device *dev,int nr); + +// collect ahb slaves +typedef struct amba_ahb_device { + unsigned int start[4], irq; +} amba_ahb_device; +extern int amba_get_free_ahbslv_devices (int vendor, int device, amba_ahb_device *dev,int nr); +extern void amba_init(void); + +#endif //!__ASSEMBLER__ + + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_LEON3_H +// End of hal_leon3.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_leon3_smp.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_leon3_smp.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_leon3_smp.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_leon3_smp.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,240 @@ +#ifndef CYGONCE_HAL_LEON3_SMP_H +#define CYGONCE_HAL_LEON3_SMP_H + +//============================================================================= +// +// hal_leon3_cmp.h +// +// HAL smp defined +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele ) +// Contributors: +// Date: 2004-01-12 +// Purpose: Define Interrupt support +// Description: +// Usage: +// #include +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + + +#include // Base types +#include +#include + +#ifdef CYGPKG_HAL_SMP_SUPPORT + +//----------------------------------------------------------------------------- +// CPU numbering macros + +externC cyg_uint32 cyg_hal_smp_cpu_running_count; + +#define HAL_SMP_CPU_TYPE cyg_uint32 + +#define HAL_SMP_CPU_MAX CYGPKG_HAL_SMP_CPU_MAX + +#define HAL_SMP_CPU_COUNT() cyg_hal_smp_cpu_running_count + +#define HAL_SMP_CPU_START_COUNT() HAL_SMP_CPU_MAX + + +externC cyg_uint32 cyg_hal_smp_cpu_count2idx(cyg_uint32 n); +externC cyg_uint32 cyg_hal_smp_cpu_idx2count(cyg_uint32 n); +#define HAL_SMP_CPU_COUNT2IDX(n) cyg_hal_smp_cpu_count2idx(n) +#define HAL_SMP_CPU_IDX2COUNT(n) cyg_hal_smp_cpu_idx2count(n) + +externC cyg_uint32 sparc_leon3_get_cpuid(void); + +#define HAL_SMP_CPU_THIS() \ +({ \ + HAL_SMP_CPU_TYPE __id; \ + __asm__ __volatile__( \ + "rd %%asr17,%0\n\t" \ + : "=r" (__id) : ); \ + ((__id >> 28) & 0xff); \ +}) + +#define HAL_SMP_CPU_NONE (CYGPKG_HAL_SMP_CPU_MAX+1) + +//----------------------------------------------------------------------------- +// CPU startup + +__externC void cyg_hal_cpu_reset(HAL_SMP_CPU_TYPE cpu); + +#define HAL_SMP_CPU_START( __cpu ) cyg_hal_cpu_reset( __cpu ); + +#define HAL_SMP_CPU_RESCHEDULE_INTERRUPT( __cpu, __wait ) \ + cyg_hal_cpu_message( __cpu, HAL_SMP_MESSAGE_RESCHEDULE, 0, __wait); + +#define HAL_SMP_CPU_TIMESLICE_INTERRUPT( __cpu, __wait ) \ + cyg_hal_cpu_message( __cpu, HAL_SMP_MESSAGE_TIMESLICE, 0, __wait); + +//----------------------------------------------------------------------------- +// CPU message exchange + +__externC void cyg_hal_cpu_message( HAL_SMP_CPU_TYPE cpu, + CYG_WORD32 msg, + CYG_WORD32 arg, + CYG_WORD32 wait); + +#define HAL_SMP_MESSAGE_TYPE 0xF0000000 +#define HAL_SMP_MESSAGE_ARG (~HAL_SMP_MESSAGE_TYPE) + +#define HAL_SMP_MESSAGE_RESCHEDULE 0x10000000 +#define HAL_SMP_MESSAGE_MASK 0x20000000 +#define HAL_SMP_MESSAGE_UNMASK 0x30000000 +#define HAL_SMP_MESSAGE_REVECTOR 0x40000000 +#define HAL_SMP_MESSAGE_TIMESLICE 0x50000000 + + +//----------------------------------------------------------------------------- +// Test-and-set support +// These macros provide test-and-set support for the least significant bit +// in a word. + +#define HAL_TAS_TYPE volatile CYG_WORD32 + +#define HAL_TAS_SET( _tas_, _oldb_ ) \ +CYG_MACRO_START \ +{ \ + register CYG_WORD32 __old = 1; \ + __asm__ volatile ("swapa [%2] %3, %0" : \ + "=r" (__old) : \ + "0" (__old), \ + "r" (&_tas_), \ + "i" (1)); \ + _oldb_ = ( __old & 1 ) != 0; \ +} \ +CYG_MACRO_END + +#define HAL_TAS_CLEAR( _tas_, _oldb_ ) \ +CYG_MACRO_START \ +{ \ + register CYG_WORD32 __old = 0; \ + __asm__ volatile ("swapa [%2] %3, %0" : \ + "=r" (__old) : \ + "0" (__old), \ + "r" (&_tas_), \ + "i" (1)); \ + _oldb_ = ( __old & 1 ) != 0; \ +} \ +CYG_MACRO_END + + + +//----------------------------------------------------------------------------- +// Spinlock support. +// Built on top of test-and-set code. + +#define HAL_SPINLOCK_TYPE volatile CYG_WORD32 + +#define HAL_SPINLOCK_INIT_CLEAR 0 + +#define HAL_SPINLOCK_INIT_SET 1 + +#define HAL_SPINLOCK_SPIN( _lock_ ) \ +CYG_MACRO_START \ +{ \ + cyg_bool _val_; \ + do \ + { \ + HAL_TAS_SET( _lock_, _val_ ); \ + } while( _val_ ); \ +} \ +CYG_MACRO_END + +#define HAL_SPINLOCK_CLEAR( _lock_ ) \ +CYG_MACRO_START \ +{ \ + cyg_bool _val_; \ + HAL_TAS_CLEAR( _lock_ , _val_ ); \ +} \ +CYG_MACRO_END + +#define HAL_SPINLOCK_TRY( _lock_, _val_ ) \ + HAL_TAS_SET( _lock_, _val_ ); \ + (_val_) = (((_val_) & 1) == 0) + +#define HAL_SPINLOCK_TEST( _lock_, _val_ ) \ + (_val_) = (((_lock_) & 1) != 0) + +//----------------------------------------------------------------------------- +// Diagnostic output serialization + +__externC HAL_SPINLOCK_TYPE cyg_hal_smp_diag_lock; + +#define CYG_HAL_DIAG_LOCK_DATA_DEFN \ + HAL_SPINLOCK_TYPE cyg_hal_smp_diag_lock = HAL_SPINLOCK_INIT_CLEAR + +#define CYG_HAL_DIAG_LOCK() HAL_SPINLOCK_SPIN( cyg_hal_smp_diag_lock ) + +#define CYG_HAL_DIAG_UNLOCK() HAL_SPINLOCK_CLEAR( cyg_hal_smp_diag_lock ) + +#define leon3smp_diag_printf(fmt,arg...) \ + CYG_HAL_DIAG_LOCK(); \ + diag_printf(fmt,##arg); \ + CYG_HAL_DIAG_UNLOCK(); + +//----------------------------------------------------------------------------- +// Some extra definitions + +__externC HAL_SPINLOCK_TYPE cyg_hal_ioapic_lock; + +//----------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// irqmp interrupt configuration +// Additional SMP interrupt configuration support. + +externC void leon3_interrupt_set_cpu( CYG_WORD32 vector, HAL_SMP_CPU_TYPE cpu ); +externC void leon3_interrupt_get_cpu( CYG_WORD32 vector, HAL_SMP_CPU_TYPE *cpu ); +externC void leon3_smpirq_raise(CYG_WORD32 cpu); + +#define HAL_INTERRUPT_SET_CPU( _vector_, _cpu_ ) leon3_interrupt_set_cpu( _vector_, _cpu_ ); +#define HAL_INTERRUPT_GET_CPU( _vector_, _cpu_ ) leon3_interrupt_get_cpu( _vector_, &(_cpu_) ); + +#endif // CYGPKG_HAL_SMP_SUPPORT + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_LEON3_SMP_H +// End of hal_leon3_smp.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_xpic.h ecos-rep/packages/hal/sparc/leon3/current/include/hal_xpic.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/hal_xpic.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/hal_xpic.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,101 @@ +#ifndef CYGONCE_HAL_XPIC_H +#define CYGONCE_HAL_XPIC_H + +//============================================================================= +// +// hal_xpic.h +// +// HAL eXternal Programmable Interrupt Controller support +// +//============================================================================= +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//============================================================================= +//#####DESCRIPTIONBEGIN#### +// +// Author(s): nickg, gthomas, hmt +// Contributors: nickg, gthomas, hmt +// Date: 1999-01-28 +// Purpose: Define Interrupt support +// Description: The macros defined here provide the HAL APIs for handling +// an external interrupt controller, and which interrupt is +// used for what. +// +// Usage: +// #include // which includes this file +// ... +// +// +//####DESCRIPTIONEND#### +// +//============================================================================= + +#include +#include +#include + +//----------------------------------------------------------------------------- +// Interrupt controller access + +// The vector used by the Real time clock +externC cyg_uint32 hal_sparc_leon3_clock_irqnr(void); +#define CYGNUM_HAL_INTERRUPT_RTC hal_sparc_leon3_clock_irqnr() + + +externC void leon3_disable_irq(unsigned int irq_nr); +externC void leon3_enable_irq(unsigned int irq_nr); + +#define HAL_INTERRUPT_MASK( _vector_ ) CYG_MACRO_START \ + cyg_uint32 _traps_, _mask_; \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ + leon3_disable_irq(_vector_); \ + HAL_RESTORE_INTERRUPTS( _traps_ ); \ +CYG_MACRO_END + +#define HAL_INTERRUPT_UNMASK( _vector_ ) CYG_MACRO_START \ + cyg_uint32 _traps_, _mask_; \ + HAL_DISABLE_INTERRUPTS( _traps_ ); \ + leon3_enable_irq(_vector_); \ + HAL_RESTORE_INTERRUPTS( _traps_ ); \ +CYG_MACRO_END + +#define HAL_INTERRUPT_ACKNOWLEDGE( _vector_ ) /* nothing */ + +#define HAL_INTERRUPT_CONFIGURE( _vector_, _level_, _up_ ) /* nothing */ + +#define HAL_INTERRUPT_SET_LEVEL( _vector_, _level_ ) /* nothing */ + + +//----------------------------------------------------------------------------- +#endif // ifndef CYGONCE_HAL_XPIC_H +// End of hal_xpic.h diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/halboot.si ecos-rep/packages/hal/sparc/leon3/current/include/halboot.si --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/halboot.si 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/halboot.si 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,75 @@ +#ifndef CYGONCE_HAL_HALBOOT_SI /* -*-asm-*- */ +#define CYGONCE_HAL_HALBOOT_SI +// ==================================================================== +// +// /halboot.si +// +// HAL bootup platform-oriented code (assembler) +// +// ==================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +// ==================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): hmt +// Contributors: hmt +// Date: 1999-02-01 +// Purpose: Bootup code, platform oriented. +// Description: +// +//####DESCRIPTIONEND#### +// +// ==================================================================== + +// External Platform Initial Setup +// +// This should set up RAM and caches, and calm down any external +// interrupt sources. +// +// It is just plain included in vectors.S +// +// RAM has not yet been touched at all; in fact all you have is a +// register window selected. + + + ! Empty macro for debugging vectors.S + .macro led val + .endm + + call hal_sparc_leon_init + nop + + +#endif /* CYGONCE_HAL_HALBOOT_SI */ +/* EOF halboot.si */ diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/leon3_arch.inc ecos-rep/packages/hal/sparc/leon3/current/include/leon3_arch.inc --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/leon3_arch.inc 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/leon3_arch.inc 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,70 @@ +#ifndef CYGONCE_HAL_LEON3_ARCH_INC +#define CYGONCE_HAL_LEON3_ARCH_INC +##============================================================================= +## +## arch.inc +## +## sparc assembler header file +## +##============================================================================= +#####ECOSGPLCOPYRIGHTBEGIN#### +## ------------------------------------------- +## This file is part of eCos, the Embedded Configurable Operating System. +## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +## +## eCos is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free +## Software Foundation; either version 2 or (at your option) any later version. +## +## eCos is distributed in the hope that it will be useful, but WITHOUT ANY +## WARRANTY; without even the implied warranty of MERCHANTABILITY or +## FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +## for more details. +## +## You should have received a copy of the GNU General Public License along +## with eCos; if not, write to the Free Software Foundation, Inc., +## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +## +## As a special exception, if other files instantiate templates or use macros +## or inline functions from this file, or you compile this file and link it +## with other works to produce a work based on this file, this file does not +## by itself cause the resulting work to be covered by the GNU General Public +## License. However the source code for this file must still be made available +## in accordance with section (3) of the GNU General Public License. +## +## This exception does not invalidate any other reasons why a work based on +## this file might be covered by the GNU General Public License. +## +## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +## at http://sources.redhat.com/ecos/ecos-license/ +## ------------------------------------------- +#####ECOSGPLCOPYRIGHTEND#### +##============================================================================= +#######DESCRIPTIONBEGIN#### +## +## Author(s): Gaisler Research (Konrad Eisele) +## Contributors: +## Date: +## Purpose: Architecture definitions. +## Description: This file contains definitions and macros that are +## useful for writing assembly code for the sparc CPU family. +## Usage: +## #include +## ... +## +## +######DESCRIPTIONEND#### +## +##============================================================================= + +#ifdef CYGPKG_HAL_SMP_SUPPORT + + // Put CPU number in register + .macro hal_smp_cpu reg + rd %asr17,\reg + srl \reg,28,\reg + .endm + +#endif + +#endif // ifndef CYGONCE_HAL_LEON3_ARCH_INC diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,21 @@ +// eCos memory layout - Fri Oct 20 08:18:20 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include +#endif + +externC unsigned int cyg_hal_stack_top; +#define CYGHAL_DSUSUPPLIED_STACK_TOP cyg_hal_stack_top + +#define CYGMEM_REGION_ram (0x40000000) +#define CYGMEM_REGION_ram_SIZE (CYGHAL_DSUSUPPLIED_STACK_TOP-CYGMEM_REGION_ram) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (CYGHAL_DSUSUPPLIED_STACK_TOP - (size_t) CYG_LABEL_NAME (__heap1)) + diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h.bck ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h.bck --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h.bck 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.h.bck 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,19 @@ +// eCos memory layout - Fri Oct 20 08:18:20 2000 + +// This is a generated file - do not edit + +#ifndef __ASSEMBLER__ +#include +#include + +#endif +#define CYGMEM_REGION_ram (0x40000000) +#define CYGMEM_REGION_ram_SIZE (0x100000) +#define CYGMEM_REGION_ram_ATTR (CYGMEM_REGION_ATTR_R | CYGMEM_REGION_ATTR_W) +#ifndef __ASSEMBLER__ +extern char CYG_LABEL_NAME (__heap1) []; +#endif +#define CYGMEM_SECTION_heap1 (CYG_LABEL_NAME (__heap1)) +#define CYGMEM_SECTION_heap1_SIZE (0x40100000 - (size_t) CYG_LABEL_NAME (__heap1)) + +#define CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.ldi ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.ldi --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.ldi 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.ldi 2005-11-07 16:37:18.000000000 +0100 @@ -0,0 +1,26 @@ +// eCos memory layout - Fri Oct 20 08:18:20 2000 + +// This is a generated file - do not edit + +#include + +MEMORY +{ + ram : ORIGIN = 0x40000000, LENGTH = 0x40000000 +} + +SECTIONS +{ + SECTIONS_BEGIN + SECTION_rom_vectors (ram, 0x40000000, LMA_EQ_VMA) + SECTION_text (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fini (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_rodata (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_rodata1 (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_fixup (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_gcc_except_table (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_data (ram, ALIGN (0x1), LMA_EQ_VMA) + SECTION_bss (ram, ALIGN (0x8) (NOLOAD), LMA_EQ_VMA) + CYG_LABEL_DEFN(__heap1) = ALIGN (0x8); + SECTIONS_END +} diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.mlt ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.mlt --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.mlt 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/include/pkgconf/mlt_sparc_leon3_ram.mlt 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,12 @@ +version 0 +region ram 40000000 40000000 0 ! +section rom_vectors 0 1 0 1 1 1 1 1 40000000 40000000 text text ! +section text 0 1 0 1 0 1 0 1 fini fini ! +section fini 0 1 0 1 0 1 0 1 rodata rodata ! +section rodata 0 1 0 1 0 1 0 1 rodata1 rodata1 ! +section rodata1 0 1 0 1 0 1 0 1 fixup fixup ! +section fixup 0 1 0 1 0 1 0 1 gcc_except_table gcc_except_table ! +section gcc_except_table 0 1 0 1 0 1 0 1 data data ! +section data 0 1 0 1 0 1 0 1 bss bss ! +section bss 0 8 0 1 0 1 0 1 heap1 heap1 ! +section heap1 0 8 0 0 0 0 0 0 ! diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/boot.S ecos-rep/packages/hal/sparc/leon3/current/src/boot.S --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/boot.S 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/boot.S 2006-01-31 19:56:12.000000000 +0100 @@ -0,0 +1,430 @@ +// ==================================================================== +// +// HAL bootup platform-oriented code (assembler) +// +// ==================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +// ==================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Konrad Eisele) +// Contributors: +// Date: 1999-02-01 +// Purpose: Bootup code, platform oriented. +// Description: +// +//####DESCRIPTIONEND#### +// +// ==================================================================== + +#include +#include +#include +#include + +!unsigned int ahbslv_scan(register unsigned int vendor,register unsigned int driver) { +! register unsigned int conf, mbar,i, *confp; +! register unsigned int cfg_area = (unsigned int ) (LEON3_IO_AREA | LEON3_CONF_AREA | LEON3_AHB_SLAVE_CONF_AREA); +! for (i = 0; i < LEON3_AHB_SLAVES; i++) +! { +! confp = (unsigned int*)(cfg_area + (i * LEON3_AHB_CONF_WORDS * 4)); +! conf = *confp; +! //mbar = *(unsigned int*)(i * LEON3_AHB_CONF_WORDS+ (4 * 4)); +! if ((amba_vendor(conf) == vendor) && (amba_device(conf) == driver)) { +! return (unsigned int)confp; +! } +! } +! return 0; +!} + + .section ".text" + .align 4 +ahbslv_scan: + mov %o0, %g1 + mov -2048, %o5 + mov 0, %o3 + sll %o3, 5, %o0 +.LL11: + add %o5, %o0, %o4 + ld [%o5+%o0], %o2 + srl %o2, 24, %o0 + cmp %o0, %g1 + bne,a .LL10 + add %o3, 1, %o3 + srl %o2, 12, %o0 + and %o0, 4095, %o0 + cmp %o0, %o1 + be .LL1 + mov %o4, %o2 + add %o3, 1, %o3 +.LL10: + cmp %o3, 63 + bleu,a .LL11 + sll %o3, 5, %o0 + mov 0, %o2 +.LL1: + retl + mov %o2, %o0 + + +!unsigned int apbslv_scan(register unsigned int base,register unsigned int vendor, register unsigned int driver) { +! register unsigned int conf, mbar,i, *confp; +! for (i = 0; i < LEON3_APB_SLAVES; i++) +! { +! confp = (unsigned int*)(base + (i * LEON3_APB_CONF_WORDS * 4)); +! conf = *confp; +! //mbar = *(unsigned int*)(i * LEON3_AHB_CONF_WORDS+ (4 * 4)); +! if ((amba_vendor(conf) == vendor) && (amba_device(conf) == driver)) { +! return (unsigned int)confp; +! } +! } +! return 0; +!} + + + + .section ".text" + .align 4 + +apbslv_scan: + mov %o0, %g1 + mov 0, %o4 + sll %o4, 3, %o0 +.LL22: + add %g1, %o0, %o5 + ld [%g1+%o0], %o3 + srl %o3, 24, %o0 + cmp %o0, %o1 + bne,a .LL21 + add %o4, 1, %o4 + srl %o3, 12, %o0 + and %o0, 4095, %o0 + cmp %o0, %o2 + be .LL12 + mov %o5, %o3 + add %o4, 1, %o4 +.LL21: + cmp %o4, 15 + bleu,a .LL22 + sll %o4, 3, %o0 + mov 0, %o3 +.LL12: + retl + mov %o3, %o0 + + + +!unsigned int getbase(register unsigned int *mbar,register unsigned int iobase) { +! register unsigned int conf = mbar[1]; +! return ((iobase & 0xfff00000) | +! ((conf & 0xfff00000)>> 12)) & (((conf & 0x0000fff0) <<4) | 0xfff00000); +! +!} + + + .section ".text" + .align 4 + +getbase: + ld [%o0+4], %o2 + sethi %hi(-1048576), %o3 + and %o1, %o3, %o1 + and %o2, %o3, %o0 + srl %o0, 12, %o0 + or %o1, %o0, %o1 + sethi %hi(64512), %o0 + or %o0, 1008, %o0 + and %o2, %o0, %o2 + sll %o2, 4, %o2 + or %o2, %o3, %o2 + and %o1, %o2, %o1 + retl + mov %o1, %o0 + + +#define BOOTLOADER_FREQ_KHZ 40000 +#define BOOTLOADER_SRAMSZ_KB 4096 +#define BOOTLOADER_SDRAMSZ_MB 0 +#define BOOTLOADER_BAUD 38400 + +#define BOOTLOADER_memcfg1 0x28022 +#define BOOTLOADER_memcfg2 0x4201220 +#define BOOTLOADER_uart 0xa2 +#define BOOTLOADER_loopback 0x0 +#define BOOTLOADER_flow 0x0 +#define BOOTLOADER_ftreg 0x0 + +#define BOOTLOADER_grlib_sdram 0x420013b + +#define BOOTLOADER_freq 40500000 + +#define BOOTLOADER_ramsize 0x3ff000 +#define BOOTLOADER_romsize 0x800000 +#define BOOTLOADER_stack 0x403fefe0 + +#define START_USING_DSU + + + + + .global hal_sparc_leon_init + .global LEON3_IrqCtrl_Regs, LEON3_GpTimer_Regs, LEON3_APBUART_Regs +hal_sparc_leon_init: + + flush + +#ifdef CYGPKG_HAL_SMP_SUPPORT + !lda [%g0] 2, %g1 ! init cache + !set 0x800000, %g2 ! snooping enable + !or %g2, %g1, %g2 + + !set 0x800000, %g2 ! snooping,disable cache for test + + !sta %g2, [%g0] 2 ! init cache + + !set 0x81000f, %g2 ! snooping enable + !set 0x800000, %g2 ! snooping enable +#else + !set 0x01000f, %g2 + !set 0x000000, %g2 + !sta %g2, [%g0] 2 ! init cache +#endif + + clr %g1 + clr %g2 + clr %g3 + clr %g4 + clr %g5 + clr %g6 + mov %o7,%g7 + + set VENDOR_GAISLER, %o0 + set GAISLER_APBMST, %o1 + call ahbslv_scan + nop + + cmp %g0,%o0 + be .goonhardreset + nop + + ld [%o0+16],%g1 + set LEON3_IO_AREA,%o0 + and %g1,%o0,%g1 !g1: apb base + + set LEON3_CONF_AREA,%o0 + or %g1,%o0,%g2 !g2: apb conf base + + ! *********** irq ***************** + mov %g2,%o0 + set VENDOR_GAISLER, %o1 + set GAISLER_IRQMP,%o2 + call apbslv_scan + nop + cmp %g0,%o0 + be .goonhardreset + nop + + call getbase + mov %g1,%o1 + + st %g0, [%o1 + 0x0] !irq pri + st %g0, [%o1 + 0x4] !irq pend + st %g0, [%o1 + 0x8] !irq force + st %g0, [%o1 + 0xC] !irq clear + st %g0, [%o1 + 0x40] !irq mask + + set LEON3_IrqCtrl_Regs,%o0 + st %o1,[%o0] + + ! *********** timer ***************** + + mov %g2,%o0 + set VENDOR_GAISLER, %o1 + set GAISLER_GPTIMER,%o2 + call apbslv_scan + nop + cmp %g0,%o0 + be .goonhardreset + nop + + call getbase + mov %g1,%o1 + + set (BOOTLOADER_FREQ_KHZ+500)/1000, %o0 ! Load timer scaler register + sub %o0, 1, %o0 + st %o0, [%o1 + 0x00] ! scaler + st %o0, [%o1 + 0x04] ! scaler reload + + set LEON3_GpTimer_Regs,%o0 + st %o1,[%o0] + +#ifndef START_USING_DSU + + ! ************ mctrl ************ + + mov %g2,%o0 + set VENDOR_ESA, %o1 + set ESA_MCTRL,%o2 + call apbslv_scan + nop + cmp %g0,%o0 + be .LL1mctlsdram + nop + + call getbase + mov %g1,%o1 + +#define MCTRLBASE %g4 + mov %o1,MCTRLBASE !mctrl base address + + set BOOTLOADER_memcfg1, %o0 ! Load memory config register 1 + ld [%o1+0x00], %o2 ! + and %o2, 0x300, %o2 + or %o0, %o2, %o0 + st %o0, [%o1 + 0x00] + + set BOOTLOADER_memcfg2, %o0 ! Load memory config register 2 +#if !( defined(TSIM) || !defined(BZIMAGE)) + st %o0, [%o1 + 0x04] ! only for prom version, else done by "dumon -i" +#endif + set BOOTLOADER_ftreg, %o0 ! Init FT register + st %o0, [%o1 + 0x08] + ld [%o1 + 0x08], %o0 + srl %o0, 30, %o0 + andcc %o0, 3, %g6 + bne,a 1f + mov %g0, %asr16 ! clear err_reg +1: + ba .LL1mctlok + nop + + + ! ************ gaisler sdram mctrl ************ + +.LL1mctlsdram: + + set VENDOR_GAISLER, %o0 + set GAISLER_SDCTRL, %o1 + call ahbslv_scan + nop + + cmp %g0,%o0 + be .LL1mctlok ! assuming sram/prom ctrl + nop + + ld [%o0+16+4],%g1 ! get io bar + set LEON3_IO_AREA,%o0 + and %g1,%o0,%g1 + srl %g1,12,%g1 + or %g1,%o0,%g1 + + + set BOOTLOADER_grlib_sdram, %o0 + st %o0, [%g1 + 0x100] + + ! ************ uart ************ + +#endif //!START_USING_DSU + +.LL1mctlok: + mov %g2,%o0 + set VENDOR_GAISLER, %o1 + set GAISLER_APBUART,%o2 + call apbslv_scan + nop + cmp %g0,%o0 + be .goonhardreset + nop + + call getbase + mov %g1,%o1 + +#define UARTBASE %g5 + mov %o1,UARTBASE !uart base address + + + !######################################################## + ! initialization: protect g5 (uartbase) + + !set BOOTLOADER_uart, %g2 ! Load UART scaler register + !st %g2, [UARTBASE + 0x0c] ! uart scalar !st %g2, [%g1 + 0x0c] + + ld [UARTBASE + 0x08], %o0 + or %o0,0x3,%o0 +#if defined(CONFIG_UARTLOOPBACK) || (BOOTLOADER_loopback==1) + !set 0x83|(BOOTLOADER_flow<<6), %g2 ! Enable uarts, (flow ctrl), loopback +#else + !set 0x03|(BOOTLOADER_flow<<6), %g2 ! Enable uarts, (flow ctrl) +#endif + st %o0, [UARTBASE + 0x08] + + !set 0xc3|(BOOTLOADER_flow<<6), %g2 ! Enable uarts, (flow ctrl) + !st %g2, [UARTBASE + 0x08] + + set LEON3_APBUART_Regs,%o0 + st UARTBASE,[%o0] + + + !####################################################### + ! end + + ! then copy the branch instructions into the vector + + rd %tbr, %g1 + andn %g1, 0xfff, %g1 ! clear non-address bits + sethi %hi(real_vector_instructions), %l0 + or %l0, %lo(real_vector_instructions), %l0 + +#if CYGHWR_HAL_SPARC_MULTIPLE_VECTOR_TRAPPING +#if !defined(CYGPKG_HAL_SMP_SUPPORT) + ld [ %l0 ], %l1 + st %l1, [ %g1 ] ! into the vector + ld [ %l0 + 4 ], %l1 + st %l1, [ %g1 + 4 ] ! into the vector +#endif +#endif + +.goonhardreset: + +#ifndef START_USING_DSU + set BOOTLOADER_stack, %fp + andn %fp, 0x0f, %fp + sub %fp, 64, %sp +#endif + + mov %g7,%o7 + retl + nop + + diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/boot_smp.S ecos-rep/packages/hal/sparc/leon3/current/src/boot_smp.S --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/boot_smp.S 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/boot_smp.S 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,68 @@ +// ==================================================================== +// +// /halboot.si +// +// HAL bootup platform-oriented code (assembler) +// +// ==================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +// ==================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research, (Konrad Eisele) +// Contributors: +// Date: 1999-02-01 +// Purpose: Bootup code, platform oriented. +// Description: +// +//####DESCRIPTIONEND#### +// +// ==================================================================== + +#include + + .global hal_sparc_leon_smpinit + +hal_sparc_leon_smpinit: + + rd %asr17,%g2 + srl %g2,28,%g2 + + ! trap all cpu's except cpu nr 0 +1: cmp %g2,%g0 + bne .1b + nop + + + diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_amba.c ecos-rep/packages/hal/sparc/leon3/current/src/hal_amba.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_amba.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_amba.c 2006-01-31 19:56:12.000000000 +0100 @@ -0,0 +1,233 @@ +//=========================================================================== +// +// hal_amba.c +// +// SPARC Architecture LEON3-specific private variables +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include +#include +#include +#include +#include + +//#define DEBUG_CONFIG + +/* Structure containing address to devices found on the Amba Plug&Play bus */ +amba_confarea_type amba_conf; + +/* Pointers to Interrupt Controller configuration registers */ +volatile LEON3_IrqCtrl_Regs_Map *LEON3_IrqCtrl_Regs = 0; +volatile LEON3_GpTimer_Regs_Map *LEON3_GpTimer_Regs = 0; +volatile LEON3_APBUART_Regs_Map *LEON3_APBUART_Regs = 0; +unsigned long LEON3_GpTimer_Irq = 0; + +static void vendor_dev_string(unsigned long conf, char *vendorbuf,char *devbuf) { + int vendor = amba_vendor(conf); int dev = amba_device(conf); + char *devstr; char *vendorstr; + sprintf(vendorbuf, "Unknown vendor %2x",vendor); + sprintf(devbuf, "Unknown device %2x",dev); + vendorstr = vendor_id2str(vendor); + if (vendorstr) { + sprintf(vendorbuf, "%s",vendorstr); + } + devstr = device_id2str(vendor,dev); + if (devstr) { + sprintf(devbuf, "%s",devstr); + } +} + +void amba_prinf_config(void) +{ + char devbuf[128]; char vendorbuf[128]; unsigned int conf; + int i = 0; int j = 0; + unsigned int addr; unsigned int m; + diag_printf(" Vendors Slaves\n"); + diag_printf("Ahb masters:\n"); + i = 0; + while (i < amba_conf.ahbmst.devnr) + { + conf = amba_get_confword(amba_conf.ahbmst, i, 0); + vendor_dev_string(conf,vendorbuf,devbuf); + diag_printf("%2i(%2x:%3x|%2i): %16s %16s \n", i, amba_vendor(conf), amba_device(conf), amba_irq(conf), vendorbuf, devbuf); + for (j = 0;j < 4;j++) { + m = amba_ahb_get_membar(amba_conf.ahbmst,i,j); + if (m) { + addr = amba_membar_start(m); + diag_printf(" +%i: 0x%x \n", j, addr); + } + } + i++; + } + diag_printf("Ahb slaves:\n"); + i = 0; + while (i < amba_conf.ahbslv.devnr) + { + conf = amba_get_confword(amba_conf.ahbslv, i, 0); + vendor_dev_string(conf,vendorbuf,devbuf); + diag_printf("%2i(%2x:%3x|%2i): %16s %16s \n", i, amba_vendor(conf), amba_device(conf), amba_irq(conf), vendorbuf, devbuf); + for (j = 0;j < 4;j++) { + m = amba_ahb_get_membar(amba_conf.ahbslv,i,j); + if (m) { + addr = amba_membar_start(m); + if (amba_membar_type(m) == AMBA_TYPE_AHBIO) { + addr = AMBA_TYPE_AHBIO_ADDR(addr); + } else if (amba_membar_type(m) == AMBA_TYPE_APBIO) { + diag_printf("Warning: apbio membar\n"); + } + diag_printf(" +%i: 0x%x (raw:0x%x)\n", j, addr, m); + } + } + i++; + } + diag_printf("Apb slaves:\n"); + i = 0; + while (i < amba_conf.apbslv.devnr) + { + + conf = amba_get_confword(amba_conf.apbslv, i, 0); + vendor_dev_string(conf,vendorbuf,devbuf); + diag_printf("%2i(%2x:%3x|%2i): %16s %16s \n", i, amba_vendor(conf), amba_device(conf), amba_irq(conf), vendorbuf, devbuf); + + m = amba_apb_get_membar(amba_conf.apbslv, i); + addr = amba_iobar_start(amba_conf.apbmst, m); + diag_printf(" +%2i: 0x%x (raw:0x%x) \n", 0, addr, m); + + i++; + + } + +} + +#define amba_insert_device(tab, address) \ +{ \ + if (LEON3_BYPASS_LOAD_PA(address)) \ + { \ + (tab)->addr[(tab)->devnr] = (address); \ + (tab)->devnr ++; \ + } \ +} while(0) + +/* + * Used to scan system bus. Probes for AHB masters, AHB slaves and + * APB slaves. Addresses to configuration areas of the AHB masters, + * AHB slaves, APB slaves and APB master are storeds in + * amba_ahb_masters, amba_ahb_slaves and amba. + */ + +void amba_init(void) +{ + unsigned int *cfg_area; /* address to configuration area */ + unsigned int mbar, conf; + int i, j; + +#ifdef DEBUG_CONFIG + diag_printf("Reading AMBA Plug&Play configuration area\n"); +#endif + + memset(&amba_conf,0,sizeof(amba_conf)); + //amba_conf.ahbmst.devnr = 0; amba_conf.ahbslv.devnr = 0; amba_conf.apbslv.devnr = 0; + + cfg_area = (unsigned int *) (LEON3_IO_AREA | LEON3_CONF_AREA); + + for (i = 0; i < LEON3_AHB_MASTERS; i++) + { + amba_insert_device(&amba_conf.ahbmst, cfg_area); + cfg_area += LEON3_AHB_CONF_WORDS; + } + + cfg_area = (unsigned int *) (LEON3_IO_AREA | LEON3_CONF_AREA | LEON3_AHB_SLAVE_CONF_AREA); + for (i = 0; i < LEON3_AHB_SLAVES; i++) + { + amba_insert_device(&amba_conf.ahbslv, cfg_area); + cfg_area += LEON3_AHB_CONF_WORDS; + } + + for (i = 0; i < amba_conf.ahbslv.devnr; i ++) + { + conf = amba_get_confword(amba_conf.ahbslv, i, 0); + mbar = amba_ahb_get_membar(amba_conf.ahbslv, i, 0); + if ((amba_vendor(conf) == VENDOR_GAISLER) && (amba_device(conf) == GAISLER_APBMST)) + { + amba_conf.apbmst = amba_membar_start(mbar); + cfg_area = (unsigned int *) (amba_conf.apbmst | LEON3_CONF_AREA); + + //diag_printf("Found apbmst, cfg: 0x%x\n",(unsigned int)cfg_area); + + for (j = amba_conf.apbslv.devnr; j < LEON3_APB_SLAVES; j++) + { + amba_insert_device(&amba_conf.apbslv, cfg_area); + cfg_area += LEON3_APB_CONF_WORDS; + } + break; + } + } + + /* Find LEON3 Interrupt controler */ + LEON3_IrqCtrl_Regs = (volatile LEON3_IrqCtrl_Regs_Map *) amba_find_apbslv_addr(VENDOR_GAISLER, GAISLER_IRQMP, 0); + LEON3_GpTimer_Regs = (volatile LEON3_GpTimer_Regs_Map *) amba_find_apbslv_addr(VENDOR_GAISLER, GAISLER_GPTIMER, &LEON3_GpTimer_Irq); + if (LEON3_IrqCtrl_Regs) { + //LEON3_BYPASS_STORE_PA(&(LEON3_IrqCtrl_Regs ->mask[0]),0); + } +} + +unsigned long amba_find_apbslv_addr(unsigned long vendor, unsigned long device, unsigned long *irq) { + unsigned int i,conf,iobar; + for (i = 0; i < amba_conf.apbslv.devnr; i++) { + conf = amba_get_confword(amba_conf.apbslv, i, 0); + if ((amba_vendor(conf) == vendor) && (amba_device(conf) == device)) + { + if (irq) { + *irq = amba_irq(conf); + } + iobar = amba_apb_get_membar(amba_conf.apbslv, i); + return amba_iobar_start(amba_conf.apbmst, iobar); + } + } + return 0; +} diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_amba_driver.c ecos-rep/packages/hal/sparc/leon3/current/src/hal_amba_driver.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_amba_driver.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_amba_driver.c 2005-12-14 11:27:31.000000000 +0100 @@ -0,0 +1,124 @@ +//=========================================================================== +// +// hal_amba_driver.c +// +// SPARC Architecture LEON3-specific private variables +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include + +//#define DEBUG_CONFIG + +/* Structure containing address to devices found on the Amba Plug&Play bus */ +extern amba_confarea_type amba_conf; + +//collect apb slaves +int amba_get_free_apbslv_devices (int vendor, int device, amba_apb_device *dev,int nr) { + unsigned int i,conf,iobar,j = 0; +#ifdef DEBUG_CONFIG + diag_printf("Apbslv: search for apdslv devices\n"); +#endif + for (i = 0; i < amba_conf.apbslv.devnr && j < nr; i++) { + conf = amba_get_confword(amba_conf.apbslv, i, 0); +#ifdef DEBUG_CONFIG + diag_printf("Apbslv: check(%x:%x)==(%x:%x)\n",vendor,device,amba_vendor(conf),amba_device(conf)); +#endif + if ((amba_vendor(conf) == vendor) && (amba_device(conf) == device)) { + if (!(amba_conf.apbslv.allocbits[i / 32] & (1 << (i & (32-1))))) { +#ifdef DEBUG_CONFIG + diag_printf("Apbslv: alloc device idx %i (%x:%x)\n",j,vendor,device); +#endif + amba_conf.apbslv.allocbits[i / 32] |= (1 << (i & (32-1))); + dev[j].irq = amba_irq(conf); + iobar = amba_apb_get_membar(amba_conf.apbslv, i); + dev[j].start = amba_iobar_start(amba_conf.apbmst, iobar); +#ifdef DEBUG_CONFIG + // diag_printf(" +bar: 0x%x \n", k, dev[j].start); +#endif + j++; + } + } + } + return j; +} + +//collect ahb slaves +int amba_get_free_ahbslv_devices (int vendor, int device, amba_ahb_device *dev,int nr) { + unsigned int addr, i,conf,iobar,j = 0,k; +#ifdef DEBUG_CONFIG + diag_printf("Ahbslv: search for ahdslv devices\n"); +#endif + for (i = 0; i < amba_conf.ahbslv.devnr && j < nr; i++) { + conf = amba_get_confword(amba_conf.ahbslv, i, 0); +#ifdef DEBUG_CONFIG + diag_printf("Ahbslv: check(%x:%x)==(%x:%x)\n",vendor,device,amba_vendor(conf),amba_device(conf)); +#endif + if ((amba_vendor(conf) == vendor) && (amba_device(conf) == device)) { + if (!(amba_conf.ahbslv.allocbits[i / 32] & (1 << (i & (32-1))))) { +#ifdef DEBUG_CONFIG + diag_printf("Ahbslv: alloc device idx %i (%x:%x)\n",j,vendor,device); +#endif + amba_conf.ahbslv.allocbits[i / 32] |= (1 << (i & (32-1))); + dev[j].irq = amba_irq(conf); + for (k = 0; k < 4; k ++) { + iobar = amba_ahb_get_membar(amba_conf.ahbslv, i, k); + addr = amba_membar_start(iobar); + if (amba_membar_type(iobar) == AMBA_TYPE_AHBIO) { + addr = AMBA_TYPE_AHBIO_ADDR(addr); + } + dev[j].start[k] = addr; +#ifdef DEBUG_CONFIG + diag_printf(" +%i: 0x%x \n", k, dev[j].start[k]); +#endif + } + j++; + } + } + } + return j; +} diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_clock.c ecos-rep/packages/hal/sparc/leon3/current/src/hal_clock.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_clock.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_clock.c 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,96 @@ +//=========================================================================== +// +// hal_amba.c +// +// SPARC Architecture LEON3-specific private variables +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include +#include +#include +#include +#include +#include +#include // tracing macros +#include // which includes this file + +extern volatile LEON3_GpTimer_Regs_Map *LEON3_GpTimer_Regs; + +void hal_sparc_leon3_clock_init(cyg_uint32 period) { + cyg_hal_sparc_clock_period = (period); \ + + if (LEON3_GpTimer_Regs) { + + LEON3_BYPASS_STORE_PA(&LEON3_GpTimer_Regs ->e[0].val,(period)); + LEON3_BYPASS_STORE_PA(&LEON3_GpTimer_Regs ->e[0].rld,(period)); + LEON3_BYPASS_STORE_PA(&LEON3_GpTimer_Regs ->e[0].ctrl,0); + + LEON3_BYPASS_STORE_PA(&LEON3_GpTimer_Regs ->e[0].ctrl, + LEON3_GPTIMER_EN | + LEON3_GPTIMER_RL | + LEON3_GPTIMER_IRQEN | + LEON3_GPTIMER_LD); + } else { + diag_printf("Clock init failed"); + } +} + +cyg_uint32 hal_sparc_leon3_clock_read(void) { + if (LEON3_GpTimer_Regs) { + return LEON3_BYPASS_LOAD_PA(&LEON3_GpTimer_Regs ->e[0].val); + } + return 1; +} + +extern unsigned long LEON3_GpTimer_Irq; +cyg_uint32 hal_sparc_leon3_clock_irqnr(void) { + if (!LEON3_GpTimer_Irq) { + amba_init(); + } + return LEON3_GpTimer_Irq; +} diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_diag.c ecos-rep/packages/hal/sparc/leon3/current/src/hal_diag.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_diag.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_diag.c 2006-06-21 10:30:57.000000000 +0200 @@ -0,0 +1,90 @@ +//=========================================================================== +// +// hal_amba.c +// +// SPARC Architecture LEON3-specific private variables +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#include +#include +#include +#include +#include +#include +#include + +extern volatile LEON3_APBUART_Regs_Map *LEON3_APBUART_Regs; + +void hal_sparc_leon3_write_char(char c, int wait) { + //if( c != '\r' ) { + if (LEON3_APBUART_Regs) { + if (wait) { + unsigned int status; + do { + HAL_READ_UINT32( &(LEON3_APBUART_Regs->status), status ); + } while (!(status & LEON_REG_UART_STATUS_THE)); + } + HAL_WRITE_UINT32(&(LEON3_APBUART_Regs->data),c); + } + //} +} + +char hal_sparc_leon3_read_char(int wait) { + char c = 0; + if (LEON3_APBUART_Regs) { + if (wait) { + unsigned int status; + do { + HAL_READ_UINT32( &(LEON3_APBUART_Regs->status), status ); + } while (!(status & LEON_REG_UART_STATUS_DR)); + } + HAL_READ_UINT32(&(LEON3_APBUART_Regs->data),c); + } + return c; +} + + diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_help.cxx ecos-rep/packages/hal/sparc/leon3/current/src/hal_help.cxx --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_help.cxx 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_help.cxx 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,94 @@ +//========================================================================== +// +// access some c++ values +// +//========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// Copyright (C) 2002 Nick Garnett +// Copyright (C) 2003 Jonathan Larmour +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): +// Contributors: +// Date: +// Purpose: +// Description: +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + +#include + +#ifdef CYGFUN_KERNEL_API_C + +#include // base kernel types +#include // tracing macros +#include // assertion macros +#include // instrumentation +#include + +#include +#include // thread inlines +#include +#include +#include + +#include +#include +#include +#include + +#include // scheduler inlines +#include // clock inlines + +#include // C API + +externC int cyg_hal_get_current_threadid() +{ + Cyg_Thread *current = Cyg_Scheduler_Base::get_current_thread(); + return current ->get_unique_id(); +} + +externC int cyg_hal_get_current_cpuid() +{ + return CYG_KERNEL_CPU_THIS(); +} + + + + +#endif //CYGFUN_KERNEL_API_C diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_irq.c ecos-rep/packages/hal/sparc/leon3/current/src/hal_irq.c --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/src/hal_irq.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/src/hal_irq.c 2006-05-12 15:32:42.000000000 +0200 @@ -0,0 +1,234 @@ +//=========================================================================== +// +// hal_irq.c +// +// SPARC Architecture LEON3-specific private variables +// +//=========================================================================== +//####ECOSGPLCOPYRIGHTBEGIN#### +// ------------------------------------------- +// This file is part of eCos, the Embedded Configurable Operating System. +// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. +// +// eCos is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 2 or (at your option) any later version. +// +// eCos is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License along +// with eCos; if not, write to the Free Software Foundation, Inc., +// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. +// +// As a special exception, if other files instantiate templates or use macros +// or inline functions from this file, or you compile this file and link it +// with other works to produce a work based on this file, this file does not +// by itself cause the resulting work to be covered by the GNU General Public +// License. However the source code for this file must still be made available +// in accordance with section (3) of the GNU General Public License. +// +// This exception does not invalidate any other reasons why a work based on +// this file might be covered by the GNU General Public License. +// +// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc. +// at http://sources.redhat.com/ecos/ecos-license/ +// ------------------------------------------- +//####ECOSGPLCOPYRIGHTEND#### +//=========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): Gaisler Research (Konrad Eisele) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#ifdef CYGPKG_KERNEL +#include +#endif + +#include // Base types +#include // tracing macros +#include // assertion macros +#include + +#include +#include +#include +#include + +#define LEON_HARD_INT(x) (1 << (x)) +externC volatile LEON3_IrqCtrl_Regs_Map *LEON3_IrqCtrl_Regs; +#define LEON_IMASK(i) ((&LEON3_IrqCtrl_Regs ->mask[i])) +#define LEON_IFORCE(i) ((&LEON3_IrqCtrl_Regs ->force[i])) + +#define get_irqmask(irq) LEON_HARD_INT(irq) + +/*static inline unsigned long get_irqmask(unsigned int irq) +{ + unsigned long mask; + if (!irq || irq > 0xf) { + //diag_printf("leon_get_irqmask: false irq number\n"); + mask = 0; + } else { + mask = LEON_HARD_INT(irq); + } + return mask; +}*/ + +#ifndef CYGPKG_HAL_SMP_SUPPORT + +void leon3_disable_irq(unsigned int irq_nr) +{ + unsigned long mask, v; + mask = get_irqmask(irq_nr) & LEON_IRQMASK_R; + HAL_READ_UINT32(LEON_IMASK(0),v); + HAL_WRITE_UINT32(LEON_IMASK(0), (v & ~(mask))); + +} + +void leon3_enable_irq(unsigned int irq_nr) +{ + unsigned long mask,v; + mask = get_irqmask(irq_nr) & LEON_IRQMASK_R; + HAL_READ_UINT32(LEON_IMASK(0),v); + HAL_WRITE_UINT32(LEON_IMASK(0), (v | (mask))); +} + +#else + +unsigned long irq_mask; +unsigned long cpu_route_mask[CYGPKG_HAL_SMP_CPU_MAX]; +HAL_SPINLOCK_TYPE cyg_hal_smp_smpirq_lock = HAL_SPINLOCK_INIT_CLEAR; + +/* route all irq to 0 */ +void leon3_smpirq_init(void) { + int i; + /* + for (i=0; i +#include +#include +#include + +// ------------------------------------------------------------------------ +// Clock static to keep period recorded. +cyg_int32 cyg_hal_sparc_clock_period = 0; + +// ------------------------------------------------------------------------ +// Board specific startups. + +extern void hal_board_prestart( void ); +extern void hal_board_poststart( void ); + +static void leon2_eth_init(void) +{ + +} + +void hal_board_prestart( void ) +{ + +//#ifdef CYGPKG_DEVS_ETH_SPARC_LEON + leon2_eth_init(); +//#endif +} + +void hal_board_poststart( void ) +{ + + amba_init(); + + HAL_ENABLE_INTERRUPTS(); +} + +cyg_uint32 +hal_lsbit_index(cyg_uint32 mask) +{ + int i; + for (i = 0; i < 32; i++) { + if (mask & (1<= 0; i--) { + if (mask & (1<) +// Contributors: +// Date: 2004 +// Purpose: private amba for LEON3 processor. +// +//####DESCRIPTIONEND#### +// +//=========================================================================== + +#ifdef CYGPKG_KERNEL +#include +#endif + +#include // Base types +#include // tracing macros +#include // assertion macros +#include + +#include +#include +#include +#include + +#ifndef BUG +#define BUG() do { diag_printf("BUG() at %s %d\n", __FILE__, __LINE__); while(1); } while (1) +#endif + +__externC void cyg_scheduler_set_need_reschedule(void); +__externC void cyg_scheduler_timeslice_cpu(void); + +cyg_uint32 sparc_leon3_get_cpuid(void) +{ + unsigned int id; + __asm__ __volatile__( + "rd %%asr17,%0\n\t" + : "=r" (id) : ); + + return ((id >> 28) & 0xff); +} + + +extern __inline__ void __delay(unsigned long loops) +{ + __asm__ __volatile__("cmp %0, 0\n\t" + "1: bne 1b\n\t" + "subcc %0, 1, %0\n" : + "=&r" (loops) : + "0" (loops) : + "cc"); +} + +#ifdef CYGPKG_HAL_SMP_SUPPORT + +volatile unsigned int cyg_hal_smp_cpu_running = 0; +CYG_WORD32 cyg_hal_smp_cpu_running_count; +externC CYG_WORD32 *__interrupt_stack_vector[HAL_SMP_CPU_MAX]; +externC CYG_WORD32 __interrupt_stack_first; + +volatile int slavesem = 0; + +#define CYG_HAL_CPU_MARKRUNNING(c) cyg_hal_smp_cpu_running |= (1 << c); +#define CYG_HAL_CPU_ISRUNNING(c) (cyg_hal_smp_cpu_running & (1 << c)) + +/* master(cpu 0) coming up from arch/vector.S: after locore init, before cyg_start(). */ +__externC void cyg_hal_smp_init(void) { + volatile int slavesemold[32]; + HAL_SMP_CPU_TYPE cpu; + + do { + HAL_TAS_SET(slavesem, slavesemold[HAL_SMP_CPU_THIS()]); + } while (slavesemold[HAL_SMP_CPU_THIS()] == 1); + + + unsigned long cfg = sparc_leon3_get_dcachecfg(); + //cyg_hal_smp_cpu_running = 0; + + + + //leon3smp_diag_printf("Master Cpu %d came up\n",HAL_SMP_CPU_THIS()); + + if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) { + sparc_leon3_enable_snooping(); + } + else { + leon3smp_diag_printf("Caches disabled due to lack snooping\n"); + sparc_leon3_disable_cache(); + } + + + for( cpu = 0; cpu < HAL_SMP_CPU_MAX; cpu++ ) { + /* + if( cpu == HAL_SMP_CPU_THIS() ) { + CYG_HAL_CPU_MARKRUNNING(cpu); + cyg_hal_smp_cpu_running_count++; + } + */ + __interrupt_stack_vector[cpu] = (((unsigned int)(&__interrupt_stack_first)) + + (CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE * cpu) + + CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE); + diag_printf("Interrupt stack(%d): 0x%x-0x%x\n",cpu, + __interrupt_stack_vector[cpu], + ((unsigned int)__interrupt_stack_vector[cpu])+CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE); + + } + CYG_HAL_CPU_MARKRUNNING(0); + cyg_hal_smp_cpu_running_count++; + + slavesem = 0; + +} + +/* release the slaves that are idling , they'll come up at cyg_hal_smp_startup() */ +void cyg_hal_cpu_reset(HAL_SMP_CPU_TYPE cpu) { + int i, maxcpus; + unsigned int tmp; + + //leon3smp_diag_printf("Try to bring Cpu %d up, running: %d\n",cpu, CYG_HAL_CPU_ISRUNNING(cpu)); + + + if (!CYG_HAL_CPU_ISRUNNING(cpu)) { + //reset cpu + LEON3_IrqCtrl_Regs->mpstatus = 1<mpstatus) >> 28) & 0xf) + 1; */ +/* tmp = 0; */ +/* //for (i = HAL_SMP_CPU_MAX; i < maxcpus; i++) */ +/* for (i = 0; i < maxcpus; i++) */ +/* tmp |= (1 << i); */ +/* LEON3_IrqCtrl_Regs->mpstatus = tmp; */ +/* } */ + + + /* + maxcpus = (((LEON3_IrqCtrl_Regs->mpstatus) >> 28) & 0xf) + 1; + for (i = HAL_SMP_CPU_MAX; i < maxcpus; i++) + { + LEON3_IrqCtrl_Regs->mpstatus = 1<= cyg_hal_smp_cpu_running_count) { + BUG(); + } + do { + idx++; + while(! CYG_HAL_CPU_ISRUNNING(idx)) { + idx++; + } + } while (n--); + if (idx >= HAL_SMP_CPU_MAX) { + diag_printf("idx(%d)>=HAL_SMP_CPU_MAX(%d)\n",idx,HAL_SMP_CPU_MAX); + BUG(); + } + return idx; +} + +cyg_uint32 cyg_hal_smp_cpu_idx2count(cyg_uint32 n) { + int i, c = 0; + if (n >= HAL_SMP_CPU_MAX || !CYG_HAL_CPU_ISRUNNING(n)) { + diag_printf("n(%d)>=HAL_SMP_CPU_MAX(%d) || !CYG_HAL_CPU_ISRUNNING(n)\n",n,HAL_SMP_CPU_MAX); + BUG(); + } + for (i = 0; i < n;i++) { + if (CYG_HAL_CPU_ISRUNNING(i)) { + c++; + } + } + if (c >= cyg_hal_smp_cpu_running_count) { + diag_printf("c(%d)>=cyg_hal_smp_cpu_running_count(%d)\n",c,cyg_hal_smp_cpu_running_count); + BUG(); } + return c; +} + +int cyg_hal_smp_cpu_count(void) { + int i = 0,cpu = 0; + for( cpu = 0; cpu < HAL_SMP_CPU_MAX; cpu++ ) { + if (CYG_HAL_CPU_ISRUNNING(cpu)) { + i++; + }; + } + return i; +} + +unsigned int rmask[4] = {0, 1, 3, 7}; + + +externC void cyg_kernel_smp_startup(void); + +/* slave cpus coming from vector.S:wakeup write to mpirq->mpstatus */ +__externC void cyg_hal_smp_startup(void) +{ + volatile int slavesemold[32]; + + do { + HAL_TAS_SET(slavesem, slavesemold[HAL_SMP_CPU_THIS()]); + } while (slavesemold[HAL_SMP_CPU_THIS()] == 1); + + + HAL_SMP_CPU_TYPE cpu = HAL_SMP_CPU_THIS(); + +/* do { */ +/* //HAL_TAS_SET(slavesem, slavesemold); */ +/* //} while ((slavesemold == 1) && (cyg_hal_smp_cpu_running != rmask)); */ + //do {} while (cyg_hal_smp_cpu_running != rmask[cpu]); + + + CYG_HAL_CPU_MARKRUNNING(cpu); + unsigned long cfg = sparc_leon3_get_dcachecfg(); + + //leon3smp_diag_printf("Slave Cpu %d came up\n",cpu); + + if (cfg & ASI_LEON3_SYSCTRL_CFG_SNOOPING) { + sparc_leon3_enable_snooping(); + } else { + leon3smp_diag_printf("You have to enable snooping in the vhdl model or disable caches\n"); + sparc_leon3_disable_cache(); + } + + cyg_hal_smp_cpu_running_count++; + slavesem = 0; + cyg_kernel_smp_startup(); + + +} + + +/*------------------------------------------------------------------------*/ +// SMP message buffers. +// SMP CPUs pass messages to eachother via a small circular buffer +// protected by a spinlock. Each message is a single 32 bit word with +// a type code in the top 4 bits and any argument in the remaining +// 28 bits. + +#define SMP_MSGBUF_SIZE 4 + +static struct smp_msg_t +{ + HAL_SPINLOCK_TYPE lock; // protecting spinlock + volatile CYG_WORD32 msgs[SMP_MSGBUF_SIZE]; // message buffer + volatile CYG_WORD32 head; // head of list + volatile CYG_WORD32 tail; // tail of list + volatile CYG_WORD32 reschedule; // reschedule request + volatile CYG_WORD32 timeslice; // timeslice request +} smp_msg[HAL_SMP_CPU_MAX]; + +void cyg_hal_cpu_message( HAL_SMP_CPU_TYPE cpu, + CYG_WORD32 msg, + CYG_WORD32 arg, + CYG_WORD32 wait) { + CYG_INTERRUPT_STATE istate; + struct smp_msg_t *m = &smp_msg[cpu]; + int i; + //HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS(); + + //leon3smp_diag_printf("Cpu %d send to %d: %x \n",HAL_SMP_CPU_THIS(),cpu,msg); + + + HAL_DISABLE_INTERRUPTS( istate ); + + // Get access to the message buffer for the selected CPU + HAL_SPINLOCK_SPIN( m->lock ); + + if( msg == HAL_SMP_MESSAGE_RESCHEDULE ) + m->reschedule = true; + else if( msg == HAL_SMP_MESSAGE_TIMESLICE ) + m->timeslice = true; + else + { + CYG_WORD32 next = (m->tail + 1) & (SMP_MSGBUF_SIZE-1); + // If the buffer is full, wait for space to appear in it. + // This should only need to be done very rarely. + while( next == m->head ) { + HAL_SPINLOCK_CLEAR( m->lock ); + for( i = 0; i < 1000; i++ ); + HAL_SPINLOCK_SPIN( m->lock ); + } + m->msgs[m->tail] = msg | arg; + m->tail = next; + } + + // Now send an interrupt to the CPU. + //if( cyg_hal_smp_cpu_running[cpu] ) { + leon3_smpirq_raise(cpu); + //} + + HAL_SPINLOCK_CLEAR( m->lock ); + + // If we are expected to wait for the command to complete, then + // spin here until it does. We actually wait for the destination + // CPU to empty its input buffer. So we might wait for messages + // from other CPUs as well. But this is benign. + + while(wait) { + for( i = 0; i < 1000; i++ ); + HAL_SPINLOCK_SPIN( m->lock ); + if( m->head == m->tail ) + wait = false; + HAL_SPINLOCK_CLEAR( m->lock ); + } + + HAL_RESTORE_INTERRUPTS( istate ); + +} + + +/*------------------------------------------------------------------------*/ +__externC CYG_WORD32 cyg_hal_cpu_message_isr( CYG_WORD32 vector, CYG_ADDRWORD data ) +{ + HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS(); + struct smp_msg_t *m = &smp_msg[me]; + CYG_WORD32 ret = 1; + CYG_INTERRUPT_STATE istate; + + HAL_DISABLE_INTERRUPTS( istate ); + + HAL_SPINLOCK_SPIN( m->lock ); + + // First, acknowledge the interrupt. + + HAL_INTERRUPT_ACKNOWLEDGE( vector ); + + if( m->reschedule || m->timeslice ) + ret |= 2; // Ask for the DSR to be called. + + // Now pick messages out of the buffer and handle them + + while( m->head != m->tail ) + { + CYG_WORD32 msg = m->msgs[m->head]; + + switch( msg & HAL_SMP_MESSAGE_TYPE ) + { + case HAL_SMP_MESSAGE_RESCHEDULE: + ret |= 2; // Ask for the DSR to be called. + break; + case HAL_SMP_MESSAGE_MASK: + break; + case HAL_SMP_MESSAGE_UNMASK: + break; + case HAL_SMP_MESSAGE_REVECTOR: + break; + } + + // Update the head pointer after handling the message, so that + // the wait in cyg_hal_cpu_message() completes after the action + // requested. + m->head = (m->head + 1) & (SMP_MSGBUF_SIZE-1); + } + + HAL_SPINLOCK_CLEAR( m->lock ); + + HAL_RESTORE_INTERRUPTS( istate ); + + return ret; +} + + +/*------------------------------------------------------------------------*/ +// CPU message DSR. +// This is only executed if the message was +// HAL_SMP_MESSAGE_RESCHEDULE. It calls up into the kernel to effect a +// reschedule. + +__externC CYG_WORD32 cyg_hal_cpu_message_dsr( CYG_WORD32 vector, CYG_ADDRWORD data ) +{ + HAL_SMP_CPU_TYPE me = HAL_SMP_CPU_THIS(); + struct smp_msg_t *m = &smp_msg[me]; + CYG_INTERRUPT_STATE istate; + CYG_WORD32 reschedule, timeslice; + + HAL_DISABLE_INTERRUPTS( istate ); + HAL_SPINLOCK_SPIN( m->lock ); + + reschedule = m->reschedule; + timeslice = m->timeslice; + m->reschedule = m->timeslice = false; + + HAL_SPINLOCK_CLEAR( m->lock ); + HAL_RESTORE_INTERRUPTS( istate ); + + if( reschedule ) + { + //leon3smp_diag_printf("Cpu %d received reshedule\n",HAL_SMP_CPU_THIS()); + cyg_scheduler_set_need_reschedule(); + } + if( timeslice ) + { + //leon3smp_diag_printf("Cpu %d received timeslice\n",HAL_SMP_CPU_THIS()); + cyg_scheduler_timeslice_cpu(); + } + + return 0; +} + +#endif //CYGPKG_HAL_SMP_SUPPORT diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/support/README ecos-rep/packages/hal/sparc/leon3/current/support/README --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/support/README 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/support/README 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,32 @@ + +LEON/TSIM Support +================= + +See for information about the TSIM +simulator and Leon project per se. + +The simulator TSIM can be run "as one" with GDB by using the +script do-gdb-sim in this directory. The script can be used in +automated testing systems to run as if it were embedded within +GDB. It contains: + +---------------------------------------------------------------- +#! /bin/csh +tsim-leon -nfp -gdb >& /dev/stdout & +sparc-rtems-gdb -nw -nx $*:q +---------------------------------------------------------------- + +which simply runs tsim in background, directing its output to the +common stdout. + +The command to connect to the simulator target will be + + (gdb) target remote localhost:1234 + +This fully described in the TSIM documentation from + (home) + (flyer) + (doc) + + + diff -Naurb ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/support/do-gdb-sim ecos-rep/packages/hal/sparc/leon3/current/support/do-gdb-sim --- ecos-cvs-2005-09-06/packages/hal/sparc/leon3/current/support/do-gdb-sim 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/hal/sparc/leon3/current/support/do-gdb-sim 2005-09-05 16:06:32.000000000 +0200 @@ -0,0 +1,3 @@ +#! /bin/csh +tsim-leon -nfp -gdb >& /dev/stdout & +sparc-rtems-gdb -nw -nx $*:q diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/cdl/kernel.cdl ecos-rep/packages/kernel/current/cdl/kernel.cdl --- ecos-cvs-2005-09-06/packages/kernel/current/cdl/kernel.cdl 2003-07-01 19:34:53.000000000 +0200 +++ ecos-rep/packages/kernel/current/cdl/kernel.cdl 2005-09-05 16:21:09.000000000 +0200 @@ -160,6 +160,13 @@ default_value 0 } + cdl_component CYGPKG_KERNEL_SMP_TEST { + display "build SMP test" + flavor bool + requires CYGPKG_KERNEL_SMP_SUPPORT + default_value 0 + } + # --------------------------------------------------------------------- cdl_component CYGPKG_KERNEL_COUNTERS { display "Counters and clocks" @@ -327,6 +334,7 @@ . ((!CYGPKG_INFRA_DEBUG && !CYGPKG_KERNEL_INSTRUMENT && CYGFUN_KERNEL_API_C) ? " tests/dhrystone" : "") . ((CYGPKG_KERNEL_SMP_SUPPORT && CYGFUN_KERNEL_API_C) ? " tests/smp" : "") . ((!CYGINT_HAL_TESTS_NO_CACHES && CYGFUN_KERNEL_API_C) ? " tests/kcache1 tests/kcache2" : "") + . ((CYGPKG_KERNEL_SMP_TEST) ? " tests_smp/fft.c tests_smp/radix.c tests_smp/lu.c " : "") } description " This option specifies the set of tests for the eCos kernel." diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/include/smp.hxx ecos-rep/packages/kernel/current/include/smp.hxx --- ecos-cvs-2005-09-06/packages/kernel/current/include/smp.hxx 2002-05-24 01:06:51.000000000 +0200 +++ ecos-rep/packages/kernel/current/include/smp.hxx 2005-09-05 16:06:32.000000000 +0200 @@ -88,6 +88,8 @@ #define CYG_KERNEL_CPU_COUNT() HAL_SMP_CPU_COUNT() +#define CYG_KERNEL_CPU_START_COUNT() HAL_SMP_CPU_START_COUNT() + #define CYG_KERNEL_CPU_THIS() HAL_SMP_CPU_THIS() #define CYG_KERNEL_CPU_NONE HAL_SMP_CPU_NONE diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/src/sched/mlqueue.cxx ecos-rep/packages/kernel/current/src/sched/mlqueue.cxx --- ecos-cvs-2005-09-06/packages/kernel/current/src/sched/mlqueue.cxx 2004-09-24 18:57:12.000000000 +0200 +++ ecos-rep/packages/kernel/current/src/sched/mlqueue.cxx 2005-09-05 16:51:31.000000000 +0200 @@ -350,7 +350,8 @@ for(int i = 0; i < cpu_count; i++) { - HAL_SMP_CPU_TYPE cpu = (i + cpu_this) % cpu_count; + HAL_SMP_CPU_TYPE cpu = + HAL_SMP_CPU_COUNT2IDX ( (i + HAL_SMP_CPU_IDX2COUNT( cpu_this ) ) % cpu_count ); // If a CPU is not already marked for rescheduling, and its // current thread is of lower priority than _thread_, then @@ -464,12 +465,15 @@ #ifdef CYGPKG_KERNEL_SMP_SUPPORT + int c; HAL_SMP_CPU_TYPE cpu; HAL_SMP_CPU_TYPE cpu_count = CYG_KERNEL_CPU_COUNT(); HAL_SMP_CPU_TYPE cpu_this = CYG_KERNEL_CPU_THIS(); - for( cpu = 0; cpu < cpu_count; cpu++ ) + for( c = 0; c < cpu_count; c++ ) { + cpu = HAL_SMP_CPU_COUNT2IDX(c); + if( --timeslice_count[cpu] == 0 ) if( cpu == cpu_this ) timeslice_cpu(); diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/src/sched/sched.cxx ecos-rep/packages/kernel/current/src/sched/sched.cxx --- ecos-cvs-2005-09-06/packages/kernel/current/src/sched/sched.cxx 2002-08-09 19:13:28.000000000 +0200 +++ ecos-rep/packages/kernel/current/src/sched/sched.cxx 2005-09-05 16:51:31.000000000 +0200 @@ -321,7 +321,7 @@ HAL_SMP_CPU_TYPE cpu; - for( cpu = 0; cpu < CYG_KERNEL_CPU_COUNT(); cpu++ ) + for( cpu = 0; cpu < CYG_KERNEL_CPU_START_COUNT(); cpu++ ) { // Don't start this CPU, it is running already! if( cpu == CYG_KERNEL_CPU_THIS() ) diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests/timeslice.c ecos-rep/packages/kernel/current/tests/timeslice.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests/timeslice.c 2004-02-19 11:57:36.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests/timeslice.c 2005-11-07 16:41:28.000000000 +0100 @@ -224,7 +224,7 @@ CYG_TEST_INIT(); // Work out how many CPUs we actually have. - ncpus = CYG_KERNEL_CPU_COUNT(); + ncpus = CYGNUM_KERNEL_CPU_MAX; //CYG_KERNEL_CPU_COUNT(); cyg_thread_create(0, // Priority - just a number run_tests, // entry diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests/tm_basic.cxx ecos-rep/packages/kernel/current/tests/tm_basic.cxx --- ecos-cvs-2005-09-06/packages/kernel/current/tests/tm_basic.cxx 2005-03-27 19:29:58.000000000 +0200 +++ ecos-rep/packages/kernel/current/tests/tm_basic.cxx 2005-09-05 16:24:34.000000000 +0200 @@ -88,7 +88,7 @@ #define STACK_SIZE CYGNUM_HAL_STACK_SIZE_MINIMUM -#ifdef CYGMEM_REGION_ram_SIZE +#if defined(CYGMEM_REGION_ram_SIZE) && !(defined(CYGPKG_HAL_SPARC_LEON3_OPTIONS) || defined(CYGPKG_HAL_SPARC_LEON_OPTIONS)) #define CYG_THREAD_OVERHEAD (STACK_SIZE+sizeof(cyg_thread)+(sizeof(fun_times)*2)) #define NTEST_THREADS ((CYGMEM_REGION_ram_SIZE/16)/CYG_THREAD_OVERHEAD) #define CYG_MUTEX_OVERHEAD (sizeof(cyg_mutex_t)+sizeof(fun_times)) diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.SPLASH2 ecos-rep/packages/kernel/current/tests_smp/README.SPLASH2 --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.SPLASH2 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/README.SPLASH2 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,349 @@ +Date: Oct 19, 1994 + +This is the directory for the second release of the Stanford Parallel +Applications for Shared-Memory (SPLASH-2) programs. For further +information contact splash@mojave.stanford.edu. + +PLEASE NOTE: Due to our limited resources, we will be unable to spend +much time answering questions about the applications. + +splash.tar contains the tared version of all the files. Grabbing this +file will get you everything you need. We also keep the files +individually untared for partial retrieval. The splash.tar file is not +compressed, but the large files in it are. We attempted to compress the +splash.tar file to reduce the file size further, but this resulted in +a negative compression ratio. + + +DIFFERENCES BETWEEN SPLASH AND SPLASH-2: +---------------------------------------- + +The SPLASH-2 suite contains two types of codes: full applications and +kernels. Each of the codes utilizes the Argonne National Laboratories +(ANL) parmacs macros for parallel constructs. Unlike the codes in the +original SPLASH release, each of the codes assumes the use of a +"lightweight threads" model (which we hereafter refer to as the "threads" +model) in which child processes share the same virtual address space as +their parent process. In order for the codes to function correctly, +the CREATE macro should call the proper Unix system routine (e.g. "sproc" +in the Silicon Graphics IRIX operating system) instead of the "fork" +routine that was used for SPLASH. The difference is that processes +created with the Unix fork command receive their own private copies of +all global variables. In the threads model, child processes share the +same virtual address space, and hence all global data. Some of the +codes function correctly when the Unix "fork" command is used for child +process creation as well. Comments in the code header denote those +applications which function correctly with "fork." + + +MACROS: +------- + +Macros for the previous release of the SPLASH application suite can be +obtained via anonymous ftp to www-flash.stanford.edu. The macros are +contained in the pub/old_splash/splash/macros subdirectory. HOWEVER, +THE MACRO FILES MUST BE MODIFIED IN ORDER TO BE USED WITH SPLASH-2 CODES. +The CREATE macros must be changed so that they call the proper process +creation routine (See DIFFERENCES section above) instead of "fork." + +In this macros subdirectory, macros and sample makefiles are provided +for three machines: + +Encore Multimax (CMU Mach 2.5: C and Fortran) +SGI 4D/240 (IRIX System V Release 3.3: C only) +Alliant FX/8 (Alliant Rev. 5.0: C and Fortran) + +These macros work for us with the above operating systems. Unfortunately, +our limited resources prevent us from supporting them in any way or +even fielding questions about them. If they don't work for you, please +contact Argonne National Labs for a version that will. An e-mail address +to try might be monitor-users-request@mcs.anl.gov. An excerpt from +a message, received from Argonne, concerning obtaining the macros follows: + +"The parmacs package is in the public domain. Approximately 15 people at +Argonne (or associated with Argonne or students) have worked on the +parmacs package at one time or another. The parmacs package is +implemented via macros using the M4 macropreprocessor (standard on most +Unix systems). Current distribution of the software is somewhat ad hoc. +Most C versions can be obtained from netlib (send electronic mail to +netlib@ornl.gov with the message send index from parmacs). Fortran +versions have been emailed directly or sent on tape. The primary +documentation for the parmacs package is the book ``Portable Programs for +Parallel Processors'' by Lusk, et al, Holt, Rinehart, and Winston 1987." + +The makefiles provided in the individual program directories specify +a null macro set that will turn the parallel programs into sequential +ones. Note that we do not have a null macro set for FORTRAN. + + +CODE ENHANCEMENTS: +------------------ + +All of the codes are designed for shared address space multiprocessors +with physically distributed main memory. For these types of machines, +process migration and poor data distribution can decrease performance +to suboptimal levels. In the applications, comments indicating potential +enhancements can be found which will improve performance. Each potential +enhancement is denoted by a comment beginning with "POSSIBLE ENHANCEMENT". +The potential enhancements which we identify are: + + (1) Data Distribution + + Comments are placed in the code indicating where directives should + be placed so that data can be migrated to the local memories of + nodes, thus allowing for remote communication to be minimized. + + (2) Process-to-Processor Assignment + + Comments are placed in the code indicating where directives should + be placed so that processes can be "pinned" to processors, + preventing them from migrating from processor to processor. + +In addition, to facilitate simulation studies, we note points in the +codes where statistics gathering routines should be turned on so that +cold-start and initialization effects can be avoided. + +As previously mentioned, processes are assumed to be created through calls +to a "threads" model creation routine. One important side effect is that +this model causes all global variables to be shared (whereas the fork model +causes all processes to get their own private copy of global variables). +In order to mimic the behavior of global variables in the fork model, many +of the applications provide arrays of structures that can be accessed by +process ID, such as: + + struct per_process_info { + char pad[PAD_LENGTH]; + unsigned start_time; + unsigned end_time; + char pad[PAD_LENGTH]; + } PPI[MAX_PROCS]; + +In these structures, padding is inserted to ensure that the structure +information associated with each process can be placed on a different +page of memory, and can thus be explicitly migrated to that processor's +local memory system. We follow this strategy for certain variables since +these data really belong to a process and should be allocated in its local +memory. A programming model that had the ability to declare global private +data would have automatically ensured that these data were private, and +that false sharing did not occur across different structures in the +array. However, since the threads model does not provide this capability, +it is provided by explicitly introducing arrays of structures with padding. +The padding constants used in the programs (PAD_LENGTH in this example) +can easily be changed to suit the particular characteristics of a given +system. The actual data that is manipulated by individual applications +(e.g. grid points, particle data, etc) is not padded, however. + +Finally, for some applications we provide less-optimized versions of the +codes. The less-optimized versions utilize data structures that lead to +simpler implementations, but which do not allow for optimal data +distribution (and can thus generate false-sharing). + + +REPORT: +------- + +A report will be put together shortly describing the structure, function, +and performance characteristics of each application. The report will be +similar to the original SPLASH report (see the original report for the +issues discussed). The report will provide quantitative data (for two +different cache line size) for characteristics such as working set size +and miss rates (local versus remote, etc.). In addition, the report +will discuss cache behavior and synchronization behavior of the +applications as well. In the mean time, each application directory has +a README file that describes how to run each application. In addition, +most applications have comments in their headers describing how to run +each application. + + +README FILES: +------------- + +Each application has an associated README file. It is VERY important to +read these files carefully, as they discuss the important parameters to +supply for each application, as well as other issues involved in running +the programs. In each README file, we discuss the impact of explicitly +distributing data on the Stanford DASH Multiprocessor. Unless otherwise +specified, we assume that the default data distribution mechanism is +through round-robin page allocation. + + +PROBLEM SIZES: +-------------- + +For each application, the README file describes a recommended problem +size that is a reasonable base problem size that both can be simulated +and is not too small for reality on a machine with up to 64 processors. +For the purposes of studying algorithm performance, the parameters +associated with each application can be varied. However, for the +purposes of comparing machine architectures, the README files describe +which parameters can be varied, and which should remain constant (or at +their default values) for comparability. If the specific "base" +parameters that are specified are not used, then results which are +reported should explicitly state which parameters were changed, what +their new values are, and address why they were changed. + + +CORE PROGRAMS: +-------------- + +Since the number of programs has increased over SPLASH, and since not +everyone may be able to use all the programs in a given study, we +identify some of the programs as "core" programs that should be used +in most studies for comparability. In the currently available set, these +core programs include: + +(1) Ocean Simulation +(2) Hierarchical Radiosity +(3) Water Simulation with Spatial data structure +(4) Barnes-Hut +(5) FFT +(6) Blocked Sparse Cholesky Factorization +(7) Radix Sort + +The less optimized versions of the programs, when provided, should be +used only in addition to these. + + +MAILING LIST: +------------- + +Please send a note to splash@mojave.stanford.edu if you have copied over +the programs, so that we can put you on a mailing list for update reports. + + +AUTHORSHIP: +----------- + +The applications provided in the SPLASH-2 suite were developed by a number +of people. The report lists authors primarily responsible for the +development of each application code. The codes were made ready for +distribution and the README files were prepared by Steven Cameron Woo and +Jaswinder Pal Singh. + + +CODE CHANGES: +------------- + +If modifications are made to the codes which improve their performance, +we would like to hear about them. Please send email to +splash@mojave.stanford.edu detailing the changes. + + +UPDATE REPORTS: +--------------- + +Watch this file for information regarding changes to codes and additions +to the application suite. + + +CHANGES: +------- + +10-21-94: Ocean code, contiguous partitions, line 247 of slave1.C changed + from + + t2a[0][0] = hh3*t2a[0][0]+hh1*psi[procid][1][0][0]; + + to + + t2a[0][0] = hh3*t2a[0][0]+hh1*t2c[0][0]; + + This change does not affect correctness; it is an optimization + that was performed elsewhere in the code but overlooked here. + +11-01-94: Barnes, file code_io.C, line 55 changed from + + in_real(instr, tnow); + + to + + in_real(instr, &tnow); + +11-01-94: Raytrace, file main.C, lines 216-223 changed from + + if ((pid == 0) || (dostats)) + CLOCK(end); + + gm->partime[0] = (end - begin) & 0x7FFFFFFF; + if (pid == 0) gm->par_start_time = begin; + +/* printf("Process %ld elapsed time %lu.\n", pid, lapsed); */ + + } + + to + + if ((pid == 0) || (dostats)) { + CLOCK(end); + gm->partime[pid] = (end - begin) & 0x7FFFFFFF; + if (pid == 0) gm->par_start_time = begin; + } + +11-13-94: Raytrace, file memory.C + + The use of the word MAIN_INITENV in a comment in memory.c causes + m4 to expand this macro, and some implementations may get confused + and generate the wrong C code. + +11-13-94: Radiosity, file rad_main.C + + rad_main.C uses the macro CREATE_LITE. All three instances of + CREATE_LITE should be changed to CREATE. + +11-13-94: Water-spatial and Water-nsquared, file makefile + + makefiles were changed so that the compilation phases included the + CFLAGS options instead of the CCOPTS options, which did not exist. + +11-17-94: FMM, file particle.C + + Comment regarding data distribution of particle_array data + structure is incorrect. Round-robin allocation should be used. + +11-18-94: OCEAN, contiguous partitions, files main.C and linkup.C + + Eliminated a problem which caused non-doubleword aligned + accesses to doublewords for the uniprocessor case. + + main.C: Added lines 467-471: + + if (nprocs%2 == 1) { /* To make sure that the actual data + starts double word aligned, add an extra + pointer */ + d_size += sizeof(double ***); + } + + Added same lines in file linkup.C at line numbers 100 and 159. + +07-30-95: RADIX has been changed. A tree-structured parallel prefix + computation is now used instead of a linear one. + + LU had been modified. A comment describing how to distribute + data (one of the POSSIBLE ENHANCEMENTS) was incorrect for the + contiguous_blocks version of LU. Also, a modification was made + that reduces false sharing at line 206 of lu.C: + + last_malloc[i] = (double *) (((unsigned) last_malloc[i]) + PAGE_SIZE - + ((unsigned) last_malloc[i]) % PAGE_SIZE); + + A subdirectory shmem_files was added under the codes directory. + This directory contains a file that can be compiled on SGI machines + which replaces the libsgi.a file distributed in the original SPLASH + release. + +09-26-95: Fixed a bug in LU. Line 201 was changed from + + last_malloc[i] = (double *) G_MALLOC(proc_bytes[i]) + + to + + last_malloc[i] = (double *) G_MALLOC(proc_bytes[i] + PAGE_SIZE) + + Fixed similar bugs in WATER-NSQUARED and WATER-SPATIAL. Both + codes needed a barrier added into the mdmain.C files. In both + codes, the line + + BARRIER(gl->start, NumProcs); + + was added. In WATER-NSQUARED, it was added in mdmain.C at line + 84. In WATER-SPATIAL, it was added in mdmain.C at line 107. diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.fft ecos-rep/packages/kernel/current/tests_smp/README.fft --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.fft 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/README.fft 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,62 @@ +GENERAL INFORMATION: + +The FFT program is a complex, one-dimensional version of the "Six-Step" +FFT described in + +Bailey, D. H. FFTs in External or Hierarchical Memory. + Journal of Supercomputing, 4(1):23-35, March 1990. + +Specific optimizations in this implementation include: (1) Performing +staggered, blocked transposes that exploit cache-line reuse; (2) The +roots of unity data structure is arranged and distributed for only local +accesses during application of the roots of unity step; (3) A small set of +roots of unity elements are replicated locally at each processor for +computation of the 1D FFTs; and (4) The matrix data structures are padded +to reduce cache mapping conflicts. The algorithm used in this +implementation is described in: + +Woo, S. C., Singh, J. P., and Hennessy, J. L. The Performance Advantages + of Integrating Block Data Transfer in Cache-Coherent Multiprocessors. + Proceedings of the 6th International Conference on Architectural + Support for Programming Languages and Operating Systems (ASPLOS-VI), + October 1994. + +This program works under both the Unix FORK and SPROC models. + +RUNNING THE PROGRAM: + +To see how to run the program, please see the comment at the top of the +file fft.C, or run the application with the "-h" command line option. +Four command-line parameters MUST be specified: The number of points +to transform, the number of processors, the log base 2 of the cache +line size, and the number of cache lines. + +The number of complex data points to be transformed and the number of +processors being used can be varied according to the following rules. +The number of data points must be an even power of 2 (2**16, 2**18, +etc). The command-line option "-mM" specifies the even power of two (M), +so for 65,536 data points, the command line option is "-m16." The number +of processors must be a power of 2. + +The main data structures are padded to reduce cache mapping conflicts. +The constant PAGE_SIZE should be changed to reflect the page size (in +bytes) of the target system. In addition, the program uses a blocking +technique to exploit cache line reuse. Both the log base 2 of the cache +line size and the number of cache lines in the cache should be specified +at the command line in order to allow the blocking algorithm to work +effectively. + +BASE PROBLEM SIZE: + +The base problem size for an upto-64 processor machine is 65,536 complex +data points (M=16). The PAGE_SIZE constant should be changed to reflect +the page size (in bytes) of the target system. In addition, the log base +2 of the cache line size, the number of cache lines, and the number of +processors must be specified. + +DATA DISTRIBUTION: + +Our "POSSIBLE ENHANCEMENT" comments in the source code tell where one +might want to distribute data and how. Data distribution has an impact +on performance on the Stanford DASH multiprocessor. + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.lu ecos-rep/packages/kernel/current/tests_smp/README.lu --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.lu 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/README.lu 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,55 @@ +GENERAL INFORMATION: + +The LU program factors a dense matrix into the product of a lower +triangular and an upper triangular matrix. The factorization uses +blocking to exploit temporal locality on individual submatrix elements. +The algorithm used in this implementation is described in + +Woo, S. C., Singh, J. P., and Hennessy, J. L. The Performance Advantages + of Integrating Block Data Transfer in Cache-Coherent Multiprocessors. + Proceedings of the 6th International Conference on Architectural + Support for Programming Languages and Operating Systems (ASPLOS-VI), + October 1994. + +Two implementations are provided in the SPLASH-2 distribution: + + (1) Non-contiguous block allocation + + This implementation (contained in the non_contiguous_blocks + subdirectory) implements the matrix to be factored with a + two-dimensional array. This data structure prevents blocks from + being allocated contiguously, but leads to a conceptually simple + programming implementation. + + (2) Contiguous block allocation + + This implementation (contained in the contiguous_blocks + subdirectory) implements the matrix to be factored as an array + of blocks. This data structure allows blocks to be allocated + contiguously and entirely in the local memory of processors that + "own" them, thus enhancing data locality properties. + +These programs work under both the Unix FORK and SPROC models. + +RUNNING THE PROGRAM: + +To see how to run the program, please see the comment at the top of the +file lu.C, or run the application with the "-h" command line option. +Three parameters may be specified on the command line, of which the +ones that are normally changed are the matrix size and the number of +processors. It is suggested that the block size be kept at the value +B=16, since this value works well in practice. If this parameter is +changed, the new value should be reported in any results that are +presented. + +BASE PROBLEM SIZE: + +The base problem size for an upto-64 processor machine is a 512x512 matrix +with a block size of B=16. + +DATA DISTRIBUTION: + +Our "POSSIBLE ENHANCEMENT" comments in the source code tell where one +might want to distribute data and how. Data distribution has a small +impact on performance on the Stanford DASH multiprocessor. + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.radix ecos-rep/packages/kernel/current/tests_smp/README.radix --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/README.radix 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/README.radix 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,44 @@ +GENERAL INFORMATION: + +The RADIX program implements an integer radix sort based on the method +described in: + +Blelloch, G. E., et. al. A Comparison of Sorting Algorithms for the + Connection Machine CM-2. In Symposium on Parallel Algorithms and + Architectures, pp. 3-16, July 1991. + +A description of this implementation can be found in: + +Woo, S. C., Singh, J. P., and Hennessy, J. L. The Performance Advantages + of Integrating Message Passing in Cache-Coherent Multiprocessors. + Technical Report CSL-TR-93-593, Stanford University, December 1993. + +This program works under both the Unix FORK and SPROC models. + +RUNNING THE PROGRAM: + +To see how to run the program, please see the comment at the top of the +file radix.C, or run the application with the "-h" command line option. +Four command line parameters can be specified, of which the ones which +would normally be changed are the number of keys to sort, the radix +for sorting, and the number of processors. The radix used for sorting +must be a power of 2. Optional command line parameters allow timing +information to be printed out at the end of the program, testing to +make sure all keys are sorted correctly, and keys to be printed out +in sorted order. + +BASE PROBLEM SIZE: + +The base problem size for an upto-64 processor machine is 256k (262,144) +keys to be sorted and a radix of 1024. The default values should be +used for other parameters (except the number of processors, which can +be varied). For larger problems, the number of keys can also be +increased by factors of 2. Any changes to these parameters should be +reported when results are presented. + +DATA DISTRIBUTION: + +Our "POSSIBLE ENHANCEMENT" comments in the source code tell where one +might want to distribute data and how. Data distribution has an impact +on performance on the Stanford DASH multiprocessor. + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/SPLASH2.POSTING ecos-rep/packages/kernel/current/tests_smp/SPLASH2.POSTING --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/SPLASH2.POSTING 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/SPLASH2.POSTING 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,124 @@ +We are pleased to announce the release of the SPLASH-2 suite of +multiprocessor applications. SPLASH-2 is the successor to the SPLASH +suite that we previously released, and the programs in it are also +written assuming a coherent shared address space communication model. +SPLASH-2 contains several new applications, as well as improved versions +of applications from SPLASH. The suite is currently available via +anonymous ftp to + + www-flash.stanford.edu (in the pub/splash2 subdirectory) + +and via the World-Wide-Web at + + http://www-flash.stanford.edu/apps/SPLASH/ + +Several programs are currently available, and a few others will be added +shortly. The programs fall into two categories: full applications and +kernels. Additionally, we designate some of these as "core programs" +(see below). The applications and kernels currently available in the +SPLASH-2 suite include: + +Applications: + Ocean Simulation + Ray Tracer + Hierarchical Radiosity + Volume Renderer + Water Simulation with Spatial Data Structure + Water Simulation without Spatial Data Structure + Barnes-Hut (gravitational N-body simulation) + Adaptive Fast Multipole (gravitational N-body simulation) + +Kernels: + FFT + Blocked LU Decomposition + Blocked Sparse Cholesky Factorization + Radix Sort + +Programs that will appear soon include: + + PSIM4 - Particle Dynamics Simulation (full application) + Conjugate Gradient (kernel) + LocusRoute (standard cell router from SPLASH) + Protein Structure Prediction + Protein Sequencing + Parallel Probabilistic Inference + +In some cases, we provide both well-optimized and less-optimized versions +of the programs. For both the Ocean simulation and the Blocked LU +Decomposition kernel, less optimized versions of the codes are currently +available. + +There are important differences between applications in the SPLASH-2 suite +and applications in the SPLASH suite. These differences are noted in the +README.SPLASH2 file in the pub/splash2 directory. It is *VERY IMPORTANT* +that you read the README.SPLASH2 file, as well as the individual README +files in the program directories, before using the SPLASH-2 programs. +These files describe how to run the programs, provide commented annotations +about how to distribute data on a machine with physically distributed main +memory, and provides guidelines on the baseline problem sizes to use when +studying architectural interactions through simulation. + +Complete documentation of SPLASH2, including a detailed characterization +of performance as well as memory system interactions and synchronization +behavior, will appear in the SPLASH2 report that is currently being +written. + + +OPTIMIZATION STRATEGY: +---------------------- + +For each application and kernel, we note potential features or +enhancements that are typically machine-specific. These potential +enhancements are encapsulated within comments in the code starting with +the string "POSSIBLE ENHANCEMENT." The potential enhancements which we +identify are: + + (1) Data Distribution + + We note where data migration routines should be called in order to + enhance locality of data access. We do not distribute data by + default as different machines implement migration routines in + different ways, and on some machines this is not relevant. + + (2) Process-to-Processor Assignment + + We note where calls can be made to "pin" processes to specific + processors so that process migration can be avoided. We do not + do this by default, since different machines implement this + feature in different ways. + +In addition, to facilitate simulation studies, we note points in the +codes where statistics gathering routines should be turned on so that +cold-start and initialization effects can be avoided. + +For two programs (Ocean and LU), we provide less-optimized versions of +the codes. The less-optimized versions utilize data structures that +lead to simpler implementations, but which do not allow for optimal data +distribution (and can generate false-sharing). + + +CORE PROGRAMS: +-------------- + +Since the number of programs has increased over SPLASH, and since not +everyone may be able to use all the programs in a given study, we +identify some of the programs as "core" programs that should be used +in most studies for comparability. In the currently available set, +these core programs include: + +(1) Ocean Simulation +(2) Hierarchical Radiosity +(3) Water Simulation with Spatial data structure +(4) Barnes-Hut +(5) FFT +(6) Blocked Sparse Cholesky Factorization +(7) Radix Sort + +The less optimized versions of the programs, when available, should be +used only in addition to these. + +The base problem sizes that we recommend are provided in the README files +for individual applications. Please use at least these for experiments +with upto 64 processors. If changes are made to these base parameters +for further experimentation, these changes should be explicitly stated +in any results that are presented. diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/c.m4.ecos ecos-rep/packages/kernel/current/tests_smp/c.m4.ecos --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/c.m4.ecos 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/c.m4.ecos 2006-06-19 19:00:28.000000000 +0200 @@ -0,0 +1,290 @@ +divert(-1) +define(NEWPROC,) dnl +define(ENDLAB, 5283) dnl + +define(BARRIER, `{ +/*---------------------------------*/ + LOCK( ( $1[0].lock ) ); + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),$3,$1[0].count[0],$1[0].queue[0].count); + } + if ( $1[0].count[0] < ($2 -1) ) { + $1[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),$3,$1[0].count[0],$1[0].queue[0].count); + } + UNLOCK( $1[0].lock ); + SEMWAIT( $1[0].queue[0] ); + } + + if (dbg_on) { + diag_printf(" thread %d: thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),$3,$1[0].count[0],$1[0].queue[0].count); + } + + UNLOCK( $1[0].lock ); + + } else { + ( $1[0].count[0] )-- ; + //UNLOCK( $1[0].count_lock[0] ); + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),$3,$1[0].count[0],$1[0].queue[0].count); + } + SEMPOST( $1[0].queue[0] ); + } + +/*---------------------------------*/ +}') + + +define(BARDEC, `DECVAR($1,1,1,)') +define(BARINIT, `{MONINIT($1,1,1)}') + +define(GSDEC, `/*##########*/ +int ($1);') +define(GSINIT, `/*##########*/ +{ ($1) = 0; }') +define(GETSUB, `/*##########*/ +{ + if (($1)<=($3)) + ($2) = ($1)++; + else { + ($2) = -1; + ($1) = 0; + } +}') + +define(NU_GSDEC, `int ($1);') +define(NU_GSINIT, `{ ($1) = 0; }') +define(NU_GETSUB, `GETSUB($1,$2,$3,$4)') + +define(ADEC, `int ($1);') +define(AINIT, `{/*##########*/;}') +define(PROBEND, `{/*##########*/;}') + +define(LOCKDEC, `cyg_spinlock_t $1;') +define(LOCKINIT, `cyg_spinlock_init( &$1,0 );') +define(LOCK, `cyg_spinlock_spin(&$1);') +define(UNLOCK, `cyg_spinlock_clear(&$1);') + +define(SEMINIT, `{ cyg_semaphore_init(&$1,$2);}') +define(SEMWAIT, `{ cyg_semaphore_wait(&$1);}') +define(SEMPOST, `{ cyg_semaphore_post(&$1);}') +define(SEMDEC, ` cyg_sem_t $1;') + +define(NLOCKDEC, `int ($1);') +define(NLOCKINIT, `{/*##########*/;}') +define(NLOCK, `{/*##########*/;}') +define(NUNLOCK, `{/*##########*/;}') + +define(ALOCKDEC, `DECVAR($1,0,$2)') +define(ALOCKINIT, `{ MONINIT($1,0,$2);}') +define(ALOCK, `{ MENTER($1,$2);}') +define(AULOCK, `{ MEXIT($1,$2);}') + + +define(PAUSEDEC, ` ') +define(PAUSEINIT, `{/*##########*/;}') +define(CLEARPAUSE, `{/*##########*/;}') +define(SETPAUSE, `{/*##########*/;}') +define(EVENT, `{/*##########*/;}') +define(WAITPAUSE, `{/*##########*/;}') +define(PAUSE, `{/*##########*/;}') + +define(AUG_ON, ` ') +define(AUG_OFF, ` ') +define(TRACE_ON, ` ') +define(TRACE_OFF, ` ') +define(REF_TRACE_ON, ` ') +define(REF_TRACE_OFF, ` ') +define(DYN_TRACE_ON, `;') +define(DYN_TRACE_OFF, `;') +define(DYN_REF_TRACE_ON, `;') +define(DYN_REF_TRACE_OFF, `;') +define(DYN_SIM_ON, `;') +define(DYN_SIM_OFF, `;') +define(DYN_SCHED_ON, `;') +define(DYN_SCHED_OFF, `;') +define(AUG_SET_LOLIMIT, `;') +define(AUG_SET_HILIMIT, `;') + +define(MENTER, `LOCK($1[$2].lock);') +define(DELAY, `{$1[$3].count[$2]++; + UNLOCK($1[$3].lock) + SEMWAIT($1[$3].queue[$2]);}') +define(CONTINUE, `{ + if ($1[$3].count[$2]) { + ($1[$3].count[$2])--; + SEMPOST($1[$3].queue[$2]) + } else + UNLOCK($1[$3].lock) + goto `L'ENDLAB; +`LGO'ENDLAB: ; +}') +define(MEXIT, `{ + UNLOCK($1[$2].lock); `L'ENDLAB: ; + define(`ENDLAB', eval(ENDLAB+1)) +}') + +define(WAIT_FOR_END, `{ +;}') + +/* create()*/ +define(CREATE,` +{ + /*---------------------------------------*/ + stack[i] = calloc(STACK_SIZE, 1); + cyg_thread_create(10, // Priority - just a number + $1, // entry + 0, // index + "slave", // Name + stack[i], // Stack + STACK_SIZE, // Size + &threadh[i], // Handle + &thread[i] // Thread data structure + ); + cyg_thread_resume( threadh[i] ); + /*---------------------------------------*/ +} +') + +define(MAIN_INITENV, `{;}') +define(MAIN_END, ` +{ + diag_printf("FP test end\n"); + return 0; +} +') +define(MAIN_ENV,` +/*---------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int smp_cyg_test_main(int argc, char **argv); + +void smp_cyg_test_main_call(void *p) { + smp_cyg_test_main(smp_cyg_test_argc, smp_cyg_test_argv); +} + + +/* #define STACK_SIZE 0x1b000 */ +#define STACK_SIZE 8192 +static cyg_thread smp_cyg_test_thread; +static char smp_cyg_test_stack[STACK_SIZE]; +static cyg_handle_t smp_cyg_test_threadh; + + + +cyg_handle_t threadh[64]; +char *stack[64]; +cyg_thread thread[64]; + + +externC void cyg_user_start( void ) +{ + CYG_TEST_INIT(); + + diag_printf("Starting test app\n"); + + cyg_thread_create(10, // Priority - just a number + smp_cyg_test_main_call, // entry + 0, // index + "smp test", // Name + smp_cyg_test_stack, // Stack + STACK_SIZE, // Size + &smp_cyg_test_threadh, // Handle + &smp_cyg_test_thread // Thread data structure + ); + cyg_thread_resume( smp_cyg_test_threadh ); + /*cyg_scheduler_start();*/ +} + + +/*---------------------------------------*/ +') + +define(ENV, ` ') +define(EXTERN_ENV, ` + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + ') + +define(G_MALLOC, `calloc($1, 1);') +define(G_FREE, `;') +define(G_MALLOC_F, `malloc($1);') +define(NU_MALLOC, `malloc($1);') +define(NU_FREE, `;') +define(NU_MALLOC_F, `malloc($1)') + +define(GET_HOME, `{($1) = 0;}') +define(GET_PID, `{($1) = 0;}') +define(AUG_DELAY, `{sleep ($1);}') +define(ST_LOG, `{;}') +define(SET_HOME, `{;}') + +/* clock()*/ +define(CLOCK, `{ + ($1) = cyg_current_time()*10; +} +') +divert(0) + + + +define(DECVAR,` +/*---------------------------------------*/ +struct $1TYP { + LOCKDEC(lock); + ifelse(eval($2 > 0),1,int count[$2];,) + ifelse(eval($2 > 0),1, SEMDEC(queue[$2]);,) + $4 + } $1[$3]; +/*---------------------------------------*/ + ' +) + +define(MONINIT, `{ +/*---------------------------------------*/ + int mon_dum1,mon_dum2; + ifelse(eval($2 > 0),1, + for (mon_dum1=0; mon_dum1 < $3; mon_dum1++) + for (mon_dum2=0; mon_dum2 < $2; mon_dum2++) { + $1[mon_dum1].count[mon_dum2] = 0; + SEMINIT($1[mon_dum1].queue[mon_dum2],0); + },,) + for (mon_dum1=0; mon_dum1 < $3; mon_dum1++) { + LOCKINIT($1[mon_dum1].lock); + } +/*---------------------------------------*/ +}') + + + + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft.C ecos-rep/packages/kernel/current/tests_smp/fft.C --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft.C 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/fft.C 2006-06-19 19:00:28.000000000 +0200 @@ -0,0 +1,1057 @@ +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Perform 1D fast Fourier transform using six-step FFT method */ +/* */ +/* 1) Performs staggered, blocked transposes for cache-line reuse */ +/* 2) Roots of unity rearranged and distributed for only local */ +/* accesses during application of roots of unity */ +/* 3) Small set of roots of unity elements replicated locally for */ +/* 1D FFTs (less than root N elements replicated at each node) */ +/* 4) Matrix data structures are padded to reduce cache mapping */ +/* conflicts */ +/* */ +/* Command line options: */ +/* */ +/* -mM : M = even integer; 2**M total complex data points transformed. */ +/* -pP : P = number of processors; Must be a power of 2. */ +/* -nN : N = number of cache lines. */ +/* -lL : L = Log base 2 of cache line length in bytes. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Perform FFT and inverse FFT. Test output by comparing the */ +/* integral of the original data to the integral of the data */ +/* that results from performing the FFT and inverse FFT. */ +/* -o : Print out complex data points. */ +/* -h : Print out command line options. */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include + +#define MAXRAND 2147483647 +#define PAGE_SIZE 4096 +#define NUM_CACHE_LINES 65536 +#define LOG2_LINE_SIZE 4 +#define PI 3.1416 +#define DEFAULT_M 10 +#define DEFAULT_P 1 + +#include + +MAIN_ENV + +#define SWAP(a,b) {double tmp; tmp=a; a=b; b=tmp;} + +struct GlobalMemory { + int id; + LOCKDEC(idlock) + BARDEC(start) + int *transtimes; + int *totaltimes; + int starttime; + int finishtime; + int initdonetime; +} *Global; + +int dbg_on = 0; + +int P = DEFAULT_P; +int M = DEFAULT_M; +int N; /* N = 2^M */ +int rootN; /* rootN = N^1/2 */ +double *x; /* x is the original time-domain data */ +double *trans; /* trans is used as scratch space */ +double *umain; /* umain is roots of unity for 1D FFTs */ +double *umain2; /* umain2 is entire roots of unity matrix */ +int test_result = 0; +int doprint = 0; +int dostats = 0; +int transtime = 0; +int transtime2 = 0; +int avgtranstime = 0; +int avgcomptime = 0; +unsigned int transstart = 0; +unsigned int transend = 0; +int maxtotal=0; +int mintotal=0; +double maxfrac=0; +double minfrac=0; +double avgfractime=0; +int orig_num_lines = NUM_CACHE_LINES; /* number of cache lines */ +int num_cache_lines = NUM_CACHE_LINES; /* number of cache lines */ +int log2_line_size = LOG2_LINE_SIZE; +int line_size; +int rowsperproc; +double ck1; +double ck3; /* checksums for testing answer */ +int pad_length; + +void SlaveStart(); +double TouchArray(double *,double *,double *,double *,int,int,int,int); +void FFT1D(int,int,int,double *,double *,double *,double *,int,int *,int, + int,int,int,int,int,int,struct GlobalMemory *); +double CheckSum(); +double drand48(); +int log_2(int); +void printerr(char *); +volatile int thread_array[4] = {0, 0, 0, 0}; + +int smp_cyg_test_main(int argc, char **argv) +{ + int i; + int j; + int c; + extern char *optarg; + int m1; + int factor; + int pages; + unsigned int start; + //memset (thread_array,0,sizeof(thread_array)); + + CLOCK(start); + + +// extern Cyg_Mempool_dlmalloc *cygmem_memalloc_heaps[ 2 ]; +// cygmem_memalloc_heaps[0]. + + + // printf(" thread %d Arguments (%d): ",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),argc); +// for (i = 0;i < argc;i++){ +// printf("%s ",argv[i]); +// } +// printf("\n"); + + while ((c = getopt(argc, argv, "p:m:n:l:stoh")) != -1) { + switch(c) { + case 'p': P = atoi(optarg); + P = HAL_SMP_CPU_MAX; + if (P < 1) { + printerr("P must be >= 1\n"); + exit(-1); + } + if (log_2(P) == -1) { + printerr("P must be a power of 2\n"); + exit(-1); + } + break; + case 'm': M = atoi(optarg); + m1 = M/2; + if (2*m1 != M) { + printerr("M must be even\n"); + exit(-1); + } + break; + case 'n': num_cache_lines = atoi(optarg); + orig_num_lines = num_cache_lines; + if (num_cache_lines < 1) { + printerr("Number of cache lines must be >= 1\n"); + exit(-1); + } + break; + case 'l': log2_line_size = atoi(optarg); + if (log2_line_size < 0) { + printerr("Log base 2 of cache line length in bytes must be >= 0\n"); + exit(-1); + } + break; + case 's': dostats = !dostats; + break; + case 't': test_result = !test_result; + break; + case 'o': doprint = !doprint; + break; + case 'h': printf("Usage: FFT \n\n"); + printf("options:\n"); + printf(" -mM : M = even integer; 2**M total complex data points transformed.\n"); + printf(" -pP : P = number of processors; Must be a power of 2.\n"); + printf(" -nN : N = number of cache lines.\n"); + printf(" -lL : L = Log base 2 of cache line length in bytes.\n"); + printf(" -s : Print individual processor timing statistics.\n"); + printf(" -t : Perform FFT and inverse FFT. Test output by comparing the\n"); + printf(" integral of the original data to the integral of the data that\n"); + printf(" results from performing the FFT and inverse FFT.\n"); + printf(" -o : Print out complex data points.\n"); + printf(" -h : Print out command line options.\n\n"); + printf("Default: FFT -m%1d -p%1d -n%1d -l%1d\n", + DEFAULT_M,DEFAULT_P,NUM_CACHE_LINES,LOG2_LINE_SIZE); + exit(0); + break; + } + } + + if (P > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + MAIN_INITENV(,80000000); + + N = 1<= P\n"); + exit(-1); + } + + line_size = 1 << log2_line_size; + if (line_size < 2*sizeof(double)) { + printf("WARNING: Each element is a complex double (%d bytes)\n",2*sizeof(double)); + printf(" => Less than one element per cache line\n"); + printf(" Computing transpose blocking factor\n"); + factor = (2*sizeof(double)) / line_size; + num_cache_lines = orig_num_lines / factor; + } + if (line_size <= 2*sizeof(double)) { + pad_length = 1; + } else { + pad_length = line_size / (2*sizeof(double)); + } + + if (rowsperproc * rootN * 2 * sizeof(double) >= PAGE_SIZE) { + pages = (2 * pad_length * sizeof(double) * rowsperproc) / PAGE_SIZE; + if (pages * PAGE_SIZE != 2 * pad_length * sizeof(double) * rowsperproc) { + pages ++; + } + pad_length = (pages * PAGE_SIZE) / (2 * sizeof(double) * rowsperproc); + } else { + pad_length = (PAGE_SIZE - (rowsperproc * rootN * 2 * sizeof(double))) / + + (2 * sizeof(double) * rowsperproc); + if (pad_length * (2 * sizeof(double) * rowsperproc) != + (PAGE_SIZE - (rowsperproc * rootN * 2 * sizeof(double)))) { + printerr("Padding algorithm unsuccessful\n"); + exit(-1); + } + } + + Global = (struct GlobalMemory *) G_MALLOC(sizeof(struct GlobalMemory)); + if (Global == NULL) { + printf("Could not malloc memory for Global (%d)\n",sizeof(struct GlobalMemory)); + exit(-1); + } + + + x = (double *) G_MALLOC(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE); + trans = (double *) G_MALLOC(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE); + umain = (double *) G_MALLOC(2*rootN*sizeof(double)); + umain2 = (double *) G_MALLOC(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE); + + + Global->transtimes = (int *) G_MALLOC(P*sizeof(int)); + Global->totaltimes = (int *) G_MALLOC(P*sizeof(int)); + if (x == NULL) { + printerr("Could not malloc memory for x\n"); + exit(-1); + } else if (trans == NULL) { + printerr("Could not malloc memory for trans\n"); + exit(-1); + } else if (umain == NULL) { + printerr("Could not malloc memory for umain\n"); + exit(-1); + } else if (umain2 == NULL) { + printerr("Could not malloc memory for umain2\n"); + exit(-1); + } + + x = (double *) (((unsigned) x) + PAGE_SIZE - ((unsigned) x) % PAGE_SIZE); + trans = (double *) (((unsigned) trans) + PAGE_SIZE - ((unsigned) trans) % PAGE_SIZE); + umain2 = (double *) (((unsigned) umain2) + PAGE_SIZE - ((unsigned) umain2) % PAGE_SIZE); + +/* In order to optimize data distribution, the data structures x, trans, + and umain2 have been aligned so that each begins on a page boundary. + This ensures that the amount of padding calculated by the program is + such that each processor's partition ends on a page boundary, thus + ensuring that all data from these structures that are needed by a + processor can be allocated to its local memory */ + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the x, + trans, and umain2 data structures across physically distributed + memories as desired. + + One way to place data is as follows: + + double *base; + int i; + + i = ((N/P)+(rootN/P)*pad_length)*2; + base = &(x[0]); + for (j=0;jstart); + LOCKINIT(Global->idlock); + Global->id = 0; + InitX(N, x); /* place random values in x */ + + if (test_result) { + ck1 = CheckSum(N, x); + } + if (doprint) { + printf("Original data values:\n"); + PrintArray(N, x); + } + + InitU(N,umain); /* initialize u arrays*/ + InitU2(N,umain2,rootN); + + /* fire off P processes */ + for (i=1; itranstimes[0]; + printf("\n"); + printf(" PROCESS STATISTICS\n"); + printf(" Computation Transpose Transpose\n"); + printf(" Proc Time Time Fraction\n"); + printf(" 0 %10d %10d %8.5f\n", + Global->totaltimes[0],Global->transtimes[0], + ((double)Global->transtimes[0])/Global->totaltimes[0]); + if (dostats) { + transtime2 = Global->transtimes[0]; + avgtranstime = Global->transtimes[0]; + avgcomptime = Global->totaltimes[0]; + maxtotal = Global->totaltimes[0]; + mintotal = Global->totaltimes[0]; + maxfrac = ((double)Global->transtimes[0])/Global->totaltimes[0]; + minfrac = ((double)Global->transtimes[0])/Global->totaltimes[0]; + avgfractime = ((double)Global->transtimes[0])/Global->totaltimes[0]; + for (i=1;itranstimes[i] > transtime) { + transtime = Global->transtimes[i]; + } + if (Global->transtimes[i] < transtime2) { + transtime2 = Global->transtimes[i]; + } + if (Global->totaltimes[i] > maxtotal) { + maxtotal = Global->totaltimes[i]; + } + if (Global->totaltimes[i] < mintotal) { + mintotal = Global->totaltimes[i]; + } + if (((double)Global->transtimes[i])/Global->totaltimes[i] > maxfrac) { + maxfrac = ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + if (((double)Global->transtimes[i])/Global->totaltimes[i] < minfrac) { + minfrac = ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + printf(" %3d %10d %10d %f\n", + i,Global->totaltimes[i],Global->transtimes[i], + ((double)Global->transtimes[i])/Global->totaltimes[i]); + avgtranstime += Global->transtimes[i]; + avgcomptime += Global->totaltimes[i]; + avgfractime += ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + printf(" Avg %10f %10f %f\n", + ((double) avgcomptime)/P,((double) avgtranstime)/P,avgfractime/P); + printf(" Max %10d %10d %f\n", + maxtotal,transtime,maxfrac); + printf(" Min %10d %10d %f\n", + mintotal,transtime2,minfrac); + } + Global->starttime = start; + printf("\n"); + printf(" TIMING INFORMATION\n"); + printf("Start time : %16d\n", + Global->starttime); + printf("Initialization finish time : %16d\n", + Global->initdonetime); + printf("Overall finish time : %16d\n", + Global->finishtime); + printf("Total time with initialization : %16d\n", + Global->finishtime-Global->starttime); + printf("Total time without initialization : %16d\n", + Global->finishtime-Global->initdonetime); + printf("Overall transpose time : %16d\n", + transtime); + printf("Overall transpose fraction : %f\n", + ((double) transtime)/(Global->finishtime-Global->initdonetime)); + printf("\n"); + + if (test_result) { + ck3 = CheckSum(N, x); + printf(" INVERSE FFT TEST RESULTS\n"); + printf("Checksum difference is %f (%f, %f)\n", + ck1-ck3, ck1, ck3); + if (fabs(ck1-ck3) < 0.001) { + printf("TEST PASSED\n"); + } else { + printf("TEST FAILED\n"); + } + } + + MAIN_END; +} + + +void SlaveStart() +{ + int i; + int j; + int MyNum; + double error; + double *upriv; + int initdone; + int finish; + int l_transtime=0; + int MyFirst; + int MyLast; + + LOCK(Global->idlock); + MyNum = Global->id; + Global->id++; +#ifdef FFT_DBG + printf("Slave %d started\n",MyNum); +#endif + UNLOCK(Global->idlock); + + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + BARRIER(Global->start, P, 1); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 1\n",MyNum); UNLOCK(Global->idlock); +#endif + + upriv = (double *) malloc(2*(rootN-1)*sizeof(double)); + if (upriv == NULL) { + printf("Proc %d could not malloc memory for upriv\n",MyNum); + exit(-1); + } + for (i=0;i<2*(rootN-1);i++) { + upriv[i] = umain[i]; + } + + MyFirst = rootN*MyNum/P; + MyLast = rootN*(MyNum+1)/P; + + TouchArray(x, trans, umain2, upriv, N, MyNum, MyFirst, MyLast); + + BARRIER(Global->start, P, 2); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 2\n",MyNum); UNLOCK(Global->idlock); +#endif + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + if ((MyNum == 0) || (dostats)) { + CLOCK(initdone); + } + + /* perform forward FFT */ + FFT1D(1, M, N, x, trans, upriv, umain2, MyNum, &l_transtime, MyFirst, + MyLast, pad_length, P, test_result, doprint, dostats, Global); + + /* perform backward FFT */ + if (test_result) { + FFT1D(-1, M, N, x, trans, upriv, umain2, MyNum, &l_transtime, MyFirst, + MyLast, pad_length, P, test_result, doprint, dostats, Global); + } + + if ((MyNum == 0) || (dostats)) { + CLOCK(finish); + Global->transtimes[MyNum] = l_transtime; + Global->totaltimes[MyNum] = finish-initdone; + } + if (MyNum == 0) { + Global->finishtime = finish; + Global->initdonetime = initdone; + } + + thread_array[MyNum] = 1; +} + + +double TouchArray(x, scratch, u, upriv, N, MyNum, MyFirst, MyLast) + +double *x; +double *scratch; +double *u; +double *upriv; +int N; +int MyNum; +int MyFirst; +int MyLast; + +{ + int i,j,k; + double tot = 0.0; + + /* touch my data */ + for (j=0;j<2*(rootN-1);j++) { + tot += upriv[j]; + } + for (j=MyFirst; j rootN-1) { + return; + } + u[2*(base+j)] = cos(2.0*PI*j/(2*n1)); + u[2*(base+j)+1] = -sin(2.0*PI*j/(2*n1)); + } + } +} + + +InitU2(N, u, n1) + +int N; +double *u; +int n1; + +{ + int i,j,k; + int base; + + for (j=0; j>1; + } + return(j); +} + + +void FFT1D(direction, M, N, x, scratch, upriv, umain2, MyNum, l_transtime, + MyFirst, MyLast, pad_length, P, test_result, doprint, dostats, + Global) + +int direction; +int M; +int N; +int *l_transtime; +double *x; +double *upriv; +double *scratch; +double *umain2; +int MyFirst; +int MyLast; +int pad_length; +int P; +int test_result; +int doprint; +int dostats; +struct GlobalMemory *Global; + +{ + int i; + int j; + int m1; + int n1; + int flag = 0; + unsigned int clocktime1; + unsigned int clocktime2; + + m1 = M/2; + n1 = 1<start, P, 3); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 3\n",MyNum); UNLOCK(Global->idlock); +#endif + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime1); + } + + /* transpose from x into scratch */ + Transpose(n1, x, scratch, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime2); + *l_transtime += (clocktime2-clocktime1); + } + + /* do n1 1D FFTs on columns */ + for (j=MyFirst; jstart, P, 4); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 4\n",MyNum); UNLOCK(Global->idlock); +#endif + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime1); + } + /* transpose */ + Transpose(n1, scratch, x, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime2); + *l_transtime += (clocktime2-clocktime1); + } + + /* do n1 1D FFTs on columns again */ + for (j=MyFirst; jstart, P, 5); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 5\n",MyNum); UNLOCK(Global->idlock); +#endif + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime1); + } + + /* transpose back */ + Transpose(n1, x, scratch, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + CLOCK(clocktime2); + *l_transtime += (clocktime2-clocktime1); + } + + BARRIER(Global->start, P, 6); +#ifdef FFT_DBG + LOCK(Global->idlock); printf("Slave %d left barrier 6\n",MyNum); UNLOCK(Global->idlock); +#endif + + /* copy columns from scratch to x */ + if ((test_result) || (doprint)) { + for (j=MyFirst; jstart, P, 7); +} + + +TwiddleOneCol(direction, n1, N, j, u, x, pad_length) + +int direction; +int n1; +int N; +int j; +double *u; +double *x; +int pad_length; + +{ + int i; + double omega_r; + double omega_c; + double x_r; + double x_c; + double r1; + double c1; + double r2; + double c2; + + for (i=0; i k) { + SWAP(x[2*j], x[2*k]); + SWAP(x[2*j+1], x[2*k+1]); + } + } +} + + +FFT1DOnce(direction, M, N, u, x) + +int direction; +int M; +int N; +double *u; +double *x; + +{ + int j; + int k; + int q; + int L; + int r; + int Lstar; + double *u1; + double *x1; + double *x2; + double omega_r; + double omega_c; + double tau_r; + double tau_c; + double x_r; + double x_c; + + Reverse(N, M, x); + + for (q=1; q<=M; q++) { + L = 1< diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft.c ecos-rep/packages/kernel/current/tests_smp/fft.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/fft.c 2006-06-21 10:30:57.000000000 +0200 @@ -0,0 +1,1460 @@ + + + + + + + + + + + +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Perform 1D fast Fourier transform using six-step FFT method */ +/* */ +/* 1) Performs staggered, blocked transposes for cache-line reuse */ +/* 2) Roots of unity rearranged and distributed for only local */ +/* accesses during application of roots of unity */ +/* 3) Small set of roots of unity elements replicated locally for */ +/* 1D FFTs (less than root N elements replicated at each node) */ +/* 4) Matrix data structures are padded to reduce cache mapping */ +/* conflicts */ +/* */ +/* Command line options: */ +/* */ +/* -mM : M = even integer; 2**M total complex data points transformed. */ +/* -pP : P = number of processors; Must be a power of 2. */ +/* -nN : N = number of cache lines. */ +/* -lL : L = Log base 2 of cache line length in bytes. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Perform FFT and inverse FFT. Test output by comparing the */ +/* integral of the original data to the integral of the data */ +/* that results from performing the FFT and inverse FFT. */ +/* -o : Print out complex data points. */ +/* -h : Print out command line options. */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include + +#define MAXRAND 2147483647 +#define PAGE_SIZE 4096 +#define NUM_CACHE_LINES 65536 +#define LOG2_LINE_SIZE 4 +#define PI 3.1416 +#define DEFAULT_M 10 +#define DEFAULT_P 1 + +#include + + +/*---------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int smp_cyg_test_main(int argc, char **argv); + +void smp_cyg_test_main_call(void *p) { + smp_cyg_test_main(smp_cyg_test_argc, smp_cyg_test_argv); +} + + +/* #define STACK_SIZE 0x1b000 */ +#define STACK_SIZE 8192 +static cyg_thread smp_cyg_test_thread; +static char smp_cyg_test_stack[STACK_SIZE]; +static cyg_handle_t smp_cyg_test_threadh; + + + +cyg_handle_t threadh[64]; +char *stack[64]; +cyg_thread thread[64]; + + +externC void cyg_user_start( void ) +{ + CYG_TEST_INIT(); + + diag_printf("Starting test app\n"); + + cyg_thread_create(10, // Priority - just a number + smp_cyg_test_main_call, // entry + 0, // index + "smp test", // Name + smp_cyg_test_stack, // Stack + STACK_SIZE, // Size + &smp_cyg_test_threadh, // Handle + &smp_cyg_test_thread // Thread data structure + ); + cyg_thread_resume( smp_cyg_test_threadh ); + /*cyg_scheduler_start();*/ +} + + +/*---------------------------------------*/ + + +#define SWAP(a,b) {double tmp; tmp=a; a=b; b=tmp;} + +struct GlobalMemory { + int id; + cyg_spinlock_t idlock; + +/*---------------------------------------*/ +struct startTYP { + cyg_spinlock_t lock;; + int count[1]; + cyg_sem_t queue[1];; + + } start[1]; +/*---------------------------------------*/ + + + int *transtimes; + int *totaltimes; + int starttime; + int finishtime; + int initdonetime; +} *Global; + +int dbg_on = 0; + +int P = DEFAULT_P; +int M = DEFAULT_M; +int N; /* N = 2^M */ +int rootN; /* rootN = N^1/2 */ +double *x; /* x is the original time-domain data */ +double *trans; /* trans is used as scratch space */ +double *umain; /* umain is roots of unity for 1D FFTs */ +double *umain2; /* umain2 is entire roots of unity matrix */ +int test_result = 0; +int doprint = 0; +int dostats = 0; +int transtime = 0; +int transtime2 = 0; +int avgtranstime = 0; +int avgcomptime = 0; +unsigned int transstart = 0; +unsigned int transend = 0; +int maxtotal=0; +int mintotal=0; +double maxfrac=0; +double minfrac=0; +double avgfractime=0; +int orig_num_lines = NUM_CACHE_LINES; /* number of cache lines */ +int num_cache_lines = NUM_CACHE_LINES; /* number of cache lines */ +int log2_line_size = LOG2_LINE_SIZE; +int line_size; +int rowsperproc; +double ck1; +double ck3; /* checksums for testing answer */ +int pad_length; + +void SlaveStart(); +double TouchArray(double *,double *,double *,double *,int,int,int,int); +void FFT1D(int,int,int,double *,double *,double *,double *,int,int *,int, + int,int,int,int,int,int,struct GlobalMemory *); +double CheckSum(); +double drand48(); +int log_2(int); +void printerr(char *); +volatile int thread_array[4] = {0, 0, 0, 0}; + +int smp_cyg_test_main(int argc, char **argv) +{ + int i; + int j; + int c; + extern char *optarg; + int m1; + int factor; + int pages; + unsigned int start; + //memset (thread_array,0,sizeof(thread_array)); + + { + (start) = cyg_current_time()*10; +} +; + + +// extern Cyg_Mempool_dlmalloc *cygmem_memalloc_heaps[ 2 ]; +// cygmem_memalloc_heaps[0]. + + + // printf(" thread %d Arguments (%d): ",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),argc); +// for (i = 0;i < argc;i++){ +// printf("%s ",argv[i]); +// } +// printf("\n"); + + while ((c = getopt(argc, argv, "p:m:n:l:stoh")) != -1) { + switch(c) { + case 'p': P = atoi(optarg); + P = HAL_SMP_CPU_MAX; + if (P < 1) { + printerr("P must be >= 1\n"); + exit(-1); + } + if (log_2(P) == -1) { + printerr("P must be a power of 2\n"); + exit(-1); + } + break; + case 'm': M = atoi(optarg); + m1 = M/2; + if (2*m1 != M) { + printerr("M must be even\n"); + exit(-1); + } + break; + case 'n': num_cache_lines = atoi(optarg); + orig_num_lines = num_cache_lines; + if (num_cache_lines < 1) { + printerr("Number of cache lines must be >= 1\n"); + exit(-1); + } + break; + case 'l': log2_line_size = atoi(optarg); + if (log2_line_size < 0) { + printerr("Log base 2 of cache line length in bytes must be >= 0\n"); + exit(-1); + } + break; + case 's': dostats = !dostats; + break; + case 't': test_result = !test_result; + break; + case 'o': doprint = !doprint; + break; + case 'h': printf("Usage: FFT \n\n"); + printf("options:\n"); + printf(" -mM : M = even integer; 2**M total complex data points transformed.\n"); + printf(" -pP : P = number of processors; Must be a power of 2.\n"); + printf(" -nN : N = number of cache lines.\n"); + printf(" -lL : L = Log base 2 of cache line length in bytes.\n"); + printf(" -s : Print individual processor timing statistics.\n"); + printf(" -t : Perform FFT and inverse FFT. Test output by comparing the\n"); + printf(" integral of the original data to the integral of the data that\n"); + printf(" results from performing the FFT and inverse FFT.\n"); + printf(" -o : Print out complex data points.\n"); + printf(" -h : Print out command line options.\n\n"); + printf("Default: FFT -m%1d -p%1d -n%1d -l%1d\n", + DEFAULT_M,DEFAULT_P,NUM_CACHE_LINES,LOG2_LINE_SIZE); + exit(0); + break; + } + } + + if (P > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + {;}; + + N = 1<= P\n"); + exit(-1); + } + + line_size = 1 << log2_line_size; + if (line_size < 2*sizeof(double)) { + printf("WARNING: Each element is a complex double (%d bytes)\n",2*sizeof(double)); + printf(" => Less than one element per cache line\n"); + printf(" Computing transpose blocking factor\n"); + factor = (2*sizeof(double)) / line_size; + num_cache_lines = orig_num_lines / factor; + } + if (line_size <= 2*sizeof(double)) { + pad_length = 1; + } else { + pad_length = line_size / (2*sizeof(double)); + } + + if (rowsperproc * rootN * 2 * sizeof(double) >= PAGE_SIZE) { + pages = (2 * pad_length * sizeof(double) * rowsperproc) / PAGE_SIZE; + if (pages * PAGE_SIZE != 2 * pad_length * sizeof(double) * rowsperproc) { + pages ++; + } + pad_length = (pages * PAGE_SIZE) / (2 * sizeof(double) * rowsperproc); + } else { + pad_length = (PAGE_SIZE - (rowsperproc * rootN * 2 * sizeof(double))) / + + (2 * sizeof(double) * rowsperproc); + if (pad_length * (2 * sizeof(double) * rowsperproc) != + (PAGE_SIZE - (rowsperproc * rootN * 2 * sizeof(double)))) { + printerr("Padding algorithm unsuccessful\n"); + exit(-1); + } + } + + Global = (struct GlobalMemory *) calloc(sizeof(struct GlobalMemory), 1);; + if (Global == NULL) { + printf("Could not malloc memory for Global (%d)\n",sizeof(struct GlobalMemory)); + exit(-1); + } + + + x = (double *) calloc(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE, 1);; + trans = (double *) calloc(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE, 1);; + umain = (double *) calloc(2*rootN*sizeof(double), 1);; + umain2 = (double *) calloc(2*(N+rootN*pad_length)*sizeof(double)+PAGE_SIZE, 1);; + + + Global->transtimes = (int *) calloc(P*sizeof(int), 1);; + Global->totaltimes = (int *) calloc(P*sizeof(int), 1);; + if (x == NULL) { + printerr("Could not malloc memory for x\n"); + exit(-1); + } else if (trans == NULL) { + printerr("Could not malloc memory for trans\n"); + exit(-1); + } else if (umain == NULL) { + printerr("Could not malloc memory for umain\n"); + exit(-1); + } else if (umain2 == NULL) { + printerr("Could not malloc memory for umain2\n"); + exit(-1); + } + + x = (double *) (((unsigned) x) + PAGE_SIZE - ((unsigned) x) % PAGE_SIZE); + trans = (double *) (((unsigned) trans) + PAGE_SIZE - ((unsigned) trans) % PAGE_SIZE); + umain2 = (double *) (((unsigned) umain2) + PAGE_SIZE - ((unsigned) umain2) % PAGE_SIZE); + +/* In order to optimize data distribution, the data structures x, trans, + and umain2 have been aligned so that each begins on a page boundary. + This ensures that the amount of padding calculated by the program is + such that each processor's partition ends on a page boundary, thus + ensuring that all data from these structures that are needed by a + processor can be allocated to its local memory */ + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the x, + trans, and umain2 data structures across physically distributed + memories as desired. + + One way to place data is as follows: + + double *base; + int i; + + i = ((N/P)+(rootN/P)*pad_length)*2; + base = &(x[0]); + for (j=0;jstart[mon_dum1].count[mon_dum2] = 0; + { cyg_semaphore_init(&Global->start[mon_dum1].queue[mon_dum2],0);}; + } + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) { + cyg_spinlock_init( &Global->start[mon_dum1].lock,0 );; + } +/*---------------------------------------*/ +}}; + cyg_spinlock_init( &Global->idlock,0 );; + Global->id = 0; + InitX(N, x); /* place random values in x */ + + if (test_result) { + ck1 = CheckSum(N, x); + } + if (doprint) { + printf("Original data values:\n"); + PrintArray(N, x); + } + + InitU(N,umain); /* initialize u arrays*/ + InitU2(N,umain2,rootN); + + /* fire off P processes */ + for (i=1; itranstimes[0]; + printf("\n"); + printf(" PROCESS STATISTICS\n"); + printf(" Computation Transpose Transpose\n"); + printf(" Proc Time Time Fraction\n"); + printf(" 0 %10d %10d %8.5f\n", + Global->totaltimes[0],Global->transtimes[0], + ((double)Global->transtimes[0])/Global->totaltimes[0]); + if (dostats) { + transtime2 = Global->transtimes[0]; + avgtranstime = Global->transtimes[0]; + avgcomptime = Global->totaltimes[0]; + maxtotal = Global->totaltimes[0]; + mintotal = Global->totaltimes[0]; + maxfrac = ((double)Global->transtimes[0])/Global->totaltimes[0]; + minfrac = ((double)Global->transtimes[0])/Global->totaltimes[0]; + avgfractime = ((double)Global->transtimes[0])/Global->totaltimes[0]; + for (i=1;itranstimes[i] > transtime) { + transtime = Global->transtimes[i]; + } + if (Global->transtimes[i] < transtime2) { + transtime2 = Global->transtimes[i]; + } + if (Global->totaltimes[i] > maxtotal) { + maxtotal = Global->totaltimes[i]; + } + if (Global->totaltimes[i] < mintotal) { + mintotal = Global->totaltimes[i]; + } + if (((double)Global->transtimes[i])/Global->totaltimes[i] > maxfrac) { + maxfrac = ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + if (((double)Global->transtimes[i])/Global->totaltimes[i] < minfrac) { + minfrac = ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + printf(" %3d %10d %10d %f\n", + i,Global->totaltimes[i],Global->transtimes[i], + ((double)Global->transtimes[i])/Global->totaltimes[i]); + avgtranstime += Global->transtimes[i]; + avgcomptime += Global->totaltimes[i]; + avgfractime += ((double)Global->transtimes[i])/Global->totaltimes[i]; + } + printf(" Avg %10f %10f %f\n", + ((double) avgcomptime)/P,((double) avgtranstime)/P,avgfractime/P); + printf(" Max %10d %10d %f\n", + maxtotal,transtime,maxfrac); + printf(" Min %10d %10d %f\n", + mintotal,transtime2,minfrac); + } + Global->starttime = start; + printf("\n"); + printf(" TIMING INFORMATION\n"); + printf("Start time : %16d\n", + Global->starttime); + printf("Initialization finish time : %16d\n", + Global->initdonetime); + printf("Overall finish time : %16d\n", + Global->finishtime); + printf("Total time with initialization : %16d\n", + Global->finishtime-Global->starttime); + printf("Total time without initialization : %16d\n", + Global->finishtime-Global->initdonetime); + printf("Overall transpose time : %16d\n", + transtime); + printf("Overall transpose fraction : %f\n", + ((double) transtime)/(Global->finishtime-Global->initdonetime)); + printf("\n"); + + if (test_result) { + ck3 = CheckSum(N, x); + printf(" INVERSE FFT TEST RESULTS\n"); + printf("Checksum difference is %f (%f, %f)\n", + ck1-ck3, ck1, ck3); + if (fabs(ck1-ck3) < 0.001) { + printf("TEST PASSED\n"); + } else { + printf("TEST FAILED\n"); + } + } + + +{ + diag_printf("FP test end\n"); + return 0; +} +; +} + + +void SlaveStart() +{ + int i; + int j; + int MyNum; + double error; + double *upriv; + int initdone; + int finish; + int l_transtime=0; + int MyFirst; + int MyLast; + + cyg_spinlock_spin(&Global->idlock);; + MyNum = Global->id; + Global->id++; +#ifdef FFT_DBG + printf("Slave %d started\n",MyNum); +#endif + cyg_spinlock_clear(&Global->idlock);; + + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 1\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + + upriv = (double *) malloc(2*(rootN-1)*sizeof(double)); + if (upriv == NULL) { + printf("Proc %d could not malloc memory for upriv\n",MyNum); + exit(-1); + } + for (i=0;i<2*(rootN-1);i++) { + upriv[i] = umain[i]; + } + + MyFirst = rootN*MyNum/P; + MyLast = rootN*(MyNum+1)/P; + + TouchArray(x, trans, umain2, upriv, N, MyNum, MyFirst, MyLast); + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 2\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + if ((MyNum == 0) || (dostats)) { + { + (initdone) = cyg_current_time()*10; +} +; + } + + /* perform forward FFT */ + FFT1D(1, M, N, x, trans, upriv, umain2, MyNum, &l_transtime, MyFirst, + MyLast, pad_length, P, test_result, doprint, dostats, Global); + + /* perform backward FFT */ + if (test_result) { + FFT1D(-1, M, N, x, trans, upriv, umain2, MyNum, &l_transtime, MyFirst, + MyLast, pad_length, P, test_result, doprint, dostats, Global); + } + + if ((MyNum == 0) || (dostats)) { + { + (finish) = cyg_current_time()*10; +} +; + Global->transtimes[MyNum] = l_transtime; + Global->totaltimes[MyNum] = finish-initdone; + } + if (MyNum == 0) { + Global->finishtime = finish; + Global->initdonetime = initdone; + } + + thread_array[MyNum] = 1; +} + + +double TouchArray(x, scratch, u, upriv, N, MyNum, MyFirst, MyLast) + +double *x; +double *scratch; +double *u; +double *upriv; +int N; +int MyNum; +int MyFirst; +int MyLast; + +{ + int i,j,k; + double tot = 0.0; + + /* touch my data */ + for (j=0;j<2*(rootN-1);j++) { + tot += upriv[j]; + } + for (j=MyFirst; j rootN-1) { + return; + } + u[2*(base+j)] = cos(2.0*PI*j/(2*n1)); + u[2*(base+j)+1] = -sin(2.0*PI*j/(2*n1)); + } + } +} + + +InitU2(N, u, n1) + +int N; +double *u; +int n1; + +{ + int i,j,k; + int base; + + for (j=0; j>1; + } + return(j); +} + + +void FFT1D(direction, M, N, x, scratch, upriv, umain2, MyNum, l_transtime, + MyFirst, MyLast, pad_length, P, test_result, doprint, dostats, + Global) + +int direction; +int M; +int N; +int *l_transtime; +double *x; +double *upriv; +double *scratch; +double *umain2; +int MyFirst; +int MyLast; +int pad_length; +int P; +int test_result; +int doprint; +int dostats; +struct GlobalMemory *Global; + +{ + int i; + int j; + int m1; + int n1; + int flag = 0; + unsigned int clocktime1; + unsigned int clocktime2; + + m1 = M/2; + n1 = 1<start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 3\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + + if ((MyNum == 0) || (dostats)) { + { + (clocktime1) = cyg_current_time()*10; +} +; + } + + /* transpose from x into scratch */ + Transpose(n1, x, scratch, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + { + (clocktime2) = cyg_current_time()*10; +} +; + *l_transtime += (clocktime2-clocktime1); + } + + /* do n1 1D FFTs on columns */ + for (j=MyFirst; jstart[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 4\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + + if ((MyNum == 0) || (dostats)) { + { + (clocktime1) = cyg_current_time()*10; +} +; + } + /* transpose */ + Transpose(n1, scratch, x, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + { + (clocktime2) = cyg_current_time()*10; +} +; + *l_transtime += (clocktime2-clocktime1); + } + + /* do n1 1D FFTs on columns again */ + for (j=MyFirst; jstart[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 5\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + + if ((MyNum == 0) || (dostats)) { + { + (clocktime1) = cyg_current_time()*10; +} +; + } + + /* transpose back */ + Transpose(n1, x, scratch, MyNum, MyFirst, MyLast, pad_length); + + if ((MyNum == 0) || (dostats)) { + { + (clocktime2) = cyg_current_time()*10; +} +; + *l_transtime += (clocktime2-clocktime1); + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +#ifdef FFT_DBG + cyg_spinlock_spin(&Global->idlock);; printf("Slave %d left barrier 6\n",MyNum); cyg_spinlock_clear(&Global->idlock);; +#endif + + /* copy columns from scratch to x */ + if ((test_result) || (doprint)) { + for (j=MyFirst; jstart[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; +} + + +TwiddleOneCol(direction, n1, N, j, u, x, pad_length) + +int direction; +int n1; +int N; +int j; +double *u; +double *x; +int pad_length; + +{ + int i; + double omega_r; + double omega_c; + double x_r; + double x_c; + double r1; + double c1; + double r2; + double c2; + + for (i=0; i k) { + SWAP(x[2*j], x[2*k]); + SWAP(x[2*j+1], x[2*k+1]); + } + } +} + + +FFT1DOnce(direction, M, N, u, x) + +int direction; +int M; +int N; +double *u; +double *x; + +{ + int j; + int k; + int q; + int L; + int r; + int Lstar; + double *u1; + double *x1; + double *x2; + double omega_r; + double omega_c; + double tau_r; + double tau_c; + double x_r; + double x_c; + + Reverse(N, M, x); + + for (q=1; q<=M; q++) { + L = 1< diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft_arg.c ecos-rep/packages/kernel/current/tests_smp/fft_arg.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/fft_arg.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/fft_arg.c 2006-05-12 15:32:42.000000000 +0200 @@ -0,0 +1,18 @@ + +//___________________________________________ +#define smp_cyg_test_argc 11 +char *_cyg_argv[] = { + "fft.exe", + "-s", + "-t", + "-l", + "5", + "-n", + "256", + "-p", + "2", /* not used, using HAL_SMP_CPU_MAX */ + "-m", + "16" +}; +#define smp_cyg_test_argv &_cyg_argv +//''''''''''''''''''''''''''''''''''''''''''' diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/getopt.c ecos-rep/packages/kernel/current/tests_smp/getopt.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/getopt.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/getopt.c 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,654 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifndef __STDC__ +# ifndef const +# define const +# endif +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +#define BAD_OPTION '\0' +int optopt = BAD_OPTION; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +static int +my_strlen (str) + const char *str; +{ + int n = 0; + while (*str++) + n++; + return n; +} + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. + + To perform the swap, we first reverse the order of all elements. So + all options now come before all non options, but they are in the + wrong order. So we put back the options and non options in original + order by reversing them again. For example: + original input: a b c -x -y + reverse all: -y -x c b a + reverse options: -x -y c b a + reverse non options: -x -y a b c +*/ + +#if __STDC__ || defined(PROTO) +static void exchange (char **argv); +#endif + +static void +exchange (argv) + char **argv; +{ + char *temp, **first, **last; + + /* Reverse all the elements [first_nonopt, optind) */ + first = &argv[first_nonopt]; + last = &argv[optind-1]; + while (first < last) { + temp = *first; *first = *last; *last = temp; first++; last--; + } + /* Put back the options in order */ + first = &argv[first_nonopt]; + first_nonopt += (optind - last_nonopt); + last = &argv[first_nonopt - 1]; + while (first < last) { + temp = *first; *first = *last; *last = temp; first++; last--; + } + + /* Put back the non options in order */ + first = &argv[first_nonopt]; + last_nonopt = optind; + last = &argv[last_nonopt-1]; + while (first < last) { + temp = *first; *first = *last; *last = temp; first++; last--; + } +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return BAD_OPTION after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return BAD_OPTION. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound = 0; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == my_strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += my_strlen (nextchar); + optind++; + return BAD_OPTION; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += my_strlen (nextchar); + return BAD_OPTION; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += my_strlen (nextchar); + return optstring[0] == ':' ? ':' : BAD_OPTION; + } + } + nextchar += my_strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return BAD_OPTION; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return BAD_OPTION; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = BAD_OPTION; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} + +int +getopt_long (argc, argv, options, long_options, opt_index) + int argc; + char *const *argv; + const char *options; + const struct option *long_options; + int *opt_index; +{ + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); +} + + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/getopt.h ecos-rep/packages/kernel/current/tests_smp/getopt.h --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/getopt.h 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/getopt.h 2006-03-02 11:39:27.000000000 +0100 @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +//#define printf diag_printf + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ || defined(PROTO) +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu.C ecos-rep/packages/kernel/current/tests_smp/lu.C --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu.C 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/lu.C 2006-02-23 13:59:21.000000000 +0100 @@ -0,0 +1,788 @@ +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Parallel dense blocked LU factorization (no pivoting) */ +/* */ +/* This version contains one dimensional arrays in which the matrix */ +/* to be factored is stored. */ +/* */ +/* Command line options: */ +/* */ +/* -nN : Decompose NxN matrix. */ +/* -pP : P = number of processors. */ +/* -bB : Use a block size of B. BxB elements should fit in cache for */ +/* good performance. Small block sizes (B=8, B=16) work well. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Test output. */ +/* -o : Print out matrix values. */ +/* -h : Print out command line options. */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include +#include + +#include + +MAIN_ENV + +#define MAXRAND 2147483647 +#define DEFAULT_N 128 +#define DEFAULT_P 1 +#define DEFAULT_B 16 +#define min(a,b) ((a) < (b) ? (a) : (b)) + +struct GlobalMemory { + double *t_in_fac; + double *t_in_solve; + double *t_in_mod; + double *t_in_bar; + double *completion; + unsigned int starttime; + unsigned int rf; + unsigned int rs; + unsigned int done; + int id; + BARDEC(start) + LOCKDEC(idlock) +} *Global; + +struct LocalCopies { + double t_in_fac; + double t_in_solve; + double t_in_mod; + double t_in_bar; +}; + +int dbg_on = 0; +int n = DEFAULT_N; /* The size of the matrix */ +int P = DEFAULT_P; /* Number of processors */ +int block_size = DEFAULT_B; /* Block dimension */ +int nblocks; /* Number of blocks in each dimension */ +int num_rows; /* Number of processors per row of processor grid */ +int num_cols; /* Number of processors per col of processor grid */ +double *a; /* a = lu; l and u both placed back in a */ +double *rhs; +int *proc_bytes; /* Bytes to malloc per processor to hold blocks + of A*/ +int test_result = 0; /* Test result of factorization? */ +int doprint = 0; /* Print out matrix values? */ +int dostats = 0; /* Print out individual processor statistics? */ + +void SlaveStart(); +void OneSolve(int, int, double *, int, int); +void lu0(double *,int, int); +void bdiv(double *, double *, int, int, int, int); +void bmodd(double *, double*, int, int, int, int); +void bmod(double *, double *, double *, int, int, int, int); +void daxpy(double *, double *, int, double); +int BlockOwner(int, int); +void lu(int, int, int, struct LocalCopies *, int); +void InitA(double *); +double TouchA(int, int); +void PrintA(); +void CheckResult(int, double *, double *); +void printerr(char *); +volatile cyg_thread *thread_array[64]; + + +int smp_cyg_test_main(argc, argv) + +int argc; +char **argv; + +{ + int i, j; + int ch; + extern char *optarg; + int MyNum=0; + double mint, maxt, avgt; + double min_fac, min_solve, min_mod, min_bar; + double max_fac, max_solve, max_mod, max_bar; + double avg_fac, avg_solve, avg_mod, avg_bar; + int proc_num; + unsigned int start; + + memset (thread_array,0,sizeof(thread_array)); + + CLOCK(start); + + while ((ch = getopt(argc, argv, "n:p:b:cstoh")) != -1) { + switch(ch) { + case 'n': n = atoi(optarg); break; + case 'p': P = atoi(optarg); + P = HAL_SMP_CPU_MAX; break; + case 'b': block_size = atoi(optarg); break; + case 's': dostats = 1; break; + case 't': test_result = !test_result; break; + case 'o': doprint = !doprint; break; + case 'h': diag_printf("Usage: LU \n\n"); + diag_printf("options:\n"); + diag_printf(" -nN : Decompose NxN matrix.\n"); + diag_printf(" -pP : P = number of processors.\n"); + diag_printf(" -bB : Use a block size of B. BxB elements should fit in cache for \n"); + diag_printf(" good performance. Small block sizes (B=8, B=16) work well.\n"); + diag_printf(" -c : Copy non-locally allocated blocks to local memory before use.\n"); + diag_printf(" -s : Print individual processor timing statistics.\n"); + diag_printf(" -t : Test output.\n"); + diag_printf(" -o : Print out matrix values.\n"); + diag_printf(" -h : Print out command line options.\n\n"); + diag_printf("Default: LU -n%1d -p%1d -b%1d\n", + DEFAULT_N,DEFAULT_P,DEFAULT_B); + exit(0); + break; + } + } + if (P > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + MAIN_INITENV(,150000000) + + diag_printf("\n"); + diag_printf("Blocked Dense LU Factorization\n"); + diag_printf(" %d by %d Matrix\n",n,n); + diag_printf(" %d Processors\n",P); + diag_printf(" %d by %d Element Blocks\n",block_size,block_size); + diag_printf("\n"); + diag_printf("\n"); + + num_rows = (int) sqrt((double) P); + for (;;) { + num_cols = P/num_rows; + if (num_rows*num_cols == P) + break; + num_rows--; + } + nblocks = n/block_size; + if (block_size * nblocks != n) { + nblocks++; + } + + a = (double *) G_MALLOC(n*n*sizeof(double)); + rhs = (double *) G_MALLOC(n*sizeof(double)); + + Global = (struct GlobalMemory *) G_MALLOC(sizeof(struct GlobalMemory)); + Global->t_in_fac = (double *) G_MALLOC(P*sizeof(double)); + Global->t_in_mod = (double *) G_MALLOC(P*sizeof(double)); + Global->t_in_solve = (double *) G_MALLOC(P*sizeof(double)); + Global->t_in_bar = (double *) G_MALLOC(P*sizeof(double)); + Global->completion = (double *) G_MALLOC(P*sizeof(double)); + + if (Global == NULL) { + printerr("Could not malloc memory for Global\n"); + exit(-1); + } else if (Global->t_in_fac == NULL) { + printerr("Could not malloc memory for Global->t_in_fac\n"); + exit(-1); + } else if (Global->t_in_mod == NULL) { + printerr("Could not malloc memory for Global->t_in_mod\n"); + exit(-1); + } else if (Global->t_in_solve == NULL) { + printerr("Could not malloc memory for Global->t_in_solve\n"); + exit(-1); + } else if (Global->t_in_bar == NULL) { + printerr("Could not malloc memory for Global->t_in_bar\n"); + exit(-1); + } else if (Global->completion == NULL) { + printerr("Could not malloc memory for Global->completion\n"); + exit(-1); + } + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the a + matrix data across physically distributed memories in a + round-robin fashion as desired. */ + + BARINIT(Global->start); + LOCKINIT(Global->idlock); + Global->id = 0; + + for (i=1; icompletion[0]; + for (i=1; icompletion[i] > maxt) { + maxt = Global->completion[i]; + } + if (Global->completion[i] < mint) { + mint = Global->completion[i]; + } + avgt += Global->completion[i]; + } + avgt = avgt / P; + + min_fac = max_fac = avg_fac = Global->t_in_fac[0]; + min_solve = max_solve = avg_solve = Global->t_in_solve[0]; + min_mod = max_mod = avg_mod = Global->t_in_mod[0]; + min_bar = max_bar = avg_bar = Global->t_in_bar[0]; + + for (i=1; it_in_fac[i] > max_fac) { + max_fac = Global->t_in_fac[i]; + } + if (Global->t_in_fac[i] < min_fac) { + min_fac = Global->t_in_fac[i]; + } + if (Global->t_in_solve[i] > max_solve) { + max_solve = Global->t_in_solve[i]; + } + if (Global->t_in_solve[i] < min_solve) { + min_solve = Global->t_in_solve[i]; + } + if (Global->t_in_mod[i] > max_mod) { + max_mod = Global->t_in_mod[i]; + } + if (Global->t_in_mod[i] < min_mod) { + min_mod = Global->t_in_mod[i]; + } + if (Global->t_in_bar[i] > max_bar) { + max_bar = Global->t_in_bar[i]; + } + if (Global->t_in_bar[i] < min_bar) { + min_bar = Global->t_in_bar[i]; + } + avg_fac += Global->t_in_fac[i]; + avg_solve += Global->t_in_solve[i]; + avg_mod += Global->t_in_mod[i]; + avg_bar += Global->t_in_bar[i]; + } + avg_fac = avg_fac/P; + avg_solve = avg_solve/P; + avg_mod = avg_mod/P; + avg_bar = avg_bar/P; + } + diag_printf(" PROCESS STATISTICS\n"); + diag_printf(" Total Diagonal Perimeter Interior Barrier\n"); + diag_printf(" Proc Time Time Time Time Time\n"); + diag_printf(" 0 %10.0f %10.0f %10.0f %10.0f %10.0f\n", + Global->completion[0],Global->t_in_fac[0], + Global->t_in_solve[0],Global->t_in_mod[0], + Global->t_in_bar[0]); + if (dostats) { + for (i=1; icompletion[i],Global->t_in_fac[i], + Global->t_in_solve[i],Global->t_in_mod[i], + Global->t_in_bar[i]); + } + diag_printf(" Avg %10.0f %10.0f %10.0f %10.0f %10.0f\n", + avgt,avg_fac,avg_solve,avg_mod,avg_bar); + diag_printf(" Min %10.0f %10.0f %10.0f %10.0f %10.0f\n", + mint,min_fac,min_solve,min_mod,min_bar); + diag_printf(" Max %10.0f %10.0f %10.0f %10.0f %10.0f\n", + maxt,max_fac,max_solve,max_mod,max_bar); + } + diag_printf("\n"); + Global->starttime = start; + diag_printf(" TIMING INFORMATION\n"); + diag_printf("Start time : %16d\n", + Global->starttime); + diag_printf("Initialization finish time : %16d\n", + Global->rs); + diag_printf("Overall finish time : %16d\n", + Global->rf); + diag_printf("Total time with initialization : %16d\n", + Global->rf-Global->starttime); + diag_printf("Total time without initialization : %16d\n", + Global->rf-Global->rs); + diag_printf("\n"); + + if (test_result) { + diag_printf(" TESTING RESULTS\n"); + CheckResult(n, a, rhs); + } + + MAIN_END; +} + +void SlaveStart() + +{ + int i; + int j; + int cluster; + int max_block; + int MyNum; + + LOCK(Global->idlock) + MyNum = Global->id; + Global->id ++; + UNLOCK(Global->idlock) + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + diag_printf("Slave start\n"); + + OneSolve(n, block_size, a, MyNum, dostats); + + thread_array[MyNum] = 0; + +} + + +void OneSolve(n, block_size, a, MyNum, dostats) + +double *a; +int n; +int block_size; +int MyNum; +int dostats; + +{ + unsigned int i; + unsigned int myrs; + unsigned int myrf; + unsigned int mydone; + struct LocalCopies *lc; + + lc = (struct LocalCopies *) malloc(sizeof(struct LocalCopies)); + if (lc == NULL) { + diag_printf("Proc %d could not malloc memory for lc\n",MyNum); + exit(-1); + } + lc->t_in_fac = 0.0; + lc->t_in_solve = 0.0; + lc->t_in_mod = 0.0; + lc->t_in_bar = 0.0; + + /* barrier to ensure all initialization is done */ + BARRIER(Global->start, P, 1); + + /* to remove cold-start misses, all processors begin by touching a[] */ + TouchA(block_size, MyNum); + + BARRIER(Global->start, P, 2); + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + if ((MyNum == 0) || (dostats)) { + CLOCK(myrs); + } + + diag_printf("Start calc\n"); + lu(n, block_size, MyNum, lc, dostats); + diag_printf("End calc\n"); + + if ((MyNum == 0) || (dostats)) { + CLOCK(mydone); + } + + BARRIER(Global->start, P, 3); + + if ((MyNum == 0) || (dostats)) { + CLOCK(myrf); + Global->t_in_fac[MyNum] = lc->t_in_fac; + Global->t_in_solve[MyNum] = lc->t_in_solve; + Global->t_in_mod[MyNum] = lc->t_in_mod; + Global->t_in_bar[MyNum] = lc->t_in_bar; + Global->completion[MyNum] = mydone-myrs; + } + if (MyNum == 0) { + Global->rs = myrs; + Global->done = mydone; + Global->rf = myrf; + } +} + + +void lu0(a, n, stride) + +double *a; +int n; +int stride; + +{ + int j; + int k; + int length; + double alpha; + + for (k=0; kn) { + kl = n; + } + + if ((MyNum == 0) || (dostats)) { + CLOCK(t1); + } + + /* factor diagonal block */ + diagowner = BlockOwner(K, K); + if (diagowner == MyNum) { + A = &(a[k+k*n]); + lu0(A, kl-k, strI); + } + + if ((MyNum == 0) || (dostats)) { + CLOCK(t11); + } + + BARRIER(Global->start, P, 4); + + if ((MyNum == 0) || (dostats)) { + CLOCK(t2); + } + + /* divide column k by diagonal block */ + D = &(a[k+k*n]); + for (i=kl, I=K+1; i n) { + il = n; + } + A = &(a[i+k*n]); + bdiv(A, D, strI, n, il-i, kl-k); + } + } + /* modify row k by diagonal block */ + for (j=kl, J=K+1; j n) { + jl = n; + } + A = &(a[k+j*n]); + bmodd(D, A, kl-k, jl-j, n, strI); + } + } + + if ((MyNum == 0) || (dostats)) { + CLOCK(t22); + } + + BARRIER(Global->start, P, 5); + + if ((MyNum == 0) || (dostats)) { + CLOCK(t3); + } + + /* modify subsequent block columns */ + for (i=kl, I=K+1; i n) { + il = n; + } + colowner = BlockOwner(I,K); + A = &(a[i+k*n]); + for (j=kl, J=K+1; j n) { + jl = n; + } + if (BlockOwner(I, J) == MyNum) { /* parcel out blocks */ + B = &(a[k+j*n]); + C = &(a[i+j*n]); + bmod(A, B, C, il-i, jl-j, kl-k, n); + } + } + } + if ((MyNum == 0) || (dostats)) { + CLOCK(t4); + lc->t_in_fac += (t11-t1); + lc->t_in_solve += (t22-t2); + lc->t_in_mod += (t4-t3); + lc->t_in_bar += (t2-t11) + (t3-t22); + } + } +} + + +void InitA(rhs) + +double *rhs; + +{ + int i, j; + + srand(1); + for (j=0; j=0; j--) { + for (i=0; i 0.00001) { + bogus = 1; + max_diff = diff; + } + } + if (bogus) { + diag_printf("TEST FAILED: (%.5f diff)\n", max_diff); + } else { + diag_printf("TEST PASSED\n"); + } + free(y); +} + + +void printerr(s) + +char *s; + +{ + diag_printf("ERROR: %s\n",s); +} + + +#include diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu.c ecos-rep/packages/kernel/current/tests_smp/lu.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/lu.c 2006-06-21 10:30:57.000000000 +0200 @@ -0,0 +1,1118 @@ + + + + + + + + + + + +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Parallel dense blocked LU factorization (no pivoting) */ +/* */ +/* This version contains one dimensional arrays in which the matrix */ +/* to be factored is stored. */ +/* */ +/* Command line options: */ +/* */ +/* -nN : Decompose NxN matrix. */ +/* -pP : P = number of processors. */ +/* -bB : Use a block size of B. BxB elements should fit in cache for */ +/* good performance. Small block sizes (B=8, B=16) work well. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Test output. */ +/* -o : Print out matrix values. */ +/* -h : Print out command line options. */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include +#include + +#include + + +/*---------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int smp_cyg_test_main(int argc, char **argv); + +void smp_cyg_test_main_call(void *p) { + smp_cyg_test_main(smp_cyg_test_argc, smp_cyg_test_argv); +} + + +/* #define STACK_SIZE 0x1b000 */ +#define STACK_SIZE 8192 +static cyg_thread smp_cyg_test_thread; +static char smp_cyg_test_stack[STACK_SIZE]; +static cyg_handle_t smp_cyg_test_threadh; + + + +cyg_handle_t threadh[64]; +char *stack[64]; +cyg_thread thread[64]; + + +externC void cyg_user_start( void ) +{ + CYG_TEST_INIT(); + + diag_printf("Starting test app\n"); + + cyg_thread_create(10, // Priority - just a number + smp_cyg_test_main_call, // entry + 0, // index + "smp test", // Name + smp_cyg_test_stack, // Stack + STACK_SIZE, // Size + &smp_cyg_test_threadh, // Handle + &smp_cyg_test_thread // Thread data structure + ); + cyg_thread_resume( smp_cyg_test_threadh ); + /*cyg_scheduler_start();*/ +} + + +/*---------------------------------------*/ + + +#define MAXRAND 2147483647 +#define DEFAULT_N 128 +#define DEFAULT_P 1 +#define DEFAULT_B 16 +#define min(a,b) ((a) < (b) ? (a) : (b)) + +struct GlobalMemory { + double *t_in_fac; + double *t_in_solve; + double *t_in_mod; + double *t_in_bar; + double *completion; + unsigned int starttime; + unsigned int rf; + unsigned int rs; + unsigned int done; + int id; + +/*---------------------------------------*/ +struct startTYP { + cyg_spinlock_t lock;; + int count[1]; + cyg_sem_t queue[1];; + + } start[1]; +/*---------------------------------------*/ + + + cyg_spinlock_t idlock; +} *Global; + +struct LocalCopies { + double t_in_fac; + double t_in_solve; + double t_in_mod; + double t_in_bar; +}; + +int dbg_on = 0; +int n = DEFAULT_N; /* The size of the matrix */ +int P = DEFAULT_P; /* Number of processors */ +int block_size = DEFAULT_B; /* Block dimension */ +int nblocks; /* Number of blocks in each dimension */ +int num_rows; /* Number of processors per row of processor grid */ +int num_cols; /* Number of processors per col of processor grid */ +double *a; /* a = lu; l and u both placed back in a */ +double *rhs; +int *proc_bytes; /* Bytes to malloc per processor to hold blocks + of A*/ +int test_result = 0; /* Test result of factorization? */ +int doprint = 0; /* Print out matrix values? */ +int dostats = 0; /* Print out individual processor statistics? */ + +void SlaveStart(); +void OneSolve(int, int, double *, int, int); +void lu0(double *,int, int); +void bdiv(double *, double *, int, int, int, int); +void bmodd(double *, double*, int, int, int, int); +void bmod(double *, double *, double *, int, int, int, int); +void daxpy(double *, double *, int, double); +int BlockOwner(int, int); +void lu(int, int, int, struct LocalCopies *, int); +void InitA(double *); +double TouchA(int, int); +void PrintA(); +void CheckResult(int, double *, double *); +void printerr(char *); +volatile cyg_thread *thread_array[64]; + + +int smp_cyg_test_main(argc, argv) + +int argc; +char **argv; + +{ + int i, j; + int ch; + extern char *optarg; + int MyNum=0; + double mint, maxt, avgt; + double min_fac, min_solve, min_mod, min_bar; + double max_fac, max_solve, max_mod, max_bar; + double avg_fac, avg_solve, avg_mod, avg_bar; + int proc_num; + unsigned int start; + + memset (thread_array,0,sizeof(thread_array)); + + { + (start) = cyg_current_time()*10; +} +; + + while ((ch = getopt(argc, argv, "n:p:b:cstoh")) != -1) { + switch(ch) { + case 'n': n = atoi(optarg); break; + case 'p': P = atoi(optarg); + P = HAL_SMP_CPU_MAX; break; + case 'b': block_size = atoi(optarg); break; + case 's': dostats = 1; break; + case 't': test_result = !test_result; break; + case 'o': doprint = !doprint; break; + case 'h': diag_printf("Usage: LU \n\n"); + diag_printf("options:\n"); + diag_printf(" -nN : Decompose NxN matrix.\n"); + diag_printf(" -pP : P = number of processors.\n"); + diag_printf(" -bB : Use a block size of B. BxB elements should fit in cache for \n"); + diag_printf(" good performance. Small block sizes (B=8, B=16) work well.\n"); + diag_printf(" -c : Copy non-locally allocated blocks to local memory before use.\n"); + diag_printf(" -s : Print individual processor timing statistics.\n"); + diag_printf(" -t : Test output.\n"); + diag_printf(" -o : Print out matrix values.\n"); + diag_printf(" -h : Print out command line options.\n\n"); + diag_printf("Default: LU -n%1d -p%1d -b%1d\n", + DEFAULT_N,DEFAULT_P,DEFAULT_B); + exit(0); + break; + } + } + if (P > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + {;} + + diag_printf("\n"); + diag_printf("Blocked Dense LU Factorization\n"); + diag_printf(" %d by %d Matrix\n",n,n); + diag_printf(" %d Processors\n",P); + diag_printf(" %d by %d Element Blocks\n",block_size,block_size); + diag_printf("\n"); + diag_printf("\n"); + + num_rows = (int) sqrt((double) P); + for (;;) { + num_cols = P/num_rows; + if (num_rows*num_cols == P) + break; + num_rows--; + } + nblocks = n/block_size; + if (block_size * nblocks != n) { + nblocks++; + } + + a = (double *) calloc(n*n*sizeof(double), 1);; + rhs = (double *) calloc(n*sizeof(double), 1);; + + Global = (struct GlobalMemory *) calloc(sizeof(struct GlobalMemory), 1);; + Global->t_in_fac = (double *) calloc(P*sizeof(double), 1);; + Global->t_in_mod = (double *) calloc(P*sizeof(double), 1);; + Global->t_in_solve = (double *) calloc(P*sizeof(double), 1);; + Global->t_in_bar = (double *) calloc(P*sizeof(double), 1);; + Global->completion = (double *) calloc(P*sizeof(double), 1);; + + if (Global == NULL) { + printerr("Could not malloc memory for Global\n"); + exit(-1); + } else if (Global->t_in_fac == NULL) { + printerr("Could not malloc memory for Global->t_in_fac\n"); + exit(-1); + } else if (Global->t_in_mod == NULL) { + printerr("Could not malloc memory for Global->t_in_mod\n"); + exit(-1); + } else if (Global->t_in_solve == NULL) { + printerr("Could not malloc memory for Global->t_in_solve\n"); + exit(-1); + } else if (Global->t_in_bar == NULL) { + printerr("Could not malloc memory for Global->t_in_bar\n"); + exit(-1); + } else if (Global->completion == NULL) { + printerr("Could not malloc memory for Global->completion\n"); + exit(-1); + } + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the a + matrix data across physically distributed memories in a + round-robin fashion as desired. */ + + {{ +/*---------------------------------------*/ + int mon_dum1,mon_dum2; + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) + for (mon_dum2=0; mon_dum2 < 1; mon_dum2++) { + Global->start[mon_dum1].count[mon_dum2] = 0; + { cyg_semaphore_init(&Global->start[mon_dum1].queue[mon_dum2],0);}; + } + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) { + cyg_spinlock_init( &Global->start[mon_dum1].lock,0 );; + } +/*---------------------------------------*/ +}}; + cyg_spinlock_init( &Global->idlock,0 );; + Global->id = 0; + + for (i=1; icompletion[0]; + for (i=1; icompletion[i] > maxt) { + maxt = Global->completion[i]; + } + if (Global->completion[i] < mint) { + mint = Global->completion[i]; + } + avgt += Global->completion[i]; + } + avgt = avgt / P; + + min_fac = max_fac = avg_fac = Global->t_in_fac[0]; + min_solve = max_solve = avg_solve = Global->t_in_solve[0]; + min_mod = max_mod = avg_mod = Global->t_in_mod[0]; + min_bar = max_bar = avg_bar = Global->t_in_bar[0]; + + for (i=1; it_in_fac[i] > max_fac) { + max_fac = Global->t_in_fac[i]; + } + if (Global->t_in_fac[i] < min_fac) { + min_fac = Global->t_in_fac[i]; + } + if (Global->t_in_solve[i] > max_solve) { + max_solve = Global->t_in_solve[i]; + } + if (Global->t_in_solve[i] < min_solve) { + min_solve = Global->t_in_solve[i]; + } + if (Global->t_in_mod[i] > max_mod) { + max_mod = Global->t_in_mod[i]; + } + if (Global->t_in_mod[i] < min_mod) { + min_mod = Global->t_in_mod[i]; + } + if (Global->t_in_bar[i] > max_bar) { + max_bar = Global->t_in_bar[i]; + } + if (Global->t_in_bar[i] < min_bar) { + min_bar = Global->t_in_bar[i]; + } + avg_fac += Global->t_in_fac[i]; + avg_solve += Global->t_in_solve[i]; + avg_mod += Global->t_in_mod[i]; + avg_bar += Global->t_in_bar[i]; + } + avg_fac = avg_fac/P; + avg_solve = avg_solve/P; + avg_mod = avg_mod/P; + avg_bar = avg_bar/P; + } + diag_printf(" PROCESS STATISTICS\n"); + diag_printf(" Total Diagonal Perimeter Interior Barrier\n"); + diag_printf(" Proc Time Time Time Time Time\n"); + diag_printf(" 0 %10.0f %10.0f %10.0f %10.0f %10.0f\n", + Global->completion[0],Global->t_in_fac[0], + Global->t_in_solve[0],Global->t_in_mod[0], + Global->t_in_bar[0]); + if (dostats) { + for (i=1; icompletion[i],Global->t_in_fac[i], + Global->t_in_solve[i],Global->t_in_mod[i], + Global->t_in_bar[i]); + } + diag_printf(" Avg %10.0f %10.0f %10.0f %10.0f %10.0f\n", + avgt,avg_fac,avg_solve,avg_mod,avg_bar); + diag_printf(" Min %10.0f %10.0f %10.0f %10.0f %10.0f\n", + mint,min_fac,min_solve,min_mod,min_bar); + diag_printf(" Max %10.0f %10.0f %10.0f %10.0f %10.0f\n", + maxt,max_fac,max_solve,max_mod,max_bar); + } + diag_printf("\n"); + Global->starttime = start; + diag_printf(" TIMING INFORMATION\n"); + diag_printf("Start time : %16d\n", + Global->starttime); + diag_printf("Initialization finish time : %16d\n", + Global->rs); + diag_printf("Overall finish time : %16d\n", + Global->rf); + diag_printf("Total time with initialization : %16d\n", + Global->rf-Global->starttime); + diag_printf("Total time without initialization : %16d\n", + Global->rf-Global->rs); + diag_printf("\n"); + + if (test_result) { + diag_printf(" TESTING RESULTS\n"); + CheckResult(n, a, rhs); + } + + +{ + diag_printf("FP test end\n"); + return 0; +} +; +} + +void SlaveStart() + +{ + int i; + int j; + int cluster; + int max_block; + int MyNum; + + cyg_spinlock_spin(&Global->idlock); + MyNum = Global->id; + Global->id ++; + cyg_spinlock_clear(&Global->idlock); + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + diag_printf("Slave start\n"); + + OneSolve(n, block_size, a, MyNum, dostats); + + thread_array[MyNum] = 0; + +} + + +void OneSolve(n, block_size, a, MyNum, dostats) + +double *a; +int n; +int block_size; +int MyNum; +int dostats; + +{ + unsigned int i; + unsigned int myrs; + unsigned int myrf; + unsigned int mydone; + struct LocalCopies *lc; + + lc = (struct LocalCopies *) malloc(sizeof(struct LocalCopies)); + if (lc == NULL) { + diag_printf("Proc %d could not malloc memory for lc\n",MyNum); + exit(-1); + } + lc->t_in_fac = 0.0; + lc->t_in_solve = 0.0; + lc->t_in_mod = 0.0; + lc->t_in_bar = 0.0; + + /* barrier to ensure all initialization is done */ + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + /* to remove cold-start misses, all processors begin by touching a[] */ + TouchA(block_size, MyNum); + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + if ((MyNum == 0) || (dostats)) { + { + (myrs) = cyg_current_time()*10; +} +; + } + + diag_printf("Start calc\n"); + lu(n, block_size, MyNum, lc, dostats); + diag_printf("End calc\n"); + + if ((MyNum == 0) || (dostats)) { + { + (mydone) = cyg_current_time()*10; +} +; + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + if ((MyNum == 0) || (dostats)) { + { + (myrf) = cyg_current_time()*10; +} +; + Global->t_in_fac[MyNum] = lc->t_in_fac; + Global->t_in_solve[MyNum] = lc->t_in_solve; + Global->t_in_mod[MyNum] = lc->t_in_mod; + Global->t_in_bar[MyNum] = lc->t_in_bar; + Global->completion[MyNum] = mydone-myrs; + } + if (MyNum == 0) { + Global->rs = myrs; + Global->done = mydone; + Global->rf = myrf; + } +} + + +void lu0(a, n, stride) + +double *a; +int n; +int stride; + +{ + int j; + int k; + int length; + double alpha; + + for (k=0; kn) { + kl = n; + } + + if ((MyNum == 0) || (dostats)) { + { + (t1) = cyg_current_time()*10; +} +; + } + + /* factor diagonal block */ + diagowner = BlockOwner(K, K); + if (diagowner == MyNum) { + A = &(a[k+k*n]); + lu0(A, kl-k, strI); + } + + if ((MyNum == 0) || (dostats)) { + { + (t11) = cyg_current_time()*10; +} +; + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + if ((MyNum == 0) || (dostats)) { + { + (t2) = cyg_current_time()*10; +} +; + } + + /* divide column k by diagonal block */ + D = &(a[k+k*n]); + for (i=kl, I=K+1; i n) { + il = n; + } + A = &(a[i+k*n]); + bdiv(A, D, strI, n, il-i, kl-k); + } + } + /* modify row k by diagonal block */ + for (j=kl, J=K+1; j n) { + jl = n; + } + A = &(a[k+j*n]); + bmodd(D, A, kl-k, jl-j, n, strI); + } + } + + if ((MyNum == 0) || (dostats)) { + { + (t22) = cyg_current_time()*10; +} +; + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( Global->start[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] < (P -1) ) { + Global->start[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + cyg_spinlock_clear(&Global->start[0].lock );; + { cyg_semaphore_wait(&Global->start[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: start[0].count[0],Global->start[0].queue[0].count); + } + if ( Global->start[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + + cyg_spinlock_clear(&Global->start[0].lock );; + + } else { + ( Global->start[0].count[0] )-- ; + //cyg_spinlock_clear(&Global->start[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,Global->start[0].count[0],Global->start[0].queue[0].count); + } + { cyg_semaphore_post(&Global->start[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + if ((MyNum == 0) || (dostats)) { + { + (t3) = cyg_current_time()*10; +} +; + } + + /* modify subsequent block columns */ + for (i=kl, I=K+1; i n) { + il = n; + } + colowner = BlockOwner(I,K); + A = &(a[i+k*n]); + for (j=kl, J=K+1; j n) { + jl = n; + } + if (BlockOwner(I, J) == MyNum) { /* parcel out blocks */ + B = &(a[k+j*n]); + C = &(a[i+j*n]); + bmod(A, B, C, il-i, jl-j, kl-k, n); + } + } + } + if ((MyNum == 0) || (dostats)) { + { + (t4) = cyg_current_time()*10; +} +; + lc->t_in_fac += (t11-t1); + lc->t_in_solve += (t22-t2); + lc->t_in_mod += (t4-t3); + lc->t_in_bar += (t2-t11) + (t3-t22); + } + } +} + + +void InitA(rhs) + +double *rhs; + +{ + int i, j; + + srand(1); + for (j=0; j=0; j--) { + for (i=0; i 0.00001) { + bogus = 1; + max_diff = diff; + } + } + if (bogus) { + diag_printf("TEST FAILED: (%.5f diff)\n", max_diff); + } else { + diag_printf("TEST PASSED\n"); + } + free(y); +} + + +void printerr(s) + +char *s; + +{ + diag_printf("ERROR: %s\n",s); +} + + +#include diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu_arg.c ecos-rep/packages/kernel/current/tests_smp/lu_arg.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/lu_arg.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/lu_arg.c 2006-02-20 16:16:38.000000000 +0100 @@ -0,0 +1,12 @@ +//___________________________________________ +#define _str_HAL_SMP_CPU_MAX(x) #x +#define smp_cyg_test_argc 5 +char *_cyg_argv[] = { + "fft.exe", + "-p", + "2", /* not used, using HAL_SMP_CPU_MAX */ + "-n", + "64" +}; +#define smp_cyg_test_argv &_cyg_argv +//''''''''''''''''''''''''''''''''''''''''''' diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/makefile ecos-rep/packages/kernel/current/tests_smp/makefile --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/makefile 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/makefile 2005-09-05 16:21:09.000000000 +0200 @@ -0,0 +1,13 @@ +MACROS = c.m4.ecos + +all: fft.c radix.c lu.c + +fft.c: fft.C $(MACROS) + m4 $(MACROS) fft.C > fft.c + +radix.c: radix.C $(MACROS) + m4 $(MACROS) radix.C > radix.c + +lu.c: lu.C $(MACROS) + m4 $(MACROS) lu.C > lu.c + diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix.C ecos-rep/packages/kernel/current/tests_smp/radix.C --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix.C 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/radix.C 2006-02-23 13:59:21.000000000 +0100 @@ -0,0 +1,909 @@ +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Integer radix sort of non-negative integers. */ +/* */ +/* Command line options: */ +/* */ +/* -pP : P = number of processors. */ +/* -rR : R = radix for sorting. Must be power of 2. */ +/* -nN : N = number of keys to sort. */ +/* -mM : M = maximum key value. Integer keys k will be generated such */ +/* that 0 <= k <= M. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Check to make sure all keys are sorted correctly. */ +/* -o : Print out sorted keys. */ +/* -h : Print out command line options. */ +/* */ +/* Default: RADIX -p1 -n262144 -r1024 -m524288 */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include + +#define DEFAULT_P 1 +#define DEFAULT_N 262144 +#define DEFAULT_R 1024 +#define DEFAULT_M 524288 +#define MAX_PROCESSORS 64 +#define RADIX_S 8388608.0e0 +#define RADIX 70368744177664.0e0 +#define SEED 314159265.0e0 +#define RATIO 1220703125.0e0 +#define PAGE_SIZE 4096 +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define MAX_RADIX 4096 + +#include + +MAIN_ENV + +struct prefix_node { + int densities[MAX_RADIX]; + int ranks[MAX_RADIX]; + PAUSEDEC(done) + char pad[PAGE_SIZE]; +}; + +struct global_memory { + int Index; /* process ID */ + LOCKDEC(lock_Index) /* for fetch and add to get ID */ + LOCKDEC(rank_lock) /* for fetch and add to get ID */ + ALOCKDEC(section_lock,MAX_PROCESSORS) /* key locks */ + BARDEC(barrier_rank) /* for ranking process */ + BARDEC(barrier_key) /* for key sorting process */ + double *ranktime; + double *sorttime; + double *totaltime; + int final; + unsigned int starttime; + unsigned int rs; + unsigned int rf; + struct prefix_node prefix_tree[2 * MAX_PROCESSORS]; +} *global; + +struct global_private { + char pad[PAGE_SIZE]; + int *rank_ff; /* overall processor ranks */ +} gp[MAX_PROCESSORS]; + +int *key[2]; /* sort from one index into the other */ +int **rank_me; /* individual processor ranks */ +int *key_partition; /* keys a processor works on */ +int *rank_partition; /* ranks a processor works on */ + +int number_of_processors = DEFAULT_P; +int max_num_digits; +int radix = DEFAULT_R; +int num_keys = DEFAULT_N; +int max_key = DEFAULT_M; +int log2_radix; +int log2_keys; +int dostats = 0; +int test_result = 0; +int doprint = 0; +volatile cyg_thread *thread_array[64]; + +int dbg_on = 0; +double ran_num_init(unsigned int,double,double); +double product_mod_46(double,double); +int get_max_digits(int); +int get_log2_radix(int); +int get_log2_keys(int); +void slave_sort(); +int log_2(int); +void printerr(char *); +void init(int,int,int); +void test_sort(int); +void printout(); + + +int smp_cyg_test_main(argc, argv) + +int argc; +char **argv; + +{ + int i; + int p; + int quotient; + int remainder; + int sum_i; + int sum_f; + int mistake=0; + int size; + int **temp; + int **temp2; + int *a; + int c; + int n1; + extern char *optarg; + double mint, maxt, avgt; + double minrank, maxrank, avgrank; + double minsort, maxsort, avgsort; + unsigned int start; + int done = 0; + int start_p; + int end_p; + int level; + int index; + int base; + int offset; + int toffset; + + + memset (thread_array,0,sizeof(thread_array)); + + CLOCK(start) + + while ((c = getopt(argc, argv, "p:r:n:m:stoh")) != -1) { + switch(c) { + case 'p': number_of_processors = atoi(optarg); + number_of_processors = HAL_SMP_CPU_MAX; + if (number_of_processors < 1) { + printerr("P must be >= 1\n"); + exit(-1); + } + if (number_of_processors > MAX_PROCESSORS) { + printerr("Maximum processors (MAX_PROCESSORS) exceeded\n"); + exit(-1); + } + break; + case 'r': radix = atoi(optarg); + if (radix < 1) { + printerr("Radix must be a power of 2 greater than 0\n"); + exit(-1); + } + log2_radix = log_2(radix); + if (log2_radix == -1) { + printerr("Radix must be a power of 2\n"); + exit(-1); + } + break; + case 'n': num_keys = atoi(optarg); + if (num_keys < 1) { + printerr("Number of keys must be >= 1\n"); + exit(-1); + } + break; + case 'm': max_key = atoi(optarg); + if (max_key < 1) { + printerr("Maximum key must be >= 1\n"); + exit(-1); + } + break; + case 's': dostats = !dostats; + break; + case 't': test_result = !test_result; + break; + case 'o': doprint = !doprint; + break; + case 'h': diag_printf("Usage: RADIX \n\n"); + diag_printf(" -pP : P = number of processors.\n"); + diag_printf(" -rR : R = radix for sorting. Must be power of 2.\n"); + diag_printf(" -nN : N = number of keys to sort.\n"); + diag_printf(" -mM : M = maximum key value. Integer keys k will be generated such\n"); + diag_printf(" that 0 <= k <= M.\n"); + diag_printf(" -s : Print individual processor timing statistics.\n"); + diag_printf(" -t : Check to make sure all keys are sorted correctly.\n"); + diag_printf(" -o : Print out sorted keys.\n"); + diag_printf(" -h : Print out command line options.\n\n"); + diag_printf("Default: RADIX -p%1d -n%1d -r%1d -m%1d\n", + DEFAULT_P,DEFAULT_N,DEFAULT_R,DEFAULT_M); + exit(0); + } + } + + if (number_of_processors > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + MAIN_INITENV(,80000000) + + log2_radix = log_2(radix); + log2_keys = log_2(num_keys); + global = (struct global_memory *) G_MALLOC(sizeof(struct global_memory)) + key[0] = (int *) G_MALLOC(num_keys*sizeof(int)); + key[1] = (int *) G_MALLOC(num_keys*sizeof(int)); + key_partition = (int *) G_MALLOC((number_of_processors+1)*sizeof(int)); + rank_partition = (int *) G_MALLOC((number_of_processors+1)*sizeof(int)); + + if ((global == NULL)) { + diag_printf("ERROR: Cannot malloc enough memory %d\n",sizeof(struct global_memory)); + } + + global->ranktime = (double *) G_MALLOC(number_of_processors*sizeof(double)); + global->sorttime = (double *) G_MALLOC(number_of_processors*sizeof(double)); + global->totaltime = (double *) G_MALLOC(number_of_processors*sizeof(double)); + size = number_of_processors*(radix*sizeof(int)+sizeof(int *)); + rank_me = (int **) G_MALLOC(size); + + if ((global == NULL) || (key[0] == NULL) || (key[1] == NULL) || + (key_partition == NULL) || (rank_partition == NULL) || + (rank_me == NULL)) { + diag_printf("ERROR: Cannot malloc enough memory\n"); + exit(-1); + } + + temp = rank_me; + temp2 = temp + number_of_processors; + a = (int *) temp2; + for (i=0;ilock_Index) + LOCKINIT(global->rank_lock) + ALOCKINIT(global->section_lock,MAX_PROCESSORS) + BARINIT(global->barrier_rank) + BARINIT(global->barrier_key) + + for (i=0; i<2*number_of_processors; i++) { + PAUSEINIT(global->prefix_tree[i].done); + } + + global->Index = 0; + max_num_digits = get_max_digits(max_key); + diag_printf("\n"); + diag_printf("Integer Radix Sort\n"); + diag_printf(" %d Keys\n",num_keys); + diag_printf(" %d Processors\n",number_of_processors); + diag_printf(" Radix = %d\n",radix); + diag_printf(" Max key = %d\n",max_key); + diag_printf("\n"); + + quotient = num_keys / number_of_processors; + remainder = num_keys % number_of_processors; + sum_i = 0; + sum_f = 0; + p = 0; + diag_printf("key_partition\n",max_key); + while (sum_i < num_keys) { + key_partition[p] = sum_i; + p++; + sum_i = sum_i + quotient; + sum_f = sum_f + remainder; + sum_i = sum_i + sum_f / number_of_processors; + sum_f = sum_f % number_of_processors; + } + key_partition[p] = num_keys; + + quotient = radix / number_of_processors; + remainder = radix % number_of_processors; + sum_i = 0; + sum_f = 0; + p = 0; + diag_printf("rank_partition\n",max_key); + while (sum_i < radix) { + rank_partition[p] = sum_i; + p++; + sum_i = sum_i + quotient; + sum_f = sum_f + remainder; + sum_i = sum_i + sum_f / number_of_processors; + sum_f = sum_f % number_of_processors; + } + rank_partition[p] = radix; + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the key, + rank_me, rank, and gp data structures across physically + distributed memories as desired. + + One way to place data is as follows: + + for (i=0;i> 1; + base = number_of_processors; + while ((offset & 0x1) != 0) { + offset >>= 1; + index = base + offset; + Place all addresses x such that: + &(global->prefix_tree[index]) <= x < + &(global->prefix_tree[index + 1]) on node toffset + base += level; + level >>= 1; + } + } */ + + /* Fill the random-number array. */ + + for (i = 1; i < number_of_processors; i++) { + CREATE(slave_sort,thread_array[i]) + } + + slave_sort(); + + for (i = 1; i < number_of_processors; i++) { + while(thread_array[i]) {}; + } + + diag_printf("\n"); + diag_printf(" PROCESS STATISTICS\n"); + diag_printf(" Total Rank Sort\n"); + diag_printf(" Proc Time Time Time\n"); + diag_printf(" 0 %10.0f %10.0f %10.0f\n", + global->totaltime[0],global->ranktime[0], + global->sorttime[0]); + if (dostats) { + maxt = avgt = mint = global->totaltime[0]; + maxrank = avgrank = minrank = global->ranktime[0]; + maxsort = avgsort = minsort = global->sorttime[0]; + for (i=1; itotaltime[i] > maxt) { + maxt = global->totaltime[i]; + } + if (global->totaltime[i] < mint) { + mint = global->totaltime[i]; + } + if (global->ranktime[i] > maxrank) { + maxrank = global->ranktime[i]; + } + if (global->ranktime[i] < minrank) { + minrank = global->ranktime[i]; + } + if (global->sorttime[i] > maxsort) { + maxsort = global->sorttime[i]; + } + if (global->sorttime[i] < minsort) { + minsort = global->sorttime[i]; + } + avgt += global->totaltime[i]; + avgrank += global->ranktime[i]; + avgsort += global->sorttime[i]; + } + avgt = avgt / number_of_processors; + avgrank = avgrank / number_of_processors; + avgsort = avgsort / number_of_processors; + for (i=1; itotaltime[i],global->ranktime[i], + global->sorttime[i]); + } + diag_printf(" Avg %10.0f %10.0f %10.0f\n",avgt,avgrank,avgsort); + diag_printf(" Min %10.0f %10.0f %10.0f\n",mint,minrank,minsort); + diag_printf(" Max %10.0f %10.0f %10.0f\n",maxt,maxrank,maxsort); + diag_printf("\n"); + } + + diag_printf("\n"); + global->starttime = start; + diag_printf(" TIMING INFORMATION\n"); + diag_printf("Start time : %16d\n", + global->starttime); + diag_printf("Initialization finish time : %16d\n", + global->rs); + diag_printf("Overall finish time : %16d\n", + global->rf); + diag_printf("Total time with initialization : %16d\n", + global->rf-global->starttime); + diag_printf("Total time without initialization : %16d\n", + global->rf-global->rs); + diag_printf("\n"); + + if (doprint) { + printout(); + } + if (test_result) { + test_sort(global->final); + } + + MAIN_END; +} + +void slave_sort() +{ + int i, j, k, kk, Ind; + int MyNum; + int this_key; + int tmp; + int last_key; + int loopnum; + double ran_num; + double sum; + int shiftnum; + int bb; + int my_key; + int key_start; + int key_stop; + int rank_start; + int rank_stop; + int from=0; + int to=1; + int *key_density; /* individual processor key densities */ + unsigned int time1; + unsigned int time2; + unsigned int time3; + unsigned int time4; + unsigned int time5; + unsigned int time6; + double ranktime=0; + double sorttime=0; + int *key_from; + int *key_to; + int *rank_me_mynum; + int *rank_me_i; + int *rank_ff_mynum; + int stats; + struct prefix_node* n; + struct prefix_node* r; + struct prefix_node* l; + struct prefix_node* my_node; + struct prefix_node* their_node; + volatile int* prefx; + int index; + int level; + int base; + int offset; + + diag_printf("SlaveSort %d\n",cyg_hal_get_current_threadid()); + + stats = dostats; + + LOCK(global->lock_Index) + MyNum = global->Index; + global->Index++; + UNLOCK(global->lock_Index) + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + key_density = (int *) malloc(radix*sizeof(int)); + + /* Fill the random-number array. */ + + key_start = key_partition[MyNum]; + key_stop = key_partition[MyNum + 1]; + rank_start = rank_partition[MyNum]; + rank_stop = rank_partition[MyNum + 1]; + if (rank_stop == radix) { + rank_stop--; + } + + diag_printf("init %d, %d-%d\n",cyg_hal_get_current_threadid(),key_start,key_stop); + init(key_start,key_stop,from); + + BARRIER(global->barrier_key, number_of_processors, 1 ) + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + BARRIER(global->barrier_key, number_of_processors, 2) + + if ((MyNum == 0) || (stats)) { + CLOCK(time1) + } + +/* Do 1 iteration per digit. */ + + rank_me_mynum = rank_me[MyNum]; + rank_ff_mynum = gp[MyNum].rank_ff; + for (loopnum=0;loopnum> shiftnum; + rank_me_mynum[my_key]++; + } + key_density[0] = rank_me_mynum[0]; + for (i=1;ibarrier_rank, number_of_processors,3) + + n = &(global->prefix_tree[MyNum]); + for (i = 0; i < radix; i++) { + n->densities[i] = key_density[i]; + n->ranks[i] = rank_me_mynum[i]; + } + offset = MyNum; + level = number_of_processors >> 1; + base = number_of_processors; + if ((MyNum & 0x1) == 0) { + SETPAUSE(global->prefix_tree[base + (offset >> 1)].done); + } + while ((offset & 0x1) != 0) { + offset >>= 1; + r = n; + l = n - 1; + index = base + offset; + n = &(global->prefix_tree[index]); + WAITPAUSE(n->done); + CLEARPAUSE(n->done); + if (offset != (level - 1)) { + for (i = 0; i < radix; i++) { + n->densities[i] = r->densities[i] + l->densities[i]; + n->ranks[i] = r->ranks[i] + l->ranks[i]; + } + } else { + for (i = 0; i < radix; i++) { + n->densities[i] = r->densities[i] + l->densities[i]; + } + } + base += level; + level >>= 1; + if ((offset & 0x1) == 0) { + SETPAUSE(global->prefix_tree[base + (offset >> 1)].done); + } + } + BARRIER(global->barrier_rank, number_of_processors,4); + + if (MyNum != (number_of_processors - 1)) { + offset = MyNum; + level = number_of_processors; + base = 0; + while ((offset & 0x1) != 0) { + offset >>= 1; + base += level; + level >>= 1; + } + my_node = &(global->prefix_tree[base + offset]); + offset >>= 1; + base += level; + level >>= 1; + while ((offset & 0x1) != 0) { + offset >>= 1; + base += level; + level >>= 1; + } + their_node = &(global->prefix_tree[base + offset]); + WAITPAUSE(my_node->done); + CLEARPAUSE(my_node->done); + for (i = 0; i < radix; i++) { + my_node->densities[i] = their_node->densities[i]; + } + } else { + my_node = &(global->prefix_tree[(2 * number_of_processors) - 2]); + } + offset = MyNum; + level = number_of_processors; + base = 0; + while ((offset & 0x1) != 0) { + SETPAUSE(global->prefix_tree[base + offset - 1].done); + offset >>= 1; + base += level; + level >>= 1; + } + offset = MyNum; + level = number_of_processors; + base = 0; + for(i = 0; i < radix; i++) { + rank_ff_mynum[i] = 0; + } + while (offset != 0) { + if ((offset & 0x1) != 0) { + /* Add ranks of node to your left at this level */ + l = &(global->prefix_tree[base + offset - 1]); + for (i = 0; i < radix; i++) { + rank_ff_mynum[i] += l->ranks[i]; + } + } + base += level; + level >>= 1; + offset >>= 1; + } + for (i = 1; i < radix; i++) { + rank_ff_mynum[i] += my_node->densities[i - 1]; + } + + if ((MyNum == 0) || (stats)) { + CLOCK(time3); + } + + BARRIER(global->barrier_rank, number_of_processors,5); + + if ((MyNum == 0) || (stats)) { + CLOCK(time4); + } + + /* put it in order according to this digit */ + + for (i = key_start; i < key_stop; i++) { + this_key = key_from[i] & bb; + this_key = this_key >> shiftnum; + tmp = rank_ff_mynum[this_key]; + key_to[tmp] = key_from[i]; + rank_ff_mynum[this_key]++; + } /* i */ + + if ((MyNum == 0) || (stats)) { + CLOCK(time5); + } + + if (loopnum != max_num_digits-1) { + from = from ^ 0x1; + to = to ^ 0x1; + } + + BARRIER(global->barrier_rank, number_of_processors, 6) + + if ((MyNum == 0) || (stats)) { + ranktime += (time3 - time2); + sorttime += (time5 - time4); + } + } /* for */ + + BARRIER(global->barrier_rank, number_of_processors, 7) + if ((MyNum == 0) || (stats)) { + CLOCK(time6) + global->ranktime[MyNum] = ranktime; + global->sorttime[MyNum] = sorttime; + global->totaltime[MyNum] = time6-time1; + } + if (MyNum == 0) { + global->rs = time1; + global->rf = time6; + global->final = to; + } + + thread_array[MyNum] = 0; +} + +double product_mod_46(t1, t2) /* product_mod_46() returns the product + (mod 2^46) of t1 and t2. */ +double t1; +double t2; + +{ + double a1; + double b1; + double a2; + double b2; + + a1 = (double)((int)(t1 / RADIX_S)); /* Decompose the arguments. */ + a2 = t1 - a1 * RADIX_S; + b1 = (double)((int)(t2 / RADIX_S)); + b2 = t2 - b1 * RADIX_S; + t1 = a1 * b2 + a2 * b1; /* Multiply the arguments. */ + t2 = (double)((int)(t1 / RADIX_S)); + t2 = t1 - t2 * RADIX_S; + t1 = t2 * RADIX_S + a2 * b2; + t2 = (double)((int)(t1 / RADIX)); + + return (t1 - t2 * RADIX); /* Return the product. */ +} + +double ran_num_init(k, b, t) /* finds the (k)th random number, + given the seed, b, and the ratio, t. */ +unsigned int k; +double b; +double t; + +{ + unsigned int j; + + while (k != 0) { /* while() is executed m times + such that 2^m > k. */ + j = k >> 1; + if ((j << 1) != k) { + b = product_mod_46(b, t); + } + t = product_mod_46(t, t); + k = j; + } + + return b; +} + +int get_max_digits(max_key) + +int max_key; + +{ + int done = 0; + int temp = 1; + int key_val; + + key_val = max_key; + while (!done) { + key_val = key_val / radix; + if (key_val == 0) { + done = 1; + } else { + temp ++; + } + } + return temp; +} + +int get_log2_radix(rad) + +int rad; + +{ + int cumulative=1; + int out; + + for (out = 0; out < 20; out++) { + if (cumulative == rad) { + return(out); + } else { + cumulative = cumulative * 2; + } + } + diag_printf("ERROR: Radix %d not a power of 2\n", rad); + exit(-1); +} + +int get_log2_keys(num_keys) + +int num_keys; + +{ + int cumulative=1; + int out; + + for (out = 0; out < 30; out++) { + if (cumulative == num_keys) { + return(out); + } else { + cumulative = cumulative * 2; + } + } + diag_printf("ERROR: Number of keys %d not a power of 2\n", num_keys); + exit(-1); +} + +int log_2(number) + +int number; + +{ + int cumulative = 1; + int out = 0; + int done = 0; + + while ((cumulative < number) && (!done) && (out < 50)) { + if (cumulative == number) { + done = 1; + } else { + cumulative = cumulative * 2; + out ++; + } + } + + if (cumulative == number) { + return(out); + } else { + return(-1); + } +} + +void printerr(s) + +char *s; + +{ + diag_printf("ERROR: %s\n",s); +} + +void init(key_start,key_stop,from) + +int key_start; +int key_stop; +int from; + +{ + double ran_num; + double sum; + int tmp; + int i; + int *key_from; + + ran_num = ran_num_init((key_start << 2) + 1, SEED, RATIO); + sum = ran_num / RADIX; + key_from = (int *) key[from]; + for (i = key_start; i < key_stop; i++) { + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + key_from[i] = (int) ((sum / 4.0) * max_key); + tmp = (int) ((key_from[i])/100); + ran_num = product_mod_46(ran_num, RATIO); + sum = ran_num / RADIX; + } + +} + +void test_sort(final) + +int final; + +{ + int i; + int mistake = 0; + int *key_final; + + diag_printf("\n"); + diag_printf(" TESTING RESULTS\n"); + key_final = key[final]; + for (i = 0; i < num_keys-1; i++) { + if (key_final[i] > key_final[i + 1]) { + diag_printf("error with key %d, value %d %d \n", + i,key_final[i],key_final[i + 1]); + mistake++; + } + } + + if (mistake) { + diag_printf("FAILED: %d keys out of place.\n", mistake); + } else { + diag_printf("PASSED: All keys in place.\n"); + } + diag_printf("\n"); +} + +void printout() + +{ + int i; + int mistake; + int *key_final; + + key_final = (int *) key[global->final]; + diag_printf("\n"); + diag_printf(" SORTED KEY VALUES\n"); + diag_printf("%8d ",key_final[0]); + for (i = 0; i < num_keys-1; i++) { + diag_printf("%8d ",key_final[i+1]); + if ((i+2)%5 == 0) { + diag_printf("\n"); + } + } + diag_printf("\n"); +} + +#include diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix.c ecos-rep/packages/kernel/current/tests_smp/radix.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/radix.c 2006-06-21 10:30:57.000000000 +0200 @@ -0,0 +1,1346 @@ + + + + + + + + + + + +/*************************************************************************/ +/* */ +/* Copyright (c) 1994 Stanford University */ +/* */ +/* All rights reserved. */ +/* */ +/* Permission is given to use, copy, and modify this software for any */ +/* non-commercial purpose as long as this copyright notice is not */ +/* removed. All other uses, including redistribution in whole or in */ +/* part, are forbidden without prior written permission. */ +/* */ +/* This software is provided with absolutely no warranty and no */ +/* support. */ +/* */ +/*************************************************************************/ + +/*************************************************************************/ +/* */ +/* Integer radix sort of non-negative integers. */ +/* */ +/* Command line options: */ +/* */ +/* -pP : P = number of processors. */ +/* -rR : R = radix for sorting. Must be power of 2. */ +/* -nN : N = number of keys to sort. */ +/* -mM : M = maximum key value. Integer keys k will be generated such */ +/* that 0 <= k <= M. */ +/* -s : Print individual processor timing statistics. */ +/* -t : Check to make sure all keys are sorted correctly. */ +/* -o : Print out sorted keys. */ +/* -h : Print out command line options. */ +/* */ +/* Default: RADIX -p1 -n262144 -r1024 -m524288 */ +/* */ +/* Note: This version works under both the FORK and SPROC models */ +/* */ +/*************************************************************************/ + +#include +#include +#include + +#define DEFAULT_P 1 +#define DEFAULT_N 262144 +#define DEFAULT_R 1024 +#define DEFAULT_M 524288 +#define MAX_PROCESSORS 64 +#define RADIX_S 8388608.0e0 +#define RADIX 70368744177664.0e0 +#define SEED 314159265.0e0 +#define RATIO 1220703125.0e0 +#define PAGE_SIZE 4096 +#define PAGE_MASK (~(PAGE_SIZE-1)) +#define MAX_RADIX 4096 + +#include + + +/*---------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int smp_cyg_test_main(int argc, char **argv); + +void smp_cyg_test_main_call(void *p) { + smp_cyg_test_main(smp_cyg_test_argc, smp_cyg_test_argv); +} + + +/* #define STACK_SIZE 0x1b000 */ +#define STACK_SIZE 8192 +static cyg_thread smp_cyg_test_thread; +static char smp_cyg_test_stack[STACK_SIZE]; +static cyg_handle_t smp_cyg_test_threadh; + + + +cyg_handle_t threadh[64]; +char *stack[64]; +cyg_thread thread[64]; + + +externC void cyg_user_start( void ) +{ + CYG_TEST_INIT(); + + diag_printf("Starting test app\n"); + + cyg_thread_create(10, // Priority - just a number + smp_cyg_test_main_call, // entry + 0, // index + "smp test", // Name + smp_cyg_test_stack, // Stack + STACK_SIZE, // Size + &smp_cyg_test_threadh, // Handle + &smp_cyg_test_thread // Thread data structure + ); + cyg_thread_resume( smp_cyg_test_threadh ); + /*cyg_scheduler_start();*/ +} + + +/*---------------------------------------*/ + + +struct prefix_node { + int densities[MAX_RADIX]; + int ranks[MAX_RADIX]; + + char pad[PAGE_SIZE]; +}; + +struct global_memory { + int Index; /* process ID */ + cyg_spinlock_t lock_Index; /* for fetch and add to get ID */ + cyg_spinlock_t rank_lock; /* for fetch and add to get ID */ + +/*---------------------------------------*/ +struct section_lockTYP { + cyg_spinlock_t lock;; + + + + } section_lock[MAX_PROCESSORS]; +/*---------------------------------------*/ + + /* key locks */ + +/*---------------------------------------*/ +struct barrier_rankTYP { + cyg_spinlock_t lock;; + int count[1]; + cyg_sem_t queue[1];; + + } barrier_rank[1]; +/*---------------------------------------*/ + + /* for ranking process */ + +/*---------------------------------------*/ +struct barrier_keyTYP { + cyg_spinlock_t lock;; + int count[1]; + cyg_sem_t queue[1];; + + } barrier_key[1]; +/*---------------------------------------*/ + + /* for key sorting process */ + double *ranktime; + double *sorttime; + double *totaltime; + int final; + unsigned int starttime; + unsigned int rs; + unsigned int rf; + struct prefix_node prefix_tree[2 * MAX_PROCESSORS]; +} *global; + +struct global_private { + char pad[PAGE_SIZE]; + int *rank_ff; /* overall processor ranks */ +} gp[MAX_PROCESSORS]; + +int *key[2]; /* sort from one index into the other */ +int **rank_me; /* individual processor ranks */ +int *key_partition; /* keys a processor works on */ +int *rank_partition; /* ranks a processor works on */ + +int number_of_processors = DEFAULT_P; +int max_num_digits; +int radix = DEFAULT_R; +int num_keys = DEFAULT_N; +int max_key = DEFAULT_M; +int log2_radix; +int log2_keys; +int dostats = 0; +int test_result = 0; +int doprint = 0; +volatile cyg_thread *thread_array[64]; + +int dbg_on = 0; +double ran_num_init(unsigned int,double,double); +double product_mod_46(double,double); +int get_max_digits(int); +int get_log2_radix(int); +int get_log2_keys(int); +void slave_sort(); +int log_2(int); +void printerr(char *); +void init(int,int,int); +void test_sort(int); +void printout(); + + +int smp_cyg_test_main(argc, argv) + +int argc; +char **argv; + +{ + int i; + int p; + int quotient; + int remainder; + int sum_i; + int sum_f; + int mistake=0; + int size; + int **temp; + int **temp2; + int *a; + int c; + int n1; + extern char *optarg; + double mint, maxt, avgt; + double minrank, maxrank, avgrank; + double minsort, maxsort, avgsort; + unsigned int start; + int done = 0; + int start_p; + int end_p; + int level; + int index; + int base; + int offset; + int toffset; + + + memset (thread_array,0,sizeof(thread_array)); + + { + (start) = cyg_current_time()*10; +} + + + while ((c = getopt(argc, argv, "p:r:n:m:stoh")) != -1) { + switch(c) { + case 'p': number_of_processors = atoi(optarg); + number_of_processors = HAL_SMP_CPU_MAX; + if (number_of_processors < 1) { + printerr("P must be >= 1\n"); + exit(-1); + } + if (number_of_processors > MAX_PROCESSORS) { + printerr("Maximum processors (MAX_PROCESSORS) exceeded\n"); + exit(-1); + } + break; + case 'r': radix = atoi(optarg); + if (radix < 1) { + printerr("Radix must be a power of 2 greater than 0\n"); + exit(-1); + } + log2_radix = log_2(radix); + if (log2_radix == -1) { + printerr("Radix must be a power of 2\n"); + exit(-1); + } + break; + case 'n': num_keys = atoi(optarg); + if (num_keys < 1) { + printerr("Number of keys must be >= 1\n"); + exit(-1); + } + break; + case 'm': max_key = atoi(optarg); + if (max_key < 1) { + printerr("Maximum key must be >= 1\n"); + exit(-1); + } + break; + case 's': dostats = !dostats; + break; + case 't': test_result = !test_result; + break; + case 'o': doprint = !doprint; + break; + case 'h': diag_printf("Usage: RADIX \n\n"); + diag_printf(" -pP : P = number of processors.\n"); + diag_printf(" -rR : R = radix for sorting. Must be power of 2.\n"); + diag_printf(" -nN : N = number of keys to sort.\n"); + diag_printf(" -mM : M = maximum key value. Integer keys k will be generated such\n"); + diag_printf(" that 0 <= k <= M.\n"); + diag_printf(" -s : Print individual processor timing statistics.\n"); + diag_printf(" -t : Check to make sure all keys are sorted correctly.\n"); + diag_printf(" -o : Print out sorted keys.\n"); + diag_printf(" -h : Print out command line options.\n\n"); + diag_printf("Default: RADIX -p%1d -n%1d -r%1d -m%1d\n", + DEFAULT_P,DEFAULT_N,DEFAULT_R,DEFAULT_M); + exit(0); + } + } + + if (number_of_processors > 64) { + printf("Maximal 64 processes\n"); + exit(0); + } + + {;} + + log2_radix = log_2(radix); + log2_keys = log_2(num_keys); + global = (struct global_memory *) calloc(sizeof(struct global_memory), 1); + key[0] = (int *) calloc(num_keys*sizeof(int), 1);; + key[1] = (int *) calloc(num_keys*sizeof(int), 1);; + key_partition = (int *) calloc((number_of_processors+1)*sizeof(int), 1);; + rank_partition = (int *) calloc((number_of_processors+1)*sizeof(int), 1);; + + if ((global == NULL)) { + diag_printf("ERROR: Cannot malloc enough memory %d\n",sizeof(struct global_memory)); + } + + global->ranktime = (double *) calloc(number_of_processors*sizeof(double), 1);; + global->sorttime = (double *) calloc(number_of_processors*sizeof(double), 1);; + global->totaltime = (double *) calloc(number_of_processors*sizeof(double), 1);; + size = number_of_processors*(radix*sizeof(int)+sizeof(int *)); + rank_me = (int **) calloc(size, 1);; + + if ((global == NULL) || (key[0] == NULL) || (key[1] == NULL) || + (key_partition == NULL) || (rank_partition == NULL) || + (rank_me == NULL)) { + diag_printf("ERROR: Cannot malloc enough memory\n"); + exit(-1); + } + + temp = rank_me; + temp2 = temp + number_of_processors; + a = (int *) temp2; + for (i=0;ilock_Index,0 ); + cyg_spinlock_init( &global->rank_lock,0 ); + { { +/*---------------------------------------*/ + int mon_dum1,mon_dum2; + + for (mon_dum1=0; mon_dum1 < MAX_PROCESSORS; mon_dum1++) { + cyg_spinlock_init( &global->section_lock[mon_dum1].lock,0 );; + } +/*---------------------------------------*/ +};} + {{ +/*---------------------------------------*/ + int mon_dum1,mon_dum2; + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) + for (mon_dum2=0; mon_dum2 < 1; mon_dum2++) { + global->barrier_rank[mon_dum1].count[mon_dum2] = 0; + { cyg_semaphore_init(&global->barrier_rank[mon_dum1].queue[mon_dum2],0);}; + } + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) { + cyg_spinlock_init( &global->barrier_rank[mon_dum1].lock,0 );; + } +/*---------------------------------------*/ +}} + {{ +/*---------------------------------------*/ + int mon_dum1,mon_dum2; + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) + for (mon_dum2=0; mon_dum2 < 1; mon_dum2++) { + global->barrier_key[mon_dum1].count[mon_dum2] = 0; + { cyg_semaphore_init(&global->barrier_key[mon_dum1].queue[mon_dum2],0);}; + } + for (mon_dum1=0; mon_dum1 < 1; mon_dum1++) { + cyg_spinlock_init( &global->barrier_key[mon_dum1].lock,0 );; + } +/*---------------------------------------*/ +}} + + for (i=0; i<2*number_of_processors; i++) { + {/*##########*/;}; + } + + global->Index = 0; + max_num_digits = get_max_digits(max_key); + diag_printf("\n"); + diag_printf("Integer Radix Sort\n"); + diag_printf(" %d Keys\n",num_keys); + diag_printf(" %d Processors\n",number_of_processors); + diag_printf(" Radix = %d\n",radix); + diag_printf(" Max key = %d\n",max_key); + diag_printf("\n"); + + quotient = num_keys / number_of_processors; + remainder = num_keys % number_of_processors; + sum_i = 0; + sum_f = 0; + p = 0; + diag_printf("key_partition\n",max_key); + while (sum_i < num_keys) { + key_partition[p] = sum_i; + p++; + sum_i = sum_i + quotient; + sum_f = sum_f + remainder; + sum_i = sum_i + sum_f / number_of_processors; + sum_f = sum_f % number_of_processors; + } + key_partition[p] = num_keys; + + quotient = radix / number_of_processors; + remainder = radix % number_of_processors; + sum_i = 0; + sum_f = 0; + p = 0; + diag_printf("rank_partition\n",max_key); + while (sum_i < radix) { + rank_partition[p] = sum_i; + p++; + sum_i = sum_i + quotient; + sum_f = sum_f + remainder; + sum_i = sum_i + sum_f / number_of_processors; + sum_f = sum_f % number_of_processors; + } + rank_partition[p] = radix; + +/* POSSIBLE ENHANCEMENT: Here is where one might distribute the key, + rank_me, rank, and gp data structures across physically + distributed memories as desired. + + One way to place data is as follows: + + for (i=0;i> 1; + base = number_of_processors; + while ((offset & 0x1) != 0) { + offset >>= 1; + index = base + offset; + Place all addresses x such that: + &(global->prefix_tree[index]) <= x < + &(global->prefix_tree[index + 1]) on node toffset + base += level; + level >>= 1; + } + } */ + + /* Fill the random-number array. */ + + for (i = 1; i < number_of_processors; i++) { + +{ + /*---------------------------------------*/ + stack[i] = calloc(STACK_SIZE, 1); + cyg_thread_create(10, // Priority - just a number + slave_sort, // entry + 0, // index + "slave", // Name + stack[i], // Stack + STACK_SIZE, // Size + &threadh[i], // Handle + &thread[i] // Thread data structure + ); + cyg_thread_resume( threadh[i] ); + /*---------------------------------------*/ +} + + } + + slave_sort(); + + for (i = 1; i < number_of_processors; i++) { + while(thread_array[i]) {}; + } + + diag_printf("\n"); + diag_printf(" PROCESS STATISTICS\n"); + diag_printf(" Total Rank Sort\n"); + diag_printf(" Proc Time Time Time\n"); + diag_printf(" 0 %10.0f %10.0f %10.0f\n", + global->totaltime[0],global->ranktime[0], + global->sorttime[0]); + if (dostats) { + maxt = avgt = mint = global->totaltime[0]; + maxrank = avgrank = minrank = global->ranktime[0]; + maxsort = avgsort = minsort = global->sorttime[0]; + for (i=1; itotaltime[i] > maxt) { + maxt = global->totaltime[i]; + } + if (global->totaltime[i] < mint) { + mint = global->totaltime[i]; + } + if (global->ranktime[i] > maxrank) { + maxrank = global->ranktime[i]; + } + if (global->ranktime[i] < minrank) { + minrank = global->ranktime[i]; + } + if (global->sorttime[i] > maxsort) { + maxsort = global->sorttime[i]; + } + if (global->sorttime[i] < minsort) { + minsort = global->sorttime[i]; + } + avgt += global->totaltime[i]; + avgrank += global->ranktime[i]; + avgsort += global->sorttime[i]; + } + avgt = avgt / number_of_processors; + avgrank = avgrank / number_of_processors; + avgsort = avgsort / number_of_processors; + for (i=1; itotaltime[i],global->ranktime[i], + global->sorttime[i]); + } + diag_printf(" Avg %10.0f %10.0f %10.0f\n",avgt,avgrank,avgsort); + diag_printf(" Min %10.0f %10.0f %10.0f\n",mint,minrank,minsort); + diag_printf(" Max %10.0f %10.0f %10.0f\n",maxt,maxrank,maxsort); + diag_printf("\n"); + } + + diag_printf("\n"); + global->starttime = start; + diag_printf(" TIMING INFORMATION\n"); + diag_printf("Start time : %16d\n", + global->starttime); + diag_printf("Initialization finish time : %16d\n", + global->rs); + diag_printf("Overall finish time : %16d\n", + global->rf); + diag_printf("Total time with initialization : %16d\n", + global->rf-global->starttime); + diag_printf("Total time without initialization : %16d\n", + global->rf-global->rs); + diag_printf("\n"); + + if (doprint) { + printout(); + } + if (test_result) { + test_sort(global->final); + } + + +{ + diag_printf("FP test end\n"); + return 0; +} +; +} + +void slave_sort() +{ + int i, j, k, kk, Ind; + int MyNum; + int this_key; + int tmp; + int last_key; + int loopnum; + double ran_num; + double sum; + int shiftnum; + int bb; + int my_key; + int key_start; + int key_stop; + int rank_start; + int rank_stop; + int from=0; + int to=1; + int *key_density; /* individual processor key densities */ + unsigned int time1; + unsigned int time2; + unsigned int time3; + unsigned int time4; + unsigned int time5; + unsigned int time6; + double ranktime=0; + double sorttime=0; + int *key_from; + int *key_to; + int *rank_me_mynum; + int *rank_me_i; + int *rank_ff_mynum; + int stats; + struct prefix_node* n; + struct prefix_node* r; + struct prefix_node* l; + struct prefix_node* my_node; + struct prefix_node* their_node; + volatile int* prefx; + int index; + int level; + int base; + int offset; + + diag_printf("SlaveSort %d\n",cyg_hal_get_current_threadid()); + + stats = dostats; + + cyg_spinlock_spin(&global->lock_Index); + MyNum = global->Index; + global->Index++; + cyg_spinlock_clear(&global->lock_Index); + +/* POSSIBLE ENHANCEMENT: Here is where one might pin processes to + processors to avoid migration */ + + key_density = (int *) malloc(radix*sizeof(int)); + + /* Fill the random-number array. */ + + key_start = key_partition[MyNum]; + key_stop = key_partition[MyNum + 1]; + rank_start = rank_partition[MyNum]; + rank_stop = rank_partition[MyNum + 1]; + if (rank_stop == radix) { + rank_stop--; + } + + diag_printf("init %d, %d-%d\n",cyg_hal_get_current_threadid(),key_start,key_stop); + init(key_start,key_stop,from); + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_key[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1 ,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + if ( global->barrier_key[0].count[0] < (number_of_processors -1) ) { + global->barrier_key[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1 ,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_key[0].lock );; + { cyg_semaphore_wait(&global->barrier_key[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + if ( global->barrier_key[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1 ,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_key[0].lock );; + + } else { + ( global->barrier_key[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_key[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),1 ,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_key[0].queue[0] );}; + } + +/*---------------------------------*/ +} + +/* POSSIBLE ENHANCEMENT: Here is where one might reset the + statistics that one is measuring about the parallel execution */ + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_key[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + if ( global->barrier_key[0].count[0] < (number_of_processors -1) ) { + global->barrier_key[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_key[0].lock );; + { cyg_semaphore_wait(&global->barrier_key[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + if ( global->barrier_key[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_key[0].lock );; + + } else { + ( global->barrier_key[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_key[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),2,global->barrier_key[0].count[0],global->barrier_key[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_key[0].queue[0] );}; + } + +/*---------------------------------*/ +} + + if ((MyNum == 0) || (stats)) { + { + (time1) = cyg_current_time()*10; +} + + } + +/* Do 1 iteration per digit. */ + + rank_me_mynum = rank_me[MyNum]; + rank_ff_mynum = gp[MyNum].rank_ff; + for (loopnum=0;loopnum> shiftnum; + rank_me_mynum[my_key]++; + } + key_density[0] = rank_me_mynum[0]; + for (i=1;ibarrier_rank[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] < (number_of_processors -1) ) { + global->barrier_rank[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + { cyg_semaphore_wait(&global->barrier_rank[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + + } else { + ( global->barrier_rank[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_rank[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),3,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_rank[0].queue[0] );}; + } + +/*---------------------------------*/ +} + + n = &(global->prefix_tree[MyNum]); + for (i = 0; i < radix; i++) { + n->densities[i] = key_density[i]; + n->ranks[i] = rank_me_mynum[i]; + } + offset = MyNum; + level = number_of_processors >> 1; + base = number_of_processors; + if ((MyNum & 0x1) == 0) { + {/*##########*/;}; + } + while ((offset & 0x1) != 0) { + offset >>= 1; + r = n; + l = n - 1; + index = base + offset; + n = &(global->prefix_tree[index]); + {/*##########*/;}; + {/*##########*/;}; + if (offset != (level - 1)) { + for (i = 0; i < radix; i++) { + n->densities[i] = r->densities[i] + l->densities[i]; + n->ranks[i] = r->ranks[i] + l->ranks[i]; + } + } else { + for (i = 0; i < radix; i++) { + n->densities[i] = r->densities[i] + l->densities[i]; + } + } + base += level; + level >>= 1; + if ((offset & 0x1) == 0) { + {/*##########*/;}; + } + } + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_rank[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] < (number_of_processors -1) ) { + global->barrier_rank[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + { cyg_semaphore_wait(&global->barrier_rank[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + + } else { + ( global->barrier_rank[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_rank[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),4,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_rank[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + if (MyNum != (number_of_processors - 1)) { + offset = MyNum; + level = number_of_processors; + base = 0; + while ((offset & 0x1) != 0) { + offset >>= 1; + base += level; + level >>= 1; + } + my_node = &(global->prefix_tree[base + offset]); + offset >>= 1; + base += level; + level >>= 1; + while ((offset & 0x1) != 0) { + offset >>= 1; + base += level; + level >>= 1; + } + their_node = &(global->prefix_tree[base + offset]); + {/*##########*/;}; + {/*##########*/;}; + for (i = 0; i < radix; i++) { + my_node->densities[i] = their_node->densities[i]; + } + } else { + my_node = &(global->prefix_tree[(2 * number_of_processors) - 2]); + } + offset = MyNum; + level = number_of_processors; + base = 0; + while ((offset & 0x1) != 0) { + {/*##########*/;}; + offset >>= 1; + base += level; + level >>= 1; + } + offset = MyNum; + level = number_of_processors; + base = 0; + for(i = 0; i < radix; i++) { + rank_ff_mynum[i] = 0; + } + while (offset != 0) { + if ((offset & 0x1) != 0) { + /* Add ranks of node to your left at this level */ + l = &(global->prefix_tree[base + offset - 1]); + for (i = 0; i < radix; i++) { + rank_ff_mynum[i] += l->ranks[i]; + } + } + base += level; + level >>= 1; + offset >>= 1; + } + for (i = 1; i < radix; i++) { + rank_ff_mynum[i] += my_node->densities[i - 1]; + } + + if ((MyNum == 0) || (stats)) { + { + (time3) = cyg_current_time()*10; +} +; + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_rank[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] < (number_of_processors -1) ) { + global->barrier_rank[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + { cyg_semaphore_wait(&global->barrier_rank[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + + } else { + ( global->barrier_rank[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_rank[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),5,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_rank[0].queue[0] );}; + } + +/*---------------------------------*/ +}; + + if ((MyNum == 0) || (stats)) { + { + (time4) = cyg_current_time()*10; +} +; + } + + /* put it in order according to this digit */ + + for (i = key_start; i < key_stop; i++) { + this_key = key_from[i] & bb; + this_key = this_key >> shiftnum; + tmp = rank_ff_mynum[this_key]; + key_to[tmp] = key_from[i]; + rank_ff_mynum[this_key]++; + } /* i */ + + if ((MyNum == 0) || (stats)) { + { + (time5) = cyg_current_time()*10; +} +; + } + + if (loopnum != max_num_digits-1) { + from = from ^ 0x1; + to = to ^ 0x1; + } + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_rank[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] < (number_of_processors -1) ) { + global->barrier_rank[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + { cyg_semaphore_wait(&global->barrier_rank[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + + } else { + ( global->barrier_rank[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_rank[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),6,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_rank[0].queue[0] );}; + } + +/*---------------------------------*/ +} + + if ((MyNum == 0) || (stats)) { + ranktime += (time3 - time2); + sorttime += (time5 - time4); + } + } /* for */ + + { +/*---------------------------------*/ + cyg_spinlock_spin(&( global->barrier_rank[0].lock ) );; + + if (dbg_on) { + diag_printf(" thread %d: >b (%d:%d:%d): Enter barrier\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] < (number_of_processors -1) ) { + global->barrier_rank[0].count[0]++; + + if (dbg_on) { + diag_printf(" thread %d: ?b (%d:%d:%d): Wait\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + { cyg_semaphore_wait(&global->barrier_rank[0].queue[0] );}; + } + + if (dbg_on) { + diag_printf(" thread %d: barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + if ( global->barrier_rank[0].count[0] == 0 ) { + if (dbg_on) { + diag_printf(" thread %d: ^b (%d:%d:%d): unlock barrier \n-----------\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + + cyg_spinlock_clear(&global->barrier_rank[0].lock );; + + } else { + ( global->barrier_rank[0].count[0] )-- ; + //cyg_spinlock_clear(&global->barrier_rank[0].count_lock[0] );; + + if (dbg_on) { + diag_printf(" thread %d: @b (%d:%d:%d): unlock queue\n",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid(),7,global->barrier_rank[0].count[0],global->barrier_rank[0].queue[0].count); + } + { cyg_semaphore_post(&global->barrier_rank[0].queue[0] );}; + } + +/*---------------------------------*/ +} + if ((MyNum == 0) || (stats)) { + { + (time6) = cyg_current_time()*10; +} + + global->ranktime[MyNum] = ranktime; + global->sorttime[MyNum] = sorttime; + global->totaltime[MyNum] = time6-time1; + } + if (MyNum == 0) { + global->rs = time1; + global->rf = time6; + global->final = to; + } + + thread_array[MyNum] = 0; +} + +double product_mod_46(t1, t2) /* product_mod_46() returns the product + (mod 2^46) of t1 and t2. */ +double t1; +double t2; + +{ + double a1; + double b1; + double a2; + double b2; + + a1 = (double)((int)(t1 / RADIX_S)); /* Decompose the arguments. */ + a2 = t1 - a1 * RADIX_S; + b1 = (double)((int)(t2 / RADIX_S)); + b2 = t2 - b1 * RADIX_S; + t1 = a1 * b2 + a2 * b1; /* Multiply the arguments. */ + t2 = (double)((int)(t1 / RADIX_S)); + t2 = t1 - t2 * RADIX_S; + t1 = t2 * RADIX_S + a2 * b2; + t2 = (double)((int)(t1 / RADIX)); + + return (t1 - t2 * RADIX); /* Return the product. */ +} + +double ran_num_init(k, b, t) /* finds the (k)th random number, + given the seed, b, and the ratio, t. */ +unsigned int k; +double b; +double t; + +{ + unsigned int j; + + while (k != 0) { /* while() is executed m times + such that 2^m > k. */ + j = k >> 1; + if ((j << 1) != k) { + b = product_mod_46(b, t); + } + t = product_mod_46(t, t); + k = j; + } + + return b; +} + +int get_max_digits(max_key) + +int max_key; + +{ + int done = 0; + int temp = 1; + int key_val; + + key_val = max_key; + while (!done) { + key_val = key_val / radix; + if (key_val == 0) { + done = 1; + } else { + temp ++; + } + } + return temp; +} + +int get_log2_radix(rad) + +int rad; + +{ + int cumulative=1; + int out; + + for (out = 0; out < 20; out++) { + if (cumulative == rad) { + return(out); + } else { + cumulative = cumulative * 2; + } + } + diag_printf("ERROR: Radix %d not a power of 2\n", rad); + exit(-1); +} + +int get_log2_keys(num_keys) + +int num_keys; + +{ + int cumulative=1; + int out; + + for (out = 0; out < 30; out++) { + if (cumulative == num_keys) { + return(out); + } else { + cumulative = cumulative * 2; + } + } + diag_printf("ERROR: Number of keys %d not a power of 2\n", num_keys); + exit(-1); +} + +int log_2(number) + +int number; + +{ + int cumulative = 1; + int out = 0; + int done = 0; + + while ((cumulative < number) && (!done) && (out < 50)) { + if (cumulative == number) { + done = 1; + } else { + cumulative = cumulative * 2; + out ++; + } + } + + if (cumulative == number) { + return(out); + } else { + return(-1); + } +} + +void printerr(s) + +char *s; + +{ + diag_printf("ERROR: %s\n",s); +} + +void init(key_start,key_stop,from) + +int key_start; +int key_stop; +int from; + +{ + double ran_num; + double sum; + int tmp; + int i; + int *key_from; + + ran_num = ran_num_init((key_start << 2) + 1, SEED, RATIO); + sum = ran_num / RADIX; + key_from = (int *) key[from]; + for (i = key_start; i < key_stop; i++) { + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + ran_num = product_mod_46(ran_num, RATIO); + sum = sum + ran_num / RADIX; + key_from[i] = (int) ((sum / 4.0) * max_key); + tmp = (int) ((key_from[i])/100); + ran_num = product_mod_46(ran_num, RATIO); + sum = ran_num / RADIX; + } + +} + +void test_sort(final) + +int final; + +{ + int i; + int mistake = 0; + int *key_final; + + diag_printf("\n"); + diag_printf(" TESTING RESULTS\n"); + key_final = key[final]; + for (i = 0; i < num_keys-1; i++) { + if (key_final[i] > key_final[i + 1]) { + diag_printf("error with key %d, value %d %d \n", + i,key_final[i],key_final[i + 1]); + mistake++; + } + } + + if (mistake) { + diag_printf("FAILED: %d keys out of place.\n", mistake); + } else { + diag_printf("PASSED: All keys in place.\n"); + } + diag_printf("\n"); +} + +void printout() + +{ + int i; + int mistake; + int *key_final; + + key_final = (int *) key[global->final]; + diag_printf("\n"); + diag_printf(" SORTED KEY VALUES\n"); + diag_printf("%8d ",key_final[0]); + for (i = 0; i < num_keys-1; i++) { + diag_printf("%8d ",key_final[i+1]); + if ((i+2)%5 == 0) { + diag_printf("\n"); + } + } + diag_printf("\n"); +} + +#include diff -Naurb ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix_arg.c ecos-rep/packages/kernel/current/tests_smp/radix_arg.c --- ecos-cvs-2005-09-06/packages/kernel/current/tests_smp/radix_arg.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/kernel/current/tests_smp/radix_arg.c 2006-02-20 16:16:38.000000000 +0100 @@ -0,0 +1,12 @@ +//___________________________________________ +#define _str_HAL_SMP_CPU_MAX(x) #x +#define smp_cyg_test_argc 5 +char *_cyg_argv[] = { + "radix.exe", + "-p", + "2", /* not used, using HAL_SMP_CPU_MAX */ + "-m", + "10" +}; +#define smp_cyg_test_argv &_cyg_argv +//''''''''''''''''''''''''''''''''''''''''''' diff -Naurb ecos-cvs-2005-09-06/packages/net/common/current/cdl/net.cdl ecos-rep/packages/net/common/current/cdl/net.cdl --- ecos-cvs-2005-09-06/packages/net/common/current/cdl/net.cdl 2004-08-02 12:43:39.000000000 +0200 +++ ecos-rep/packages/net/common/current/cdl/net.cdl 2005-09-05 16:21:09.000000000 +0200 @@ -479,6 +479,7 @@ no_define calculated { CYGPKG_NET_BUILD_HW_TESTS ? \ "tests/mbuf_test \ + tests/pd_test \ tests/socket_test \ tests/ftp_test \ tests/server_test \ diff -Naurb ecos-cvs-2005-09-06/packages/net/common/current/tests/pd_test.c ecos-rep/packages/net/common/current/tests/pd_test.c --- ecos-cvs-2005-09-06/packages/net/common/current/tests/pd_test.c 1970-01-01 01:00:00.000000000 +0100 +++ ecos-rep/packages/net/common/current/tests/pd_test.c 2005-09-06 15:05:17.000000000 +0200 @@ -0,0 +1,408 @@ +//========================================================================== +// +// tests/tcp_echo.c +// +// Simple TCP throughput test - echo component +// +//========================================================================== +//####BSDCOPYRIGHTBEGIN#### +// +// ------------------------------------------- +// +// Portions of this software may have been derived from OpenBSD or other sources, +// and are covered by the appropriate copyright disclaimers included herein. +// +// ------------------------------------------- +// +//####BSDCOPYRIGHTEND#### +//========================================================================== +//#####DESCRIPTIONBEGIN#### +// +// Author(s): gthomas +// Contributors: gthomas +// Date: 2000-01-10 +// Purpose: +// Description: This is the middle part of a three part test. The idea is +// to test the throughput of box in a configuration like this: +// +// +------+ port +----+ port +----+ +// |SOURCE|=========>|ECHO|============>|SINK| +// +------+ 9990 +----+ 9991 +----+ +// +// +//####DESCRIPTIONEND#### +// +//========================================================================== + + +#include +#include +#include + + + +#ifdef CYGBLD_DEVS_ETH_DEVICE_H // Get the device config if it exists +#include CYGBLD_DEVS_ETH_DEVICE_H // May provide CYGTST_DEVS_ETH_TEST_NET_REALTIME +#endif + +#ifdef CYGPKG_NET_TESTS_USE_RT_TEST_HARNESS // do we use the rt test? +# ifdef CYGTST_DEVS_ETH_TEST_NET_REALTIME // Get the test ancilla if it exists +# include CYGTST_DEVS_ETH_TEST_NET_REALTIME +# endif +#endif + + +// Fill in the blanks if necessary +#ifndef TNR_OFF +# define TNR_OFF() +#endif +#ifndef TNR_ON +# define TNR_ON() +#endif +#ifndef TNR_INIT +# define TNR_INIT() +#endif +#ifndef TNR_PRINT_ACTIVITY +# define TNR_PRINT_ACTIVITY() +#endif + +#ifndef CYGPKG_KERNEL_SMP_SUPPORT +#define cyg_hal_get_current_cpuid() 0 +#define cyg_hal_get_current_threadid() 0 +#endif + +// Network throughput test code + +#include + +static __inline__ unsigned int +max(unsigned int m, unsigned int n) +{ + return m > n ? m : n; +} + +#define SOURCE_PORT1 9990 +#define SOURCE_PORT2 9991 + +#define MAX_BUF 8192 +static unsigned char data_buf[MAX_BUF]; + +struct test_params { + long nbufs; + long bufsize; + long load; +}; + +struct test_status { + long ok; +}; + +#ifndef CYGPKG_LIBC_STDIO +#define perror(s) diag_printf(#s ": %s\n", strerror(errno)) +#endif + +#define STACK_SIZE (CYGNUM_HAL_STACK_SIZE_TYPICAL + 0x2000) +static char stack[STACK_SIZE*2]; +static cyg_thread thread_data1; +static cyg_handle_t thread_handle1; +static cyg_thread thread_data2; +static cyg_handle_t thread_handle2; + +// Background load stuff +#define NUM_LOAD_THREADS 20 // Get 5% granularity +#define IDLE_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY+3 +#define LOAD_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-3 +#define MAIN_THREAD_PRIORITY CYGPKG_NET_THREAD_PRIORITY-4 +#define DESIRED_BACKGROUND_LOAD 50 // should be accurate enough over range + +// starting points for load calculation +#define MAX_LOAD_THREAD_LEVEL 100 +#define MIN_LOAD_THREAD_LEVEL 0 + +static cyg_sem_t init_net_thread_sem; + + +static char idle_thread_stack[STACK_SIZE]; +static cyg_thread idle_thread_data; +static cyg_handle_t idle_thread_handle; +static cyg_sem_t idle_thread_sem; +volatile static long long idle_thread_count; +static cyg_thread load_thread_data[NUM_LOAD_THREADS]; +static cyg_handle_t load_thread_handle[NUM_LOAD_THREADS]; +static cyg_sem_t load_thread_sem[NUM_LOAD_THREADS]; +static long load_thread_level; +static void start_load(int load); +static void do_some_random_computation(int p,int id); +#define abs(n) ((n) < 0 ? -(n) : (n)) + +static long long no_load_idle_count_1_second; + +extern void +cyg_test_exit(void); + +void +pexit(char *s) +{ + TNR_OFF(); + perror(s); + cyg_test_exit(); +} + +int +do_read(int s, void *_buf, int len) +{ + int total, slen, rlen; + unsigned char *buf = (unsigned char *)_buf; + total = 0; + rlen = len; + while (total < len) { + slen = read(s, buf, rlen); + if (slen != rlen) { + if (slen < 0) { + diag_printf("Error after reading %d bytes\n", total); + return -1; + } + rlen -= slen; + buf += slen; + } + total += slen; + } + return total; +} + +int +do_write(int s, void *_buf, int len) +{ + int total, slen, rlen; + unsigned char *buf = (unsigned char *)_buf; + total = 0; + rlen = len; + while (total < len) { + slen = write(s, buf, rlen); + if (slen != rlen) { + if (slen < 0) { + diag_printf("Error after writing %d bytes\n", total); + return -1; + } + rlen -= slen; + buf += slen; + } + total += slen; + } + return total; +} + + + +// +// These thread(s) do some amount of "background" computing. This is used +// to simulate a given load level. They need to be run at a higher priority +// than the network code itself. +// +// Like the "idle" thread, they run as long as their "switch" (aka semaphore) +// is enabled. +// +void +net_load(cyg_addrword_t who) +{ + int i; + while (true) { + cyg_semaphore_wait(&load_thread_sem[who]); + for (i = 0; i < load_thread_level; i++) { + do_some_random_computation(i,who); + } + cyg_thread_delay(1); // Wait until the next 'tick' + cyg_semaphore_post(&load_thread_sem[who]); + } +} + +// +// Some arbitrary computation, designed to use up the CPU and cause associated +// cache "thrash" behaviour - part of background load modelling. +// +static void +do_some_random_computation(int p,int id) +{ + // Just something that might be "hard" +#if 0 + { + volatile double x; + x = ((p * 10) * 3.14159) / 180.0; // radians + } +#endif +#if 1 + { + static int footle[0x10001]; + static int counter = 0; + register int i; + + i = (p << 8) + id + counter++; + i &= 0xffff; + footle[ i+1 ] += footle[ i ] + 1; + } +#endif +} + +// +// This thread does nothing but count. It will be allowed to count +// as long as the semaphore is "free". +// +void +net_idle(cyg_addrword_t param) +{ + while (true) { + cyg_semaphore_wait(&idle_thread_sem); + idle_thread_count++; + cyg_semaphore_post(&idle_thread_sem); + } +} + +static void +echo_test(cyg_addrword_t p) +{ + int s_source, e_source; + struct sockaddr_in e_source_addr, e_sink_addr, local; + int one = 1; + fd_set in_fds; + int i, num, len; + struct test_params params,nparams; + struct test_status status,nstatus; + char buf[1024]; int bufpos = 0; + + int loopc = 0; + + cyg_tick_count_t starttime, stoptime; + + + s_source = socket(AF_INET, SOCK_STREAM, 0); + if (s_source < 0) { + pexit("stream socket"); + } + if (setsockopt(s_source, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) { + pexit("setsockopt /source/ SO_REUSEADDR"); + } + if (setsockopt(s_source, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one))) { + pexit("setsockopt /source/ SO_REUSEPORT"); + } + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_len = sizeof(local); + local.sin_port = ntohs(p); + local.sin_addr.s_addr = INADDR_ANY; + if(bind(s_source, (struct sockaddr *) &local, sizeof(local)) < 0) { + pexit("bind /source/ error"); + } + diag_printf("Listem at port %d\n",p); + listen(s_source, SOMAXCONN); + + while (1) { + + e_source = 0; + while (true) { + FD_ZERO(&in_fds); + FD_SET(s_source, &in_fds); + num = select(s_source+1, &in_fds, 0, 0, 0); + if (FD_ISSET(s_source, &in_fds)) { + len = sizeof(e_source_addr); + if ((e_source = accept(s_source, (struct sockaddr *)&e_source_addr, &len)) < 0) { + pexit("accept /source/"); + } + diag_printf("SOURCE connection from %s:%d\n", + inet_ntoa(e_source_addr.sin_addr), ntohs(e_source_addr.sin_port)); + } + if ((e_source != 0) ) { + break; + } + } + + while(1) { + char b; + if ((len = do_read(e_source, &b, 1) != 1)) { + if (len <= 0) { + break; + } + } + buf[bufpos++] = b; + buf[bufpos] = 0; + if (b == '\n' || bufpos >= 1000){ + unsigned long sp; + //if (loopc++ > 10) { + loopc = 0; + __GET_SP(sp); + diag_printf(" thread %d:",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid()); + //diag_printf("%d\n",cyg_hal_get_current_threadid()); + diag_printf(&buf); + //} + + bufpos = 0; + } + } + + diag_printf("Connection closed"); + } + + +} + +void +net_test(cyg_addrword_t param) +{ + diag_printf("Start TCP test - ECHO mode\n"); + //cyg_thread_delay(1*100); // Pause for one second + diag_printf("init Network\n"); + init_all_network_interfaces(); + diag_printf("Network initilized\n"); + cyg_semaphore_post(&init_net_thread_sem); // Start idle thread + diag_printf(" thread %d: start",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid()); + echo_test(SOURCE_PORT1); + cyg_test_exit(); +} + +void +net_test2(cyg_addrword_t param) +{ + cyg_semaphore_wait(&init_net_thread_sem); + diag_printf(" thread %d: start",cyg_hal_get_current_cpuid(),cyg_hal_get_current_threadid()); + echo_test(SOURCE_PORT2); +} + +void +cyg_start(void) +{ + int i; + + cyg_semaphore_init(&init_net_thread_sem, 0); + // Create a main thread which actually runs the test + diag_printf("Create thread 1\n"); + cyg_thread_create(MAIN_THREAD_PRIORITY, // Priority + net_test, // entry + 0, // entry parameter + "Network test1", // Name + &stack[0], // Stack + STACK_SIZE, // Size + &thread_handle1, // Handle + &thread_data1 // Thread data structure + ); + cyg_thread_resume(thread_handle1); // Start it + diag_printf("stack[0]:0x%x-0x%x\n",&stack[0], + ((unsigned int)&stack[0])+STACK_SIZE); + + // Create the idle thread environment + diag_printf("Create idle 3\n"); + cyg_thread_create(IDLE_THREAD_PRIORITY, // Priority + net_test2, // entry + 0, // entry parameter + "Network idle", // Name + &idle_thread_stack[0], // Stack + STACK_SIZE, // Size + &idle_thread_handle, // Handle + &idle_thread_data // Thread data structure + ); + cyg_thread_resume(idle_thread_handle); // Start it + diag_printf("stack[1]:0x%x-0x%x\n",&idle_thread_stack[0], + ((unsigned int)(&idle_thread_stack[0]))+STACK_SIZE); + + cyg_scheduler_start(); +} + +// EOF tcp_echo.c