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

📄 if_tx.c

📁 基于组件方式开发操作系统的OSKIT源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
 * DP83840A data sheet * http://www.national.com/ds/DP/DP83840A.pdf */static int epic_autoneg(    epic_softc_t * sc){	u_int16_t media;	u_int16_t i;        /* BMSR must be read twice to update the link status bit	 * since that bit is a latch bit         */	PHY_READ_2( sc, DP83840_BMSR);	i = PHY_READ_2( sc, DP83840_BMSR);                if ((i & BMSR_LINK_STATUS) && (i & BMSR_AUTONEG_COMPLETE)){		i = PHY_READ_2( sc, DP83840_LPAR );		if ( i & (ANAR_100_TX_FD|ANAR_10_FD) )			return 	EPIC_FULL_DUPLEX;		else			return EPIC_HALF_DUPLEX;        } else {   		/*Auto-negotiation or link status is not 1		  Thus the auto-negotiation failed and one		  must take other means to fix it.		 */		/* ANER must be read twice to get the correct reading for the 		 * Multiple link fault bit -- it is a latched bit	 	 */ 		PHY_READ_2( sc, DP83840_ANER );		i = PHY_READ_2( sc, DP83840_ANER );			if ( i & ANER_MULTIPLE_LINK_FAULT ) {			/* it can be forced to 100Mb/s Half-Duplex */	 		media = PHY_READ_2( sc, DP83840_BMCR );			media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX);			media |= BMCR_100MBPS;			PHY_WRITE_2( sc, DP83840_BMCR, media );					/* read BMSR again to determine link status */			PHY_READ_2( sc, DP83840_BMSR );			i=PHY_READ_2( sc, DP83840_BMSR );					if (i & BMSR_LINK_STATUS){				/* port is linked to the non Auto-Negotiation				 * 100Mbs partner.			 	 */				return EPIC_HALF_DUPLEX;			}			else {				media = PHY_READ_2( sc, DP83840_BMCR);				media &= ~(BMCR_AUTONEGOTIATION | BMCR_FULL_DUPLEX | BMCR_100MBPS);				PHY_WRITE_2( sc, DP83840_BMCR, media);				PHY_READ_2( sc, DP83840_BMSR );				i = PHY_READ_2( sc, DP83840_BMSR );				if (i & BMSR_LINK_STATUS) {					/*port is linked to the non					 * Auto-Negotiation10Mbs partner			 	 	 */					return EPIC_HALF_DUPLEX;				}			}		}		/* If we get here we are most likely not connected		 * so lets default it to half duplex		 */		return EPIC_HALF_DUPLEX;	}	}/* */static voidepic_set_tx_mode (    epic_softc_t *sc ){    if( sc->txcon & TXCON_EARLY_TRANSMIT_ENABLE )	CSR_WRITE_4( sc, ETXTHR, sc->tx_threshold );    CSR_WRITE_4( sc, TXCON, sc->txcon );}/* * Synopsis: This function should update multicast hash table. * I suppose there is a bug in chips MC filter so this function * only set it to receive all MC packets. The second problem is * that we should wait for TX and RX processes to stop before * reprogramming MC filter. The epic_stop_activity() and  * epic_start_activity() should help to do this. */static voidepic_set_mc_table (    epic_softc_t * sc){	struct ifnet *ifp = &sc->sc_if;	if( ifp->if_flags & IFF_MULTICAST ){		CSR_WRITE_4( sc, MC0, 0xFFFF );		CSR_WRITE_4( sc, MC1, 0xFFFF );		CSR_WRITE_4( sc, MC2, 0xFFFF );		CSR_WRITE_4( sc, MC3, 0xFFFF );	}	return;}/*  * Synopsis: Start receive process and transmit one, if they need. */static voidepic_start_activity __P((    epic_softc_t * sc)){    /* Start rx process */    CSR_WRITE_4(sc, COMMAND,	COMMAND_RXQUEUED | COMMAND_START_RX |	(sc->pending_txs?COMMAND_TXQUEUED:0));    dprintf((EPIC_FORMAT ": activity started\n",EPIC_ARGS(sc)));}/* * Synopsis: Completely stop Rx and Tx processes. If TQE is set additional * packet needs to be queued to stop Tx DMA. */static voidepic_stop_activity __P((    epic_softc_t * sc)){    int i;    /* Stop Tx and Rx DMA */    CSR_WRITE_4(sc,COMMAND,COMMAND_STOP_RX|COMMAND_STOP_RDMA|COMMAND_STOP_TDMA);    /* Wait Rx and Tx DMA to stop (why 1 ms ??? XXX) */    dprintf((EPIC_FORMAT ": waiting Rx and Tx DMA to stop\n",EPIC_ARGS(sc)));    for(i=0;i<0x1000;i++) {	if((CSR_READ_4(sc,INTSTAT) & (INTSTAT_TXIDLE | INTSTAT_RXIDLE)) == 	   (INTSTAT_TXIDLE | INTSTAT_RXIDLE) )	    break;	DELAY(1);    }    if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_RXIDLE) ) 	printf(EPIC_FORMAT ": can't stop Rx DMA\n",EPIC_ARGS(sc));    if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) ) 	printf(EPIC_FORMAT ": can't stop Tx DMA\n",EPIC_ARGS(sc));    /* Catch all finished packets */    epic_rx_done(sc);    epic_tx_done(sc);    /*     * May need to queue one more packet if TQE, this is rare but existing     * case.     */    if( (CSR_READ_4( sc, INTSTAT ) & INTSTAT_TQE) &&       !(CSR_READ_4( sc, INTSTAT ) & INTSTAT_TXIDLE) ) {	struct epic_tx_desc *desc;	struct epic_frag_list *flist;	struct epic_tx_buffer *buf;	struct mbuf *m0;	dprintf((EPIC_FORMAT ": queue last packet\n",EPIC_ARGS(sc)));	desc = sc->tx_desc + sc->cur_tx;	flist = sc->tx_flist + sc->cur_tx;	buf = sc->tx_buffer + sc->cur_tx;	if ((desc->status & 0x8000) || (buf->mbuf != NULL))	    return;	MGETHDR(m0,M_DONTWAIT,MT_DATA);	if (NULL == m0)	    return;	/* Prepare mbuf */	m0->m_len = min(MHLEN,ETHER_MIN_LEN-ETHER_CRC_LEN);	flist->frag[0].fraglen = m0->m_len;	m0->m_pkthdr.len = m0->m_len;	m0->m_pkthdr.rcvif = &sc->sc_if;	bzero(mtod(m0,caddr_t),m0->m_len);	/* Fill fragments list */	flist->frag[0].fraglen = m0->m_len; 	flist->frag[0].fragaddr = vtophys( mtod(m0, caddr_t) );	flist->numfrags = 1;	/* Fill in descriptor */	buf->mbuf = m0;	sc->pending_txs++;	sc->cur_tx = (sc->cur_tx + 1) & TX_RING_MASK;	desc->control = 0x01;	desc->txlength = max(m0->m_pkthdr.len,ETHER_MIN_LEN-ETHER_CRC_LEN);	desc->status = 0x8000;	/* Launch transmition */	CSR_WRITE_4(sc, COMMAND, COMMAND_STOP_TDMA | COMMAND_TXQUEUED);	/* Wait Tx DMA to stop (for how long??? XXX) */	dprintf((EPIC_FORMAT ": waiting Tx DMA to stop\n",EPIC_ARGS(sc)));	for(i=0;i<1000;i++) {	    if( (CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) == INTSTAT_TXIDLE )		break;	    DELAY(1);	}	if( !(CSR_READ_4(sc,INTSTAT)&INTSTAT_TXIDLE) )	    printf(EPIC_FORMAT ": can't stop TX DMA\n",EPIC_ARGS(sc));	else	    epic_tx_done(sc);    }    dprintf((EPIC_FORMAT ": activity stoped\n",EPIC_ARGS(sc)));}/* *  Synopsis: Shut down board and deallocates rings. * *  splimp() invoked here */static voidepic_stop __P((    epic_softc_t * sc)){	int s;	s = splimp();	sc->sc_if.if_timer = 0;	/* Disable interrupts */	CSR_WRITE_4( sc, INTMASK, 0 );	CSR_WRITE_4( sc, GENCTL, 0 );	/* Try to stop Rx and TX processes */	epic_stop_activity(sc);	/* Reset chip */	CSR_WRITE_4( sc, GENCTL, GENCTL_SOFT_RESET );	DELAY(1000);	/* Make chip go to bed */	CSR_WRITE_4(sc, GENCTL, GENCTL_POWER_DOWN);	/* Free memory allocated for rings */	epic_free_rings(sc);	/* Mark as stoped */	sc->sc_if.if_flags &= ~IFF_RUNNING;	splx(s);	return;}/* * Synopsis: This function should free all memory allocated for rings. */ static voidepic_free_rings __P((    epic_softc_t * sc)){	int i;	for(i=0;i<RX_RING_SIZE;i++){		struct epic_rx_buffer *buf = sc->rx_buffer + i;		struct epic_rx_desc *desc = sc->rx_desc + i;				desc->status = 0;		desc->buflength = 0;		desc->bufaddr = 0;		if( buf->mbuf ) m_freem( buf->mbuf );		buf->mbuf = NULL;	}	for(i=0;i<TX_RING_SIZE;i++){		struct epic_tx_buffer *buf = sc->tx_buffer + i;		struct epic_tx_desc *desc = sc->tx_desc + i;		desc->status = 0;		desc->buflength = 0;		desc->bufaddr = 0;		if( buf->mbuf ) m_freem( buf->mbuf );		buf->mbuf = NULL;	}}/* * Synopsis:  Allocates mbufs for Rx ring and point Rx descs to them. * Point Tx descs to fragment lists. Check that all descs and fraglists * are bounded and aligned properly. */static intepic_init_rings(epic_softc_t * sc){	int i;	sc->cur_rx = sc->cur_tx = sc->dirty_tx = sc->pending_txs = 0;	for (i = 0; i < RX_RING_SIZE; i++) {		struct epic_rx_buffer *buf = sc->rx_buffer + i;		struct epic_rx_desc *desc = sc->rx_desc + i;		desc->status = 0;		/* Owned by driver */		desc->next = vtophys( sc->rx_desc + ((i+1) & RX_RING_MASK) );		if( (desc->next & 3) || ((desc->next & 0xFFF) + sizeof(struct epic_rx_desc) > 0x1000 ) )			printf(EPIC_FORMAT ": WARNING! rx_desc is misbound or misaligned\n",EPIC_ARGS(sc));		EPIC_MGETCLUSTER( buf->mbuf );		if( NULL == buf->mbuf ) {			epic_free_rings(sc);			return -1;		}		desc->bufaddr = vtophys( mtod(buf->mbuf,caddr_t) );		desc->buflength = ETHER_MAX_FRAME_LEN;		desc->status = 0x8000;			/* Give to EPIC */	}	for (i = 0; i < TX_RING_SIZE; i++) {		struct epic_tx_buffer *buf = sc->tx_buffer + i;		struct epic_tx_desc *desc = sc->tx_desc + i;		desc->status = 0;		desc->next = vtophys( sc->tx_desc + ( (i+1) & TX_RING_MASK ) );		if( (desc->next & 3) || ((desc->next & 0xFFF) + sizeof(struct epic_tx_desc) > 0x1000 ) )			printf(EPIC_FORMAT ": WARNING! tx_desc is misbound or misaligned\n",EPIC_ARGS(sc));		buf->mbuf = NULL;		desc->bufaddr = vtophys( sc->tx_flist + i );		if( (desc->bufaddr & 3) || ((desc->bufaddr & 0xFFF) + sizeof(struct epic_frag_list) > 0x1000 ) )			printf(EPIC_FORMAT ": WARNING! frag_list is misbound or misaligned\n",EPIC_ARGS(sc));	}	return 0;}/* * EEPROM operation functions */static void epic_write_eepromreg __P((    epic_softc_t *sc,    u_int8_t val)){	u_int16_t i;	CSR_WRITE_1( sc, EECTL, val );	for (i=0; i<0xFF; i++)		if( !(CSR_READ_1( sc, EECTL ) & 0x20) ) break;	return;}static u_int8_tepic_read_eepromreg __P((    epic_softc_t *sc)){	return CSR_READ_1( sc,EECTL );}  static u_int8_tepic_eeprom_clock __P((    epic_softc_t *sc,    u_int8_t val)){	epic_write_eepromreg( sc, val );	epic_write_eepromreg( sc, (val | 0x4) );	epic_write_eepromreg( sc, val );		return epic_read_eepromreg( sc );}static voidepic_output_eepromw __P((    epic_softc_t * sc,    u_int16_t val)){	int i;          	for( i = 0xF; i >= 0; i--){		if( (val & (1 << i)) ) epic_eeprom_clock( sc, 0x0B );		else epic_eeprom_clock( sc, 3);	}}static u_int16_tepic_input_eepromw __P((    epic_softc_t *sc)){	int i;	int tmp;	u_int16_t retval = 0;	for( i = 0xF; i >= 0; i--) {			tmp = epic_eeprom_clock( sc, 0x3 );		if( tmp & 0x10 ){			retval |= (1 << i);		}	}	return retval;}static intepic_read_eeprom __P((    epic_softc_t *sc,    u_int16_t loc)){	u_int16_t dataval;	u_int16_t read_cmd;	epic_write_eepromreg( sc , 3);	if( epic_read_eepromreg( sc ) & 0x40 )		read_cmd = ( loc & 0x3F ) | 0x180;	else		read_cmd = ( loc & 0xFF ) | 0x600;	epic_output_eepromw( sc, read_cmd );        dataval = epic_input_eepromw( sc );	epic_write_eepromreg( sc, 1 );		return dataval;}static u_int16_tepic_read_phy_register __P((    epic_softc_t *sc,    u_int16_t loc)){	int i;	CSR_WRITE_4( sc, MIICTL, ((loc << 4) | 0x0601) );	for (i=0;i<0x100;i++) {		if( !(CSR_READ_4( sc, MIICTL )&1) ) break;		DELAY(1);	}	return CSR_READ_4( sc, MIIDATA );}static voidepic_write_phy_register __P((    epic_softc_t * sc,    u_int16_t loc,    u_int16_t val)){	int i;	CSR_WRITE_4( sc, MIIDATA, val );	CSR_WRITE_4( sc, MIICTL, ((loc << 4) | 0x0602) );	for( i=0;i<0x100;i++) {		if( !(CSR_READ_4( sc, MIICTL )&2) ) break;		DELAY(1);	}	return;}static voidepic_dump_state __P((    epic_softc_t * sc)){	int j;	struct epic_tx_desc *tdesc;	struct epic_rx_desc *rdesc;	printf(EPIC_FORMAT ": cur_rx: %d, pending_txs: %d, dirty_tx: %d, cur_tx: %d\n", EPIC_ARGS(sc),sc->cur_rx,sc->pending_txs,sc->dirty_tx,sc->cur_tx);	printf(EPIC_FORMAT ": COMMAND: 0x%08x, INTSTAT: 0x%08x\n",EPIC_ARGS(sc),CSR_READ_4(sc,COMMAND),CSR_READ_4(sc,INTSTAT));	printf(EPIC_FORMAT ": PRCDAR: 0x%08x, PTCDAR: 0x%08x\n",EPIC_ARGS(sc),CSR_READ_4(sc,PRCDAR),CSR_READ_4(sc,PTCDAR));	printf(EPIC_FORMAT ": dumping rx descriptors\n",EPIC_ARGS(sc));	for(j=0;j<RX_RING_SIZE;j++){		rdesc = sc->rx_desc + j;		printf("desc%d: %4d 0x%04x, 0x%08x, %4d, 0x%08x\n",			j,			rdesc->rxlength,rdesc->status,			rdesc->bufaddr,			rdesc->buflength,			rdesc->next		);	}	printf(EPIC_FORMAT ": dumping tx descriptors\n",EPIC_ARGS(sc));	for(j=0;j<TX_RING_SIZE;j++){		tdesc = sc->tx_desc + j;		printf( 		"desc%d: %4d 0x%04x, 0x%08lx, 0x%04x %4u, 0x%08lx, mbuf: %p\n",			j,			tdesc->txlength,tdesc->status,			(u_long)tdesc->bufaddr,			tdesc->control,tdesc->buflength,			(u_long)tdesc->next,			(void *)sc->tx_buffer[j].mbuf		);	}}#endif /* NPCI > 0 */

⌨️ 快捷键说明

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