📄 cb20_cb.c
字号:
/* * MIC Compatable CB20 cardbus card driver Copyright (C) 2003, 2004 Cisco Systems, Inc. All Rights Reserved. Dec 2003 - Masukawa - fixed compatibility with newer radio firmware added driver version request added wireless-tools interface added RF monitor support */#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include <linux/config.h>#include <linux/version.h>#include <linux/init.h>#include <asm/segment.h>#ifdef CONFIG_MODVERSIONS#define MODVERSIONS#include <linux/modversions.h>#endif #include <linux/kernel.h>#include <linux/module.h>#include <linux/proc_fs.h>#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,6)#include <linux/slab.h>#else#include <linux/malloc.h>#endif#include <linux/sched.h>#include <linux/ptrace.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/in.h>#include <linux/init.h>#include <asm/io.h>#include <asm/system.h>#include <asm/bitops.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/skbuff.h>#include <linux/if_arp.h>#include <linux/ioport.h>#include <linux/config.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <pcmcia/driver_ops.h>#ifdef CONFIG_PCI#include <linux/pci.h>#endif/*#include <linux/wireless.h>*/#include "aes.h"#include "cb20_cb.h"#ifndef MIN#define MIN(x,y) ((x<y)?x:y)#endif#ifndef RUN_AT#define RUN_AT(x) (jiffies+(x))#endif#if (LINUX_VERSION_CODE >= 0x20420)MODULE_LICENSE("MPL");#endifMODULE_AUTHOR("Roland Wilcher");MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11a wireless ethernet \ cards. Direct support for cb20 cardbus cards with MIC support");MODULE_SUPPORTED_DEVICE("Aironet Cisco CB20 802.11a cardbus card.");unsigned char iobuf[2048];static char flashbuffer[FLASHSIZE];typedef struct aironet_ioctl { unsigned short command; /* What to do */ unsigned short length; /* Len of data */ unsigned short ridnum; /* rid number */ unsigned char *data; /* d-data */} aironet_ioctl;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13))static struct proc_dir_entry cb20_entry = { 0, /* low ino */ 4, /* namelen */ PRODNAME, /* name */ S_IFDIR | S_IRUGO | S_IXUGO, /* mode */ 2, /* nlink */ 0, 0, /* uid gid */ 0, /* size */ &proc_dir_inode_operations, /* ops */ 0, /* get_info */ 0, /* fill inode */ 0,&proc_root,0 /* next parent subdir */};#elsestatic struct proc_dir_entry *cb20_entry = 0;#endif#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13))static void *pci_alloc_consistent(struct pci_dev *,size_t,dma_addr_t*);static void pci_free_consistent(struct pci_dev *,size_t,void *,dma_addr_t);#if 0#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,55)static int pci_enable_device(struct pci_dev *);#endif#endifstatic unsigned long pci_resource_start(struct pci_dev *,int);#if LINUX_VERSION_CODE < KERNEL_VERSION(2,2,19)static unsigned long pci_resource_len(struct pci_dev *,int);#endif#endif/* * Identify the usual suspects */static char *version = "cb20_cb.c 2.1 2003/12/15"; static char *swversion = "2.1"; static int cb20_clear(struct cb20_info *);static void schednap(int);static int enable_mac(struct cb20_info *,Resp *);static struct net_device *cb20_probe(struct pci_dev *);CB20_CARDS *cb20_units = 0; /* List of found cards *//* * Handle kernel PCMCIA and Hotplugging on else assume pcmcia-cs * is being used. */#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET_PCMCIA) static int cb20_probe1(struct pci_dev *,const struct pci_device_id *);int eject_cb20_card( struct net_device *);static struct net_device *pcidev_loc(struct pci_dev *locater);void cb20_remove(struct pci_dev *);static struct net_device *pcidev_loc(struct pci_dev *locate);#elsestatic void cb20_cleanup(struct net_device *);static struct net_device *loc_cb20(char *);static int stop_cb20_card( struct net_device *vdev);static dev_node_t *cb20_attach(dev_locator_t *);static void cb20_detach(dev_node_t *);static void cb20_suspend(dev_node_t *);static void cb20_resume(dev_node_t *);#endifstatic int softreset(struct cb20_info * );static int cmdreset(struct cb20_info * );static int waitport(struct cb20_info *,int,int,int);static int start_cb20(struct net_device *);static int cb20_init_descriptors(struct net_device *);static int flashcard(struct net_device *, aironet_ioctl *);static int txreclaim(struct net_device *);#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13))static int send_packet(struct net_device *);static int cb20_transmit(struct sk_buff *, struct net_device *);static void cb20txtmo(struct net_device *);#endifstatic void cb20_linkstat(struct net_device *,int );static struct net_device_stats *cb20_get_stats(struct net_device *);static int cb20_change_mtu(struct net_device *,int);static int cb20_close(struct net_device *);static void cb20_kick(struct cb20_info *);static unsigned short cb20in(struct cb20_info *,u16 register );static void cb20out(struct cb20_info *,u16 register,u16 value );static u16 cb20command(struct cb20_info*, Cmd *pCmd, Resp *pRsp);static struct net_device *init_cb20_card(struct pci_dev *);static int vreadrid(struct cb20_info *,unsigned short,unsigned char *, int);static int vwriterid(struct cb20_info *,unsigned short,unsigned char *,int);void cb20_interrupt( int irq, void* dev_id, struct pt_regs *regs);static int cb20_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);static int mac_enable(struct cb20_info *, Resp * );static void mac_disable( struct cb20_info * );static void disable_interrupts(struct cb20_info *);static void enable_interrupts(struct cb20_info *);static int del_proc_entry( struct net_device *,struct cb20_info *);/* Mic functions*/static void micinit(struct cb20_info *, STMIC *);static void micsetup(struct cb20_info *);static int RxSeqValid (struct cb20_info *,MICCNTX *context, u32 micSeq);static void MoveWindow(MICCNTX *, u32 );static int Encapsulate(struct cb20_info *,ETH_HEADER_STRUC *, u32 *,int );static int Decapsulate(struct cb20_info *,ETH_HEADER_STRUC *, u32 *);static void UshortByteSwap(u16 *);static void UlongByteSwap(u32 *);static ssize_t proc_read( struct file *,char *,size_t ,loff_t * );static ssize_t proc_write( struct file *,const char *,size_t ,loff_t * );static int proc_close( struct inode *, struct file * ); static int proc_ssid_open( struct inode *, struct file * );static int proc_status_open( struct inode *, struct file * );static void procsetup(struct net_device *);static void del_cb20(struct net_device *);static void add_cb20(struct net_device *);static void cb20_reap(void);#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,13))static int net_send_packet(struct sk_buff *, struct net_device *);#endif/* INCLUDE_RFMONITOR - "#define" this will include RF monitor mode code for use with sniffers must have WIRELESS_EXT (include linux/wireless.h)#define INCLUDE_RFMONITOR */#ifdef INCLUDE_RFMONITORstatic void cb20_set_rfmonitor(struct cb20_info *v_info);#endif#ifdef WIRELESS_EXTstruct iw_statistics *airo_get_wireless_stats(struct net_device *dev);#endif/* * Proc filesystem definitions */static struct file_operations proc_ssid_ops = { read: proc_read, write: proc_write, open: proc_ssid_open, release: proc_close};static struct file_operations proc_status_ops = { read: proc_read, open: proc_status_open, release: proc_close};/* * Handle 2.2 /proc */#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,11))static struct inode_operations proc_inode_ssid_ops = { &proc_ssid_ops};static struct inode_operations proc_inode_status_ops = { &proc_status_ops};static struct proc_dir_entry ssid_entry = { 0, 4, "SSID", S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 13, &proc_inode_ssid_ops, NULL};static struct proc_dir_entry status_entry = { 0,6,"Status", S_IFREG | S_IRUGO | S_IWUSR, 2, 0, 0, 13, &proc_inode_status_ops,NULL};#endif/* * Start of kernel PCMCIA/CARDBUS */#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET_PCMCIA)#undef CONFIG_PM/* * device driver ID table and * operations . */static struct pci_device_id cb20_pci_tbl[] = { { AIRONET, 0xa505,PCI_ANY_ID, PCI_ANY_ID, }, { 0,},};static struct pci_driver cb20_driver = { name: "cb20_cb", id_table: cb20_pci_tbl, probe: cb20_probe1,#if (LINUX_VERSION_CODE >= 0x20416 ) remove: __devexit_p(cb20_remove),#else remove: cb20_remove,#endif#ifdef CONFIG_PM suspend: cb20_suspend, resume: cb20_resume,#endif /* CONFIG_PM */};MODULE_DEVICE_TABLE(pci, cb20_pci_tbl);#else/* ** *** external pcmcia-cs driver interface */struct driver_operations cb20_ops = { "cb20_cb", cb20_attach, cb20_suspend, cb20_resume, cb20_detach};#endifstatic int waitbusy(struct cb20_info *cb_info){ int time=0; while ((cb20in (cb_info, V_COMMAND) & COMMAND_BUSY) & (time < 10000)) { udelay (10); if (++time % 20) cb20out(cb_info, V_EVACK, EV_CLEARCOMMANDBUSY); } return time >= 10000 ;}/* * @New style PCI and Kernel PCMCIA + HOTPLUG * */#if defined(CONFIG_HOTPLUG) && defined(CONFIG_NET_PCMCIA) /* *@remove */void cb20_remove(struct pci_dev *pdev){ struct net_device *nd; if((nd=pcidev_loc(pdev))!=0){ del_proc_entry(nd,nd->priv); eject_cb20_card(nd); } else printk(KERN_WARNING "Cant locate device %p\n",pdev);}/* * @eject CB20 * Card has been removed */int eject_cb20_card( struct net_device *vdev){ struct cb20_info *v_info = (struct cb20_info*)vdev->priv; struct sk_buff *skb=0; /* device has been freed * already bail */ if(vdev == 0) return -1; del_proc_entry(vdev,v_info); del_cb20(vdev); cb20out(v_info,0,CB_FLAGBIT); /* disable cardbus ints */ netif_device_detach(vdev);#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)) /* Clean out tx queue */ if(skb_queue_len(&v_info->txq)> 0 ) for(;(skb = skb_dequeue(&v_info->txq));) dev_kfree_skb(skb);#endif pci_free_consistent(v_info->pcip, SHAREDMEMSIZE,v_info->SharedRegion,v_info->SharedBusaddr); iounmap(v_info->auxregmembase); unregister_netdev(vdev); kfree(vdev); return 0;}/* * @probe1 Insert time probe */static int cb20_probe1(struct pci_dev *pci,const struct pci_device_id *ent){ struct net_device *ndev; struct cb20_info *v_info ; if((ndev=cb20_probe(pci))!=0){ schednap(10); v_info = (struct cb20_info *)ndev->priv; v_info->device = create_proc_entry(ndev->name,S_IFDIR|0555,cb20_entry); procsetup(ndev); add_cb20(ndev); return 0; } else return -ENODEV;}/* New style PCI driver routines */static int __init cb20_init_module(void){ cb20_reap(); cb20_entry = create_proc_entry(PRODNAME,S_IFDIR | S_IRUGO,proc_root_driver); return pci_module_init(&cb20_driver);}static void __exit cb20_cleanup_module(void){ cb20_reap(); remove_proc_entry(PRODNAME, proc_root_driver); pci_unregister_driver(&cb20_driver);}module_init(cb20_init_module);module_exit(cb20_cleanup_module);#else/* Old style pcmcia-cs interface * */int init_module(void){ printk(KERN_DEBUG "%s\n", version);#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)) cb20_entry = create_proc_entry(PRODNAME,S_IFDIR | 0555,proc_root_driver);#else cb20_entry.ops->lookup = proc_net->ops->lookup; cb20_entry.ops->default_file_ops->readdir = proc_net->ops->default_file_ops->readdir; proc_register( &proc_root,&cb20_entry);#endif register_driver(&cb20_ops); return 0;}void cleanup_module(void){ printk(KERN_DEBUG "cb20_cb: unloading\n");#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)) remove_proc_entry(PRODNAME, proc_root_driver); #else proc_unregister(&proc_root,cb20_entry.low_ino);#endif unregister_driver(&cb20_ops); cb20_reap();}#endif/* * Enable MAC * @MAC */static int enable_mac(struct cb20_info *cb_info,Resp *rsp){ Cmd command; int tries = 6000000; int delay,rc,flags; delay=rc=0; if(cb_info->flags & FLASHING ) return 0; memset(&command,0,sizeof(command)); command.cmd = CMD_X500_EnableAll; spin_lock_irqsave(&cb_info->cmd_lock, flags); if(waitbusy(cb_info)){ printk(KERN_ERR "MAC: WaitBusy timeout\n"); spin_lock_irqsave(&cb_info->cmd_lock, flags); return -1; } cb20out(cb_info, V_PARAM0, command.parm0); cb20out(cb_info, V_PARAM1, command.parm1); cb20out(cb_info, V_PARAM2, command.parm2); cb20out(cb_info, V_COMMAND, command.cmd); while(tries-- && (cb20in(cb_info, V_EVSTAT) & EV_CMD) == 0) { if ( cb20in(cb_info, V_COMMAND) == command.cmd) { /* didn't notice command, try again */ cb20out(cb_info, V_COMMAND, command.cmd); } if(tries % 20 ) udelay(10); } if(tries == -1 ){ printk(KERN_ERR "MAC: Max tries enabling mac\n"); spin_unlock_irqrestore(&cb_info->cmd_lock, flags); return -1; } /* command completed */ rsp->status = cb20in(cb_info, V_STATUS); rsp->rsp0 = cb20in(cb_info, V_RESP0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -