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

📄 wlc_pio.c

📁 wi-fi sources for asus wl138g v2 pci card
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (len) {		W_REG(&regs->fifocontrol, XFC_LO);		W_REG(fifo, (uint16)*(uint8*)va16);	}}/* 4-byte mode for corerev >= 8. poke a chain of fragment buffers into tx channel fifo */static int_wlc_pio4_tx(pio_info_t *pt, void *p0){	pio4regs_t *pioregs = pt->p4txregs;	void *p;	osl_t *osh;	uint totlen;	uchar *va;	uint len;	WL_TRACE(("wl%d: _wlc_pio4_tx\n", pt->pub->unit));	ASSERT(pioregs);	osh = pt->pub->osh;	totlen = pkttotlen(osh, p0);	/* ASSERT(_wlc_pio_tx_available((pio_t *)pt, totlen, 1)); */	PIO_ADD_TX_CNT(pt, totlen);	/* clear frameready */	W_REG(&pioregs->fifocontrol, XFC4_FR);	for (p = p0; p; p = PKTNEXT(osh, p)) {		va = PKTDATA(osh, p);		len = PKTLEN(osh, p);		/* skip any zero-byte buffers */		if (len == 0)			continue;		_wlc_pio4_xmtfifo(pt, pioregs, va, len);		totlen -= len;	}	W_REG(&pioregs->fifocontrol, XFC4_EF);	/* save frag in pio sw queue */	pktenq(&pt->txpioq, p0);	return 0;}/* 4-byte mode for corerev >= 8.  move tx data to fifo */static void_wlc_pio4_xmtfifo(pio_info_t *pt, pio4regs_t *regs, uchar *va, uint len){	uint i;	uint32 *va32;	volatile uint32 *fifo;#ifndef IL_BIGENDIAN	uint byte_valid[] = {0, 1, 3, 7}; /* for first byte, first word, first three bytes */#else	uint byte_valid[] = {0, 8, 12, 14}; /* for first byte, first word, first three bytes */#endif /* IL_BIGENDIAN */	if (len == 0)		return;	fifo = &regs->fifodata;	/* write any leading bytes which not aligned to 32-bit boundary */	i = (uint)((uintptr)va & 3);	if (i) {		i = MIN(i, len);		W_REG(&regs->fifocontrol, byte_valid[i]);		W_REG(fifo, *(uint32*)va);		va += i;		len -= i;	}	va32 = (uint32*)va;	if (len >= 4) {		{			/* all 4 bytes are valid */			W_REG(&regs->fifocontrol, 0xf);			while (len >= 4) {				W_REG(fifo, *va32);				va32++;				len -= 4;			}		}	}	if (len) {		/* write any trailing bytes */		W_REG(&regs->fifocontrol, byte_valid[len]);		W_REG(fifo, *va32);	}}/* shared rx process between pio2 and pio4 */static bool_wlc_pio_rxcheck(pio_info_t *pt, int len, void **p){	/* flush giant frames */	if (len > RXBUFSZ) {		WL_ERROR(("wl%d: %s: giant frame. len %d\n", pt->pub->unit, __FUNCTION__, len));		WLCNTINCR(pt->pub->_cnt.rxgiant);		return FALSE;	}	/* flush runt frames if not tx status frame */	if (len == 0 && pt->_fifo != RX_TXSTATUS_FIFO) {		WL_ERROR(("wl%d: %s: runt frame\n", pt->pub->unit, __FUNCTION__));		WLCNTINCR(pt->pub->_cnt.rxrunt);		return FALSE;	}	/* alloc a new buf-wlc_recvdata() fragment reassembly requires RXBUFSZ receive buffers */	if ((*p = PKTGET(pt->pub->osh, RXBUFSZ, FALSE)) == NULL) {		WL_ERROR(("wl%d: %s: out of rxbufs\n", pt->pub->unit, __FUNCTION__));		WLCNTINCR(pt->pub->_cnt.rxnobuf);		return FALSE;	}	return TRUE;}/* 2-byte mode for corerev < 8.  move rx fifo data to buffer */static void*_wlc_pio2_rx(pio_info_t *pt){	void *p = NULL;	osl_t *osh;	uint8 *va;	uint16 rxstatus;	uint32 fifocontrol;	d11rxhdr_t *rxh;	int i, len, rxhdrlen = 0;	pio2regs_t *regs;	uint16 *va16;	volatile uint16 *dptr, w;	WL_TRACE(("wl%d: _wlc_pio2_rx\n", pt->pub->unit));	osh = pt->pub->osh;	regs = pt->p2rxregs;	ASSERT(regs);	/* if frame is not ready, return */	if (!(R_REG(&regs->fifocontrol) & RFC_FR))		return NULL;	/* clear frame ready */	W_REG(&regs->fifocontrol, RFC_FR);	/* wait for data valid */	SPINWAIT((((fifocontrol = R_REG(&regs->fifocontrol)) & RFC_DR) == 0), 100);	if ((fifocontrol & RFC_DR) == 0) {		WL_ERROR(("wl%d: %s: data ready never set\n", pt->pub->unit, __FUNCTION__));		return NULL;	}	dptr = &regs->fifodata;	/* rcv data */	/* read the first 16bits of the rxhdr which gives the length */	w = R_REG(dptr);	/* hanlde both Big and Little endian */	len = ltoh16(w);	if (!_wlc_pio_rxcheck(pt, len, &p))		goto flush;	va = (uint8 *)PKTDATA(osh, p);	ASSERT(ISALIGNED((uintptr)va, sizeof(uint32)));	PKTSETLEN(osh, p, (HWRXOFF + len));	/* get header length */	rxhdrlen = (pt->_fifo == RX_TXSTATUS_FIFO) ? TXSTATUS_LEN : RXHDR_LEN;	/* read the rxheader from the fifo first */	va16 = (uint16 *)va;	*va16++ = w;	i = (rxhdrlen / 2) - 1;	{		while (i--) {			*va16 = R_REG(dptr);			va16++;		}	}	/* toss bad packet before read/pass up whole frame */	rxh = (d11rxhdr_t*)va;	rxstatus = ltoh16(rxh->RxStatus1);	if (rxstatus & RXS_FCSERR) {		/* ucode should toss it */		ASSERT(0);		goto flush;	}	/* tx status frame only has header */	if (pt->_fifo == RX_TXSTATUS_FIFO)		return (p);	/* read the frame */	va16 = (uint16*) &va[HWRXOFF];	if (rxstatus & RXS_PBPRES) {		/* advance data pointer by two-byte for address alignment */		va16++;		PKTSETLEN(osh, p, (HWRXOFF + len + 2));	}	{		i = len / 2;		while (i--) {			*va16 = R_REG(dptr);			va16++;		}		/* read last (odd) byte */		if (len & 1) {			*va16 = R_REG(dptr) & 0xff;		}	}	return (p);flush:	/* flush rx frame */	W_REG(&regs->fifocontrol, RFC_DR);	if (p)		PKTFREE(osh, p, FALSE);	return (NULL);}/* 4-byte mode for corerev >= 8.  move rx fifo data to buffer */static void*_wlc_pio4_rx(pio_info_t *pt){	void *p = NULL;	osl_t *osh;	uint8 *va;	uint16 rxstatus;	uint32 fifocontrol;	d11rxhdr_t *rxh;	int i, len, rxhdrlen = 0;	pio4regs_t *regs;	uint32 *va32;	volatile uint32 *dptr, w;	WL_TRACE(("wl%d: _wlc_pio4_rx\n", pt->pub->unit));	osh = pt->pub->osh;	regs = pt->p4rxregs;	ASSERT(regs);	/* if frame is not ready, return */	if (!(R_REG(&regs->fifocontrol) & RFC_FR))		return NULL;	/* clear frame ready */	W_REG(&regs->fifocontrol, RFC_FR);	/* wait for data valid */	SPINWAIT((((fifocontrol = R_REG(&regs->fifocontrol)) & RFC_DR) == 0), 100);	if ((fifocontrol & RFC_DR) == 0) {		WL_ERROR(("wl%d: %s: data ready never set\n", pt->pub->unit, __FUNCTION__));		return NULL;	}	dptr = &regs->fifodata;	/* rcv data */	/* read the first 16bits of the rxhdr which gives the length */	w = R_REG(dptr);	/* hanlde both Big and Little endian */	len = (uint16)ltoh32(w);	if (!_wlc_pio_rxcheck(pt, len, &p))		goto flush;	va = (uint8 *)PKTDATA(osh, p);	ASSERT(ISALIGNED((uintptr)va, sizeof(uint32)));	PKTSETLEN(osh, p, (HWRXOFF + len));	/* get header length */	rxhdrlen = (pt->_fifo == RX_TXSTATUS_FIFO) ? TXSTATUS_LEN : RXHDR_LEN;	/* read the rxheader from the fifo first */	va32 = (uint32 *)va;	*va32++ = w;	i = (rxhdrlen / 4) - 1;	{		while (i--) {			*va32 = R_REG(dptr);			va32++;		}	}	if (rxhdrlen % 4) {		ASSERT((rxhdrlen % 4) == 2);		*((uint16 *)va32) = R_REG((volatile uint16 *)dptr);		va32 = (uint32 *)((int8*)va32 + 2);	}	/* toss bad packet before read/pass up whole frame */	rxh = (d11rxhdr_t*)va;	rxstatus = ltoh16(rxh->RxStatus1);	if (rxstatus & RXS_FCSERR) {		/* ucode should toss it */		ASSERT(0);		goto flush;	}	/* tx status frame only has header */	if (pt->_fifo == RX_TXSTATUS_FIFO)		return (p);	/* read the frame */	va32 = (uint32*) &va[HWRXOFF];	/* align buffer to 32-bit boundary */	if ((uintptr)va32 % 4 && len >= 2) {		*((uint16 *)va32) = R_REG((volatile uint16 *)dptr);		va32 = (uint32 *)((int8*)va32 + 2);		len -= 2;	}	i = len / 4;	{		while (i--) {			*va32 = R_REG(dptr);			va32++;		}	}	/* read the remain bytes if exist */	i = len % 4;	if (i) {		uint32 mask[] = {0, 0x000000ff, 0x0000ffff, 0x00ffffff};		*va32 = R_REG(dptr) & mask[i];	}	return (p);flush:	/* flush rx frame */	W_REG(&regs->fifocontrol, RFC_DR);	if (p)		PKTFREE(osh, p, FALSE);	return (NULL);}static void*_wlc_pio_getnexttxp(pio_info_t *pt){	return pktdeq(&pt->txpioq);}static int_wlc_pio_txreclaim(pio_info_t *pt){	void *p;	while ((p = pktdeq(&pt->txpioq)))		PKTFREE(pt->pub->osh, p, TRUE);	/* reset per-fifo software counters */	pt->txfrmcnt = 0;	pt->txdatacnt = 0;	return 0;}static int_wlc_pio_txfifodepthset(pio_info_t *pt, uint len){	pt->txfifolimit = len;	return 0;}static uint_wlc_pio_txfifodepthget(pio_info_t *pt){	return pt->txfifolimit;}

⌨️ 快捷键说明

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