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

📄 if_wx.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (sc->wx_mii) {		mii_pollstat(WX_MII_FROM_SOFTC(sc));		return;	}	rxcw = READ_CSR(sc, WXREG_RECV_CFGW);	dcr = READ_CSR(sc, WXREG_DCR);	dsr = READ_CSR(sc, WXREG_DSR);	if ((dsr & WXDSR_LU) == 0 && (dcr & WXDCR_SWDPIN1) == 0 &&	    (rxcw & WXRXCW_C) == 0) {		if (sc->ane_failed == 0) {			sc->ane_failed = 1;			return;		}		DPRINTF(sc, (inane, sc->wx_name));		WRITE_CSR(sc, WXREG_XMIT_CFGW, WXTXCW_DEFAULT & ~WXTXCW_ANE);		if (sc->wx_idnrev < WX_WISEMAN_2_1)			sc->wx_dcr &= ~WXDCR_TFCE;		sc->wx_dcr |= WXDCR_SLU;     		WRITE_CSR(sc, WXREG_DCR, sc->wx_dcr);	} else if ((rxcw & WXRXCW_C) != 0 && (dcr & WXDCR_SLU) != 0) {		DPRINTF(sc, (ane, sc->wx_name));		WRITE_CSR(sc, WXREG_XMIT_CFGW, WXTXCW_DEFAULT);		sc->wx_dcr &= ~WXDCR_SLU;		WRITE_CSR(sc, WXREG_DCR, sc->wx_dcr);	}}static voidwx_handle_rxint(wx_softc_t *sc){	struct ether_header *eh;	struct mbuf *m0, *mb, *pending[WX_MAX_RDESC];	struct ifnet *ifp = &sc->wx_if;	int npkts, ndesc, lidx, idx, tlen;	DPRINTF(sc, ("%s: wx_handle_rxint\n", sc->wx_name));	for (m0 = sc->rpending, tlen = ndesc = npkts = 0, idx = sc->rnxt,	    lidx = R_PREV_IDX(idx); ndesc < WX_MAX_RDESC;	    ndesc++, lidx = idx, idx = R_NXT_IDX(idx)) {		wxrd_t *rd;		rxpkt_t *rxpkt;		int length, offset, lastframe;		rd = &sc->rdescriptors[idx];#if defined(__mips__)		rd = (wxrd_t *)PHYS_TO_UNCACHED(vtophys(rd));#endif		/*		 * XXX: DMA Flush descriptor		 */		if ((rd->status & RDSTAT_DD) == 0) {			if (m0) {				if (sc->rpending == NULL) {					m0->m_pkthdr.len = tlen;					sc->rpending = m0;				} else {					m_freem(m0);				}				m0 = NULL;			}			DPRINTF(sc, ("%s: WXRX: ndesc %d idx %d lidx %d\n",			    sc->wx_name, ndesc, idx, lidx));			break;		}		if (rd->errors != 0) {#if 0			printf("%s: packet with errors (%x)\n",			    sc->wx_name, rd->errors);#endif			rd->status = 0;			ifp->if_ierrors++;			if (m0) {				m_freem(m0);				m0 = NULL;				if (sc->rpending) {					m_freem(sc->rpending);					sc->rpending = NULL;				}			}			continue;		}		rxpkt = &sc->rbase[idx];		mb = rxpkt->dptr;		if (mb == NULL) {			printf("%s: receive descriptor with no mbuf\n",			    sc->wx_name);			(void) wx_get_rbuf(sc, rxpkt);			rd->status = 0;			ifp->if_ierrors++;			if (m0) {				m_freem(m0);				m0 = NULL;				if (sc->rpending) {					m_freem(sc->rpending);					sc->rpending = NULL;				}			}			continue;		}		/* XXX: Flush DMA for rxpkt */		if (wx_get_rbuf(sc, rxpkt)) {			sc->wx_rxnobuf++;			wx_rxdma_map(sc, rxpkt, mb);			ifp->if_ierrors++;			rd->status = 0;			if (m0) {				m_freem(m0);				m0 = NULL;				if (sc->rpending) {					m_freem(sc->rpending);					sc->rpending = NULL;				}			}			continue;		}		/*		 * Save the completing packet's offset value and length		 * and install the new one into the descriptor.		 */		lastframe = (rd->status & RDSTAT_EOP) != 0;		length = letoh16(rd->length);		offset = letoh32(rd->address.lowpart) & 0xff;		bzero (rd, sizeof (*rd));		rd->address.lowpart = htole32(rxpkt->dma_addr + WX_RX_OFFSET_VALUE);		mb->m_len = length;		mb->m_data += offset;		mb->m_next = NULL;		if (m0 == NULL) {			m0 = mb;			tlen = length;		} else if (m0 == sc->rpending) {			/*			 * Pick up where we left off before. If			 * we have an offset (we're assuming the			 * first frame has an offset), then we've			 * lost sync somewhere along the line.			 */			if (offset) {				printf("%s: lost sync with partial packet\n",				    sc->wx_name);				m_freem(sc->rpending);				sc->rpending = NULL;				m0 = mb;				tlen = length;			} else {				sc->rpending = NULL;				tlen = m0->m_pkthdr.len;			}		} else {			tlen += length;		}		DPRINTF(sc, ("%s: RDESC[%d] len %d off %d lastframe %d\n",		    sc->wx_name, idx, mb->m_len, offset, lastframe));		if (m0 != mb)			m_cat(m0, mb);		if (lastframe == 0) {			continue;		}		m0->m_pkthdr.rcvif = ifp;		m0->m_pkthdr.len = tlen - WX_CRC_LENGTH;		mb->m_len -= WX_CRC_LENGTH;		eh = mtod(m0, struct ether_header *);		/*		 * No need to check for promiscous mode since 		 * the decision to keep or drop the packet is		 * handled by ether_input()		 */		pending[npkts++] = m0;		m0 = NULL;		tlen = 0;	}	if (ndesc) {		if (IS_WISEMAN(sc)) {			WRITE_CSR(sc, WXREG_RDT0, lidx);		} else {			WRITE_CSR(sc, WXREG_RDT0_LIVENGOOD, lidx);		}		sc->rnxt = idx;	}	if (npkts) {		sc->wx_rxintr++;	}	for (idx = 0; idx < npkts; idx++) {		mb = pending[idx];#if	NBPFILTER > 0                if (ifp->if_bpf) {                        bpf_mtap(WX_BPFTAP_ARG(ifp), mb);		}#endif		ifp->if_ipackets++;		DPRINTF(sc, ("%s: RECV packet length %d\n",		    sc->wx_name, mb->m_pkthdr.len));#ifndef PMON		ether_input_mbuf(ifp, mb);#else		{			struct ether_header *eh;			eh = mtod(mb, struct ether_header *);			mb->m_data += sizeof(struct ether_header);			ether_input(ifp, eh, mb);		}#endif	}}static voidwx_gc(wx_softc_t *sc){	struct ifnet *ifp = &sc->wx_if;	txpkt_t *txpkt;	u_int32_t tdh;	WX_LOCK(sc);	txpkt = sc->tbsyf;	if (IS_WISEMAN(sc)) {		tdh = READ_CSR(sc, WXREG_TDH);	} else {		tdh = READ_CSR(sc, WXREG_TDH_LIVENGOOD);	}	while (txpkt != NULL) {		u_int32_t end = txpkt->eidx, cidx = tdh;		/*		 * Normalize start..end indices to 2 *	 	 * WX_MAX_TDESC range to eliminate wrap.		 */		if (txpkt->eidx < txpkt->sidx) {			end += WX_MAX_TDESC;		}		/*		 * Normalize current chip index to 2 *	 	 * WX_MAX_TDESC range to eliminate wrap.		 */		if (cidx < txpkt->sidx) {			cidx += WX_MAX_TDESC;		}		/*		 * If the current chip index is between low and		 * high indices for this packet, it's not finished		 * transmitting yet. Because transmits are done FIFO,		 * this means we're done garbage collecting too.		 */		if (txpkt->sidx <= cidx && cidx < txpkt->eidx) {#if 0			DPRINTF(sc, ("%s: TXGC %d..%d TDH %d\n", sc->wx_name,			    txpkt->sidx, txpkt->eidx, tdh));#endif			break;		}		ifp->if_opackets++;		if (txpkt->dptr) {			(void) m_freem(txpkt->dptr);		} else {			printf("%s: null mbuf in gc\n", sc->wx_name);		}		for (cidx = txpkt->sidx; cidx != txpkt->eidx;		    cidx = T_NXT_IDX(cidx)) {			txpkt_t *tmp;			wxtd_t *td;			td = &sc->tdescriptors[cidx];#if defined(__mips__)			td = (wxtd_t *)PHYS_TO_UNCACHED(vtophys(td));#else			CACHESYNC(td, sizeof(*td), SYNC_R);#endif			if (td->status & TXSTS_EC) {				IPRINTF(sc, ("%s: excess collisions\n",				    sc->wx_name));				ifp->if_collisions++;				ifp->if_oerrors++;			}			if (td->status & TXSTS_LC) {				IPRINTF(sc,				    ("%s: lost carrier\n", sc->wx_name));				ifp->if_oerrors++;			}			tmp = &sc->tbase[cidx];			DPRINTF(sc, ("%s: TXGC[%d] %p %d..%d done nact %d "			    "TDH %d\n", sc->wx_name, cidx, tmp->dptr,			    txpkt->sidx, txpkt->eidx, sc->tactive, tdh));			tmp->dptr = NULL;			if (sc->tactive == 0) {				printf("%s: nactive < 0?\n", sc->wx_name);			} else {				sc->tactive -= 1;			}			bzero(td, sizeof (*td));		}		sc->tbsyf = txpkt->next;		txpkt = sc->tbsyf;	}	if (sc->tactive < WX_MAX_TDESC - 1) {		ifp->if_timer = 0;		ifp->if_flags &= ~IFF_OACTIVE;	}	/* used SW LED to indicate transmission not active */	if (sc->tactive == 0 && sc->wx_mii) {		WRITE_CSR(sc, WXREG_DCR,		    READ_CSR(sc, WXREG_DCR) & ~(WXDCR_SWDPIO0|WXDCR_SWDPIN0));	}	WX_UNLOCK(sc);}static voidwx_watchdog(void *arg){	wx_softc_t *sc = arg;	WX_LOCK(sc);	if (sc->wx_needreinit) {		WX_UNLOCK(sc);		if (wx_init(sc) == 0) {			WX_LOCK(sc);			sc->wx_needreinit = 0;		} else {			WX_LOCK(sc);		}	} else {		wx_gc(sc);		wx_check_link(sc);	}	WX_UNLOCK(sc);	/*	 * Schedule another timeout one second from now.	 */	TIMEOUT(sc, wx_watchdog, sc, hz);}/* * Stop and reinitialize the hardware */static voidwx_hw_stop(wx_softc_t *sc){	u_int32_t icr;	DPRINTF(sc, ("%s: wx_hw_stop\n", sc->wx_name));	WX_DISABLE_INT(sc);	if (sc->wx_idnrev < WX_WISEMAN_2_1) {		wx_mwi_whackon(sc);	}	WRITE_CSR(sc, WXREG_DCR, WXDCR_RST);	DELAY(20 * 1000);	icr = READ_CSR(sc, WXREG_ICR);	if (sc->wx_idnrev < WX_WISEMAN_2_1) {		wx_mwi_unwhack(sc);	}}static voidwx_set_addr(wx_softc_t *sc, int idx, u_int8_t *mac){	u_int32_t t0, t1;	DPRINTF(sc, ("%s: wx_set_addr\n", sc->wx_name));	t0 = (mac[0]) | (mac[1] << 8) | (mac[2] << 16) | (mac[3] << 24);	t1 = (mac[4] << 0) | (mac[5] << 8);	t1 |= WX_RAL_AV;	WRITE_CSR(sc, WXREG_RAL_LO(idx), t0);	WRITE_CSR(sc, WXREG_RAL_HI(idx), t1);}static intwx_hw_initialize(wx_softc_t *sc){	int i;	DPRINTF(sc, ("%s: wx_hw_initialize\n", sc->wx_name));	WRITE_CSR(sc, WXREG_VET, 0);	for (i = 0; i < (WX_VLAN_TAB_SIZE << 2); i += 4) {		WRITE_CSR(sc, (WXREG_VFTA + i), 0);	}	if (sc->wx_idnrev < WX_WISEMAN_2_1) {		wx_mwi_whackon(sc);		WRITE_CSR(sc, WXREG_RCTL, WXRCTL_RST);		DELAY(5 * 1000);	}	/*	 * Load the first receiver address with our MAC address,	 * and load as many multicast addresses as can fit into	 * the receive address array.	 */	wx_set_addr(sc, 0, sc->wx_enaddr);	for (i = 1; i <= sc->wx_nmca; i++) {		if (i >= WX_RAL_TAB_SIZE) {			break;		} else {			wx_set_addr(sc, i, sc->wx_mcaddr[i-1]);		}	}	while (i < WX_RAL_TAB_SIZE) {		WRITE_CSR(sc, WXREG_RAL_LO(i), 0);		WRITE_CSR(sc, WXREG_RAL_HI(i), 0);		i++;	}	if (sc->wx_idnrev < WX_WISEMAN_2_1) {		WRITE_CSR(sc, WXREG_RCTL, 0);		DELAY(1 * 1000);		wx_mwi_unwhack(sc);	}	/*	 * Clear out the hashed multicast table array.	 */	for (i = 0; i < WX_MC_TAB_SIZE; i++) {		WRITE_CSR(sc, WXREG_MTA + (sizeof (u_int32_t) * 4), 0);	}	if (IS_LIVENGOOD_CU(sc)) {		/*		 * has a PHY - raise its reset line to make it operational		 */		u_int32_t tmp = READ_CSR(sc, WXREG_EXCT);		tmp |= WXPHY_RESET_DIR4;		WRITE_CSR(sc, WXREG_EXCT, tmp);		DELAY(20*1000);		tmp = READ_CSR(sc, WXREG_EXCT);		tmp &= ~WXPHY_RESET4;		WRITE_CSR(sc, WXREG_EXCT, tmp);		DELAY(20*1000);		tmp = READ_CSR(sc, WXREG_EXCT);		tmp |= WXPHY_RESET4;		WRITE_CSR(sc, WXREG_EXCT, tmp);		DELAY(20*1000);	} else if (IS_LIVENGOOD(sc)) {		u_int16_t tew;		/*		 * Handle link control		 */		WRITE_CSR(sc, WXREG_DCR, sc->wx_dcr | WXDCR_LRST);		DELAY(50 * 1000);		wx_read_eeprom(sc, &tew, WX_EEPROM_CTLR2_OFF, 1);		tew = (tew & WX_EEPROM_CTLR2_SWDPIO) << WX_EEPROM_EXT_SHIFT;		WRITE_CSR(sc, WXREG_EXCT, (u_int32_t)tew);	}	if (sc->wx_dcr & (WXDCR_RFCE|WXDCR_TFCE)) {		WRITE_CSR(sc, WXREG_FCAL, FC_FRM_CONST_LO);		WRITE_CSR(sc, WXREG_FCAH, FC_FRM_CONST_HI);		WRITE_CSR(sc, WXREG_FCT, FC_TYP_CONST);	} else {		WRITE_CSR(sc, WXREG_FCAL, 0);		WRITE_CSR(sc, WXREG_FCAH, 0);		WRITE_CSR(sc, WXREG_FCT, 0);	}	WRITE_CSR(sc, WXREG_FLOW_XTIMER, WX_XTIMER_DFLT);	if (IS_WISEMAN(sc)) {		if (sc->wx_idnrev < WX_WISEMAN_2_1) {			WRITE_CSR(sc, WXREG_FLOW_RCV_HI, 0);			WRITE_CSR(sc, WXREG_FLOW_RCV_LO, 0);			sc->wx_dcr &= ~(WXDCR_RFCE|WXDCR_TFCE);		} else {			WRITE_CSR(sc, WXREG_FLOW_RCV_HI, WX_RCV_FLOW_HI_DFLT);			WRITE_CSR(sc, WXREG_FLOW_RCV_LO, WX_RCV_FLOW_LO_DFLT);		}	} else {		WRITE_CSR(sc, WXREG_FLOW_RCV_HI_LIVENGOOD, WX_RCV_FLOW_HI_DFLT);		WRITE_CSR(sc, WXREG_FLOW_RCV_LO_LIVENGOOD, WX_RCV_FLOW_LO_DFLT);	}	if (!IS_LIVENGOOD_CU(sc))		WRITE_CSR(sc, WXREG_XMIT_CFGW, WXTXCW_DEFAULT);	WRITE_CSR(sc, WXREG_DCR, sc->wx_dcr);	DELAY(50 * 1000);	if (!IS_LIVENGOOD_CU(sc)) {		/*		 * The pin stuff is all FM from the Linux driver.		 */		if ((READ_CSR(sc, WXREG_DCR) & WXDCR_SWDPIN1) == 0) {			for (i = 0; i < (WX_LINK_UP_TIMEOUT/10); i++) {				DELAY(10 * 1000);				if (READ_CSR(sc, WXREG_DSR) & WXDSR_LU) {					sc->linkup = 1;					break;				}			}			if (sc->linkup == 0) {				sc->ane_failed = 1;				wx_check_link(sc);			}			sc->ane_failed = 0;		} else {			printf("%s: SWDPIO1 did not clear- check for reversed "				"or disconnected cable\n", sc->wx_name);			/* but return okay anyway */		}	}	sc->wx_ienable = WXIENABLE_DEFAULT;	return (0);}/* * Stop the interface. Cancels the statistics updater and resets the interface. */static voidwx_stop(wx_softc_t *sc){	txpkt_t *txp;	rxpkt_t *rxp;	struct ifnet *ifp = &sc->wx_if;	DPRINTF(sc, ("%s: wx_stop\n", sc->wx_name));	/*	 * Cancel stats updater.	 */	UNTIMEOUT(wx_watchdog, sc, sc);	/*	 * Reset the chip	 */	wx_hw_stop(sc);	/*	 * Release any xmit buffers.	 */	for (txp = sc->tbase; txp && txp < &sc->tbase[WX_MAX_TDESC]; txp++) {		if (txp->dptr) {			m_free(txp->dptr);			txp->dptr = NULL;		}	}

⌨️ 快捷键说明

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