diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 09:53:31 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-23 15:18:44 +0200 |
commit | 031df3914990db0336a0d386fb53558b05de467e (patch) | |
tree | 4661e22f0cdb3f9d06879f0194b77c75f62bac79 /c/src/lib/libbsp/powerpc/mpc8260ads | |
parent | bsps: Move interrupt controller support to bsps (diff) | |
download | rtems-031df3914990db0336a0d386fb53558b05de467e.tar.bz2 |
bsps: Move legacy network drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'c/src/lib/libbsp/powerpc/mpc8260ads')
5 files changed, 2 insertions, 1410 deletions
diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am index 6fe77e9ed4..cac9650005 100644 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am @@ -42,8 +42,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-defa librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspreset-empty.c if HAS_NETWORKING -librtemsbsp_a_SOURCES += network/if_hdlcsubr.c -librtemsbsp_a_SOURCES += network/network.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/mpc8260ads/net/if_hdlcsubr.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/mpc8260ads/net/network.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/cache/cache.c diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/README b/c/src/lib/libbsp/powerpc/mpc8260ads/network/README deleted file mode 100644 index d5722557c3..0000000000 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/network/README +++ /dev/null @@ -1,55 +0,0 @@ -Networking with HDLC -==================== - -Author: Andy Dachs <a.dachs@sstl.co.uk> -Date: 31st August 2001 -Surrey Satellite Technology Limited - - -The network support in this BSP is not Ethernet support. The -"network" referred to here is a point to point HDLC communication link. -The ADS board does have a 10/100 ethernet port and it would be nice to -get support for that added. - -My requirement is for a WAN so I need the ability to send IP frames over -HDLC. Ultimately this will end up as frame relay support but in the meantime -I'm simply wrapping up the IP packet inside an HDLC frame. There is no -addressing mechanism or mac address attached to the start of the frame. - -This is what is physically transmitted: -<FLAG><IP Frame><CRC><FLAG> - - -The physical link consists of four lines, -TX DATA : Data transmitted -TX CLOCK: Clock for transmitted data. Data source provides clock. -RX DATA : Received data -RX CLOCK: Clock for received data. Data sink accepts clock. - -To connect two entities you require a NULL modem arrangement, i.e. TX data -and Tx clock from one end go into RX data and Rx clock on the other end. - -The MPC8260ADS side of the link is implemented using SCC3 in HDLC mode. The -TX clock is generated by BRG4. The RX clock in input to the board on the CLK5 -input. I built a LVTTL to RS422 converter. - -The other end of the link is a Windows NT PC with WANic400 synchronous -communication card. We bought the card from ImageStream -(http://www.imagestream.com/WANic400.html). You also need the NT -drivers and a cable. There are other distributors but I found these -guys helpful - and they also do Linux drivers. - -The NT WANic driver has a number of modes, one of which is ethernet emulation. -This mode is what is needed to transport IP packets in HDLC frames. - -In libnetworking/net you will find a file called if_hdlcsubr.c containing -the hdlc_input and hdlc_output routines required by network.c. This file was -created by taking out the addressing mechanisms from if_ethersubr.c in the -same directory. There are probably neater ways to do this <any -contributions welcome here>. - - - - - - diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c deleted file mode 100644 index 350efdbc22..0000000000 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Created from if_ethersubr.c by Andy Dachs <a.dachs@sstl.co.uk> - * Surrey Satellite Technology Limited (SSTL), 2001 - * Modified (hacked) to support IP frames transmitted over HDLC. This - * all needs tidying up in future but it does actually work for point - * to point communications. I have an SDL WANic400 synchronous - * communications card that comes with Windows NT drivers. The drivers - * support a mode that they call "Ethernet Emulation". That simply - * puts the IP frame in an HDLC frame without any ethernet header. i.e. - * <HDLC Flag><IpFrame><CRC><HDLC Flag>. There is no addressing beyond - * the IP header information so is only suitable for point to point links - * with a single protocol. "At some point" I will add a Frame Relay header - * but at the moment I have difficulties getting the WANic card driver's - * Frame Relay driver to work. - * - * Copyright (c) 1982, 1989, 1993 - * The Regents of the University of California. 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 by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. - * - * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include <rtems/rtems_bsdnet.h> - -#include <sys/param.h> -/*#include <sys/systm.h> -#include <sys/kernel.h> */ -#define KERNEL -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/protosw.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <errno.h> -#include <sys/syslog.h> -#include <sys/sysctl.h> - -#include <net/if.h> -#include <net/netisr.h> -#include <net/route.h> -#include <net/if_llc.h> -#include <net/if_dl.h> -#include <net/if_types.h> -#include <net/ethernet.h> - -#include <netinet/in.h> -#include <netinet/in_var.h> -#include <netinet/if_ether.h> - -#include <stdio.h> - -#include "if_hdlcsubr.h" - -/* -u_char etherbroadcastaddr[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; -*/ -#define senderr(e) { error = (e); goto bad;} - -/* - * HDLC output routine. - * Just transmit the packet (hardware adds flags and CRC) - */ -int -hdlc_output(ifp, m0, dst, rt0) - register struct ifnet *ifp; - struct mbuf *m0; - struct sockaddr *dst; - struct rtentry *rt0; -{ - short type; - int s, error = 0; -#if 0 - u_char edst[6]; -#endif - register struct mbuf *m = m0; - register struct rtentry *rt; - struct mbuf *mcopy = (struct mbuf *)0; -/* register struct ether_header *eh; */ - int off, len = m->m_pkthdr.len; - -/* printk( "hdlc output" ); */ -/* struct arpcom *ac = (struct arpcom *)ifp; */ - - if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) - senderr(ENETDOWN); - rt = rt0; - if (rt) { - if ((rt->rt_flags & RTF_UP) == 0) { - rt0 = rt = rtalloc1(dst, 1, 0UL); - if (rt0) - rt->rt_refcnt--; - else - senderr(EHOSTUNREACH); - } - if (rt->rt_flags & RTF_GATEWAY) { - if (rt->rt_gwroute == 0) - goto lookup; - if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { - rtfree(rt); rt = rt0; - lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, - 0UL); - if ((rt = rt->rt_gwroute) == 0) - senderr(EHOSTUNREACH); - } - } - if (rt->rt_flags & RTF_REJECT) - if (rt->rt_rmx.rmx_expire == 0 || - rtems_bsdnet_seconds_since_boot() < rt->rt_rmx.rmx_expire) - senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); - } - switch (dst->sa_family) { - - case AF_INET: -#if 0 - if (!arpresolve(ac, rt, m, dst, edst, rt0)) - return (0); /* if not yet resolved */ -#endif - - /* If broadcasting on a simplex interface, loopback a copy */ - if ((m->m_flags & M_BCAST) && (ifp->if_flags & IFF_SIMPLEX)) - mcopy = m_copy(m, 0, (int)M_COPYALL); - off = m->m_pkthdr.len - m->m_len; - type = htons(ETHERTYPE_IP); - break; -#if 0 - case AF_UNSPEC: - eh = (struct ether_header *)dst->sa_data; - (void)memcpy(edst, eh->ether_dhost, sizeof (edst)); - type = eh->ether_type; - break; -#endif - default: - printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit, - dst->sa_family); - senderr(EAFNOSUPPORT); - } - - if (mcopy) - (void) looutput(ifp, mcopy, dst, rt); -#if 0 - /* - * Add local net header. If no space in first mbuf, - * allocate another. - */ - M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT); -#endif - - if (m == 0) - senderr(ENOBUFS); - -#if 0 - eh = mtod(m, struct ether_header *); - (void)memcpy(&eh->ether_type, &type, - sizeof(eh->ether_type)); - (void)memcpy(eh->ether_dhost, edst, sizeof (edst)); - (void)memcpy(eh->ether_shost, ac->ac_enaddr, - sizeof(eh->ether_shost)); -#endif - - s = splimp(); - /* - * Queue message on interface, and start output if interface - * not yet active. - */ - if (IF_QFULL(&ifp->if_snd)) { - IF_DROP(&ifp->if_snd); - splx(s); - senderr(ENOBUFS); - } - IF_ENQUEUE(&ifp->if_snd, m); - if ((ifp->if_flags & IFF_OACTIVE) == 0) - (*ifp->if_start)(ifp); - splx(s); - - ifp->if_obytes += len /*+ sizeof (struct ether_header)*/; - if (m->m_flags & M_MCAST) - ifp->if_omcasts++; - return (error); - -bad: - if (m) - m_freem(m); - return (error); -} - -/* - * Process a received Ethernet packet; - * the packet is in the mbuf chain m without - * the ether header, which is provided separately. - */ -void -hdlc_input(ifp, m) - struct ifnet *ifp; - struct mbuf *m; -{ - register struct ifqueue *inq; - int s; - - struct ether_header eh; - - if ((ifp->if_flags & IFF_UP) == 0) { - m_freem(m); - return; - } - ifp->if_ibytes += m->m_pkthdr.len; -/* - if (memcmp((caddr_t)etherbroadcastaddr, (caddr_t)eh->ether_dhost, - sizeof(etherbroadcastaddr)) == 0) - m->m_flags |= M_BCAST; - else if (eh->ether_dhost[0] & 1) - m->m_flags |= M_MCAST; -*/ - if (m->m_flags & (M_BCAST|M_MCAST)) - ifp->if_imcasts++; - - /* - * RTEMS addition -- allow application to `tap into' - * the incoming packet stream. - */ - if (ifp->if_tap && (*ifp->if_tap)(ifp, &eh, m)) { - m_freem(m); - return; - } - - schednetisr(NETISR_IP); - inq = &ipintrq; - - s = splimp(); - if (IF_QFULL(inq)) { - IF_DROP(inq); - m_freem(m); - } else - IF_ENQUEUE(inq, m); - splx(s); -} - -/* - * Perform common duties while attaching to interface list - */ -void -hdlc_ifattach(ifp) - register struct ifnet *ifp; -{ - register struct ifaddr *ifa; - register struct sockaddr_dl *sdl; - - ifp->if_type = IFT_ETHER; - ifp->if_addrlen = 0; - ifp->if_hdrlen = 0; - ifp->if_mtu = 2048; - if (ifp->if_baudrate == 0) - ifp->if_baudrate = 8000000; - for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) - if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) && - sdl->sdl_family == AF_LINK) { - sdl->sdl_type = IFT_ETHER; - sdl->sdl_alen = ifp->if_addrlen; -/* - memcpy(LLADDR(sdl), - (caddr_t)((struct arpcom *)ifp)->ac_enaddr, - ifp->if_addrlen); -*/ - break; - } -} - -/* SYSCTL_NODE(_net_link, IFT_ETHER, ether, CTLFLAG_RW, 0, "Ethernet"); */ - -int -hdlc_ioctl(struct ifnet *ifp, int command, caddr_t data) -{ - struct ifaddr *ifa = (struct ifaddr *) data; - struct ifreq *ifr = (struct ifreq *) data; - int error = 0; - - switch (command) { - case SIOCSIFADDR: - ifp->if_flags |= IFF_UP; - - switch (ifa->ifa_addr->sa_family) { -#if 0 -#ifdef INET - case AF_INET: - ifp->if_init(ifp->if_softc); /* before arpwhohas */ - - arp_ifinit((struct arpcom *)ifp, ifa); - break; -#endif -#endif - default: - ifp->if_init(ifp->if_softc); - break; - } - break; - - case SIOCGIFADDR: - { - struct sockaddr *sa; - - sa = (struct sockaddr *) & ifr->ifr_data; -/* - memcpy((caddr_t) sa->sa_data, - ((struct arpcom *)ifp->if_softc)->ac_enaddr, - ETHER_ADDR_LEN); -*/ - } - break; - - case SIOCSIFMTU: - /* - * Set the interface MTU. - */ - if (ifr->ifr_mtu > ETHERMTU) { - error = EINVAL; - } else { - ifp->if_mtu = ifr->ifr_mtu; - } - break; - } - return (error); -} diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h b/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h deleted file mode 100644 index 8289c4bf75..0000000000 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/network/if_hdlcsubr.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * RTEMS/TCPIP driver for MPC8260 SCC HDLC networking - * - * Submitted by Andy Dachs <a.dachs@sstl.co.uk> - * (c) Surrey Satellite Technology Limited, 2001 - * - * On the ADS board the ethernet interface is connected to FCC2 - * but in my application I want TCP over HDLC (see README) - * so will use SCC3 as the network interface. I have other plans - * for the FCCs so am unlikely to add true ethernet support to - * this BSP. Contributions welcome! - * - * COPYRIGHT (c) 1989-1997. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may in - * the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ -#ifndef __IF_HDLCSUBR_H -#define __IF_HDLCSUBR_H - -struct ifnet; -struct mbuf; -struct sockaddr; -struct rtentry; - -void hdlc_ifattach (struct ifnet *); -void hdlc_input (struct ifnet *, struct mbuf *); -int hdlc_output (struct ifnet *, - struct mbuf *, struct sockaddr *, struct rtentry *); -int hdlc_ioctl (struct ifnet *, int , caddr_t ); - -#endif diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c b/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c deleted file mode 100644 index fb87fc0e64..0000000000 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/network/network.c +++ /dev/null @@ -1,969 +0,0 @@ -/* - * RTEMS/TCPIP driver for MPC8260 SCC - * - * Modified for MPC8260 by Andy Dachs <a.dachs@sstl.co.uk> - * Surrey Satellite Technology Limited - * - * On the ADS board the ethernet interface is connected to FCC2 - * but in my application I want TCP over HDLC (see README) - * so will use SCC3 as the network interface. I have other plans - * for the FCCs so am unlikely to add true ethernet support to - * this BSP. Contributions welcome! - * - * Modified for MPC860 by Jay Monkman (jmonkman@frasca.com) - * - * This supports ethernet on either SCC1 or the FEC of the MPC860T. - * Right now, we only do 10 Mbps, even with the FEC. The function - * rtems_m860_enet_driver_attach determines which one to use. Currently, - * only one may be used at a time. - * - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include <bsp.h> -#include <bsp/irq.h> -#include <mpc8260.h> -#include <mpc8260/cpm.h> -#include <stdio.h> -#include <rtems/error.h> -#include <rtems/rtems_bsdnet.h> -#include <rtems/bspIo.h> - -#include <sys/param.h> -#include <sys/mbuf.h> -#include <sys/socket.h> -#include <sys/sockio.h> -#include <errno.h> - -#include <net/if.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include "if_hdlcsubr.h" - -/* - * Number of interfaces supported by this driver - */ -#define NIFACES 1 - -/* - * Default number of buffer descriptors set aside for this driver. - * The number of transmit buffer descriptors has to be quite large - * since a single frame often uses four or more buffer descriptors. - */ -#define RX_BUF_COUNT 32 -#define TX_BUF_COUNT 8 -#define TX_BD_PER_BUF 4 - -#define INET_ADDR_MAX_BUF_SIZE (sizeof "255.255.255.255") - -extern void m8xx_dump_brgs( void ); - -/* - * RTEMS event used by interrupt handler to signal daemons. - * This must *not* be the same event used by the TCP/IP task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* - * Receive buffer size -- Allow for a full ethernet packet plus CRC (1518). - * Round off to nearest multiple of RBUF_ALIGN. - */ -#define MAX_MTU_SIZE 1518 -/*#define MAX_MTU_SIZE 2050*/ -#define RBUF_ALIGN 4 -#define RBUF_SIZE ((MAX_MTU_SIZE + RBUF_ALIGN) & ~RBUF_ALIGN) - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct m8260_hdlc_struct { - struct ifnet ac_if; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - m8260BufferDescriptor_t *rxBdBase; - m8260BufferDescriptor_t *txBdBase; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - - /* - * Statistics - */ - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxInterrupts; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxAbort; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxLostCarrier; - unsigned long txInterrupts; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; -static struct m8260_hdlc_struct hdlc_driver[NIFACES]; - -static void m8xx_scc3_hdlc_on(const rtems_irq_connect_data* ptr) -{ -} - -static void m8xx_scc3_hdlc_off(const rtems_irq_connect_data* ptr) -{ - /* - * Please put relevant code there - */ -} - -static int m8xx_scc3_hdlc_isOn(const rtems_irq_connect_data* ptr) -{ - return BSP_irq_enabled_at_cpm (ptr->name); -} - -/* - * SCC interrupt handler - * TBD: Can we work out which SCC generated the interrupt from the - * value of v? If so we can use the same handler for multiple - * SCCs. - */ -static void -m8xx_scc3_interrupt_handler (rtems_irq_hdl_param unused) -{ - /* - * Frame received? - */ - if ((m8260.scc3.sccm & M8260_SCCE_RXF) && - (m8260.scc3.scce & M8260_SCCE_RXF) ) { - m8260.scc3.scce = M8260_SCCE_RXF; -/* m8260.scc3.sccm &= ~M8260_SCCE_RXF; */ - hdlc_driver[0].rxInterrupts++; - rtems_bsdnet_event_send (hdlc_driver[0].rxDaemonTid, INTERRUPT_EVENT); -/* - printk( "Rx " ); -*/ - } - - /* - * Buffer transmitted or transmitter error? - */ - if ((m8260.scc3.sccm & (M8260_SCCE_TX | M8260_SCCE_TXE) ) && - (m8260.scc3.scce & (M8260_SCCE_TX | M8260_SCCE_TXE) )) { - m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE; -/* m8260.scc3.sccm &= ~(M8260_SCCE_TX | M8260_SCCE_TXE); */ - hdlc_driver[0].txInterrupts++; - rtems_bsdnet_event_send (hdlc_driver[0].txDaemonTid, INTERRUPT_EVENT); -/* - printk( "Tx " ); -*/ - } - -#if 0 - m8260.sipnr_l = M8260_SIMASK_SCC3; /* Clear SCC3 interrupt-in-service bit */ -#endif -} - -static rtems_irq_connect_data hdlcSCC3IrqData = { - BSP_CPM_IRQ_SCC3, - (rtems_irq_hdl) m8xx_scc3_interrupt_handler, - NULL, - (rtems_irq_enable) m8xx_scc3_hdlc_on, - (rtems_irq_disable) m8xx_scc3_hdlc_off, - (rtems_irq_is_enabled)m8xx_scc3_hdlc_isOn -}; - -/* - * Initialize the SCC hardware - * Configure I/O ports for SCC3 - * Internal Tx clock, External Rx clock - */ -static void -m8260_scc_initialize_hardware (struct m8260_hdlc_struct *sc) -{ - int i; - int brg; - - rtems_status_code status; - - /* RxD PB14 */ - m8260.pparb |= 0x00020000; - m8260.psorb &= ~0x00020000; - m8260.pdirb &= ~0x00020000; - - /* RxC (CLK5) PC27 */ - m8260.pparc |= 0x00000010; - m8260.psorc &= ~0x00000010; - m8260.pdirc &= ~0x00000010; - - /* TxD PD24 and TxC PD10 (BRG4) */ - m8260.ppard |= 0x00200080; - m8260.psord |= 0x00200000; - m8260.psord &= ~0x00000080; - m8260.pdird |= 0x00200080; - - /* External Rx Clock from CLK5 */ - if( m8xx_get_clk( M8xx_CLK_5 ) == -1 ) - printk( "Error allocating CLK5 for network device.\n" ); - else - m8260.cmxscr |= 0x00002000; - - /* Internal Tx Clock from BRG4 */ - if( (brg = m8xx_get_brg(M8xx_BRG_4, 8000000 )) == -1 ) - printk( "Error allocating BRG for network device\n" ); - else - m8260.cmxscr |= ((unsigned)brg << 8); - - /* - * Allocate mbuf pointers - */ - sc->rxMbuf = malloc (sc->rxBdCount * sizeof *sc->rxMbuf, - M_MBUF, M_NOWAIT); - sc->txMbuf = malloc (sc->txBdCount * sizeof *sc->txMbuf, - M_MBUF, M_NOWAIT); - if (!sc->rxMbuf || !sc->txMbuf) - rtems_panic ("No memory for mbuf pointers"); - - /* - * Set receiver and transmitter buffer descriptor bases - */ - sc->rxBdBase = m8xx_bd_allocate (sc->rxBdCount); - sc->txBdBase = m8xx_bd_allocate (sc->txBdCount); - - m8260.scc3p.rbase = (char *)sc->rxBdBase - (char *)&m8260; - m8260.scc3p.tbase = (char *)sc->txBdBase - (char *)&m8260; - - /* - * Send "Init parameters" command - */ - - m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 ); - - /* - * Set receive and transmit function codes - */ - m8260.scc3p.rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS; - m8260.scc3p.tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS; - - /* - * Set maximum receive buffer length - */ - m8260.scc3p.mrblr = RBUF_SIZE; - - m8260.scc3p.un.hdlc.c_mask = 0xF0B8; - m8260.scc3p.un.hdlc.c_pres = 0xFFFF; - m8260.scc3p.un.hdlc.disfc = 0; - m8260.scc3p.un.hdlc.crcec = 0; - m8260.scc3p.un.hdlc.abtsc = 0; - m8260.scc3p.un.hdlc.nmarc = 0; - m8260.scc3p.un.hdlc.retrc = 0; - m8260.scc3p.un.hdlc.rfthr = 1; - m8260.scc3p.un.hdlc.mflr = RBUF_SIZE; - - m8260.scc3p.un.hdlc.hmask = 0x0000; /* promiscuous */ - - m8260.scc3p.un.hdlc.haddr1 = 0xFFFF; /* Broadcast address */ - m8260.scc3p.un.hdlc.haddr2 = 0xFFFF; /* Station address */ - m8260.scc3p.un.hdlc.haddr3 = 0xFFFF; /* Dummy */ - m8260.scc3p.un.hdlc.haddr4 = 0xFFFF; /* Dummy */ - - /* - * Send "Init parameters" command - */ -/* - m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3 ); -*/ - - /* - * Set up receive buffer descriptors - */ - for (i = 0 ; i < sc->rxBdCount ; i++) { - (sc->rxBdBase + i)->status = 0; - } - - /* - * Set up transmit buffer descriptors - */ - for (i = 0 ; i < sc->txBdCount ; i++) { - (sc->txBdBase + i)->status = 0; - sc->txMbuf[i] = NULL; - } - sc->txBdHead = sc->txBdTail = 0; - sc->txBdActiveCount = 0; - - m8260.scc3.sccm = 0; /* No interrupts unmasked till necessary */ - - /* - * Clear any outstanding events - */ - m8260.scc3.scce = 0xFFFF; - - /* - * Set up interrupts - */ - status = BSP_install_rtems_irq_handler (&hdlcSCC3IrqData); -/* - printk( "status = %d, Success = %d\n", status, RTEMS_SUCCESSFUL ); -*/ - if (status != 1 /*RTEMS_SUCCESSFUL*/ ) { - rtems_panic ("Can't attach M8260 SCC3 interrupt handler: %s\n", - rtems_status_text (status)); - } - m8260.scc3.sccm = 0; /* No interrupts unmasked till necessary */ - - m8260.scc3.gsmr_h = 0; - m8260.scc3.gsmr_l = 0x10000000; - m8260.scc3.dsr = 0x7E7E; /* flag character */ - m8260.scc3.psmr = 0x2000; /* 2 flags between Tx'd frames */ - -/* printk("scc3 init\n" ); */ - - m8260.scc3.gsmr_l |= 0x00000030; /* Set ENR and ENT to enable Rx and Tx */ - -} - -/* - * Soak up buffer descriptors that have been sent - * Note that a buffer descriptor can't be retired as soon as it becomes - * ready. The MC68360 Errata (May 96) says that, "If an Ethernet frame is - * made up of multiple buffers, the user should not reuse the first buffer - * descriptor until the last buffer descriptor of the frame has had its - * ready bit cleared by the CPM". - */ -static void -m8260Enet_retire_tx_bd (struct m8260_hdlc_struct *sc) -{ - uint16_t status; - int i; - int nRetired; - struct mbuf *m, *n; - - i = sc->txBdTail; - nRetired = 0; - while ((sc->txBdActiveCount != 0) - && (((status = (sc->txBdBase + i)->status) & M8260_BD_READY) == 0)) { - /* - * See if anything went wrong - */ - if (status & (M8260_BD_UNDERRUN | - M8260_BD_CTS_LOST)) { - /* - * Check for errors which stop the transmitter. - */ - if( status & M8260_BD_UNDERRUN ) { - hdlc_driver[0].txUnderrun++; - - /* - * Restart the transmitter - */ - /* FIXME: this should get executed only if using the SCC */ - m8xx_cp_execute_cmd (M8260_CR_OP_RESTART_TX | M8260_CR_SCC3); - } - if (status & M8260_BD_CTS_LOST) - hdlc_driver[0].txLostCarrier++; - } - nRetired++; - if (status & M8260_BD_LAST) { - /* - * A full frame has been transmitted. - * Free all the associated buffer descriptors. - */ - sc->txBdActiveCount -= nRetired; - while (nRetired) { - nRetired--; - m = sc->txMbuf[sc->txBdTail]; - MFREE (m, n); - if (++sc->txBdTail == sc->txBdCount) - sc->txBdTail = 0; - } - } - if (++i == sc->txBdCount) - i = 0; - } -} - -/* - * reader task - */ -static void -scc_rxDaemon (void *arg) -{ - struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg; - struct ifnet *ifp = &sc->ac_if; - struct mbuf *m; - uint16_t status; - m8260BufferDescriptor_t *rxBd; - int rxBdIndex; - - /* - * Allocate space for incoming packets and start reception - */ - for (rxBdIndex = 0 ; ;) { - rxBd = sc->rxBdBase + rxBdIndex; - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - rxBd->status = M8260_BD_EMPTY | M8260_BD_INTERRUPT; - if (++rxBdIndex == sc->rxBdCount) { - rxBd->status |= M8260_BD_WRAP; - break; - } - } - -/* - m8260.scc3.sccm |= M8260_SCCE_RXF; -*/ - - /* - * Input packet handling loop - */ - rxBdIndex = 0; - for (;;) { - rxBd = sc->rxBdBase + rxBdIndex; - - /* - * Wait for packet if there's not one ready - */ - if ((status = rxBd->status) & M8260_BD_EMPTY) { - /* - * Clear old events - */ - - m8260.scc3.scce = M8260_SCCE_RXF; - - /* - * Wait for packet - * Note that the buffer descriptor is checked - * *before* the event wait -- this catches the - * possibility that a packet arrived between the - * `if' above, and the clearing of the event register. - */ - while ((status = rxBd->status) & M8260_BD_EMPTY) { - rtems_event_set events; - - /* - * Unmask RXF (Full frame received) event - */ - m8260.scc3.sccm |= M8260_SCCE_RXF; - -/* printk( "Rxdwait "); */ - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - -/* printk( "Rxd " ); */ - } - } - - /* - * Check that packet is valid - */ - if ((status & (M8260_BD_LAST | - M8260_BD_FIRST_IN_FRAME | - M8260_BD_LONG | - M8260_BD_NONALIGNED | - M8260_BD_ABORT | - M8260_BD_CRC_ERROR | - M8260_BD_OVERRUN /*| - M8260_BD_CARRIER_LOST*/)) == - (M8260_BD_LAST | - M8260_BD_FIRST_IN_FRAME ) ) { - -/* printk( "RxV " ); */ - -/* - * Invalidate the buffer for this descriptor - */ - - rtems_cache_invalidate_multiple_data_lines((void *)rxBd->buffer, rxBd->length); - - m = sc->rxMbuf[rxBdIndex]; - - /* strip off HDLC CRC */ - m->m_len = m->m_pkthdr.len = rxBd->length - sizeof(uint16_t); - - hdlc_input( ifp, m ); - - /* - * Allocate a new mbuf - */ - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - sc->rxMbuf[rxBdIndex] = m; - rxBd->buffer = mtod (m, void *); - } - else { - printk( "RxErr[%04X,%d]", status, rxBd->length ); - /* - * Something went wrong with the reception - */ - if (!(status & M8260_BD_LAST)) - sc->rxNotLast++; - if (!(status & M8260_BD_FIRST_IN_FRAME)) - sc->rxNotFirst++; - - if (status & M8260_BD_LONG) - sc->rxGiant++; - if (status & M8260_BD_NONALIGNED) - sc->rxNonOctet++; - if (status & M8260_BD_ABORT) - sc->rxAbort++; - if (status & M8260_BD_CRC_ERROR) - sc->rxBadCRC++; - if (status & M8260_BD_OVERRUN) - sc->rxOverrun++; - if (status & M8260_BD_CARRIER_LOST) - sc->rxLostCarrier++; - } - - /* - * Reenable the buffer descriptor - */ - rxBd->status = (status & (M8260_BD_WRAP | M8260_BD_INTERRUPT)) | - M8260_BD_EMPTY; - - /* - * Move to next buffer descriptor - */ - if (++rxBdIndex == sc->rxBdCount) - rxBdIndex = 0; - } -} - -static void -scc_sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct m8260_hdlc_struct *sc = ifp->if_softc; - volatile m8260BufferDescriptor_t *firstTxBd, *txBd; - struct mbuf *l = NULL; - uint16_t status; - int nAdded; - - /* - * Free up buffer descriptors - */ - m8260Enet_retire_tx_bd (sc); - - /* - * Set up the transmit buffer descriptors. - * No need to pad out short packets since the - * hardware takes care of that automatically. - * No need to copy the packet to a contiguous buffer - * since the hardware is capable of scatter/gather DMA. - */ - nAdded = 0; - txBd = firstTxBd = sc->txBdBase + sc->txBdHead; - -/* - m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE); -*/ - - for (;;) { - /* - * Wait for buffer descriptor to become available. - */ - if ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - /* - * Clear old events - */ - m8260.scc3.scce = M8260_SCCE_TX | M8260_SCCE_TXE; - - /* - * Wait for buffer descriptor to become available. - * Note that the buffer descriptors are checked - * *before* * entering the wait loop -- this catches - * the possibility that a buffer descriptor became - * available between the `if' above, and the clearing - * of the event register. - * This is to catch the case where the transmitter - * stops in the middle of a frame -- and only the - * last buffer descriptor in a frame can generate - * an interrupt. - */ - m8260Enet_retire_tx_bd (sc); - while ((sc->txBdActiveCount + nAdded) == sc->txBdCount) { - rtems_event_set events; - - /* - * Unmask TX (buffer transmitted) event - */ - m8260.scc3.sccm |= (M8260_SCCE_TX | M8260_SCCE_TXE); - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - m8260Enet_retire_tx_bd (sc); - } - } - - /* - * Don't set the READY flag till the - * whole packet has been readied. - */ - status = nAdded ? M8260_BD_READY : 0; - - /* - * FIXME: Why not deal with empty mbufs at at higher level? - * The IP fragmentation routine in ip_output - * can produce packet fragments with zero length. - * I think that ip_output should be changed to get - * rid of these zero-length mbufs, but for now, - * I'll deal with them here. - */ - if (m->m_len) { - /* - * Fill in the buffer descriptor - */ - - txBd->buffer = mtod (m, void *); - txBd->length = m->m_len; - - /* - * Flush the buffer for this descriptor - */ - - rtems_cache_flush_multiple_data_lines((void *)txBd->buffer, txBd->length); - -/* throw off the header for Ethernet Emulation mode */ -/* - txBd->buffer = mtod (m, void *); - txBd->buffer += sizeof( struct ether_header ) + 2; - txBd->length = m->m_len - sizeof( struct ether_header ) - 2; -*/ - sc->txMbuf[sc->txBdHead] = m; - nAdded++; - if (++sc->txBdHead == sc->txBdCount) { - status |= M8260_BD_WRAP; - sc->txBdHead = 0; - } - l = m; - m = m->m_next; - } - else { - /* - * Just toss empty mbufs - */ - struct mbuf *n; - MFREE (m, n); - m = n; - if (l != NULL) - l->m_next = m; - } - - /* - * Set the transmit buffer status. - * Break out of the loop if this mbuf is the last in the frame. - */ - if (m == NULL) { - if (nAdded) { - status |= M8260_BD_LAST | M8260_BD_TX_CRC | M8260_BD_INTERRUPT; - txBd->status = status; - firstTxBd->status |= M8260_BD_READY; - sc->txBdActiveCount += nAdded; - } - break; - } - txBd->status = status; - txBd = sc->txBdBase + sc->txBdHead; - } -} - -/* - * Driver transmit daemon - */ -void -scc_txDaemon (void *arg) -{ - struct m8260_hdlc_struct *sc = (struct m8260_hdlc_struct *)arg; - struct ifnet *ifp = &sc->ac_if; - struct mbuf *m; - rtems_event_set events; - - for (;;) { - /* - * Wait for packet - */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, RTEMS_EVENT_ANY | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &events); - - /* - * Send packets till queue is empty - */ - for (;;) { - /* - * Get the next mbuf chain to transmit. - */ - IF_DEQUEUE(&ifp->if_snd, m); - if (!m) - break; - - scc_sendpacket (ifp, m); - - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - * Send packet (caller provides header). - */ -static void -m8260_hdlc_start (struct ifnet *ifp) -{ - struct m8260_hdlc_struct *sc = ifp->if_softc; - - rtems_bsdnet_event_send (sc->txDaemonTid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* - * Initialize and start the device - */ -static void -scc_init (void *arg) -{ - struct m8260_hdlc_struct *sc = arg; - struct ifnet *ifp = &sc->ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up SCC hardware - */ - m8260_scc_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, scc_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, scc_rxDaemon, sc); - - } - -#if 0 - /* - * Set flags appropriately - */ - if (ifp->if_flags & IFF_PROMISC) - m8260.scc3.psmr |= 0x200; - else - m8260.scc3.psmr &= ~0x200; -#endif - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - - /* - * Enable receiver and transmitter - */ - m8260.scc3.gsmr_l |= 0x30; -} - -/* - * Stop the device - */ -static void -scc_stop (struct m8260_hdlc_struct *sc) -{ - struct ifnet *ifp = &sc->ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Shut down receiver and transmitter - */ - m8260.scc3.gsmr_l &= ~0x30; -} - -/* - * Show interface statistics - */ -static void -hdlc_stats (struct m8260_hdlc_struct *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" No Carrier:%-8lu\n", sc->rxLostCarrier); - printf (" Discarded:%-8lu\n", (unsigned long)m8260.scc3p.un.hdlc.disfc); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf (" Underrun:%-8lu\n", sc->txUnderrun); - printf (" Raw output wait:%-8lu\n", sc->txRawWait); -} - -/* - * Driver ioctl handler - */ -static int -scc_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct m8260_hdlc_struct *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - hdlc_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - scc_stop (sc); - break; - - case IFF_UP: - scc_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - scc_stop (sc); - scc_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - hdlc_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an SCC driver to the system - */ -int -rtems_scc3_driver_attach (struct rtems_bsdnet_ifconfig *config) -{ - struct m8260_hdlc_struct *sc; - struct ifnet *ifp; - int mtu; - int i; - - /* - * Find a free driver - */ - for (i = 0 ; i < NIFACES ; i++) { - sc = &hdlc_driver[i]; - ifp = &sc->ac_if; - if (ifp->if_softc == NULL) - break; - } - if (i >= NIFACES) { - printf ("Too many SCC drivers.\n"); - return 0; - } - -#if 0 - /* - * Process options - */ - - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else { - sc->arpcom.ac_enaddr[0] = 0x44; - sc->arpcom.ac_enaddr[1] = 0x22; - sc->arpcom.ac_enaddr[2] = 0x33; - sc->arpcom.ac_enaddr[3] = 0x33; - sc->arpcom.ac_enaddr[4] = 0x22; - sc->arpcom.ac_enaddr[5] = 0x44; - } -#endif - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - if (config->rbuf_count) - sc->rxBdCount = config->rbuf_count; - else - sc->rxBdCount = RX_BUF_COUNT; - if (config->xbuf_count) - sc->txBdCount = config->xbuf_count; - else - sc->txBdCount = TX_BUF_COUNT * TX_BD_PER_BUF; - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = i + 1; - ifp->if_name = "eth"; - ifp->if_mtu = mtu; - ifp->if_init = scc_init; - ifp->if_ioctl = scc_ioctl; - ifp->if_start = m8260_hdlc_start; - ifp->if_output = hdlc_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | /*IFF_PROMISC |*/ IFF_NOARP; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - hdlc_ifattach (ifp); - return 1; -}; - -int -rtems_enet_driver_attach(struct rtems_bsdnet_ifconfig *config, int attaching) -{ - return rtems_scc3_driver_attach( config ); - -/* - if ((m8260.fec.mii_data & 0xffff) == 0x2000) { - return rtems_fec_driver_attach(config); - } - else { - return rtems_scc1_driver_attach(config); - } -*/ -} |