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

📄 wlc_pio.c

📁 wi-fi sources for asus wl138g v2 pci card
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * HND PIO module * Broadcom 802.11abg Networking Device Driver * * Copyright 2005-2006, Broadcom Corporation * All Rights Reserved.                 *                                      * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE. * * $Id$ */#ifndef WLPIO#error "WLPIO is not defined"#endif	/* WLPIO */#include <wlc_cfg.h>#include <typedefs.h>#include <bcmdefs.h>#include <osl.h>#include <sbutils.h>#include <bcmendian.h>#include <bcmutils.h>#include <wlioctl.h>#include <sbhndpio.h>#include <sbhnddma.h>#include <hnddma.h>#include <d11.h>#include <wlc_rate.h>#include <wlc_key.h>#include <wlc_channel.h>#include <wlc_pub.h>#include <wlc_bsscfg.h>#include <wlc_pio.h>#include <wlc.h>/* private pio structure */typedef struct pio_info_s {	pio_t		piopub;			/* public structure of pio module */	wlc_info_t	*wlc;			/* common code handler */	wlc_pub_t	*pub;			/* public common code handler */	uint		_fifo;			/* fifo number */	bool		pio4;			/* PIO 4 bytes or 2 bytes */	pio2regs_t	*p2txregs;		/* pio2 trx regs */	pio2regs_t	*p2rxregs;		/* pio2 rx regs */	pio4regs_t	*p4txregs;		/* pio4 tx regs */	pio4regs_t	*p4rxregs;		/* pio4 rx regs */	/* pio */	struct pktq	txpioq;			/* tx sw queue, wait txstatus to reclaim */	uint		txfrmcnt;		/* tx frame count */	uint		txdatacnt;		/* tx data count */	uint		txfifolimit;		/* tx fifo depth */} pio_info_t;#define PIO_INFO(pio)	(pio_info_t *)pio/* local prototype *//* pio common routines for both pio2 and pio4 */static int _wlc_pio_com_detach(pio_info_t *pt);static int _wlc_pio_com_init(pio_info_t *pt);static int _wlc_pio_com_reset(pio_info_t *pt);static int _wlc_pio_com_txsuspend(pio_info_t *pt);static bool _wlc_pio_com_txsuspended(pio_info_t *pt);static int _wlc_pio_com_txresume(pio_info_t *pt);static bool _wlc_pio_com_txavailable(pio_info_t *pt, uint len, uint nfrags);static bool _wlc_pio_com_rxfrmrdy(pio_info_t *pt);static int _wlc_pio_com_cntupd(pio_info_t *pt, uint len);static char* _wlc_pio_com_dump(pio_info_t *pt, char *buf);static void* _wlc_pio_getnexttxp(pio_info_t *pt);static int   _wlc_pio_txreclaim(pio_info_t *pt);static int   _wlc_pio_txfifodepthset(pio_info_t *pt, uint len);static uint  _wlc_pio_txfifodepthget(pio_info_t *pt);/* pio routines for 2 bytes pio */static int _wlc_pio2_tx(pio_info_t *pt, void *p0);static void _wlc_pio2_xmtfifo(pio_info_t *pioh, pio2regs_t *regs, uchar *va, uint len);static void *_wlc_pio2_rx(pio_info_t *pt);/* pio routines for 4 bytes pio */static int _wlc_pio4_tx(pio_info_t *pt, void *p0);static void _wlc_pio4_xmtfifo(pio_info_t *pt, pio4regs_t *regs, uchar *va, uint len);static void *_wlc_pio4_rx(pio_info_t *pt);static bool _wlc_pio_rxcheck(pio_info_t *pt, int len, void **p);/* len is rounded up since free fifo length in ucode counts in multiples of 4 */#define PIO_ADD_TX_CNT(pt, len) {	\	pt->txfrmcnt++; \	ASSERT(pt->txfrmcnt <= D11_MAX_TX_FRMS); \	pt->txdatacnt += ROUNDUP(len, 4); \	ASSERT(pt->txdatacnt <= pt->txfifolimit);	\	}#define PIO_SUB_TX_CNT(pt, len) {	\	ASSERT(pt->txfrmcnt); \	pt->txfrmcnt--;	\	ASSERT(pt->txdatacnt >= ROUNDUP(len, 4));	\	pt->txdatacnt -= ROUNDUP(len, 4);	\	}pio_t*wlc_pio_attach(wlc_pub_t *pub, wlc_info_t *cwlc, uint fifo, void *pioregstx, void *pioregsrx){	pio_info_t *pt;	piof_t	pio_fns;	if ((pt = (pio_info_t *)MALLOC(pub->osh, sizeof(pio_info_t))) == NULL) {		WL_ERROR(("wlc_pio_attach: out of memory, malloced %d bytes", MALLOCED(pub->osh)));		return NULL;	}	bzero((char *)pt, sizeof(pio_info_t));	pt->wlc = cwlc;	pt->pub = pub;	pt->_fifo = fifo;	/*	 * register pio functions	 * To add a new one, add the type and array element in wlc_pio.h,	 *    add handler here and in wlc_pio_register_fn	 */	pio_fns.detach = (pio_detach_t)_wlc_pio_com_detach;	pio_fns.reset = (pio_reset_t)_wlc_pio_com_reset;	pio_fns.init = (pio_init_t)_wlc_pio_com_init;	pio_fns.txsuspend = (pio_txsuspend_t)_wlc_pio_com_txsuspend;	pio_fns.txsuspended = (pio_txsuspended_t)_wlc_pio_com_txsuspended;	pio_fns.txresume = (pio_txresume_t)_wlc_pio_com_txresume;	pio_fns.txavailable = (pio_txavailable_t)_wlc_pio_com_txavailable;	pio_fns.rxfrmrdy = (pio_rxfrmrdy_t)_wlc_pio_com_rxfrmrdy;	if (WLC_UPDATE_STATS(wlc)) {		pio_fns.dump = (pio_dump_t)_wlc_pio_com_dump;	}	else {		pio_fns.dump = NULL;	}	pio_fns.cntupd = (pio_cntupd_t)_wlc_pio_com_cntupd;	pio_fns.nexttxp = (pio_getnexttxp_t)_wlc_pio_getnexttxp;	pio_fns.txreclaim = (pio_txreclaim_t)_wlc_pio_txreclaim;	pio_fns.txdepthget = (pio_txfifodepthget_t)_wlc_pio_txfifodepthget;	pio_fns.txdepthset = (pio_txfifodepthset_t)_wlc_pio_txfifodepthset;	/* init pio reg pointer */	if (D11REV_LT(pt->pub->corerev, 8)) {		pt->p2txregs = (pio2regs_t *)pioregstx;		pt->p2rxregs = (pio2regs_t *)pioregsrx;		pio_fns.rx = (pio_rx_t)_wlc_pio2_rx;		pio_fns.tx = (pio_tx_t)_wlc_pio2_tx;		pt->pio4 = 0;	} else {		pt->p4txregs = (pio4regs_t *)pioregstx;		pt->p4rxregs = (pio4regs_t *)pioregsrx;		pio_fns.rx = (pio_rx_t)_wlc_pio4_rx;		pio_fns.tx = (pio_tx_t)_wlc_pio4_tx;		pt->pio4 = 1;	}	wlc_pio_register_fn((pio_t *)pt, &pio_fns);	pktq_init(&pt->txpioq, 1, PKTQ_LEN_DEFAULT);	ASSERT(pktq_avail(&pt->txpioq) >= D11_MAX_TX_FRMS);	return (pio_t*)pt;}/* register pio mode function pointers */voidwlc_pio_register_fn(pio_t *pioh, piof_t *fn){	pioh->pio_fn.detach = fn->detach;	pioh->pio_fn.reset = fn->reset;	pioh->pio_fn.init = fn->init;	pioh->pio_fn.txsuspend = fn->txsuspend;	pioh->pio_fn.txsuspended = fn->txsuspended;	pioh->pio_fn.txresume = fn->txresume;	pioh->pio_fn.rxfrmrdy = fn->rxfrmrdy;	pioh->pio_fn.txavailable = fn->txavailable;	pioh->pio_fn.dump = fn->dump;	pioh->pio_fn.cntupd = fn->cntupd;	pioh->pio_fn.nexttxp = fn->nexttxp;	pioh->pio_fn.txreclaim = fn->txreclaim;	pioh->pio_fn.txdepthget = fn->txdepthget;	pioh->pio_fn.txdepthset = fn->txdepthset;	pioh->pio_fn.tx = fn->tx;	pioh->pio_fn.rx = fn->rx;}static int_wlc_pio_com_detach(pio_info_t *pt){	/* assert pkts are freed */	ASSERT(pktq_empty(&pt->txpioq));	if (pt)		MFREE(pt->pub->osh, pt, sizeof(pio_info_t));	return 0;}/* pio initialization */static int_wlc_pio_com_init(pio_info_t *pt){	return 0;}static int_wlc_pio_com_reset(pio_info_t *pt){	return 0;}static int_wlc_pio_com_txsuspend(pio_info_t *pt){	if (pt->pio4) {		OR_REG(&pt->p4txregs->fifocontrol, XFC4_SE);	} else {		OR_REG(&pt->p2txregs->fifocontrol, XFC_SE);	}	return 0;}static bool_wlc_pio_com_txsuspended(pio_info_t *pt){	if (pt->pio4) {		if ((R_REG(&pt->p4txregs->fifocontrol) & (XFC4_SE | XFC4_SP)) == XFC4_SE)			return TRUE;	} else {		if ((R_REG(&pt->p2txregs->fifocontrol) & (XFC_SE | XFC_SP)) == XFC_SE)			return TRUE;	}	return FALSE;}static int_wlc_pio_com_txresume(pio_info_t *pt){	if (pt->pio4) {		AND_REG(&pt->p4txregs->fifocontrol, ~XFC4_SE);	} else {		AND_REG(&pt->p2txregs->fifocontrol, ~XFC_SE);	}	return 0;}static bool_wlc_pio_com_rxfrmrdy(pio_info_t *pt){	if (pt->pio4)		return (R_REG(&pt->p4rxregs->fifocontrol) & RFC_FR);	else		return (R_REG(&pt->p2rxregs->fifocontrol) & RFC_FR);}static bool_wlc_pio_com_txavailable(pio_info_t *pt, uint len, uint nfrags){	if (((pt->txfrmcnt + nfrags) <= D11_MAX_TX_FRMS) &&	    ((pt->txdatacnt + ((nfrags == 1) ?		(ROUNDUP(len, 4)) : (len + 3*nfrags))) <= pt->txfifolimit)) {		if (pt->pio4)			return (!(R_REG(&pt->p4txregs->fifocontrol) & XFC4_SE));		else			return (!(R_REG(&pt->p2txregs->fifocontrol) & XFC_SE));	}	return FALSE;}static int_wlc_pio_com_cntupd(pio_info_t *pt, uint len){	PIO_SUB_TX_CNT(pt, len);	return 0;}/* need fifo to avoid touch some rx fifo, which doesn't exist */static char*_wlc_pio_com_dump(pio_info_t *pt, char *buf){	/* common software part */	buf += sprintf(buf, "pio%d: qlen %d txfrmcnt %d txdatacnt %d txfifodepth %d\n",		pt->_fifo, pktq_len(&pt->txpioq), pt->txfrmcnt, pt->txdatacnt, pt->txfifolimit);	if (pt->pio4) {		buf += sprintf(buf, "xmtcontrol 0x%x\n", R_REG(&pt->p4txregs->fifocontrol));		if (pt->_fifo == RX_FIFO) {			buf += sprintf(buf, "rcvcontrol 0x%x\n", R_REG(&pt->p4rxregs->fifocontrol));		}	} else {		buf += sprintf(buf, "xmtcontrol 0x%x\n", R_REG(&pt->p2txregs->fifocontrol));		if (pt->_fifo == RX_FIFO) {			buf += sprintf(buf, "rcvcontrol 0x%x\n", R_REG(&pt->p2rxregs->fifocontrol));		}	}	return (buf);}/* 2-byte mode for corerev < 8. poke a chain of fragment buffers into tx channel fifo */static int_wlc_pio2_tx(pio_info_t *pt, void *p0){	pio2regs_t *pioregs = pt->p2txregs;	void *p;	osl_t *osh;	uint totlen;	uchar *va;	uint len;	WL_TRACE(("wl%d: _wlc_pio2_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, XFC_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_pio2_xmtfifo(pt, pioregs, va, len);		totlen -= len;	}	W_REG(&pioregs->fifocontrol, XFC_EF);	/* save frag in pio sw queue */	pktenq(&pt->txpioq, p0);	return 0;}/* 2-byte mode for corerev < 8.  move tx data to fifo */static void_wlc_pio2_xmtfifo(pio_info_t *pt, pio2regs_t *regs, uchar *va, uint len){	uint16 *va16;	volatile uint16 *fifo;	if (len == 0)		return;	fifo = &regs->fifodata;	/* write any odd leading byte */	if ((uintptr)va & 1) {		W_REG(&regs->fifocontrol, XFC_LO);		W_REG(fifo, (uint16)*va);		va++;		len--;	}	va16 = (uint16*)va;	if (len >= 2) {		W_REG(&regs->fifocontrol, XFC_BOTH);		{			while (len >= 2) {				W_REG(fifo, *va16);				va16++;				len -= 2;			}		}	}	/* write any odd trailing byte */

⌨️ 快捷键说明

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