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

📄 ib-net.c

📁 linux下的无线宽带驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* iBurst (TM) compatible driver for 2.6 Linux kernel. * based on the original ArrayComm (TM) iBurst (TM) driver. * Nicholas Jefferson <nicholas@pythontraining.com.au> * 11 May 2005 * * Fixes by Nik Trevallyn-Jones. * Fixes to support new hardware by Shane MacPhillamy. * Support for 2.6.20 by Daniel Burr. * * Wireless Extension IOCTL code based on that in * orinoco.c (v0.15rc2 28 July 2004) in the orinoco driver, written by * Pavel Roskin, David Gibson, Jean Tourrilhes & Benjamin Herrenschmidt. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */#include "ib-net.h"#include <linux/version.h>#include <linux/etherdevice.h>#include <net/iw_handler.h>#define IB_NET_QUEUE_LO 4#define IB_NET_QUEUE_HI 10#define IB_PROTO_CONTROL 0x00#define IB_CONTROL_STATUS1 0x05#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9)#define IW_QUAL_QUAL_UPDATED	0x01	/* Value was updated since last read */#define IW_QUAL_LEVEL_UPDATED	0x02#define IW_QUAL_NOISE_UPDATED	0x04#endifenum ib_net_offset{	OFFSET_STATUS1_NPAYLOAD = 0x00,	OFFSET_STATUS1_TYPE = 0x01,	OFFSET_STATUS1_LEVEL = 0x02,	OFFSET_STATUS1_UPCOUNT = 0x03,	OFFSET_STATUS1_DOWNCOUNT = 0x04,	OFFSET_STATUS1_SAMPLE = 0x05,	OFFSET_STATUS1_SUCCESS = 0x0a,	OFFSET_STATUS1_ATTEMPT = 0x0b,	OFFSET_STATUS1_SINR = 0x0c,};static int debug = 0;module_param(debug, int, 0);#define DEBUG(n, args...) if (debug < (n)) ; else printk(KERN_INFO args)/** * ifname - interface name. */static char *ifname = "ib%d";module_param(ifname, charp, 0);spinlock_t ib_lock = SPIN_LOCK_UNLOCKED;/** * ib_net_rx_deliver - deliver received radio frame as ethernet frame. *     called under ib_lock * @modem: modem state. * @nbuf: radio frame size. */static void ib_net_rx_deliver(struct ib_net_modem_t *modem, int nbuf){	struct ib_net_radio_t *radio = (struct ib_net_radio_t*) modem->rx_buf;	struct ib_net_ether_t *ether;	struct sk_buff *skb;	int npayload;	modem->stats.rx_bytes += nbuf;	modem->stats.rx_packets += 1;	modem->netdev->last_rx = jiffies;	npayload = nbuf - IB_NET_RADIO_HEAD;	skb = alloc_skb(IB_NET_ETHER_HEAD + npayload, GFP_ATOMIC);	if (skb == NULL) {		modem->stats.rx_dropped += 1;		return;	}	skb->dev = modem->netdev;	ether = (struct ib_net_ether_t*)			skb_put(skb, IB_NET_ETHER_HEAD + npayload);	memcpy(ether->source, modem->netdev->dev_addr, ETH_ALEN);	if (radio->word[0] & FLAG_BROADCAST)		memset(ether->dest, 0xff, ETH_ALEN);	else {		ether->source[ETH_ALEN - 1] ^= 1;		memcpy(ether->dest, modem->netdev->dev_addr, ETH_ALEN);	}	ether->proto[0] = radio->proto[0];	ether->proto[1] = radio->proto[1];	memcpy(ether->payload, radio->payload, npayload);	skb->protocol = eth_type_trans(skb, modem->netdev);	skb->ip_summed = CHECKSUM_UNNECESSARY;	netif_rx(skb);}/** * ib_net_rx_control_parse - process received control frame. *     called under ib_lock * @modem: modem state. * @nbuf: control frame size. */static void ib_net_rx_control_parse(struct ib_net_modem_t *modem, int nbuf){	struct ib_net_radio_t *radio = (struct ib_net_radio_t*) modem->rx_buf;	int32_t *payload = (int32_t*) &radio->payload;	int npayload, type, level, sinr, attempt, success;#if 17 <= WIRELESS_EXT	int sample, upcount, downcount;#endif	level = 0;	// to silence a benign warning	npayload = nbuf - IB_NET_RADIO_HEAD;	if (npayload < 8)		return;	if (npayload != be32_to_cpup(payload + OFFSET_STATUS1_NPAYLOAD))		return;	type = be32_to_cpup(payload + OFFSET_STATUS1_TYPE);	if (type == IB_CONTROL_STATUS1 && 12 <= npayload) {		/**		 * level is reported as an int 0 <= n <= 100,		 * or -1 => invalid		 */		level = le32_to_cpup(payload + OFFSET_STATUS1_LEVEL);		if (level != -1) {			modem->wstats.qual.level = modem->wstats.qual.qual					= level;			modem->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED					| IW_QUAL_QUAL_UPDATED;		}	}#if 17 <= WIRELESS_EXT	if (type == IB_CONTROL_STATUS1 && 24 <= npayload) {		/**		 * up and down throughput are reported as int byte		 * counts; the sample time is reported in milliseconds.		 *		 * The rates are calculated as bits/sec.		 */		sample = le32_to_cpup(payload + OFFSET_STATUS1_SAMPLE);		upcount = le32_to_cpup(payload + OFFSET_STATUS1_UPCOUNT);		downcount = le32_to_cpup(payload + OFFSET_STATUS1_DOWNCOUNT);		if (sample) {			modem->uprate = upcount * 1000 / sample * 8;			modem->downrate = downcount * 1000 / sample * 8;		}	}#endif	if (type == IB_CONTROL_STATUS1 && 48 <= npayload) {		/**		 * success and attempt report the number of bursts		 * attempted/successful since last report.		 *		 * Missed bursts are calculated as attempt - success.		 */		attempt = le32_to_cpup(payload + OFFSET_STATUS1_ATTEMPT);		success = le32_to_cpup(payload + OFFSET_STATUS1_SUCCESS);		modem->wstats.miss.beacon = attempt - success;	}	if (type == IB_CONTROL_STATUS1 && 52 <= npayload) {		/**		 * sinr (signal to interference AND noise) is reported as		 * actual-sinr << 4 (ie sinr * 16).		 *		 * noise is calculated as level / (sinr+1).		 *		 * Since sinr is already multiplied by 16, top and bottom of		 * ratio are multiplied by 16. Hence level => level*16 and		 * sinr+1 => sinr+16 (sinr is already multiplied by 16).		 */		sinr = le32_to_cpup(payload + OFFSET_STATUS1_SINR);		if (sinr) {			modem->wstats.qual.noise = (level * 16) / (sinr + 16);			modem->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;		}	}}/** * ib_net_rx_parse - process received radio frame. *     called under ib_lock * @modem: modem state. * @nbuf: radio frame size. */void ib_net_rx_parse(struct ib_net_modem_t *modem, int nbuf){	struct ib_net_radio_t *radio = (struct ib_net_radio_t*) modem->rx_buf;	if (radio->word[0] & FLAG_EXTENSION)		return;	if (radio->word[1] ^ radio->check ^ 0xff)		return;	if (radio->proto[0] != IB_PROTO)		ib_net_rx_deliver(modem, nbuf);	else if (radio->proto[1] == IB_PROTO_CONTROL)		ib_net_rx_control_parse(modem, nbuf);	else if (modem->driver->rx_parse)		modem->driver->rx_parse(modem->pdriver);}/** * ib_net_tx_prepare - prepare next radio frame for transmission. *     called under ib_lock * @modem: modem state. */int ib_net_tx_prepare(struct ib_net_modem_t *modem){	struct sk_buff *skb;	struct ib_net_radio_t *radio;	int nqueue;	nqueue = skb_queue_len(&modem->tx_queue);	if (nqueue < IB_NET_QUEUE_LO)		netif_wake_queue(modem->netdev);	skb = skb_dequeue(&modem->tx_queue);	if (skb == NULL)		return 0;	memcpy(modem->tx_buf, skb->data, skb->len);	dev_kfree_skb(skb);	radio = (struct ib_net_radio_t*) modem->tx_buf;	radio->packet = modem->stats.tx_packets & 0xff;	modem->netdev->trans_start = jiffies;	return skb->len;}/** * ib_net_deregister - deregister network device. * @modem: modem state. */void ib_net_deregister(struct ib_net_modem_t *modem){	unregister_netdev(modem->netdev);	free_netdev(modem->netdev);}/** * ib_net_poll - bottom half handler for interrupts. * @_modem: modem state. */#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)static void ib_net_poll(void *_modem)#elsestatic void ib_net_poll(struct work_struct *work)#endif{	unsigned long state;	struct ib_net_modem_t *modem = #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)		_modem;#else		container_of(work, struct ib_net_modem_t, work_queue);#endif	spin_lock_irqsave(&ib_lock, state);	if (modem->driver->poll)		modem->driver->poll(modem->pdriver);	spin_unlock_irqrestore(&ib_lock, state);}/** * ib_net_stats - return network device statistics. * @netdev: network device state. */static struct net_device_stats *ib_net_stats(struct net_device *netdev){	struct ib_net_modem_t *modem = netdev->priv;	return &modem->stats;}/** * ib_wireless_stats - return wireless statistics. * @netdev: network device state. */

⌨️ 快捷键说明

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