diff options
author | Eric Norum <WENorum@lbl.gov> | 2004-10-20 15:21:05 +0000 |
---|---|---|
committer | Eric Norum <WENorum@lbl.gov> | 2004-10-20 15:21:05 +0000 |
commit | 7be6ad9701934100d2929abbcce770da1e0a005f (patch) | |
tree | 5b8fc8b6cfcf0a61594e54f8fc2fafc6a4dc1a25 /c/src/lib/libbsp/powerpc/mvme5500/network | |
parent | 2004-10-20 Ralf Corsepius <ralf_corsepius@rtems.org> (diff) | |
download | rtems-7be6ad9701934100d2929abbcce770da1e0a005f.tar.bz2 |
Add MVME550 BSP
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mvme5500/network')
-rw-r--r-- | c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.c | 1649 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.h | 135 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/mvme5500/network/GT64260ethreg.h | 879 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.am | 43 | ||||
-rw-r--r-- | c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.in | 594 |
5 files changed, 3300 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.c b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.c new file mode 100644 index 0000000000..530fa65fab --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.c @@ -0,0 +1,1649 @@ +/* GT64260eth.c : GT64260 10/100 Mb ethernet MAC driver + * + * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc. + * + * Copyright (c) 2003,2004 RTEMS/Mvme5500 port by S. Kate Feng <feng1@bnl.gov> + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Allegro Networks, Inc., and Wasabi Systems, Inc. + * 4. The name of Allegro Networks, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * 5. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * S. Kate Feng, other notes in addition to porting to RTEMS : + * + * 1) Mvme5500 uses Eth0 (controller 0) of the GT64260 to implement + * the 10/100 BaseT Ethernet with PCI Master Data Byte Swap\ + * control. + * 2) It implements hardware snoop instead of software snoop + * to ensure SDRAM cache coherency. + * 3) The origianl ISR is optimized to minimize interrupt latencies, + * and to reduce system overhead. The driver's work is done by one single + * task who blocks on an event while it is idle. This implemetation + * is heavily inspired by the modification of SVGM network driver for + * RTEMS port written by Till Straumann, whihc is licensed under the + * EPICS open source. Ditto the GT64260eth_sendpacket(). + * + */ +#define BYTE_ORDER BIG_ENDIAN + +#ifndef KERNEL +#define KERNEL +#endif + +#define INET + +#include <rtems.h> +#include <rtems/bspIo.h> /* printk */ +#include <stdio.h> /* printf for statistics */ +#include <string.h> + +#include <libcpu/io.h> /* inp & friends */ +#include <libcpu/spr.h> /* registers.h is included here */ +#include <bsp.h> + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#include <rtems/rtems_bsdnet.h> +#include <rtems/rtems_bsdnet_internal.h> +#include <rtems/error.h> +#include <errno.h> + +#include <rtems/rtems/types.h> + +#include <sys/queue.h> + +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <sys/sockio.h> /* SIOCADDMULTI, SIOC... */ +#include <net/if.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#include <netinet/if_ether.h> + +#ifdef INET +#include <netinet/in_var.h> +#endif + +#include <bsp/irq.h> +#include <bsp/GT64260ethreg.h> +#include <bsp/GT64260eth.h> +#include <bsp/VPD.h> + +#define GT_ETH_TASK_NAME "Geth" +#define PKT_BUF_SZ 1536 +#define SOFTC_ALIGN 31 +#define HASH_ALIGN 15 + +#define TXQ_HiLmt_OFF 2 + +/* <skf> + * 1. printk debug is for diagnosis only, which may cause + * unexpected result, especially if txq is under heavy load + * because CPU is fast with a decent cache. + */ +#define GTeth_debug 0 +#define GTeth_rx_debug 0 + +#if 0 +#define GE_FORGOT +#define GE_NORX +#define GT_DEBUG +#endif + +/* RTEMS event to kill the daemon */ +#define KILL_EVENT RTEMS_EVENT_1 +/* RTEMS event to (re)start the transmitter */ +#define START_TRANSMIT_EVENT RTEMS_EVENT_2 +/* RTEMS events used by the ISR */ +#define RX_EVENT RTEMS_EVENT_3 +#define TX_EVENT RTEMS_EVENT_4 +#define ERR_EVENT RTEMS_EVENT_5 + +#define ALL_EVENTS (KILL_EVENT|START_TRANSMIT_EVENT|RX_EVENT|TX_EVENT|ERR_EVENT) + +enum GTeth_whack_op { + GE_WHACK_START, GE_WHACK_RESTART, + GE_WHACK_CHANGE, GE_WHACK_STOP +}; + +enum GTeth_hash_op { + GE_HASH_ADD, GE_HASH_REMOVE, +}; + +#define ET_MINLEN 64 /* minimum message length */ + +static int GTeth_ifioctl(struct ifnet *ifp,unsigned cmd, caddr_t data); +static void GTeth_ifstart (struct ifnet *); +static void GTeth_ifchange(struct GTeth_softc *sc); +static void GTeth_init_rx_ring(struct GTeth_softc *sc); +static void GT64260eth_daemon(void *arg); +static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m,enum GTeth_txprio); +static unsigned GTeth_txq_done(struct GTeth_softc *sc, enum GTeth_txprio txprio); +static void GTeth_tx_cleanup(struct GTeth_softc *sc, enum GTeth_txprio, int); +static void GTeth_tx_start(struct GTeth_softc *sc, enum GTeth_txprio); +static void GTeth_tx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op); +static void GTeth_rx_cleanup(struct GTeth_softc *sc, enum GTeth_rxprio); +static int GT64260eth_rx(struct GTeth_softc *sc, enum GTeth_rxprio); +static void GTeth_rx_setup(struct GTeth_softc *sc); +static void GTeth_rxprio_setup(struct GTeth_softc *sc, enum GTeth_rxprio); +static void GTeth_rx_stop(struct GTeth_softc *dc, enum GTeth_whack_op op); +static void GT64260eth_isr(); +static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN]); +static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op, + enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN]); + +static int GTeth_hash_fill(struct GTeth_softc *sc); +static void GTeth_hash_init(struct GTeth_softc *sc); + +static struct GTeth_softc *root_GT64260eth_dev = NULL; +static int GTeth_MissedFrame_err=0; + +/* + * Convert Ethernet address to printable (loggable) representation. + */ +static const char digits[] = "0123456789abcdef"; +char * ether_sprintf(unsigned char *ap) +{ + int i; + static char etherbuf[18]; + char *cp = etherbuf; + + for (i = 0; i < 6; i++) { + *cp++ = digits[*ap >> 4]; + *cp++ = digits[*ap++ & 0xf]; + *cp++ = ':'; + } + *--cp = 0; + return (etherbuf); +} + +/* We can hard code the address here if config->hardware_address failed */ +static int GTethGet_macaddr(int macno, char *hwaddr) +{ + hwaddr[0] = 0x00; + hwaddr[1] = 0x01; + hwaddr[2] = 0xaf; + hwaddr[3] = 0x0b; + hwaddr[4] = 0x75; + hwaddr[5] = 0x36; + + return 0; +} + +static void GT64260eth_irq_on(const rtems_irq_connect_data *irq) +{ + struct GTeth_softc *sc; + + for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module) { + printk("GT64260eth_irq_on\n"); + outl(0x30883444,ETH0_EIMR); /* MOTLoad default interrupt mask */ + return; + } +} + +static void GT64260eth_irq_off(const rtems_irq_connect_data *irq) +{ + struct GTeth_softc *sc; + + for (sc= root_GT64260eth_dev; sc; sc= sc-> next_module) + outl(0, ETH0_EIMR); +} + +static int GT64260eth_irq_is_on(const rtems_irq_connect_data *irq) +{ + return(inl(ETH0_EICR) & ETH_IR_EtherIntSum); +} + +static void GT64260eth_isr() +{ + struct GTeth_softc *sc = root_GT64260eth_dev; + rtems_event_set events=0; + uint32_t cause; + + + cause = inl(ETH0_EICR); + outl( ~cause,ETH0_EICR); /* clear the ICR */ + + if (cause & (ETH_IR_RxBuffer_3|ETH_IR_RxError_3)) { + sc->stats.rxInterrupts++; + events |= RX_EVENT; + } + /* If there is an error, we want to continue to next descriptor */ + if (cause & (ETH_IR_TxBufferHigh|ETH_IR_TxEndHigh|ETH_IR_TxErrorHigh)) { + sc->stats.txInterrupts++; + events |= TX_EVENT; + if ((sc->txq_nactive) && ((inl(ETH0_ESDCMR)Ð_ESDCMR_TXDH)==0)) + outl(ETH_ESDCMR_TXDH | ETH_ESDCMR_ERD,ETH0_ESDCMR); + } + if ( (!cause) || (cause & 0x803d00)) { + sc->intr_errsts[sc->intr_err_ptr2++]=cause; + sc->intr_err_ptr2 %=INTR_ERR_SIZE; /* Till Straumann */ + events |= ERR_EVENT; + } + + rtems_event_send(sc->daemonTid, events); +} + +static rtems_irq_connect_data GT64260ethIrqData={ + BSP_MAIN_ETH0_IRQ, + (rtems_irq_hdl) GT64260eth_isr, + (rtems_irq_enable) GT64260eth_irq_on, + (rtems_irq_disable) GT64260eth_irq_off, + (rtems_irq_is_enabled) GT64260eth_irq_is_on, +}; + +static void GT64260eth_init_hw(struct GTeth_softc *sc) +{ + +#ifdef GT_DEBUG + printk("GT64260eth_init_hw("); +#endif + /* Kate Feng : Turn the hardware snoop on as MOTLoad did not have + * it on by default. + */ + outl(RxBSnoopEn|TxBSnoopEn|RxDSnoopEn|TxDSnoopEn, GT_CUU_Eth0_AddrCtrlLow); + outl(HashSnoopEn, GT_CUU_Eth0_AddrCtrlHigh); + + sc->rxq_intrbits=0; + sc->sc_flags=0; + +#ifndef GE_NORX + GTeth_rx_setup(sc); +#endif + +#ifndef GE_NOTX + GTeth_tx_start(sc, GE_TXPRIO_HI); +#endif + + sc->sc_pcr |= ETH_EPCR_HS_512; + outl(sc->sc_pcr, ETH0_EPCR); + outl(sc->sc_pcxr, ETH0_EPCXR); /* port config. extended reg. */ + outl(0, ETH0_EICR); /* interrupt cause register */ + outl(sc->sc_intrmask, ETH0_EIMR); +#ifndef GE_NOHASH + /* Port Hash Table Pointer Reg*/ + outl(((unsigned) sc->sc_hashtable),ETH0_EHTPR); +#endif +#ifndef GE_NORX + outl(ETH_ESDCMR_ERD,ETH0_ESDCMR); /* enable Rx DMA in SDMA Command Register */ + sc->sc_flags |= GE_RXACTIVE; +#endif +#ifdef GT_DEBUG + printk("SDCMR 0x%x ", inl(ETH0_ESDCMR)); +#endif + + /* connect the interrupt handler which should + * take care of enabling interrupts + */ + if (!BSP_install_rtems_irq_handler(>64260ethIrqData)) + rtems_panic("GT64260eth: unable to install ISR"); + + /* The ethernet port is ready to transmit/receive */ + outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR); + +#ifdef GT_DEBUG + printk(")\n"); +#endif +} + +static void GT64260eth_stop_hw(struct GTeth_softc *sc) +{ + + printk("GT64260eth_stop_hw("); + + /* remove our interrupt handler which will also + * disable interrupts at the MPIC and the device + * itself + */ + if (!BSP_remove_rtems_irq_handler(>64260ethIrqData)) + rtems_panic("Yellowfin: unable to remove IRQ handler!"); + + outl(sc->sc_pcr, ETH0_EPCR); + outl(0, ETH0_EIMR); + + sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; +#ifndef GE_NOTX + GTeth_tx_stop(sc, GE_WHACK_STOP); +#endif +#ifndef GE_NORX + GTeth_rx_stop(sc, GE_WHACK_STOP); +#endif + sc->sc_hashtable = NULL; + if (GTeth_debug>0) printk(")"); +} + +static void GT64260eth_stop(struct GTeth_softc *sc) +{ + if (GTeth_debug>0) printk("GT64260eth_stop("); + + /* The hardware is shutdown in the daemon */ + /* kill the daemon. We also must release the networking + * semaphore or there'll be a deadlock... + */ + rtems_event_send(sc->daemonTid, KILL_EVENT); + rtems_bsdnet_semaphore_release(); + + sc->daemonTid=0; + /* now wait for it to die */ + rtems_semaphore_obtain(sc->daemonSync,RTEMS_WAIT,RTEMS_NO_TIMEOUT); + + /* reacquire the bsdnet semaphore */ + rtems_bsdnet_semaphore_obtain(); + if (GTeth_debug>0) printk(")"); +} + +static void GT64260eth_ifinit(void *arg) +{ + struct GTeth_softc *sc = (struct GTeth_softc*)arg; + int i; + +#ifdef GT_DEBUG + printk("GT64260eth_ifinit(): daemon ID: 0x%08x)\n", sc->daemonTid); +#endif + if (sc->daemonTid) { +#ifdef GT_DEBUG + printk("GT64260eth: daemon already up, doing nothing\n"); +#endif + return; + } + +#ifndef GE_NOHASH + /* Mvme5500, the user must initialize the hash table before enabling the + * Ethernet controller + */ + GTeth_hash_init(sc); + GTeth_hash_fill(sc); +#endif + + sc->intr_err_ptr1=0; + sc->intr_err_ptr2=0; + for (i=0; i< INTR_ERR_SIZE; i++) sc->intr_errsts[i]=0; + + /* initialize the hardware (we are holding the network semaphore at this point) */ + (void)GT64260eth_init_hw(sc); + + /* launch network daemon */ + + /* NOTE: + * in ss-20011025 (and later) any task created by 'bsdnet_newproc' is + * wrapped by code which acquires the network semaphore... + */ + sc->daemonTid = rtems_bsdnet_newproc(GT_ETH_TASK_NAME,4096,GT64260eth_daemon,arg); + + /* Tell the world that we're running */ + sc->arpcom.ac_if.if_flags |= IFF_RUNNING; + +} + +/* attach parameter tells us whether to attach or to detach the driver */ +/* Attach this instance, and then all the sub-devices */ +int rtems_GT64260eth_driver_attach(struct rtems_bsdnet_ifconfig *config, int attach) +{ + struct GTeth_softc *sc; + struct ifnet *ifp; + unsigned sdcr, data; + unsigned char hwaddr[6]; + int i, unit, phyaddr; + void *softc_mem; + char *name; + + unit = rtems_bsdnet_parse_driver_name(config, &name); + if (unit < 0) return 0; + + printk("\nEthernet driver name %s unit %d \n",name, unit); + printk("Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc.\n"); + printk("(c) 2004, Brookhaven National Lab. <feng1@bnl.gov> (RTEMS/mvme5500 port)\n"); + + /* Make certain elements e.g. descriptor lists are aligned. */ + softc_mem = rtems_bsdnet_malloc(sizeof(*sc) + SOFTC_ALIGN, M_FREE, M_NOWAIT); + + /* Check for the very unlikely case of no memory. */ + if (softc_mem == NULL) + rtems_panic("GT64260eth: OUT OF MEMORY"); + + sc = (void *)(((long)softc_mem + SOFTC_ALIGN) & ~SOFTC_ALIGN); + memset(sc, 0, sizeof(*sc)); + + if (GTeth_debug>0) printk("txq_desc[0] addr:%x, rxq_desc[0] addr:%x, sizeof sc %d\n",&sc->txq_desc[0], &sc->rxq_desc[0], sizeof(*sc)); + + sc->sc_macno = unit-1; + + data = inl(ETH_EPAR); + phyaddr = ETH_EPAR_PhyAD_GET(data, sc->sc_macno); + + /* try to read HW address from the device if not overridden + * by config + */ + if (config->hardware_address) { + memcpy(hwaddr, config->hardware_address, ETHER_ADDR_LEN); + } else { + printk("Read EEPROM "); + for (i = 0; i < 6; i++) + hwaddr[i] = ConfVPD_buff[VPD_ENET0_OFFSET+i]; + } + +#ifdef GT_DEBUG + printk("using MAC addr from device:"); + for (i = 0; i < ETHER_ADDR_LEN; i++) printk("%x:", hwaddr[i]); + printk("\n"); +#endif + + memcpy(sc->arpcom.ac_enaddr, hwaddr, ETHER_ADDR_LEN); + + ifp = &sc->arpcom.ac_if; + + sc->sc_pcr = inl(ETH0_EPCR); + sc->sc_pcxr = inl(ETH0_EPCXR); + sc->sc_intrmask = inl(ETH0_EIMR) | ETH_IR_MIIPhySTC; + + printk("address %s\n", ether_sprintf(hwaddr)); + +#ifdef GT_DEBUG + printk(", pcr %x, pcxr %x ", sc->sc_pcr, sc->sc_pcxr); +#endif + + + sc->sc_pcxr |= ETH_EPCXR_PRIOrx_Override; + sc->sc_pcxr |= (3<<6); /* highest priority only */ + sc->sc_pcxr &= ~ETH_EPCXR_RMIIEn; /* MII mode */ + + /* Max. Frame Length (packet) allowed for reception is 1536 bytes, + * instead of 2048 (MOTLoad default) or 64K. + */ + sc->sc_pcxr &= ~(3 << 14); + sc->sc_pcxr |= (ETH_EPCXR_MFL_1536 << 14); + sc->sc_max_frame_length = PKT_BUF_SZ; + + + if (sc->sc_pcr & ETH_EPCR_EN) { + int tries = 1000; + /* Abort transmitter and receiver and wait for them to quiese*/ + outl(ETH_ESDCMR_AR|ETH_ESDCMR_AT,ETH0_ESDCMR); + do { + rtems_bsp_delay(100); + } while (tries-- > 0 && (inl(ETH0_ESDCMR) & (ETH_ESDCMR_AR|ETH_ESDCMR_AT))); + } +#ifdef GT_DEBUG + printk(", phy %d (mii)\n", phyaddr); + printk("ETH0_ESDCMR %x ", inl(ETH0_ESDCMR)); +#endif + + sc->sc_pcr &= ~(ETH_EPCR_EN | ETH_EPCR_RBM | ETH_EPCR_PM | ETH_EPCR_PBF); + +#ifdef GT_DEBUG + printk("Now sc_pcr %x,sc_pcxr %x", sc->sc_pcr, sc->sc_pcxr); +#endif + + /* + * Now turn off the GT. If it didn't quiese, too ***ing bad. + */ + outl(sc->sc_pcr, ETH0_EPCR); + outl(sc->sc_intrmask, ETH0_EIMR); + sdcr = inl(ETH0_ESDCR); + /* Burst size is limited to 4 64bit words */ + ETH_ESDCR_BSZ_SET(sdcr, ETH_ESDCR_BSZ_4); + sdcr |= ETH_ESDCR_RIFB;/*limit interrupt on frame boundaries, instead of buffer*/ +#if 0 + sdcr &= ~(ETH_ESDCR_BLMT|ETH_ESDCR_BLMR); /* MOTLoad defualt Big-endian */ +#endif + outl(sdcr, ETH0_ESDCR); + +#ifdef GT_DEBUG + printk("sdcr %x \n", sdcr); +#endif + + if (phyaddr== -1) rtems_panic("MII auto negotiation ?"); + + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + + ifp->if_softc = sc; + + /* set this interface's name and unit */ + ifp->if_unit = unit; + ifp->if_name = name; + + ifp->if_mtu = config->mtu ? config->mtu : ETHERMTU; + + ifp->if_init = GT64260eth_ifinit; + ifp->if_ioctl = GTeth_ifioctl; + ifp->if_start = GTeth_ifstart; + ifp->if_output = ether_output; + + /* ifp->if_watchdog = GTeth_ifwatchdog;*/ + + if (ifp->if_snd.ifq_maxlen == 0) + ifp->if_snd.ifq_maxlen = ifqmaxlen; + + /* create the synchronization semaphore */ + if (RTEMS_SUCCESSFUL != rtems_semaphore_create( + rtems_build_name('G','e','t','h'),0,0,0,&sc->daemonSync)) + rtems_panic("GT64260eth: semaphore creation failed"); + + sc->next_module = root_GT64260eth_dev; + root_GT64260eth_dev = sc; + + /* Actually attach the interface */ + if_attach(ifp); + ether_ifattach(ifp); + +#ifdef GT_DEBUG + printk("GT64260eth: Ethernet driver has been attached (handle 0x%08x,ifp 0x%08x)\n",sc, ifp); +#endif + + return(1); +} + +static void GT64260eth_stats(struct GTeth_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + + printf(" Rx Interrupts:%-8lu\n", sc->stats.rxInterrupts); + printf(" Receive Packets:%-8lu\n", ifp->if_ipackets); + printf(" Receive errors:%-8lu\n", ifp->if_ierrors); + printf(" Missed Frame errors:%-8lu\n", GTeth_MissedFrame_err); + printf(" Framing Errors:%-8lu\n", sc->stats.frame_errors); + printf(" Crc Errors:%-8lu\n", sc->stats.crc_errors); + printf(" Oversized Frames:%-8lu\n", sc->stats.length_errors); + printf(" Active Rxqs:%-8lu\n", sc->rxq_active); + printf(" Tx Interrupts:%-8lu\n", sc->stats.txInterrupts); + printf("Multi-Buffer Packets:%-8lu\n", sc->stats.txMultiBuffPacket); + printf(" Transmitt Packets:%-8lu\n", ifp->if_opackets); + printf(" Transmitt errors:%-8lu\n", ifp->if_oerrors); + printf(" Tx/Rx collisions:%-8lu\n", ifp->if_collisions); + printf(" Active Txqs:%-8lu\n", sc->txq_nactive); +} + +GT64260eth_err() +{ + printf(" Missed Frame errors:%-8lu\n", GTeth_MissedFrame_err); +} + +static int GTeth_ifioctl(struct ifnet *ifp,unsigned cmd, caddr_t data) +{ + struct GTeth_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *) data; + + int error = 0; + +#ifdef GT_DEBUG + printk("GTeth_ifioctl("); +#endif + + switch (cmd) { + default: + if (GTeth_debug >0) { + printk("etherioctl("); + if (cmd== SIOCSIFADDR) printk("SIOCSIFADDR "); + } + return ether_ioctl(ifp, cmd, data); + + case SIOCSIFFLAGS: + switch (ifp->if_flags & (IFF_UP|IFF_RUNNING)) { + case IFF_RUNNING: /* not up, so we stop */ + GT64260eth_stop(sc); + break; + case IFF_UP: /* not running, so we start */ + GT64260eth_ifinit(sc); + break; + case IFF_UP|IFF_RUNNING:/* active->active, update */ + GT64260eth_stop(sc); + GT64260eth_ifinit(sc); + break; + default: /* idle->idle: do nothing */ + break; + } + break; + case SIO_RTEMS_SHOW_STATS: + GT64260eth_stats (sc); + break; + case SIOCADDMULTI: + case SIOCDELMULTI: + error = (cmd == SIOCADDMULTI) + ? ether_addmulti(ifr, &sc->arpcom) + : ether_delmulti(ifr, &sc->arpcom); + if (error == ENETRESET) { + if (ifp->if_flags & IFF_RUNNING) + GTeth_ifchange(sc); + error = 0; + } + break; + case SIOCSIFMTU: + if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) { + error = EINVAL; + break; + } + ifp->if_mtu = ifr->ifr_mtu; + break; + } + +#ifdef GT_DEBUG + printk("exit ioctl\n"); +#endif + return error; +} + +static void GTeth_ifstart(struct ifnet *ifp) +{ + struct GTeth_softc *sc = ifp->if_softc; + +#ifdef GT_DEBUG + printk("GTeth_ifstart("); +#endif + + if ((ifp->if_flags & IFF_RUNNING) == 0) { +#ifdef GT_DEBUG + printk("IFF_RUNNING==0\n"); +#endif + return; + } + + ifp->if_flags |= IFF_OACTIVE; + rtems_event_send (sc->daemonTid, START_TRANSMIT_EVENT); +#ifdef GT_DEBUG + printk(")\n"); +#endif +} + +/* Initialize the Rx rings */ +static void GTeth_init_rx_ring(struct GTeth_softc *sc) +{ + int i; + volatile struct GTeth_desc *rxd; + unsigned nxtaddr; + + sc->rxq_fi=0; + sc->rxq_head_desc = &sc->rxq_desc[0]; + rxd = sc->rxq_head_desc; + + sc->rxq_desc_busaddr = sc->rxq_head_desc; +#ifdef GT_DEBUG + printk("rxq_desc_busaddr %x ,&sc->rxq_desc[0] %x\n", + sc->rxq_desc_busaddr, sc->rxq_head_desc); +#endif + + nxtaddr = sc->rxq_desc_busaddr + sizeof(*rxd); + sc->rx_buf_sz = (sc->arpcom.ac_if.if_mtu <= 1500 ? PKT_BUF_SZ : sc->arpcom.ac_if.if_mtu + 32); + sc->rxq_active = RX_RING_SIZE; + + for (i = 0; i < RX_RING_SIZE; i++, rxd++, nxtaddr += sizeof(*rxd)) { + struct mbuf *m; + + rxd->ed_lencnt= sc->rx_buf_sz <<16; + rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI; + + MGETHDR(m, M_WAIT, MT_DATA); + MCLGET(m, M_WAIT); + m->m_pkthdr.rcvif = &sc->arpcom.ac_if; + sc->rxq_mbuf[i] = m; + + /* convert mbuf pointer to data pointer of correct type */ + rxd->ed_bufptr = mtod(m, void *); + + /* + * update the nxtptr to point to the next txd. + */ + if (i == RX_RING_SIZE - 1) + nxtaddr = sc->rxq_desc_busaddr; + rxd->ed_nxtptr = nxtaddr; + +#ifdef GT_DEBUG + printk("ed_lencnt %x, rx_buf_sz %x ",rxd->ed_lencnt, sc->rx_buf_sz); + printk("ed_cmdsts %x \n",rxd->ed_cmdsts); + printk("mbuf @ 0x%x, next desc. @ 0x%x\n",rxd->ed_bufptr,rxd->ed_nxtptr); +#endif + } +} + +static void GTeth_rxprio_setup(struct GTeth_softc *sc, enum GTeth_rxprio rxprio) +{ + + if (GTeth_debug>0) printk("GTeth_rxprio_setup(\n"); + GTeth_init_rx_ring(sc); + + sc->rxq_intrbits = ETH_IR_RxBuffer | ETH_IR_RxError; + + switch (rxprio) { + case GE_RXPRIO_HI: + sc->rxq_intrbits |= ETH_IR_RxBuffer_3|ETH_IR_RxError_3; + break; + case GE_RXPRIO_MEDHI: + sc->rxq_intrbits |= ETH_IR_RxBuffer_2|ETH_IR_RxError_2; + break; + case GE_RXPRIO_MEDLO: + sc->rxq_intrbits |= ETH_IR_RxBuffer_1|ETH_IR_RxError_1; + break; + case GE_RXPRIO_LO: + sc->rxq_intrbits |= ETH_IR_RxBuffer_0|ETH_IR_RxError_0; + break; + } + if (GTeth_debug>0) printk(")"); +} + +static int GT64260eth_rx(struct GTeth_softc *sc, enum GTeth_rxprio rxprio) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + struct mbuf *m; + int nloops=0; + unsigned int intr_status = sc->intr_errsts[sc->intr_err_ptr1]; + + if (GTeth_rx_debug>0) printk("GT64260eth_rx("); + if (GTeth_rx_debug>5) printk("(%d)", rxprio); + + while (sc->rxq_active > 0) { + volatile struct GTeth_desc *rxd = &sc->rxq_desc[sc->rxq_fi]; + struct ether_header *eh; + unsigned int cmdsts; + unsigned int byteCount; + + cmdsts = rxd->ed_cmdsts; + + /* + * Sometimes the GE "forgets" to reset the ownership bit. + * But if the length has been rewritten, the packet is ours + * so pretend the O bit is set. + * + */ + byteCount = rxd->ed_lencnt & 0xffff; + + if (cmdsts & RX_CMD_O) { + if (byteCount == 0) + return(0); + + /* <Kate Feng> Setting command/status to be zero seems to eliminate + * the spurious interrupt associated with the GE_FORGOT issue. + */ + rxd->ed_cmdsts=0; + +#ifdef GE_FORGOT + /* + * For dignosis purpose only. Not a good practice to turn it on + */ + printk("Rxq %d %d %d\n", sc->rxq_fi, byteCount,nloops); +#endif + } + + /* GT gave the ownership back to the CPU or the length has + * been rewritten , which means there + * is new packet in the descriptor/buffer + */ + + if (GTeth_rx_debug>0) printk("desc%d: cmdsts=%x, len=%d\n", + sc->rxq_fi,cmdsts,byteCount); + nloops++; + /* + * If this is not a single buffer packet with no errors + * or for some reason it's bigger than our frame size, + * ignore it and go to the next packet. + */ + if ((cmdsts & (RX_CMD_F|RX_CMD_L|RX_STS_ES)) != + (RX_CMD_F|RX_CMD_L) || + byteCount > sc->sc_max_frame_length) { + if (GTeth_rx_debug>0) printk("Rx Error"); + --sc->rxq_active; + ifp->if_ipackets++; + ifp->if_ierrors++; + if (cmdsts & RX_STS_OR) sc->stats.or_errors++; + if (cmdsts & RX_STS_CE) sc->stats.crc_errors++; + if (cmdsts & RX_STS_MFL) sc->stats.length_errors++; + if (cmdsts & RX_STS_SF) sc->stats.frame_errors++; + /* if (cmdsts & RX_STS_M) GTeth_MissedFrame_err++;*/ + if ((cmdsts & RX_STS_LC) || (cmdsts & RX_STS_COL)) + ifp->if_collisions++; + goto give_it_back; + } + + m = sc->rxq_mbuf[sc->rxq_fi]; + sc->rxq_mbuf[sc->rxq_fi] = NULL; + m->m_len = m->m_pkthdr.len = byteCount - sizeof(struct ether_header); + eh = mtod (m, struct ether_header *); + m->m_data += sizeof(struct ether_header); + ether_input (ifp, eh, m); + if (GTeth_rx_debug>20) { + if ( m->m_flags & M_BCAST ) printk("desc%d broadcast\n",sc->rxq_fi); + if ( m->m_flags & M_MCAST ) printk("multicast "); + } + + ifp->if_ipackets++; + ifp->if_ibytes+=byteCount; + --sc->rxq_active; + + give_it_back: + MGETHDR (m, M_WAIT, MT_DATA); + MCLGET (m, M_WAIT); + m->m_pkthdr.rcvif = ifp; + sc->rxq_mbuf[sc->rxq_fi]= m; + /* convert mbuf pointer to data pointer of correct type */ + rxd->ed_bufptr = mtod(m, void*); + rxd->ed_lencnt = (unsigned long) sc->rx_buf_sz <<16; + rxd->ed_cmdsts = RX_CMD_F|RX_CMD_L|RX_CMD_O|RX_CMD_EI; + + if (++sc->rxq_fi == RX_RING_SIZE) sc->rxq_fi = 0; + + sc->rxq_active++; + } /* while (sc->rxq_active > 0) */ + if (GTeth_rx_debug>0) printk(")"); + return nloops; +} + +static void GTeth_rx_setup(struct GTeth_softc *sc) +{ + + if (GTeth_rx_debug>0) printk("GTeth_rx_setup("); + + GTeth_rxprio_setup(sc, GE_RXPRIO_HI); + + if ((sc->sc_flags & GE_RXACTIVE) == 0) { + /* First Rx Descriptor Pointer 3 */ + outl( sc->rxq_desc_busaddr, ETH0_EFRDP3); + /* Current Rx Descriptor Pointer 3 */ + outl( sc->rxq_desc_busaddr,ETH0_ECRDP3); +#ifdef GT_DEBUG + printk("ETH0_EFRDP3 0x%x, ETH0_ECRDP3 0x%x \n", inl(ETH0_EFRDP3), + inl(ETH0_ECRDP3)); +#endif + } + sc->sc_intrmask |= sc->rxq_intrbits; + + if (GTeth_rx_debug>0) printk(")\n"); +} + +static void GTeth_rx_cleanup(struct GTeth_softc *sc, enum GTeth_rxprio rxprio) +{ + int i; + + if (GTeth_rx_debug>0) printk( "GTeth_rx_cleanup("); + if (sc->rxq_curpkt) + m_freem(sc->rxq_curpkt); + + for (i=0; i< RX_RING_SIZE; i++) { + if (sc->rxq_mbuf[i]) { + m_freem(sc->rxq_mbuf[i]); + sc->rxq_mbuf[i]=0; + } + } + if (GTeth_rx_debug>0) printk(")"); +} + +static void GTeth_rx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op) +{ + if (GTeth_rx_debug>0) printk( "GTeth_rx_stop("); + sc->sc_flags &= ~GE_RXACTIVE; + sc->sc_idlemask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3); + sc->sc_intrmask &= ~(ETH_IR_RxBits|ETH_IR_RxBuffer_3|ETH_IR_RxError_3); + outl(sc->sc_intrmask, ETH0_EIMR); + outl(ETH_ESDCMR_AR, ETH0_ESDCMR); /* abort receive */ + do { + rtems_bsp_delay(10); + } while (inl(ETH0_ESDCMR) & ETH_ESDCMR_AR); + GTeth_rx_cleanup(sc, GE_RXPRIO_HI); + if (GTeth_rx_debug>0) printk(")"); +} + +static void GTeth_txq_free(struct GTeth_softc *sc, unsigned cmdsts) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi]; + + /* ownership is sent back to CPU */ + if (GTeth_debug>0) printk("txq%d,active %d\n", sc->txq_fi, sc->txq_nactive); + + txd->ed_cmdsts &= ~TX_CMD_O; /* <skf> in case GT forgot */ + + /* statistics */ + ifp->if_opackets++; + ifp->if_obytes += sc->txq_mbuf[sc->txq_fi]->m_len; + if (cmdsts & TX_STS_ES) { + ifp->if_oerrors++; + if ((cmdsts & TX_STS_LC) || (cmdsts & TX_STS_COL)) + ifp->if_collisions++; + } + /* Free the original mbuf chain */ + m_freem(sc->txq_mbuf[sc->txq_fi]); + sc->txq_mbuf[sc->txq_fi] = 0; + ifp->if_timer = 5; + + sc->txq_free++; + if (++sc->txq_fi == TX_RING_SIZE) sc->txq_fi = 0; + --sc->txq_nactive; +} + +static int txq_high_limit(struct GTeth_softc *sc) +{ + /* + * Have we [over]consumed our limit of descriptors? + * Do we have enough free descriptors? + */ + if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) { + volatile struct GTeth_desc *txd2 = &sc->txq_desc[sc->txq_fi]; + unsigned cmdsts; + + cmdsts = txd2->ed_cmdsts; + if (cmdsts & TX_CMD_O) { /* Ownership (1=GT 0=CPU) */ + int nextin; + + /* + * Sometime the Discovery forgets to update the + * last descriptor. See if CPU owned the descriptor + * after it (since we know we've turned that to + * the discovery and if CPU owned it, the Discovery + * gave it back). If CPU does, we know the Discovery + * gave back this one but forgot to mark it back to CPU. + */ + nextin = (sc->txq_fi + 1) % TX_RING_SIZE; + if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) { +#if 0 + printk("Overconsuming Tx descriptors!\n"); +#endif + return 1; + } + printk("Txq %d forgot\n", sc->txq_fi); + } + /* Txq ring is almost full, let's free the current buffer here */ +#if 0 + printk("Txq ring near full, free desc%d\n",sc->txq_fi); +#endif + GTeth_txq_free(sc, cmdsts); + } /* end if ( TX_RING_SIZE == sc->txq_nactive + TXQ_HiLmt_OFF) */ + return 0; +} + +static int GT64260eth_sendpacket(struct GTeth_softc *sc,struct mbuf *m, enum GTeth_txprio txprio) +{ + struct ifnet *ifp=&sc->arpcom.ac_if; + volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_lo]; + unsigned intrmask = sc->sc_intrmask; + unsigned index= sc->txq_lo; + + if (GTeth_debug>0) printk("sendpacket("); + + /* + * The end-of-list descriptor we put on last time is the starting point + * for this packet. The GT is supposed to terminate list processing on + * a NULL nxtptr but that currently is broken so a CPU-owned descriptor + * must terminate the list. + */ + intrmask = sc->sc_intrmask; + + if ( !(m->m_next)) /* single buffer packet */ + sc->txq_mbuf[index]= m; + else /* multiple mbufs in this packet */ + { + struct mbuf *mtp, *mdest; + volatile unsigned char *pt; + int len, y; + +#ifdef GT_DEBUG + printk("multi mbufs "); +#endif + MGETHDR(mdest, M_WAIT, MT_DATA); + MCLGET(mdest, M_WAIT); + pt = (volatile unsigned char *)mdest->m_data; + for (mtp=m,len=0;mtp;mtp=mtp->m_next) { + if ( (y=(len+mtp->m_len)) > sizeof(union mcluster)) { + /* GT64260 allows us to chain the remaining to the nex + * free descriptors. + */ + printk("packet size %x > mcluster %x\n", y,sizeof(union mcluster)); + rtems_panic("GT64260eth : packet too large "); + } + memcpy((void *)pt,(char *)mtp->m_data, mtp->m_len); + pt += mtp->m_len; +#if 0 + printk("%d ",mtp->m_len); +#endif + len += mtp->m_len; + } +#if 0 + printk("\n"); +#endif + mdest->m_len=len; + /* free old mbuf chain */ + m_freem(m); + sc->txq_mbuf[index] = m = mdest; + sc->stats.txMultiBuffPacket++; + } + if (m->m_len < ET_MINLEN) m->m_len = ET_MINLEN; + + txd->ed_bufptr = mtod(m, void*); + txd->ed_lencnt = m->m_len << 16; + txd->ed_cmdsts = TX_CMD_L|TX_CMD_GC|TX_CMD_P|TX_CMD_O|TX_CMD_F|TX_CMD_EI; + +#ifdef GT_DEBUG + printk("len = %d, cmdsts 0x%x ", m->m_len,txd->ed_cmdsts); +#endif + + /* + * Tell the SDMA engine to "Fetch!" + * Start Tx high and Tx low. + */ + outl(ETH_ESDCMR_TXDH,ETH0_ESDCMR); + sc->txq_nactive++; + if ( ++sc->txq_lo == TX_RING_SIZE) sc->txq_lo = 0; + sc->txq_free--; + + /* + * Since we have put an item into the packet queue, we now want + * an interrupt when the transmit queue finishes processing the + * list. But only update the mask if needs changing. + */ + intrmask |= sc->txq_intrbits & ( ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh); + if (sc->sc_intrmask != intrmask) { + sc->sc_intrmask = intrmask; + outl(sc->sc_intrmask, ETH0_EIMR); + } + +#if 0 + printk("EICR= %x, EIMR= %x ", inl(ETH0_EICR), inl(ETH0_EIMR)); + printk("%s:transmit frame #%d queued in slot %d.\n", + sc->arpcom.ac_if.if_name, sc->txq_lo, index); + printk("pcr %x, pcxr %x DMA dcr %x cmr %x\n", inl(ETH0_EPCR), inl(ETH0_EPCXR), inl(ETH0_ESDCR), inl(ETH0_ESDCMR)); +#endif + + if (GTeth_debug>0) printk(")"); + return 1; +} + +static unsigned GTeth_txq_done(struct GTeth_softc *sc, enum GTeth_txprio txprio) +{ + if (GTeth_debug>0) printk("Txdone(" ); + + while (sc->txq_nactive > 0) { + /* next to be returned to the CPU */ + volatile struct GTeth_desc *txd = &sc->txq_desc[sc->txq_fi]; + unsigned cmdsts; + + /* if GT64260 still owns it ....... */ + if ((cmdsts = txd->ed_cmdsts) & TX_CMD_O) { + int nextin; + + /* Someone quoted : + * "Sometimes the Discovery forgets to update the + * ownership bit in the descriptor." + * <skf> More correctly, the last descriptor of each + * transmitted frame is returned to CPU ownership and + * status is updated only after the actual transmission + * of the packet is completed. Also, if there is an error + * during transmission, we want to continue the + * transmission of the next descriptor, in additions to + * reporting the error. + */ + /* The last descriptor */ + if (sc->txq_nactive == 1) return(0); + + /* + * Sometimes the Discovery forgets to update the + * ownership bit in the descriptor. See if CPU owned + * the descriptor after it (since we know we've turned + * that to the Discovery and if CPU owned it now then the + * Discovery gave it back). If we do, we know the + * Discovery gave back this one but forgot to mark it + * back to CPU. + */ + nextin = (sc->txq_fi + 1) % TX_RING_SIZE; + + if (sc->txq_desc[nextin].ed_cmdsts & TX_CMD_O) return(0); + printk("Txq%d forgot\n",sc->txq_fi); + } /* end checking GT64260eth owner */ + GTeth_txq_free(sc, cmdsts); + } /* end while */ + if (GTeth_debug>0) printk(")\n"); + return(1); +} + +static void GTeth_tx_start(struct GTeth_softc *sc, enum GTeth_txprio txprio) +{ + int i; + volatile struct GTeth_desc *txd; + unsigned nxtaddr; + +#ifdef GT_DEBUG + printk("GTeth_tx_start("); +#endif + sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh| + ETH_IR_TxEndLow |ETH_IR_TxBufferLow); + + txd = &sc->txq_desc[0]; + sc->txq_desc_busaddr = &sc->txq_desc[0]; +#ifdef GT_DEBUG + printk("txq_desc_busaddr %x, &sc->txq_desc[0] %x \n", + sc->txq_desc_busaddr,&sc->txq_desc[0]); +#endif + + nxtaddr = sc->txq_desc_busaddr + sizeof(*txd); + + sc->txq_pendq.ifq_maxlen = 10; + sc->txq_pendq.ifq_head= NULL; + sc->txq_pendq.ifq_tail= NULL; + sc->txq_nactive = 0; + sc->txq_fi = 0; + sc->txq_lo = 0; + sc->txq_inptr = PKT_BUF_SZ; + sc->txq_outptr = 0; + sc->txq_free = TX_RING_SIZE; + + for (i = 0; i < TX_RING_SIZE; + i++, txd++, nxtaddr += sizeof(*txd)) { + sc->txq_mbuf[i]=0; + txd->ed_bufptr = 0; + + /* + * update the nxtptr to point to the next txd. + */ + txd->ed_cmdsts = 0; + if ( i== TX_RING_SIZE-1) nxtaddr = sc->txq_desc_busaddr; + txd->ed_nxtptr = nxtaddr; +#ifdef GT_DEBUG + printk("next desc. @ 0x%x\n",txd->ed_nxtptr); +#endif + } + + switch (txprio) { + case GE_TXPRIO_HI: + sc->txq_intrbits = ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh; + sc->txq_esdcmrbits = ETH_ESDCMR_TXDH; /* Start Tx high */ + sc->txq_epsrbits = ETH_EPSR_TxHigh; + /* offset to current tx desc ptr reg */ + sc->txq_ectdp = ETH0_ECTDP1; + /* Current Tx Desc Pointer 1 */ + outl(sc->txq_desc_busaddr,ETH0_ECTDP1); +#ifdef GT_DEBUG + printk("ETH0_ECTDP1 %x",inl(ETH0_ECTDP1)); +#endif + break; + + case GE_TXPRIO_LO: + sc->txq_intrbits = ETH_IR_TxEndLow|ETH_IR_TxBufferLow; + sc->txq_esdcmrbits = ETH_ESDCMR_TXDL; /* Start TX low */ + sc->txq_epsrbits = ETH_EPSR_TxLow; + sc->txq_ectdp = ETH0_ECTDP0; + /* Current Tx Desc Pointer 0 */ + outl(sc->txq_desc_busaddr,ETH0_ECTDP0); +#ifdef GT_DEBUG + printk("ETH0_ECTDP1 %x",inl(ETH0_ECTDP0)); +#endif + break; + + default: + printk("Invalid Txq prio\n"); + break; + } + +#ifdef GT_DEBUG + printk(")\n"); +#endif +} + +static void GTeth_tx_cleanup(struct GTeth_softc *sc,enum GTeth_txprio txprio,int flush) +{ + int i; + + if (GTeth_debug>0) printk( "GTeth_tx_cleanup("); + + if (!flush) { + if (GTeth_debug>0) printk("--"); + return; + } + for (i=0; i< TX_RING_SIZE; i++) { + if (sc->txq_mbuf[i]) { + m_freem(sc->txq_mbuf[i]); + sc->txq_mbuf[i]=0; + } + } + if (GTeth_debug>0) printk(")"); +} + +static void GTeth_tx_stop(struct GTeth_softc *sc, enum GTeth_whack_op op) +{ + if (GTeth_debug>0) printk("GTeth_tx_stop( "); + + /* SDMA command register : stop Tx high and low */ + outl(ETH_ESDCMR_STDH|ETH_ESDCMR_STDL, ETH0_ESDCMR); + + GTeth_txq_done(sc, GE_TXPRIO_HI); + sc->sc_intrmask &= ~(ETH_IR_TxEndHigh|ETH_IR_TxBufferHigh| + ETH_IR_TxEndLow |ETH_IR_TxBufferLow); + GTeth_tx_cleanup(sc, GE_TXPRIO_HI, op == GE_WHACK_STOP); + + sc->arpcom.ac_if.if_timer = 0; + if (GTeth_debug>0) printk(")"); +} + + +/* TOCHECK : Should it be about rx or tx ? */ +static void GTeth_ifchange(struct GTeth_softc *sc) +{ + if (GTeth_debug>0) printk("GTeth_ifchange("); + if (GTeth_debug>5) printk("(pcr=%#x,imr=%#x)",inl(ETH0_EPCR),inl(ETH0_EIMR)); + printk("SIOCADDMULTI (SIOCDELMULTI): is it about rx or tx ?\n"); + outl(sc->sc_pcr | ETH_EPCR_EN, ETH0_EPCR); + outl(sc->sc_intrmask, ETH0_EIMR); + GTeth_ifstart(&sc->arpcom.ac_if); + /* Current Tx Desc Pointer 0 and 1 */ + if (GTeth_debug>5) printk("(ectdp0=%#x, ectdp1=%#x)", + inl(ETH0_ECTDP0), inl(ETH0_ECTDP1)); + if (GTeth_debug>0) printk(")"); +} + +static int GTeth_hash_compute(struct GTeth_softc *sc,unsigned char eaddr[ETHER_ADDR_LEN]) +{ + unsigned w0, add0, add1; + unsigned result; + + if (GTeth_debug>0) printk("GTeth_hash_compute("); + add0 = ((unsigned) eaddr[5] << 0) | + ((unsigned) eaddr[4] << 8) | + ((unsigned) eaddr[3] << 16); + + add0 = ((add0 & 0x00f0f0f0) >> 4) | ((add0 & 0x000f0f0f) << 4); + add0 = ((add0 & 0x00cccccc) >> 2) | ((add0 & 0x00333333) << 2); + add0 = ((add0 & 0x00aaaaaa) >> 1) | ((add0 & 0x00555555) << 1); + + add1 = ((unsigned) eaddr[2] << 0) | + ((unsigned) eaddr[1] << 8) | + ((unsigned) eaddr[0] << 16); + + add1 = ((add1 & 0x00f0f0f0) >> 4) | ((add1 & 0x000f0f0f) << 4); + add1 = ((add1 & 0x00cccccc) >> 2) | ((add1 & 0x00333333) << 2); + add1 = ((add1 & 0x00aaaaaa) >> 1) | ((add1 & 0x00555555) << 1); + + if (GTeth_debug>0) printk("eaddr= %s add1:%x add0:%x\n", ether_sprintf(eaddr), add1, add0); + + /* + * hashResult is the 15 bits Hash entry address. + * ethernetADD is a 48 bit number, which is derived from the Ethernet + * MAC address, by nibble swapping in every byte (i.e MAC address + * of 0x123456789abc translates to ethernetADD of 0x21436587a9cb). + */ + if ((sc->sc_pcr & ETH_EPCR_HM) == 0) { + /* + * hashResult[14:0] = hashFunc0(ethernetADD[47:0]) + * + * hashFunc0 calculates the hashResult in the following manner: + * hashResult[ 8:0] = ethernetADD[14:8,1,0] + * XOR ethernetADD[23:15] XOR ethernetADD[32:24] + */ + result = (add0 & 3) | ((add0 >> 6) & ~3); + result ^= (add0 >> 15) ^ (add1 >> 0); + result &= 0x1ff; + /* + * hashResult[14:9] = ethernetADD[7:2] + */ + result |= (add0 & ~3) << 7; /* excess bits will be masked */ + if (GTeth_debug>0) printk("hash result %x ", result & 0x7fff); + } else { +#define TRIBITFLIP 073516240 /* yes its in octal */ + /* + * hashResult[14:0] = hashFunc1(ethernetADD[47:0]) + * + * hashFunc1 calculates the hashResult in the following manner: + * hashResult[08:00] = ethernetADD[06:14] + * XOR ethernetADD[15:23] XOR ethernetADD[24:32] + */ + w0 = ((add0 >> 6) ^ (add0 >> 15) ^ (add1)) & 0x1ff; + /* + * Now bitswap those 9 bits + */ + result = 0; + result |= ((TRIBITFLIP >> (((w0 >> 0) & 7) * 3)) & 7) << 6; + result |= ((TRIBITFLIP >> (((w0 >> 3) & 7) * 3)) & 7) << 3; + result |= ((TRIBITFLIP >> (((w0 >> 6) & 7) * 3)) & 7) << 0; + + /* + * hashResult[14:09] = ethernetADD[00:05] + */ + result |= ((TRIBITFLIP >> (((add0 >> 0) & 7) * 3)) & 7) << 12; + result |= ((TRIBITFLIP >> (((add0 >> 3) & 7) * 3)) & 7) << 9; + if (GTeth_debug>5) printk("1(%#x)", result); + } + if (GTeth_debug>0) printk(")"); + /* 1/2K address filtering (MOTLoad default )? ->16KB memory required + * or 8k address filtering ? -> 256KB memory required + */ + return result & ((sc->sc_pcr & ETH_EPCR_HS_512) ? 0x7ff : 0x7fff); +} + +static int GTeth_hash_entry_op(struct GTeth_softc *sc, enum GTeth_hash_op op, + enum GTeth_rxprio prio,unsigned char eaddr[ETHER_ADDR_LEN]) +{ + unsigned long long he; + unsigned long long *maybe_he_p = NULL; + int limit; + int hash; + int maybe_hash = 0; + + if (GTeth_debug>0) printk("GTeth_hash_entry_op(prio %d ", prio); + + hash = GTeth_hash_compute(sc, eaddr); + + if (sc->sc_hashtable == NULL) { + rtems_panic("hashtable == NULL!"); + } + if (GTeth_debug>0) printk("Hash computed %x eaddr %s\n", hash,ether_sprintf(eaddr)); + + + /* + * Assume we are going to insert so create the hash entry we + * are going to insert. We also use it to match entries we + * will be removing. The datasheet is wrong for this. + */ + he = (((unsigned long long) eaddr[5]) << 43) | + (((unsigned long long) eaddr[4]) << 35) | + (((unsigned long long) eaddr[3]) << 27) | + (((unsigned long long) eaddr[2]) << 19) | + (((unsigned long long) eaddr[1]) << 11) | + (((unsigned long long) eaddr[0]) << 3) | + ((unsigned long long) HSH_PRIO_INS(prio) | HSH_V | HSH_R); + /* he = 0x1b1acd87d08005;*/ + /* + * The GT will search upto 12 entries for a hit, so we must mimic that. + */ + hash &= (sc->sc_hashmask / sizeof(he)); + + if (GTeth_debug>0) { + unsigned val1, val2; + + val1= he & 0xffffffff; + val2= (he >>32) & 0xffffffff; + printk("Hash addr value %x%x, entry %x\n",val2,val1, hash); + } + + for (limit = HSH_LIMIT; limit > 0 ; --limit) { + /* + * Does the GT wrap at the end, stop at the, or overrun the + * end? Assume it wraps for now. Stash a copy of the + * current hash entry. + */ + unsigned long long *he_p = &sc->sc_hashtable[hash]; + unsigned long long thishe = *he_p; + + /* + * If the hash entry isn't valid, that break the chain. And + * this entry a good candidate for reuse. + */ + if ((thishe & HSH_V) == 0) { + maybe_he_p = he_p; + break; + } + + /* + * If the hash entry has the same address we are looking for + * then ... if we are removing and the skip bit is set, its + * already been removed. if are adding and the skip bit is + * clear, then its already added. In either return EBUSY + * indicating the op has already been done. Otherwise flip + * the skip bit and return 0. + */ + if (((he ^ thishe) & HSH_ADDR_MASK) == 0) { + if (((op == GE_HASH_REMOVE) && (thishe & HSH_S)) || + ((op == GE_HASH_ADD) && (thishe & HSH_S) == 0)) + return EBUSY; + *he_p = thishe ^ HSH_S; + + if (GTeth_debug>0) { + unsigned val1, val2; + + val1= *he_p & 0xffffffff; + val2= (*he_p >>32) & 0xffffffff; + printk("flip skip bit result %x%x entry %x ",val2,val1, hash); + } + return 0; + } + + /* + * If we haven't found a slot for the entry and this entry + * is currently being skipped, return this entry. + */ + if (maybe_he_p == NULL && (thishe & HSH_S)) { + maybe_he_p = he_p; + maybe_hash = hash; + } + hash = (hash + 1) & (sc->sc_hashmask / sizeof(he)); + } + + /* + * If we got here, then there was no entry to remove. + */ + if (op == GE_HASH_REMOVE) { + printk("GT64260eth : No entry to remove\n"); + return ENOENT; + } + + /* + * If we couldn't find a slot, return an error. + */ + if (maybe_he_p == NULL) { + rtems_panic("GT64260eth : No slot found"); + return ENOSPC; + } + + /* Update the entry.*/ + *maybe_he_p = he; + if (GTeth_debug>0) { + unsigned val1, val2; +#if 0 + unsigned long *pt= sc->sc_hashtable; + int i, loop; + + for (loop= 0; loop< 256; loop++) { + printk("%d)", loop); + for (i=0; i< 16; i++, pt++) printk("%x ",*pt); + printk("\n"); + } +#endif + val1= he & 0xffffffff; + val2= (he >>32) & 0xffffffff; + printk("Update Hash result %x%x, table addr %x entry %x )\n",val2, val1, maybe_he_p, hash); + } + return 0; +} + +static int GTeth_hash_fill(struct GTeth_softc *sc) +{ + struct ether_multistep step; + struct ether_multi *enm; + int error; + + if (GTeth_debug>0) printk( "GTeth_hash_fill("); + error = GTeth_hash_entry_op(sc,GE_HASH_ADD,GE_RXPRIO_HI,sc->arpcom.ac_enaddr); + + if (error) { + if (GTeth_debug>0) printk("!"); + return error; + } + + sc->sc_flags &= ~GE_ALLMULTI; + if ((sc->arpcom.ac_if.if_flags & IFF_PROMISC) == 0) + sc->sc_pcr &= ~ETH_EPCR_PM; + /* see lib/include/netinet/if_ether.h */ + ETHER_FIRST_MULTI(step, &sc->arpcom, enm); + while (enm != NULL) { + if (memcmp(enm->enm_addrlo, enm->enm_addrhi, ETHER_ADDR_LEN)) { + /* Frames are received regardless of their destinatin address */ + sc->sc_flags |= GE_ALLMULTI; + sc->sc_pcr |= ETH_EPCR_PM; + } else { + /* Frames are only received if the destinatin address is found + * in the hash table + */ + error = GTeth_hash_entry_op(sc, GE_HASH_ADD, + GE_RXPRIO_MEDLO, enm->enm_addrlo); + if (error == ENOSPC) break; + } + ETHER_NEXT_MULTI(step, enm); + } + if (GTeth_debug>0) printk(")\n"); + return error; +} + +static void GTeth_hash_init(struct GTeth_softc *sc) +{ + void *hash_mem; + + if (GTeth_debug>0) printk("GTeth_hash_init("); + /* MOTLoad defualt : 512 bytes of address filtering, which + * requires 16KB of memory + */ +#if 1 + hash_mem = rtems_bsdnet_malloc(HASH_DRAM_SIZE + HASH_ALIGN, M_FREE, M_NOWAIT); + sc->sc_hashtable =(void *)(((long)hash_mem+ HASH_ALIGN) & ~HASH_ALIGN); +#else + /* only for test */ + hash_mem = 0x68F000; + sc->sc_hashtable =(unsigned long long *)hash_mem; +#endif + sc->sc_hashmask = HASH_DRAM_SIZE - 1; + + memset((void *)sc->sc_hashtable, 0,HASH_DRAM_SIZE); + if (GTeth_debug>0) + printk("hashtable addr:%x, mask %x)\n", sc->sc_hashtable,sc->sc_hashmask); +} + +static void GT64260eth_error(struct GTeth_softc *sc) +{ + struct ifnet *ifp = &sc->arpcom.ac_if; + unsigned int intr_status= sc->intr_errsts[sc->intr_err_ptr1]; + + /* read and reset the status; because this is written + * by the ISR, we must disable interrupts here + */ + if (intr_status) { + printk("%s%d: ICR = 0x%x ", + ifp->if_name, ifp->if_unit, intr_status); +#if 1 + if (intr_status & INTR_RX_ERROR) { + printk("Rxq error, if_ierrors %d\n", + ifp->if_ierrors); + } +#endif + /* Rx error is handled in GT64260eth_rx() */ + if (intr_status & INTR_TX_ERROR) { + ifp->if_oerrors++; + printk("Txq error, if_oerrors %d\n",ifp->if_oerrors); + } + } + else + printk("%s%d: Ghost interrupt ?\n",ifp->if_name, + ifp->if_unit); + sc->intr_errsts[sc->intr_err_ptr1++]=0; + sc->intr_err_ptr1 %= INTR_ERR_SIZE; /* Till Straumann */ +} + + +/* The daemon does all of the work; RX, TX and cleaning up buffers/descriptors */ +static void GT64260eth_daemon(void *arg) +{ + struct GTeth_softc *sc = (struct GTeth_softc*)arg; + rtems_event_set events; + struct mbuf *m=0; + struct ifnet *ifp=&sc->arpcom.ac_if; + +#if 0 + /* see comments in GT64260eth_init(); in newer versions of + * rtems, we hold the network semaphore at this point + */ + rtems_semaphore_release(sc->daemonSync); +#endif + + /* NOTE: our creator possibly holds the bsdnet_semaphore. + * since that has PRIORITY_INVERSION enabled, our + * subsequent call to bsdnet_event_receive() will + * _not_ release it. It's still in posession of our + * owner. + * This is different from how killing this task + * is handled. + */ + + for (;;) { + /* sleep until there's work to be done */ + /* Note: bsdnet_event_receive() acquires + * the global bsdnet semaphore for + * mutual exclusion. + */ + rtems_bsdnet_event_receive(ALL_EVENTS, + RTEMS_WAIT | RTEMS_EVENT_ANY, + RTEMS_NO_TIMEOUT, + &events); + + if (KILL_EVENT & events) break; + +#ifndef GE_NORX + if (events & RX_EVENT) GT64260eth_rx(sc,GE_RXPRIO_HI); +#endif + + /* clean up and try sending packets */ + do { +#if 1 + if (gpp_int_error!=0) { + printk("GPP interrupt error %d\n", gpp_int_error); + gpp_int_error=0; + } +#endif + if (sc->txq_nactive) GTeth_txq_done(sc, GE_TXPRIO_HI); + + while (sc->txq_free>0) { + if (sc->txq_free>TXQ_HiLmt_OFF) { + m=0; + IF_DEQUEUE(&ifp->if_snd,m); + if (m==0) break; + GT64260eth_sendpacket(sc, m, GE_TXPRIO_HI); + } + else { + if (txq_high_limit(sc)) + break; + } + } + /* we leave this loop + * - either because there's no free buffer + * (m=0 initializer && !sc->txq_free) + * - or there's nothing to send (IF_DEQUEUE + * returned 0 + */ + } while (m); + + ifp->if_flags &= ~IFF_OACTIVE; + + /* Log errors and other uncommon events. */ + if (events & ERR_EVENT) GT64260eth_error(sc); + } /* end for(;;) { rtems_bsdnet_event_receive() .....*/ + + ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); + + /* shut down the hardware */ + GT64260eth_stop_hw(sc); + /* flush the output queue */ + for (;;) { + IF_DEQUEUE(&ifp->if_snd,m); + if (!m) break; + m_freem(m); + } + /* as of 'rtems_bsdnet_event_receive()' we own the + * networking semaphore + */ + rtems_bsdnet_semaphore_release(); + rtems_semaphore_release(sc->daemonSync); + + /* Note that I dont use sc->daemonTid here - + * theoretically, that variable could already + * hold a newly created TID + */ + rtems_task_delete(RTEMS_SELF); +} + diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.h b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.h new file mode 100644 index 0000000000..926e436884 --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260eth.h @@ -0,0 +1,135 @@ +/* GT64260eth.h + * + * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc. + * All rights reserved. + * + * RTEMS/Mvme5500 port 2004 by S. Kate Feng, <feng1@bnl.gov>, + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Allegro Networks, Inc., and Wasabi Systems, Inc. + * 4. The name of Allegro Networks, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * 5. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND + * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC. + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* Keep the ring sizes a power of two for efficiency. + Making the Tx ring too long decreases the effectiveness of channel + bonding and packet priority. + There are no ill effects from too-large receive rings. */ +#define TX_RING_SIZE 32 +#define GT_NEXTTX(x) ((x + 1) % TX_RING_SIZE ) +#define TX_QUARTER_FULL TX_RING_SIZE/2 +#define TX_HALF_FULL TX_RING_SIZE/2 +#define RX_RING_SIZE 16 +#define HASH_TABLE_SIZE 16 +#define HASH_DRAM_SIZE HASH_TABLE_SIZE*1024 /* size of DRAM for hash table */ +#define INTR_ERR_SIZE 16 + +enum GTeth_txprio { + GE_TXPRIO_HI=1, + GE_TXPRIO_LO=0, + GE_TXPRIO_NONE=2 +}; +enum GTeth_rxprio { + GE_RXPRIO_HI=3, + GE_RXPRIO_MEDHI=2, + GE_RXPRIO_MEDLO=1, + GE_RXPRIO_LO=0 +}; + +struct GTeth_softc { + struct GTeth_desc txq_desc[TX_RING_SIZE]; /* transmit descriptor memory */ + struct GTeth_desc rxq_desc[RX_RING_SIZE]; /* receive descriptor memory */ + struct mbuf* txq_mbuf[TX_RING_SIZE]; /* transmit buffer memory */ + struct mbuf* rxq_mbuf[RX_RING_SIZE]; /* receive buffer memory */ + struct GTeth_softc *next_module; + volatile unsigned int intr_errsts[INTR_ERR_SIZE]; /* capture the right intr_status */ + unsigned int intr_err_ptr1; /* ptr used in GTeth_error() */ + unsigned int intr_err_ptr2; /* ptr used in ISR */ + struct ifqueue txq_pendq; /* these are ready to go to the GT */ + unsigned int txq_pending; + unsigned int txq_lo; /* next to be given to GT */ + unsigned int txq_fi; /* next to be returned to CPU */ + unsigned int txq_ei_gapcount; /* counter until next EI */ + unsigned int txq_nactive; /* number of active descriptors */ + unsigned int txq_nintr; /* number of txq desc. send TX_EVENT */ + unsigned int txq_outptr; /* where to put next transmit packet */ + unsigned int txq_inptr; /* start of 1st queued tx packet */ + unsigned int txq_free; /* free Tx queue slots. */ + unsigned txq_intrbits; /* bits to write to EIMR */ + unsigned txq_esdcmrbits; /* bits to write to ESDCMR */ + unsigned txq_epsrbits; /* bits to test with EPSR */ + + caddr_t txq_ectdp; /* offset to cur. tx desc ptr reg */ + unsigned long txq_desc_busaddr; /* bus addr of tx descriptors */ + caddr_t txq_buf_busaddr; /* bus addr of tx buffers */ + + struct mbuf *rxq_curpkt; /* mbuf for current packet */ + struct GTeth_desc *rxq_head_desc; /* rxq head descriptor */ + unsigned int rxq_fi; /* next to be returned to CPU */ + unsigned int rxq_active; /* # of descriptors given to GT */ + unsigned rxq_intrbits; /* bits to write to EIMR */ + unsigned long rxq_desc_busaddr; /* bus addr of rx descriptors */ + + struct arpcom arpcom; /* rtems if structure, contains ifnet */ + int sc_macno; /* which mac? 0, 1, or 2 */ + + unsigned int sc_tickflags; + #define GE_TICK_TX_IFSTART 0x0001 + #define GE_TICK_RX_RESTART 0x0002 + unsigned int sc_flags; + #define GE_ALLMULTI 0x0001 + #define GE_PHYSTSCHG 0x0002 + #define GE_RXACTIVE 0x0004 + unsigned sc_pcr; /* current EPCR value */ + unsigned sc_pcxr; /* current EPCXR value */ + unsigned sc_intrmask; /* current EIMR value */ + unsigned sc_idlemask; /* suspended EIMR bits */ + unsigned sc_max_frame_length; /* maximum frame length */ + unsigned rx_buf_sz; + + /* Hash table related members */ + unsigned long long *sc_hashtable; + unsigned int sc_hashmask; /* 0x1ff or 0x1fff */ + + rtems_id daemonTid; + rtems_id daemonSync; /* synchronization with the daemon */ + /* statistics */ + struct { + volatile unsigned long rxInterrupts; + + volatile unsigned long txInterrupts; + unsigned long txMultiBuffPacket; + unsigned long length_errors; + unsigned long frame_errors; + unsigned long crc_errors; + unsigned long or_errors; /* overrun error */ + } stats; +}; diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260ethreg.h b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260ethreg.h new file mode 100644 index 0000000000..0b8133e99c --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/GT64260ethreg.h @@ -0,0 +1,879 @@ +/* $NetBSD: GT64260ethreg.h,v 1.2 2003/03/17 16:41:16 matt Exp $ */ + +/* + * Copyright (c) 2002 Allegro Networks, Inc., Wasabi Systems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Allegro Networks, Inc., and Wasabi Systems, Inc. + * 4. The name of Allegro Networks, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * 5. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY ALLEGRO NETWORKS, INC. AND + * WASABI SYSTEMS, INC. ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL EITHER ALLEGRO NETWORKS, INC. OR WASABI SYSTEMS, INC. + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DEV_GTETHREG_H_ +#define _DEV_GTETHREG_H_ + +#define ETH__BIT(bit) (1U << (bit)) +#define ETH__LLBIT(bit) (1ULL << (bit)) +#define ETH__MASK(bit) (ETH__BIT(bit) - 1) +#define ETH__LLMASK(bit) (ETH__LLBIT(bit) - 1) +#define ETH__GEN(n, off) (0x2400+((n) << 10)+(ETH__ ## off)) +#define ETH__EXT(data, bit, len) (((data) >> (bit)) & ETH__MASK(len)) +#define ETH__LLEXT(data, bit, len) (((data) >> (bit)) & ETH__LLMASK(len)) +#define ETH__CLR(data, bit, len) ((data) &= ~(ETH__MASK(len) << (bit))) +#define ETH__INS(new, bit) ((new) << (bit)) +#define ETH__LLINS(new, bit) ((unsigned long long)(new) << (bit)) + +/* + * Descriptors used for both receive & transmit data. Note that the descriptor + * must start on a 4LW boundary. Since the GT accesses the descriptor as + * two 64-bit quantities, we must present them 32bit quantities in the right + * order based on endianess. + */ + +struct GTeth_desc { +#if defined(BYTE_ORDER) && BYTE_ORDER == BIG_ENDIAN /* for mvme5500 */ + unsigned ed_lencnt; /* Buffer size is hi 16 bits; Byte count (rx) is lo 16 */ + unsigned ed_cmdsts; /* command (hi16)/status (lo16) bits */ + unsigned ed_nxtptr; /* next descriptor (must be 4LW aligned) */ + unsigned ed_bufptr; /* pointer to packet buffer */ +#endif +#if defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN + unsigned ed_cmdsts; /* command (hi16)/status (lo16) bits */ + unsigned ed_lencnt; /* length is hi 16 bits; count (rx) is lo 16 */ + unsigned ed_bufptr; /* pointer to packet buffer */ + unsigned ed_nxtptr; /* next descriptor (must be 4LW aligned) */ +#endif +}; + +/* Ethernet 0 address control (Low), Offset: 0xf200 */ +#define RxBSnoopEn ETH__BIT(6) /* Rx buffer snoop enable,1=enable*/ +#define TxBSnoopEn ETH__BIT(14) /* Tx buffer snoop enable */ +#define RxDSnoopEn ETH__BIT(22) /* Rx descriptor snoop enable */ +#define TxDSnoopEn ETH__BIT(30) /* Tx descriptor snoop enable */ + +/* Ethernet 0 address control (High), Offset: 0xf204 */ +#define HashSnoopEn ETH__BIT(6) /* Hash Table snoop enable */ + +/* <skf> */ +#define GT_CUU_Eth0_AddrCtrlLow 0xf200 +#define GT_CUU_Eth0_AddrCtrlHigh 0xf204 + +/* Table 578: Ethernet TX Descriptor - Command/Status word + * All bits except F, EI, AM, O are only valid if TX_CMD_L is also set, + * otherwise should be 0 (tx). + */ + +#define TX_STS_LC ETH__BIT(5) /* Late Collision */ +#define TX_STS_UR ETH__BIT(6) /* Underrun error */ +#define TX_STS_RL ETH__BIT(8) /* Retransmit Limit (excession coll) */ +#define TX_STS_COL ETH__BIT(9) /* Collision Occurred */ +#define TX_STS_RC(v) ETH__GETBITS(v, 10, 4) /* Retransmit Count */ +#define TX_STS_ES ETH__BIT(15) /* Error Summary (LC|UR|RL) */ +#define TX_CMD_L ETH__BIT(16) /* Last - End Of Packet */ +#define TX_CMD_F ETH__BIT(17) /* First - Start Of Packet */ +#define TX_CMD_P ETH__BIT(18) /* Pad Packet */ +#define TX_CMD_GC ETH__BIT(22) /* Generate CRC */ +#define TX_CMD_EI ETH__BIT(23) /* Enable Interrupt */ +#define TX_CMD_AM ETH__BIT(30) /* Auto Mode */ +#define TX_CMD_O ETH__BIT(31) /* Ownership (1=GT 0=CPU) */ + +#define TX_CMD_FIRST (TX_CMD_F|TX_CMD_O) +#define TX_CMD_LAST (TX_CMD_L|TX_CMD_GC|TX_CMD_P|TX_CMD_O) + +/* Table 608: Ethernet RX Descriptor - Command/Status Word + * All bits except F, EI, AM, O are only valid if RX_CMD_L is also set, + * otherwise should be ignored (rx). + */ +#define RX_STS_CE ETH__BIT(0) /* CRC Error */ +#define RX_STS_COL ETH__BIT(1) /* Collision sensed during reception */ +#define RX_STS_LC ETH__BIT(5) /* Late Collision (Reserved) */ +#define RX_STS_OR ETH__BIT(6) /* Overrun Error */ +#define RX_STS_MFL ETH__BIT(7) /* Max Frame Len Error */ +#define RX_STS_SF ETH__BIT(8) /* Short Frame Error (< 64 bytes) */ +#define RX_STS_FT ETH__BIT(11) /* Frame Type (1 = 802.3) */ +#define RX_STS_M ETH__BIT(12) /* Missed Frame */ +#define RX_STS_HE ETH__BIT(13) /* Hash Expired (manual match) */ +#define RX_STS_IGMP ETH__BIT(14) /* IGMP Packet */ +#define RX_STS_ES ETH__BIT(15) /* Error Summary (CE|COL|LC|OR|MFL|SF) */ +#define RX_CMD_L ETH__BIT(16) /* Last - End Of Packet */ +#define RX_CMD_F ETH__BIT(17) /* First - Start Of Packet */ +#define RX_CMD_EI ETH__BIT(23) /* Enable Interrupt */ +#define RX_CMD_AM ETH__BIT(30) /* Auto Mode */ +#define RX_CMD_O ETH__BIT(31) /* Ownership (1=GT 0=CPU) */ + +/* Table 586: Hash Table Entry Fields + */ +#define HSH_V ETH__LLBIT(0) /* Entry is valid */ +#define HSH_S ETH__LLBIT(1) /* Skip this entry */ +#define HSH_RD ETH__LLBIT(2) /* Receive(1) / Discard (0) */ +#define HSH_R ETH__LLBIT(2) /* Receive(1) */ +#define HSH_PRIO_GET(v) ETH__LLEXT(v, 51, 2) +#define HSH_PRIO_INS(v) ETH__LLINS(v, 51) +#define HSH_ADDR_MASK 0x7fffff8LLU +#define HSH_LIMIT 12 + + +#define ETH_EPAR 0x2000 /* PHY Address Register */ +#define ETH_ESMIR 0x2010 /* SMI Register */ + +#define ETH_BASE_ETH0 0x2400 /* Ethernet0 Register Base */ +#define ETH_BASE_ETH1 0x2800 /* Ethernet1 Register Base */ +#define ETH_BASE_ETH2 0x2c00 /* Ethernet2 Register Base */ +#define ETH_SIZE 0x0400 /* Register Space */ + +#define ETH__EBASE 0x0000 /* Base of Registers */ +#define ETH__EPCR 0x0000 /* Port Config. Register */ +#define ETH__EPCXR 0x0008 /* Port Config. Extend Reg */ +#define ETH__EPCMR 0x0010 /* Port Command Register */ +#define ETH__EPSR 0x0018 /* Port Status Register */ +#define ETH__ESPR 0x0020 /* Port Serial Parameters Reg */ +#define ETH__EHTPR 0x0028 /* Port Hash Table Pointer Reg*/ +#define ETH__EFCSAL 0x0030 /* Flow Control Src Addr Low */ +#define ETH__EFCSAH 0x0038 /* Flow Control Src Addr High */ +#define ETH__ESDCR 0x0040 /* SDMA Configuration Reg */ +#define ETH__ESDCMR 0x0048 /* SDMA Command Register */ +#define ETH__EICR 0x0050 /* Interrupt Cause Register */ +#define ETH__EIMR 0x0058 /* Interrupt Mask Register */ +#define ETH__EFRDP0 0x0080 /* First Rx Desc Pointer 0 */ +#define ETH__EFRDP1 0x0084 /* First Rx Desc Pointer 1 */ +#define ETH__EFRDP2 0x0088 /* First Rx Desc Pointer 2 */ +#define ETH__EFRDP3 0x008c /* First Rx Desc Pointer 3 */ +#define ETH__ECRDP0 0x00a0 /* Current Rx Desc Pointer 0 */ +#define ETH__ECRDP1 0x00a4 /* Current Rx Desc Pointer 1 */ +#define ETH__ECRDP2 0x00a8 /* Current Rx Desc Pointer 2 */ +#define ETH__ECRDP3 0x00ac /* Current Rx Desc Pointer 3 */ +#define ETH__ECTDP0 0x00e0 /* Current Tx Desc Pointer 0 */ +#define ETH__ECTDP1 0x00e4 /* Current Tx Desc Pointer 1 */ +#define ETH__EDSCP2P0L 0x0060 /* IP Differentiated Services + CodePoint to Priority0 low */ +#define ETH__EDSCP2P0H 0x0064 /* IP Differentiated Services + CodePoint to Priority0 high*/ +#define ETH__EDSCP2P1L 0x0068 /* IP Differentiated Services + CodePoint to Priority1 low */ +#define ETH__EDSCP2P1H 0x006c /* IP Differentiated Services + CodePoint to Priority1 high*/ +#define ETH__EVPT2P 0x0068 /* VLAN Prio. Tag to Priority */ +#define ETH__EMIBCTRS 0x0100 /* MIB Counters */ + +/* SKF : we are only concerned with the Ethernet0 for the mvme5500 board */ +#define ETH0_EBASE 0x2400 /* Base of Registers */ +#define ETH0_EPCR 0x2400 /* Port Config. Register */ +#define ETH0_EPCXR 0x2408 /* Port Config. Extend Reg */ +#define ETH0_EPCMR 0x2410 /* Port Command Register */ +#define ETH0_EPSR 0x2418 /* Port Status Register */ +#define ETH0_ESPR 0x2420 /* Port Serial Parameters Reg */ +#define ETH0_EHTPR 0x2428 /* Port Hash Table Pointer Reg*/ +#define ETH0_EFCSAL 0x2430 /* Flow Control Src Addr Low */ +#define ETH0_EFCSAH 0x2438 /* Flow Control Src Addr High */ +#define ETH0_ESDCR 0x2440 /* SDMA Configuration Reg */ +#define ETH0_ESDCMR 0x2448 /* SDMA Command Register */ +#define ETH0_EICR 0x2450 /* Interrupt Cause Register */ +#define ETH0_EIMR 0x2458 /* Interrupt Mask Register */ +#define ETH0_EFRDP0 0x2480 /* First Rx Desc Pointer 0 */ +#define ETH0_EFRDP1 0x2484 /* First Rx Desc Pointer 1 */ +#define ETH0_EFRDP2 0x2488 /* First Rx Desc Pointer 2 */ +#define ETH0_EFRDP3 0x248c /* First Rx Desc Pointer 3 */ +#define ETH0_ECRDP0 0x24a0 /* Current Rx Desc Pointer 0 */ +#define ETH0_ECRDP1 0x24a4 /* Current Rx Desc Pointer 1 */ +#define ETH0_ECRDP2 0x24a8 /* Current Rx Desc Pointer 2 */ +#define ETH0_ECRDP3 0x24ac /* Current Rx Desc Pointer 3 */ +#define ETH0_ECTDP0 0x24e0 /* Current Tx Desc Pointer 0 */ +#define ETH0_ECTDP1 0x24e4 /* Current Tx Desc Pointer 1 */ +#define ETH0_EDSCP2P0L 0x2460 /* IP Differentiated Services + CodePoint to Priority0 low */ +#define ETH0_EDSCP2P0H 0x2464 /* IP Differentiated Services + CodePoint to Priority0 high*/ +#define ETH0_EDSCP2P1L 0x2468 /* IP Differentiated Services + CodePoint to Priority1 low */ +#define ETH0_EDSCP2P1H 0x246c /* IP Differentiated Services + CodePoint to Priority1 high*/ +#define ETH0_EVPT2P 0x2468 /* VLAN Prio. Tag to Priority */ +#define ETH0_EMIBCTRS 0x2500 /* MIB Counters */ + +#define ETH_BASE(n) ETH__GEN(n, EBASE) +#define ETH_EPCR(n) ETH__GEN(n, EPCR) /* Port Config. Register */ +#define ETH_EPCXR(n) ETH__GEN(n, EPCXR) /* Port Config. Extend Reg */ +#define ETH_EPCMR(n) ETH__GEN(n, EPCMR) /* Port Command Register */ +#define ETH_EPSR(n) ETH__GEN(n, EPSR) /* Port Status Register */ +#define ETH_ESPR(n) ETH__GEN(n, ESPR) /* Port Serial Parameters Reg */ +#define ETH_EHTPR(n) ETH__GEN(n, EHPTR) /* Port Hash Table Pointer Reg*/ +#define ETH_EFCSAL(n) ETH__GEN(n, EFCSAL) /* Flow Control Src Addr Low */ +#define ETH_EFCSAH(n) ETH__GEN(n, EFCSAH) /* Flow Control Src Addr High */ +#define ETH_ESDCR(n) ETH__GEN(n, ESDCR) /* SDMA Configuration Reg */ +#define ETH_ESDCMR(n) ETH__GEN(n, ESDCMR) /* SDMA Command Register */ +#define ETH_EICR(n) ETH__GEN(n, EICR) /* Interrupt Cause Register */ +#define ETH_EIMR(n) ETH__GEN(n, EIMR) /* Interrupt Mask Register */ +#define ETH_EFRDP0(n) ETH__GEN(n, EFRDP0) /* First Rx Desc Pointer 0 */ +#define ETH_EFRDP1(n) ETH__GEN(n, EFRDP1) /* First Rx Desc Pointer 1 */ +#define ETH_EFRDP2(n) ETH__GEN(n, EFRDP2) /* First Rx Desc Pointer 2 */ +#define ETH_EFRDP3(n) ETH__GEN(n, EFRDP3) /* First Rx Desc Pointer 3 */ +#define ETH_ECRDP0(n) ETH__GEN(n, ECRDP0) /* Current Rx Desc Pointer 0 */ +#define ETH_ECRDP1(n) ETH__GEN(n, ECRDP1) /* Current Rx Desc Pointer 1 */ +#define ETH_ECRDP2(n) ETH__GEN(n, ECRDP2) /* Current Rx Desc Pointer 2 */ +#define ETH_ECRDP3(n) ETH__GEN(n, ECRDP3) /* Current Rx Desc Pointer 3 */ +#define ETH_ECTDP0(n) ETH__GEN(n, ECTDP0) /* Current Tx Desc Pointer 0 */ +#define ETH_ECTDP1(n) ETH__GEN(n, ECTDP1) /* Current Tx Desc Pointer 1 */ +#define ETH_EDSCP2P0L(n) ETH__GEN(n, EDSCP2P0L) /* IP Differentiated Services + CodePoint to Priority0 low */ +#define ETH_EDSCP2P0H(n) ETH__GEN(n, EDSCP2P0H) /* IP Differentiated Services + CodePoint to Priority0 high*/ +#define ETH_EDSCP2P1L(n) ETH__GEN(n, EDSCP2P1L) /* IP Differentiated Services + CodePoint to Priority1 low */ +#define ETH_EDSCP2P1H(n) ETH__GEN(n, EDSCP1P1H) /* IP Differentiated Services + CodePoint to Priority1 high*/ +#define ETH_EVPT2P(n) ETH__GEN(n, EVPT2P) /* VLAN Prio. Tag to Priority */ +#define ETH_EMIBCTRS(n) ETH__GEN(n, EMIBCTRS) /* MIB Counters */ + +#define ETH_EPAR_PhyAD_GET(v, n) (((v) >> ((n) * 5)) & 0x1f) + +#define ETH_ESMIR_READ(phy, reg) (ETH__INS(phy, 16)|\ + ETH__INS(reg, 21)|\ + ETH_ESMIR_ReadOpcode) +#define ETH_ESMIR_WRITE(phy, reg, val) (ETH__INS(phy, 16)|\ + ETH__INS(reg, 21)|\ + ETH__INS(val, 0)|\ + ETH_ESMIR_WriteOpcode) +#define ETH_ESMIR_Value_GET(v) ETH__EXT(v, 0, 16) +#define ETH_ESMIR_WriteOpcode 0 +#define ETH_ESMIR_ReadOpcode ETH__BIT(26) +#define ETH_ESMIR_ReadValid ETH__BIT(27) +#define ETH_ESMIR_Busy ETH__BIT(28) + +/* + * Table 597: Port Configuration Register (PCR) + * 00:00 PM Promiscuous mode + * 0: Normal mode (Frames are only received if the + * destination address is found in the hash + * table) + * 1: Promiscuous mode (Frames are received + * regardless of their destination address. + * Errored frames are discarded unless the Port + * Configuration register's PBF bit is set) + * 01:01 RBM Reject Broadcast Mode + * 0: Receive broadcast address + * 1: Reject frames with broadcast address + * Overridden by the promiscuous mode. + * 02:02 PBF Pass Bad Frames + * (0: Normal mode, 1: Pass bad Frames) + * The Ethernet receiver passes to the CPU errored + * frames (like fragments and collided packets) + * that are normally rejected. + * NOTE: Frames are only passed if they + * successfully pass address filtering. + * 06:03 Reserved + * 07:07 EN Enable (0: Disabled, 1: Enable) + * When enabled, the ethernet port is ready to + * transmit/receive. + * 09:08 LPBK Loop Back Mode + * 00: Normal mode + * 01: Internal loop back mode (TX data is looped + * back to the RX lines. No transition is seen + * on the interface pins) + * 10: External loop back mode (TX data is looped + * back to the RX lines and also transmitted + * out to the MII interface pins) + * 11: Reserved + * 10:10 FC Force Collision + * 0: Normal mode. + * 1: Force Collision on any TX frame. + * For RXM test (in Loopback mode). + * 11:11 Reserved. + * 12:12 HS Hash Size + * 0: 8K address filtering + * (256KB of memory space required). + * 1: 512 address filtering + * ( 16KB of memory space required). + * 13:13 HM Hash Mode (0: Hash Func. 0; 1: Hash Func. 1) + * 14:14 HDM Hash Default Mode + * 0: Discard addresses not found in address table + * 1: Pass addresses not found in address table + * 15:15 HD Duplex Mode (0: Half Duplex, 1: Full Duplex) + * NOTE: Valid only when auto-negotiation for + * duplex mode is disabled. + * 30:16 Reserved + * 31:31 ACCS Accelerate Slot Time + * (0: Normal mode, 1: Reserved) + */ +#define ETH_EPCR_PM ETH__BIT(0) +#define ETH_EPCR_RBM ETH__BIT(1) +#define ETH_EPCR_PBF ETH__BIT(2) +#define ETH_EPCR_EN ETH__BIT(7) +#define ETH_EPCR_LPBK_GET(v) ETH__BIT(v, 8, 2) +#define ETH_EPCR_LPBK_Normal 0 +#define ETH_EPCR_LPBK_Internal 1 +#define ETH_EPCR_LPBK_External 2 +#define ETH_EPCR_FC ETH__BIT(10) + +#define ETH_EPCR_HS ETH__BIT(12) +#define ETH_EPCR_HS_8K 0 +#define ETH_EPCR_HS_512 ETH_EPCR_HS + +#define ETH_EPCR_HM ETH__BIT(13) +#define ETH_EPCR_HM_0 0 +#define ETH_EPCR_HM_1 ETH_EPCR_HM + +#define ETH_EPCR_HDM ETH__BIT(14) +#define ETH_EPCR_HDM_Discard 0 +#define ETH_EPCR_HDM_Pass ETH_EPCR_HDM + +#define ETH_EPCR_HD_Half 0 +#define ETH_EPCR_HD_Full ETH_EPCR_HD_Full + +#define ETH_EPCR_ACCS ETH__BIT(31) + + + +/* + * Table 598: Port Configuration Extend Register (PCXR) + * 00:00 IGMP IGMP Packets Capture Enable + * 0: IGMP packets are treated as normal Multicast + * packets. + * 1: IGMP packets on IPv4/Ipv6 over Ethernet/802.3 + * are trapped and sent to high priority RX + * queue. + * 01:01 SPAN Spanning Tree Packets Capture Enable + * 0: BPDU (Bridge Protocol Data Unit) packets are + * treated as normal Multicast packets. + * 1: BPDU packets are trapped and sent to high + * priority RX queue. + * 02:02 PAR Partition Enable (0: Normal, 1: Partition) + * When more than 61 collisions occur while + * transmitting, the port enters Partition mode. + * It waits for the first good packet from the + * wire and then goes back to Normal mode. Under + * Partition mode it continues transmitting, but + * it does not receive. + * 05:03 PRIOtx Priority weight in the round-robin between high + * and low priority TX queues. + * 000: 1 pkt from HIGH, 1 pkt from LOW. + * 001: 2 pkt from HIGH, 1 pkt from LOW. + * 010: 4 pkt from HIGH, 1 pkt from LOW. + * 011: 6 pkt from HIGH, 1 pkt from LOW. + * 100: 8 pkt from HIGH, 1 pkt from LOW. + * 101: 10 pkt from HIGH, 1 pkt from LOW. + * 110: 12 pkt from HIGH, 1 pkt from LOW. + * 111: All pkt from HIGH, 0 pkt from LOW. LOW is + * served only if HIGH is empty. + * NOTE: If the HIGH queue is emptied before + * finishing the count, the count is reset + * until the next first HIGH comes in. + * 07:06 PRIOrx Default Priority for Packets Received on this + * Port (00: Lowest priority, 11: Highest priority) + * 08:08 PRIOrx_Override Override Priority for Packets Received on this + * Port (0: Do not override, 1: Override with + * <PRIOrx> field) + * 09:09 DPLXen Enable Auto-negotiation for Duplex Mode + * (0: Enable, 1: Disable) + * 11:10 FCTLen Enable Auto-negotiation for 802.3x Flow-control + * 0: Enable; When enabled, 1 is written (through + * SMI access) to the PHY's register 4 bit 10 + * to advertise flow-control capability. + * 1: Disable; Only enables flow control after the + * PHY address is set by the CPU. When changing + * the PHY address the flow control + * auto-negotiation must be disabled. + * 11:11 FLP Force Link Pass + * (0: Force Link Pass, 1: Do NOT Force Link pass) + * 12:12 FCTL 802.3x Flow-Control Mode (0: Enable, 1: Disable) + * NOTE: Only valid when auto negotiation for flow + * control is disabled. + * 13:13 Reserved + * 15:14 MFL Max Frame Length + * Maximum packet allowed for reception (including + * CRC): 00: 1518 bytes, 01: 1536 bytes, + * 10: 2048 bytes, 11: 64K bytes + * 16:16 MIBclrMode MIB Counters Clear Mode (0: Clear, 1: No effect) + * 17:17 MIBctrMode Reserved. (MBZ) + * 18:18 Speed Port Speed (0: 10Mbit/Sec, 1: 100Mbit/Sec) + * NOTE: Only valid if SpeedEn bit is set. + * 19:19 SpeedEn Enable Auto-negotiation for Speed + * (0: Enable, 1: Disable) + * 20:20 RMIIen RMII enable + * 0: Port functions as MII port + * 1: Port functions as RMII port + * 21:21 DSCPen DSCP enable + * 0: IP DSCP field decoding is disabled. + * 1: IP DSCP field decoding is enabled. + * 31:22 Reserved + */ +#define ETH_EPCXR_IGMP ETH__BIT(0) +#define ETH_EPCXR_SPAN ETH__BIT(1) +#define ETH_EPCXR_PAR ETH__BIT(2) +#define ETH_EPCXR_PRIOtx_GET(v) ETH__EXT(v, 3, 3) +#define ETH_EPCXR_PRIOrx_GET(v) ETH__EXT(v, 3, 3) +#define ETH_EPCXR_PRIOrx_Override ETH__BIT(8) +#define ETH_EPCXR_DLPXen ETH__BIT(9) +#define ETH_EPCXR_FCTLen ETH__BIT(10) +#define ETH_EPCXR_FLP ETH__BIT(11) +#define ETH_EPCXR_FCTL ETH__BIT(12) +#define ETH_EPCXR_MFL_GET(v) ETH__EXT(v, 14, 2) +#define ETH_EPCXR_MFL_1518 0 +#define ETH_EPCXR_MFL_1536 1 +#define ETH_EPCXR_MFL_2048 2 +#define ETH_EPCXR_MFL_64K 3 +#define ETH_EPCXR_MIBclrMode ETH__BIT(16) +#define ETH_EPCXR_MIBctrMode ETH__BIT(17) +#define ETH_EPCXR_Speed ETH__BIT(18) +#define ETH_EPCXR_SpeedEn ETH__BIT(19) +#define ETH_EPCXR_RMIIEn ETH__BIT(20) +#define ETH_EPCXR_DSCPEn ETH__BIT(21) + + + +/* + * Table 599: Port Command Register (PCMR) + * 14:00 Reserved + * 15:15 FJ Force Jam / Flow Control + * When in half-duplex mode, the CPU uses this bit + * to force collisions on the Ethernet segment. + * When the CPU recognizes that it is going to run + * out of receive buffers, it can force the + * transmitter to send jam frames, forcing + * collisions on the wire. To allow transmission + * on the Ethernet segment, the CPU must clear the + * FJ bit when more resources are available. When + * in full-duplex and flow-control is enabled, this + * bit causes the port's transmitter to send + * flow-control PAUSE packets. The CPU must reset + * this bit when more resources are available. + * 31:16 Reserved + */ + +#define ETH_EPCMR_FJ ETH__BIT(15) + + +/* + * Table 600: Port Status Register (PSR) -- Read Only + * 00:00 Speed Indicates Port Speed (0: 10Mbs, 1: 100Mbs) + * 01:01 Duplex Indicates Port Duplex Mode (0: Half, 1: Full) + * 02:02 Fctl Indicates Flow-control Mode + * (0: enabled, 1: disabled) + * 03:03 Link Indicates Link Status (0: down, 1: up) + * 04:04 Pause Indicates that the port is in flow-control + * disabled state. This bit is set when an IEEE + * 802.3x flow-control PAUSE (XOFF) packet is + * received (assuming that flow-control is + * enabled and the port is in full-duplex mode). + * Reset when XON is received, or when the XOFF + * timer has expired. + * 05:05 TxLow Tx Low Priority Status + * Indicates the status of the low priority + * transmit queue: (0: Stopped, 1: Running) + * 06:06 TxHigh Tx High Priority Status + * Indicates the status of the high priority + * transmit queue: (0: Stopped, 1: Running) + * 07:07 TXinProg TX in Progress + * Indicates that the port's transmitter is in an + * active transmission state. + * 31:08 Reserved + */ +#define ETH_EPSR_Speed ETH__BIT(0) +#define ETH_EPSR_Duplex ETH__BIT(1) +#define ETH_EPSR_Fctl ETH__BIT(2) +#define ETH_EPSR_Link ETH__BIT(3) +#define ETH_EPSR_Pause ETH__BIT(4) +#define ETH_EPSR_TxLow ETH__BIT(5) +#define ETH_EPSR_TxHigh ETH__BIT(6) +#define ETH_EPSR_TXinProg ETH__BIT(7) + + +/* + * Table 601: Serial Parameters Register (SPR) + * 01:00 JAM_LENGTH Two bits to determine the JAM Length + * (in Backpressure) as follows: + * 00 = 12K bit-times + * 01 = 24K bit-times + * 10 = 32K bit-times + * 11 = 48K bit-times + * 06:02 JAM_IPG Five bits to determine the JAM IPG. + * The step is four bit-times. The value may vary + * between 4 bit time to 124. + * 11:07 IPG_JAM_TO_DATA Five bits to determine the IPG JAM to DATA. + * The step is four bit-times. The value may vary + * between 4 bit time to 124. + * 16:12 IPG_DATA Inter-Packet Gap (IPG) + * The step is four bit-times. The value may vary + * between 12 bit time to 124. + * NOTE: These bits may be changed only when the + * Ethernet ports is disabled. + * 21:17 Data_Blind Data Blinder + * The number of nibbles from the beginning of the + * IPG, in which the IPG counter is restarted when + * detecting a carrier activity. Following this + * value, the port enters the Data Blinder zone and + * does not reset the IPG counter. This ensures + * fair access to the medium. + * The default is 10 hex (64 bit times - 2/3 of the + * default IPG). The step is 4 bit-times. Valid + * range is 3 to 1F hex nibbles. + * NOTE: These bits may be only changed when the + * Ethernet port is disabled. + * 22:22 Limit4 The number of consecutive packet collisions that + * occur before the collision counter is reset. + * 0: The port resets its collision counter after + * 16 consecutive retransmit trials and + * restarts the Backoff algorithm. + * 1: The port resets its collision counter and + * restarts the Backoff algorithm after 4 + * consecutive transmit trials. + * 31:23 Reserved + */ +#define ETH_ESPR_JAM_LENGTH_GET(v) ETH__EXT(v, 0, 2) +#define ETH_ESPR_JAM_IPG_GET(v) ETH__EXT(v, 2, 5) +#define ETH_ESPR_IPG_JAM_TO_DATA_GET(v) ETH__EXT(v, 7, 5) +#define ETH_ESPR_IPG_DATA_GET(v) ETH__EXT(v, 12, 5) +#define ETH_ESPR_Data_Bilnd_GET(v) ETH__EXT(v, 17, 5) +#define ETH_ESPR_Limit4(v) ETH__BIT(22) + +/* + * Table 602: Hash Table Pointer Register (HTPR) + * 31:00 HTP 32-bit pointer to the address table. + * Bits [2:0] must be set to zero. + */ + +/* + * Table 603: Flow Control Source Address Low (FCSAL) + * 15:0 SA[15:0] Source Address + * The least significant bits of the source + * address for the port. This address is used for + * Flow Control. + * 31:16 Reserved + */ + +/* + * Table 604: Flow Control Source Address High (FCSAH) + * 31:0 SA[47:16] Source Address + * The most significant bits of the source address + * for the port. This address is used for Flow + * Control. + */ + + +/* + * Table 605: SDMA Configuration Register (SDCR) + * 01:00 Reserved + * 05:02 RC Retransmit Count + * Sets the maximum number of retransmits per + * packet. After executing retransmit for RC + * times, the TX SDMA closes the descriptor with a + * Retransmit Limit error indication and processes + * the next packet. When RC is set to 0, the + * number of retransmits is unlimited. In this + * case, the retransmit process is only terminated + * if CPU issues an Abort command. + * 06:06 BLMR Big/Little Endian Receive Mode + * The DMA supports Big or Little Endian + * configurations on a per channel basis. The BLMR + * bit only affects data transfer to memory. + * 0: Big Endian + * 1: Little Endian + * 07:07 BLMT Big/Little Endian Transmit Mode + * The DMA supports Big or Little Endian + * configurations on a per channel basis. The BLMT + * bit only affects data transfer from memory. + * 0: Big Endian + * 1: Little Endian + * 08:08 POVR PCI Override + * When set, causes the SDMA to direct all its + * accesses in PCI_0 direction and overrides + * normal address decoding process. + * 09:09 RIFB Receive Interrupt on Frame Boundaries + * When set, the SDMA Rx generates interrupts only + * on frame boundaries (i.e. after writing the + * frame status to the descriptor). + * 11:10 Reserved + * 13:12 BSZ Burst Size + * Sets the maximum burst size for SDMA + * transactions: + * 00: Burst is limited to 1 64bit words. + * 01: Burst is limited to 2 64bit words. + * 10: Burst is limited to 4 64bit words. + * 11: Burst is limited to 8 64bit words. + * 31:14 Reserved + */ +#define ETH_ESDCR_RC_GET(v) ETH__EXT(v, 2, 4) +#define ETH_ESDCR_BLMR ETH__BIT(6) +#define ETH_ESDCR_BLMT ETH__BIT(7) +#define ETH_ESDCR_POVR ETH__BIT(8) +#define ETH_ESDCR_RIFB ETH__BIT(9) +#define ETH_ESDCR_BSZ_GET(v) ETH__EXT(v, 12, 2) +#define ETH_ESDCR_BSZ_SET(v, n) (ETH__CLR(v, 12, 2),\ + (v) |= ETH__INS(n, 12)) +#define ETH_ESDCR_BSZ_1 0 +#define ETH_ESDCR_BSZ_2 1 +#define ETH_ESDCR_BSZ_4 2 +#define ETH_ESDCR_BSZ_8 3 + +#define ETH_ESDCR_BSZ_Strings { "1 64-bit word", "2 64-bit words", \ + "4 64-bit words", "8 64-bit words" } + +/* + * Table 606: SDMA Command Register (SDCMR) + * 06:00 Reserved + * 07:07 ERD Enable RX DMA. + * Set to 1 by the CPU to cause the SDMA to start + * a receive process. Cleared when the CPU issues + * an Abort Receive command. + * 14:08 Reserved + * 15:15 AR Abort Receive + * Set to 1 by the CPU to abort a receive SDMA + * operation. When the AR bit is set, the SDMA + * aborts its current operation and moves to IDLE. + * No descriptor is closed. The AR bit is cleared + * upon entering IDLE. After setting the AR bit, + * the CPU must poll the bit to verify that the + * abort sequence is completed. + * 16:16 STDH Stop TX High + * Set to 1 by the CPU to stop the transmission + * process from the high priority queue at the end + * of the current frame. An interrupt is generated + * when the stop command has been executed. + * Writing 1 to STDH resets TXDH bit. + * Writing 0 to this bit has no effect. + * 17:17 STDL Stop TX Low + * Set to 1 by the CPU to stop the transmission + * process from the low priority queue at the end + * of the current frame. An interrupt is generated + * when the stop command has been executed. + * Writing 1 to STDL resets TXDL bit. + * Writing 0 to this bit has no effect. + * 22:18 Reserved + * 23:23 TXDH Start Tx High + * Set to 1 by the CPU to cause the SDMA to fetch + * the first descriptor and start a transmit + * process from the high priority Tx queue. + * Writing 1 to TXDH resets STDH bit. + * Writing 0 to this bit has no effect. + * 24:24 TXDL Start Tx Low + * Set to 1 by the CPU to cause the SDMA to fetch + * the first descriptor and start a transmit + * process from the low priority Tx queue. + * Writing 1 to TXDL resets STDL bit. + * Writing 0 to this bit has no effect. + * 30:25 Reserved + * 31:31 AT Abort Transmit + * Set to 1 by the CPU to abort a transmit DMA + * operation. When the AT bit is set, the SDMA + * aborts its current operation and moves to IDLE. + * No descriptor is closed. Cleared upon entering + * IDLE. After setting AT bit, the CPU must poll + * it in order to verify that the abort sequence + * is completed. + */ +#define ETH_ESDCMR_ERD ETH__BIT(7) +#define ETH_ESDCMR_AR ETH__BIT(15) +#define ETH_ESDCMR_STDH ETH__BIT(16) +#define ETH_ESDCMR_STDL ETH__BIT(17) +#define ETH_ESDCMR_TXDH ETH__BIT(23) +#define ETH_ESDCMR_TXDL ETH__BIT(24) +#define ETH_ESDCMR_AT ETH__BIT(31) + +/* + * Table 607: Interrupt Cause Register (ICR) + * 00:00 RxBuffer Rx Buffer Return + * Indicates an Rx buffer returned to CPU ownership + * or that the port finished reception of a Rx + * frame in either priority queues. + * NOTE: In order to get a Rx Buffer return per + * priority queue, use bit 19:16. This bit is + * set upon closing any Rx descriptor which + * has its EI bit set. To limit the + * interrupts to frame (rather than buffer) + * boundaries, the user must set SDMA + * Configuration register's RIFB bit. When + * the RIFB bit is set, an interrupt + * generates only upon closing the first + * descriptor of a received packet, if this + * descriptor has it EI bit set. + * 01:01 Reserved + * 02:02 TxBufferHigh Tx Buffer for High priority Queue + * Indicates a Tx buffer returned to CPU ownership + * or that the port finished transmission of a Tx + * frame. + * NOTE: This bit is set upon closing any Tx + * descriptor which has its EI bit set. To + * limit the interrupts to frame (rather than + * buffer) boundaries, the user must set EI + * only in the last descriptor. + * 03:03 TxBufferLow Tx Buffer for Low Priority Queue + * Indicates a Tx buffer returned to CPU ownership + * or that the port finished transmission of a Tx + * frame. + * NOTE: This bit is set upon closing any Tx + * descriptor which has its EI bit set. To + * limit the interrupts to frame (rather than + * buffer) boundaries, the user must set EI + * only in the last descriptor. + * 05:04 Reserved + * 06:06 TxEndHigh Tx End for High Priority Queue + * Indicates that the Tx DMA stopped processing the + * high priority queue after stop command, or that + * it reached the end of the high priority + * descriptor chain. + * 07:07 TxEndLow Tx End for Low Priority Queue + * Indicates that the Tx DMA stopped processing the + * low priority queue after stop command, or that + * it reached the end of the low priority + * descriptor chain. + * 08:08 RxError Rx Resource Error + * Indicates a Rx resource error event in one of + * the priority queues. + * NOTE: To get a Rx Resource Error Indication per + * priority queue, use bit 23:20. + * 09:09 Reserved + * 10:10 TxErrorHigh Tx Resource Error for High Priority Queue + * Indicates a Tx resource error event during + * packet transmission from the high priority queue + * 11:11 TxErrorLow Tx Resource Error for Low Priority Queue + * Indicates a Tx resource error event during + * packet transmission from the low priority queue + * 12:12 RxOVR Rx Overrun + * Indicates an overrun event that occurred during + * reception of a packet. + * 13:13 TxUdr Tx Underrun + * Indicates an underrun event that occurred during + * transmission of packet from either queue. + * 15:14 Reserved + * 16:16 RxBuffer-Queue[0] Rx Buffer Return in Priority Queue[0] + * Indicates a Rx buffer returned to CPU ownership + * or that the port completed reception of a Rx + * frame in a receive priority queue[0] + * 17:17 RxBuffer-Queue[1] Rx Buffer Return in Priority Queue[1] + * Indicates a Rx buffer returned to CPU ownership + * or that the port completed reception of a Rx + * frame in a receive priority queue[1]. + * 18:18 RxBuffer-Queue[2] Rx Buffer Return in Priority Queue[2] + * Indicates a Rx buffer returned to CPU ownership + * or that the port completed reception of a Rx + * frame in a receive priority queue[2]. + * 19:19 RxBuffer-Queue[3] Rx Buffer Return in Priority Queue[3] + * Indicates a Rx buffer returned to CPU ownership + * or that the port completed reception of a Rx + * frame in a receive priority queue[3]. + * 20:20 RxError-Queue[0] Rx Resource Error in Priority Queue[0] + * Indicates a Rx resource error event in receive + * priority queue[0]. + * 21:21 RxError-Queue[1] Rx Resource Error in Priority Queue[1] + * Indicates a Rx resource error event in receive + * priority queue[1]. + * 22:22 RxError-Queue[2] Rx Resource Error in Priority Queue[2] + * Indicates a Rx resource error event in receive + * priority queue[2]. + * 23:23 RxError-Queue[3] Rx Resource Error in Priority Queue[3] + * Indicates a Rx resource error event in receive + * priority queue[3]. + * 27:24 Reserved + * 28:29 MIIPhySTC MII PHY Status Change + * Indicates a status change reported by the PHY + * connected to this port. Set when the MII + * management interface block identifies a change + * in PHY's register 1. + * 29:29 SMIdone SMI Command Done + * Indicates that the SMI completed a MII + * management command (either read or write) that + * was initiated by the CPU writing to the SMI + * register. + * 30:30 Reserved + * 31:31 EtherIntSum Ethernet Interrupt Summary + * This bit is a logical OR of the (unmasked) bits + * [30:04] in the Interrupt Cause register. + */ + +#define ETH_IR_RxBuffer ETH__BIT(0) +#define ETH_IR_TxBufferHigh ETH__BIT(2) +#define ETH_IR_TxBufferLow ETH__BIT(3) +#define ETH_IR_TxEndHigh ETH__BIT(6) +#define ETH_IR_TxEndLow ETH__BIT(7) +#define ETH_IR_RxError ETH__BIT(8) +#define ETH_IR_TxErrorHigh ETH__BIT(10) +#define ETH_IR_TxErrorLow ETH__BIT(11) +#define ETH_IR_RxOVR ETH__BIT(12) +#define ETH_IR_TxUdr ETH__BIT(13) +#define ETH_IR_RxBuffer_0 ETH__BIT(16) +#define ETH_IR_RxBuffer_1 ETH__BIT(17) +#define ETH_IR_RxBuffer_2 ETH__BIT(18) +#define ETH_IR_RxBuffer_3 ETH__BIT(19) +#define ETH_IR_RxBuffer_GET(v) ETH__EXT(v, 16, 4) +#define ETH_IR_RxError_0 ETH__BIT(20) +#define ETH_IR_RxError_1 ETH__BIT(21) +#define ETH_IR_RxError_2 ETH__BIT(22) +#define ETH_IR_RxError_3 ETH__BIT(23) +#define ETH_IR_RxError_GET(v) ETH__EXT(v, 20, 4) +#define ETH_IR_RxBits (ETH_IR_RxBuffer_0|\ + ETH_IR_RxBuffer_1|\ + ETH_IR_RxBuffer_2|\ + ETH_IR_RxBuffer_3|\ + ETH_IR_RxError_0|\ + ETH_IR_RxError_1|\ + ETH_IR_RxError_2|\ + ETH_IR_RxError_3) +#define ETH_IR_MIIPhySTC ETH__BIT(28) +#define ETH_IR_SMIdone ETH__BIT(29) +#define ETH_IR_EtherIntSum (1<<31) +#define ETH_IR_Summary (1<<31) +#define ETH_IR_ErrorSum 0x803d00 +#define INTR_RX_ERROR 0x801100 +#define INTR_TX_ERROR 0x002c00 + +/* + * Table 608: Interrupt Mask Register (IMR) + * 31:00 Various Mask bits for the Interrupt Cause register. + */ + +/* + * Table 609: IP Differentiated Services CodePoint to Priority0 low (DSCP2P0L), + * 31:00 Priority0_low The LSB priority bits for DSCP[31:0] entries. + */ + +/* + * Table 610: IP Differentiated Services CodePoint to Priority0 high (DSCP2P0H) + * 31:00 Priority0_high The LSB priority bits for DSCP[63:32] entries. + */ + +/* + * Table 611: IP Differentiated Services CodePoint to Priority1 low (DSCP2P1L) + * 31:00 Priority1_low The MSB priority bits for DSCP[31:0] entries. + */ + +/* + * Table 612: IP Differentiated Services CodePoint to Priority1 high (DSCP2P1H) + * 31:00 Priority1_high The MSB priority bit for DSCP[63:32] entries. + */ + +/* + * Table 613: VLAN Priority Tag to Priority (VPT2P) + * 07:00 Priority0 The LSB priority bits for VLAN Priority[7:0] + * entries. + * 15:08 Priority1 The MSB priority bits for VLAN Priority[7:0] + * entries. + * 31:16 Reserved + */ +#endif /* _DEV_GTETHREG_H_ */ diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.am b/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.am new file mode 100644 index 0000000000..55ead4c93e --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.am @@ -0,0 +1,43 @@ +## +## $Id$ +## + +VPATH = @srcdir@: + +INCLUDES = -I @srcdir@/../GT64260 + +C_FILES = GT64260eth.c +include_bspdir = $(includedir)/bsp +include_bsp_HEADERS = GT64260eth.h GT64260ethreg.h + +H_FILES = GT64260eth.h GT64260ethreg.h + +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT)) + +EXTRA_DIST = GT64260eth.c + +OBJS = $(C_O_FILES) + +include $(top_srcdir)/../../../../../../automake/compile.am +include $(top_srcdir)/../../../../../../automake/lib.am + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $< + +$(PROJECT_INCLUDE)/bsp/GT64260eth.h: GT64260eth.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/bsp/GT64260ethreg.h: GT64260ethreg.h + $(INSTALL_DATA) $< $@ + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +PREINSTALL_FILES = $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/GT64260eth.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/GT64260ethreg.h + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) + +include $(top_srcdir)/../../../../../../automake/local.am diff --git a/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.in b/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.in new file mode 100644 index 0000000000..fade651cde --- /dev/null +++ b/c/src/lib/libbsp/powerpc/mvme5500/network/Makefile.in @@ -0,0 +1,594 @@ +# Makefile.in generated by automake 1.7.2 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_triplet = @host@ + +VPATH = @srcdir@: +ACLOCAL = @ACLOCAL@ +AMDEP_FALSE = @AMDEP_FALSE@ +AMDEP_TRUE = @AMDEP_TRUE@ +AMTAR = @AMTAR@ + +AR = @AR@ + +# OBSOLETE: Don't use +AS = $(CC) +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +BARE_CPU_CFLAGS = @BARE_CPU_CFLAGS@ +BARE_CPU_MODEL = @BARE_CPU_MODEL@ + +CC = @CC@ $(GCCSPECS) + +CCAS = $(CC) +CCASFLAGS = @CCASFLAGS@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @RTEMS_CFLAGS@ $(XCFLAGS) +CFLAGS_DEBUG_V = @CFLAGS_DEBUG_V@ +CFLAGS_OPTIMIZE_V = @CFLAGS_OPTIMIZE_V@ +CFLAGS_PROFILE_V = @CFLAGS_PROFILE_V@ +CPP = @CPP@ $(GCCSPECS) + +CPPFLAGS = @CPPFLAGS@ $(CPU_DEFINES) $(DEFINES) $(XCPPFLAGS) + +CPU_CFLAGS = @CPU_CFLAGS@ +CYGPATH_W = @CYGPATH_W@ + +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +ENDIF = @ENDIF@ +EXEEXT = @EXEEXT@ +GCC_SPECS = @GCC_SPECS@ +HAS_MP = @HAS_MP@ +HAS_NETWORKING = @HAS_NETWORKING@ +HAS_NETWORKING_FALSE = @HAS_NETWORKING_FALSE@ +HAS_NETWORKING_TRUE = @HAS_NETWORKING_TRUE@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ + +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LTLIBOBJS = @LTLIBOBJS@ +MAINT = @MAINT@ +MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@ +MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@ +MAKE = @MAKE@ +MAKEINFO = @MAKEINFO@ +MULTILIB_FALSE = @MULTILIB_FALSE@ +MULTILIB_TRUE = @MULTILIB_TRUE@ +NM = @NM@ +OBJCOPY = @OBJCOPY@ +OBJEXT = @OBJEXT@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PACKHEX = @PACKHEX@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PROJECT_INCLUDE = @PROJECT_INCLUDE@ +PROJECT_RELEASE = @PROJECT_RELEASE@ +PROJECT_ROOT = @PROJECT_ROOT@ +PROJECT_TOPdir = @PROJECT_TOPdir@ +RANLIB = @RANLIB@ +RTEMS_BSP = @RTEMS_BSP@ +RTEMS_BSP_FAMILY = @RTEMS_BSP_FAMILY@ +RTEMS_BSP_SPECS = @RTEMS_BSP_SPECS@ +RTEMS_CFLAGS = @RTEMS_CFLAGS@ +RTEMS_CPPFLAGS = @RTEMS_CPPFLAGS@ +RTEMS_CPU = @RTEMS_CPU@ +RTEMS_CPU_MODEL = @RTEMS_CPU_MODEL@ +RTEMS_HAS_NETWORKING = @RTEMS_HAS_NETWORKING@ +RTEMS_HOST = @RTEMS_HOST@ +RTEMS_ROOT = @RTEMS_ROOT@ +RTEMS_TOPdir = @RTEMS_TOPdir@ +RTEMS_USE_GCC_FALSE = @RTEMS_USE_GCC_FALSE@ +RTEMS_USE_GCC_TRUE = @RTEMS_USE_GCC_TRUE@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +SIZE = @SIZE@ +STRIP = @STRIP@ +VERSION = @VERSION@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_STRIP = @ac_ct_STRIP@ +am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ +am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ +am__include = @am__include@ +am__quote = @am__quote@ +bindir = @bindir@ +bsplibdir = @bsplibdir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +datadir = @datadir@ +exceptions = @exceptions@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +oldincludedir = @oldincludedir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +sysconfdir = @sysconfdir@ +target = @target@ +target_alias = @target_alias@ +target_cpu = @target_cpu@ +target_os = @target_os@ +target_vendor = @target_vendor@ + +INCLUDES = -I @srcdir@/../GT64260 + +C_FILES = GT64260eth.c +include_bspdir = $(includedir)/bsp +include_bsp_HEADERS = GT64260eth.h GT64260ethreg.h + +H_FILES = GT64260eth.h GT64260ethreg.h + +C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.$(OBJEXT)) + +EXTRA_DIST = GT64260eth.c + +OBJS = $(C_O_FILES) + +@RTEMS_USE_GCC_TRUE@GCCSPECS = $(GCC_SPECS) $(RTEMS_BSP_SPECS) +# CXXFLAGS = @RTEMS_CXXFLAGS@ $(XCXXFLAGS) +CXXFLAGS = @RTEMS_CFLAGS@ $(XCXXFLAGS) +ASFLAGS = $(CPU_ASFLAGS) $(CPU_CFLAGS) $(XASFLAGS) + +LINK_LIBS = $(LD_LIBS) + + +# +# Client compiler and support tools +# + +# +# How to compile stuff into ${ARCH} subdirectory +# +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) + +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ + + +CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) + +CXXLD = $(CXX) +CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ + +CCASCOMPILE = $(CCAS) $(AM_CCASFLAGS) $(CCASFLAGS) +ASCOMPILE = $(AS) $(AM_ASFLAGS) $(ASFLAGS) + + +# Dependency files for use by gmake +# NOTE: we don't put them into $(ARCH) +# so that 'make clean' doesn't blow it away +DEPEND = Depends-${ARCH} + + +# spell out all the LINK_FILE's, rather than using -lbsp, so +# that $(LINK_FILES) can be a dependency +LINK_OBJS = \ + $(OBJS) \ + $(MANAGERS_NOT_WANTED:%=$(PROJECT_RELEASE)/lib/no-%$(LIB_VARIANT).rel) + + +LINK_FILES = \ + $(START_FILE) \ + $(OBJS) \ + $(MANAGERS_NOT_WANTED:%=$(PROJECT_RELEASE)/lib/no-%$(LIB_VARIANT).rel) + + +VARIANT = OPTIMIZE + +VARIANT_OPTIMIZE_V = OPTIMIZE +VARIANT_DEBUG_V = DEBUG +VARIANT_PROFILE_V = PROFILE +VARIANT_optimize_V = OPTIMIZE +VARIANT_debug_V = DEBUG +VARIANT_profile_V = PROFILE + +VARIANT_V = $(VARIANT_$(VARIANT)_V) + +ARCH_OPTIMIZE_V = o-optimize +ARCH_DEBUG_V = o-debug +ARCH_PROFILE_V = o-profile + +ARCH__V = $(ARCH_OPTIMIZE_V) +ARCH = $(ARCH_$(VARIANT_V)_V) + +LIBSUFFIX_OPTIMIZE_V = +LIBSUFFIX_DEBUG_V = _g +LIBSUFFIX_PROFILE_V = _p +LIBSUFFIX__V = $(LIBSUFFIX_OPTIMIZE_V) + +LIB_VARIANT = $(LIBSUFFIX_$(VARIANT_V)_V) +CFLAGS__V = $(CFLAGS_OPTIMIZE_V) + +@RTEMS_USE_GCC_TRUE@RTEMS_CFLAGS_OPTIMIZE_V = +@RTEMS_USE_GCC_TRUE@RTEMS_CFLAGS_DEBUG_V = -qrtems_debug -Wno-unused +@RTEMS_USE_GCC_TRUE@RTEMS_CFLAGS_PROFILE_V = -pg + +RTEMS_CFLAGS__V = $(RTEMS_CFLAGS_OPTIMIZE_V) +CXX = @CXX@ $(GCCSPECS) + +AM_CPPFLAGS = $(RTEMS_CPPFLAGS) +AM_CFLAGS = +AM_CXXFLAGS = +AM_CCASFLAGS = $(CPU_CFLAGS) $(RTEMS_CPPFLAGS) $(RTEMS_CCASFLAGS) + +ARFLAGS = ruv + +TMPINSTALL_FILES = $(PROJECT_RELEASE)/lib + +# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile +PREINSTALL_FILES = $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/GT64260eth.h $(PROJECT_INCLUDE)/bsp/GT64260ethreg.h + +PROJECT_TOOLS = $(PROJECT_RELEASE)/build-tools +subdir = network +mkinstalldirs = $(SHELL) $(top_srcdir)/../../../../../../mkinstalldirs +CONFIG_HEADER = $(top_builddir)/include/bspopts.tmp +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(include_bsp_HEADERS) + +DIST_COMMON = $(include_bsp_HEADERS) \ + $(top_srcdir)/../../../../../../automake/compile.am \ + $(top_srcdir)/../../../../../../automake/lib.am \ + $(top_srcdir)/../../../../../../automake/local.am Makefile.am \ + Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/../../../../../../automake/compile.am $(top_srcdir)/../../../../../../automake/lib.am $(top_srcdir)/../../../../../../automake/local.am $(top_srcdir)/configure.ac $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --foreign network/Makefile +Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +uninstall-info-am: +include_bspHEADERS_INSTALL = $(INSTALL_HEADER) +install-include_bspHEADERS: $(include_bsp_HEADERS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(include_bspdir) + @list='$(include_bsp_HEADERS)'; for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " $(include_bspHEADERS_INSTALL) $$d$$p $(DESTDIR)$(include_bspdir)/$$f"; \ + $(include_bspHEADERS_INSTALL) $$d$$p $(DESTDIR)$(include_bspdir)/$$f; \ + done + +uninstall-include_bspHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(include_bsp_HEADERS)'; for p in $$list; do \ + f="`echo $$p | sed -e 's|^.*/||'`"; \ + echo " rm -f $(DESTDIR)$(include_bspdir)/$$f"; \ + rm -f $(DESTDIR)$(include_bspdir)/$$f; \ + done + +ETAGS = etags +ETAGSFLAGS = + +CTAGS = ctags +CTAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(CTAGS_ARGS)$$tags$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + $(mkinstalldirs) $(distdir)/../../../../../../../automake + @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ + list='$(DISTFILES)'; for file in $$list; do \ + case $$file in \ + $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ + $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ + esac; \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) all-local + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(include_bspdir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-local mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-include_bspHEADERS + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-include_bspHEADERS uninstall-info-am + +.PHONY: CTAGS GTAGS all all-am all-local check check-am clean \ + clean-generic clean-local ctags distclean distclean-generic \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-include_bspHEADERS install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic pdf \ + pdf-am ps ps-am tags uninstall uninstall-am \ + uninstall-include_bspHEADERS uninstall-info-am + +@RTEMS_USE_GCC_FALSE@include $(CONFIG.CC) + +${ARCH}/%.o: %.c + ${COMPILE} -o $@ -c $< + +${ARCH}/%.o: %.cc + ${CXXCOMPILE} -o $@ -c $< + +${ARCH}/%.o: %.S + ${CCASCOMPILE} -DASM -o $@ -c $< + +# We deliberately don't have anything depend on the +# $(DEPEND) file; otherwise it will get rebuilt even +# on 'make clean' +# + +@RTEMS_USE_GCC_TRUE@depend-gcc: $(C_FILES) $(CC_FILES) $(S_FILES) +@RTEMS_USE_GCC_TRUE@ $(COMPILE) -M $^ | \ +@RTEMS_USE_GCC_TRUE@ sed -e 's?^\(.*\)\.o[ ]*:?$$(ARCH)/\1.o:?' \ +@RTEMS_USE_GCC_TRUE@ -e 's?$(ARCH)/?$$(ARCH)/?' >$(DEPEND).tmp +@RTEMS_USE_GCC_TRUE@ mv $(DEPEND).tmp $(DEPEND) + +# pull in dependencies if they exist +@RTEMS_USE_GCC_TRUE@ifeq (${DEPEND},$(wildcard ${DEPEND})) +@RTEMS_USE_GCC_TRUE@include ${DEPEND} +@RTEMS_USE_GCC_TRUE@@ENDIF@ +depend: depend-am + +@RTEMS_USE_GCC_TRUE@define make-rel +@RTEMS_USE_GCC_TRUE@ $(LINK) -qnolinkcmds -nostdlib -Wl,-r $(XLDFLAGS) $^ +@RTEMS_USE_GCC_TRUE@endef +@RTEMS_USE_GCC_FALSE@define make-rel +@RTEMS_USE_GCC_FALSE@ $(LINK) $(XLDFLAGS) $^ +@RTEMS_USE_GCC_FALSE@endef + +${ARCH}: + mkdir ${ARCH} + +clean-local: + $(RM) -r o-optimize o-debug o-profile $(CLEANDIRS) + $(RM) Depends-o-optimize.tmp Depends-o-debug.tmp Depends-o-profile.tmp + +define make-library +test -d $(ARCH) || mkdir $(ARCH) +$(RM) $@ +$(AR) $(ARFLAGS) $@ $^ +$(RANLIB) $@ +endef + +$(PROJECT_RELEASE)/lib: + @$(mkinstalldirs) $@ + +.PRECIOUS: $(LIB) + +# +# (OPTIONAL) Add local stuff here using += +# + +$(PROJECT_INCLUDE)/bsp: + $(mkinstalldirs) $< + +$(PROJECT_INCLUDE)/bsp/GT64260eth.h: GT64260eth.h + $(INSTALL_DATA) $< $@ + +$(PROJECT_INCLUDE)/bsp/GT64260ethreg.h: GT64260ethreg.h + $(INSTALL_DATA) $< $@ + +all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS) + +debug: + @echo + @echo "\"make debug\" is obsolete, instead use:" + @echo " make VARIANT=DEBUG" + @echo + +.PHONY: debug + +profile: + @echo + @echo "\"make profile\" is obsolete, instead use:" + @echo " make VARIANT=PROFILE" + @echo + +.PHONY: profile + +preinstall-am: $(PREINSTALL_FILES) +preinstall: preinstall-am +.PHONY: preinstall preinstall-am + +depend-am: depend-gcc +depend: depend-am +.PHONY: depend depend-am depend-gcc +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: |