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

📄 if_tx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		else sc->sc_if.if_oerrors++;		sc->sc_if.if_collisions += (status >> 8) & 0x1F;#if defined(EPIC_DEBUG)		if( (status & 0x1001) == 0x1001 ) 			dprintf((EPIC_FORMAT ": frame not transmitted due collisions\n",EPIC_ARGS(sc)));#endif	}	if( sc->pending_txs < TX_RING_SIZE ) 		sc->sc_if.if_flags &= ~IFF_OACTIVE;}/* * Interrupt function * * splimp() assumed to be done  */static EPIC_INTR_RET_TYPEepic_intr (    void *arg){    epic_softc_t * sc = (epic_softc_t *) arg;    int status,i=4;#if defined(__OpenBSD__)    int claimed = 0;#endif    while( i-- && ((status = CSR_READ_4(sc, INTSTAT)) & INTSTAT_INT_ACTV) ){#if defined(__OpenBSD__)	claimed = 1;#endif	CSR_WRITE_4( sc, INTSTAT, status );	if( status & (INTSTAT_RQE|INTSTAT_RCC|INTSTAT_OVW) ) {            epic_rx_done( sc );            if( status & (INTSTAT_RQE|INTSTAT_OVW) ){#if defined(EPIC_DEBUG)                if( status & INTSTAT_OVW )                     printf(EPIC_FORMAT ": RX buffer overflow\n",EPIC_ARGS(sc));                if( status & INTSTAT_RQE )                     printf(EPIC_FORMAT ": RX FIFO overflow\n",EPIC_ARGS(sc));                if( sc->sc_if.if_flags & IFF_DEBUG )                     epic_dump_state(sc);#endif                if( !(CSR_READ_4( sc, COMMAND ) & COMMAND_RXQUEUED) )                    CSR_WRITE_4( sc, COMMAND, COMMAND_RXQUEUED );                sc->sc_if.if_ierrors++;            }        }        if( status & (INTSTAT_TXC|INTSTAT_TCC|INTSTAT_TQE) ) {            epic_tx_done( sc );	    if(!(sc->sc_if.if_flags & IFF_OACTIVE) &&		sc->sc_if.if_snd.ifq_head )		    epic_ifstart( &sc->sc_if );	}        if( (status & INTSTAT_GP2) && (QS6612_OUI == sc->phyid) ) {	    u_int32_t phystatus = PHY_READ_2( sc, QS6612_INTSTAT );	    if( phystatus & INTSTAT_AN_COMPLETE ) {		u_int32_t bmcr;		if( epic_autoneg(sc) == EPIC_FULL_DUPLEX ) {		    dprintf((EPIC_FORMAT ": going fullduplex\n",EPIC_ARGS(sc)));		    bmcr = BMCR_FULL_DUPLEX | PHY_READ_2( sc, DP83840_BMCR );		    sc->txcon |= TXCON_FULL_DUPLEX;		} else {		    /* Default to half-duplex */		    dprintf((EPIC_FORMAT ": going halfduplex\n",EPIC_ARGS(sc)));		    bmcr = ~BMCR_FULL_DUPLEX & PHY_READ_2( sc, DP83840_BMCR );		    sc->txcon &= ~TXCON_FULL_DUPLEX;		}		/* There is apparently QS6612 chip bug: */		/* BMCR_FULL_DUPLEX flag is not updated by */		/* autonegotiation process, so update it by hands */		/* so we can rely on it in epic_ifmedia_status() */		PHY_WRITE_2( sc, DP83840_BMCR, bmcr );		epic_stop_activity(sc);		epic_set_tx_mode(sc);		epic_start_activity(sc);	    }	    PHY_READ_2(sc, DP83840_BMSR);	    if( !(PHY_READ_2(sc, DP83840_BMSR) & BMSR_LINK_STATUS) ) {		dprintf((EPIC_FORMAT ": WARNING! link down\n",EPIC_ARGS(sc)));		sc->flags |= EPIC_LINK_DOWN;	    } else {    		dprintf((EPIC_FORMAT ": link up\n",EPIC_ARGS(sc)));		sc->flags &= ~EPIC_LINK_DOWN;	    }	    /* We should clear GP2 int again after we clear it on PHY */	    CSR_WRITE_4( sc, INTSTAT, INTSTAT_GP2 ); 	}	/* Check for errors */	if( status & (INTSTAT_FATAL|INTSTAT_PMA|INTSTAT_PTA|		      INTSTAT_APE|INTSTAT_DPE|INTSTAT_TXU|INTSTAT_RXE) ){    	    if( status & (INTSTAT_FATAL|INTSTAT_PMA|INTSTAT_PTA|			  INTSTAT_APE|INTSTAT_DPE) ){		printf(EPIC_FORMAT ": PCI fatal error occured (%s%s%s%s)\n",    		    EPIC_ARGS(sc),		    (status&INTSTAT_PMA)?"PMA":"",		    (status&INTSTAT_PTA)?" PTA":"",		    (status&INTSTAT_APE)?" APE":"",		    (status&INTSTAT_DPE)?" DPE":""		);		epic_dump_state(sc);		epic_stop(sc);		epic_init(sc);			    	break;	    }	    if (status & INTSTAT_RXE) {		dprintf((EPIC_FORMAT ": CRC/Alignment error\n",EPIC_ARGS(sc)));		sc->sc_if.if_ierrors++;	    }	    /* Tx FIFO underflow. Increase tx threshold, */	    /* if it grown above 2048, disable EARLY_TX */	    if (status & INTSTAT_TXU) {		if( sc->tx_threshold > 0x800 ) {		    sc->txcon &= ~TXCON_EARLY_TRANSMIT_ENABLE;    		    dprintf((EPIC_FORMAT ": TX underrun error, early tx disabled\n",EPIC_ARGS(sc)));		} else {		    sc->tx_threshold += 0x40;    		    dprintf((EPIC_FORMAT ": TX underrun error, tx threshold increased to %d\n",EPIC_ARGS(sc),sc->tx_threshold));		}		CSR_WRITE_4(sc, COMMAND, COMMAND_TXUGO | COMMAND_TXQUEUED);		epic_stop_activity(sc);		epic_set_tx_mode(sc);		epic_start_activity(sc);		sc->sc_if.if_oerrors++;	    }	}    }    /* If no packets are pending, thus no timeouts */    if( sc->pending_txs == 0 ) sc->sc_if.if_timer = 0;#if defined(__OpenBSD__)    return claimed;#endif}/* * Synopsis: This one is called if packets wasn't transmitted * during timeout. Try to deallocate transmitted packets, and  * if success continue to work. * * splimp() invoked here */static voidepic_ifwatchdog __P((    struct ifnet *ifp)){	epic_softc_t *sc = ifp->if_softc;	int x;	x = splimp();	printf(EPIC_FORMAT ": device timeout %d packets, ",	    EPIC_ARGS(sc),sc->pending_txs);	/* Try to finish queued packets */	epic_tx_done( sc );	/* If not successful */	if( sc->pending_txs > 0 ){#if defined(EPIC_DEBUG)		if( ifp->if_flags & IFF_DEBUG ) epic_dump_state(sc);#endif		ifp->if_oerrors+=sc->pending_txs;		/* Reinitialize board */		printf("reinitialization\n");		epic_stop(sc);		epic_init(sc);	} else 		printf("seems we can continue normaly\n");	/* Start output */	if( ifp->if_snd.ifq_head ) epic_ifstart( ifp );	splx(x);}#if defined(SIOCSIFMEDIA) && !defined(EPIC_NOIFMEDIA)static intepic_ifmedia_change __P((    struct ifnet * ifp)){	epic_softc_t *sc = (epic_softc_t *)(ifp->if_softc);	if (IFM_TYPE(sc->ifmedia.ifm_media) != IFM_ETHER)        	return (EINVAL);	if (!(ifp->if_flags & IFF_UP))		return (0);	epic_stop_activity(sc);	epic_set_media_speed(sc);	epic_start_activity(sc);	return 0;}static voidepic_ifmedia_status __P((    struct ifnet * ifp,    struct ifmediareq *ifmr)){	epic_softc_t *sc = ifp->if_softc;	u_int32_t bmcr;	u_int32_t bmsr;	if (!(ifp->if_flags & IFF_UP))		return;	bmcr = PHY_READ_2( sc, DP83840_BMCR );	PHY_READ_2( sc, DP83840_BMSR );	bmsr = PHY_READ_2( sc, DP83840_BMSR );	ifmr->ifm_active = IFM_ETHER;	ifmr->ifm_status = IFM_AVALID;	if( !(bmsr & BMSR_LINK_STATUS) ) { 		ifmr->ifm_active |= 		    (bmcr&BMCR_AUTONEGOTIATION)?IFM_AUTO:IFM_NONE;		return;	}	ifmr->ifm_status |= IFM_ACTIVE;	ifmr->ifm_active |= (bmcr & BMCR_100MBPS) ? IFM_100_TX : IFM_10_T;	ifmr->ifm_active |= (bmcr & BMCR_FULL_DUPLEX) ? IFM_FDX : 0;	if ((sc->txcon & TXCON_LOOPBACK_MODE) == TXCON_LOOPBACK_MODE_INT)		ifmr->ifm_active |= (IFM_LOOP | IFM_FLAG1);	else if ((sc->txcon & TXCON_LOOPBACK_MODE) == TXCON_LOOPBACK_MODE_PHY)		ifmr->ifm_active |= IFM_LOOP;}#endif/* * Reset chip, PHY, allocate rings *  * splimp() invoked here */static int epic_init __P((    epic_softc_t * sc)){       	struct ifnet *ifp = &sc->sc_if;	int s,i; 	s = splimp();	/* Soft reset the chip (we have to power up card before) */	CSR_WRITE_4( sc, GENCTL, 0 );	CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET );	/*	 * Reset takes 15 pci ticks which depends on PCI bus speed.	 * Assuming it >= 33000000 hz, we have wait at least 495e-6 sec.	 */	DELAY(500);	/* Wake up */	CSR_WRITE_4( sc, GENCTL, 0 );	/* Workaround for Application Note 7-15 */	for (i=0; i<16; i++) CSR_WRITE_4(sc, TEST1, TEST1_CLOCK_TEST);	/* Initialize rings */	if( epic_init_rings( sc ) ) {		printf(EPIC_FORMAT ": failed to init rings\n",EPIC_ARGS(sc));		splx(s);		return -1;	}		/* Give rings to EPIC */	CSR_WRITE_4( sc, PRCDAR, vtophys( sc->rx_desc ) );	CSR_WRITE_4( sc, PTCDAR, vtophys( sc->tx_desc ) );	/* Put node address to EPIC */	CSR_WRITE_4( sc, LAN0, ((u_int16_t *)sc->sc_macaddr)[0] );        CSR_WRITE_4( sc, LAN1, ((u_int16_t *)sc->sc_macaddr)[1] );	CSR_WRITE_4( sc, LAN2, ((u_int16_t *)sc->sc_macaddr)[2] );	/* Set tx mode, includeing transmit threshold */	epic_set_tx_mode(sc);	/* Compute and set RXCON. */	epic_set_rx_mode( sc );	/* Set multicast table */	epic_set_mc_table( sc );	/* Enable interrupts by setting the interrupt mask. */	CSR_WRITE_4( sc, INTMASK,		INTSTAT_RCC | INTSTAT_RQE | INTSTAT_OVW | INTSTAT_RXE |		INTSTAT_TXC | INTSTAT_TCC | INTSTAT_TQE | INTSTAT_TXU |		INTSTAT_FATAL |		((QS6612_OUI == sc->phyid)?INTSTAT_GP2:0) );	/* Enable interrupts,  set for PCI read multiple and etc */	CSR_WRITE_4( sc, GENCTL,		GENCTL_ENABLE_INTERRUPT | GENCTL_MEMORY_READ_MULTIPLE |		GENCTL_ONECOPY | GENCTL_RECEIVE_FIFO_THRESHOLD64 );	/* Set media speed mode */	epic_set_media_speed( sc );	/* Mark interface running ... */	if( ifp->if_flags & IFF_UP ) ifp->if_flags |= IFF_RUNNING;	else ifp->if_flags &= ~IFF_RUNNING;	/* ... and free */	ifp->if_flags &= ~IFF_OACTIVE;	/* Start Rx process */	epic_start_activity(sc);	splx(s);	return 0;}/* * Synopsis: calculate and set Rx mode. Chip must be in idle state to * access RXCON. */static voidepic_set_rx_mode(    epic_softc_t * sc){	u_int32_t flags = sc->sc_if.if_flags;        u_int32_t rxcon = RXCON_DEFAULT | RXCON_RECEIVE_MULTICAST_FRAMES | RXCON_RECEIVE_BROADCAST_FRAMES;	rxcon |= (flags & IFF_PROMISC)?RXCON_PROMISCUOUS_MODE:0;	CSR_WRITE_4( sc, RXCON, rxcon );	return;}voiddump_phy_regs(epic_softc_t *sc) {	printf("BMCR: 0x%04x\n", PHY_READ_2(sc, DP83840_BMCR));	printf("BMSR: 0x%04x\n", PHY_READ_2(sc, DP83840_BMSR));	printf("ANAR: 0x%04x\n", PHY_READ_2(sc, DP83840_ANAR));	printf("LPAR: 0x%04x\n", PHY_READ_2(sc, DP83840_LPAR));	printf("ANER: 0x%04x\n", PHY_READ_2(sc, DP83840_ANER));	printf("MCTL: 0x%04x\n", PHY_READ_2(sc, QS6612_MCTL));	printf("INTSTAT: 0x%04x\n", PHY_READ_2(sc, QS6612_INTSTAT));	printf("INTMASK: 0x%04x\n", PHY_READ_2(sc, QS6612_INTMASK));	printf("BPCR: 0x%04x\n", PHY_READ_2(sc, QS6612_BPCR));}/* * Synopsis: Reset PHY and do PHY-special initialization: */static voidepic_init_phy __P((    epic_softc_t * sc)){	u_int32_t i;	/* Reset PHY (We have to take the delay from manual XXX) */	PHY_WRITE_2(sc, DP83840_BMCR, BMCR_RESET);	DELAY(10);	for(i=0;i<0x1000;i++) {		if( !(PHY_READ_2(sc, DP83840_BMCR) & BMCR_RESET) )			break;		DELAY(1);	}	if( PHY_READ_2(sc, DP83840_BMCR) & BMCR_RESET )		printf(EPIC_FORMAT ": WARNING! cant reset PHY\n",EPIC_ARGS(sc));	PHY_WRITE_2(sc, DP83840_BMCR, 0 );	PHY_WRITE_2(sc, DP83840_BMCR, BMCR_LOOPBACK | BMCR_ISOLATE );	switch( sc->phyid ){	case QS6612_OUI: {		/* Init QS6612 and EPIC to generate interrupt */		CSR_WRITE_4(sc, NVCTL, NVCTL_GP1_OUTPUT_ENABLE | NVCTL_GP1);		/* Mask interrupts sources */		PHY_WRITE_2(sc, QS6612_INTMASK,			PHY_READ_2(sc, QS6612_INTSTAT) |				INTMASK_THUNDERLAN | INTSTAT_AN_COMPLETE |			INTSTAT_LINK_STATUS );		/* Enable QS6612 extended cable length capabilites */		/* PHY_WRITE_2(sc, QS6612_MCTL,			   */		/*	PHY_READ_2(sc, QS6612_MCTL) | MCTL_BTEXT); */		break;	}	default:		break;	}}/* * Synopsis: Set PHY to media type specified by IFF_LINK* flags or * ifmedia structure. Chip must be in idle state to access TXCON. */static voidepic_set_media_speed __P((    epic_softc_t * sc)){	u_int16_t media;#if !defined(EPIC_NOIFMEDIA)	u_int32_t tgtmedia = sc->ifmedia.ifm_cur->ifm_media;#endif	epic_init_phy(sc);#if !defined(EPIC_NOIFMEDIA)	if( IFM_SUBTYPE(tgtmedia) != IFM_AUTO ){		/* Clean previous values */		sc->txcon &= ~(TXCON_LOOPBACK_MODE | TXCON_FULL_DUPLEX);		media = 0;		/* Set mode */		media |= (IFM_SUBTYPE(tgtmedia)==IFM_100_TX) ? BMCR_100MBPS : 0;		if (tgtmedia & IFM_FDX) {			media |= BMCR_FULL_DUPLEX; 			sc->txcon |= TXCON_FULL_DUPLEX;		}		if (tgtmedia & IFM_LOOP) {			if (tgtmedia & IFM_FLAG1)				sc->txcon |= TXCON_LOOPBACK_MODE_INT;			else {				media |= BMCR_LOOPBACK | BMCR_ISOLATE;				sc->txcon |= TXCON_LOOPBACK_MODE_PHY;			}		}		sc->sc_if.if_baudrate = 			(IFM_SUBTYPE(tgtmedia)==IFM_100_TX)?100000000:10000000;		PHY_WRITE_2( sc, DP83840_BMCR, media );	}#else /* EPIC_NOIFMEDIA */	struct ifnet *ifp = &sc->sc_if;	if( ifp->if_flags & IFF_LINK0 ) {		/* Set mode */		media = 0;		media|= (ifp->if_flags & IFF_LINK2) ? BMCR_100MBPS : 0;		media|= (ifp->if_flags & IFF_LINK1) ? BMCR_FULL_DUPLEX : 0;		sc->sc_if.if_baudrate = 			(ifp->if_flags & IFF_LINK2)?100000000:10000000;		PHY_WRITE_2( sc, DP83840_BMCR, media );		if( ifp->if_flags & IFF_LINK2 ) sc->txcon |= TXCON_FULL_DUPLEX;		else sc->txcon &= ~TXCON_FULL_DUPLEX;  		CSR_WRITE_4( sc, TXCON, sc->txcon );	}#endif /* !EPIC_NOIFMEDIA */	  else {		sc->sc_if.if_baudrate = 100000000;		sc->txcon &= ~TXCON_FULL_DUPLEX; 		CSR_WRITE_4(sc, TXCON, sc->txcon);		/* Set and restart autoneg */		PHY_WRITE_2(sc, DP83840_BMCR, BMCR_AUTONEGOTIATION );		PHY_WRITE_2(sc, DP83840_BMCR,			BMCR_AUTONEGOTIATION | BMCR_RESTART_AUTONEG);		/* If it is not QS6612 PHY, try to get result of autoneg. */		if( QS6612_OUI != sc->phyid ) {			/* Wait 3 seconds for the autoneg to finish			 * This is the recommended time from the DP83840A data			 * sheet Section 7.1			 */        		DELAY(3000000);						if( epic_autoneg(sc) == EPIC_FULL_DUPLEX ) {				sc->txcon |= TXCON_FULL_DUPLEX;				CSR_WRITE_4(sc, TXCON, sc->txcon);			}		}		/* Else it will be done when GP2 int occured */	}	epic_set_tx_mode(sc);	return;}/* * This functions get results of the autoneg processes of the phy * It implements the workaround that is described in section 7.2 & 7.3 of the 

⌨️ 快捷键说明

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