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

📄 if_wlp.c

📁 WaveLAN无线网卡Linux驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
voidwlpinit(sc)	struct wlp_softc *sc;{	int             s;	s = splimp();	if (sc->sc_gone)		goto done;#if 0	if (sc->sc_iftype == IFTYPE_REDWING) {		/*		 * Fix for ASIC Problem ???		 */		IOWrite1(0x0C, P12_SERIAL_CLOCK);		IOWrite1(0x0C, 0x00);	}#endif	/*	 * (1) Disable Receive (2) Reset the 82593	 */	IOWrite1(0x00, P0_RCV_DISABLE);	IOWrite1(0x00, P0_RESET);	DELAY(200);	if (sc->sc_ifconfig(sc)) {		printf("wlp%d: Configuration failed.\n", sc->sc_unit);		goto done;	}	if (sc->sc_iftype == IFTYPE_REDWING) {		/*		 * (1) Reset the Receive DMA Counter (Port 0x02 and 0x03)		 * (2) Reset the Transmit DMA Counter (Port 0x04 and 0x05)		 * (3) Reset the Interrupt Control Port (Port 0x07)		 * (4) Enable Collision Avoidance and set IFS (Port 0x08)		 * (5) Reset the Page Control Port (Port 0x09)		 * (6) Reset the status information		 */		RW_ResetRXDMA();		sc->sc_rxnext = 0;		RW_ResetTXDMA();		IOWrite1(0x07, 0x00);		IOWrite1(0x08, IORead1(0x08) | P8_CA_ENABLE | (P8_IFS_TIME & IFS_TIME));#if 0		IOWrite1(0x09, 0x00);#endif	} else if (sc->sc_iftype == IFTYPE_WAVELAN) {#ifdef WAVELAN_ROAMING		sc->sc_rs.rs_disabletx = 0;#endif		sc->sc_nwidprom = 0;	/* NWID Promisc Mode */		/*		 * (1) Reset the RX DMA		 */		WLP_ResetRXDMA();		sc->sc_rxnext = 0;	}	/*	 * (1) Switch to Port 1         * (2) Reset/Setup the Ring Buffer Management	 * (3) Enable interrupts         * (4) Switch to Port 0	 * (5) Enable packet reception	 */	IOWrite1(0x00, P0_SWITCH_TO_P1);	IOWrite1(0x00, P1_RST_RING_MGMT);	IOWrite1(0x00, P1_ENABLE_INT);	IOWrite1(0x00, P1_SWITCH_TO_P0);	IOWrite1(0x00, P0_RCV_ENABLE);	sc->sc_ac.ac_if.if_flags |= IFF_RUNNING;	sc->sc_ac.ac_if.if_flags &= ~IFF_OACTIVE;#ifdef WAVELAN_ROAMING	sc->sc_rs.rs_activetx = 0;#endif	/*	 * Try to start output	 */	wlpstart(&sc->sc_ac.ac_if);done:	splx(s);}/* * ====================================================================== * PACKET TRANSMISSION ROUTINES * ====================================================================== */voidwlpwatchdog(ifp)	struct ifnet   *ifp;{	struct wlp_softc *sc = (struct wlp_softc *) ifp->if_softc;	ifp->if_oerrors++;	if (sc->sc_gone)		return;	printf("wlp%d: watchdog resetting interface\n", ifp->if_unit);	wlpinit(sc);		/* calls wlpstart() */}static voidwlpstart(ifp)	struct ifnet   *ifp;{	struct wlp_softc *sc = ifp->if_softc;	struct mbuf    *m;	int             s;	s = splimp();	/*	 * If the card has been removed, quit.	 */	if (sc->sc_gone)		goto done;	/*	 * If no resources have been allocated for this interface, quit.	 */	if ((ifp->if_flags & IFF_RUNNING) == 0 ||	    (ifp->if_flags & IFF_OACTIVE))		goto done;#ifdef WAVELAN_ROAMING	if(sc->sc_rs.rs_activetx)		goto done;#endif#ifdef MONARCH_DSRIFQ	DSRIFQ_DEQUEUE(ifp, m);	if(0 == m)		goto done;#else	/*	 * Determine if there's anything to send.	 */	m = ifp->if_snd.ifq_head;	if (!m)		goto done;	IF_DEQUEUE(&ifp->if_snd, m);#endif /* MONARCH_DSRIFQ */	wlptransmit(sc, m);	m_freem(m);done:	splx(s);}/* *  This routine is called from wlpstart() and from the *  roaming code - jgb 02/13/99 */voidwlptransmit(sc, m)	struct wlp_softc *sc;	struct mbuf *m;{	struct ifnet *ifp = &sc->sc_ac.ac_if;	struct mbuf *m0;	u_int16_t len;	u_int16_t totlen;#ifdef WAVELAN_ROAMING	if(sc->sc_rs.rs_activetx) {#ifdef notdef		printf("wlptransmit: returning... (activetx set)\n");#endif              return;      }#endif	/*	 * Determine the packet's length	 */	for (m0 = m, totlen = 0; m0; m0 = m0->m_next)		totlen += m0->m_len;	/*	 * If the packet is too long, discard it.	 */	if (totlen > ETHER_MAX_LEN) {		++ifp->if_oerrors;		goto done;	}#ifdef WLP_STATS	sc->sc_txcnt++;#endif	ifp->if_opackets++;	ifp->if_obytes += totlen;	ifp->if_flags |= IFF_OACTIVE;	ifp->if_timer = 2; /* 2 seconds */#ifdef WAVELAN_ROAMING	sc->sc_rs.rs_activetx = 1;#endif	if (sc->sc_iftype == IFTYPE_REDWING) {		len = 2;		for (m0 = m; m0; m0 = m0->m_next) {			MEMWrite(mtod(m0, caddr_t), RW_RXWINDOW + len, m0->m_len);			len += m0->m_len;		}		if (len < ETHER_MIN_LEN + 2) {			int             i;			for (i = len; i <= (ETHER_MIN_LEN + 2); i++)				MEMWrite1(RW_RXWINDOW + i, 0x00);			len = (ETHER_MIN_LEN + 2);		}		MEMWrite1(RW_RXWINDOW + len, P0_NOP);		MEMWrite1(RW_RXWINDOW + len + 1, P0_NOP);		len -= 2;		MEMWrite1(RW_RXWINDOW, len & 0xFF); /* Insert "Byte Count" */		MEMWrite1(RW_RXWINDOW + 1, (len >> 8) & 0xFF);		/*		 * (1) Update the interface flags		 * (2) Reset the TX DMA counter		 * (3) Give the Card a Collision Avoidance Seed		 */		RW_ResetTXDMA();#if 0		IOWrite1(0x0A, time.tv_usec & P10_CASEED);#endif	} else if (sc->sc_iftype == IFTYPE_WAVELAN) {		/*		 * Pointer at the beginning of the Transmit Buffer		 */		WLP_PointTXBUF(WLP_TXBASE);		if (totlen < ETHER_MIN_LEN)			totlen = ETHER_MIN_LEN;		IOWrite1(0x04, (totlen & 0xFF));		IOWrite1(0x04, ((totlen >> 8) & 0xFF));		for (m0 = m, len = 0; m0; m0 = m0->m_next) {			IOWrite(0x04, mtod(m0, caddr_t), m0->m_len);			len += m0->m_len;		}		for (; len < ETHER_MIN_LEN; len++)			IOWrite1(0x04, 0x00);		IOWrite1(0x04, P0_NOP);		IOWrite1(0x04, P0_NOP);		/*		 * (1) Reset the TX DMA counter		 */		WLP_ResetTXDMA();	}	/*	 * (1) Issue the transmit command	 */	IOWrite1(0x00, P0_TRANSMIT);#if NBPFILTER > 0	if (ifp->if_bpf) {		bpf_mtap(ifp, m);	}#endifdone:	;}/* * ====================================================================== * INTERRUPT SERVICE ROUTINE * ====================================================================== */voidwlpintr(unit)	int             unit;{	struct wlp_softc *sc = &wlp_softc[unit];	struct ifnet   *ifp = &(sc->sc_ac.ac_if);	u_int8_t        status;#ifdef WLP_STATS	sc->sc_irqcnt++;#endif	/*	 * If the card has been removed, quit.	 */	if (sc->sc_gone) {		printf("wlp%d: Interrupt received but card is missing\n",			sc->sc_unit);		return;	}#if 0	/*	 * Disable INTs	 */	IOWrite1(0x00, P0_SWITCH_TO_P1);	IOWrite1(0x00, P1_DISABLE_INT);	IOWrite1(0x00, P1_SWITCH_TO_P0);#endif	while (1) {		if (sc->sc_iftype == IFTYPE_REDWING) {			/*			 * (1) Check for Timer IRQ from Alliston			 * (2) Check for Carrier Sense IRQ from Alliston			 * (3) Check for IRQs from the 82593			 */			status = IORead1(0x07);			if (status & P7_TIRQ) {	/* Timer IRQ */				printf("\tTimer IRQ received\n");				IOWrite1(0x07, status | P7_TIRQ);				DELAY(100);				continue;			}			if (status & P7_CIRQ) {	/* Carrier Sense IRQ */				printf("\tCarrier Sense IRQ received\n");				IOWrite1(0x07, status | P7_CIRQ);				DELAY(100);				continue;			}		}		IOWrite1(0x00, P0_NOP);	/* Reset Register Pointer */		status = IORead1(0x00);		if ((status & P0_S0_INT) == 0)	/* 82593 IRQ */			goto done;		switch (status & P0_S0_EVENT) {		case END_OF_FRAME:                {			u_int32_t       RFP = 0;   /* Receive Frame Pointer */			u_int16_t       BlockLength = 0;			u_int16_t       First = 0;			u_int16_t       Current;			u_int16_t       Next;			u_int8_t        RxPage;			if (status != (P0_S0_INT | P0_S0_RCV | P0_S0_CHNL | END_OF_FRAME)) {				printf("wlp%d: invalid END_OF_FRAME status\n",					sc->sc_unit);			}			if (sc->sc_iftype == IFTYPE_REDWING) {				/*				 * Figure out where the next frame is...				 */				IOWrite1(0x00, P0_NOP | P0_STATUS2);				RFP = IORead1(0x00);				RFP += (IORead1(0x00) << 8);				/*				 * Take all of the frames out of the				 * receive buffer that were received				 * as of the time this interrupt was				 * generated.				 */				if (RFP == sc->sc_rxnext)					goto rx_done;				/*				 * (1) Map the correct page into memory.				 * (2) Figure out how many bytes we have to process.				 */				RxPage = ((((RFP & 0x3C00) >> 10) - 3) & 0x0F);				IOWrite1(0x09, (IORead1(0x09) & P9_TXBUF) | RxPage);				if (RFP > sc->sc_rxnext) {					BlockLength = RFP - sc->sc_rxnext;				} else {					BlockLength = RW_RXBUFSIZE - sc->sc_rxnext + RFP;				}				First = ((sc->sc_rxnext - (RxPage << 10)) & 0xFFF);			} else if (sc->sc_iftype == IFTYPE_WAVELAN) {				/*				 * Figure out where the next frame is...				 */				RFP = IORead1(0x02);				RFP |= ((IORead1(0x03) & P3_RPLH) << 8);				if (RFP == sc->sc_rxnext)					goto rx_done;				/*				 * Take all of the frames out of the				 * receive buffer that were received				 * as of the time this interrupt was				 * generated.				 */				if (RFP > sc->sc_rxnext) {					BlockLength = RFP - sc->sc_rxnext;				} else {					BlockLength = WLP_RXBUFSIZE - sc->sc_rxnext + RFP;				}				First = sc->sc_rxnext;			}			Current = 0;#define WORKING 1#define ERROR   2#define READY   3			do {				int             rx_status = 0;				int             sigstat = 0;				u_int32_t       len = 0;				u_int16_t       RxFrameStatus = WORKING;				u_int16_t       EBYTES = (sc->sc_iftype == IFTYPE_REDWING ? 2 : 5);				Next = BlockLength;				while (RxFrameStatus == WORKING) {					if (sc->sc_iftype == IFTYPE_REDWING) {						rx_status = MEMRead1(First + Next - 4);						rx_status += (MEMRead1(First + Next - 3) << 8);						len = MEMRead1(First + Next - 2);						len += (MEMRead1(First + Next - 1) << 8);					} else if (sc->sc_iftype == IFTYPE_WAVELAN) {						WLP_PointRXBUF(First + Next - 7);						rx_status = IORead1(0x04);						rx_status += (IORead1(0x04) << 8);						len = IORead1(0x04);						len += (IORead1(0x04) << 8);						sigstat = ((IORead1(0x04) & 0x3F) << SIGL_SHIFT);						sigstat += ((IORead1(0x04) & 0x3F) << SILL_SHIFT);						sigstat += ((IORead1(0x04) & 0x0F) << SIGQ_SHIFT);					}					/*					 * I don't check ETHER_MIN_LEN because					 * of BEACONS					 */					if ((rx_status & RX_STAT_BITS) != (RX_RCV_OK | 0x10) ||					    (len - EBYTES > ETHER_MAX_LEN)) {						RxFrameStatus = ERROR;						ifp->if_ierrors++;#ifdef WLP_STATS						if (rx_status & RX_RCLD)							sc->sc_rcvcld++;						if (rx_status & RX_IA_MCH)							sc->sc_iamch++;						if (rx_status & RX_SRT_FRM)							sc->sc_srtfrm++;						if (rx_status & RX_OVRRUN)							sc->sc_overrun++;						if (rx_status & RX_ALG_ERR)							sc->sc_algerr++;						if (rx_status & RX_CRC_ERR)							sc->sc_crcerr++;						if (rx_status & RX_LEN_ERR)							sc->sc_lenerr++;#endif					} else if (((Next - (len + EBYTES)) & RXBUF_MAX_ADDR) == Current) {						RxFrameStatus = READY;					} else {						Next = (Next - (len + EBYTES)) & RXBUF_MAX_ADDR;					}					/*					 * Sanity Check					 */					if (Next < Current) {						goto rx_fatal_error;					}				}	/* while( WORKING ) */#ifdef WLP_STATS				sc->sc_rxcnt++;#endif				if (RxFrameStatus == READY) {					ifp->if_ipackets++;					ifp->if_ibytes += (Next - (Current + EBYTES + 2));#ifdef WLP_STATS					sc->sc_rxok++;#endif					if (sc->sc_iftype == IFTYPE_REDWING) {						wlpread(sc, Next - (Current + 4), 0, First + Current);					} else if (sc->sc_iftype == IFTYPE_WAVELAN) {						WLP_PointRXBUF((First + Current) & RXBUF_MAX_ADDR);						wlpread(sc, (Next - (Current + 7)) & RXBUF_MAX_ADDR, sigstat, 0);					}				} else {					/* RxFrameStatus == ERROR */				}				Current = Next;			} while (Current != BlockLength);#undef WORKING#undef READY#undef ERROR			goto rx_done;	rx_fatal_error:			printf("wlp%d: receive error\n", ifp->if_unit);			ifp->if_ierrors++;			IOWrite1(0x00, P0_RCV_DISABLE);			IOWrite1(0x00, P0_SWITCH_TO_P1);			IOWrite1(0x00, P1_RST_RING_MGMT);			IOWrite1(0x00, P1_SWITCH_TO_P0);			if (sc->sc_iftype == IFTYPE_REDWING) {				RW_ResetRXDMA();			} else if (sc->sc_iftype == IFTYPE_WAVELAN) {				WLP_ResetRXDMA();			}			sc->sc_rxnext = 0;			RFP = 0;			IOWrite1(0x00, P0_RCV_ENABLE);	rx_done:			sc->sc_rxnext = RFP;		}		break;		case TRANSMIT_DONE:		case TRANSMIT_NOCRC_DONE:		case RETRANSMIT_DONE:			{				u_int16_t       tx_status;				ifp->if_timer = 0;	/* stop the watchdog							 * timer */				tx_status = IORead1(0x00);				tx_status |= (IORead1(0x00) << 8);				if ((tx_status & TX_STAT_BITS) == TX_OK) {#ifdef WLP_STATS					sc->sc_txok++;#endif					goto tx_done;				}				/* ERROR: Unsuccessful Transmission */				if (tx_status & (TX_FRTL | TX_COLL |						 TX_UND_RUN | TX_LST_CTS))					ifp->if_oerrors++;#ifdef WLP_STATS				if (tx_status & TX_FRTL)					sc->sc_frtl++;				if (tx_status & TX_MAX_COL)					sc->sc_maxcol++;				if (tx_status & TX_UND_RUN)					sc->sc_undrun++;				if (tx_status & TX_LST_CTS)					sc->sc_lostcts++;				if (tx_status & TX_LST_CRS)					sc->sc_lostcrs++;				if (tx_status & TX_LTCOL)					sc->sc_ltcol++;				if (tx_status & TX_COLL)					sc->sc_col++;#endif		tx_done:

⌨️ 快捷键说明

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