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

📄 if_fe.c

📁 很好的一个嵌入式linux平台下的bootloader
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*	 * Program the 86960 as follows:	 *	SRAM: 32KB, 100ns, byte-wide access.	 *	Transmission buffer: 4KB x 2.	 *	System bus interface: 16 bits.	 * We cannot change these values but TXBSIZE, because they	 * are hard-wired on the board.  Modifying TXBSIZE will affect	 * the driver performance.	 */	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB		| FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "ATI found" );#endif	/* Initialize 86965.  */	OUTB( sc->addr, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE );	DELAY(200);	/* Disable all interrupts.  */	OUTB( sc->addr, FE_DLCR2, 0 );	OUTB( sc->addr, FE_DLCR3, 0 );#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "end of fe_probe_ati()" );#endif	/*	 * That's all.  AT1700 occupies 32 I/O addresses, by the way.	 */	return 32;}/* * Probe and initialization for Fujitsu MBH10302 PCMCIA Ethernet interface. */static intfe_probe_mbh ( struct isa_device * isa_dev, struct fe_softc * sc ){	static struct fe_simple_probe_struct probe_table [] = {		{ FE_DLCR2, 0x70, 0x00 },		{ FE_DLCR4, 0x08, 0x00 },	    /*	{ FE_DLCR5, 0x80, 0x00 },	Does not work well.  */#if 0	/*	 * Test *vendor* part of the address for Fujitsu.	 * The test will gain reliability of probe process, but	 * it rejects clones by other vendors, or OEM product	 * supplied by resalers other than Fujitsu.	 */		{ FE_MBH10, 0xFF, 0x00 },		{ FE_MBH11, 0xFF, 0x00 },		{ FE_MBH12, 0xFF, 0x0E },#else	/*	 * We can always verify the *first* 2 bits (in Ehternet	 * bit order) are "global" and "unicast" even for	 * unknown vendors.	 */		{ FE_MBH10, 0x03, 0x00 },#endif        /* Just a gap?  Seems reliable, anyway.  */		{ 0x12, 0xFF, 0x00 },		{ 0x13, 0xFF, 0x00 },		{ 0x14, 0xFF, 0x00 },		{ 0x15, 0xFF, 0x00 },		{ 0x16, 0xFF, 0x00 },		{ 0x17, 0xFF, 0x00 },		{ 0x18, 0xFF, 0xFF },		{ 0x19, 0xFF, 0xFF },		{ 0 }	};#if 0	/*	 * We need a PCMCIA flag.	 */	if ( ( isa_dev->id_flags & FE_FLAGS_PCMCIA ) == 0 ) return ( 0 );#endif	/*	 * We need explicit IRQ and supported address.	 */	if ( isa_dev->id_irq == 0 || ( sc->addr & ~0x3E0 ) != 0 ) return ( 0 );#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "top of probe" );#endif	/*	 * See if MBH10302 is on its address.	 * I'm not sure the following probe code works.  FIXME.	 */	if ( !fe_simple_probe( sc->addr, probe_table ) ) return 0;	/* Determine the card type.  */	sc->type = FE_TYPE_MBH10302;	sc->typestr = "MBH10302 (PCMCIA)";	sc->sc_description = "Ethernet adapter: MBH10302 (PCMCIA)";	/*	 * Initialize constants in the per-line structure.	 */	/* Get our station address from EEPROM.  */	inblk( sc->addr, FE_MBH10, sc->sc_enaddr, ETHER_ADDR_LEN );	/* Make sure we got a valid station address.  */	if ( ( sc->sc_enaddr[ 0 ] & 0x03 ) != 0x00	  || ( sc->sc_enaddr[ 0 ] == 0x00	    && sc->sc_enaddr[ 1 ] == 0x00	    && sc->sc_enaddr[ 2 ] == 0x00 ) ) return 0;	/* Should find all register prototypes here.  FIXME.  */	sc->proto_dlcr4 = FE_D4_LBC_DISABLE | FE_D4_CNTRL;	sc->proto_dlcr5 = 0;	sc->proto_dlcr7 = FE_D7_BYTSWP_LH | FE_D7_IDENT_NICE;	/*	 * Program the 86960 as follows:	 *	SRAM: 32KB, 100ns, byte-wide access.	 *	Transmission buffer: 4KB x 2.	 *	System bus interface: 16 bits.	 * We cannot change these values but TXBSIZE, because they	 * are hard-wired on the board.  Modifying TXBSIZE will affect	 * the driver performance.	 */	sc->proto_dlcr6 = FE_D6_BUFSIZ_32KB | FE_D6_TXBSIZ_2x4KB		| FE_D6_BBW_BYTE | FE_D6_SBW_WORD | FE_D6_SRAM_100ns;	/* Setup hooks.  We need a special initialization procedure.  */	sc->init = fe_init_mbh;	/*	 * Minimum initialization.	 */	/* Wait for a while.  I'm not sure this is necessary.  FIXME.  */	DELAY(200);	/* Minimul initialization of 86960.  */	OUTB( sc->addr, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE );	DELAY( 200 );	/* Disable all interrupts.  */	OUTB( sc->addr, FE_DLCR2, 0 );	OUTB( sc->addr, FE_DLCR3, 0 );#if 1	/* FIXME.  */	/* Initialize system bus interface and encoder/decoder operation.  */	OUTB( sc->addr, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_DISABLE );#endif	/*	 * That's all.  MBH10302 occupies 32 I/O addresses, by the way.	 */	return 32;}/* MBH specific initialization routine.  */static voidfe_init_mbh ( struct fe_softc * sc ){	/* Probably required after hot-insertion...  */	/* Wait for a while.  I'm not sure this is necessary.  FIXME.  */	DELAY(200);	/* Minimul initialization of 86960.  */	OUTB( sc->addr, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE );	DELAY( 200 );	/* Disable all interrupts.  */	OUTB( sc->addr, FE_DLCR2, 0 );	OUTB( sc->addr, FE_DLCR3, 0 );	/* Enable master interrupt flag.  */	OUTB( sc->addr, FE_MBH0, FE_MBH0_MAGIC | FE_MBH0_INTR_ENABLE );}/* * Install interface into kernel networking data structures */intfe_attach ( struct isa_device *isa_dev ){	struct fe_softc *sc = &fe_softc[isa_dev->id_unit];	/*	 * Initialize ifnet structure	 */	sc->sc_if.if_unit     = sc->sc_unit;	sc->sc_if.if_name     = "fe";	sc->sc_if.if_init     = fe_init;	sc->sc_if.if_output   = ether_output;	sc->sc_if.if_start    = fe_start;	sc->sc_if.if_ioctl    = fe_ioctl;	sc->sc_if.if_reset    = fe_reset;	sc->sc_if.if_watchdog = fe_watchdog;	/*	 * Set default interface flags.	 */	sc->sc_if.if_flags = IFF_BROADCAST | IFF_NOTRAILERS | IFF_MULTICAST;	/*	 * Set maximum size of output queue, if it has not been set.	 * It is done here as this driver may be started after the	 * system intialization (i.e., the interface is PCMCIA.)	 *	 * I'm not sure this is really necessary, but, even if it is,	 * it should be done somewhere else, e.g., in if_attach(),	 * since it must be a common workaround for all network drivers.	 * FIXME.	 */	if ( sc->sc_if.if_snd.ifq_maxlen == 0 ) {		sc->sc_if.if_snd.ifq_maxlen = ifqmaxlen;	}#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "attach()" );#endif#if FE_SINGLE_TRANSMISSION	/* Override txb config to allocate minimum.  */	sc->proto_dlcr6 &= ~FE_D6_TXBSIZ	sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;#endif	/* Modify hardware config if it is requested.  */	if ( isa_dev->id_flags & FE_FLAGS_OVERRIDE_DLCR6 ) {		sc->proto_dlcr6 = isa_dev->id_flags & FE_FLAGS_DLCR6_VALUE;	}	/* Find TX buffer size, based on the hardware dependent proto.  */	switch ( sc->proto_dlcr6 & FE_D6_TXBSIZ ) {	  case FE_D6_TXBSIZ_2x2KB: sc->txb_size = 2048; break;	  case FE_D6_TXBSIZ_2x4KB: sc->txb_size = 4096; break;	  case FE_D6_TXBSIZ_2x8KB: sc->txb_size = 8192; break;	  default:		/* Oops, we can't work with single buffer configuration.  */#if FE_DEBUG >= 2		log( LOG_WARNING, "fe%d: strange TXBSIZ config; fixing\n",			sc->sc_unit );#endif		sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;		sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;		sc->txb_size = 2048;		break;	}	/* Attach and stop the interface.  */	if_attach( &sc->sc_if );	fe_stop( sc->sc_unit );		/* This changes the state to IDLE.  */#ifdef PROM	if_newaddr(ifp, IFT_ETHER, (caddr_t)((struct arpcom *)ifp)->ac_enaddr);#else	fe_setlinkaddr( sc );#endif	/* Print additional info when attached.  */	printf( "fe%d: address %s, type %s\n", sc->sc_unit,		ether_sprintf( sc->sc_enaddr ), sc->typestr );#if FE_DEBUG >= 3	{		int buf, txb, bbw, sbw, ram;		buf = txb = bbw = sbw = ram = -1;		switch ( sc->proto_dlcr6 & FE_D6_BUFSIZ ) {		  case FE_D6_BUFSIZ_8KB:  buf =  8; break;		  case FE_D6_BUFSIZ_16KB: buf = 16; break;		  case FE_D6_BUFSIZ_32KB: buf = 32; break;		  case FE_D6_BUFSIZ_64KB: buf = 64; break;		}		switch ( sc->proto_dlcr6 & FE_D6_TXBSIZ ) {		  case FE_D6_TXBSIZ_2x2KB: txb = 2; break;		  case FE_D6_TXBSIZ_2x4KB: txb = 4; break;		  case FE_D6_TXBSIZ_2x8KB: txb = 8; break;		}		switch ( sc->proto_dlcr6 & FE_D6_BBW ) {		  case FE_D6_BBW_BYTE: bbw =  8; break;		  case FE_D6_BBW_WORD: bbw = 16; break;		}		switch ( sc->proto_dlcr6 & FE_D6_SBW ) {		  case FE_D6_SBW_BYTE: sbw =  8; break;		  case FE_D6_SBW_WORD: sbw = 16; break;		}		switch ( sc->proto_dlcr6 & FE_D6_SRAM ) {		  case FE_D6_SRAM_100ns: ram = 100; break;		  case FE_D6_SRAM_150ns: ram = 150; break;		}		printf( "fe%d: SRAM %dKB %dbit %dns, TXB %dKBx2, %dbit I/O\n",			sc->sc_unit, buf, bbw, ram, txb, sbw );	}#endif#if NBPFILTER > 0	/* If BPF is in the kernel, call the attach for it.  */	bpfattach(&sc->bpf, &sc->sc_if, DLT_EN10MB,		  sizeof(struct ether_header));#endif	return 1;}#else /* PROM *//* * eninit(): initialise ethernet */inteninit (){    int unit = 0;    struct fe_softc *sc = &fe_softc[unit];    struct ifnet *ifp = &sc->sc_if;    int timeout;    /* check for presence */    /* config it */    ifp->if_name	= "en";    ifp->if_unit	= unit;    if (sbdethaddr (sc->sc_enaddr) < 0)      return;    log (LOG_INFO, "%s%d: ethernet address: %s\n", 	 sc->sc_if.if_name, sc->sc_if.if_unit,	 ether_sprintf (sc->sc_enaddr));    sc->addr = PHYS_TO_K1(NIC_BASE);    /* network management */    ifp->if_type	= IFT_ETHER;    ifp->if_addrlen	= 6;    ifp->if_hdrlen	= 14;    ifp->if_mtu		= ETHERMTU;    ifp->if_flags	= IFF_BROADCAST | IFF_NOTRAILERS;#ifdef DEBUG        ifp->if_flags	|= IFF_DEBUG;#endif    ifp->if_init	= fe_init;    ifp->if_output	= ether_output;		    ifp->if_start	= fe_start;		    ifp->if_ioctl	= fe_ioctl;    ifp->if_watchdog	= fe_watchdog;    ifp->if_reset	= fe_reset;    ifp->if_timer	= 0;    sc->type = FE_TYPE_FMV181;    sc->typestr = "mb86964";    /* Register values which depend on board design.  */    sc->proto_dlcr4 = FE_D4_INIT;    sc->proto_dlcr5 = FE_D5_INIT;    sc->proto_dlcr6 = FE_D6_INIT;    sc->proto_dlcr7 = FE_D7_INIT;#if FE_SINGLE_TRANSMISSION	/* Override txb config to allocate minimum.  */    sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;    sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;#endif	/* Find TX buffer size, based on the hardware dependent proto.  */    switch ( sc->proto_dlcr6 & FE_D6_TXBSIZ ) {    case FE_D6_TXBSIZ_2x2KB: sc->txb_size = 2048; break;    case FE_D6_TXBSIZ_2x4KB: sc->txb_size = 4096; break;    case FE_D6_TXBSIZ_2x8KB: sc->txb_size = 8192; break;    default:	/* Oops, we can't work with single buffer configuration.  */#if FE_DEBUG >= 2	log( LOG_WARNING, "fe%d: strange TXBSIZ config; fixing\n",	     sc->sc_unit );#endif	sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;	sc->proto_dlcr6 |=  FE_D6_TXBSIZ_2x2KB;	sc->txb_size = 2048;	break;    }    if_attach (ifp);#ifdef PROM    if_newaddr(ifp, IFT_ETHER, (caddr_t)((struct arpcom *)ifp)->ac_enaddr);#else    fe_stop( sc->sc_unit );		/* This changes the state to IDLE.  */#if defined(IP_NET) && defined(USEINTS)    sbd_setvec (IP_NET, 0, feintr, unit);#endif}#endif/* * Reset interface. */voidfe_reset ( int unit ){	/*	 * Stop interface and re-initialize.	 */	fe_stop(unit);	fe_init(unit);}/* * Stop everything on the interface. * * All buffered packets, both transmitting and receiving, * if any, will be lost by stopping the interface. */voidfe_stop ( int unit ){	struct fe_softc *sc = &fe_softc[unit];	int s;	s = splimp();#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "stop()" );#endif	/* Disable interrupts.  */	OUTB( sc->addr, FE_DLCR2, 0x00 );	OUTB( sc->addr, FE_DLCR3, 0x00 );	/* Stop interface hardware.  */	DELAY( 200 );	OUTB( sc->addr, FE_DLCR6, sc->proto_dlcr6 | FE_D6_DLC_DISABLE );	DELAY( 200 );	/* Clear all interrupt status.  */	OUTB( sc->addr, FE_DLCR0, 0xFF );	OUTB( sc->addr, FE_DLCR1, 0xFF );	/* Put the chip in stand-by mode.  */	DELAY( 200 );	OUTB( sc->addr, FE_DLCR7, sc->proto_dlcr7 | FE_D7_POWER_DOWN );	DELAY( 200 );	/* Reset transmitter variables and interface flags.  */	sc->sc_if.if_flags &= ~( IFF_OACTIVE | IFF_RUNNING );	sc->sc_if.if_timer = 0;	sc->txb_free = sc->txb_size;	sc->txb_count = 0;	sc->txb_sched = 0;#ifdef MULTICAST	/* MAR loading can be delayed.  */	sc->filter_change = 0;#endif#ifndef PROM	/* Update config status also.  */	sc->sc_dcstate = DC_IDLE;#endif	/* Call a hook.  */	if ( sc->stop ) sc->stop( sc );#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, "end of stop()" );#endif	(void) splx(s);}/* * Device timeout/watchdog routine. Entered if the device neglects to * generate an interrupt after a transmit has been started on it. */voidfe_watchdog ( int unit ){	struct fe_softc *sc = &fe_softc[unit];#if FE_DEBUG >= 1	log( LOG_ERR, "fe%d: transmission timeout (%d+%d)%s\n",		unit, sc->txb_sched, sc->txb_count,		( sc->sc_if.if_flags & IFF_UP )	? "" : " when down" );#endif#if FE_DEBUG >= 3	fe_dump( LOG_INFO, sc, NULL );#endif	/* Record how many packets are lost by this accident.  */	sc->sc_if.if_oerrors += sc->txb_sched + sc->txb_count;

⌨️ 快捷键说明

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