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

📄 if_fxp.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
		txp = sc->cbl_last->next;		/*		 * Go through each of the mbufs in the chain and initialize		 * the transmit buffer descriptors with the physical address		 * and size of the mbuf.		 */tbdinit:		for (m = mb_head, segment = 0; m != NULL; m = m->m_next) {			if (m->m_len != 0) {				if (segment == FXP_NTXSEG)					break;				txp->tbd[segment].tb_addr =				    htole32(vtophys(mtod(m, vm_offset_t)));				txp->tbd[segment].tb_size = htole32(m->m_len);#if defined(__mips__)				pci_sync_cache(sc->sc_pc, mtod(m, vm_offset_t),						m->m_len, SYNC_W);#endif				segment++;			}		}		if (m != NULL) {			struct mbuf *mn;			/*			 * We ran out of segments. We have to recopy this mbuf			 * chain first. Bail out if we can't get the new buffers.			 */			MGETHDR(mn, M_DONTWAIT, MT_DATA);			if (mn == NULL) {				m_freem(mb_head);				break;			}			if (mb_head->m_pkthdr.len > MHLEN) {				MCLGET(mn, M_DONTWAIT);				if ((mn->m_flags & M_EXT) == 0) {					m_freem(mn);					m_freem(mb_head);					break;				}			}			m_copydata(mb_head, 0, mb_head->m_pkthdr.len,			    mtod(mn, caddr_t));			mn->m_pkthdr.len = mn->m_len = mb_head->m_pkthdr.len;			m_freem(mb_head);			mb_head = mn;			goto tbdinit;		}		txp->tbd_number = segment;		txp->mb_head = mb_head;		txp->cb_status = htole16(0);		if (sc->tx_queued != FXP_CXINT_THRESH - 1) {			txp->cb_command =			    htole16(FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_S);		} else {			txp->cb_command =			    htole16(FXP_CB_COMMAND_XMIT | FXP_CB_COMMAND_SF | FXP_CB_COMMAND_S | FXP_CB_COMMAND_I);			/*			 * Set a 5 second timer just in case we don't hear			 * from the card again.			 */			ifp->if_timer = 5;		}		txp->tx_threshold = tx_threshold;			/*		 * Advance the end of list forward.		 */		sc->cbl_last->cb_command &= htole16(~FXP_CB_COMMAND_S);		sc->cbl_last = txp;		/*		 * Advance the beginning of the list forward if there are		 * no other packets queued (when nothing is queued, cbl_first		 * sits on the last TxCB that was sent out).		 */		if (sc->tx_queued == 0)			sc->cbl_first = txp;		sc->tx_queued++;#if NBPFILTER > 0		/*		 * Pass packet to bpf if there is a listener.		 */		if (ifp->if_bpf)			bpf_mtap(FXP_BPFTAP_ARG(ifp), mb_head);#endif	}	/*	 * We're finished. If we added to the list, issue a RESUME to get DMA	 * going again if suspended.	 */	if (txp != NULL) {		fxp_scb_wait(sc);		CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_RESUME);	}}/* * Process interface interrupts. */FXP_INTR_TYPEfxp_intr(arg)	void *arg;{	struct fxp_softc *sc = arg;	struct ifnet *ifp = &sc->sc_if;	u_int8_t statack;#if defined(__NetBSD__) || defined(__OpenBSD__)	int claimed = 0;	/*	 * If the interface isn't running, don't try to	 * service the interrupt.. just ack it and bail.	 */	if ((ifp->if_flags & IFF_RUNNING) == 0) {		statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK);		if (statack) {			claimed = 1;			CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);		}		return claimed;	}#endif	while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) {#if defined(__NetBSD__) || defined(__OpenBSD__)		claimed = 1;#endif		/*		 * First ACK all the interrupts in this pass.		 */		CSR_WRITE_1(sc, FXP_CSR_SCB_STATACK, statack);		/*		 * Free any finished transmit mbuf chains.		 */		if (statack & FXP_SCB_STATACK_CXTNO||FXP_SCB_STATACK_CNA) {			struct fxp_cb_tx *txp;			for (txp = sc->cbl_first; sc->tx_queued &&			    (txp->cb_status & htole16(FXP_CB_STATUS_C)) != 0;			    txp = txp->next) {				if (txp->mb_head != NULL) {					m_freem(txp->mb_head);					txp->mb_head = NULL;				}				sc->tx_queued--;			}			sc->cbl_first = txp;			ifp->if_timer = 0;#ifdef USE_FXP_MCAST			if (sc->tx_queued == 0) {				if (sc->need_mcsetup)					fxp_mc_setup(sc);			}#endif			/*			 * Try to start more packets transmitting.			 */			if (ifp->if_snd.ifq_head != NULL)				fxp_start(ifp);		}		//printf("transmit buf freed\n");		/*		 * Process receiver interrupts. If a no-resource (RNR)		 * condition exists, get whatever packets we can and		 * re-start the receiver.		 */		if (statack & (FXP_SCB_STATACK_FR | FXP_SCB_STATACK_RNR)) {			struct mbuf *m;			u_int8_t *rfap;rcvloop:			//printf("recving a packet\n");			m = sc->rfa_headm;			rfap = m->m_ext.ext_buf + RFA_ALIGNMENT_FUDGE;#if defined(__mips__)			/*			 * Read uncached so we don't create any funny			 * cache coherency side effects.			 */			//printf("rfap=%x\n",rfap);			if (*(u_int16_t *)(PHYS_TO_UNCACHED(vtophys(rfap)) +			    offsetof(struct fxp_rfa, rfa_status)) &			    htole16(FXP_RFA_STATUS_C)) {#else 			if (*(u_int16_t *)(rfap +			    offsetof(struct fxp_rfa, rfa_status)) &			    htole16(FXP_RFA_STATUS_C)) {#endif /* __mips__ */			        //printf("packet ready for %x\n",rfap);				/*				 * Remove first packet from the chain.				 */				sc->rfa_headm = m->m_next;				m->m_next = NULL;				/*				 * Add a new buffer to the receive chain.				 * If this fails, the old buffer is recycled				 * instead.				 */				if (fxp_add_rfabuf(sc, m) == 0) {					struct ether_header *eh;					u_int16_t total_len;					total_len = (htole16(*(u_int16_t *)(rfap +					    offsetof(struct fxp_rfa,					    actual_size)))) &					    (MCLBYTES - 1);					if (total_len <					    sizeof(struct ether_header)) {						m_freem(m);						goto rcvloop;					}					m->m_pkthdr.rcvif = ifp;					m->m_pkthdr.len = m->m_len =					    total_len -					    sizeof(struct ether_header);#ifdef BADPCIBRIDGE					m->m_data -= 2;					bcopy(m->m_data + 2, m->m_data, total_len);#endif#ifdef GODSONEV1					{						int i;					        if ((*(unsigned char* volatile)PHYS_TO_UNCACHED(vtophys(m->m_data+0)))!=0xff) {							for(i=0;i<total_len;i+=32){								m->m_data[i]=*(unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+i));#ifdef BEBUG_DMA_FLUSH_CACHE								printf("%x: %2x\n", (unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+i)),*(unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+i)));								printf("%x: %2x\t%x,(%2x)\n", (unsigned int)&m->m_data[i],(unsigned int)(unsigned char)m->m_data[80], (unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+i)),*(unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+i)));#endif							}						}						m->m_data[total_len-1]=*(unsigned char*)PHYS_TO_UNCACHED(vtophys(m->m_data+total_len-1));												}#endif					eh = mtod(m, struct ether_header *);#if NBPFILTER > 0					if (ifp->if_bpf)						bpf_tap(FXP_BPFTAP_ARG(ifp),						    mtod(m, caddr_t),						    total_len); #endif /* NBPFILTER > 0 */					m->m_data +=					    sizeof(struct ether_header);					//printf("ether input,size=%d\n",total_len);					ether_input(ifp, eh, m);				}				else {#ifndef Pocono					int i; 					for (i=0;i<100;i++)					printf("HELP! fxp recycling rxbuf!\n");#endif				}				goto rcvloop;			}			if (statack & FXP_SCB_STATACK_RNR) {				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);			}		}	}#if defined(__NetBSD__) || defined(__OpenBSD__)	return (claimed);#endif}/* * Update packet in/out/collision statistics. The i82557 doesn't * allow you to access these counters without doing a fairly * expensive DMA to get _all_ of the statistics it maintains, so * we do this operation here only once per second. The statistics * counters in the kernel are updated from the previous dump-stats * DMA and then a new dump-stats DMA is started. The on-chip * counters are zeroed when the DMA completes. If we can't start * the DMA immediately, we don't wait - we just prepare to read * them again next time. */voidfxp_stats_update(arg)	void *arg;{#ifdef USE_FXP_STATS	struct fxp_softc *sc = arg;	struct ifnet *ifp = &sc->sc_if;	struct fxp_stats *sp = sc->fxp_stats;	int s;	ifp->if_opackets += sp->tx_good;	ifp->if_collisions += sp->tx_total_collisions;	if (sp->rx_good) {		ifp->if_ipackets += sp->rx_good;		sc->rx_idle_secs = 0;	} else {		sc->rx_idle_secs++;	}	ifp->if_ierrors +=	    sp->rx_crc_errors +	    sp->rx_alignment_errors +	    sp->rx_rnr_errors +	    sp->rx_overrun_errors;	/*	 * If any transmit underruns occured, bump up the transmit	 * threshold by another 512 bytes (64 * 8).	 */	if (sp->tx_underruns) {		ifp->if_oerrors += sp->tx_underruns;		if (tx_threshold < 192)			tx_threshold += 64;	}	s = splimp();	/*	 * If we haven't received any packets in FXP_MAC_RX_IDLE seconds,	 * then assume the receiver has locked up and attempt to clear	 * the condition by reprogramming the multicast filter. This is	 * a work-around for a bug in the 82557 where the receiver locks	 * up if it gets certain types of garbage in the syncronization	 * bits prior to the packet header. This bug is supposed to only	 * occur in 10Mbps mode, but has been seen to occur in 100Mbps	 * mode as well (perhaps due to a 10/100 speed transition).	 */	if (sc->rx_idle_secs > FXP_MAX_RX_IDLE) {		sc->rx_idle_secs = 0;		fxp_mc_setup(sc);	}	/*	 * If there is no pending command, start another stats	 * dump. Otherwise punt for now.	 */	if (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) == 0) {		/*		 * Start another stats dump.		 */		CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND,		    FXP_SCB_COMMAND_CU_DUMPRESET);	} else {		/*		 * A previous command is still waiting to be accepted.		 * Just zero our copy of the stats and wait for the		 * next timer event to update them.		 */		sp->tx_good = 0;		sp->tx_underruns = 0;		sp->tx_total_collisions = 0;		sp->rx_good = 0;		sp->rx_crc_errors = 0;		sp->rx_alignment_errors = 0;		sp->rx_rnr_errors = 0;		sp->rx_overrun_errors = 0;	}	/* Tick the MII clock. */	mii_tick(&sc->sc_mii);	splx(s);	/*	 * Schedule another timeout one second from now.	 */	timeout(fxp_stats_update, sc, hz);#endif}/* * Stop the interface. Cancels the statistics updater and resets * the interface. */voidfxp_stop(sc, drain)	struct fxp_softc *sc;	int drain;{	struct ifnet *ifp = &sc->sc_if;	struct fxp_cb_tx *txp;	int i;	/*	 * Turn down interface (done early to avoid bad interactions	 * between panics, shutdown hooks, and the watchdog timer)	 */	ifp->if_timer = 0;	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);#ifdef USE_FXP_STATS	/*	 * Cancel stats updater.	 */	untimeout(fxp_stats_update, sc);#endif	/*	 * Issue software reset	 */	CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET);	DELAY(10);	/*	 * Release any xmit buffers.	 */	for (txp = sc->cbl_first; txp != NULL && txp->mb_head != NULL;	    txp = txp->next) {		m_freem(txp->mb_head);		txp->mb_head = NULL;	}	sc->tx_queued = 0;	if (drain) {		/*		 * Free all the receive buffers then reallocate/reinitialize		 */		if (sc->rfa_headm != NULL)			m_freem(sc->rfa_headm);		sc->rfa_headm = NULL;		sc->rfa_tailm = NULL;		for (i = 0; i < FXP_NRFABUFS; i++) {			if (fxp_add_rfabuf(sc, NULL) != 0) {				/*				 * This "can't happen" - we're at splimp()				 * and we just freed all the buffers we need				 * above.				 */				panic("fxp_stop: no buffers!");			}		}	}}/* * Watchdog/transmission transmit timeout handler. Called when a * transmission is started on the interface, but no interrupt is * received before the timeout. This usually indicates that the * card has wedged for some reason. */voidfxp_watchdog(ifp)	struct ifnet *ifp;{	struct fxp_softc *sc = ifp->if_softc;	int s;		log(LOG_ERR, FXP_FORMAT ": device timeout\n", FXP_ARGS(sc));	ifp->if_oerrors++;	if (fxp_init(sc) != 0) {		ifp->if_timer = FXP_DELAY_BEFORE_REINIT;		return;	}	/* Empty transmit queue */	s = splimp();      /* Protect Q-handling in fxp_start */	if (ifp->if_snd.ifq_head != NULL)	{	     fxp_start(ifp);	}	splx(s);}intfxp_init(xsc)	void *xsc;{	struct fxp_softc *sc = xsc;	struct ifnet *ifp = &sc->sc_if;	struct fxp_cb_config *cbp;	struct fxp_cb_ias *cb_ias;	struct fxp_cb_tx *txp;	int i, s, prm;	s = splimp();	/*	 * Cancel any pending I/O	 */	fxp_stop(sc, 0);	prm = (ifp->if_flags & IFF_PROMISC) ? 1 : 0;	/*	 * Initialize base of CBL and RFA memory. Loading with zero	 * sets it up for regular linear addressing.	 */	printf("IO write loop test..\n");	for(i=0;i<10000;i++) {	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, 0);	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_BASE);	fxp_scb_wait(sc);	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_RU_BASE);	}	printf("IO write loop test done\n");	/*	 * Initialize base of dump-stats buffer.	 */	fxp_scb_wait(sc);	CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(sc->fxp_stats));	CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_DUMP_ADR);	/*	 * We temporarily use memory that contains the TxCB list to	 * construct the config CB. The TxCB list memory is rebuilt	 * later.	 */	cbp = (struct fxp_cb_config *) sc->cbl_base;	/*	 * This bcopy is kind of disgusting, but there are a bunch of must be

⌨️ 快捷键说明

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