📄 ray_cs.c
字号:
/*============================================================================= * * A PCMCIA client driver for the Raylink wireless LAN card. * The starting point for this module was the skeleton.c in the * PCMCIA 2.9.12 package written by David Hinds, dhinds@allegro.stanford.edu * * * Copyright (c) 1998 Corey Thomas (corey@world.std.com) * * This driver is free software; you can redistribute it and/or modify * it under the terms of version 2 only of the GNU General Public License as * published by the Free Software Foundation. * * It is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * =============================================================================*/#include <linux/kernel.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/proc_fs.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/string.h>#include <linux/timer.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm/system.h>#include <asm/byteorder.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/if_arp.h>#include <linux/ioport.h>#include <linux/skbuff.h>#include <pcmcia/version.h>#include <pcmcia/cs_types.h>#include <pcmcia/cs.h>#include <pcmcia/cistpl.h>#include <pcmcia/cisreg.h>#include <pcmcia/ds.h>#include <pcmcia/mem_op.h>#ifdef CONFIG_NET_PCMCIA_RADIO#include <linux/wireless.h>#if WIRELESS_EXT < 9#warning "Wireless extension v9 or newer required"#endif /* WIRELESS_EXT < 9 *//* Warning : these stuff will slow down the driver... */#define WIRELESS_SPY /* Enable spying addresses *//* Definitions we need for spy */typedef struct iw_statistics iw_stats;typedef struct iw_quality iw_qual;typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */#endif /* CONFIG_NET_PCMCIA_RADIO */#include "rayctl.h"#include "ray_cs.h"/* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not define PCMCIA_DEBUG at all, all the debug code will be left out. If you compile with PCMCIA_DEBUG=0, the debug code will be present but disabled -- but it can then be enabled for specific modules at load time with a 'pc_debug=#' option to insmod.*/#ifdef RAYLINK_DEBUG#define PCMCIA_DEBUG RAYLINK_DEBUG#endif#ifdef PCMCIA_DEBUGstatic int ray_debug = 0;static int pc_debug = PCMCIA_DEBUG;MODULE_PARM(pc_debug, "i");/* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */#define DEBUG(n, args...) if (pc_debug>(n)) printk(args);#else#define DEBUG(n, args...)#endif/** Prototypes based on PCMCIA skeleton driver *******************************/static void ray_config(dev_link_t *link);static void ray_release(u_long arg);static int ray_event(event_t event, int priority, event_callback_args_t *args);static dev_link_t *ray_attach(void);static void ray_detach(dev_link_t *);/***** Prototypes indicated by device structure ******************************/static int ray_dev_close(struct net_device *dev);static int ray_dev_config(struct net_device *dev, struct ifmap *map);static struct net_device_stats *ray_get_stats(struct net_device *dev);static int ray_dev_init(struct net_device *dev);static int ray_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);static int ray_open(struct net_device *dev);static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);static void set_multicast_list(struct net_device *dev);static void ray_update_multi_list(struct net_device *dev, int all);static int translate_frame(ray_dev_t *local, struct tx_msg *ptx, unsigned char *data, int len);static void ray_build_header(ray_dev_t *local, struct tx_msg *ptx, UCHAR msg_type, unsigned char *data);static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);#if WIRELESS_EXT > 7 /* If wireless extension exist in the kernel */static iw_stats * ray_get_wireless_stats(struct net_device * dev);#endif /* WIRELESS_EXT > 7 *//***** Prototypes for raylink functions **************************************/static int asc_to_int(char a);static void authenticate(ray_dev_t *local);static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);static void authenticate_timeout(u_long);static int get_free_ccs(ray_dev_t *local);static int get_free_tx_ccs(ray_dev_t *local);static void init_startup_params(ray_dev_t *local);static int parse_addr(char *in_str, UCHAR *out);static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);static int ray_init(struct net_device *dev);static int interrupt_ecf(ray_dev_t *local, int ccs);static void ray_reset(struct net_device *dev);static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);static void verify_dl_startup(u_long);/* Prototypes for interrpt time functions **********************************/static void ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);static void clear_interrupt(ray_dev_t *local);static void rx_deauthenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len);static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs *prcs);static void release_frag_chain(ray_dev_t *local, struct rcs *prcs);static void rx_authenticate(ray_dev_t *local, struct rcs *prcs, unsigned int pkt_addr, int rx_len);static void rx_data(struct net_device *dev, struct rcs *prcs, unsigned int pkt_addr, int rx_len);static void associate(ray_dev_t *local);/* Card command functions */static int dl_startup_params(struct net_device *dev);static void join_net(u_long local);static void start_net(u_long local);/* void start_net(ray_dev_t *local); */static int ray_cs_proc_read(char *, char **, off_t, int, int *, void *);/* Create symbol table for registering with kernel in init_module */#if (LINUX_VERSION_CODE <= VERSION(2,1,17))static struct symbol_table ray_cs_syms = {#include <linux/symtab_begin.h>#undef X#define X(sym) { (void *)&sym, SYMBOL_NAME_STR(sym) } X(ray_rx), X(ray_dev_ioctl),#include <linux/symtab_end.h>};#else /* (kernel > 2.1.17) Use new kernel method of registering symbols */EXPORT_SYMBOL(ray_dev_ioctl);EXPORT_SYMBOL(ray_rx);#endif/*===========================================================================*//* Parameters that can be set with 'insmod' *//* Bit map of interrupts to choose from *//* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */static u_long irq_mask = 0xdeb8;/* ADHOC=0, Infrastructure=1 */static int net_type = ADHOC;/* Hop dwell time in Kus (1024 us units defined by 802.11) */static int hop_dwell = 128;/* Beacon period in Kus */static int beacon_period = 256;/* power save mode (0 = off, 1 = save power) */static int psm = 0;/* String for network's Extended Service Set ID. 32 Characters max */static char *essid = NULL;/* Default to encapsulation unless translation requested */static int translate = 1;static int country = USA;static int sniffer = 0;static int bc = 0;/* 48 bit physical card address if overriding card's real physical * address is required. Since IEEE 802.11 addresses are 48 bits * like ethernet, an int can't be used, so a string is used. To * allow use of addresses starting with a decimal digit, the first * character must be a letter and will be ignored. This letter is * followed by up to 12 hex digits which are the address. If less * than 12 digits are used, the address will be left filled with 0's. * Note that bit 0 of the first byte is the broadcast bit, and evil * things will happen if it is not 0 in a card address. */static char *phy_addr = NULL;/* The dev_info variable is the "key" that is used to match up this device driver with appropriate cards, through the card configuration database.*/static dev_info_t dev_info = "ray_cs";/* A linked list of "instances" of the ray device. Each actual PCMCIA card corresponds to one device instance, and is described by one dev_link_t structure (defined in ds.h).*/static dev_link_t *dev_list = NULL;/* A dev_link_t structure has fields for most things that are needed to keep track of a socket, but there will usually be some device specific information that also needs to be kept track of. The 'priv' pointer in a dev_link_t structure can be used to point to a device-specific private data structure, like this.*/static unsigned int ray_mem_speed = 500;MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");MODULE_LICENSE("GPL");MODULE_PARM(irq_mask,"i");MODULE_PARM(net_type,"i");MODULE_PARM(hop_dwell,"i");MODULE_PARM(beacon_period,"i");MODULE_PARM(psm,"i");MODULE_PARM(essid,"s");MODULE_PARM(translate,"i");MODULE_PARM(country,"i");MODULE_PARM(sniffer,"i");MODULE_PARM(bc,"i");MODULE_PARM(phy_addr,"s");MODULE_PARM(ray_mem_speed, "i");static UCHAR b5_default_startup_parms[] = { 0, 0, /* Adhoc station */ 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* Active scan, CA Mode */ 0, 0, 0, 0, 0, 0, /* No default MAC addr */ 0x7f, 0xff, /* Frag threshold */ 0x00, 0x80, /* Hop time 128 Kus*/ 0x01, 0x00, /* Beacon period 256 Kus */ 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ 0x7f, 0xff, /* RTS threshold */ 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ 0x05, /* assoc resp timeout thresh */ 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max*/ 0, /* Promiscuous mode */ 0x0c, 0x0bd, /* Unique word */ 0x32, /* Slot time */ 0xff, 0xff, /* roam-low snr, low snr count */ 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length *//* b4 - b5 differences start here */ 0x00, 0x3f, /* CW max */ 0x00, 0x0f, /* CW min */ 0x04, 0x08, /* Noise gain, limit offset */ 0x28, 0x28, /* det rssi, med busy offsets */ 7, /* det sync thresh */ 0, 2, 2, /* test mode, min, max */ 0, /* allow broadcast SSID probe resp */ 0, 0, /* privacy must start, can join */ 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */};static UCHAR b4_default_startup_parms[] = { 0, 0, /* Adhoc station */ 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, /* Active scan, CA Mode */ 0, 0, 0, 0, 0, 0, /* No default MAC addr */ 0x7f, 0xff, /* Frag threshold */ 0x02, 0x00, /* Hop time */ 0x00, 0x01, /* Beacon period */ 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/ 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ 0x7f, 0xff, /* RTS threshold */ 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ 0x05, /* assoc resp timeout thresh */ 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max*/ 0, /* Promiscuous mode */ 0x0c, 0x0bd, /* Unique word */ 0x4e, /* Slot time (TBD seems wrong)*/ 0xff, 0xff, /* roam-low snr, low snr count */ 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length *//* b4 - b5 differences start here */ 0x3f, 0x0f, /* CW max, min */ 0x04, 0x08, /* Noise gain, limit offset */ 0x28, 0x28, /* det rssi, med busy offsets */ 7, /* det sync thresh */ 0, 2, 2 /* test mode, min, max*/};/*===========================================================================*/static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0};static char hop_pattern_length[] = { 1, USA_HOP_MOD, EUROPE_HOP_MOD, JAPAN_HOP_MOD, KOREA_HOP_MOD, SPAIN_HOP_MOD, FRANCE_HOP_MOD, ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, JAPAN_TEST_HOP_MOD};static char rcsid[] = " ray_cs.c,v 1.33 2002/06/29 06:39:33 root Exp - Corey Thomas corey@world.std.com";/*===========================================================================*/static void cs_error(client_handle_t handle, int func, int ret){ error_info_t err = { func, ret }; CardServices(ReportError, handle, &err);}/*====================================================================== This bit of code is used to avoid unregistering network devices at inappropriate times. 2.2 and later kernels are fairly picky about when this can happen. ======================================================================*/static void flush_stale_links(void){ dev_link_t *link, *next; for (link = dev_list; link; link = next) { next = link->next; if (link->state & DEV_STALE_LINK) ray_detach(link); }}/*============================================================================= ray_attach() creates an "instance" of the driver, allocating local data structures for one device. The device is registered with Card Services. The dev_link structure is initialized, but we don't actually configure the card at this point -- we wait until we receive a card insertion event.=============================================================================*/static dev_link_t *ray_attach(void){ client_reg_t client_reg; dev_link_t *link; ray_dev_t *local; int ret; struct net_device *dev; DEBUG(1, "ray_attach()\n"); flush_stale_links(); /* Initialize the dev_link_t structure */ link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL); if (link == NULL) return link; memset(link, 0, sizeof(struct dev_link_t)); link->release.function = &ray_release; link->release.data = (u_long)link; /* The io structure describes IO port mapping. None used here */ link->io.NumPorts1 = 0; link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; link->io.IOAddrLines = 5; /* Interrupt setup. For PCMCIA, driver takes what's given */ link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; link->irq.IRQInfo2 = irq_mask;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -