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

📄 if_wx.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/*	 * Free all the receive buffers.	 */	for (rxp = sc->rbase; rxp && rxp < &sc->rbase[WX_MAX_RDESC]; rxp++) {		if (rxp->dptr) {			m_free(rxp->dptr);			rxp->dptr = NULL;		}	}	if (sc->rpending) {		m_freem(sc->rpending);		sc->rpending = NULL;	}	/*	 * And we're outta here...	 */	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);	ifp->if_timer = 0;}/* * Transmit Watchdog */static voidwx_txwatchdog(struct ifnet *ifp){	wx_softc_t *sc = SOFTC_IFP(ifp);	printf("%s: device timeout\n", sc->wx_name);	ifp->if_oerrors++;	if (wx_init(sc)) {		printf("%s: could not re-init device\n", sc->wx_name);		sc->wx_needreinit = 1;	}}static intwx_init(void *xsc){	struct ifmedia *ifm;	wx_softc_t *sc = xsc;	struct ifnet *ifp = &sc->wx_if;	rxpkt_t *rxpkt;	wxrd_t *rd;	size_t len;	int i, bflags;	DPRINTF(sc, ("%s: wx_init\n", sc->wx_name));	WX_LOCK(sc);	/*	 * Cancel any pending I/O by resetting things.	 * wx_stop will free any allocated mbufs.	 */	wx_stop(sc);	/*	 * Reset the hardware. All network addresses loaded here, but	 * neither the receiver nor the transmitter are enabled.	 */	if (wx_hw_initialize(sc)) {		DPRINTF(sc, ("%s: wx_hw_initialize failed\n", sc->wx_name));		WX_UNLOCK(sc);		return (EIO);	}	/*	 * Set up the receive ring stuff.	 */	len = sizeof (wxrd_t) * WX_MAX_RDESC;	bzero(sc->rdescriptors, len);	for (rxpkt = sc->rbase, i = 0; rxpkt != NULL && i < WX_MAX_RDESC;	    i += RXINCR, rxpkt++) {		rd = &sc->rdescriptors[i];		if (wx_get_rbuf(sc, rxpkt)) {			break;		}		rd->address.lowpart = htole32(rxpkt->dma_addr + WX_RX_OFFSET_VALUE);	}	if (i != WX_MAX_RDESC) {		printf("%s: could not set up rbufs\n", sc->wx_name);		wx_stop(sc);		WX_UNLOCK(sc);		return (ENOMEM);	}	CACHESYNC(&sc->rdescriptors[0], sizeof (wxrd_t) * WX_MAX_RDESC, SYNC_W);	CACHESYNC(&sc->rdescriptors[0], sizeof (wxrd_t) * WX_MAX_RDESC, SYNC_R);	/*	 * Set up transmit parameters and enable the transmitter.	 */	sc->tnxtfree = sc->tactive = 0;	sc->tbsyf = sc->tbsyl = NULL;	CACHESYNC(&sc->tdescriptors[0], sizeof (wxtd_t) * WX_MAX_TDESC, SYNC_W);	CACHESYNC(&sc->tdescriptors[0], sizeof (wxtd_t) * WX_MAX_TDESC, SYNC_R);	WRITE_CSR(sc, WXREG_TCTL, 0);	DELAY(5 * 1000);	if (IS_WISEMAN(sc)) {		WRITE_CSR(sc, WXREG_TDBA_LO,			vtophys((vm_offset_t)&sc->tdescriptors[0]));		WRITE_CSR(sc, WXREG_TDBA_HI, 0);		WRITE_CSR(sc, WXREG_TDLEN, WX_MAX_TDESC * sizeof (wxtd_t));		WRITE_CSR(sc, WXREG_TDH, 0);		WRITE_CSR(sc, WXREG_TDT, 0);		WRITE_CSR(sc, WXREG_TQSA_HI, 0);		WRITE_CSR(sc, WXREG_TQSA_LO, 0);		WRITE_CSR(sc, WXREG_TIPG, WX_WISEMAN_TIPG_DFLT);		WRITE_CSR(sc, WXREG_TIDV, 5000);	} else {		WRITE_CSR(sc, WXREG_TDBA_LO_LIVENGOOD,			vtophys((vm_offset_t)&sc->tdescriptors[0]));		WRITE_CSR(sc, WXREG_TDBA_HI_LIVENGOOD, 0);		WRITE_CSR(sc, WXREG_TDLEN_LIVENGOOD,			WX_MAX_TDESC * sizeof (wxtd_t));		WRITE_CSR(sc, WXREG_TDH_LIVENGOOD, 0);		WRITE_CSR(sc, WXREG_TDT_LIVENGOOD, 0);		WRITE_CSR(sc, WXREG_TQSA_HI, 0);		WRITE_CSR(sc, WXREG_TQSA_LO, 0);		WRITE_CSR(sc, WXREG_TIPG, WX_LIVENGOOD_TIPG_DFLT);		WRITE_CSR(sc, WXREG_TIDV_LIVENGOOD, 5000);	}	WRITE_CSR(sc, WXREG_TCTL, (WXTCTL_CT(WX_COLLISION_THRESHOLD) |	    WXTCTL_COLD(WX_FDX_COLLISION_DX) | WXTCTL_EN));	/*	 * Set up receive parameters and enable the receiver.	 */	sc->rnxt = 0;	WRITE_CSR(sc, WXREG_RCTL, 0);	DELAY(5 * 1000);	if (IS_WISEMAN(sc)) {		WRITE_CSR(sc, WXREG_RDTR0, WXRDTR_FPD);		WRITE_CSR(sc, WXREG_RDBA0_LO,		    vtophys((vm_offset_t)&sc->rdescriptors[0]));		WRITE_CSR(sc, WXREG_RDBA0_HI, 0);		WRITE_CSR(sc, WXREG_RDLEN0, WX_MAX_RDESC * sizeof (wxrd_t));		WRITE_CSR(sc, WXREG_RDH0, 0);		WRITE_CSR(sc, WXREG_RDT0, (WX_MAX_RDESC - RXINCR));	} else {		/*		 * The delay should yield ~10us receive interrupt delay 		 */		WRITE_CSR(sc, WXREG_RDTR0_LIVENGOOD, WXRDTR_FPD | 0x40);		WRITE_CSR(sc, WXREG_RDBA0_LO_LIVENGOOD,		    vtophys((vm_offset_t)&sc->rdescriptors[0]));		WRITE_CSR(sc, WXREG_RDBA0_HI_LIVENGOOD, 0);		WRITE_CSR(sc, WXREG_RDLEN0_LIVENGOOD,		    WX_MAX_RDESC * sizeof (wxrd_t));		WRITE_CSR(sc, WXREG_RDH0_LIVENGOOD, 0);		WRITE_CSR(sc, WXREG_RDT0_LIVENGOOD, (WX_MAX_RDESC - RXINCR));	}	WRITE_CSR(sc, WXREG_RDTR1, 0);	WRITE_CSR(sc, WXREG_RDBA1_LO, 0);	WRITE_CSR(sc, WXREG_RDBA1_HI, 0);	WRITE_CSR(sc, WXREG_RDLEN1, 0);	WRITE_CSR(sc, WXREG_RDH1, 0);	WRITE_CSR(sc, WXREG_RDT1, 0);	if (ifp->if_mtu > ETHERMTU) {		bflags = WXRCTL_EN | WXRCTL_LPE | WXRCTL_2KRBUF;	} else {		bflags = WXRCTL_EN | WXRCTL_2KRBUF;	}	WRITE_CSR(sc, WXREG_RCTL, bflags |	    ((ifp->if_flags & IFF_BROADCAST) ? WXRCTL_BAM : 0) |	    ((ifp->if_flags & IFF_PROMISC) ? WXRCTL_UPE : 0) |	    ((sc->all_mcasts) ? WXRCTL_MPE : 0));	/*	 * Enable Interrupts	 */	WX_ENABLE_INT(sc);	if (sc->wx_mii) {		mii_mediachg(WX_MII_FROM_SOFTC(sc));	} else {		ifm = &sc->wx_media;		i = ifm->ifm_media;		ifm->ifm_media = ifm->ifm_cur->ifm_media;		wx_ifmedia_upd(ifp);		ifm->ifm_media = i;	}	/*	 * Mark that we're up and running...	 */	ifp->if_flags |= IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	/*	 * Start stats updater.	 */	TIMEOUT(sc, wx_watchdog, sc, hz);	WX_UNLOCK(sc);	/*	 * And we're outta here...	 */	return (0);}/* * Get a receive buffer for our use (and dma map the data area). *  * The Wiseman chip can have buffers be 256, 512, 1024 or 2048 bytes in size. * The LIVENGOOD chip can go higher (up to 16K), but what's the point as * we aren't doing non-MCLGET memory management. * * It wants them aligned on 256 byte boundaries, but can actually cope * with an offset in the first 255 bytes of the head of a receive frame. * * We'll allocate a MCLBYTE sized cluster but *not* adjust the data pointer * by any alignment value. Instead, we'll tell the chip to offset by any * alignment and we'll catch the alignment on the backend at interrupt time. */static voidwx_rxdma_map(wx_softc_t *sc, rxpkt_t *rxpkt, struct mbuf *mb){	rxpkt->dptr = mb;	rxpkt->dma_addr = vtophys(mtod(mb, vm_offset_t));	CACHESYNC(mtod(mb, vm_offset_t), MCLBYTES, SYNC_R);	CACHESYNC(rxpkt, sizeof(rxpkt_t), SYNC_W);}static intwx_get_rbuf(wx_softc_t *sc, rxpkt_t *rxpkt){	struct mbuf *mb;	MGETHDR(mb, M_DONTWAIT, MT_DATA);	if (mb == NULL) {		rxpkt->dptr = NULL;		return (-1);	}	MCLGET(mb, M_DONTWAIT);	if ((mb->m_flags & M_EXT) == 0) {		m_freem(mb);		rxpkt->dptr = NULL;		return (-1);	}	wx_rxdma_map(sc, rxpkt, mb);	return (0);}static intwx_ioctl(struct ifnet *ifp, IOCTL_CMD_TYPE command, caddr_t data){	wx_softc_t *sc = SOFTC_IFP(ifp);	struct ifreq *ifr = (struct ifreq *) data;	int error = 0;	WX_LOCK(sc);	switch (command) {	case SIOCSIFADDR:	case SIOCGIFADDR:		error = ether_ioctl(ifp, command, data);		break;#ifndef PMON	case SIOCSIFMTU:		if (ifr->ifr_mtu > WX_MAXMTU || ifr->ifr_mtu < ETHERMIN) {			error = EINVAL;                } else if (ifp->if_mtu != ifr->ifr_mtu) {			ifp->if_mtu = ifr->ifr_mtu;			error = wx_init(sc);                }                break;#endif	case SIOCSIFFLAGS:		sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;		/*		 * If interface is marked up and not running, then start it.		 * If it is marked down and running, stop it.		 * If it's up then re-initialize it. This is so flags		 * such as IFF_PROMISC are handled.		 */		if (ifp->if_flags & IFF_UP) {			if ((ifp->if_flags & IFF_RUNNING) == 0) {				error = wx_init(sc);			}		} else {			if (ifp->if_flags & IFF_RUNNING) {				wx_stop(sc);			}		}		break;	case SIOCADDMULTI:	case SIOCDELMULTI:		sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;		error = wx_mc_setup(sc);		break;	case SIOCGIFMEDIA:	case SIOCSIFMEDIA:		DPRINTF(sc, ("%s: ioctl SIOC[GS]IFMEDIA: command=%#lx\n",		    sc->wx_name, command));		if (sc->wx_mii) {			mii_data_t *mii = WX_MII_FROM_SOFTC(sc);			error = ifmedia_ioctl(ifp, ifr,			    &mii->mii_media, command);		} else {			error = ifmedia_ioctl(ifp, ifr, &sc->wx_media, command);		}		break;	default:		error = EINVAL;	}	WX_UNLOCK(sc);	return (error);}static intwx_ifmedia_upd(struct ifnet *ifp){	struct wx_softc *sc = SOFTC_IFP(ifp);	struct ifmedia *ifm;	DPRINTF(sc, ("%s: ifmedia_upd\n", sc->wx_name));	if (sc->wx_mii) {		mii_mediachg(WX_MII_FROM_SOFTC(sc));		return 0;	}	ifm = &sc->wx_media;	if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) {		return (EINVAL);	}	return (0);}static voidwx_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr){	u_int32_t dsr;	struct wx_softc *sc = SOFTC_IFP(ifp);	DPRINTF(sc, ("%s: ifmedia_sts: ", sc->wx_name));	if (sc->wx_mii) {		mii_data_t *mii = WX_MII_FROM_SOFTC(sc);		mii_pollstat(mii);		ifmr->ifm_active = mii->mii_media_active;		ifmr->ifm_status = mii->mii_media_status;		DPRINTF(sc, ("active=%#x status=%#x\n",		    ifmr->ifm_active, ifmr->ifm_status));		return;	}	DPRINTF(sc, ("\n"));	ifmr->ifm_status = IFM_AVALID;	ifmr->ifm_active = IFM_ETHER;	if (sc->linkup == 0)		return;	ifmr->ifm_status |= IFM_ACTIVE;	dsr = READ_CSR(sc, WXREG_DSR);	if (IS_LIVENGOOD(sc)) {		if (dsr &  WXDSR_1000BT) {			if (IS_LIVENGOOD_CU(sc)) {				ifmr->ifm_status |= IFM_1000_TX;			}			else {				ifmr->ifm_status |= IFM_1000_SX;			}		} else if (dsr & WXDSR_100BT) {			ifmr->ifm_status |= IFM_100_FX;	/* ?? */		} else {			ifmr->ifm_status |= IFM_10_T;	/* ?? */		}	} else {		ifmr->ifm_status |= IFM_1000_SX;	}	if (dsr & WXDSR_FD) {		ifmr->ifm_active |= IFM_FDX;	}}#define RAISE_CLOCK(sc, dcr)	\		WRITE_CSR(sc, WXREG_DCR, (dcr) | WXPHY_MDC), DELAY(2)#define LOWER_CLOCK(sc, dcr)	\		WRITE_CSR(sc, WXREG_DCR, (dcr) & ~WXPHY_MDC), DELAY(2)static u_int32_twx_mii_shift_in(wx_softc_t *sc){	u_int32_t dcr, i;	u_int32_t data = 0;	dcr = READ_CSR(sc, WXREG_DCR);	dcr &= ~(WXPHY_MDIO_DIR | WXPHY_MDIO);	WRITE_CSR(sc, WXREG_DCR, dcr);	RAISE_CLOCK(sc, dcr);	LOWER_CLOCK(sc, dcr);	for (i = 0; i < 16; i++) {		data <<= 1;		RAISE_CLOCK(sc, dcr);		dcr = READ_CSR(sc, WXREG_DCR);		if (dcr & WXPHY_MDIO)			data |= 1;				LOWER_CLOCK(sc, dcr);	}	RAISE_CLOCK(sc, dcr);	LOWER_CLOCK(sc, dcr);	return (data);}static voidwx_mii_shift_out(wx_softc_t *sc, u_int32_t data, u_int32_t count){	u_int32_t dcr, mask;	dcr = READ_CSR(sc, WXREG_DCR);	dcr |= WXPHY_MDIO_DIR | WXPHY_MDC_DIR;	for (mask = (1 << (count - 1)); mask; mask >>= 1) {		if (data & mask)			dcr |= WXPHY_MDIO;		else			dcr &= ~WXPHY_MDIO;		WRITE_CSR(sc, WXREG_DCR, dcr);		DELAY(2);		RAISE_CLOCK(sc, dcr);		LOWER_CLOCK(sc, dcr);	}}static intwx_miibus_readreg(void *arg, int phy, int reg){	wx_softc_t *sc = WX_SOFTC_FROM_MII_ARG(arg);	unsigned int data = 0;	if (!IS_LIVENGOOD_CU(sc)) {		return 0;	}	wx_mii_shift_out(sc, WXPHYC_PREAMBLE, WXPHYC_PREAMBLE_LEN);	wx_mii_shift_out(sc, reg | (phy << 5) | (WXPHYC_READ << 10) |	    (WXPHYC_SOF << 12), 14);	data = wx_mii_shift_in(sc);	return (data & WXMDIC_DATA_MASK);}static intwx_miibus_writereg(void *arg, int phy, int reg, int data){	wx_softc_t *sc = WX_SOFTC_FROM_MII_ARG(arg);	if (!IS_LIVENGOOD_CU(sc)) {		return 0;	}	wx_mii_shift_out(sc, WXPHYC_PREAMBLE, WXPHYC_PREAMBLE_LEN);	wx_mii_shift_out(sc, (u_int32_t)data | (WXPHYC_TURNAROUND << 16) |	    (reg << 18) | (phy << 23) | (WXPHYC_WRITE << 28) |	    (WXPHYC_SOF << 30), 32);	return (0);}static voidwx_miibus_statchg(void *arg){	wx_softc_t *sc = WX_SOFTC_FROM_MII_ARG(arg);	mii_data_t *mii = WX_MII_FROM_SOFTC(sc);	u_int32_t dcr, tctl;	if (mii == NULL)		return;	dcr = sc->wx_dcr;	tctl = READ_CSR(sc, WXREG_TCTL);	DPRINTF(sc, ("%s: statchg dcr=%#x tctl=%#x", sc->wx_name, dcr, tctl));	dcr |= WXDCR_FRCSPD | WXDCR_FRCDPX | WXDCR_SLU;	dcr &= ~(WXDCR_SPEED_MASK | WXDCR_ASDE /* | WXDCR_ILOS */);	if (mii->mii_media_status & IFM_ACTIVE) {		if (IFM_SUBTYPE(mii->mii_media_active) == IFM_NONE) {			DPRINTF(sc, (" link-down\n"));			sc->linkup = 0;			return;		}		sc->linkup = 1;	}	if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_TX) {		DPRINTF(sc, (" 1000TX"));		dcr |= WXDCR_1000BT;	} else if (IFM_SUBTYPE(mii->mii_media_active) == IFM_100_TX) {		DPRINTF(sc, (" 100TX"));		dcr |= WXDCR_100BT;	} else	/* assume IFM_10_TX */ {		DPRINTF(sc, (" 10TX"));		dcr |= WXDCR_10BT;	}	if (mii->mii_media_active & IFM_FDX) {		DPRINTF(sc, ("-FD"));		tctl = WXTCTL_CT(WX_COLLISION_THRESHOLD) |		    WXTCTL_COLD(WX_FDX_COLLISION_DX) | WXTCTL_EN;		dcr |= WXDCR_FD;	} else {		DPRINTF(sc, ("-HD"));		tctl = WXTCTL_CT(WX_COLLISION_THRESHOLD) |		    WXTCTL_COLD(WX_HDX_COLLISION_DX) | WXTCTL_EN;		dcr &= ~WXDCR_FD;	}	/* FLAG0==rx-flow-control FLAG1==tx-flow-control */	if (mii->mii_media_active & IFM_FLAG0) {		dcr |= WXDCR_RFCE;	} else {		dcr &= ~WXDCR_RFCE;	}	if (mii->mii_media_active & IFM_FLAG1) {		dcr |= WXDCR_TFCE;	} else {		dcr &= ~WXDCR_TFCE;	}	if (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);	}	DPRINTF(sc, (" dcr=%#x tctl=%#x\n", dcr, tctl));	WRITE_CSR(sc, WXREG_TCTL, tctl);	sc->wx_dcr = dcr;	WRITE_CSR(sc, WXREG_DCR, dcr);}

⌨️ 快捷键说明

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