airo.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 2,328 行 · 第 1/5 页

C
2,328
字号
typedef struct {	emmh32_context seed;	    // Context - the seed	u32		 rx;	    // Received sequence number	u32		 tx;	    // Tx sequence number	u32		 window;    // Start of window	u8		 valid;	    // Flag to say if context is valid or not	u8		 key[16];} miccntx;typedef struct {	miccntx mCtx;		// Multicast context	miccntx uCtx;		// Unicast context} mic_module;typedef struct {	unsigned int  rid: 16;	unsigned int  len: 15;	unsigned int  valid: 1;	dma_addr_t host_addr;} Rid;typedef struct {	unsigned int  offset: 15;	unsigned int  eoc: 1;	unsigned int  len: 15;	unsigned int  valid: 1;	dma_addr_t host_addr;} TxFid;typedef struct {	unsigned int  ctl: 15;	unsigned int  rdy: 1;	unsigned int  len: 15;	unsigned int  valid: 1;	dma_addr_t host_addr;} RxFid;/* * Host receive descriptor */typedef struct {	unsigned char __iomem *card_ram_off; /* offset into card memory of the						desc */	RxFid         rx_desc;		     /* card receive descriptor */	char          *virtual_host_addr;    /* virtual address of host receive					        buffer */	int           pending;} HostRxDesc;/* * Host transmit descriptor */typedef struct {	unsigned char __iomem *card_ram_off;	     /* offset into card memory of the						desc */	TxFid         tx_desc;		     /* card transmit descriptor */	char          *virtual_host_addr;    /* virtual address of host receive					        buffer */	int           pending;} HostTxDesc;/* * Host RID descriptor */typedef struct {	unsigned char __iomem *card_ram_off;      /* offset into card memory of the					     descriptor */	Rid           rid_desc;		  /* card RID descriptor */	char          *virtual_host_addr; /* virtual address of host receive					     buffer */} HostRidDesc;typedef struct {	u16 sw0;	u16 sw1;	u16 status;	u16 len;#define HOST_SET (1 << 0)#define HOST_INT_TX (1 << 1) /* Interrupt on successful TX */#define HOST_INT_TXERR (1 << 2) /* Interrupt on unseccessful TX */#define HOST_LCC_PAYLOAD (1 << 4) /* LLC payload, 0 = Ethertype */#define HOST_DONT_RLSE (1 << 5) /* Don't release buffer when done */#define HOST_DONT_RETRY (1 << 6) /* Don't retry trasmit */#define HOST_CLR_AID (1 << 7) /* clear AID failure */#define HOST_RTS (1 << 9) /* Force RTS use */#define HOST_SHORT (1 << 10) /* Do short preamble */	u16 ctl;	u16 aid;	u16 retries;	u16 fill;} TxCtlHdr;typedef struct {        u16 ctl;        u16 duration;        char addr1[6];        char addr2[6];        char addr3[6];        u16 seq;        char addr4[6];} WifiHdr;typedef struct {	TxCtlHdr ctlhdr;	u16 fill1;	u16 fill2;	WifiHdr wifihdr;	u16 gaplen;	u16 status;} WifiCtlHdr;static WifiCtlHdr wifictlhdr8023 = {	.ctlhdr = {		.ctl	= HOST_DONT_RLSE,	}};// Frequency list (map channels to frequencies)static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,				2447, 2452, 2457, 2462, 2467, 2472, 2484 };// A few details needed for WEP (Wireless Equivalent Privacy)#define MAX_KEY_SIZE 13			// 128 (?) bits#define MIN_KEY_SIZE  5			// 40 bits RC4 - WEPtypedef struct wep_key_t {	u16	len;	u8	key[16];	/* 40-bit and 104-bit keys */} wep_key_t;/* Backward compatibility */#ifndef IW_ENCODE_NOKEY#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */#define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)#endif /* IW_ENCODE_NOKEY *//* List of Wireless Handlers (new API) */static const struct iw_handler_def	airo_handler_def;static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";struct airo_info;static int get_dec_u16( char *buffer, int *start, int limit );static void OUT4500( struct airo_info *, u16 register, u16 value );static unsigned short IN4500( struct airo_info *, u16 register );static u16 setup_card(struct airo_info*, u8 *mac, int lock);static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock );static void disable_MAC(struct airo_info *ai, int lock);static void enable_interrupts(struct airo_info*);static void disable_interrupts(struct airo_info*);static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp);static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap);static int aux_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,			int whichbap);static int fast_bap_read(struct airo_info*, u16 *pu16Dst, int bytelen,			 int whichbap);static int bap_write(struct airo_info*, const u16 *pu16Src, int bytelen,		     int whichbap);static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd);static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock);static int PC4500_writerid(struct airo_info*, u16 rid, const void			   *pBuf, int len, int lock);static int do_writerid( struct airo_info*, u16 rid, const void *rid_data,			int len, int dummy );static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw);static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket);static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket);static int mpi_send_packet (struct net_device *dev);static void mpi_unmap_card(struct pci_dev *pci);static void mpi_receive_802_3(struct airo_info *ai);static void mpi_receive_802_11(struct airo_info *ai);static int waitbusy (struct airo_info *ai);static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs			    *regs);static int airo_thread(void *data);static void timer_func( struct net_device *dev );static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);static void airo_read_wireless_stats (struct airo_info *local);#ifdef CISCO_EXTstatic int readrids(struct net_device *dev, aironet_ioctl *comp);static int writerids(struct net_device *dev, aironet_ioctl *comp);static int flashcard(struct net_device *dev, aironet_ioctl *comp);#endif /* CISCO_EXT */static void micinit(struct airo_info *ai);static int micsetup(struct airo_info *ai);static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen);static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);static void airo_networks_free(struct airo_info *ai);struct airo_info {	struct net_device_stats	stats;	struct net_device             *dev;	/* Note, we can have MAX_FIDS outstanding.  FIDs are 16-bits, so we	   use the high bit to mark whether it is in use. */#define MAX_FIDS 6#define MPI_MAX_FIDS 1	int                           fids[MAX_FIDS];	ConfigRid config;	char keyindex; // Used with auto wep	char defindex; // Used with auto wep	struct proc_dir_entry *proc_entry;        spinlock_t aux_lock;        unsigned long flags;#define FLAG_PROMISC	8	/* IFF_PROMISC 0x100 - include/linux/if.h */#define FLAG_RADIO_OFF	0	/* User disabling of MAC */#define FLAG_RADIO_DOWN	1	/* ifup/ifdown disabling of MAC */#define FLAG_RADIO_MASK 0x03#define FLAG_ENABLED	2#define FLAG_ADHOC	3	/* Needed by MIC */#define FLAG_MIC_CAPABLE 4#define FLAG_UPDATE_MULTI 5#define FLAG_UPDATE_UNI 6#define FLAG_802_11	7#define FLAG_PENDING_XMIT 9#define FLAG_PENDING_XMIT11 10#define FLAG_MPI	11#define FLAG_REGISTERED	12#define FLAG_COMMIT	13#define FLAG_RESET	14#define FLAG_FLASHING	15#define JOB_MASK	0x2ff0000#define JOB_DIE		16#define JOB_XMIT	17#define JOB_XMIT11	18#define JOB_STATS	19#define JOB_PROMISC	20#define JOB_MIC		21#define JOB_EVENT	22#define JOB_AUTOWEP	23#define JOB_WSTATS	24#define JOB_SCAN_RESULTS  25	int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,			int whichbap);	unsigned short *flash;	tdsRssiEntry *rssi;	struct task_struct *task;	struct semaphore sem;	pid_t thr_pid;	wait_queue_head_t thr_wait;	struct completion thr_exited;	unsigned long expires;	struct {		struct sk_buff *skb;		int fid;	} xmit, xmit11;	struct net_device *wifidev;	struct iw_statistics	wstats;		// wireless stats	unsigned long		scan_timeout;	/* Time scan should be read */	struct iw_spy_data	spy_data;	struct iw_public_data	wireless_data;	/* MIC stuff */	struct crypto_tfm	*tfm;	mic_module		mod[2];	mic_statistics		micstats;	HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors	HostTxDesc txfids[MPI_MAX_FIDS];	HostRidDesc config_desc;	unsigned long ridbus; // phys addr of config_desc	struct sk_buff_head txq;// tx queue used by mpi350 code	struct pci_dev          *pci;	unsigned char		__iomem *pcimem;	unsigned char		__iomem *pciaux;	unsigned char		*shared;	dma_addr_t		shared_dma;	pm_message_t		power;	SsidRid			*SSID;	APListRid		*APList;#define	PCI_SHARED_LEN		2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE	char			proc_name[IFNAMSIZ];	struct list_head network_list;	struct list_head network_free_list;	BSSListElement *networks;};static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,			   int whichbap) {	return ai->bap_read(ai, pu16Dst, bytelen, whichbap);}static int setup_proc_entry( struct net_device *dev,			     struct airo_info *apriv );static int takedown_proc_entry( struct net_device *dev,				struct airo_info *apriv );static int cmdreset(struct airo_info *ai);static int setflashmode (struct airo_info *ai);static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);static int flashputbuf(struct airo_info *ai);static int flashrestart(struct airo_info *ai,struct net_device *dev);#define airo_print(type, name, fmt, args...) \	{ printk(type "airo(%s): " fmt "\n", name, ##args); }#define airo_print_info(name, fmt, args...) \	airo_print(KERN_INFO, name, fmt, ##args)#define airo_print_dbg(name, fmt, args...) \	airo_print(KERN_DEBUG, name, fmt, ##args)#define airo_print_warn(name, fmt, args...) \	airo_print(KERN_WARNING, name, fmt, ##args)#define airo_print_err(name, fmt, args...) \	airo_print(KERN_ERR, name, fmt, ##args)/*********************************************************************** *                              MIC ROUTINES                           * *********************************************************************** */static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);static void MoveWindow(miccntx *context, u32 micSeq);static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);static void emmh32_init(emmh32_context *context);static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);static void emmh32_final(emmh32_context *context, u8 digest[4]);static int flashpchar(struct airo_info *ai,int byte,int dwelltime);/* micinit - Initialize mic seed */static void micinit(struct airo_info *ai){	MICRid mic_rid;	clear_bit(JOB_MIC, &ai->flags);	PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);	up(&ai->sem);	ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;	if (ai->micstats.enabled) {		/* Key must be valid and different */		if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||		    (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,			     sizeof(ai->mod[0].mCtx.key)) != 0))) {			/* Age current mic Context */			memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));			/* Initialize new context */			memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));			ai->mod[0].mCtx.window  = 33; //Window always points to the middle			ai->mod[0].mCtx.rx      = 0;  //Rx Sequence numbers			ai->mod[0].mCtx.tx      = 0;  //Tx sequence numbers			ai->mod[0].mCtx.valid   = 1;  //Key is now valid  			/* Give key to mic seed */			emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);		}		/* Key must be valid and different */		if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || 		    (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,			    sizeof(ai->mod[0].uCtx.key)) != 0))) {			/* Age current mic Context */			memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));			/* Initialize new context */			memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));				ai->mod[0].uCtx.window  = 33; //Window always points to the middle			ai->mod[0].uCtx.rx      = 0;  //Rx Sequence numbers			ai->mod[0].uCtx.tx      = 0;  //Tx sequence numbers			ai->mod[0].uCtx.valid   = 1;  //Key is now valid				//Give key to mic seed			emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);		}	} else {      /* So next time we have a valid key and mic is enabled, we will update       * the sequence number if the key is the same as before.       */		ai->mod[0].uCtx.valid = 0;		ai->mod[0].mCtx.valid = 0;	}}/* micsetup - Get ready for business */static int micsetup(struct airo_info *ai) {	int i;	if (ai->tfm == NULL)	        ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);        if (ai->tfm == NULL) {                airo_print_err(ai->dev->name, "failed to load transform for AES");                return ERROR;        }	for (i=0; i < NUM_MODULES; i++) {		memset(&ai->mod[i].mCtx,0,sizeof(miccntx));		memset(&ai->mod[i].uCtx,0,sizeof(miccntx));	}	return SUCCESS;}static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};/*=========================================================================== * Description: Mic a packet *     *      Inputs: etherHead * pointer to an 802.3 frame *     *     Returns: BOOLEAN if successful, otherwise false. *             PacketTxLen will be updated with the mic'd packets size. * *    Caveats: It is assumed that the frame buffer will already *             be big enough to hold the largets mic message possible. *            (No memory allocation is done here). *   *    Author: sbraneky (10/15/01) *    Merciless hacks by rwilcher (1/14/02) */static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, int payLen){	miccntx   *context;	// Determine correct context	// If not adhoc, always use unicast key	if (test_bit(FLAG_ADHOC, &ai->flags) && (frame->da[0] & 0x1))		context = &ai->mod[0].mCtx;	else		context = &ai->mod[0].uCtx;  	if (!context->valid)		return ERROR;	mic->typelen = htons(payLen + 16); //Length of Mic'd packet	memcpy(&mic->u.snap, micsnap, sizeof(micsnap)); // Add Snap	// Add Tx sequence	mic->seq = htonl(context->tx);	context->tx += 2;	emmh32_init(&context->seed); // Mic the packet	emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA	emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap	emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ	emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload	emmh32_final(&context->seed, (u8*)&mic->mic);	/*    New Type/length ?????????? */	mic->typelen = 0; //Let NIC know it could be an oversized packet	return SUCCESS;}typedef enum {    NONE,    NOMIC,    NOMICPLUMMED,    SEQUENCE,    INCORRECTMIC,} mic_error;/*===========================================================================

⌨️ 快捷键说明

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