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

📄 3c509.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 3 页
字号:
 * **********************************************************************************/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_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, int 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->irqInfo.name = config->irno;	else		sc->irqInfo.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->irqInfo.name = irq;    GO_WINDOW( 0 );    SET_IRQ( BASE, irq );    printf( "3C509: I/O=0x%x, IRQ=%d, CONNECTOR=%s, ",  	    sc->ep_io_addr, sc->irqInfo.name,ep_conn_type[ sc->ep_connector ] );    ep_attach( sc );    return 1;}/********************************************************************************** * 

⌨️ 快捷键说明

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