From 031df3914990db0336a0d386fb53558b05de467e Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 09:53:31 +0200 Subject: bsps: Move legacy network drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/i386/pc386/3c509/3c509.c | 1538 --------------------------- c/src/lib/libbsp/i386/pc386/3c509/3c509.h | 436 -------- c/src/lib/libbsp/i386/pc386/3c509/elink.c | 82 -- c/src/lib/libbsp/i386/pc386/3c509/elink.h | 49 - c/src/lib/libbsp/i386/pc386/Makefile.am | 8 +- c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c | 1310 ----------------------- c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c | 647 ----------- 7 files changed, 4 insertions(+), 4066 deletions(-) delete mode 100644 c/src/lib/libbsp/i386/pc386/3c509/3c509.c delete mode 100644 c/src/lib/libbsp/i386/pc386/3c509/3c509.h delete mode 100644 c/src/lib/libbsp/i386/pc386/3c509/elink.c delete mode 100644 c/src/lib/libbsp/i386/pc386/3c509/elink.h delete mode 100644 c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c delete mode 100644 c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c (limited to 'c/src/lib/libbsp/i386/pc386') diff --git a/c/src/lib/libbsp/i386/pc386/3c509/3c509.c b/c/src/lib/libbsp/i386/pc386/3c509/3c509.c deleted file mode 100644 index 3cf7ec5226..0000000000 --- a/c/src/lib/libbsp/i386/pc386/3c509/3c509.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* - * Ported by Rosimildo da Silva. - * ConnectTel,Inc. - * e-mail: rdasilva@connecttel.com - * - * MODULE DESCRIPTION: - * RTEMS driver for 3COM 3C509 Ethernet Card. - * The driver has been tested on PC with a single network card. - * - * - * This driver was based on the FreeBSD implementation( if_ep.c ) of the 3c5x9 - * family and on the network framework of the RTEMS network driver. - * ( WD80x3 by Eric Norum ). - * See notes below: - * - ****************************************************************************** - * Copyright (c) 1994 Herb Peyerl - * 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 Herb Peyerl. - * 4. The name of Herb Peyerl may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - * - ******************************************************************************* - * - * RTEMS driver for M68360 WD1 Ethernet - * - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -/* Local includes */ -#include "3c509.h" -#include "elink.h" - -/* #define ET_MINLEN 60 */ /* minimum message length */ - -/* - * Number of WDs supported by this driver - */ -#define NWDDRIVER 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 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 -*/ - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network 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 including CRC - */ - -/* -#define RBUF_SIZE 1520 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif -*/ - -/* network driver name */ -#define NET_DRIVER_NAME "ep" - -/* - * Per device structure. - * - * XXX Note: id_conflicts should either become an array of things we're - * specifically allowed to conflict with or be subsumed into some - * more powerful mechanism for detecting and dealing with multiple types - * of non-fatal conflict. -jkh XXX - */ -struct isa_device -{ - int id_id; /* device id */ - int id_unit; /* unit number */ - int id_iobase; /* base i/o address */ - u_int id_irq; /* interrupt request */ -}; - -struct ep_board -{ - int epb_addr; /* address of this board */ - char epb_used; /* was this entry already used for configuring ? */ - /* data from EEPROM for later use */ - u_short eth_addr[3]; /* Ethernet address */ - u_short prod_id; /* product ID */ - u_short res_cfg; /* resource configuration */ -}; - -/* - * Ethernet software status per interface. - */ -struct ep_softc -{ - struct arpcom arpcom; /* Ethernet common part */ - int ep_io_addr; /* i/o bus address */ - struct mbuf *top, *mcur; - short cur_len; - u_short ep_connectors; /* Connectors on this card. */ - u_char ep_connector; /* Configured connector. */ - int stat; /* some flags */ - struct ep_board *epb; - int unit; - - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - rtems_vector_number name; - - int acceptBroadcast; - - short tx_underrun; - short rx_no_first; - short rx_no_mbuf; - short rx_bpf_disc; - short rx_overrunf; - short rx_overrunl; -}; - -/* static unsigned long loopc; */ -static volatile unsigned long overrun; -static volatile unsigned long resend; -static struct ep_softc ep_softc[ NWDDRIVER ]; -static struct isa_device isa_dev[ NWDDRIVER ] = -{ - { 0, /* device id */ - 0, /* unit number */ - -1, /* base i/o address ??? */ - 0 /* interrupt request ??? */ - } -}; - -static u_long ep_unit; -static int ep_boards; -struct ep_board ep_board[ EP_MAX_BOARDS + 1]; -static int ep_current_tag = EP_LAST_TAG + 1; -static char *ep_conn_type[] = {"UTP", "AUI", "???", "BNC"}; - -#define ep_ftst(f) (sc->stat&(f)) -#define ep_fset(f) (sc->stat|=(f)) -#define ep_frst(f) (sc->stat&=~(f)) - -/* forward declarations for functions */ -static int ep_attach( struct ep_softc *sc ); -static int ep_isa_probe( struct isa_device *is ); -static void epinit( struct ep_softc *sc ); -static void epread( register struct ep_softc *sc ); -static void epstart( struct ifnet *ifp ); -static void epread( register struct ep_softc *sc ); -static int ep_isa_attach( struct isa_device *is ); -static int get_eeprom_data( int id_port, int offset ); -static void ep_intr( struct ep_softc *sc ); - -/* external functions */ -extern void Wait_X_ms( unsigned int timeToWait ); /* timer.c ??? */ - -/********************************************************************************** - * - * DESCRIPTION: Writes a buffer of data to the I/O port. The data is sent to the - * port as 32 bits units( 4 bytes ). - * - * RETURNS: nothing. - * - **********************************************************************************/ -static __inline void outsl( unsigned short io_addr, uint8_t *out_data, int len ) -{ - u_long *pl = ( u_long *)out_data; - while( len-- ) - { - outport_long( io_addr, *pl ); - pl++; - } -} - -/********************************************************************************** - * - * DESCRIPTION: Writes a buffer of data to the I/O port. The data is sent to the - * port as 16 bits units( 2 bytes ). - * - * RETURNS: - * - **********************************************************************************/ -static __inline void outsw( unsigned short io_addr, uint8_t *out_data, int len ) -{ - u_short *ps = ( u_short *)out_data; - while( len-- ) - { - outport_word( io_addr, *ps ); - ps++; - } -} - -/********************************************************************************** - * - * DESCRIPTION: Writes a buffer of data to the I/O port. The data is sent to the - * port as 8 bits units( 1 byte ). - * - * RETURNS: nothing - * - **********************************************************************************/ -static __inline void outsb( unsigned short io_addr, uint8_t *out_data, int len ) -{ - while( len-- ) - { - outport_byte( io_addr, *out_data ); - out_data++; - } -} - -/********************************************************************************** - * - * DESCRIPTION: Read a buffer of data from an I/O port. The data is read as 16 bits - * units or 2 bytes. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static __inline void insw( unsigned short io_addr, uint8_t *in_data, int len ) -{ - u_short *ps = ( u_short *)in_data; - while( len-- ) - { - inport_word( io_addr, *ps ); - ps++; - } -} - -/********************************************************************************** - * - * DESCRIPTION: Read a buffer of data from an I/O port. The data is read as 32 bits - * units or 4 bytes. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static __inline void insl( unsigned short io_addr, uint8_t *in_data, int len ) -{ - u_long *pl = ( u_long *)in_data; - while( len-- ) - { - inport_long( io_addr, *pl ); - pl++; - } -} - -/********************************************************************************** - * - * DESCRIPTION: Read a buffer of data from an I/O port. The data is read as 8 bits - * units or 1 bytes. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static __inline void insb( unsigned short io_addr, uint8_t *in_data, int len ) -{ - while( len-- ) - { - inport_byte( io_addr, *in_data++ ); - } -} - -/********************************************************************************** - * - * DESCRIPTION: Writes a word to the I/O port. - * - * RETURNS: nothing. - * - **********************************************************************************/ -/* - * Routine to output a word as defined in FreeBSD. - */ -static __inline void outw( unsigned short io_addr, unsigned short out_data ) -{ - outport_word( io_addr, out_data ); -} - -/********************************************************************************** - * - * DESCRIPTION: Routine to read a word as defined in FreeBSD. - * - * RETURNS: nothing - * - **********************************************************************************/ -static __inline unsigned short inw( unsigned short io_addr ) -{ - unsigned short in_data; - inport_word( io_addr, in_data ); - return in_data; -} - -/********************************************************************************** - * - * DESCRIPTION: Routine to output a word as defined in FreeBSD. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static __inline void outb( unsigned short io_addr, uint8_t out_data ) -{ - outport_byte( io_addr, out_data ); -} - -/********************************************************************************** - * - * DESCRIPTION: Routine to read a word as defined in FreeBSD. - * - * RETURNS: byte read. - * - **********************************************************************************/ -static __inline uint8_t inb( unsigned short io_addr ) -{ - uint8_t in_data; - inport_byte( io_addr, in_data ); - return in_data; -} - -/********************************************************************************** - * - * DESCRIPTION: - * We get eeprom data from the id_port given an offset into the eeprom. - * Basically; after the ID_sequence is sent to all of the cards; they enter - * the ID_CMD state where they will accept command requests. 0x80-0xbf loads - * the eeprom data. We then read the port 16 times and with every read; the - * cards check for contention (ie: if one card writes a 0 bit and another - * writes a 1 bit then the host sees a 0. At the end of the cycle; each card - * compares the data on the bus; if there is a difference then that card goes - * into ID_WAIT state again). In the meantime; one bit of data is returned in - * the AX register which is conveniently returned to us by inb(). Hence; we - * read 16 times getting one bit of data with each read. - * - * RETURNS: 16 bit word from the EEPROM - * - **********************************************************************************/ -static int get_eeprom_data( int id_port, int offset ) -{ - int i, data = 0; - outb(id_port, 0x80 + offset); - Wait_X_ms( 1 ); - for (i = 0; i < 16; i++) - data = (data << 1) | (inw(id_port) & 1); - return( data ); -} - -/********************************************************************************** - * - * DESCRIPTION: - * Driver interrupt handler. This routine is called by the RTEMS kernel when this - * interrupt is raised. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static rtems_isr ap_interrupt_handler(void *arg) -{ - struct ep_softc *sc = (struct ep_softc *)arg; - - /* de-activate any pending interrrupt, and sent and event to interrupt task - * to process all events required by this interrupt. - */ - outw( BASE + EP_COMMAND, SET_INTR_MASK ); /* disable all Ints */ - rtems_bsdnet_event_send( sc->rxDaemonTid, INTERRUPT_EVENT ); -} - -/********************************************************************************** - * - * DESCRIPTION: - * Initializes the ethernet hardware. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void _3c509_initialize_hardware (struct ep_softc *sc) -{ - rtems_status_code status; - - epinit( sc ); - - /* - * Set up interrupts - */ - printf ("3c509: IRQ with Kernel: %d\n", (int)sc->name ); - status = rtems_interrupt_handler_install( - sc->name, - "3c509", - RTEMS_INTERRUPT_UNIQUE, - ap_interrupt_handler, - sc - ); - assert(status == RTEMS_SUCCESSFUL); -} - -/********************************************************************************** - * - * DESCRIPTION: Driver interrupt daemon. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void _3c509_rxDaemon (void *arg) -{ - struct ep_softc *dp = (struct ep_softc *)&ep_softc[ 0 ]; - rtems_event_set events; - - printf ("3C509: RX Daemon is starting.\n"); - for( ;; ) - { - /* printk( "R-" ); */ - rtems_bsdnet_event_receive( INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events ); - /* printk( "R+" ); */ - ep_intr( dp ); - epstart( &dp->arpcom.ac_if ); - } - printf ("3C509: RX Daemon is finishing.\n"); -} - -/********************************************************************************** - * - * DESCRIPTION: Driver transmit daemon - * - * RETURNS: - * - **********************************************************************************/ -static void _3c509_txDaemon (void *arg) -{ - struct ep_softc *sc = (struct ep_softc *)&ep_softc[0]; - struct ifnet *ifp = &sc->arpcom.ac_if; - rtems_event_set events; - - printf ("3C509: TX Daemon is starting.\n"); - for( ;; ) - { - /* - * Wait for packet - */ - /* printk( "T-\n" ); */ - rtems_bsdnet_event_receive( START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events ); - /* printk( "T+\n" ); */ - epstart( ifp ); - while( ifp->if_flags & IFF_OACTIVE ) - epstart( ifp ); - } - printf ("3C509: TX Daemon is finishing.\n"); -} - -/********************************************************************************** - * - * DESCRIPTION: Activates the trabsmitter task... - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void _3c509_start (struct ifnet *ifp) -{ - struct ep_softc *sc = ifp->if_softc; - /* printk ("S"); */ - ifp->if_flags |= IFF_OACTIVE; - rtems_bsdnet_event_send( sc->txDaemonTid, START_TRANSMIT_EVENT ); -} - -/********************************************************************************** - * - * DESCRIPTION: Initialize and start the device - * - * RETURNS: - * - **********************************************************************************/ -static void _3c509_init (void *arg) -{ - struct ep_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - printf ("3C509: Initialization called.\n"); - if (sc->txDaemonTid == 0) { - - /* - * Set up WD hardware - */ - _3c509_initialize_hardware (sc); - printf ("3C509: starting network driver tasks..\n"); - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("APtx", 4096, _3c509_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("APrx", 4096, _3c509_rxDaemon, sc); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/********************************************************************************** - * - * DESCRIPTION: Stop the device - * - * RETURNS: - * - **********************************************************************************/ -static void _3c509_stop (struct ep_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - ifp->if_flags &= ~IFF_RUNNING; - - printf ("3C509: stop() called.\n"); - /* - * Stop the transmitter - */ - outw(BASE + EP_COMMAND, RX_DISABLE); - outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); - while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); - outw(BASE + EP_COMMAND, TX_DISABLE); - outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); - outw(BASE + EP_COMMAND, RX_RESET); - outw(BASE + EP_COMMAND, TX_RESET); - while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); - outw(BASE + EP_COMMAND, C_INTR_LATCH); - outw(BASE + EP_COMMAND, SET_RD_0_MASK); - outw(BASE + EP_COMMAND, SET_INTR_MASK); - outw(BASE + EP_COMMAND, SET_RX_FILTER); -} - -/********************************************************************************** - * - * DESCRIPTION: Show interface statistics - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void _3c509_stats (struct ep_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - printf ("3C509: stats() called.\n"); - printf("\tStat: %x\n", sc->stat); - printf("\tIpackets=%ld, Opackets=%ld\n", ifp->if_ipackets, ifp->if_opackets); - printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n", - sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf, - sc->rx_overrunl, sc->tx_underrun ); -} - -/********************************************************************************** - * - * DESCRIPTION: Driver ioctl handler - * - * RETURNS: - * - **********************************************************************************/ -static int _3c509_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct ep_softc *sc = ifp->if_softc; - int error = 0; - - printf ("3C509: ioctl() called.\n"); - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - _3c509_stop (sc); - break; - - case IFF_UP: - _3c509_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - _3c509_stop (sc); - _3c509_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - _3c509_stats( sc ); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/********************************************************************************** - * - * DESCRIPTION: - * Attaches this network driver to the system. This function is called by the network - * interface during the initialization of the system. - * - * RETURNS: - 1 - success; 0 - fail to initialize - * - **********************************************************************************/ -int rtems_3c509_driver_attach (struct rtems_bsdnet_ifconfig *config ) -{ - struct ep_softc *sc; - struct ifnet *ifp; - int mtu; - int i; - - printf ("3C509: attach() called.\n"); - - /* - * init some variables - */ - overrun = 0; - resend = 0; - ep_unit = 0; - ep_boards = 0; - - /* - * Find a free driver - */ - for (i = 0 ; i < NWDDRIVER ; i++) { - sc = &ep_softc[i]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc == NULL) - break; - } - if (i >= NWDDRIVER) - { - printf ("Too many 3C509 drivers.\n"); - return 0; - } - - /* - * Process options - */ - if( config->hardware_address ) - { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN); - } - else - { - /* set it to something ... */ - memset (sc->arpcom.ac_enaddr, 0x08,ETHER_ADDR_LEN); - } - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - if (config->irno) - sc->name = config->irno; - else - sc->name = 10; - - if (config->port) - sc->ep_io_addr = config->port; - else - sc->ep_io_addr = 0x300; - - sc->acceptBroadcast = !config->ignore_broadcast; - - printf ("3C509: isa_probe() looking for a card...\n"); - if( !ep_isa_probe( &isa_dev[ 0 ] ) ) - { - printf ("3C509: isa_probe() fail to find a board.\n"); - return 0; - } - - /* A board has been found, so proceed with the installation of the driver */ - ep_isa_attach( &isa_dev[ 0 ] ); - /* - * Set up network interface values - */ - - ifp->if_softc = sc; - ifp->if_unit = i; - ifp->if_name = NET_DRIVER_NAME; - ifp->if_mtu = mtu; - ifp->if_init = _3c509_init; - ifp->if_ioctl = _3c509_ioctl; - ifp->if_start = _3c509_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - if( ifp->if_snd.ifq_maxlen == 0 ) - { - ifp->if_snd.ifq_maxlen = ifqmaxlen; - } - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - printf ("3C509: attach() is complete.\n"); - return 1; -} - -/********************************************************************************** - * - * DESCRIPTION: - * This function looks for a 3COM card 3c5x9 in an isa bus. If a board is found, it - * returns a structure describing the caracteristics of the card. It returns zero when - * card can not be found. - * - * RETURNS: 0 - fail - could not find a card... - * <> description of the card. - * - **********************************************************************************/ -static struct ep_board *ep_look_for_board_at( struct isa_device *is ) -{ - int data, i, j, id_port = ELINK_ID_PORT; - int count = 0; - - if(ep_current_tag == (EP_LAST_TAG + 1) ) - { - /* Come here just one time */ - ep_current_tag--; - - /* Look for the ISA boards. Init and leave them actived */ - outb(id_port, 0); - outb(id_port, 0); - - elink_idseq(0xCF); - elink_reset(); - Wait_X_ms( 10 ); /* RPS: assuming delay in miliseconds */ - for (i = 0; i < EP_MAX_BOARDS; i++) - { - outb(id_port, 0); - outb(id_port, 0); - elink_idseq(0xCF); - - data = get_eeprom_data(id_port, EEPROM_MFG_ID); - if (data != MFG_ID) - break; - - /* resolve contention using the Ethernet address */ - for (j = 0; j < 3; j++) - get_eeprom_data(id_port, j); - - /* and save this address for later use */ - - for (j = 0; j < 3; j++) - ep_board[ep_boards].eth_addr[j] = get_eeprom_data(id_port, j); - - ep_board[ep_boards].res_cfg = get_eeprom_data(id_port, EEPROM_RESOURCE_CFG); - ep_board[ep_boards].prod_id = get_eeprom_data(id_port, EEPROM_PROD_ID); - ep_board[ep_boards].epb_used = 0; -#ifdef PC98 - ep_board[ep_boards].epb_addr = - (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x100 + 0x40d0; -#else - ep_board[ep_boards].epb_addr = - (get_eeprom_data(id_port, EEPROM_ADDR_CFG) & 0x1f) * 0x10 + 0x200; - if (ep_board[ep_boards].epb_addr > 0x3E0) - /* Board in EISA configuration mode */ - continue; -#endif /* PC98 */ - - outb(id_port, ep_current_tag); /* tags board */ - outb(id_port, ACTIVATE_ADAPTER_TO_CONFIG); - ep_boards++; - count++; - ep_current_tag--; - } - ep_board[ep_boards].epb_addr = 0; - if( count ) - { - printf("%d 3C5x9 board(s) on ISA found at", count); - for (j = 0; ep_board[j].epb_addr; j++) - if( ep_board[j].epb_addr <= 0x3E0 ) - printf(" 0x%x", ep_board[j].epb_addr ); - printf("\n"); - } - } - - /* we have two cases: - * - * 1. Device was configured with 'port ?' - * In this case we search for the first unused card in list - * - * 2. Device was configured with 'port xxx' - * In this case we search for the unused card with that address - * - */ - - if (IS_BASE == -1) - { /* port? */ - for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_used; i++) ; - if (ep_board[i].epb_addr == 0) - return 0; - - IS_BASE = ep_board[i].epb_addr; - ep_board[i].epb_used = 1; - return &ep_board[ i ]; - } - else - { - for (i = 0; ep_board[i].epb_addr && ep_board[i].epb_addr != IS_BASE; i++ ) ; - if (ep_board[i].epb_used || ep_board[i].epb_addr != IS_BASE) - return 0; - if (inw(IS_BASE + EP_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) - { - printf("ep%d: 3c5x9 at 0x%x in PnP mode. Disable PnP mode!\n", - is->id_unit, IS_BASE ); - } - ep_board[i].epb_used = 1; - return &ep_board[i]; - } -} - -/********************************************************************************** - * - * DESCRIPTION: - * This routine checks if there card installed on the machine. - * - * RETURNS: 0 - no card founded. - * 16 - size of the IO range for the card. - * - **********************************************************************************/ -static int ep_isa_probe( struct isa_device *is ) -{ - struct ep_softc *sc; - struct ep_board *epb; - u_short k; - - /* try to find a 3COM 3c5x9 .... */ - if( (epb = ep_look_for_board_at(is)) == 0 ) - return (0); - - sc = &ep_softc[ 0 ]; - sc->ep_io_addr = epb->epb_addr; - sc->epb = epb; - - /* - * The iobase was found and MFG_ID was 0x6d50. PROD_ID should be - * 0x9[0-f]50 (IBM-PC) - * 0x9[0-f]5[0-f] (PC-98) - */ - GO_WINDOW(0); - k = sc->epb->prod_id; -#ifdef PC98 - if ((k & 0xf0f0) != (PROD_ID & 0xf0f0)) - { -#else - if ((k & 0xf0ff) != (PROD_ID & 0xf0ff)) - { -#endif - printf("ep_isa_probe: ignoring model %04x\n", k ); -/* ep_unit--; */ - return (0); - } - k = sc->epb->res_cfg; - k >>= 12; - - /* Now we have two cases again: - * - * 1. Device was configured with 'irq?' - * In this case we use irq read from the board - * - * 2. Device was configured with 'irq xxx' - * In this case we set up the board to use specified interrupt - * - */ - - if (is->id_irq == 0) - { /* irq? */ - is->id_irq = ( k == 2 ) ? 9 : k; - } - - sc->stat = 0; /* 16 bit access */ - - /* By now, the adapter is already activated */ - - return (EP_IOSIZE); /* 16 bytes of I/O space used. */ -} - -/********************************************************************************** - * - * DESCRIPTION: - * This routine attaches this network driver and the network interface routines. - * - * RETURNS: 0 - failed to attach - * 1 - success - * - **********************************************************************************/ -static int ep_isa_attach( struct isa_device *is ) -{ - struct ep_softc *sc = &ep_softc[ 0 ]; - u_short config; - int irq; - - sc->ep_connectors = 0; - config = inw( IS_BASE + EP_W0_CONFIG_CTRL ); - if (config & IS_AUI) - { - sc->ep_connectors |= AUI; - } - if (config & IS_BNC) - { - sc->ep_connectors |= BNC; - } - if (config & IS_UTP) - { - sc->ep_connectors |= UTP; - } - if( !(sc->ep_connectors & 7) ) - printf( "no connectors!" ); - sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS; - - /* - * Write IRQ value to board - */ - - irq = is->id_irq; - /* update the interrupt line number to registered with kernel */ - sc->name = irq; - - GO_WINDOW( 0 ); - SET_IRQ( BASE, irq ); - - printf( "3C509: I/O=0x%x, IRQ=%d, CONNECTOR=%s, ", - sc->ep_io_addr, (int)sc->name,ep_conn_type[ sc->ep_connector ] ); - - ep_attach( sc ); - return 1; -} - -/********************************************************************************** - * - * DESCRIPTION: Completes the initialization/attachement of the driver. - * - * RETURNS: 0 - ok. - * - **********************************************************************************/ -static int ep_attach( struct ep_softc *sc ) -{ - u_short *p; - int i; - - /* - * Setup the station address - */ - p = (u_short *) &sc->arpcom.ac_enaddr; - GO_WINDOW(2); - printf("ADDRESS=" ); - for (i = 0; i < 3; i++) - { - p[i] = htons( sc->epb->eth_addr[i] ); - outw( BASE + EP_W2_ADDR_0 + (i * 2), ntohs( p[i] ) ); - printf("%04x ", (u_short)ntohs( p[i] ) ); - } - printf("\n" ); - - sc->rx_no_first = sc->rx_no_mbuf = - sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl = - sc->tx_underrun = 0; - - ep_fset( F_RX_FIRST ); - sc->top = sc->mcur = 0; - return 0; -} - -/********************************************************************************** - * - * DESCRIPTION: - * Initializes the card. - * The order in here seems important. Otherwise we may not receive interrupts. ?! - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void epinit( struct ep_softc *sc ) -{ - register struct ifnet *ifp = &sc->arpcom.ac_if; - int i, j; - - while( inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS ) ; - GO_WINDOW(0); - outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); - GO_WINDOW(4); - outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP); - GO_WINDOW(0); - - /* Disable the card */ - outw(BASE + EP_W0_CONFIG_CTRL, 0); - - /* Enable the card */ - outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); - - GO_WINDOW(2); - - /* Reload the ether_addr. */ - for (i = 0; i < 6; i++) - outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]); - - outw(BASE + EP_COMMAND, RX_RESET); - outw(BASE + EP_COMMAND, TX_RESET); - while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); - - /* Window 1 is operating window */ - GO_WINDOW(1); - for (i = 0; i < 31; i++) - inb(BASE + EP_W1_TX_STATUS); - - /* get rid of stray intr's */ - outw(BASE + EP_COMMAND, ACK_INTR | 0xff); - - outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS); - - outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); - - if (ifp->if_flags & IFF_PROMISC) - outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | - FIL_GROUP | FIL_BRDCST | FIL_ALL); - else - outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_GROUP | FIL_BRDCST); - - /* - * S.B. - * - * Now behavior was slightly changed: - * - * if any of flags link[0-2] is used and its connector is - * physically present the following connectors are used: - * - * link0 - AUI * highest precedence - * link1 - BNC - * link2 - UTP * lowest precedence - * - * If none of them is specified then - * connector specified in the EEPROM is used - * (if present on card or AUI if not). - * - */ - - /* Set the xcvr. */ - if (ifp->if_flags & IFF_LINK0 && sc->ep_connectors & AUI) - { - i = ACF_CONNECTOR_AUI; - } - else if (ifp->if_flags & IFF_LINK1 && sc->ep_connectors & BNC) - { - i = ACF_CONNECTOR_BNC; - } - else if (ifp->if_flags & IFF_LINK2 && sc->ep_connectors & UTP) - { - i = ACF_CONNECTOR_UTP; - } - else - { - i = sc->ep_connector; - } - GO_WINDOW(0); - j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff; - outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS)); - - switch(i) - { - case ACF_CONNECTOR_UTP: - if (sc->ep_connectors & UTP) - { - GO_WINDOW(4); - outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); - } - break; - - case ACF_CONNECTOR_BNC: - if (sc->ep_connectors & BNC) - { - outw(BASE + EP_COMMAND, START_TRANSCEIVER); - Wait_X_ms( 1 ); - } - break; - - case ACF_CONNECTOR_AUI: - /* nothing to do */ - break; - - default: - printf("ep%d: strange connector type in EEPROM: assuming AUI\n", sc->unit); - break; - } - - outw(BASE + EP_COMMAND, RX_ENABLE); - outw(BASE + EP_COMMAND, TX_ENABLE); - - ifp->if_flags |= IFF_RUNNING; - ifp->if_flags &= ~IFF_OACTIVE; /* just in case */ - - sc->rx_no_first = sc->rx_no_mbuf = - sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl = - sc->tx_underrun = 0; - - ep_fset(F_RX_FIRST); - if( sc->top ) - { - m_freem( sc->top ); - sc->top = sc->mcur = 0; - } - outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH); - outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16); - - /* - * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up - * any that we had in case we're being called from intr or somewhere - * else. - */ - - GO_WINDOW(1); -} - -static const char padmap[] = {0, 3, 2, 1}; - -/********************************************************************************** - * - * DESCRIPTION: Routine to transmit frames to the card. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void epstart( struct ifnet *ifp ) -{ - register struct ep_softc *sc = ifp->if_softc; - register u_int len; - register struct mbuf *m; - struct mbuf *top; - int pad; - - while( inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS ) - ; -startagain: - /* printk( "S-" ); */ - - /* Sneak a peek at the next packet */ - m = ifp->if_snd.ifq_head; - if (m == 0) - { - ifp->if_flags &= ~IFF_OACTIVE; - return; - } - - for( len = 0, top = m; m; m = m->m_next ) - len += m->m_len; - - pad = padmap[ len & 3 ]; - - /* - * The 3c509 automatically pads short packets to minimum ethernet length, - * but we drop packets that are too large. Perhaps we should truncate - * them instead? - */ - if( len + pad > ETHER_MAX_LEN ) - { - /* packet is obviously too large: toss it */ - ++ifp->if_oerrors; - IF_DEQUEUE( &ifp->if_snd, m ); - m_freem( m ); - goto readcheck; - } - if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) - { - /* no room in FIFO */ - outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | (len + pad + 4)); - /* make sure */ - if (inw(BASE + EP_W1_FREE_TX) < len + pad + 4) - { - ifp->if_flags |= IFF_OACTIVE; - return; - } - } - IF_DEQUEUE( &ifp->if_snd, m ); - outw(BASE + EP_W1_TX_PIO_WR_1, len); - outw(BASE + EP_W1_TX_PIO_WR_1, 0x0); /* Second dword meaningless */ - - for (top = m; m != 0; m = m->m_next) - { - if( ep_ftst(F_ACCESS_32_BITS ) ) - { - outsl( BASE + EP_W1_TX_PIO_WR_1, mtod(m, uint8_t *), m->m_len / 4 ); - if( m->m_len & 3 ) - outsb(BASE + EP_W1_TX_PIO_WR_1, mtod(m, uint8_t *) + (m->m_len & (~3)), m->m_len & 3 ); - } - else - { - outsw( BASE + EP_W1_TX_PIO_WR_1, mtod(m, uint8_t *), m->m_len / 2 ); - if( m->m_len & 1 ) - outb( BASE + EP_W1_TX_PIO_WR_1, *(mtod(m, uint8_t *) + m->m_len - 1) ); - } - } - while( pad-- ) - { - outb(BASE + EP_W1_TX_PIO_WR_1, 0); /* Padding */ - } - ifp->if_timer = 2; - ifp->if_opackets++; - m_freem(top); - -/* goto startagain; */ - /* - * Is another packet coming in? We don't want to overflow the tiny RX - * fifo. - */ -readcheck: - if( inw(BASE + EP_W1_RX_STATUS) & RX_BYTES_MASK ) - { - /* - * we check if we have packets left, in that case we prepare to come - * back later - */ - if( ifp->if_snd.ifq_head ) - { - outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8); - } - return; - } - goto startagain; -} - -/********************************************************************************** - * - * DESCRIPTION: Routine to read frames from the card. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void epread( register struct ep_softc *sc ) -{ - struct ether_header *eh; - struct mbuf *top, *mcur, *m; - struct ifnet *ifp; - int lenthisone; - - short rx_fifo2, status; - register short rx_fifo; - - ifp = &sc->arpcom.ac_if; - status = inw( BASE + EP_W1_RX_STATUS ); - -read_again: - - if (status & ERR_RX) - { - ++ifp->if_ierrors; - if( status & ERR_RX_OVERRUN ) - { - /* - * we can think the rx latency is actually greather than we - * expect - */ - if( ep_ftst(F_RX_FIRST) ) - sc->rx_overrunf++; - else - sc->rx_overrunl++; - - } - goto out; - } - rx_fifo = rx_fifo2 = status & RX_BYTES_MASK; - - if( ep_ftst( F_RX_FIRST ) ) - { - MGETHDR( m, M_DONTWAIT, MT_DATA ); - if( !m ) - goto out; - if( rx_fifo >= MINCLSIZE ) - MCLGET( m, M_DONTWAIT ); - sc->top = sc->mcur = top = m; -#define EROUND ((sizeof(struct ether_header) + 3) & ~3) -#define EOFF (EROUND - sizeof(struct ether_header)) - top->m_data += EOFF; - - /* Read what should be the header. */ - insw(BASE + EP_W1_RX_PIO_RD_1, mtod(top, uint8_t *), sizeof(struct ether_header) / 2); - top->m_len = sizeof(struct ether_header); - rx_fifo -= sizeof(struct ether_header); - sc->cur_len = rx_fifo2; - } - else - { - /* come here if we didn't have a complete packet last time */ - top = sc->top; - m = sc->mcur; - sc->cur_len += rx_fifo2; - } - - /* Reads what is left in the RX FIFO */ - while (rx_fifo > 0) - { - lenthisone = min( rx_fifo, M_TRAILINGSPACE(m) ); - if( lenthisone == 0 ) - { /* no room in this one */ - mcur = m; - MGET(m, M_WAIT, MT_DATA); - if (!m) - goto out; - if (rx_fifo >= MINCLSIZE) - MCLGET(m, M_WAIT); - m->m_len = 0; - mcur->m_next = m; - lenthisone = min(rx_fifo, M_TRAILINGSPACE(m)); - } - if( ep_ftst( F_ACCESS_32_BITS ) ) - { /* default for EISA configured cards*/ - insl( BASE + EP_W1_RX_PIO_RD_1, mtod(m, uint8_t *) + m->m_len, lenthisone / 4); - m->m_len += (lenthisone & ~3); - if (lenthisone & 3) - insb(BASE + EP_W1_RX_PIO_RD_1, mtod(m, uint8_t *) + m->m_len, lenthisone & 3); - m->m_len += (lenthisone & 3); - } - else - { - insw(BASE + EP_W1_RX_PIO_RD_1, mtod(m, uint8_t *) + m->m_len, lenthisone / 2); - m->m_len += lenthisone; - if( lenthisone & 1 ) - *(mtod(m, uint8_t *) + m->m_len - 1) = inb(BASE + EP_W1_RX_PIO_RD_1); - } - rx_fifo -= lenthisone; - } - - if( status & ERR_RX_INCOMPLETE) - { /* we haven't received the complete packet */ - sc->mcur = m; - sc->rx_no_first++; /* to know how often we come here */ - ep_frst( F_RX_FIRST ); - if( !((status = inw(BASE + EP_W1_RX_STATUS)) & ERR_RX_INCOMPLETE) ) - { - /* we see if by now, the packet has completly arrived */ - goto read_again; - } - outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_NEXT_EARLY_THRESH); - return; - } - outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); - ++ifp->if_ipackets; - ep_fset(F_RX_FIRST); - top->m_pkthdr.rcvif = &sc->arpcom.ac_if; - top->m_pkthdr.len = sc->cur_len; - - eh = mtod(top, struct ether_header *); - m_adj(top, sizeof(struct ether_header)); - ether_input(ifp, eh, top); - sc->top = 0; - while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) - ; - outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH); - return; - -out: - outw(BASE + EP_COMMAND, RX_DISCARD_TOP_PACK); - if (sc->top) - { - m_freem(sc->top); - sc->top = 0; - sc->rx_no_mbuf++; - } - ep_fset(F_RX_FIRST); - while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) ; - outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH); -} - -/********************************************************************************** - * - * DESCRIPTION: - * This routine handles interrupts. It is called from the "RX" task whenever - * the ISR post an event to the task. - * This is basically the "isr" from the FreeBSD driver. - * - * RETURNS: nothing. - * - **********************************************************************************/ -static void ep_intr( struct ep_softc *sc ) -{ - register int status; - struct ifnet *ifp; - ifp = &sc->arpcom.ac_if; - -rescan: - - /* printk( "I-" ); */ - while( ( status = inw(BASE + EP_STATUS)) & S_5_INTS ) - { - /* first acknowledge all interrupt sources */ - outw( BASE + EP_COMMAND, ACK_INTR | ( status & S_MASK ) ); - - if( status & ( S_RX_COMPLETE | S_RX_EARLY ) ) - { - epread( sc ); - continue; - } - if (status & S_TX_AVAIL) - { - /* we need ACK */ - ifp->if_timer = 0; - ifp->if_flags &= ~IFF_OACTIVE; - GO_WINDOW(1); - inw(BASE + EP_W1_FREE_TX); - epstart(ifp); - } - if (status & S_CARD_FAILURE) - { - ifp->if_timer = 0; - printf("\nep%d:\n\tStatus: %x\n", sc->unit, status); - GO_WINDOW(4); - printf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG)); - printf("\tStat: %x\n", sc->stat); - printf("\tIpackets=%ld, Opackets=%ld\n", ifp->if_ipackets, ifp->if_opackets); - printf("\tNOF=%d, NOMB=%d, BPFD=%d, RXOF=%d, RXOL=%d, TXU=%d\n", - sc->rx_no_first, sc->rx_no_mbuf, sc->rx_bpf_disc, sc->rx_overrunf, - sc->rx_overrunl, sc->tx_underrun); - - printf("ep%d: Status: %x (input buffer overflow)\n", sc->unit, status); - ++ifp->if_ierrors; - epinit(sc); - return; - } - if (status & S_TX_COMPLETE) - { - ifp->if_timer = 0; - /* we need ACK. we do it at the end */ - /* - * We need to read TX_STATUS until we get a 0 status in order to - * turn off the interrupt flag. - */ - while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) - { - if (status & TXS_SUCCES_INTR_REQ) - ; - else if( status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION ) ) - { - outw(BASE + EP_COMMAND, TX_RESET); - if (status & TXS_UNDERRUN) - { - sc->tx_underrun++; - } - else - { - if( status & TXS_JABBER ) - ; - else /* TXS_MAX_COLLISION - we shouldn't get here */ - ++ifp->if_collisions; - } - ++ifp->if_oerrors; - outw(BASE + EP_COMMAND, TX_ENABLE); - /* - * To have a tx_avail_int but giving the chance to the - * Reception - */ - if( ifp->if_snd.ifq_head ) - { - outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8); - } - } - outb( BASE + EP_W1_TX_STATUS, 0x0 ); /* pops up the next status */ - } /* while */ - ifp->if_flags &= ~IFF_OACTIVE; - GO_WINDOW(1); - inw(BASE + EP_W1_FREE_TX); - epstart( ifp ); - } /* end TX_COMPLETE */ - } - outw(BASE + EP_COMMAND, C_INTR_LATCH); /* ACK int Latch */ - if( (status = inw(BASE + EP_STATUS) ) & S_5_INTS ) - goto rescan; - - /* re-enable Ints */ - outw( BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS ); - /* printk( "I+" ); */ -} diff --git a/c/src/lib/libbsp/i386/pc386/3c509/3c509.h b/c/src/lib/libbsp/i386/pc386/3c509/3c509.h deleted file mode 100644 index 975342970a..0000000000 --- a/c/src/lib/libbsp/i386/pc386/3c509/3c509.h +++ /dev/null @@ -1,436 +0,0 @@ -/** - * @file - * - * @ingroup pc386_3c509 - * - * @brief 3C509 PC card support. - */ - -/* - * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) 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. The name - * of the author may not be used to endorse or promote products derived from - * this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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_epreg.h,v 1.4 1994/11/13 10:12:37 gibbs Exp Modified by: - * - October 2, 1994 - - Modified by: Andres Vega Garcia - - INRIA - Sophia Antipolis, France - e-mail: avega@sophia.inria.fr - finger: avega@pax.inria.fr - - */ -/* - * Promiscuous mode added and interrupt logic slightly changed - * to reduce the number of adapter failures. Transceiver select - * logic changed to use value from EEPROM. Autoconfiguration - * features added. - * Done by: - * Serge Babkin - * Chelindbank (Chelyabinsk, Russia) - * babkin@hq.icb.chel.su - */ - -/* - * Pccard support for 3C589 by: - * HAMADA Naoki - * nao@tom-yam.or.jp - */ - -/** - * @defgroup pc386_3c509 3C509 Support - * - * @ingroup i386_pc386 - * - * @brief 3C509 support. - */ - -/* -typedef unsigned short u_short; -typedef unsigned long u_long; -typedef unsigned char u_char; -*/ - -/* - * Some global constants - */ -#define F_RX_FIRST 0x1 -#define F_PROMISC 0x8 -#define F_ACCESS_32_BITS 0x100 - -#define TX_INIT_RATE 16 -#define TX_INIT_MAX_RATE 64 -#define RX_INIT_LATENCY 64 -#define RX_INIT_EARLY_THRESH 208 /* not less than MINCLSIZE */ -#define RX_NEXT_EARLY_THRESH 500 - -#define EEPROMSIZE 0x40 -#define MAX_EEPROMBUSY 1000 -#define EP_LAST_TAG 0xd7 -#define EP_MAX_BOARDS 16 -/* - * This `ID' port is a mere hack. There's currently no chance to register - * it with config's idea of the ports that are in use. - * - * "After the automatic configuration is completed, the IDS is in its initial - * state (ID-WAIT), and it monitors all write access to I/O port 01x0h, where - * 'x' is any hex digit. If a zero is written to any one of these ports, then - * that address is remembered and becomes the ID port. A second zero written - * to that port resets the ID sequence to its initial state. The IDS watches - * for the ID sequence to be written to the ID port." - * - * We prefer 0x110 over 0x100 so to not conflict with the Plaque&Pray - * ports. - */ -#define EP_ID_PORT 0x110 -#define EP_IOSIZE 16 /* 16 bytes of I/O space used. */ - -/* - * some macros to acces long named fields - */ -#define IS_BASE (is->id_iobase) -#define BASE (sc->ep_io_addr) - -/* - * Commands to read/write EEPROM trough EEPROM command register (Window 0, - * Offset 0xa) - */ -#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ -#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ -#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ -#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ - -#define EEPROM_BUSY (1<<15) -#define EEPROM_TST_MODE (1<<14) - -/* - * Some short functions, worth to let them be a macro - */ -#define is_eeprom_busy(b) (inw((b)+EP_W0_EEPROM_COMMAND)&EEPROM_BUSY) -#define GO_WINDOW(x) outw(BASE+EP_COMMAND, WINDOW_SELECT|(x)) - -/************************************************************************** - * * - * These define the EEPROM data structure. They are used in the probe - * function to verify the existence of the adapter after having sent - * the ID_Sequence. - * - * There are others but only the ones we use are defined here. - * - **************************************************************************/ - -#define EEPROM_NODE_ADDR_0 0x0 /* Word */ -#define EEPROM_NODE_ADDR_1 0x1 /* Word */ -#define EEPROM_NODE_ADDR_2 0x2 /* Word */ -#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ -#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ -#define EEPROM_ADDR_CFG 0x8 /* Base addr */ -#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ - -/************************************************************************** - * * - * These are the registers for the 3Com 3c509 and their bit patterns when * - * applicable. They have been taken out the the "EtherLink III Parallel * - * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * - * from 3com. * - * * - **************************************************************************/ - -#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a - * command reg. */ -#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status - * reg. */ -#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window - * reg. */ -/* - * Window 0 registers. Setup. - */ -/* Write */ -#define EP_W0_EEPROM_DATA 0x0c -#define EP_W0_EEPROM_COMMAND 0x0a -#define EP_W0_RESOURCE_CFG 0x08 -#define EP_W0_ADDRESS_CFG 0x06 -#define EP_W0_CONFIG_CTRL 0x04 -/* Read */ -#define EP_W0_PRODUCT_ID 0x02 -#define EP_W0_MFG_ID 0x00 - -/* - * Window 1 registers. Operating Set. - */ -/* Write */ -#define EP_W1_TX_PIO_WR_2 0x02 -#define EP_W1_TX_PIO_WR_1 0x00 -/* Read */ -#define EP_W1_FREE_TX 0x0c -#define EP_W1_TX_STATUS 0x0b /* byte */ -#define EP_W1_TIMER 0x0a /* byte */ -#define EP_W1_RX_STATUS 0x08 -#define EP_W1_RX_PIO_RD_2 0x02 -#define EP_W1_RX_PIO_RD_1 0x00 - -/* - * Window 2 registers. Station Address Setup/Read - */ -/* Read/Write */ -#define EP_W2_ADDR_5 0x05 -#define EP_W2_ADDR_4 0x04 -#define EP_W2_ADDR_3 0x03 -#define EP_W2_ADDR_2 0x02 -#define EP_W2_ADDR_1 0x01 -#define EP_W2_ADDR_0 0x00 - -/* - * Window 3 registers. FIFO Management. - */ -/* Read */ -#define EP_W3_FREE_TX 0x0c -#define EP_W3_FREE_RX 0x0a - -/* - * Window 4 registers. Diagnostics. - */ -/* Read/Write */ -#define EP_W4_MEDIA_TYPE 0x0a -#define EP_W4_CTRLR_STATUS 0x08 -#define EP_W4_NET_DIAG 0x06 -#define EP_W4_FIFO_DIAG 0x04 -#define EP_W4_HOST_DIAG 0x02 -#define EP_W4_TX_DIAG 0x00 - -/* - * Window 5 Registers. Results and Internal status. - */ -/* Read */ -#define EP_W5_READ_0_MASK 0x0c -#define EP_W5_INTR_MASK 0x0a -#define EP_W5_RX_FILTER 0x08 -#define EP_W5_RX_EARLY_THRESH 0x06 -#define EP_W5_TX_AVAIL_THRESH 0x02 -#define EP_W5_TX_START_THRESH 0x00 - -/* - * Window 6 registers. Statistics. - */ -/* Read/Write */ -#define TX_TOTAL_OK 0x0c -#define RX_TOTAL_OK 0x0a -#define TX_DEFERRALS 0x08 -#define RX_FRAMES_OK 0x07 -#define TX_FRAMES_OK 0x06 -#define RX_OVERRUNS 0x05 -#define TX_COLLISIONS 0x04 -#define TX_AFTER_1_COLLISION 0x03 -#define TX_AFTER_X_COLLISIONS 0x02 -#define TX_NO_SQE 0x01 -#define TX_CD_LOST 0x00 - -/**************************************** - * - * Register definitions. - * - ****************************************/ - -/* - * Command register. All windows. - * - * 16 bit register. - * 15-11: 5-bit code for command to be executed. - * 10-0: 11-bit arg if any. For commands with no args; - * this can be set to anything. - */ -#define GLOBAL_RESET (u_short) 0x0000 /* Wait at least 1ms - * after issuing */ -#define WINDOW_SELECT (u_short) (0x1<<11) -#define START_TRANSCEIVER (u_short) (0x2<<11) /* Read ADDR_CFG reg to - * determine whether - * this is needed. If - * so; wait 800 uSec - * before using trans- - * ceiver. */ -#define RX_DISABLE (u_short) (0x3<<11) /* state disabled on - * power-up */ -#define RX_ENABLE (u_short) (0x4<<11) -#define RX_RESET (u_short) (0x5<<11) -#define RX_DISCARD_TOP_PACK (u_short) (0x8<<11) -#define TX_ENABLE (u_short) (0x9<<11) -#define TX_DISABLE (u_short) (0xa<<11) -#define TX_RESET (u_short) (0xb<<11) -#define REQ_INTR (u_short) (0xc<<11) -#define SET_INTR_MASK (u_short) (0xe<<11) -#define SET_RD_0_MASK (u_short) (0xf<<11) -#define SET_RX_FILTER (u_short) (0x10<<11) -#define FIL_INDIVIDUAL (u_short) (0x1) -#define FIL_GROUP (u_short) (0x2) -#define FIL_BRDCST (u_short) (0x4) -#define FIL_ALL (u_short) (0x8) -#define SET_RX_EARLY_THRESH (u_short) (0x11<<11) -#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11) -#define SET_TX_START_THRESH (u_short) (0x13<<11) -#define STATS_ENABLE (u_short) (0x15<<11) -#define STATS_DISABLE (u_short) (0x16<<11) -#define STOP_TRANSCEIVER (u_short) (0x17<<11) -/* - * The following C_* acknowledge the various interrupts. Some of them don't - * do anything. See the manual. - */ -#define ACK_INTR (u_short) (0x6800) -#define C_INTR_LATCH (u_short) (ACK_INTR|0x1) -#define C_CARD_FAILURE (u_short) (ACK_INTR|0x2) -#define C_TX_COMPLETE (u_short) (ACK_INTR|0x4) -#define C_TX_AVAIL (u_short) (ACK_INTR|0x8) -#define C_RX_COMPLETE (u_short) (ACK_INTR|0x10) -#define C_RX_EARLY (u_short) (ACK_INTR|0x20) -#define C_INT_RQD (u_short) (ACK_INTR|0x40) -#define C_UPD_STATS (u_short) (ACK_INTR|0x80) -#define C_MASK (u_short) 0xFF /* mask of C_* */ - -/* - * Status register. All windows. - * - * 15-13: Window number(0-7). - * 12: Command_in_progress. - * 11: reserved. - * 10: reserved. - * 9: reserved. - * 8: reserved. - * 7: Update Statistics. - * 6: Interrupt Requested. - * 5: RX Early. - * 4: RX Complete. - * 3: TX Available. - * 2: TX Complete. - * 1: Adapter Failure. - * 0: Interrupt Latch. - */ -#define S_INTR_LATCH (u_short) (0x1) -#define S_CARD_FAILURE (u_short) (0x2) -#define S_TX_COMPLETE (u_short) (0x4) -#define S_TX_AVAIL (u_short) (0x8) -#define S_RX_COMPLETE (u_short) (0x10) -#define S_RX_EARLY (u_short) (0x20) -#define S_INT_RQD (u_short) (0x40) -#define S_UPD_STATS (u_short) (0x80) -#define S_MASK (u_short) 0xFF /* mask of S_* */ -#define S_5_INTS (S_CARD_FAILURE|S_TX_COMPLETE|\ - S_TX_AVAIL|S_RX_COMPLETE|S_RX_EARLY) -#define S_COMMAND_IN_PROGRESS (u_short) (0x1000) - -/* Address Config. Register. - * Window 0/Port 06 - */ - -#define ACF_CONNECTOR_BITS 14 -#define ACF_CONNECTOR_UTP 0 -#define ACF_CONNECTOR_AUI 1 -#define ACF_CONNECTOR_BNC 3 - -/* Resource configuration register. - * Window 0/Port 08 - * - */ - -#define SET_IRQ(base,irq) outw((base) + EP_W0_RESOURCE_CFG, \ - ((inw((base) + EP_W0_RESOURCE_CFG) & 0x0fff) | \ - ((u_short)(irq)<<12)) ) /* set IRQ i */ - -/* - * FIFO Registers. - * RX Status. Window 1/Port 08 - * - * 15: Incomplete or FIFO empty. - * 14: 1: Error in RX Packet 0: Incomplete or no error. - * 13-11: Type of error. - * 1000 = Overrun. - * 1011 = Run Packet Error. - * 1100 = Alignment Error. - * 1101 = CRC Error. - * 1001 = Oversize Packet Error (>1514 bytes) - * 0010 = Dribble Bits. - * (all other error codes, no errors.) - * - * 10-0: RX Bytes (0-1514) - */ -#define ERR_RX_INCOMPLETE (u_short) (0x1<<15) -#define ERR_RX (u_short) (0x1<<14) -#define ERR_RX_OVERRUN (u_short) (0x8<<11) -#define ERR_RX_RUN_PKT (u_short) (0xb<<11) -#define ERR_RX_ALIGN (u_short) (0xc<<11) -#define ERR_RX_CRC (u_short) (0xd<<11) -#define ERR_RX_OVERSIZE (u_short) (0x9<<11) -#define ERR_RX_DRIBBLE (u_short) (0x2<<11) - -/* - * FIFO Registers. - * TX Status. Window 1/Port 0B - * - * Reports the transmit status of a completed transmission. Writing this - * register pops the transmit completion stack. - * - * Window 1/Port 0x0b. - * - * 7: Complete - * 6: Interrupt on successful transmission requested. - * 5: Jabber Error (TP Only, TX Reset required. ) - * 4: Underrun (TX Reset required. ) - * 3: Maximum Collisions. - * 2: TX Status Overflow. - * 1-0: Undefined. - * - */ -#define TXS_COMPLETE 0x80 -#define TXS_SUCCES_INTR_REQ 0x40 -#define TXS_JABBER 0x20 -#define TXS_UNDERRUN 0x10 -#define TXS_MAX_COLLISION 0x8 -#define TXS_STATUS_OVERFLOW 0x4 - -/* - * Configuration control register. - * Window 0/Port 04 - */ -/* Read */ -#define IS_AUI (1<<13) -#define IS_BNC (1<<12) -#define IS_UTP (1<<9) -/* Write */ -#define ENABLE_DRQ_IRQ 0x0001 -#define W0_P4_CMD_RESET_ADAPTER 0x4 -#define W0_P4_CMD_ENABLE_ADAPTER 0x1 -/* - * Media type and status. - * Window 4/Port 0A - */ -#define ENABLE_UTP 0xc0 -#define DISABLE_UTP 0x0 - -/* - * Misc defines for various things. - */ -#define ACTIVATE_ADAPTER_TO_CONFIG 0xff /* to the id_port */ -#define MFG_ID 0x6d50 /* in EEPROM and W0 ADDR_CONFIG */ -#define PROD_ID 0x9150 - -#define AUI 0x1 -#define BNC 0x2 -#define UTP 0x4 - -#define RX_BYTES_MASK (u_short) (0x07ff) diff --git a/c/src/lib/libbsp/i386/pc386/3c509/elink.c b/c/src/lib/libbsp/i386/pc386/3c509/elink.c deleted file mode 100644 index ca637fb0a8..0000000000 --- a/c/src/lib/libbsp/i386/pc386/3c509/elink.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 1994 Charles Hannum. 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 Charles Hannum. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -/* - * Common code for dealing with 3COM ethernet cards. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include - -#include "elink.h" - -#include - -static void outb( unsigned short io_addr, unsigned char out_data ) -{ - outport_byte( io_addr, out_data ); -} - -/* - * Issue a `global reset' to all cards. We have to be careful to do this only - * once during autoconfig, to prevent resetting boards that have already been - * configured. - */ -void -elink_reset() -{ - static int x = 0; - - if (x == 0) { - x = 1; - outb(ELINK_ID_PORT, ELINK_RESET); - } -} - -/* - * The `ID sequence' is really just snapshots of an 8-bit CRC register as 0 - * bits are shifted in. Different board types use different polynomials. - */ -void -elink_idseq(u_char p) -{ - register int i; - register u_char c; - - c = 0xff; - for (i = 255; i; i--) { - outb(ELINK_ID_PORT, c); - if (c & 0x80) { - c <<= 1; - c ^= p; - } else - c <<= 1; - } -} diff --git a/c/src/lib/libbsp/i386/pc386/3c509/elink.h b/c/src/lib/libbsp/i386/pc386/3c509/elink.h deleted file mode 100644 index bcb13a494a..0000000000 --- a/c/src/lib/libbsp/i386/pc386/3c509/elink.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @file - * - * @ingroup pc386_3c509 - * - * @brief EtherLink definitions. - */ - -/* - * Copyright (c) 1994 Charles Hannum. 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 Charles Hannum. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -#ifdef PC98 -#define ELINK_ID_PORT 0x71d0 -#else -#define ELINK_ID_PORT 0x110 -#endif -#define ELINK_RESET 0xc0 - -#define ELINK_507_POLY 0xe7 -#define ELINK_509_POLY 0xcf - -extern void elink_reset ( void ); -extern void elink_idseq ( u_char p ); diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am index 8cd12e3430..70028f5e65 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.am +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am @@ -148,10 +148,10 @@ appstart.$(OBJEXT): appcpustart.$(OBJEXT) endif if HAS_NETWORKING -librtemsbsp_a_SOURCES += 3c509/3c509.c -librtemsbsp_a_SOURCES += 3c509/elink.c -librtemsbsp_a_SOURCES += ne2000/ne2000.c -librtemsbsp_a_SOURCES += wd8003/wd8003.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/net/3c509.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/net/elink.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/net/ne2000.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/net/wd8003.c endif librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/cache/cache.c diff --git a/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c b/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c deleted file mode 100644 index 17861405a6..0000000000 --- a/c/src/lib/libbsp/i386/pc386/ne2000/ne2000.c +++ /dev/null @@ -1,1310 +0,0 @@ -/* ne2k.c -- RTEMS NE2000 Ethernet driver. - * Written by Ian Lance Taylor, Zembu Labs. - * October, 1998. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * Both the ne2000 and the wd80x3 are based on the National Semiconductor - * 8390 chip, so there is a fair amount of overlap between the two - * drivers. It would be possible in principle to combine some code into - * a separate set of subroutines called by both. In fact, the drivers in - * both OpenBSD and Linux work this way. I didn't bother, because for - * the relatively simple drivers used by RTEMS, the overlap is not - * especially large, and any reasonable use of subroutines would lead to - * slightly less efficient code. - - * This ne2000 driver uses two transmit buffers. While one packet is - * being transmitted over the Ethernet, RTEMS will upload another. Since - * uploading a packet to the ne2000 is rather slow, I don't think there - * is any point to having more than two transmit buffers. However, the - * code does make it possible, by changing NE_TX_BUFS, although that - * would of course reduce the number of receive buffers. - * - * I suspect that the wd80x3 driver would benefit slightly from copying - * the multiple transmit buffer code. However, I have no way to test - * that. - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -/* Define this to force byte-wide data transfers with the NIC. This - is needed for boards like the TS-1325 386EX PC, which support only - an 8-bit PC/104 bus. Undefine this on a normal PC.*/ - -/* #define NE2000_BYTE_TRANSFERS */ - -/* Define this to print debugging messages with printk. */ - -/* #define DEBUG_NE2000 */ -/* #define DEBUG_NE */ - -/* We expect to be able to read a complete packet into an mbuf. */ - -#if (MCLBYTES < 1520) -# error "Driver must have MCLBYTES >= 1520" -#endif - -/* The 8390 macro definitions in wd80x3.h expect RO to be defined. */ -#define RO 0 - -/* Minimum size of Ethernet packet. */ -#define ET_MINLEN 60 - -/* The number of NE2000 devices supported by this driver. */ - -#define NNEDRIVER 1 - -/* RTEMS event number used by the interrupt handler to signal the - driver task. This must not be any of the events used by the - network task synchronization. */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* RTEMS event number used to start the transmit daemon. This must - not be the same as INTERRUPT_EVENT. */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - -/* Interrupts we want to handle from the device. */ - -#define NE_INTERRUPTS \ - (MSK_PRX | MSK_PTX | MSK_RXE | MSK_TXE | MSK_OVW | MSK_CNT) - -/* The size of a page in device memory. */ - -#define NE_PAGE_SIZE (256) - -/* The first page address in device memory. */ - -#define NE_START_PAGE (0x40) - -/* The last page address, plus 1. */ - -#define NE_STOP_PAGE (0x80) - -/* The number of pages used for a single transmit buffer. This is - 1536 bytes, enough for a full size packet. */ - -#define NE_TX_PAGES (6) - -/* The number of transmit buffers. We use two, so we can load one - packet while the other is being sent. */ - -#define NE_TX_BUFS (2) - -/* We use the first pages in memory as transmit buffers, and the - remaining ones as receive buffers. */ - -#define NE_FIRST_TX_PAGE (NE_START_PAGE) - -#define NE_FIRST_RX_PAGE (NE_FIRST_TX_PAGE + NE_TX_PAGES * NE_TX_BUFS) - -/* Data we store for each NE2000 device. */ - -struct ne_softc { - /* The bsdnet information structure. */ - struct arpcom arpcom; - - /* The interrupt request number. */ - unsigned int irno; - /* The base IO port number. */ - unsigned int port; - - /* Whether we accept broadcasts. */ - int accept_broadcasts; - - /* The thread ID of the transmit task. */ - rtems_id tx_daemon_tid; - /* The thread ID of the receive task. */ - rtems_id rx_daemon_tid; - - /* Whether we use byte-transfers with the device. */ - bool byte_transfers; - - /* The number of memory buffers which the transmit daemon has loaded - with data to be sent, but which have not yet been completely - sent. */ - int inuse; - /* The index of the next available transmit memory buffer. */ - int nextavail; - /* The index of the next transmit buffer to send. */ - int nextsend; - /* Nonzero if the device is currently transmitting a packet. */ - int transmitting; - /* The length of the data stored in each transmit buffer. */ - int sendlen[NE_TX_BUFS]; - - /* Set if we have a packet overrun while receiving. */ - int overrun; - /* Set if we should resend after an overrun. */ - int resend; - - /* Statistics. */ - struct { - /* Number of packets received. */ - unsigned long rx_packets; - /* Number of packets sent. */ - unsigned long tx_packets; - /* Number of interrupts. */ - unsigned long interrupts; - /* Number of receive acknowledgements. */ - unsigned long rx_acks; - /* Number of transmit acknowledgements. */ - unsigned long tx_acks; - /* Number of packet overruns. */ - unsigned long overruns; - /* Number of frame errors. */ - unsigned long rx_frame_errors; - /* Number of CRC errors. */ - unsigned long rx_crc_errors; - /* Number of missed packets. */ - unsigned long rx_missed_errors; - } stats; -}; - -/* The list of NE2000 devices on this system. */ - -static struct ne_softc ne_softc[NNEDRIVER]; - -/* - * receive ring descriptor - * - * The National Semiconductor DS8390 Network interface controller uses - * the following receive ring headers. The way this works is that the - * memory on the interface card is chopped up into 256 bytes blocks. - * A contiguous portion of those blocks are marked for receive packets - * by setting start and end block #'s in the NIC. For each packet that - * is put into the receive ring, one of these headers (4 bytes each) is - * tacked onto the front. The first byte is a copy of the receiver status - * register at the time the packet was received. - */ -struct ne_ring -{ - unsigned char rsr; /* receiver status */ - unsigned char next; /* pointer to next packet */ - unsigned char cnt_lo; /* bytes in packet (length + 4) */ - unsigned char cnt_hi; /* 16-bit, little-endian value */ -}; - -/* Forward declarations to avoid warnings */ - -static void ne_init_irq_handler (int irno); -static void ne_stop (struct ne_softc *sc); -static void ne_stop_hardware (struct ne_softc *sc); -static void ne_init (void *arg); -static void ne_init_hardware (struct ne_softc *sc); - -static void ne_reset(struct ne_softc *sc); -#ifdef DEBUG_NE -static void ne_dump(struct ne_softc *sc); -#endif - -/* Find the NE2000 device which is attached at a particular interrupt - vector. */ - -static struct ne_softc * -ne_device_for_irno (int irno) -{ - int i; - - for (i = 0; i < NNEDRIVER; ++i) - { - if (ne_softc[i].irno == irno - && ne_softc[i].arpcom.ac_if.if_softc != NULL) - return &ne_softc[i]; - } - - return NULL; -} - -/* Read data from an NE2000 device. Read LEN bytes at ADDR, storing - them into P. */ - -static void -ne_read_data (struct ne_softc *sc, int addr, int len, unsigned char *p) -{ - unsigned int port = sc->port; - unsigned int dport = port + DATAPORT; - - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA); - outport_byte (port + RBCR0, len); - outport_byte (port + RBCR1, len >> 8); - outport_byte (port + RSAR0, addr); - outport_byte (port + RSAR1, addr >> 8); - outport_byte (port + CMDR, MSK_PG0 | MSK_RRE | MSK_STA); - - if (sc->byte_transfers) - { - unsigned char d; - while (len > 0) - { - inport_byte(dport, d); - *p++ = d; - len--; - } - } - else /* word transfers */ - { - unsigned short d; - while (len > 1) - { - inport_word(dport, d); - *p++ = d; - *p++ = d >> 8; - len -= 2; - } - if (len) - { - inport_word(dport, d); - *p++ = d; - } - } - - outport_byte (port + ISR, MSK_RDC); -} - -/* Handle the current NE2000 status. This is called when the device - signals an interrupt. It is also called at other times while - NE2000 interrupts have been disabled. */ - -static void -ne_check_status (struct ne_softc *sc, int from_irq_handler) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - unsigned char status; - - /* It seems that we need to use a loop here, because if the NE2000 - signals an interrupt because packet transmission is complete, and - then receives a packet while interrupts are disabled, it seems to - sometimes fail to signal the interrupt for the received packet - when interrupts are reenabled. (Based on the behaviour of the - Realtek 8019AS chip). */ - - /* int count = 0; */ - while (1) - { - inport_byte (port + ISR, status); - if (status == 0) - break; - - /* ack */ - outport_byte (port + ISR, status); - -#ifdef DEBUG_NE2000 - printk ("NE2000 status 0x%x (8259 enabled: %s; mask: %x)\n", status, - i8259s_cache & (1 << sc->irno) ? "no" : "yes", - i8259s_cache); -#endif - - /* Check for incoming packet overwrite. */ - if (status & MSK_OVW) - { - ifp->if_timer = 0; -#ifdef DEBUG_NE - printk("^"); -#endif - ++sc->stats.overruns; - ne_reset(sc); - /* Reenable device interrupts. */ - if (from_irq_handler) - outport_byte(port + IMR, NE_INTERRUPTS); - return; - } - - /* Check for transmitted packet. The transmit daemon may now be - able to send another packet to the device. */ - if ((status & (MSK_PTX | MSK_TXE)) != 0) - { - ifp->if_timer = 0; - ++sc->stats.tx_acks; - --sc->inuse; - sc->transmitting = 0; - if (sc->inuse > 0 || (sc->arpcom.ac_if.if_flags & IFF_OACTIVE) != 0) - rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT); - } - - /* Check for received packet. */ - if ((status & (MSK_PRX | MSK_RXE)) != 0) - { - ++sc->stats.rx_acks; - rtems_bsdnet_event_send (sc->rx_daemon_tid, INTERRUPT_EVENT); - } - - /* Check for counter change. */ - if ((status & MSK_CNT) != 0) - { - unsigned char add; - inport_byte (port + CNTR0, add); - sc->stats.rx_frame_errors += add; - inport_byte (port + CNTR1, add); - sc->stats.rx_crc_errors += add; - inport_byte (port + CNTR2, add); - sc->stats.rx_missed_errors += add; - } - - break; - /* if (++count >= 1000) - { - printk("status: %x\n", status); - ne_reset(sc); - if (from_irq_handler) - outport_byte(port + IMR, NE_INTERRUPTS); - return; - } */ - } - - outport_byte (port + CMDR, MSK_PG0 | MSK_STA | MSK_RD2); -} - -/* Handle an NE2000 interrupt. */ - -static void -ne_interrupt_handler (rtems_irq_hdl_param cdata) -{ - rtems_vector_number v = (rtems_vector_number) cdata; - struct ne_softc *sc; - - sc = ne_device_for_irno (v); - if (sc == NULL) - return; - - ++sc->stats.interrupts; - -#ifdef DEBUG_NE - printk("!"); -#endif - ne_check_status(sc, 1); -} - -/* Turn NE2000 interrupts on. */ - -static void -ne_interrupt_on (const rtems_irq_connect_data *irq) -{ - struct ne_softc *sc; - -#ifdef DEBUG_NE - printk ("ne_interrupt_on()\n"); -#endif - sc = ne_device_for_irno (irq->name); - if (sc != NULL) - outport_byte (sc->port + IMR, NE_INTERRUPTS); -} - -/* Turn NE2000 interrupts off. See ne_interrupt_on. */ - -static void -ne_interrupt_off (const rtems_irq_connect_data *irq) -{ - struct ne_softc *sc; - -#ifdef DEBUG_NE - printk ("ne_interrupt_off()\n"); -#endif - sc = ne_device_for_irno (irq->name); - if (sc != NULL) - outport_byte (sc->port + IMR, 0); -} - -/* Initialize the NE2000 hardware. */ - -static void -ne_init_hardware (struct ne_softc *sc) -{ - unsigned int port = sc->port; - int i; - -#ifdef DEBUG_NE2000 - printk ("ne_init_hardware()\n"); -#endif - - /* Initialize registers. */ - - /* Set interface for page 0, Remote DMA complete, Stopped */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - /* Set FIFO threshold to 8, No auto-init Remote DMA, byte order=80x86 */ - /* byte-wide DMA xfers */ - if (sc->byte_transfers) - outport_byte (port + DCR, MSK_FT10 | MSK_BMS); - /* word-wide DMA xfers */ - else - outport_byte (port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS); - - /* Clear Remote Byte Count Registers */ - outport_byte (port + RBCR0, 0); - outport_byte (port + RBCR1, 0); - - /* For the moment, don't store incoming packets in memory. */ - outport_byte (port + RCR, MSK_MON); - - /* Place NIC in internal loopback mode */ - outport_byte (port + TCR, MSK_LOOP); - - /* Initialize transmit/receive (ring-buffer) Page Start */ - outport_byte (port + TPSR, NE_FIRST_TX_PAGE); - outport_byte (port + PSTART, NE_FIRST_RX_PAGE); - - /* Initialize Receiver (ring-buffer) Page Stop and Boundary */ - outport_byte (port + PSTOP, NE_STOP_PAGE); - outport_byte (port + BNRY, NE_STOP_PAGE - 1); - - /* Clear all interrupts */ - outport_byte (port + ISR, 0xff); - /* Disable all interrupts */ - outport_byte (port + IMR, 0); - - /* Program Command Register for page 1 */ - outport_byte (port + CMDR, MSK_PG1 | MSK_RD2 | MSK_STP); - - /* Set the Ethernet hardware address. */ - for (i = 0; i < ETHER_ADDR_LEN; ++i) - outport_byte (port + PAR + i, sc->arpcom.ac_enaddr[i]); - - /* Set Current Page pointer to next_packet */ - outport_byte (port + CURR, NE_FIRST_RX_PAGE); - - /* Clear the multicast address. */ - for (i = 0; i < MARsize; ++i) - outport_byte (port + MAR + i, 0); - - /* Set page 0 registers */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - /* accept broadcast + multicast */ - outport_byte (port + RCR, (sc->accept_broadcasts ? MSK_AB : 0) | MSK_AM); - - /* Start interface */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STA); - - /* Take interface out of loopback */ - outport_byte (port + TCR, 0); -} - -/* Set up interrupts. -*/ -static void -ne_init_irq_handler(int irno) -{ - rtems_irq_connect_data irq; - -#ifdef DEBUG_NE - printk("ne_init_irq_handler(%d)\n", irno); -#endif - irq.name = irno; - irq.hdl = ne_interrupt_handler; - irq.handle = (rtems_irq_hdl) irno; - irq.on = ne_interrupt_on; - irq.off = ne_interrupt_off; - irq.isOn = NULL; - - if (!BSP_install_rtems_irq_handler (&irq)) - rtems_panic ("Can't attach NE interrupt handler for irq %d\n", irno); -} - -/* The NE2000 packet receive daemon. This task is started when the - NE2000 driver is initialized. */ - -#ifdef DEBUG_NE -static int ccc = 0; /* experinent! */ -#endif - -static void -ne_rx_daemon (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - - while (1) - { - rtems_event_set events; - - /* Wait for the interrupt handler to tell us that there is a - packet ready to receive. */ - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - /* Don't let the device interrupt us now. */ - outport_byte (port + IMR, 0); - - while (1) - { - unsigned char startpage, currpage; - unsigned short len; - unsigned char next, cnt1, cnt2; - struct mbuf *m; - unsigned char *p; - int startaddr; - int toend; - struct ether_header *eh; - struct ne_ring hdr; /* ring buffer header */ - int reset; - - inport_byte (port + BNRY, startpage); - - outport_byte (port + CMDR, MSK_PG1 | MSK_RD2); - inport_byte (port + CURR, currpage); - outport_byte (port + CMDR, MSK_PG0 | MSK_RD2); - - ++startpage; - if (startpage >= NE_STOP_PAGE) - startpage = NE_FIRST_RX_PAGE; - - if (startpage == currpage) - break; - -#ifdef DEBUG_NE2000 - printk ("ne_rx_daemon: start page %x; current page %x\n", - startpage, currpage); -#endif - - reset = 0; - - /* Read the buffer header */ - startaddr = startpage * NE_PAGE_SIZE; - ne_read_data(sc, startaddr, sizeof(hdr), (unsigned char *)&hdr); - next = hdr.next; - if (next >= NE_STOP_PAGE) - next = NE_FIRST_RX_PAGE; - - /* check packet length */ - len = ( hdr.cnt_hi << 8 ) | hdr.cnt_lo; - if (currpage < startpage) - cnt1 = currpage + (NE_STOP_PAGE - NE_FIRST_RX_PAGE) - startpage; - else - cnt1 = currpage - startpage; - cnt2 = len / NE_PAGE_SIZE; - if (len % NE_PAGE_SIZE) - cnt2++; - if (cnt1 < cnt2) - { -#ifdef DEBUG_NE - printk("(%x<%x:%x)", cnt1, cnt2, len); -/* - printk("start page 0x%x; current page 0x%x\n", - startpage, currpage); - printk("cnt1 < cnt2 (0x%x, 0x%x); len 0x%x\n", - cnt1, cnt2, len); -*/ -#endif - reset = 1; - } - if (len > (ETHER_MAX_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) || - len < (ETHER_MIN_LEN - ETHER_CRC_LEN + sizeof(struct ne_ring)) || - len > MCLBYTES) - { -#ifdef DEBUG_NE - printk("(%x)", len); -/* - printk("start page 0x%x; current page 0x%x\n", - startpage, currpage); - printk("len out of range: 0x%x\n", len); - printk("stat: 0x%x, next: 0x%x\n", hdr.rsr, hdr.next); -*/ -#endif - reset = 1; - } -#ifdef DEBUG_NE - if (++ccc == 100) - { ccc = 0; reset = 1; - printk("T"); - } -#endif - - /* reset interface */ - if (reset) - { - ne_reset(sc); - goto Next; - } - - /* The first four bytes of the length are the buffer header. */ - len -= sizeof(struct ne_ring); - startaddr += sizeof(struct ne_ring); - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - - p = mtod (m, unsigned char *); - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - - toend = NE_STOP_PAGE * NE_PAGE_SIZE - startaddr; - if (toend < len) - { - ne_read_data (sc, startaddr, toend, p); - p += toend; - len -= toend; - startaddr = NE_FIRST_RX_PAGE * NE_PAGE_SIZE; - } - - if (len > 0) - ne_read_data (sc, startaddr, len, p); - - eh = mtod (m, struct ether_header *); - m->m_data += sizeof (struct ether_header); - -#ifdef DEBUG_NE - /* printk("[r%d]", ((hdr.cnt_hi<<8) + hdr.cnt_lo - sizeof(hdr))); */ - printk("<"); -#endif - ether_input (ifp, eh, m); - ++sc->stats.rx_packets; - - outport_byte (port + BNRY, next - 1); - } - - if (sc->overrun) { - outport_byte (port + ISR, MSK_OVW); - outport_byte (port + TCR, 0); - if (sc->resend) - outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA); - sc->resend = 0; - sc->overrun = 0; - } - - Next: - /* Reenable device interrupts. */ - outport_byte (port + IMR, NE_INTERRUPTS); - } -} - -/* Load an NE2000 packet onto the device. */ - -static void -ne_loadpacket (struct ne_softc *sc, struct mbuf *m) -{ - unsigned int port = sc->port; - unsigned int dport = port + DATAPORT; - struct mbuf *mhold = m; - int leftover; - unsigned char leftover_data; - int timeout; - int send_cnt = 0; - -#ifdef DEBUG_NE2000 - printk ("Uploading NE2000 packet\n"); -#endif - - /* Reset remote DMA complete flag. */ - outport_byte (port + ISR, MSK_RDC); - - /* Write out the count. */ - outport_byte (port + RBCR0, m->m_pkthdr.len); - outport_byte (port + RBCR1, m->m_pkthdr.len >> 8); - - sc->sendlen[sc->nextavail] = m->m_pkthdr.len; - - /* Tell the device which address we want to write to. */ - outport_byte (port + RSAR0, 0); - outport_byte (port + RSAR1, - NE_FIRST_TX_PAGE + (sc->nextavail * NE_TX_PAGES)); - - /* Set up the write. */ - outport_byte (port + CMDR, MSK_PG0 | MSK_RWR | MSK_STA); - - /* Transfer the mbuf chain to device memory. NE2000 devices require - that the data be transferred as words, so we need to handle odd - length mbufs. Never occurs if we force byte transfers. */ - - leftover = 0; - leftover_data = '\0'; - - for (; m != NULL; m = m->m_next) { - int len; - unsigned char *data; - - len = m->m_len; - if (len == 0) - continue; - - data = mtod (m, unsigned char *); - - if (leftover) { - unsigned char next; - - /* Data left over from previous mbuf in chain. */ - next = *data++; - --len; - outport_word (dport, leftover_data | (next << 8)); - send_cnt += 2; - leftover = 0; - } - - /* If using byte transfers, len always ends up as zero so - there are no leftovers. */ - - if (sc->byte_transfers) - while (len > 0) { - outport_byte (dport, *data++); - len--; - } - else - while (len > 1) { - outport_word (dport, data[0] | (data[1] << 8)); - data += 2; - len -= 2; - send_cnt += 2; - } - - if (len > 0) - { - leftover = 1; - leftover_data = *data++; - } - } - - if (leftover) - { - outport_word (dport, leftover_data); - send_cnt += 2; - } - -#ifdef DEBUG_NE - /* printk("{l%d|%d}", send_cnt, sc->nextavail); */ - printk("v"); -#endif - m_freem (mhold); - - /* Wait for the device to complete accepting the data, with a - limiting counter so that we don't wait too long. */ - for (timeout = 0; timeout < 100; ++timeout) - { - unsigned char status; - - inport_byte (port + ISR, status); - -#ifdef DEBUG_NE2000 - if ((status &~ MSK_RDC) != 0) - printk ("Status 0x%x while waiting for acknowledgement of uploaded packet\n", - status); -#endif - - if ((status & MSK_RDC) != 0) { - outport_byte (port + ISR, MSK_RDC); - break; - } - } - - if (timeout >= 100) - printk ("Timed out waiting for acknowledgement of uploaded NE2000 packet\n"); - - ++sc->nextavail; - if (sc->nextavail == NE_TX_BUFS) - sc->nextavail = 0; -} - -/* Tell the NE2000 to transmit a buffer whose contents we have already - loaded onto the device. */ - -static void -ne_transmit (struct ne_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - unsigned int port = sc->port; - int len; - -#ifdef DEBUG_NE2000 - printk ("Transmitting NE2000 packet\n"); -#endif - - len = sc->sendlen[sc->nextsend]; - if (len < ET_MINLEN) - len = ET_MINLEN; - outport_byte (port + TBCR0, len); - outport_byte (port + TBCR1, len >> 8); - - outport_byte (port + TPSR, NE_FIRST_TX_PAGE + (sc->nextsend * NE_TX_PAGES)); - - outport_byte (port + CMDR, MSK_PG0 | MSK_TXP | MSK_RD2 | MSK_STA); - -#ifdef DEBUG_NE - /* printk("{s%d|%d}", len, sc->nextsend); */ - printk(">"); -#endif - ++sc->nextsend; - if (sc->nextsend == NE_TX_BUFS) - sc->nextsend = 0; - - ++sc->stats.tx_packets; - - /* set watchdog timer */ - ifp->if_timer = 2; -} - -/* The NE2000 packet transmit daemon. This task is started when the - NE2000 driver is initialized. */ - -static void -ne_tx_daemon (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - unsigned int port = sc->port; - struct ifnet *ifp = &sc->arpcom.ac_if; - - while (1) { - rtems_event_set events; - - /* Wait for a packet to be ready for sending, or for there to be - room for another packet in the device memory. */ - rtems_bsdnet_event_receive (START_TRANSMIT_EVENT, - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &events); - -#ifdef DEBUG_NE2000 - printk ("ne_tx_daemon\n"); -#endif - - /* This daemon handles both uploading data onto the device and - telling the device to transmit data which has been uploaded. - These are separate tasks, because while the device is - transmitting one buffer we will upload another. */ - - /* Don't let the device interrupt us now. */ - outport_byte (port + IMR, 0); - - while (1) { - struct mbuf *m; - - /* If the device is not transmitting a packet, and we have - uploaded a packet, tell the device to transmit it. */ - if (! sc->transmitting && sc->inuse > 0) { - sc->transmitting = 1; - ne_transmit (sc); - } - - /* If we don't have any more buffers to send, quit now. */ - if (ifp->if_snd.ifq_head == NULL) { - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - - /* Allocate a buffer to load data into. If there are none - available, quit until a buffer has been transmitted. */ - if (sc->inuse >= NE_TX_BUFS) - break; - - ++sc->inuse; - - IF_DEQUEUE (&ifp->if_snd, m); - if (m == NULL) - panic ("ne_tx_daemon"); - - ne_loadpacket (sc, m); - - /* Check the device status. It may have finished transmitting - the last packet. */ - ne_check_status(sc, 0); - } - - /* Reenable device interrupts. */ - outport_byte (port + IMR, NE_INTERRUPTS); - } -} - -/* Start sending an NE2000 packet. */ - -static void -ne_start (struct ifnet *ifp) -{ - struct ne_softc *sc = ifp->if_softc; - -#ifdef DEBUG_NE - printk("S"); -#endif - /* Tell the transmit daemon to wake up and send a packet. */ - rtems_bsdnet_event_send (sc->tx_daemon_tid, START_TRANSMIT_EVENT); - ifp->if_flags |= IFF_OACTIVE; -} - -/* Initialize and start and NE2000. */ - -static void -ne_init (void *arg) -{ - struct ne_softc *sc = (struct ne_softc *) arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - -#ifdef DEBUG_NE - printk("ne_init()\n"); - ne_dump(sc); -#endif - - /* only once... */ - if (sc->tx_daemon_tid == 0) - { - sc->inuse = 0; - sc->nextavail = 0; - sc->nextsend = 0; - sc->transmitting = 0; - - ne_init_hardware (sc); - - sc->tx_daemon_tid = rtems_bsdnet_newproc ("SCtx", 4096, ne_tx_daemon, sc); - sc->rx_daemon_tid = rtems_bsdnet_newproc ("SCrx", 4096, ne_rx_daemon, sc); - - /* install rtems irq handler */ - ne_init_irq_handler(sc->irno); - } - - ifp->if_flags |= IFF_RUNNING; -} - -/* Stop an NE2000. */ - -static void -ne_stop (struct ne_softc *sc) -{ - sc->arpcom.ac_if.if_flags &= ~IFF_RUNNING; - - ne_stop_hardware(sc); - - sc->inuse = 0; - sc->nextavail = 0; - sc->nextsend = 0; - sc->transmitting = 0; - sc->overrun = 0; - sc->resend = 0; -} - -static void -ne_stop_hardware (struct ne_softc *sc) -{ - unsigned int port = sc->port; - int i; - - /* Stop everything. */ - outport_byte (port + CMDR, MSK_STP | MSK_RD2); - - /* Wait for the interface to stop, using I as a time limit. */ - for (i = 0; i < 5000; ++i) - { - unsigned char status; - - inport_byte (port + ISR, status); - if ((status & MSK_RST) != 0) - break; - } -} - -/* reinitializing interface -*/ -static void -ne_reset(struct ne_softc *sc) -{ - ne_stop(sc); - ne_init_hardware(sc); - sc->arpcom.ac_if.if_flags |= IFF_RUNNING; - sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE; -#ifdef DEBUG_NE - printk("*"); -#endif -} - -#ifdef DEBUG_NE -/* show anything about ne -*/ -static void -ne_dump(struct ne_softc *sc) -{ - int i; - printk("\nne configuration:\n"); - printk("ethernet addr:"); - for (i=0; iarpcom.ac_enaddr[i]); - printk("\n"); - printk("irq = %d\n", sc->irno); - printk("port = 0x%x\n", sc->port); - printk("accept_broadcasts = %d\n", sc->accept_broadcasts); - printk("byte_transfers = %d\n", sc->byte_transfers); -} -#endif - -/* Show NE2000 interface statistics. */ - -static void -ne_stats (struct ne_softc *sc) -{ - printf (" Received packets: %-8lu", sc->stats.rx_packets); - printf (" Transmitted packets: %-8lu\n", sc->stats.tx_packets); - printf (" Receive acks: %-8lu", sc->stats.rx_acks); - printf (" Transmit acks: %-8lu\n", sc->stats.tx_acks); - printf (" Packet overruns: %-8lu", sc->stats.overruns); - printf (" Frame errors: %-8lu\n", sc->stats.rx_frame_errors); - printf (" CRC errors: %-8lu", sc->stats.rx_crc_errors); - printf (" Missed packets: %-8lu\n", sc->stats.rx_missed_errors); - printf (" Interrupts: %-8lu\n", sc->stats.interrupts); -} - -static int ne_set_multicast_filter(struct ne_softc* sc) -{ - int i=0; - unsigned int port = sc->port; - unsigned char cmd = 0; - - /* Save CMDR settings */ - inport_byte(port + CMDR, cmd); - /* Change to page 1 */ - outport_byte(port + CMDR, cmd | MSK_PG1); - - /* Set MAR to accept _all_ multicast packets */ - for (i = 0; i < MARsize; ++i) { - outport_byte (port + MAR + i, 0xFF); - } - - /* Revert to original CMDR settings */ - outport_byte(port + CMDR, cmd); - - return 0; -} - -/* NE2000 driver ioctl handler. */ - -static int -ne_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct ne_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - error = ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - ne_stop (sc); - break; - - case IFF_UP: - ne_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - ne_stop (sc); - ne_init (sc); - break; - - default: - break; - } - break; - - case SIOCADDMULTI: - case SIOCDELMULTI: - { - struct ifreq* ifr = (struct ifreq*) data; - error = (command == SIOCADDMULTI ? - ether_addmulti(ifr, &(sc->arpcom)) : - ether_delmulti(ifr, &(sc->arpcom)) ); - /* ENETRESET indicates that driver should update its multicast filters */ - if(error == ENETRESET) { - error = ne_set_multicast_filter(sc); - } - break; - } - - case SIO_RTEMS_SHOW_STATS: - ne_stats (sc); - break; - - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Device timeout/watchdog routine. Entered if the device neglects to - * generate an interrupt after a transmit has been started on it. - */ -static void -ne_watchdog(struct ifnet *ifp) -{ - struct ne_softc *sc = ifp->if_softc; - - printk("ne2000: device timeout\n"); - ifp->if_oerrors++; - - ne_reset(sc); -} - -static void -print_byte(unsigned char b) -{ - printk("%x%x", b >> 4, b & 0x0f); -} - -/* Attach an NE2000 driver to the system. */ - -int -rtems_ne_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) -{ - int i; - struct ne_softc *sc; - struct ifnet *ifp; - int mtu; - - /* dettach ... */ - if (!attach) - return 0; - - /* Find a free driver. */ - sc = NULL; - for (i = 0; i < NNEDRIVER; ++i) { - sc = &ne_softc[i]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc == NULL) - break; - } - - if (sc == NULL) { - printf ("Too many NE2000 drivers.\n"); - return 0; - } - - memset (sc, 0, sizeof *sc); - - /* Check whether we do byte-wide or word-wide transfers. */ - -#ifdef NE2000_BYTE_TRANSFERS - sc->byte_transfers = true; -#else - sc->byte_transfers = false; -#endif - - /* Handle the options passed in by the caller. */ - - if (config->mtu != 0) - mtu = config->mtu; - else - mtu = ETHERMTU; - - if (config->irno != 0) - sc->irno = config->irno; - else { - const char* opt; - opt = bsp_cmdline_arg ("--ne2k-irq="); - if (opt) { - opt += sizeof ("--ne2k-irq=") - 1; - sc->irno = strtoul (opt, 0, 0); - } - if (sc->irno == 0) { - /* We use 5 as the default IRQ. */ - sc->irno = 5; - } - } - - if (config->port != 0) - sc->port = config->port; - else { - const char* opt; - opt = bsp_cmdline_arg ("--ne2k-port="); - if (opt) { - opt += sizeof ("--ne2k-port=") - 1; - sc->port = strtoul (opt, 0, 0); - } - if (config->port == 0) { - /* We use 0x300 as the default IO port number. */ - sc->port = 0x300; - } - } - - sc->accept_broadcasts = ! config->ignore_broadcast; - - if (config->hardware_address != NULL) - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - else - { - unsigned char prom[16]; - int ia; - - /* Read the PROM to get the Ethernet hardware address. */ - - outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - if (sc->byte_transfers) { - outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS); - } - else { - outport_byte (sc->port + DCR, MSK_FT10 | MSK_BMS | MSK_WTS); - } - - outport_byte (sc->port + RBCR0, 0); - outport_byte (sc->port + RBCR1, 0); - outport_byte (sc->port + RCR, MSK_MON); - outport_byte (sc->port + TCR, MSK_LOOP); - outport_byte (sc->port + IMR, 0); - outport_byte (sc->port + ISR, 0xff); - - ne_read_data (sc, 0, sizeof prom, prom); - - outport_byte (sc->port + CMDR, MSK_PG0 | MSK_RD2 | MSK_STP); - - for (ia = 0; ia < ETHER_ADDR_LEN; ++ia) - sc->arpcom.ac_enaddr[ia] = prom[ia * 2]; - } - - /* Set up the network interface. */ - - ifp->if_softc = sc; - ifp->if_unit = i + 1; - ifp->if_name = "ne"; - ifp->if_mtu = mtu; - ifp->if_init = ne_init; - ifp->if_ioctl = ne_ioctl; - ifp->if_watchdog = ne_watchdog; - ifp->if_start = ne_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* Attach the interface. */ - - if_attach (ifp); - ether_ifattach (ifp); - - printk("network device '%s' <", config->name); - print_byte(sc->arpcom.ac_enaddr[0]); - for (i=1; iarpcom.ac_enaddr[i]); - } - printk("> initialized on port 0x%x, irq %d\n", sc->port, sc->irno); - - return 1; -} diff --git a/c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c b/c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c deleted file mode 100644 index d10361bf2c..0000000000 --- a/c/src/lib/libbsp/i386/pc386/wd8003/wd8003.c +++ /dev/null @@ -1,647 +0,0 @@ -/* - * RTEMS driver for WD800x - * - * Based on the 68360 Network Driver by: - * W. Eric Norum - * Saskatchewan Accelerator Laboratory - * University of Saskatchewan - * Saskatoon, Saskatchewan, CANADA - * eric@skatter.usask.ca - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#include - -#include -#include -#include /* memcpy, memset */ -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#include -#include - -#include - -#define ET_MINLEN 60 /* minimum message length */ - -/* - * Number of WDs supported by this driver - */ -#define NWDDRIVER 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 15 -#define TX_BUF_COUNT 4 -#define TX_BD_PER_BUF 4 - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network 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 including CRC - */ -#define RBUF_SIZE 1520 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* - * Per-device data - */ -struct wd_softc { - struct arpcom arpcom; - struct mbuf **rxMbuf; - struct mbuf **txMbuf; - int acceptBroadcast; - int rxBdCount; - int txBdCount; - int txBdHead; - int txBdTail; - int txBdActiveCount; - rtems_id rxDaemonTid; - rtems_id txDaemonTid; - rtems_vector_number name; - - unsigned int port; - unsigned char *base; - unsigned long bpar; - - /* - * Statistics - */ - unsigned long rxInterrupts; - unsigned long rxNotFirst; - unsigned long rxNotLast; - unsigned long rxGiant; - unsigned long rxNonOctet; - unsigned long rxRunt; - unsigned long rxBadCRC; - unsigned long rxOverrun; - unsigned long rxCollision; - - unsigned long txInterrupts; - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - unsigned long txLostCarrier; - unsigned long txRawWait; -}; - -#define RO 0x10 - -#define SHATOT (8*1024) /* size of shared memory */ -#define SHAPAGE 256 /* shared memory information */ -#define MAXSIZ 1536 /*(MAXBUF - MESSH_SZ)*/ -#define OUTPAGE ((SHATOT-(MAXSIZ+SHAPAGE-1))/SHAPAGE) - -static volatile unsigned long overrun; -static volatile unsigned long resend; -static struct wd_softc wd_softc[NWDDRIVER]; - -/* - * WD interrupt handler - */ -static void -wd8003Enet_interrupt_handler (void * unused) -{ - unsigned int tport; - unsigned char status, status2; - - tport = wd_softc[0].port ; - - /* - * Read status - */ - inport_byte(tport+ISR, status); - outport_byte(tport+IMR, 0x00); - - /* - * Ring overwrite - */ - - if (status & MSK_OVW){ - outport_byte(tport+CMDR, MSK_STP + MSK_RD2); /* stop 8390 */ - Wait_X_ms(2); - outport_byte(tport+RBCR0, 0); /* clear byte count */ - outport_byte(tport+RBCR1, 0); - inport_byte(tport+ISR, status2); - status |= (status2 & (MSK_PTX+MSK_TXE)) ; /* TX status */ - outport_byte(tport+TCR, MSK_LOOP); /* loopback mode */ - outport_byte(tport+CMDR, MSK_STA + MSK_RD2); /* start */ - overrun = 1 ; - if ((status & (MSK_PTX+MSK_TXE)) == 0) - resend = 1; - } - - /* - * Frame received? - */ - if (status & (MSK_PRX+MSK_RXE)) { - outport_byte(tport+ISR, status & (MSK_PRX+MSK_RXE)); - wd_softc[0].rxInterrupts++; - rtems_bsdnet_event_send (wd_softc[0].rxDaemonTid, INTERRUPT_EVENT); - } - -} - -/* - * Initialize the ethernet hardware - */ -static void -wd8003Enet_initialize_hardware (struct wd_softc *sc) -{ - int i1, ultra; - char cc1, cc2; - unsigned char temp; - rtems_status_code status; - unsigned int tport; - unsigned char *hwaddr; - - tport = sc->port; - - /* address from board ROM */ - inport_byte(tport+0x04, temp); - outport_byte(tport+0x04, temp & 0x7f); - - hwaddr = sc->arpcom.ac_enaddr; - for (i1=cc2=0; i1<8; i1++) { - inport_byte(tport + ADDROM + i1, cc1); - cc2 += cc1; - if (i1 < 6) - hwaddr[i1] = cc1; - } - - inport_byte(tport+0x04, temp); - outport_byte(tport+0x04, temp | 0x80); /* alternate registers */ - outport_byte(tport+W83CREG, MSK_RESET); /* reset board, set buffer */ - outport_byte(tport+W83CREG, 0); - outport_byte(tport+W83CREG, MSK_ENASH + (int)((sc->bpar>>13)&0x3f)); - - outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); - cc1 = MSK_BMS + MSK_FT10; /* configure 8 or 16 bits */ - - inport_byte(tport+0x07, temp) ; - - ultra = ((temp & 0xf0) == 0x20 || (temp & 0xf0) == 0x40); - if (ultra) - cc1 = MSK_WTS + MSK_BMS + MSK_FT10; - outport_byte(tport+DCR, cc1); - outport_byte(tport+RBCR0, 0); - outport_byte(tport+RBCR1, 0); - outport_byte(tport+RCR, MSK_MON); /* disable the rxer */ - outport_byte(tport+TCR, 0); /* normal operation */ - outport_byte(tport+PSTOP, OUTPAGE); /* init PSTOP */ - outport_byte(tport+PSTART, 0); /* init PSTART */ - outport_byte(tport+BNRY, -1); /* init BNRY */ - outport_byte(tport+ISR, -1); /* clear IR's */ - outport_byte(tport+IMR, 0x15); /* enable interrupt */ - - outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); - - for (i1=0; i1<6; i1++) /* initial physical addr */ - outport_byte(tport+PAR+i1, hwaddr[i1]); - - for (i1=0; i1name, - "wd8003", - RTEMS_INTERRUPT_UNIQUE, - wd8003Enet_interrupt_handler, - NULL - ); - assert(status == RTEMS_SUCCESSFUL); -} - -static void -wd_rxDaemon (void *arg) -{ - unsigned int tport; - struct ether_header *eh; - struct wd_softc *dp = (struct wd_softc *)&wd_softc[0]; - struct ifnet *ifp = &dp->arpcom.ac_if; - struct mbuf *m; - unsigned int i2; - unsigned int len; - volatile unsigned char start, next, current; - unsigned char *shp, *temp; - unsigned short *real_short_ptr; - rtems_event_set events; - - tport = wd_softc[0].port ; - - for (;;){ - - rtems_bsdnet_event_receive (INTERRUPT_EVENT, - RTEMS_WAIT|RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, - &events); - - for (;;){ - inport_byte(tport+BNRY, start); - - outport_byte(tport+CMDR, MSK_PG1 + MSK_RD2); - inport_byte(tport+CURR, current); - outport_byte(tport+CMDR, MSK_PG0 + MSK_RD2); - - start += 1; - if (start >= OUTPAGE){ - start = 0; - } - - if (current == start) - break; - - /* real_short_ptr avoids cast on lvalue which gcc no longer allows */ - shp = dp->base + 1 + (SHAPAGE * start); - next = *shp++; - real_short_ptr = (unsigned short *)shp; - len = *(real_short_ptr)++ - 4; - - if (next >= OUTPAGE){ - next = 0; - } - - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - m->m_pkthdr.rcvif = ifp; - - temp = (unsigned char *) m->m_data; - m->m_len = m->m_pkthdr.len = len - sizeof(struct ether_header); - - if ((i2 = (OUTPAGE - start) * SHAPAGE - 4) < len){ - memcpy(temp, shp, i2); - len -= i2; - temp += i2; - shp = dp->base; - } - memcpy(temp, shp, len); - - eh = mtod (m, struct ether_header *); - m->m_data += sizeof(struct ether_header); - ether_input (ifp, eh, m); - - outport_byte(tport+BNRY, next-1); - } - - /* - * Ring overwrite - */ - if (overrun){ - outport_byte(tport+ISR, MSK_OVW); /* reset IR */ - outport_byte(tport+TCR, 0); /* out of loopback */ - if (resend == 1) - outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); /* resend */ - resend = 0; - overrun = 0; - } - - outport_byte(tport+IMR, 0x15); /* re-enable IT rx */ - } -} - -static void -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct wd_softc *dp = ifp->if_softc; - struct mbuf *n; - unsigned int len, tport; - uint8_t *shp, txReady; - - tport = dp->port; - - /* - * Waiting for Transmitter ready - */ - inport_byte(tport+CMDR, txReady); - while(txReady & MSK_TXP) - inport_byte(tport+CMDR, txReady); - - len = 0; - shp = dp->base + (SHAPAGE * OUTPAGE); - - n = m; - - for (;;){ - len += m->m_len; - memcpy(shp, (char *)m->m_data, m->m_len); - shp += m->m_len ; - if ((m = m->m_next) == NULL) - break; - } - - m_freem(n); - - if (len < ET_MINLEN) len = ET_MINLEN; - outport_byte(tport+TBCR0, len); - outport_byte(tport+TBCR1, (len >> 8) ); - outport_byte(tport+TPSR, OUTPAGE); - outport_byte(tport+CMDR, MSK_TXP + MSK_RD2); -} - -/* - * Driver transmit daemon - */ -static void -wd_txDaemon (void *arg) -{ - struct wd_softc *sc = (struct wd_softc *)arg; - struct ifnet *ifp = &sc->arpcom.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; - sendpacket (ifp, m); - } - ifp->if_flags &= ~IFF_OACTIVE; - } -} - -/* - * Send packet (caller provides header). - */ -static void -wd_start (struct ifnet *ifp) -{ - struct wd_softc *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 -wd_init (void *arg) -{ - struct wd_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - - if (sc->txDaemonTid == 0) { - - /* - * Set up WD hardware - */ - wd8003Enet_initialize_hardware (sc); - - /* - * Start driver tasks - */ - sc->txDaemonTid = rtems_bsdnet_newproc ("SCtx", 4096, wd_txDaemon, sc); - sc->rxDaemonTid = rtems_bsdnet_newproc ("SCrx", 4096, wd_rxDaemon, sc); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; - -} - -/* - * Stop the device - */ -static void -wd_stop (struct wd_softc *sc) -{ - unsigned int tport; - unsigned char temp; - struct ifnet *ifp = &sc->arpcom.ac_if; - - ifp->if_flags &= ~IFF_RUNNING; - - /* - * Stop the transmitter - */ - tport=wd_softc[0].port ; - inport_byte(tport+0x04,temp); - outport_byte(tport+0x04, temp & 0x7f); - outport_byte(tport + CMDR, MSK_STP + MSK_RD2); - -} - -/* - * Show interface statistics - */ -static void -wd_stats (struct wd_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Not First:%-8lu", sc->rxNotFirst); - printf (" Not Last:%-8lu\n", sc->rxNotLast); - printf (" Giant:%-8lu", sc->rxGiant); - printf (" Runt:%-8lu", sc->rxRunt); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Collision:%-8lu\n", sc->rxCollision); - - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Deferred:%-8lu", sc->txDeferred); - printf (" Missed Hearbeat:%-8lu\n", sc->txHeartbeat); - printf (" No Carrier:%-8lu", sc->txLostCarrier); - printf ("Retransmit Limit:%-8lu", sc->txRetryLimit); - printf (" Late Collision:%-8lu\n", sc->txLateCollision); - printf (" Underrun:%-8lu", sc->txUnderrun); - printf (" Raw output wait:%-8lu\n", sc->txRawWait); -} - -/* - * Driver ioctl handler - */ -static int -wd_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct wd_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) { - case IFF_RUNNING: - wd_stop (sc); - break; - - case IFF_UP: - wd_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - wd_stop (sc); - wd_init (sc); - break; - - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - wd_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - return error; -} - -/* - * Attach an WD driver to the system - */ -int -rtems_wd_driver_attach (struct rtems_bsdnet_ifconfig *config, int attach) -{ - struct wd_softc *sc; - struct ifnet *ifp; - int mtu; - int i; - - /* - * Find a free driver - */ - for (i = 0 ; i < NWDDRIVER ; i++) { - sc = &wd_softc[i]; - ifp = &sc->arpcom.ac_if; - if (ifp->if_softc == NULL) - break; - } - if (i >= NWDDRIVER) { - printf ("Too many WD drivers.\n"); - return 0; - } - - /* - * Process options - */ - if (config->hardware_address) { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - } - else { - memset (sc->arpcom.ac_enaddr, 0x08,ETHER_ADDR_LEN); - } - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - if (config->irno) - sc->name = config->irno; - else - sc->name = 5; - - if (config->port) - sc->port = config->port; - else - sc->port = 0x240; - - if (config->bpar) { - sc->bpar = config->bpar; - sc->base = (unsigned char*) config->bpar; - } - else { - sc->bpar = 0xD0000; - sc->base = (unsigned char*) 0xD0000; - } - - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = i + 1; - ifp->if_name = "wd"; - ifp->if_mtu = mtu; - ifp->if_init = wd_init; - ifp->if_ioctl = wd_ioctl; - ifp->if_start = wd_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * init some variables - */ - overrun = 0; - resend = 0; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - return 1; -}; -- cgit v1.2.3