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

📄 if_fxp.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	 * zero and must be one bits in this structure and this is the easiest	 * way to initialize them all to proper values.	 */	bcopy(fxp_cb_config_template, (void *)&cbp->cb_status,		sizeof(fxp_cb_config_template));	cbp->cb_command = htole16(FXP_CB_COMMAND_CONFIG | FXP_CB_COMMAND_EL);	/*	 * Start the config command/DMA.	 */	fxp_scb_wait(sc);	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status));	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);	/* ...and wait for it to complete. */	for (i = 0; !(cbp->cb_status & htole16(FXP_CB_STATUS_C)) && i < FXP_MAX_STATUS_READS; ++i)		DELAY(2);		if (i == FXP_MAX_STATUS_READS) {		printf("bus congestion, restarting");		return -1;	}	/*	 * Now initialize the station address. Temporarily use the TxCB	 * memory area like we did above for the config CB.	 */	cb_ias = (struct fxp_cb_ias *) sc->cbl_base;	cb_ias->cb_status = htole16(0);	cb_ias->cb_command = htole16(FXP_CB_COMMAND_IAS | FXP_CB_COMMAND_EL);	cb_ias->link_addr = htole32(-1);	bcopy(sc->arpcom.ac_enaddr, (void *)cb_ias->macaddr,	    sizeof(sc->arpcom.ac_enaddr));	/*	 * Start the IAS (Individual Address Setup) command/DMA.	 */	fxp_scb_wait(sc);	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);	/* ...and wait for it to complete. */	for (i = 0; !(cb_ias->cb_status & htole16(FXP_CB_STATUS_C)) && i < FXP_MAX_STATUS_READS; ++i)		DELAY(2);	if (i == FXP_MAX_STATUS_READS) {		printf("bus congestion, restarting");		return -1;	}	/*	 * Initialize transmit control block (TxCB) list.	 */	txp = sc->cbl_base;	bzero(txp, sizeof(struct fxp_cb_tx) * FXP_NTXCB);	for (i = 0; i < FXP_NTXCB; i++) {		txp[i].cb_status = htole16(FXP_CB_STATUS_C | FXP_CB_STATUS_OK);		txp[i].cb_command = htole16(FXP_CB_COMMAND_NOP);		txp[i].link_addr = htole32(vtophys(&txp[(i + 1) & FXP_TXCB_MASK].cb_status));		txp[i].tbd_array_addr = htole32(vtophys(&txp[i].tbd[0]));		txp[i].next = &txp[(i + 1) & FXP_TXCB_MASK];	}	/*	 * Set the suspend flag on the first TxCB and start the control	 * unit. It will execute the NOP and then suspend.	 */	txp->cb_command = htole16(FXP_CB_COMMAND_NOP | FXP_CB_COMMAND_S);	sc->cbl_first = sc->cbl_last = txp;	sc->tx_queued = 1;	fxp_scb_wait(sc);	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);	/*	 * Initialize receiver buffer area - RFA.	 */	fxp_scb_wait(sc);/* XXXX MIPS: Flush not req. Already done when put on rfa_headm */	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL,	    vtophys(sc->rfa_headm->m_ext.ext_buf) + RFA_ALIGNMENT_FUDGE);	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_START);	/*	 * Set current media.	 */	mii_mediachg(&sc->sc_mii);	ifp->if_flags |= IFF_RUNNING;	ifp->if_flags &= ~IFF_OACTIVE;	splx(s);#ifdef USE_FXP_STATS	/*	 * Start stats updater.	 */	timeout(fxp_stats_update, sc, hz);#endif	return(0);}/* * Change media according to request. */intfxp_mediachange(ifp)	struct ifnet *ifp;{	if (ifp->if_flags & IFF_UP)		fxp_init(ifp->if_softc);	return (0);}/* * Notify the world which media we're using. */voidfxp_mediastatus(ifp, ifmr)	struct ifnet *ifp;	struct ifmediareq *ifmr;{	struct fxp_softc *sc = ifp->if_softc;	mii_pollstat(&sc->sc_mii);	ifmr->ifm_status = sc->sc_mii.mii_media_status;	ifmr->ifm_active = sc->sc_mii.mii_media_active;}/* * Add a buffer to the end of the RFA buffer list. * Return 0 if successful, 1 for failure. A failure results in * adding the 'oldm' (if non-NULL) on to the end of the list - * tossing out its old contents and recycling it. * The RFA struct is stuck at the beginning of mbuf cluster and the * data pointer is fixed up to point just past it. */intfxp_add_rfabuf(sc, oldm)	struct fxp_softc *sc;	struct mbuf *oldm;{	u_int32_t v;	struct mbuf *m;	u_int8_t *rfap;	MGETHDR(m, M_DONTWAIT, MT_DATA);	if (m != NULL) {		MCLGET(m, M_DONTWAIT);		if ((m->m_flags & M_EXT) == 0) {			m_freem(m);			if (oldm == NULL)				return 1;			m = oldm;			m->m_data = m->m_ext.ext_buf;		}	} else {		//printf("m=%x,oldm=%x\n",m,oldm);		if (oldm == NULL)			return 1;		m = oldm;		m->m_data = m->m_ext.ext_buf;	}	/*	 * Move the data pointer up so that the incoming data packet	 * will be 32-bit aligned.	 * Get a pointer to the base of the mbuf cluster and move	 * data start past it.	 */#if defined(__mips__)	/*	 * Sync the buffer so we can access it uncached.	 */	if (m->m_ext.ext_buf!=NULL) {		pci_sync_cache(sc->sc_pc, (vm_offset_t)m->m_ext.ext_buf,				MCLBYTES, SYNC_R);	}	m->m_data += RFA_ALIGNMENT_FUDGE;	rfap = (u_int8_t *)PHYS_TO_UNCACHED(vtophys(m->m_data));	//printf("rfap=%x\n",rfap);#else	m->m_data += RFA_ALIGNMENT_FUDGE;	rfap = m->m_data;#endif	m->m_data += sizeof(struct fxp_rfa);	*(u_int16_t *)(rfap + offsetof(struct fxp_rfa, size)) =	    htole16(MCLBYTES - sizeof(struct fxp_rfa) - RFA_ALIGNMENT_FUDGE);	/*	 * Initialize the rest of the RFA.  Note that since the RFA	 * is misaligned, we cannot store values directly.  Instead,	 * we use an optimized, inline copy.	 */	*(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_status)) = 0;	*(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_control)) =	    htole16(FXP_RFA_CONTROL_EL);	*(u_int16_t *)(rfap + offsetof(struct fxp_rfa, actual_size)) = 0;	v = -1;	fxp_lwcopy(&v,	    (u_int32_t *)(rfap + offsetof(struct fxp_rfa, link_addr)));	fxp_lwcopy(&v,	    (u_int32_t *)(rfap + offsetof(struct fxp_rfa, rbd_addr)));	/*	 * If there are other buffers already on the list, attach this	 * one to the end by fixing up the tail to point to this one.	 */	if (sc->rfa_headm != NULL) {		sc->rfa_tailm->m_next = m;		v = htole32(vtophys(rfap));		rfap = sc->rfa_tailm->m_ext.ext_buf + RFA_ALIGNMENT_FUDGE;#if defined(__mips__)		/* Noone should have touched this, so no flush req. */		rfap = (u_int8_t *)PHYS_TO_UNCACHED(vtophys(rfap));#endif /* __mips__ */		fxp_lwcopy(&v,		    (u_int32_t *)(rfap + offsetof(struct fxp_rfa, link_addr)));		*(u_int16_t *)(rfap + offsetof(struct fxp_rfa, rfa_control)) &=		    ~htole16(FXP_RFA_CONTROL_EL);	} else {		sc->rfa_headm = m;	}	sc->rfa_tailm = m;	return (m == oldm);}volatile intfxp_mdi_read(self, phy, reg)	struct device *self;	int phy;	int reg;{	struct fxp_softc *sc = (struct fxp_softc *)self;	int count = 10000;	int value;	CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,	    (FXP_MDI_READ << 26) | (reg << 16) | (phy << 21));	while (((value = CSR_READ_4(sc, FXP_CSR_MDICONTROL)) & 0x10000000) == 0	    && count--)		DELAY(10);	if (count <= 0)		printf(FXP_FORMAT ": fxp_mdi_read: timed out\n",		    FXP_ARGS(sc));	return (value & 0xffff);}static voidfxp_statchg(self)	struct device *self;{	/* XXX Update ifp->if_baudrate */}voidfxp_mdi_write(self, phy, reg, value)	struct device *self;	int phy;	int reg;	int value;{	struct fxp_softc *sc = (struct fxp_softc *)self;	int count = 10000;	CSR_WRITE_4(sc, FXP_CSR_MDICONTROL,	    (FXP_MDI_WRITE << 26) | (reg << 16) | (phy << 21) |	    (value & 0xffff));	while((CSR_READ_4(sc, FXP_CSR_MDICONTROL) & 0x10000000) == 0 &&	    count--)		DELAY(10);	if (count <= 0)		printf(FXP_FORMAT ": fxp_mdi_write: timed out\n",		    FXP_ARGS(sc));}intfxp_ioctl(ifp, command, data)	struct ifnet *ifp;	FXP_IOCTLCMD_TYPE command;	caddr_t data;{	struct fxp_softc *sc = ifp->if_softc;	struct ifreq *ifr = (struct ifreq *)data;	int s, error = 0;	s = splimp();	switch (command) {	case SIOCSIFADDR:#if !(defined(__NetBSD__) || defined(__OpenBSD__))	case SIOCGIFADDR:	case SIOCSIFMTU:#endif		error = ether_ioctl(ifp, command, data);		break;	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.		 * XXX If it's up then re-initialize it. This is so flags		 * such as IFF_PROMISC are handled.		 */		if (ifp->if_flags & IFF_UP) {			fxp_init(sc);		} else {			if (ifp->if_flags & IFF_RUNNING)				fxp_stop(sc, 1);		}		break;#ifdef USE_FXP_MCAST	case SIOCADDMULTI:	case SIOCDELMULTI:		sc->all_mcasts = (ifp->if_flags & IFF_ALLMULTI) ? 1 : 0;#if defined(__NetBSD__) || defined(__OpenBSD__)#if defined(__OpenBSD__)		error = (command == SIOCADDMULTI) ?		    ether_addmulti(ifr, &sc->arpcom) :		    ether_delmulti(ifr, &sc->arpcom);#else		error = (command == SIOCADDMULTI) ?		    ether_addmulti(ifr, &sc->sc_ethercom) :		    ether_delmulti(ifr, &sc->sc_ethercom);#endif		if (error == ENETRESET) {			/*			 * Multicast list has changed; set the hardware			 * filter accordingly.			 */			if (!sc->all_mcasts)				fxp_mc_setup(sc);			/*			 * fxp_mc_setup() can turn on all_mcasts if we run			 * out of space, so check it again rather than else {}.			 */			if (sc->all_mcasts)				fxp_init(sc);			error = 0;		}#else /* __FreeBSD__ */		/*		 * Multicast list has changed; set the hardware filter		 * accordingly.		 */		fxp_init(sc);		error = 0;#endif /* __NetBSD__ || __OpenBSD__ */		break;#endif	case SIOCSIFMEDIA:	case SIOCGIFMEDIA:		error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);		break;	default:		error = EINVAL;	}	(void) splx(s);	return (error);}#ifdef USE_FXP_MCAST/* * Program the multicast filter. * * We have an artificial restriction that the multicast setup command * must be the first command in the chain, so we take steps to ensure * this. By requiring this, it allows us to keep up the performance of * the pre-initialized command ring (esp. link pointers) by not actually * inserting the mcsetup command in the ring - i.e. its link pointer * points to the TxCB ring, but the mcsetup descriptor itself is not part * of it. We then can do 'CU_START' on the mcsetup descriptor and have it * lead into the regular TxCB ring when it completes. * * This function must be called at splimp. */voidfxp_mc_setup(sc)	struct fxp_softc *sc;{	struct fxp_cb_mcs *mcsp = sc->mcsp;	struct ifnet *ifp = &sc->sc_if;#if defined(__OpenBSD__)	struct ether_multistep step;	struct ether_multi *enm;#else	struct ifmultiaddr *ifma;#endif	int nmcasts;	/*	 * If there are queued commands, we must wait until they are all	 * completed. If we are already waiting, then add a NOP command	 * with interrupt option so that we're notified when all commands	 * have been completed - fxp_start() ensures that no additional	 * TX commands will be added when need_mcsetup is true.	 */	if (sc->tx_queued) {		struct fxp_cb_tx *txp;		/*		 * need_mcsetup will be true if we are already waiting for the		 * NOP command to be completed (see below). In this case, bail.		 */		if (sc->need_mcsetup)			return;		sc->need_mcsetup = 1;		/*		 * Add a NOP command with interrupt so that we are notified when all		 * TX commands have been processed.		 */		txp = sc->cbl_last->next;		txp->mb_head = NULL;		txp->cb_status = htole16(0);		txp->cb_command = htole16(FXP_CB_COMMAND_NOP | FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);		/*		 * Advance the end of list forward.		 */		sc->cbl_last->cb_command &= htole16(~FXP_CB_COMMAND_S);		sc->cbl_last = txp;		sc->tx_queued++;		/*		 * Issue a resume in case the CU has just suspended.		 */		fxp_scb_wait(sc);		CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);		/*		 * Set a 5 second timer just in case we don't hear from the		 * card again.		 */		ifp->if_timer = 5;		return;	}	sc->need_mcsetup = 0;	/*	 * Initialize multicast setup descriptor.	 */	mcsp->next = sc->cbl_base;	mcsp->mb_head = NULL;	mcsp->cb_status = htole16(0);	mcsp->cb_command = htole16(FXP_CB_COMMAND_MCAS | FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);	mcsp->link_addr = htole32(vtophys(&sc->cbl_base->cb_status));	nmcasts = 0;	if (!sc->all_mcasts) {#if defined(__OpenBSD__)		ETHER_FIRST_MULTI(step, &sc->arpcom, enm);		while (enm != NULL) {			if (nmcasts >= MAXMCADDR) {				sc->all_mcasts = 1;				nmcasts = 0;				break;			}			/* Punt on ranges. */			if (bcmp(enm->enm_addrlo, enm->enm_addrhi,			    sizeof(enm->enm_addrlo)) != 0) {				sc->all_mcasts = 1;				nmcasts = 0;				break;			}			bcopy(enm->enm_addrlo,			    (void *) &sc->mcsp->mc_addr[nmcasts][0], 6);			nmcasts++;			ETHER_NEXT_MULTI(step, enm);		}#else		for (ifma = ifp->if_multiaddrs.lh_first; ifma != NULL;		    ifma = ifma->ifma_link.le_next) {			if (ifma->ifma_addr->sa_family != AF_LINK)				continue;			if (nmcasts >= MAXMCADDR) {				sc->all_mcasts = 1;				nmcasts = 0;				break;			}			bcopy(LLADDR((struct sockaddr_dl *)ifma->ifma_addr),			    (void *) &sc->mcsp->mc_addr[nmcasts][0], 6);			nmcasts++;		}#endif	}	mcsp->mc_cnt = htole16(nmcasts * 6);	sc->cbl_first = sc->cbl_last = (struct fxp_cb_tx *) mcsp;	sc->tx_queued = 1;	/*	 * Wait until command unit is not active. This should never	 * be the case when nothing is queued, but make sure anyway.	 */	while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) ==	    FXP_SCB_CUS_ACTIVE) ;	/*	 * Start the multicast setup command.	 */	fxp_scb_wait(sc);	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&mcsp->cb_status));	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START);	ifp->if_timer = 2;	return;}#endif

⌨️ 快捷键说明

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