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

📄 airo.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static int readCapabilityRid(struct airo_info*ai, CapabilityRid *capr, int lock) {	int rc = PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock);	u16 *s;	capr->len = le16_to_cpu(capr->len);	capr->prodNum = le16_to_cpu(capr->prodNum);	capr->radioType = le16_to_cpu(capr->radioType);	capr->country = le16_to_cpu(capr->country);	for(s = &capr->txPowerLevels[0]; s <= &capr->requiredHard; s++)		*s = le16_to_cpu(*s);	return rc;}static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) {	int rc = PC4500_readrid(ai, rid, sr, sizeof(*sr), lock);	u32 *i;	sr->len = le16_to_cpu(sr->len);	for(i = &sr->vals[0]; i <= &sr->vals[99]; i++) *i = le32_to_cpu(*i);	return rc;}static int airo_open(struct net_device *dev) {	struct airo_info *info = dev->priv;	Resp rsp;	if (test_bit(FLAG_FLASHING, &info->flags))		return -EIO;	/* Make sure the card is configured.	 * Wireless Extensions may postpone config changes until the card	 * is open (to pipeline changes and speed-up card setup). If	 * those changes are not yet commited, do it now - Jean II */	if (test_bit (FLAG_COMMIT, &info->flags)) {		disable_MAC(info, 1);		writeConfigRid(info, 1);	}	if (info->wifidev != dev) {		/* Power on the MAC controller (which may have been disabled) */		clear_bit(FLAG_RADIO_DOWN, &info->flags);		enable_interrupts(info);	}	enable_MAC(info, &rsp, 1);	netif_start_queue(dev);	return 0;}static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {	int npacks, pending;	unsigned long flags;	struct airo_info *ai = dev->priv;	if (!skb) {		printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__);		return 0;	}	npacks = skb_queue_len (&ai->txq);	if (npacks >= MAXTXQ - 1) {		netif_stop_queue (dev);		if (npacks > MAXTXQ) {			ai->stats.tx_fifo_errors++;			return 1;		}		skb_queue_tail (&ai->txq, skb);		return 0;	}	spin_lock_irqsave(&ai->aux_lock, flags);	skb_queue_tail (&ai->txq, skb);	pending = test_bit(FLAG_PENDING_XMIT, &ai->flags);	spin_unlock_irqrestore(&ai->aux_lock,flags);	netif_wake_queue (dev);	if (pending == 0) {		set_bit(FLAG_PENDING_XMIT, &ai->flags);		mpi_send_packet (dev);	}	return 0;}/* * @mpi_send_packet * * Attempt to transmit a packet. Can be called from interrupt * or transmit . return number of packets we tried to send */static int mpi_send_packet (struct net_device *dev){	struct sk_buff *skb;	unsigned char *buffer;	s16 len, *payloadLen;	struct airo_info *ai = dev->priv;	u8 *sendbuf;	/* get a packet to send */	if ((skb = skb_dequeue(&ai->txq)) == 0) {		printk (KERN_ERR			"airo: %s: Dequeue'd zero in send_packet()\n",			__FUNCTION__);		return 0;	}	/* check min length*/	len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	buffer = skb->data;	ai->txfids[0].tx_desc.offset = 0;	ai->txfids[0].tx_desc.valid = 1;	ai->txfids[0].tx_desc.eoc = 1;	ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr);/* * Magic, the cards firmware needs a length count (2 bytes) in the host buffer * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen * is immediatly after it. ------------------------------------------------ *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA| *                         ------------------------------------------------ */	memcpy((char *)ai->txfids[0].virtual_host_addr,		(char *)&wifictlhdr8023, sizeof(wifictlhdr8023));	payloadLen = (s16 *)(ai->txfids[0].virtual_host_addr +		sizeof(wifictlhdr8023));	sendbuf = ai->txfids[0].virtual_host_addr +		sizeof(wifictlhdr8023) + 2 ;	/*	 * Firmware automaticly puts 802 header on so	 * we don't need to account for it in the length	 */#ifdef MICSUPPORT	if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&		(ntohs(((u16 *)buffer)[6]) != 0x888E)) {		MICBuffer pMic;		if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS)			return ERROR;		*payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic));		ai->txfids[0].tx_desc.len += sizeof(pMic);		/* copy data into airo dma buffer */		memcpy (sendbuf, buffer, sizeof(etherHead));		buffer += sizeof(etherHead);		sendbuf += sizeof(etherHead);		memcpy (sendbuf, &pMic, sizeof(pMic));		sendbuf += sizeof(pMic);		memcpy (sendbuf, buffer, len - sizeof(etherHead));	} else#endif	{		*payloadLen = cpu_to_le16(len - sizeof(etherHead));		dev->trans_start = jiffies;		/* copy data into airo dma buffer */		memcpy(sendbuf, buffer, len);	}	memcpy_toio(ai->txfids[0].card_ram_off,		&ai->txfids[0].tx_desc, sizeof(TxFid));	OUT4500(ai, EVACK, 8);	dev_kfree_skb_any(skb);	return 1;}static void get_tx_error(struct airo_info *ai, s32 fid){	u16 status;	if (fid < 0)		status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status;	else {		if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) != SUCCESS)			return;		bap_read(ai, &status, 2, BAP0);	}	if (le16_to_cpu(status) & 2) /* Too many retries */		ai->stats.tx_aborted_errors++;	if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */		ai->stats.tx_heartbeat_errors++;	if (le16_to_cpu(status) & 8) /* Aid fail */		{ }	if (le16_to_cpu(status) & 0x10) /* MAC disabled */		ai->stats.tx_carrier_errors++;	if (le16_to_cpu(status) & 0x20) /* Association lost */		{ }	/* We produce a TXDROP event only for retry or lifetime	 * exceeded, because that's the only status that really mean	 * that this particular node went away.	 * Other errors means that *we* screwed up. - Jean II */	if ((le16_to_cpu(status) & 2) ||	     (le16_to_cpu(status) & 4)) {		union iwreq_data	wrqu;		char junk[0x18];		/* Faster to skip over useless data than to do		 * another bap_setup(). We are at offset 0x6 and		 * need to go to 0x18 and read 6 bytes - Jean II */		bap_read(ai, (u16 *) junk, 0x18, BAP0);		/* Copy 802.11 dest address.		 * We use the 802.11 header because the frame may		 * not be 802.3 or may be mangled...		 * In Ad-Hoc mode, it will be the node address.		 * In managed mode, it will be most likely the AP addr		 * User space will figure out how to convert it to		 * whatever it needs (IP address or else).		 * - Jean II */		memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN);		wrqu.addr.sa_family = ARPHRD_ETHER;		/* Send event to user space */		wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL);	}}static void airo_end_xmit(struct net_device *dev) {	u16 status;	int i;	struct airo_info *priv = dev->priv;	struct sk_buff *skb = priv->xmit.skb;	int fid = priv->xmit.fid;	u32 *fids = priv->fids;	clear_bit(JOB_XMIT, &priv->flags);	clear_bit(FLAG_PENDING_XMIT, &priv->flags);	status = transmit_802_3_packet (priv, fids[fid], skb->data);	up(&priv->sem);	i = 0;	if ( status == SUCCESS ) {		dev->trans_start = jiffies;		for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++);	} else {		priv->fids[fid] &= 0xffff;		priv->stats.tx_window_errors++;	}	if (i < MAX_FIDS / 2)		netif_wake_queue(dev);	dev_kfree_skb(skb);}static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {	s16 len;	int i, j;	struct airo_info *priv = dev->priv;	u32 *fids = priv->fids;	if ( skb == NULL ) {		printk( KERN_ERR "airo:  skb == NULL!!!\n" );		return 0;	}	/* Find a vacant FID */	for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ );	for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ );	if ( j >= MAX_FIDS / 2 ) {		netif_stop_queue(dev);		if (i == MAX_FIDS / 2) {			priv->stats.tx_fifo_errors++;			return 1;		}	}	/* check min length*/	len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;        /* Mark fid as used & save length for later */	fids[i] |= (len << 16);	priv->xmit.skb = skb;	priv->xmit.fid = i;	if (down_trylock(&priv->sem) != 0) {		set_bit(FLAG_PENDING_XMIT, &priv->flags);		netif_stop_queue(dev);		set_bit(JOB_XMIT, &priv->flags);		wake_up_interruptible(&priv->thr_wait);	} else		airo_end_xmit(dev);	return 0;}static void airo_end_xmit11(struct net_device *dev) {	u16 status;	int i;	struct airo_info *priv = dev->priv;	struct sk_buff *skb = priv->xmit11.skb;	int fid = priv->xmit11.fid;	u32 *fids = priv->fids;	clear_bit(JOB_XMIT11, &priv->flags);	clear_bit(FLAG_PENDING_XMIT11, &priv->flags);	status = transmit_802_11_packet (priv, fids[fid], skb->data);	up(&priv->sem);	i = MAX_FIDS / 2;	if ( status == SUCCESS ) {		dev->trans_start = jiffies;		for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++);	} else {		priv->fids[fid] &= 0xffff;		priv->stats.tx_window_errors++;	}	if (i < MAX_FIDS)		netif_wake_queue(dev);	dev_kfree_skb(skb);}static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {	s16 len;	int i, j;	struct airo_info *priv = dev->priv;	u32 *fids = priv->fids;	if (test_bit(FLAG_MPI, &priv->flags)) {		/* Not implemented yet for MPI350 */		netif_stop_queue(dev);		return -ENETDOWN;	}	if ( skb == NULL ) {		printk( KERN_ERR "airo:  skb == NULL!!!\n" );		return 0;	}	/* Find a vacant FID */	for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ );	for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ );	if ( j >= MAX_FIDS ) {		netif_stop_queue(dev);		if (i == MAX_FIDS) {			priv->stats.tx_fifo_errors++;			return 1;		}	}	/* check min length*/	len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;        /* Mark fid as used & save length for later */	fids[i] |= (len << 16);	priv->xmit11.skb = skb;	priv->xmit11.fid = i;	if (down_trylock(&priv->sem) != 0) {		set_bit(FLAG_PENDING_XMIT11, &priv->flags);		netif_stop_queue(dev);		set_bit(JOB_XMIT11, &priv->flags);		wake_up_interruptible(&priv->thr_wait);	} else		airo_end_xmit11(dev);	return 0;}static void airo_read_stats(struct airo_info *ai) {	StatsRid stats_rid;	u32 *vals = stats_rid.vals;	clear_bit(JOB_STATS, &ai->flags);	if (ai->power.event) {		up(&ai->sem);		return;	}	readStatsRid(ai, &stats_rid, RID_STATS, 0);	up(&ai->sem);	ai->stats.rx_packets = vals[43] + vals[44] + vals[45];	ai->stats.tx_packets = vals[39] + vals[40] + vals[41];	ai->stats.rx_bytes = vals[92];	ai->stats.tx_bytes = vals[91];	ai->stats.rx_errors = vals[0] + vals[2] + vals[3] + vals[4];	ai->stats.tx_errors = vals[42] + ai->stats.tx_fifo_errors;	ai->stats.multicast = vals[43];	ai->stats.collisions = vals[89];	/* detailed rx_errors: */	ai->stats.rx_length_errors = vals[3];	ai->stats.rx_crc_errors = vals[4];	ai->stats.rx_frame_errors = vals[2];	ai->stats.rx_fifo_errors = vals[0];}static struct net_device_stats *airo_get_stats(struct net_device *dev){	struct airo_info *local =  dev->priv;	if (!test_bit(JOB_STATS, &local->flags)) {		/* Get stats out of the card if available */		if (down_trylock(&local->sem) != 0) {			set_bit(JOB_STATS, &local->flags);			wake_up_interruptible(&local->thr_wait);		} else			airo_read_stats(local);	}	return &local->stats;}static void airo_set_promisc(struct airo_info *ai) {	Cmd cmd;	Resp rsp;	memset(&cmd, 0, sizeof(cmd));	cmd.cmd=CMD_SETMODE;	clear_bit(JOB_PROMISC, &ai->flags);	cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC;	issuecommand(ai, &cmd, &rsp);	up(&ai->sem);}static void airo_set_multicast_list(struct net_device *dev) {	struct airo_info *ai = dev->priv;	if ((dev->flags ^ ai->flags) & IFF_PROMISC) {		change_bit(FLAG_PROMISC, &ai->flags);		if (down_trylock(&ai->sem) != 0) {			set_bit(JOB_PROMISC, &ai->flags);			wake_up_interruptible(&ai->thr_wait);		} else			airo_set_promisc(ai);	}	if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) {		/* Turn on multicast.  (Should be already setup...) */	}}static int airo_set_mac_address(struct net_device *dev, void *p){	struct airo_info *ai = dev->priv;	struct sockaddr *addr = p;	Resp rsp;	readConfigRid(ai, 1);	memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len);	set_bit (FLAG_COMMIT, &ai->flags);	disable_MAC(ai, 1);	writeConfigRid (ai, 1);	enable_MAC(ai, &rsp, 1);	memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len);	if (ai->wifidev)		memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len);	return 0;}static int airo_change_mtu(struct net_device *dev, int new_mtu){	if ((new_mtu < 68) || (new_mtu > 2400))		return -EINVAL;	dev->mtu = new_mtu;	return 0;}static int airo_close(struct net_device *dev) {	struct airo_info *ai = dev->priv;	netif_stop_queue(dev);	if (ai->wifidev != dev) {#ifdef POWER_ON_DOWN		/* Shut power to the card. The idea is that the user can save		 * power when he doesn't need the 

⌨️ 快捷键说明

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