⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 3c509.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
/********************************************************************************** * $Header: /usr1/CVS/rtems/c/src/lib/libbsp/i386/pc386/3c509/3c509.c,v 1.2 1999/12/13 21:21:31 joel Exp $ * * 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 <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. 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 ******************************************************************************* *  * * MODIFICATION/HISTORY: * $Log: 3c509.c,v $ * Revision 1.2  1999/12/13 21:21:31  joel * Warning removal patch from Philip A. Prindeville <philipp@zembu.com>. * * Revision 1.1  1999/05/14 16:23:42  joel * Added 3COM 3C509 driver from Rosimildo DaSilva <rdasilva@connecttel.com>. * * **********************************************************************************/#include <bsp.h>#include <stdio.h>#include <stdarg.h>#include <rtems/error.h>#include <rtems/rtems_bsdnet.h>#include <sys/param.h>#include <sys/mbuf.h>#include <sys/socket.h>#include <sys/sockio.h>#include <sys/libkern.h>#include <net/if.h>#include <netinet/in.h>#include <netinet/if_ether.h>#include <irq.h>/* 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_irq_connect_data   irqInfo;    rtems_id		     	 rxDaemonTid;    rtems_id		     	 txDaemonTid;    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, unsigned char *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, unsigned char *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, unsigned char *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, unsigned char *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, unsigned char *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, unsigned char *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. * **********************************************************************************/void __inline outb( unsigned short io_addr, unsigned char out_data ){  outport_byte( io_addr, out_data );}/********************************************************************************** *  * DESCRIPTION: Routine to read a word as defined in FreeBSD. * * RETURNS: byte read. * **********************************************************************************/static __inline unsigned char inb( unsigned short io_addr ){  unsigned char 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: Waits until the EEPROM of the card is ready to be accessed. * * RETURNS: 0 - not ready; 1 - ok * **********************************************************************************/static int eeprom_rdy( struct ep_softc *sc ){    int i;    for (i = 0; is_eeprom_busy(BASE) && i < MAX_EEPROMBUSY; i++)	    continue;    if (i >= MAX_EEPROMBUSY)     {	   printf("ep%d: eeprom failed to come ready.\n", sc->unit);	   return (0);    }    return (1);}/********************************************************************************** *  * DESCRIPTION: * get_e: gets a 16 bits word from the EEPROM.  * We must have set the window before call this routine. * * RETURNS: data from EEPROM * **********************************************************************************/u_short get_e(  struct ep_softc *sc, int offset ){    if( !eeprom_rdy(sc) )	   return (0xffff);    outw(BASE + EP_W0_EEPROM_COMMAND, EEPROM_CMD_RD | offset );    if( !eeprom_rdy(sc) )	   return( 0xffff );    return( inw( BASE + EP_W0_EEPROM_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( rtems_vector_number v ){  struct ep_softc *sc = (struct ep_softc *)&ep_softc[ 0 ];  /* 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_event_send( sc->rxDaemonTid, INTERRUPT_EVENT );    }/********************************************************************************** *  * DESCRIPTION: * * RETURNS: * **********************************************************************************/static void nopOn(const rtems_irq_connect_data* notUsed){  /* does nothing */}/********************************************************************************** *  * DESCRIPTION: * * RETURNS: * **********************************************************************************/static int _3c509_IsOn(const rtems_irq_connect_data* irq){  return BSP_irq_enabled_at_i8259s (irq->name);}/********************************************************************************** *  * DESCRIPTION: * Initializes the ethernet hardware. * * RETURNS: nothing. * **********************************************************************************/static void _3c509_initialize_hardware (struct ep_softc *sc){  rtems_status_code st;  epinit( sc );    /*   * Set up interrupts    */  sc->irqInfo.hdl = ( rtems_irq_hdl )ap_interrupt_handler;  sc->irqInfo.on  = nopOn;  sc->irqInfo.off = nopOn;  sc->irqInfo.isOn = _3c509_IsOn;    printf ("3c509: IRQ with Kernel: %d\n", sc->irqInfo.name );  st = BSP_install_rtems_irq_handler( &sc->irqInfo );  if( !st )  {    rtems_panic ("Can't attach WD interrupt handler for irq %d\n", sc->irqInfo.name );  }}/********************************************************************************** *  * DESCRIPTION: Driver interrupt daemon. * * RETURNS: nothing.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -