blob: 70fd6fd8feb9bd5fb856043e8e195ddfccea84e6 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*=============================================================================
2 *
3 * A PCMCIA client driver for the Raylink wireless LAN card.
4 * The starting point for this module was the skeleton.c in the
5 * PCMCIA 2.9.12 package written by David Hinds, dahinds@users.sourceforge.net
6 *
7 *
8 * Copyright (c) 1998 Corey Thomas (corey@world.std.com)
9 *
10 * This driver is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 only of the GNU General Public License as
12 * published by the Free Software Foundation.
13 *
14 * It is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 *
23 * Changes:
24 * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 08/08/2000
25 * - reorganize kmallocs in ray_attach, checking all for failure
26 * and releasing the previous allocations if one fails
27 *
28 * Daniele Bellucci <bellucda@tiscali.it> - 07/10/2003
29 * - Audit copy_to_user in ioctl(SIOCGIWESSID)
30 *
31=============================================================================*/
32
33#include <linux/config.h>
34#include <linux/module.h>
35#include <linux/kernel.h>
36#include <linux/proc_fs.h>
37#include <linux/ptrace.h>
38#include <linux/slab.h>
39#include <linux/string.h>
40#include <linux/timer.h>
41#include <linux/init.h>
42#include <linux/netdevice.h>
43#include <linux/etherdevice.h>
44#include <linux/if_arp.h>
45#include <linux/ioport.h>
46#include <linux/skbuff.h>
47#include <linux/ethtool.h>
48
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <pcmcia/cs_types.h>
50#include <pcmcia/cs.h>
51#include <pcmcia/cistpl.h>
52#include <pcmcia/cisreg.h>
53#include <pcmcia/ds.h>
54#include <pcmcia/mem_op.h>
55
Jeff Garzikbbeec902005-09-07 00:27:54 -040056#include <net/ieee80211.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#include <linux/wireless.h>
58
59#include <asm/io.h>
60#include <asm/system.h>
61#include <asm/byteorder.h>
62#include <asm/uaccess.h>
63
64/* Warning : these stuff will slow down the driver... */
65#define WIRELESS_SPY /* Enable spying addresses */
66/* Definitions we need for spy */
67typedef struct iw_statistics iw_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -070068typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */
69
70#include "rayctl.h"
71#include "ray_cs.h"
72
73/* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
74 you do not define PCMCIA_DEBUG at all, all the debug code will be
75 left out. If you compile with PCMCIA_DEBUG=0, the debug code will
76 be present but disabled -- but it can then be enabled for specific
77 modules at load time with a 'pc_debug=#' option to insmod.
78*/
79
80#ifdef RAYLINK_DEBUG
81#define PCMCIA_DEBUG RAYLINK_DEBUG
82#endif
83#ifdef PCMCIA_DEBUG
84static int ray_debug;
85static int pc_debug = PCMCIA_DEBUG;
86module_param(pc_debug, int, 0);
87/* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */
88#define DEBUG(n, args...) if (pc_debug>(n)) printk(args);
89#else
90#define DEBUG(n, args...)
91#endif
92/** Prototypes based on PCMCIA skeleton driver *******************************/
93static void ray_config(dev_link_t *link);
94static void ray_release(dev_link_t *link);
95static int ray_event(event_t event, int priority, event_callback_args_t *args);
96static dev_link_t *ray_attach(void);
97static void ray_detach(dev_link_t *);
98
99/***** Prototypes indicated by device structure ******************************/
100static int ray_dev_close(struct net_device *dev);
101static int ray_dev_config(struct net_device *dev, struct ifmap *map);
102static struct net_device_stats *ray_get_stats(struct net_device *dev);
103static int ray_dev_init(struct net_device *dev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104
105static struct ethtool_ops netdev_ethtool_ops;
106
107static int ray_open(struct net_device *dev);
108static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev);
109static void set_multicast_list(struct net_device *dev);
110static void ray_update_multi_list(struct net_device *dev, int all);
111static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx,
112 unsigned char *data, int len);
113static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
114 unsigned char *data);
115static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116static iw_stats * ray_get_wireless_stats(struct net_device * dev);
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -0700117static const struct iw_handler_def ray_handler_def;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118
119/***** Prototypes for raylink functions **************************************/
120static int asc_to_int(char a);
121static void authenticate(ray_dev_t *local);
122static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type);
123static void authenticate_timeout(u_long);
124static int get_free_ccs(ray_dev_t *local);
125static int get_free_tx_ccs(ray_dev_t *local);
126static void init_startup_params(ray_dev_t *local);
127static int parse_addr(char *in_str, UCHAR *out);
128static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev, UCHAR type);
129static int ray_init(struct net_device *dev);
130static int interrupt_ecf(ray_dev_t *local, int ccs);
131static void ray_reset(struct net_device *dev);
132static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len);
133static void verify_dl_startup(u_long);
134
135/* Prototypes for interrpt time functions **********************************/
136static irqreturn_t ray_interrupt (int reg, void *dev_id, struct pt_regs *regs);
137static void clear_interrupt(ray_dev_t *local);
138static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs,
139 unsigned int pkt_addr, int rx_len);
140static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len);
141static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs);
142static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs);
143static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
144 unsigned int pkt_addr, int rx_len);
145static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr,
146 int rx_len);
147static void associate(ray_dev_t *local);
148
149/* Card command functions */
150static int dl_startup_params(struct net_device *dev);
151static void join_net(u_long local);
152static void start_net(u_long local);
153/* void start_net(ray_dev_t *local); */
154
155/*===========================================================================*/
156/* Parameters that can be set with 'insmod' */
157
158/* ADHOC=0, Infrastructure=1 */
159static int net_type = ADHOC;
160
161/* Hop dwell time in Kus (1024 us units defined by 802.11) */
162static int hop_dwell = 128;
163
164/* Beacon period in Kus */
165static int beacon_period = 256;
166
167/* power save mode (0 = off, 1 = save power) */
168static int psm;
169
170/* String for network's Extended Service Set ID. 32 Characters max */
171static char *essid;
172
173/* Default to encapsulation unless translation requested */
174static int translate = 1;
175
176static int country = USA;
177
178static int sniffer;
179
180static int bc;
181
182/* 48 bit physical card address if overriding card's real physical
183 * address is required. Since IEEE 802.11 addresses are 48 bits
184 * like ethernet, an int can't be used, so a string is used. To
185 * allow use of addresses starting with a decimal digit, the first
186 * character must be a letter and will be ignored. This letter is
187 * followed by up to 12 hex digits which are the address. If less
188 * than 12 digits are used, the address will be left filled with 0's.
189 * Note that bit 0 of the first byte is the broadcast bit, and evil
190 * things will happen if it is not 0 in a card address.
191 */
192static char *phy_addr = NULL;
193
194
195/* The dev_info variable is the "key" that is used to match up this
196 device driver with appropriate cards, through the card configuration
197 database.
198*/
199static dev_info_t dev_info = "ray_cs";
200
201/* A linked list of "instances" of the ray device. Each actual
202 PCMCIA card corresponds to one device instance, and is described
203 by one dev_link_t structure (defined in ds.h).
204*/
205static dev_link_t *dev_list = NULL;
206
207/* A dev_link_t structure has fields for most things that are needed
208 to keep track of a socket, but there will usually be some device
209 specific information that also needs to be kept track of. The
210 'priv' pointer in a dev_link_t structure can be used to point to
211 a device-specific private data structure, like this.
212*/
213static unsigned int ray_mem_speed = 500;
214
215MODULE_AUTHOR("Corey Thomas <corey@world.std.com>");
216MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver");
217MODULE_LICENSE("GPL");
218
219module_param(net_type, int, 0);
220module_param(hop_dwell, int, 0);
221module_param(beacon_period, int, 0);
222module_param(psm, int, 0);
223module_param(essid, charp, 0);
224module_param(translate, int, 0);
225module_param(country, int, 0);
226module_param(sniffer, int, 0);
227module_param(bc, int, 0);
228module_param(phy_addr, charp, 0);
229module_param(ray_mem_speed, int, 0);
230
231static UCHAR b5_default_startup_parms[] = {
232 0, 0, /* Adhoc station */
233 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */
234 0, 0, 0, 0, 0, 0, 0, 0,
235 0, 0, 0, 0, 0, 0, 0, 0,
236 0, 0, 0, 0, 0, 0, 0, 0,
237 1, 0, /* Active scan, CA Mode */
238 0, 0, 0, 0, 0, 0, /* No default MAC addr */
239 0x7f, 0xff, /* Frag threshold */
240 0x00, 0x80, /* Hop time 128 Kus*/
241 0x01, 0x00, /* Beacon period 256 Kus */
242 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/
243 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */
244 0x7f, 0xff, /* RTS threshold */
245 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */
246 0x05, /* assoc resp timeout thresh */
247 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max*/
248 0, /* Promiscuous mode */
249 0x0c, 0x0bd, /* Unique word */
250 0x32, /* Slot time */
251 0xff, 0xff, /* roam-low snr, low snr count */
252 0x05, 0xff, /* Infra, adhoc missed bcn thresh */
253 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */
254/* b4 - b5 differences start here */
255 0x00, 0x3f, /* CW max */
256 0x00, 0x0f, /* CW min */
257 0x04, 0x08, /* Noise gain, limit offset */
258 0x28, 0x28, /* det rssi, med busy offsets */
259 7, /* det sync thresh */
260 0, 2, 2, /* test mode, min, max */
261 0, /* allow broadcast SSID probe resp */
262 0, 0, /* privacy must start, can join */
263 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */
264};
265
266static UCHAR b4_default_startup_parms[] = {
267 0, 0, /* Adhoc station */
268 'L','I','N','U','X', 0, 0, 0, /* 32 char ESSID */
269 0, 0, 0, 0, 0, 0, 0, 0,
270 0, 0, 0, 0, 0, 0, 0, 0,
271 0, 0, 0, 0, 0, 0, 0, 0,
272 1, 0, /* Active scan, CA Mode */
273 0, 0, 0, 0, 0, 0, /* No default MAC addr */
274 0x7f, 0xff, /* Frag threshold */
275 0x02, 0x00, /* Hop time */
276 0x00, 0x01, /* Beacon period */
277 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout*/
278 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */
279 0x7f, 0xff, /* RTS threshold */
280 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */
281 0x05, /* assoc resp timeout thresh */
282 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max*/
283 0, /* Promiscuous mode */
284 0x0c, 0x0bd, /* Unique word */
285 0x4e, /* Slot time (TBD seems wrong)*/
286 0xff, 0xff, /* roam-low snr, low snr count */
287 0x05, 0xff, /* Infra, adhoc missed bcn thresh */
288 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */
289/* b4 - b5 differences start here */
290 0x3f, 0x0f, /* CW max, min */
291 0x04, 0x08, /* Noise gain, limit offset */
292 0x28, 0x28, /* det rssi, med busy offsets */
293 7, /* det sync thresh */
294 0, 2, 2 /* test mode, min, max*/
295};
296/*===========================================================================*/
297static unsigned char eth2_llc[] = {0xaa, 0xaa, 3, 0, 0, 0};
298
299static char hop_pattern_length[] = { 1,
300 USA_HOP_MOD, EUROPE_HOP_MOD,
301 JAPAN_HOP_MOD, KOREA_HOP_MOD,
302 SPAIN_HOP_MOD, FRANCE_HOP_MOD,
303 ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD,
304 JAPAN_TEST_HOP_MOD
305};
306
307static char rcsid[] = "Raylink/WebGear wireless LAN - Corey <Thomas corey@world.std.com>";
308
309/*=============================================================================
310 ray_attach() creates an "instance" of the driver, allocating
311 local data structures for one device. The device is registered
312 with Card Services.
313 The dev_link structure is initialized, but we don't actually
314 configure the card at this point -- we wait until we receive a
315 card insertion event.
316=============================================================================*/
317static dev_link_t *ray_attach(void)
318{
319 client_reg_t client_reg;
320 dev_link_t *link;
321 ray_dev_t *local;
322 int ret;
323 struct net_device *dev;
324
325 DEBUG(1, "ray_attach()\n");
326
327 /* Initialize the dev_link_t structure */
328 link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
329
330 if (!link)
331 return NULL;
332
333 /* Allocate space for private device-specific data */
334 dev = alloc_etherdev(sizeof(ray_dev_t));
335
336 if (!dev)
337 goto fail_alloc_dev;
338
339 local = dev->priv;
340
341 memset(link, 0, sizeof(struct dev_link_t));
342
343 /* The io structure describes IO port mapping. None used here */
344 link->io.NumPorts1 = 0;
345 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
346 link->io.IOAddrLines = 5;
347
348 /* Interrupt setup. For PCMCIA, driver takes what's given */
349 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
350 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
351 link->irq.Handler = &ray_interrupt;
352
353 /* General socket configuration */
354 link->conf.Attributes = CONF_ENABLE_IRQ;
355 link->conf.Vcc = 50;
356 link->conf.IntType = INT_MEMORY_AND_IO;
357 link->conf.ConfigIndex = 1;
358 link->conf.Present = PRESENT_OPTION;
359
360 link->priv = dev;
361 link->irq.Instance = dev;
362
363 local->finder = link;
364 local->card_status = CARD_INSERTED;
365 local->authentication_state = UNAUTHENTICATED;
366 local->num_multi = 0;
367 DEBUG(2,"ray_attach link = %p, dev = %p, local = %p, intr = %p\n",
368 link,dev,local,&ray_interrupt);
369
370 /* Raylink entries in the device structure */
371 dev->hard_start_xmit = &ray_dev_start_xmit;
372 dev->set_config = &ray_dev_config;
373 dev->get_stats = &ray_get_stats;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -0700375 dev->wireless_handlers = &ray_handler_def;
376#ifdef WIRELESS_SPY
377 local->wireless_data.spy_data = &local->spy_data;
378 dev->wireless_data = &local->wireless_data;
379#endif /* WIRELESS_SPY */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380
381 dev->set_multicast_list = &set_multicast_list;
382
383 DEBUG(2,"ray_cs ray_attach calling ether_setup.)\n");
384 SET_MODULE_OWNER(dev);
385 dev->init = &ray_dev_init;
386 dev->open = &ray_open;
387 dev->stop = &ray_dev_close;
388 netif_stop_queue(dev);
389
390 /* Register with Card Services */
391 link->next = dev_list;
392 dev_list = link;
393 client_reg.dev_info = &dev_info;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394 client_reg.Version = 0x0210;
395 client_reg.event_callback_args.client_data = link;
396
397 DEBUG(2,"ray_cs ray_attach calling pcmcia_register_client(...)\n");
398
399 init_timer(&local->timer);
400
401 ret = pcmcia_register_client(&link->handle, &client_reg);
402 if (ret != 0) {
403 printk("ray_cs ray_attach RegisterClient unhappy - detaching\n");
404 cs_error(link->handle, RegisterClient, ret);
405 ray_detach(link);
406 return NULL;
407 }
408 DEBUG(2,"ray_cs ray_attach ending\n");
409 return link;
410
411fail_alloc_dev:
412 kfree(link);
413 return NULL;
414} /* ray_attach */
415/*=============================================================================
416 This deletes a driver "instance". The device is de-registered
417 with Card Services. If it has been released, all local data
418 structures are freed. Otherwise, the structures will be freed
419 when the device is released.
420=============================================================================*/
421static void ray_detach(dev_link_t *link)
422{
423 dev_link_t **linkp;
424
425 DEBUG(1, "ray_detach(0x%p)\n", link);
426
427 /* Locate device structure */
428 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
429 if (*linkp == link) break;
430 if (*linkp == NULL)
431 return;
432
433 /* If the device is currently configured and active, we won't
434 actually delete it yet. Instead, it is marked so that when
435 the release() function is called, that will trigger a proper
436 detach().
437 */
438 if (link->state & DEV_CONFIG)
439 ray_release(link);
440
441 /* Break the link with Card Services */
442 if (link->handle)
443 pcmcia_deregister_client(link->handle);
444
445 /* Unlink device structure, free pieces */
446 *linkp = link->next;
447 if (link->priv) {
448 struct net_device *dev = link->priv;
449 if (link->dev) unregister_netdev(dev);
450 free_netdev(dev);
451 }
452 kfree(link);
453 DEBUG(2,"ray_cs ray_detach ending\n");
454} /* ray_detach */
455/*=============================================================================
456 ray_config() is run after a CARD_INSERTION event
457 is received, to configure the PCMCIA socket, and to make the
458 ethernet device available to the system.
459=============================================================================*/
460#define CS_CHECK(fn, ret) \
461do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
462#define MAX_TUPLE_SIZE 128
463static void ray_config(dev_link_t *link)
464{
465 client_handle_t handle = link->handle;
466 tuple_t tuple;
467 cisparse_t parse;
468 int last_fn = 0, last_ret = 0;
469 int i;
470 u_char buf[MAX_TUPLE_SIZE];
471 win_req_t req;
472 memreq_t mem;
473 struct net_device *dev = (struct net_device *)link->priv;
474 ray_dev_t *local = (ray_dev_t *)dev->priv;
475
476 DEBUG(1, "ray_config(0x%p)\n", link);
477
478 /* This reads the card's CONFIG tuple to find its configuration regs */
479 tuple.DesiredTuple = CISTPL_CONFIG;
480 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
481 tuple.TupleData = buf;
482 tuple.TupleDataMax = MAX_TUPLE_SIZE;
483 tuple.TupleOffset = 0;
484 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
485 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
486 link->conf.ConfigBase = parse.config.base;
487 link->conf.Present = parse.config.rmask[0];
488
489 /* Determine card type and firmware version */
490 buf[0] = buf[MAX_TUPLE_SIZE - 1] = 0;
491 tuple.DesiredTuple = CISTPL_VERS_1;
492 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
493 tuple.TupleData = buf;
494 tuple.TupleDataMax = MAX_TUPLE_SIZE;
495 tuple.TupleOffset = 2;
496 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
497
498 for (i=0; i<tuple.TupleDataLen - 4; i++)
499 if (buf[i] == 0) buf[i] = ' ';
500 printk(KERN_INFO "ray_cs Detected: %s\n",buf);
501
502 /* Configure card */
503 link->state |= DEV_CONFIG;
504
505 /* Now allocate an interrupt line. Note that this does not
506 actually assign a handler to the interrupt.
507 */
508 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
509 dev->irq = link->irq.AssignedIRQ;
510
511 /* This actually configures the PCMCIA socket -- setting up
512 the I/O windows and the interrupt mapping.
513 */
514 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
515
516/*** Set up 32k window for shared memory (transmit and control) ************/
517 req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
518 req.Base = 0;
519 req.Size = 0x8000;
520 req.AccessSpeed = ray_mem_speed;
521 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
522 mem.CardOffset = 0x0000; mem.Page = 0;
523 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
524 local->sram = ioremap(req.Base,req.Size);
525
526/*** Set up 16k window for shared memory (receive buffer) ***************/
527 req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT;
528 req.Base = 0;
529 req.Size = 0x4000;
530 req.AccessSpeed = ray_mem_speed;
531 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->rmem_handle));
532 mem.CardOffset = 0x8000; mem.Page = 0;
533 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem));
534 local->rmem = ioremap(req.Base,req.Size);
535
536/*** Set up window for attribute memory ***********************************/
537 req.Attributes = WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT;
538 req.Base = 0;
539 req.Size = 0x1000;
540 req.AccessSpeed = ray_mem_speed;
541 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &local->amem_handle));
542 mem.CardOffset = 0x0000; mem.Page = 0;
543 CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem));
544 local->amem = ioremap(req.Base,req.Size);
545
546 DEBUG(3,"ray_config sram=%p\n",local->sram);
547 DEBUG(3,"ray_config rmem=%p\n",local->rmem);
548 DEBUG(3,"ray_config amem=%p\n",local->amem);
549 if (ray_init(dev) < 0) {
550 ray_release(link);
551 return;
552 }
553
554 SET_NETDEV_DEV(dev, &handle_to_dev(handle));
555 i = register_netdev(dev);
556 if (i != 0) {
557 printk("ray_config register_netdev() failed\n");
558 ray_release(link);
559 return;
560 }
561
562 strcpy(local->node.dev_name, dev->name);
563 link->dev = &local->node;
564
565 link->state &= ~DEV_CONFIG_PENDING;
566 printk(KERN_INFO "%s: RayLink, irq %d, hw_addr ",
567 dev->name, dev->irq);
568 for (i = 0; i < 6; i++)
569 printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));
570
571 return;
572
573cs_failed:
574 cs_error(link->handle, last_fn, last_ret);
575
576 ray_release(link);
577} /* ray_config */
578
579static inline struct ccs __iomem *ccs_base(ray_dev_t *dev)
580{
581 return dev->sram + CCS_BASE;
582}
583
584static inline struct rcs __iomem *rcs_base(ray_dev_t *dev)
585{
586 /*
587 * This looks nonsensical, since there is a separate
588 * RCS_BASE. But the difference between a "struct rcs"
589 * and a "struct ccs" ends up being in the _index_ off
590 * the base, so the base pointer is the same for both
591 * ccs/rcs.
592 */
593 return dev->sram + CCS_BASE;
594}
595
596/*===========================================================================*/
597static int ray_init(struct net_device *dev)
598{
599 int i;
600 UCHAR *p;
601 struct ccs __iomem *pccs;
602 ray_dev_t *local = (ray_dev_t *)dev->priv;
603 dev_link_t *link = local->finder;
604 DEBUG(1, "ray_init(0x%p)\n", dev);
605 if (!(link->state & DEV_PRESENT)) {
606 DEBUG(0,"ray_init - device not present\n");
607 return -1;
608 }
609
610 local->net_type = net_type;
611 local->sta_type = TYPE_STA;
612
613 /* Copy the startup results to local memory */
614 memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE,\
615 sizeof(struct startup_res_6));
616
617 /* Check Power up test status and get mac address from card */
618 if (local->startup_res.startup_word != 0x80) {
619 printk(KERN_INFO "ray_init ERROR card status = %2x\n",
620 local->startup_res.startup_word);
621 local->card_status = CARD_INIT_ERROR;
622 return -1;
623 }
624
625 local->fw_ver = local->startup_res.firmware_version[0];
626 local->fw_bld = local->startup_res.firmware_version[1];
627 local->fw_var = local->startup_res.firmware_version[2];
628 DEBUG(1,"ray_init firmware version %d.%d \n",local->fw_ver, local->fw_bld);
629
630 local->tib_length = 0x20;
631 if ((local->fw_ver == 5) && (local->fw_bld >= 30))
632 local->tib_length = local->startup_res.tib_length;
633 DEBUG(2,"ray_init tib_length = 0x%02x\n", local->tib_length);
634 /* Initialize CCS's to buffer free state */
635 pccs = ccs_base(local);
636 for (i=0; i<NUMBER_OF_CCS; i++) {
637 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
638 }
639 init_startup_params(local);
640
641 /* copy mac address to startup parameters */
642 if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr))
643 {
644 p = local->sparm.b4.a_mac_addr;
645 }
646 else
647 {
648 memcpy(&local->sparm.b4.a_mac_addr,
649 &local->startup_res.station_addr, ADDRLEN);
650 p = local->sparm.b4.a_mac_addr;
651 }
652
653 clear_interrupt(local); /* Clear any interrupt from the card */
654 local->card_status = CARD_AWAITING_PARAM;
655 DEBUG(2,"ray_init ending\n");
656 return 0;
657} /* ray_init */
658/*===========================================================================*/
659/* Download startup parameters to the card and command it to read them */
660static int dl_startup_params(struct net_device *dev)
661{
662 int ccsindex;
663 ray_dev_t *local = (ray_dev_t *)dev->priv;
664 struct ccs __iomem *pccs;
665 dev_link_t *link = local->finder;
666
667 DEBUG(1,"dl_startup_params entered\n");
668 if (!(link->state & DEV_PRESENT)) {
669 DEBUG(2,"ray_cs dl_startup_params - device not present\n");
670 return -1;
671 }
672
673 /* Copy parameters to host to ECF area */
674 if (local->fw_ver == 0x55)
675 memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4,
676 sizeof(struct b4_startup_params));
677 else
678 memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5,
679 sizeof(struct b5_startup_params));
680
681
682 /* Fill in the CCS fields for the ECF */
683 if ((ccsindex = get_free_ccs(local)) < 0) return -1;
684 local->dl_param_ccs = ccsindex;
685 pccs = ccs_base(local) + ccsindex;
686 writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd);
687 DEBUG(2,"dl_startup_params start ccsindex = %d\n", local->dl_param_ccs);
688 /* Interrupt the firmware to process the command */
689 if (interrupt_ecf(local, ccsindex)) {
690 printk(KERN_INFO "ray dl_startup_params failed - "
691 "ECF not ready for intr\n");
692 local->card_status = CARD_DL_PARAM_ERROR;
693 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
694 return -2;
695 }
696 local->card_status = CARD_DL_PARAM;
697 /* Start kernel timer to wait for dl startup to complete. */
698 local->timer.expires = jiffies + HZ/2;
699 local->timer.data = (long)local;
700 local->timer.function = &verify_dl_startup;
701 add_timer(&local->timer);
702 DEBUG(2,"ray_cs dl_startup_params started timer for verify_dl_startup\n");
703 return 0;
704} /* dl_startup_params */
705/*===========================================================================*/
706static void init_startup_params(ray_dev_t *local)
707{
708 int i;
709
710 if (country > JAPAN_TEST) country = USA;
711 else
712 if (country < USA) country = USA;
713 /* structure for hop time and beacon period is defined here using
714 * New 802.11D6.1 format. Card firmware is still using old format
715 * until version 6.
716 * Before After
717 * a_hop_time ms byte a_hop_time ms byte
718 * a_hop_time 2s byte a_hop_time ls byte
719 * a_hop_time ls byte a_beacon_period ms byte
720 * a_beacon_period a_beacon_period ls byte
721 *
722 * a_hop_time = uS a_hop_time = KuS
723 * a_beacon_period = hops a_beacon_period = KuS
724 */ /* 64ms = 010000 */
725 if (local->fw_ver == 0x55) {
726 memcpy((UCHAR *)&local->sparm.b4, b4_default_startup_parms,
727 sizeof(struct b4_startup_params));
728 /* Translate sane kus input values to old build 4/5 format */
729 /* i = hop time in uS truncated to 3 bytes */
730 i = (hop_dwell * 1024) & 0xffffff;
731 local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff;
732 local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff;
733 local->sparm.b4.a_beacon_period[0] = 0;
734 local->sparm.b4.a_beacon_period[1] =
735 ((beacon_period/hop_dwell) - 1) & 0xff;
736 local->sparm.b4.a_curr_country_code = country;
737 local->sparm.b4.a_hop_pattern_length =
738 hop_pattern_length[(int)country] - 1;
739 if (bc)
740 {
741 local->sparm.b4.a_ack_timeout = 0x50;
742 local->sparm.b4.a_sifs = 0x3f;
743 }
744 }
745 else { /* Version 5 uses real kus values */
746 memcpy((UCHAR *)&local->sparm.b5, b5_default_startup_parms,
747 sizeof(struct b5_startup_params));
748
749 local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff;
750 local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff;
751 local->sparm.b5.a_beacon_period[0] = (beacon_period >> 8) & 0xff;
752 local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff;
753 if (psm)
754 local->sparm.b5.a_power_mgt_state = 1;
755 local->sparm.b5.a_curr_country_code = country;
756 local->sparm.b5.a_hop_pattern_length =
757 hop_pattern_length[(int)country];
758 }
759
760 local->sparm.b4.a_network_type = net_type & 0x01;
761 local->sparm.b4.a_acting_as_ap_status = TYPE_STA;
762
763 if (essid != NULL)
764 strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE);
765} /* init_startup_params */
766/*===========================================================================*/
767static void verify_dl_startup(u_long data)
768{
769 ray_dev_t *local = (ray_dev_t *)data;
770 struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs;
771 UCHAR status;
772 dev_link_t *link = local->finder;
773
774 if (!(link->state & DEV_PRESENT)) {
775 DEBUG(2,"ray_cs verify_dl_startup - device not present\n");
776 return;
777 }
778#ifdef PCMCIA_DEBUG
779 if (pc_debug > 2) {
780 int i;
781 printk(KERN_DEBUG "verify_dl_startup parameters sent via ccs %d:\n",
782 local->dl_param_ccs);
783 for (i=0; i<sizeof(struct b5_startup_params); i++) {
784 printk(" %2x", (unsigned int) readb(local->sram + HOST_TO_ECF_BASE + i));
785 }
786 printk("\n");
787 }
788#endif
789
790 status = readb(&pccs->buffer_status);
791 if (status!= CCS_BUFFER_FREE)
792 {
793 printk(KERN_INFO "Download startup params failed. Status = %d\n",
794 status);
795 local->card_status = CARD_DL_PARAM_ERROR;
796 return;
797 }
798 if (local->sparm.b4.a_network_type == ADHOC)
799 start_net((u_long)local);
800 else
801 join_net((u_long)local);
802
803 return;
804} /* end verify_dl_startup */
805/*===========================================================================*/
806/* Command card to start a network */
807static void start_net(u_long data)
808{
809 ray_dev_t *local = (ray_dev_t *)data;
810 struct ccs __iomem *pccs;
811 int ccsindex;
812 dev_link_t *link = local->finder;
813 if (!(link->state & DEV_PRESENT)) {
814 DEBUG(2,"ray_cs start_net - device not present\n");
815 return;
816 }
817 /* Fill in the CCS fields for the ECF */
818 if ((ccsindex = get_free_ccs(local)) < 0) return;
819 pccs = ccs_base(local) + ccsindex;
820 writeb(CCS_START_NETWORK, &pccs->cmd);
821 writeb(0, &pccs->var.start_network.update_param);
822 /* Interrupt the firmware to process the command */
823 if (interrupt_ecf(local, ccsindex)) {
824 DEBUG(1,"ray start net failed - card not ready for intr\n");
825 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
826 return;
827 }
828 local->card_status = CARD_DOING_ACQ;
829 return;
830} /* end start_net */
831/*===========================================================================*/
832/* Command card to join a network */
833static void join_net(u_long data)
834{
835 ray_dev_t *local = (ray_dev_t *)data;
836
837 struct ccs __iomem *pccs;
838 int ccsindex;
839 dev_link_t *link = local->finder;
840
841 if (!(link->state & DEV_PRESENT)) {
842 DEBUG(2,"ray_cs join_net - device not present\n");
843 return;
844 }
845 /* Fill in the CCS fields for the ECF */
846 if ((ccsindex = get_free_ccs(local)) < 0) return;
847 pccs = ccs_base(local) + ccsindex;
848 writeb(CCS_JOIN_NETWORK, &pccs->cmd);
849 writeb(0, &pccs->var.join_network.update_param);
850 writeb(0, &pccs->var.join_network.net_initiated);
851 /* Interrupt the firmware to process the command */
852 if (interrupt_ecf(local, ccsindex)) {
853 DEBUG(1,"ray join net failed - card not ready for intr\n");
854 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
855 return;
856 }
857 local->card_status = CARD_DOING_ACQ;
858 return;
859}
860/*============================================================================
861 After a card is removed, ray_release() will unregister the net
862 device, and release the PCMCIA configuration. If the device is
863 still open, this will be postponed until it is closed.
864=============================================================================*/
865static void ray_release(dev_link_t *link)
866{
867 struct net_device *dev = link->priv;
868 ray_dev_t *local = dev->priv;
869 int i;
870
871 DEBUG(1, "ray_release(0x%p)\n", link);
872
873 del_timer(&local->timer);
874 link->state &= ~DEV_CONFIG;
875
876 iounmap(local->sram);
877 iounmap(local->rmem);
878 iounmap(local->amem);
879 /* Do bother checking to see if these succeed or not */
880 i = pcmcia_release_window(link->win);
881 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(link->win) ret = %x\n",i);
882 i = pcmcia_release_window(local->amem_handle);
883 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->amem) ret = %x\n",i);
884 i = pcmcia_release_window(local->rmem_handle);
885 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseWindow(local->rmem) ret = %x\n",i);
886 i = pcmcia_release_configuration(link->handle);
887 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseConfiguration ret = %x\n",i);
888 i = pcmcia_release_irq(link->handle, &link->irq);
889 if ( i != CS_SUCCESS ) DEBUG(0,"ReleaseIRQ ret = %x\n",i);
890
891 DEBUG(2,"ray_release ending\n");
892}
893
894/*=============================================================================
895 The card status event handler. Mostly, this schedules other
896 stuff to run after an event is received. A CARD_REMOVAL event
897 also sets some flags to discourage the net drivers from trying
898 to talk to the card any more.
899
900 When a CARD_REMOVAL event is received, we immediately set a flag
901 to block future accesses to this device. All the functions that
902 actually access the device should check this flag to make sure
903 the card is still present.
904=============================================================================*/
905static int ray_event(event_t event, int priority,
906 event_callback_args_t *args)
907{
908 dev_link_t *link = args->client_data;
909 struct net_device *dev = link->priv;
910 ray_dev_t *local = (ray_dev_t *)dev->priv;
911 DEBUG(1, "ray_event(0x%06x)\n", event);
912
913 switch (event) {
914 case CS_EVENT_CARD_REMOVAL:
915 link->state &= ~DEV_PRESENT;
916 netif_device_detach(dev);
917 if (link->state & DEV_CONFIG) {
918 ray_release(link);
919 del_timer(&local->timer);
920 }
921 break;
922 case CS_EVENT_CARD_INSERTION:
923 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
924 ray_config(link);
925 break;
926 case CS_EVENT_PM_SUSPEND:
927 link->state |= DEV_SUSPEND;
928 /* Fall through... */
929 case CS_EVENT_RESET_PHYSICAL:
930 if (link->state & DEV_CONFIG) {
931 if (link->open)
932 netif_device_detach(dev);
933
934 pcmcia_release_configuration(link->handle);
935 }
936 break;
937 case CS_EVENT_PM_RESUME:
938 link->state &= ~DEV_SUSPEND;
939 /* Fall through... */
940 case CS_EVENT_CARD_RESET:
941 if (link->state & DEV_CONFIG) {
942 pcmcia_request_configuration(link->handle, &link->conf);
943 if (link->open) {
944 ray_reset(dev);
945 netif_device_attach(dev);
946 }
947 }
948 break;
949 }
950 return 0;
951 DEBUG(2,"ray_event ending\n");
952} /* ray_event */
953/*===========================================================================*/
954int ray_dev_init(struct net_device *dev)
955{
956#ifdef RAY_IMMEDIATE_INIT
957 int i;
958#endif /* RAY_IMMEDIATE_INIT */
959 ray_dev_t *local = dev->priv;
960 dev_link_t *link = local->finder;
961
962 DEBUG(1,"ray_dev_init(dev=%p)\n",dev);
963 if (!(link->state & DEV_PRESENT)) {
964 DEBUG(2,"ray_dev_init - device not present\n");
965 return -1;
966 }
967#ifdef RAY_IMMEDIATE_INIT
968 /* Download startup parameters */
969 if ( (i = dl_startup_params(dev)) < 0)
970 {
971 printk(KERN_INFO "ray_dev_init dl_startup_params failed - "
972 "returns 0x%x\n",i);
973 return -1;
974 }
975#else /* RAY_IMMEDIATE_INIT */
976 /* Postpone the card init so that we can still configure the card,
977 * for example using the Wireless Extensions. The init will happen
978 * in ray_open() - Jean II */
979 DEBUG(1,"ray_dev_init: postponing card init to ray_open() ; Status = %d\n",
980 local->card_status);
981#endif /* RAY_IMMEDIATE_INIT */
982
983 /* copy mac and broadcast addresses to linux device */
984 memcpy(&dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN);
985 memset(dev->broadcast, 0xff, ETH_ALEN);
986
987 DEBUG(2,"ray_dev_init ending\n");
988 return 0;
989}
990/*===========================================================================*/
991static int ray_dev_config(struct net_device *dev, struct ifmap *map)
992{
993 ray_dev_t *local = dev->priv;
994 dev_link_t *link = local->finder;
995 /* Dummy routine to satisfy device structure */
996 DEBUG(1,"ray_dev_config(dev=%p,ifmap=%p)\n",dev,map);
997 if (!(link->state & DEV_PRESENT)) {
998 DEBUG(2,"ray_dev_config - device not present\n");
999 return -1;
1000 }
1001
1002 return 0;
1003}
1004/*===========================================================================*/
1005static int ray_dev_start_xmit(struct sk_buff *skb, struct net_device *dev)
1006{
1007 ray_dev_t *local = dev->priv;
1008 dev_link_t *link = local->finder;
1009 short length = skb->len;
1010
1011 if (!(link->state & DEV_PRESENT)) {
1012 DEBUG(2,"ray_dev_start_xmit - device not present\n");
1013 return -1;
1014 }
1015 DEBUG(3,"ray_dev_start_xmit(skb=%p, dev=%p)\n",skb,dev);
1016 if (local->authentication_state == NEED_TO_AUTH) {
1017 DEBUG(0,"ray_cs Sending authentication request.\n");
1018 if (!build_auth_frame (local, local->auth_id, OPEN_AUTH_REQUEST)) {
1019 local->authentication_state = AUTHENTICATED;
1020 netif_stop_queue(dev);
1021 return 1;
1022 }
1023 }
1024
1025 if (length < ETH_ZLEN)
1026 {
1027 skb = skb_padto(skb, ETH_ZLEN);
1028 if (skb == NULL)
1029 return 0;
1030 length = ETH_ZLEN;
1031 }
1032 switch (ray_hw_xmit( skb->data, length, dev, DATA_TYPE)) {
1033 case XMIT_NO_CCS:
1034 case XMIT_NEED_AUTH:
1035 netif_stop_queue(dev);
1036 return 1;
1037 case XMIT_NO_INTR:
1038 case XMIT_MSG_BAD:
1039 case XMIT_OK:
1040 default:
1041 dev->trans_start = jiffies;
1042 dev_kfree_skb(skb);
1043 return 0;
1044 }
1045 return 0;
1046} /* ray_dev_start_xmit */
1047/*===========================================================================*/
1048static int ray_hw_xmit(unsigned char* data, int len, struct net_device* dev,
1049 UCHAR msg_type)
1050{
1051 ray_dev_t *local = (ray_dev_t *)dev->priv;
1052 struct ccs __iomem *pccs;
1053 int ccsindex;
1054 int offset;
1055 struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */
1056 short int addr; /* Address of xmit buffer in card space */
1057
1058 DEBUG(3,"ray_hw_xmit(data=%p, len=%d, dev=%p)\n",data,len,dev);
1059 if (len + TX_HEADER_LENGTH > TX_BUF_SIZE)
1060 {
1061 printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n",len);
1062 return XMIT_MSG_BAD;
1063 }
1064 switch (ccsindex = get_free_tx_ccs(local)) {
1065 case ECCSBUSY:
1066 DEBUG(2,"ray_hw_xmit tx_ccs table busy\n");
1067 case ECCSFULL:
1068 DEBUG(2,"ray_hw_xmit No free tx ccs\n");
1069 case ECARDGONE:
1070 netif_stop_queue(dev);
1071 return XMIT_NO_CCS;
1072 default:
1073 break;
1074 }
1075 addr = TX_BUF_BASE + (ccsindex << 11);
1076
1077 if (msg_type == DATA_TYPE) {
1078 local->stats.tx_bytes += len;
1079 local->stats.tx_packets++;
1080 }
1081
1082 ptx = local->sram + addr;
1083
1084 ray_build_header(local, ptx, msg_type, data);
1085 if (translate) {
1086 offset = translate_frame(local, ptx, data, len);
1087 }
1088 else { /* Encapsulate frame */
1089 /* TBD TIB length will move address of ptx->var */
1090 memcpy_toio(&ptx->var, data, len);
1091 offset = 0;
1092 }
1093
1094 /* fill in the CCS */
1095 pccs = ccs_base(local) + ccsindex;
1096 len += TX_HEADER_LENGTH + offset;
1097 writeb(CCS_TX_REQUEST, &pccs->cmd);
1098 writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]);
1099 writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]);
1100 writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]);
1101 writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]);
1102/* TBD still need psm_cam? */
1103 writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode);
1104 writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate);
1105 writeb(0, &pccs->var.tx_request.antenna);
1106 DEBUG(3,"ray_hw_xmit default_tx_rate = 0x%x\n",\
1107 local->net_default_tx_rate);
1108
1109 /* Interrupt the firmware to process the command */
1110 if (interrupt_ecf(local, ccsindex)) {
1111 DEBUG(2,"ray_hw_xmit failed - ECF not ready for intr\n");
1112/* TBD very inefficient to copy packet to buffer, and then not
1113 send it, but the alternative is to queue the messages and that
1114 won't be done for a while. Maybe set tbusy until a CCS is free?
1115*/
1116 writeb(CCS_BUFFER_FREE, &pccs->buffer_status);
1117 return XMIT_NO_INTR;
1118 }
1119 return XMIT_OK;
1120} /* end ray_hw_xmit */
1121/*===========================================================================*/
1122static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, unsigned char *data,
1123 int len)
1124{
1125 unsigned short int proto = ((struct ethhdr *)data)->h_proto;
1126 if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */
1127 DEBUG(3,"ray_cs translate_frame DIX II\n");
1128 /* Copy LLC header to card buffer */
1129 memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc));
1130 memcpy_toio( ((void __iomem *)&ptx->var) + sizeof(eth2_llc), (UCHAR *)&proto, 2);
1131 if ((proto == 0xf380) || (proto == 0x3781)) {
1132 /* This is the selective translation table, only 2 entries */
1133 writeb(0xf8, &((struct snaphdr_t __iomem *)ptx->var)->org[3]);
1134 }
1135 /* Copy body of ethernet packet without ethernet header */
1136 memcpy_toio((void __iomem *)&ptx->var + sizeof(struct snaphdr_t), \
1137 data + ETH_HLEN, len - ETH_HLEN);
1138 return (int) sizeof(struct snaphdr_t) - ETH_HLEN;
1139 }
1140 else { /* already 802 type, and proto is length */
1141 DEBUG(3,"ray_cs translate_frame 802\n");
1142 if (proto == 0xffff) { /* evil netware IPX 802.3 without LLC */
1143 DEBUG(3,"ray_cs translate_frame evil IPX\n");
1144 memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN);
1145 return 0 - ETH_HLEN;
1146 }
1147 memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN);
1148 return 0 - ETH_HLEN;
1149 }
1150 /* TBD do other frame types */
1151} /* end translate_frame */
1152/*===========================================================================*/
1153static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, UCHAR msg_type,
1154 unsigned char *data)
1155{
1156 writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1);
1157/*** IEEE 802.11 Address field assignments *************
1158 TODS FROMDS addr_1 addr_2 addr_3 addr_4
1159Adhoc 0 0 dest src (terminal) BSSID N/A
1160AP to Terminal 0 1 dest AP(BSSID) source N/A
1161Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A
1162AP to AP 1 1 dest AP src AP dest source
1163*******************************************************/
1164 if (local->net_type == ADHOC) {
1165 writeb(0, &ptx->mac.frame_ctl_2);
1166 memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, 2 * ADDRLEN);
1167 memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN);
1168 }
1169 else /* infrastructure */
1170 {
1171 if (local->sparm.b4.a_acting_as_ap_status)
1172 {
1173 writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2);
1174 memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, ADDRLEN);
1175 memcpy_toio(ptx->mac.addr_2, local->bss_id, 6);
1176 memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_source, ADDRLEN);
1177 }
1178 else /* Terminal */
1179 {
1180 writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2);
1181 memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN);
1182 memcpy_toio(ptx->mac.addr_2, ((struct ethhdr *)data)->h_source, ADDRLEN);
1183 memcpy_toio(ptx->mac.addr_3, ((struct ethhdr *)data)->h_dest, ADDRLEN);
1184 }
1185 }
1186} /* end encapsulate_frame */
1187
1188
1189/*===========================================================================*/
1190
1191static void netdev_get_drvinfo(struct net_device *dev,
1192 struct ethtool_drvinfo *info)
1193{
1194 strcpy(info->driver, "ray_cs");
1195}
1196
1197static struct ethtool_ops netdev_ethtool_ops = {
1198 .get_drvinfo = netdev_get_drvinfo,
1199};
1200
1201/*====================================================================*/
1202
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001203/*------------------------------------------------------------------*/
1204/*
1205 * Wireless Handler : get protocol name
1206 */
1207static int ray_get_name(struct net_device *dev,
1208 struct iw_request_info *info,
1209 char *cwrq,
1210 char *extra)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211{
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001212 strcpy(cwrq, "IEEE 802.11-FH");
1213 return 0;
1214}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001216/*------------------------------------------------------------------*/
1217/*
1218 * Wireless Handler : set frequency
1219 */
1220static int ray_set_freq(struct net_device *dev,
1221 struct iw_request_info *info,
1222 struct iw_freq *fwrq,
1223 char *extra)
1224{
1225 ray_dev_t *local = (ray_dev_t *)dev->priv;
1226 int err = -EINPROGRESS; /* Call commit handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001228 /* Reject if card is already initialised */
1229 if(local->card_status != CARD_AWAITING_PARAM)
1230 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001231
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001232 /* Setting by channel number */
1233 if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001234 err = -EOPNOTSUPP;
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001235 else
1236 local->sparm.b5.a_hop_pattern = fwrq->m;
1237
1238 return err;
1239}
1240
1241/*------------------------------------------------------------------*/
1242/*
1243 * Wireless Handler : get frequency
1244 */
1245static int ray_get_freq(struct net_device *dev,
1246 struct iw_request_info *info,
1247 struct iw_freq *fwrq,
1248 char *extra)
1249{
1250 ray_dev_t *local = (ray_dev_t *)dev->priv;
1251
1252 fwrq->m = local->sparm.b5.a_hop_pattern;
1253 fwrq->e = 0;
1254 return 0;
1255}
1256
1257/*------------------------------------------------------------------*/
1258/*
1259 * Wireless Handler : set ESSID
1260 */
1261static int ray_set_essid(struct net_device *dev,
1262 struct iw_request_info *info,
1263 struct iw_point *dwrq,
1264 char *extra)
1265{
1266 ray_dev_t *local = (ray_dev_t *)dev->priv;
1267
1268 /* Reject if card is already initialised */
1269 if(local->card_status != CARD_AWAITING_PARAM)
1270 return -EBUSY;
1271
1272 /* Check if we asked for `any' */
1273 if(dwrq->flags == 0) {
1274 /* Corey : can you do that ? */
1275 return -EOPNOTSUPP;
1276 } else {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277 /* Check the size of the string */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001278 if(dwrq->length > IW_ESSID_MAX_SIZE + 1) {
1279 return -E2BIG;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001280 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001281
1282 /* Set the ESSID in the card */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001283 memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE);
1284 memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001287 return -EINPROGRESS; /* Call commit handler */
1288}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001290/*------------------------------------------------------------------*/
1291/*
1292 * Wireless Handler : get ESSID
1293 */
1294static int ray_get_essid(struct net_device *dev,
1295 struct iw_request_info *info,
1296 struct iw_point *dwrq,
1297 char *extra)
1298{
1299 ray_dev_t *local = (ray_dev_t *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001301 /* Get the essid that was set */
1302 memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE);
1303 extra[IW_ESSID_MAX_SIZE] = '\0';
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001305 /* Push it out ! */
1306 dwrq->length = strlen(extra) + 1;
1307 dwrq->flags = 1; /* active */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001308
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001309 return 0;
1310}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001311
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001312/*------------------------------------------------------------------*/
1313/*
1314 * Wireless Handler : get AP address
1315 */
1316static int ray_get_wap(struct net_device *dev,
1317 struct iw_request_info *info,
1318 struct sockaddr *awrq,
1319 char *extra)
1320{
1321 ray_dev_t *local = (ray_dev_t *)dev->priv;
1322
1323 memcpy(awrq->sa_data, local->bss_id, ETH_ALEN);
1324 awrq->sa_family = ARPHRD_ETHER;
1325
1326 return 0;
1327}
1328
1329/*------------------------------------------------------------------*/
1330/*
1331 * Wireless Handler : set Bit-Rate
1332 */
1333static int ray_set_rate(struct net_device *dev,
1334 struct iw_request_info *info,
1335 struct iw_param *vwrq,
1336 char *extra)
1337{
1338 ray_dev_t *local = (ray_dev_t *)dev->priv;
1339
1340 /* Reject if card is already initialised */
1341 if(local->card_status != CARD_AWAITING_PARAM)
1342 return -EBUSY;
1343
1344 /* Check if rate is in range */
1345 if((vwrq->value != 1000000) && (vwrq->value != 2000000))
1346 return -EINVAL;
1347
1348 /* Hack for 1.5 Mb/s instead of 2 Mb/s */
1349 if((local->fw_ver == 0x55) && /* Please check */
1350 (vwrq->value == 2000000))
1351 local->net_default_tx_rate = 3;
1352 else
1353 local->net_default_tx_rate = vwrq->value/500000;
1354
1355 return 0;
1356}
1357
1358/*------------------------------------------------------------------*/
1359/*
1360 * Wireless Handler : get Bit-Rate
1361 */
1362static int ray_get_rate(struct net_device *dev,
1363 struct iw_request_info *info,
1364 struct iw_param *vwrq,
1365 char *extra)
1366{
1367 ray_dev_t *local = (ray_dev_t *)dev->priv;
1368
1369 if(local->net_default_tx_rate == 3)
1370 vwrq->value = 2000000; /* Hum... */
1371 else
1372 vwrq->value = local->net_default_tx_rate * 500000;
1373 vwrq->fixed = 0; /* We are in auto mode */
1374
1375 return 0;
1376}
1377
1378/*------------------------------------------------------------------*/
1379/*
1380 * Wireless Handler : set RTS threshold
1381 */
1382static int ray_set_rts(struct net_device *dev,
1383 struct iw_request_info *info,
1384 struct iw_param *vwrq,
1385 char *extra)
1386{
1387 ray_dev_t *local = (ray_dev_t *)dev->priv;
1388 int rthr = vwrq->value;
1389
1390 /* Reject if card is already initialised */
1391 if(local->card_status != CARD_AWAITING_PARAM)
1392 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001393
1394 /* if(wrq->u.rts.fixed == 0) we should complain */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001395 if(vwrq->disabled)
1396 rthr = 32767;
1397 else {
1398 if((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */
1399 return -EINVAL;
1400 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401 local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF;
1402 local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001404 return -EINPROGRESS; /* Call commit handler */
1405}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001406
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001408/*------------------------------------------------------------------*/
1409/*
1410 * Wireless Handler : get RTS threshold
1411 */
1412static int ray_get_rts(struct net_device *dev,
1413 struct iw_request_info *info,
1414 struct iw_param *vwrq,
1415 char *extra)
1416{
1417 ray_dev_t *local = (ray_dev_t *)dev->priv;
1418
1419 vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8)
1420 + local->sparm.b5.a_rts_threshold[1];
1421 vwrq->disabled = (vwrq->value == 32767);
1422 vwrq->fixed = 1;
1423
1424 return 0;
1425}
1426
1427/*------------------------------------------------------------------*/
1428/*
1429 * Wireless Handler : set Fragmentation threshold
1430 */
1431static int ray_set_frag(struct net_device *dev,
1432 struct iw_request_info *info,
1433 struct iw_param *vwrq,
1434 char *extra)
1435{
1436 ray_dev_t *local = (ray_dev_t *)dev->priv;
1437 int fthr = vwrq->value;
1438
1439 /* Reject if card is already initialised */
1440 if(local->card_status != CARD_AWAITING_PARAM)
1441 return -EBUSY;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001442
1443 /* if(wrq->u.frag.fixed == 0) should complain */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001444 if(vwrq->disabled)
1445 fthr = 32767;
1446 else {
1447 if((fthr < 256) || (fthr > 2347)) /* To check out ! */
1448 return -EINVAL;
1449 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450 local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF;
1451 local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001453 return -EINPROGRESS; /* Call commit handler */
1454}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001455
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001456/*------------------------------------------------------------------*/
1457/*
1458 * Wireless Handler : get Fragmentation threshold
1459 */
1460static int ray_get_frag(struct net_device *dev,
1461 struct iw_request_info *info,
1462 struct iw_param *vwrq,
1463 char *extra)
1464{
1465 ray_dev_t *local = (ray_dev_t *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001467 vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8)
1468 + local->sparm.b5.a_frag_threshold[1];
1469 vwrq->disabled = (vwrq->value == 32767);
1470 vwrq->fixed = 1;
1471
1472 return 0;
1473}
1474
1475/*------------------------------------------------------------------*/
1476/*
1477 * Wireless Handler : set Mode of Operation
1478 */
1479static int ray_set_mode(struct net_device *dev,
1480 struct iw_request_info *info,
1481 __u32 *uwrq,
1482 char *extra)
1483{
1484 ray_dev_t *local = (ray_dev_t *)dev->priv;
1485 int err = -EINPROGRESS; /* Call commit handler */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486 char card_mode = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001488 /* Reject if card is already initialised */
1489 if(local->card_status != CARD_AWAITING_PARAM)
1490 return -EBUSY;
1491
1492 switch (*uwrq)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493 {
1494 case IW_MODE_ADHOC:
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001495 card_mode = 0;
1496 // Fall through
Linus Torvalds1da177e2005-04-16 15:20:36 -07001497 case IW_MODE_INFRA:
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001498 local->sparm.b5.a_network_type = card_mode;
1499 break;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 default:
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001501 err = -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001503
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001504 return err;
1505}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001506
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001507/*------------------------------------------------------------------*/
1508/*
1509 * Wireless Handler : get Mode of Operation
1510 */
1511static int ray_get_mode(struct net_device *dev,
1512 struct iw_request_info *info,
1513 __u32 *uwrq,
1514 char *extra)
1515{
1516 ray_dev_t *local = (ray_dev_t *)dev->priv;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001518 if(local->sparm.b5.a_network_type)
1519 *uwrq = IW_MODE_INFRA;
1520 else
1521 *uwrq = IW_MODE_ADHOC;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001522
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001523 return 0;
1524}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001526/*------------------------------------------------------------------*/
1527/*
1528 * Wireless Handler : get range info
1529 */
1530static int ray_get_range(struct net_device *dev,
1531 struct iw_request_info *info,
1532 struct iw_point *dwrq,
1533 char *extra)
1534{
1535 struct iw_range *range = (struct iw_range *) extra;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001536
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001537 memset((char *) range, 0, sizeof(struct iw_range));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001538
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001539 /* Set the length (very important for backward compatibility) */
1540 dwrq->length = sizeof(struct iw_range);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001541
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001542 /* Set the Wireless Extension versions */
1543 range->we_version_compiled = WIRELESS_EXT;
1544 range->we_version_source = 9;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001545
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001546 /* Set information in the range struct */
1547 range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */
1548 range->num_channels = hop_pattern_length[(int)country];
1549 range->num_frequency = 0;
1550 range->max_qual.qual = 0;
1551 range->max_qual.level = 255; /* What's the correct value ? */
1552 range->max_qual.noise = 255; /* Idem */
1553 range->num_bitrates = 2;
1554 range->bitrate[0] = 1000000; /* 1 Mb/s */
1555 range->bitrate[1] = 2000000; /* 2 Mb/s */
1556 return 0;
1557}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001559/*------------------------------------------------------------------*/
1560/*
1561 * Wireless Private Handler : set framing mode
1562 */
1563static int ray_set_framing(struct net_device *dev,
1564 struct iw_request_info *info,
1565 union iwreq_data *wrqu,
1566 char *extra)
1567{
1568 translate = *(extra); /* Set framing mode */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001570 return 0;
1571}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001572
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001573/*------------------------------------------------------------------*/
1574/*
1575 * Wireless Private Handler : get framing mode
1576 */
1577static int ray_get_framing(struct net_device *dev,
1578 struct iw_request_info *info,
1579 union iwreq_data *wrqu,
1580 char *extra)
1581{
1582 *(extra) = translate;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001583
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001584 return 0;
1585}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001587/*------------------------------------------------------------------*/
1588/*
1589 * Wireless Private Handler : get country
1590 */
1591static int ray_get_country(struct net_device *dev,
1592 struct iw_request_info *info,
1593 union iwreq_data *wrqu,
1594 char *extra)
1595{
1596 *(extra) = country;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001597
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001598 return 0;
1599}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001600
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001601/*------------------------------------------------------------------*/
1602/*
1603 * Commit handler : called after a bunch of SET operations
1604 */
1605static int ray_commit(struct net_device *dev,
1606 struct iw_request_info *info, /* NULL */
1607 void *zwrq, /* NULL */
1608 char *extra) /* NULL */
1609{
1610 return 0;
1611}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001612
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001613/*------------------------------------------------------------------*/
1614/*
1615 * Stats handler : return Wireless Stats
1616 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001617static iw_stats * ray_get_wireless_stats(struct net_device * dev)
1618{
1619 ray_dev_t * local = (ray_dev_t *) dev->priv;
1620 dev_link_t *link = local->finder;
1621 struct status __iomem *p = local->sram + STATUS_BASE;
1622
1623 if(local == (ray_dev_t *) NULL)
1624 return (iw_stats *) NULL;
1625
1626 local->wstats.status = local->card_status;
1627#ifdef WIRELESS_SPY
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001628 if((local->spy_data.spy_number > 0) && (local->sparm.b5.a_network_type == 0))
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629 {
1630 /* Get it from the first node in spy list */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001631 local->wstats.qual.qual = local->spy_data.spy_stat[0].qual;
1632 local->wstats.qual.level = local->spy_data.spy_stat[0].level;
1633 local->wstats.qual.noise = local->spy_data.spy_stat[0].noise;
1634 local->wstats.qual.updated = local->spy_data.spy_stat[0].updated;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001635 }
1636#endif /* WIRELESS_SPY */
1637
1638 if((link->state & DEV_PRESENT)) {
1639 local->wstats.qual.noise = readb(&p->rxnoise);
1640 local->wstats.qual.updated |= 4;
1641 }
1642
1643 return &local->wstats;
1644} /* end ray_get_wireless_stats */
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001645
1646/*------------------------------------------------------------------*/
1647/*
1648 * Structures to export the Wireless Handlers
1649 */
1650
1651static const iw_handler ray_handler[] = {
viro@ZenIV.linux.org.uk7a700fa2005-09-09 20:40:23 +01001652 [SIOCSIWCOMMIT-SIOCIWFIRST] = (iw_handler) ray_commit,
1653 [SIOCGIWNAME -SIOCIWFIRST] = (iw_handler) ray_get_name,
1654 [SIOCSIWFREQ -SIOCIWFIRST] = (iw_handler) ray_set_freq,
1655 [SIOCGIWFREQ -SIOCIWFIRST] = (iw_handler) ray_get_freq,
1656 [SIOCSIWMODE -SIOCIWFIRST] = (iw_handler) ray_set_mode,
1657 [SIOCGIWMODE -SIOCIWFIRST] = (iw_handler) ray_get_mode,
1658 [SIOCGIWRANGE -SIOCIWFIRST] = (iw_handler) ray_get_range,
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001659#ifdef WIRELESS_SPY
viro@ZenIV.linux.org.uk7a700fa2005-09-09 20:40:23 +01001660 [SIOCSIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_set_spy,
1661 [SIOCGIWSPY -SIOCIWFIRST] = (iw_handler) iw_handler_get_spy,
1662 [SIOCSIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy,
1663 [SIOCGIWTHRSPY-SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy,
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001664#endif /* WIRELESS_SPY */
viro@ZenIV.linux.org.uk7a700fa2005-09-09 20:40:23 +01001665 [SIOCGIWAP -SIOCIWFIRST] = (iw_handler) ray_get_wap,
1666 [SIOCSIWESSID -SIOCIWFIRST] = (iw_handler) ray_set_essid,
1667 [SIOCGIWESSID -SIOCIWFIRST] = (iw_handler) ray_get_essid,
1668 [SIOCSIWRATE -SIOCIWFIRST] = (iw_handler) ray_set_rate,
1669 [SIOCGIWRATE -SIOCIWFIRST] = (iw_handler) ray_get_rate,
1670 [SIOCSIWRTS -SIOCIWFIRST] = (iw_handler) ray_set_rts,
1671 [SIOCGIWRTS -SIOCIWFIRST] = (iw_handler) ray_get_rts,
1672 [SIOCSIWFRAG -SIOCIWFIRST] = (iw_handler) ray_set_frag,
1673 [SIOCGIWFRAG -SIOCIWFIRST] = (iw_handler) ray_get_frag,
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001674};
1675
1676#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */
1677#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */
1678#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */
1679
1680static const iw_handler ray_private_handler[] = {
viro@ZenIV.linux.org.uk7a700fa2005-09-09 20:40:23 +01001681 [0] = (iw_handler) ray_set_framing,
1682 [1] = (iw_handler) ray_get_framing,
1683 [3] = (iw_handler) ray_get_country,
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07001684};
1685
1686static const struct iw_priv_args ray_private_args[] = {
1687/* cmd, set_args, get_args, name */
1688{ SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "set_framing" },
1689{ SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_framing" },
1690{ SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "get_country" },
1691};
1692
1693static const struct iw_handler_def ray_handler_def =
1694{
1695 .num_standard = sizeof(ray_handler)/sizeof(iw_handler),
1696 .num_private = sizeof(ray_private_handler)/sizeof(iw_handler),
1697 .num_private_args = sizeof(ray_private_args)/sizeof(struct iw_priv_args),
1698 .standard = ray_handler,
1699 .private = ray_private_handler,
1700 .private_args = ray_private_args,
1701 .get_wireless_stats = ray_get_wireless_stats,
1702};
1703
Linus Torvalds1da177e2005-04-16 15:20:36 -07001704/*===========================================================================*/
1705static int ray_open(struct net_device *dev)
1706{
1707 dev_link_t *link;
1708 ray_dev_t *local = (ray_dev_t *)dev->priv;
1709
1710 DEBUG(1, "ray_open('%s')\n", dev->name);
1711
1712 for (link = dev_list; link; link = link->next)
1713 if (link->priv == dev) break;
1714 if (!DEV_OK(link)) {
1715 return -ENODEV;
1716 }
1717
1718 if (link->open == 0) local->num_multi = 0;
1719 link->open++;
1720
1721 /* If the card is not started, time to start it ! - Jean II */
1722 if(local->card_status == CARD_AWAITING_PARAM) {
1723 int i;
1724
1725 DEBUG(1,"ray_open: doing init now !\n");
1726
1727 /* Download startup parameters */
1728 if ( (i = dl_startup_params(dev)) < 0)
1729 {
1730 printk(KERN_INFO "ray_dev_init dl_startup_params failed - "
1731 "returns 0x%x\n",i);
1732 return -1;
1733 }
1734 }
1735
1736 if (sniffer) netif_stop_queue(dev);
1737 else netif_start_queue(dev);
1738
1739 DEBUG(2,"ray_open ending\n");
1740 return 0;
1741} /* end ray_open */
1742/*===========================================================================*/
1743static int ray_dev_close(struct net_device *dev)
1744{
1745 dev_link_t *link;
1746
1747 DEBUG(1, "ray_dev_close('%s')\n", dev->name);
1748
1749 for (link = dev_list; link; link = link->next)
1750 if (link->priv == dev) break;
1751 if (link == NULL)
1752 return -ENODEV;
1753
1754 link->open--;
1755 netif_stop_queue(dev);
1756
1757 /* In here, we should stop the hardware (stop card from beeing active)
1758 * and set local->card_status to CARD_AWAITING_PARAM, so that while the
1759 * card is closed we can chage its configuration.
1760 * Probably also need a COR reset to get sane state - Jean II */
1761
1762 return 0;
1763} /* end ray_dev_close */
1764/*===========================================================================*/
1765static void ray_reset(struct net_device *dev) {
1766 DEBUG(1,"ray_reset entered\n");
1767 return;
1768}
1769/*===========================================================================*/
1770/* Cause a firmware interrupt if it is ready for one */
1771/* Return nonzero if not ready */
1772static int interrupt_ecf(ray_dev_t *local, int ccs)
1773{
1774 int i = 50;
1775 dev_link_t *link = local->finder;
1776
1777 if (!(link->state & DEV_PRESENT)) {
1778 DEBUG(2,"ray_cs interrupt_ecf - device not present\n");
1779 return -1;
1780 }
1781 DEBUG(2,"interrupt_ecf(local=%p, ccs = 0x%x\n",local,ccs);
1782
1783 while ( i &&
1784 (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & ECF_INTR_SET))
1785 i--;
1786 if (i == 0) {
1787 DEBUG(2,"ray_cs interrupt_ecf card not ready for interrupt\n");
1788 return -1;
1789 }
1790 /* Fill the mailbox, then kick the card */
1791 writeb(ccs, local->sram + SCB_BASE);
1792 writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET);
1793 return 0;
1794} /* interrupt_ecf */
1795/*===========================================================================*/
1796/* Get next free transmit CCS */
1797/* Return - index of current tx ccs */
1798static int get_free_tx_ccs(ray_dev_t *local)
1799{
1800 int i;
1801 struct ccs __iomem *pccs = ccs_base(local);
1802 dev_link_t *link = local->finder;
1803
1804 if (!(link->state & DEV_PRESENT)) {
1805 DEBUG(2,"ray_cs get_free_tx_ccs - device not present\n");
1806 return ECARDGONE;
1807 }
1808
1809 if (test_and_set_bit(0,&local->tx_ccs_lock)) {
1810 DEBUG(1,"ray_cs tx_ccs_lock busy\n");
1811 return ECCSBUSY;
1812 }
1813
1814 for (i=0; i < NUMBER_OF_TX_CCS; i++) {
1815 if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) {
1816 writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status);
1817 writeb(CCS_END_LIST, &(pccs+i)->link);
1818 local->tx_ccs_lock = 0;
1819 return i;
1820 }
1821 }
1822 local->tx_ccs_lock = 0;
1823 DEBUG(2,"ray_cs ERROR no free tx CCS for raylink card\n");
1824 return ECCSFULL;
1825} /* get_free_tx_ccs */
1826/*===========================================================================*/
1827/* Get next free CCS */
1828/* Return - index of current ccs */
1829static int get_free_ccs(ray_dev_t *local)
1830{
1831 int i;
1832 struct ccs __iomem *pccs = ccs_base(local);
1833 dev_link_t *link = local->finder;
1834
1835 if (!(link->state & DEV_PRESENT)) {
1836 DEBUG(2,"ray_cs get_free_ccs - device not present\n");
1837 return ECARDGONE;
1838 }
1839 if (test_and_set_bit(0,&local->ccs_lock)) {
1840 DEBUG(1,"ray_cs ccs_lock busy\n");
1841 return ECCSBUSY;
1842 }
1843
1844 for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) {
1845 if (readb(&(pccs+i)->buffer_status) == CCS_BUFFER_FREE) {
1846 writeb(CCS_BUFFER_BUSY, &(pccs+i)->buffer_status);
1847 writeb(CCS_END_LIST, &(pccs+i)->link);
1848 local->ccs_lock = 0;
1849 return i;
1850 }
1851 }
1852 local->ccs_lock = 0;
1853 DEBUG(1,"ray_cs ERROR no free CCS for raylink card\n");
1854 return ECCSFULL;
1855} /* get_free_ccs */
1856/*===========================================================================*/
1857static void authenticate_timeout(u_long data)
1858{
1859 ray_dev_t *local = (ray_dev_t *)data;
1860 del_timer(&local->timer);
1861 printk(KERN_INFO "ray_cs Authentication with access point failed"
1862 " - timeout\n");
1863 join_net((u_long)local);
1864}
1865/*===========================================================================*/
1866static int asc_to_int(char a)
1867{
1868 if (a < '0') return -1;
1869 if (a <= '9') return (a - '0');
1870 if (a < 'A') return -1;
1871 if (a <= 'F') return (10 + a - 'A');
1872 if (a < 'a') return -1;
1873 if (a <= 'f') return (10 + a - 'a');
1874 return -1;
1875}
1876/*===========================================================================*/
1877static int parse_addr(char *in_str, UCHAR *out)
1878{
1879 int len;
1880 int i,j,k;
1881 int status;
1882
1883 if (in_str == NULL) return 0;
1884 if ((len = strlen(in_str)) < 2) return 0;
1885 memset(out, 0, ADDRLEN);
1886
1887 status = 1;
1888 j = len - 1;
1889 if (j > 12) j = 12;
1890 i = 5;
1891
1892 while (j > 0)
1893 {
1894 if ((k = asc_to_int(in_str[j--])) != -1) out[i] = k;
1895 else return 0;
1896
1897 if (j == 0) break;
1898 if ((k = asc_to_int(in_str[j--])) != -1) out[i] += k << 4;
1899 else return 0;
1900 if (!i--) break;
1901 }
1902 return status;
1903}
1904/*===========================================================================*/
1905static struct net_device_stats *ray_get_stats(struct net_device *dev)
1906{
1907 ray_dev_t *local = (ray_dev_t *)dev->priv;
1908 dev_link_t *link = local->finder;
1909 struct status __iomem *p = local->sram + STATUS_BASE;
1910 if (!(link->state & DEV_PRESENT)) {
1911 DEBUG(2,"ray_cs net_device_stats - device not present\n");
1912 return &local->stats;
1913 }
1914 if (readb(&p->mrx_overflow_for_host))
1915 {
1916 local->stats.rx_over_errors += ntohs(readb(&p->mrx_overflow));
1917 writeb(0,&p->mrx_overflow);
1918 writeb(0,&p->mrx_overflow_for_host);
1919 }
1920 if (readb(&p->mrx_checksum_error_for_host))
1921 {
1922 local->stats.rx_crc_errors += ntohs(readb(&p->mrx_checksum_error));
1923 writeb(0,&p->mrx_checksum_error);
1924 writeb(0,&p->mrx_checksum_error_for_host);
1925 }
1926 if (readb(&p->rx_hec_error_for_host))
1927 {
1928 local->stats.rx_frame_errors += ntohs(readb(&p->rx_hec_error));
1929 writeb(0,&p->rx_hec_error);
1930 writeb(0,&p->rx_hec_error_for_host);
1931 }
1932 return &local->stats;
1933}
1934/*===========================================================================*/
1935static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len)
1936{
1937 ray_dev_t *local = (ray_dev_t *)dev->priv;
1938 dev_link_t *link = local->finder;
1939 int ccsindex;
1940 int i;
1941 struct ccs __iomem *pccs;
1942
1943 if (!(link->state & DEV_PRESENT)) {
1944 DEBUG(2,"ray_update_parm - device not present\n");
1945 return;
1946 }
1947
1948 if ((ccsindex = get_free_ccs(local)) < 0)
1949 {
1950 DEBUG(0,"ray_update_parm - No free ccs\n");
1951 return;
1952 }
1953 pccs = ccs_base(local) + ccsindex;
1954 writeb(CCS_UPDATE_PARAMS, &pccs->cmd);
1955 writeb(objid, &pccs->var.update_param.object_id);
1956 writeb(1, &pccs->var.update_param.number_objects);
1957 writeb(0, &pccs->var.update_param.failure_cause);
1958 for (i=0; i<len; i++) {
1959 writeb(value[i], local->sram + HOST_TO_ECF_BASE);
1960 }
1961 /* Interrupt the firmware to process the command */
1962 if (interrupt_ecf(local, ccsindex)) {
1963 DEBUG(0,"ray_cs associate failed - ECF not ready for intr\n");
1964 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
1965 }
1966}
1967/*===========================================================================*/
1968static void ray_update_multi_list(struct net_device *dev, int all)
1969{
1970 struct dev_mc_list *dmi, **dmip;
1971 int ccsindex;
1972 struct ccs __iomem *pccs;
1973 int i = 0;
1974 ray_dev_t *local = (ray_dev_t *)dev->priv;
1975 dev_link_t *link = local->finder;
1976 void __iomem *p = local->sram + HOST_TO_ECF_BASE;
1977
1978 if (!(link->state & DEV_PRESENT)) {
1979 DEBUG(2,"ray_update_multi_list - device not present\n");
1980 return;
1981 }
1982 else
1983 DEBUG(2,"ray_update_multi_list(%p)\n",dev);
1984 if ((ccsindex = get_free_ccs(local)) < 0)
1985 {
1986 DEBUG(1,"ray_update_multi - No free ccs\n");
1987 return;
1988 }
1989 pccs = ccs_base(local) + ccsindex;
1990 writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd);
1991
1992 if (all) {
1993 writeb(0xff, &pccs->var);
1994 local->num_multi = 0xff;
1995 }
1996 else {
1997 /* Copy the kernel's list of MC addresses to card */
1998 for (dmip=&dev->mc_list; (dmi=*dmip)!=NULL; dmip=&dmi->next) {
1999 memcpy_toio(p, dmi->dmi_addr, ETH_ALEN);
2000 DEBUG(1,"ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n",dmi->dmi_addr[0],dmi->dmi_addr[1],dmi->dmi_addr[2],dmi->dmi_addr[3],dmi->dmi_addr[4],dmi->dmi_addr[5]);
2001 p += ETH_ALEN;
2002 i++;
2003 }
2004 if (i > 256/ADDRLEN) i = 256/ADDRLEN;
2005 writeb((UCHAR)i, &pccs->var);
2006 DEBUG(1,"ray_cs update_multi %d addresses in list\n", i);
2007 /* Interrupt the firmware to process the command */
2008 local->num_multi = i;
2009 }
2010 if (interrupt_ecf(local, ccsindex)) {
2011 DEBUG(1,"ray_cs update_multi failed - ECF not ready for intr\n");
2012 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
2013 }
2014} /* end ray_update_multi_list */
2015/*===========================================================================*/
2016static void set_multicast_list(struct net_device *dev)
2017{
2018 ray_dev_t *local = (ray_dev_t *)dev->priv;
2019 UCHAR promisc;
2020
2021 DEBUG(2,"ray_cs set_multicast_list(%p)\n",dev);
2022
2023 if (dev->flags & IFF_PROMISC)
2024 {
2025 if (local->sparm.b5.a_promiscuous_mode == 0) {
2026 DEBUG(1,"ray_cs set_multicast_list promisc on\n");
2027 local->sparm.b5.a_promiscuous_mode = 1;
2028 promisc = 1;
2029 ray_update_parm(dev, OBJID_promiscuous_mode, \
2030 &promisc, sizeof(promisc));
2031 }
2032 }
2033 else {
2034 if (local->sparm.b5.a_promiscuous_mode == 1) {
2035 DEBUG(1,"ray_cs set_multicast_list promisc off\n");
2036 local->sparm.b5.a_promiscuous_mode = 0;
2037 promisc = 0;
2038 ray_update_parm(dev, OBJID_promiscuous_mode, \
2039 &promisc, sizeof(promisc));
2040 }
2041 }
2042
2043 if (dev->flags & IFF_ALLMULTI) ray_update_multi_list(dev, 1);
2044 else
2045 {
2046 if (local->num_multi != dev->mc_count) ray_update_multi_list(dev, 0);
2047 }
2048} /* end set_multicast_list */
2049/*=============================================================================
2050 * All routines below here are run at interrupt time.
2051=============================================================================*/
2052static irqreturn_t ray_interrupt(int irq, void *dev_id, struct pt_regs * regs)
2053{
2054 struct net_device *dev = (struct net_device *)dev_id;
2055 dev_link_t *link;
2056 ray_dev_t *local;
2057 struct ccs __iomem *pccs;
2058 struct rcs __iomem *prcs;
2059 UCHAR rcsindex;
2060 UCHAR tmp;
2061 UCHAR cmd;
2062 UCHAR status;
2063
2064 if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */
2065 return IRQ_NONE;
2066
2067 DEBUG(4,"ray_cs: interrupt for *dev=%p\n",dev);
2068
2069 local = (ray_dev_t *)dev->priv;
2070 link = (dev_link_t *)local->finder;
2071 if ( ! (link->state & DEV_PRESENT) || link->state & DEV_SUSPEND ) {
2072 DEBUG(2,"ray_cs interrupt from device not present or suspended.\n");
2073 return IRQ_NONE;
2074 }
2075 rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index);
2076
2077 if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS))
2078 {
2079 DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex);
2080 clear_interrupt(local);
2081 return IRQ_HANDLED;
2082 }
2083 if (rcsindex < NUMBER_OF_CCS) /* If it's a returned CCS */
2084 {
2085 pccs = ccs_base(local) + rcsindex;
2086 cmd = readb(&pccs->cmd);
2087 status = readb(&pccs->buffer_status);
2088 switch (cmd)
2089 {
2090 case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */
2091 del_timer(&local->timer);
2092 if (status == CCS_COMMAND_COMPLETE) {
2093 DEBUG(1,"ray_cs interrupt download_startup_parameters OK\n");
2094 }
2095 else {
2096 DEBUG(1,"ray_cs interrupt download_startup_parameters fail\n");
2097 }
2098 break;
2099 case CCS_UPDATE_PARAMS:
2100 DEBUG(1,"ray_cs interrupt update params done\n");
2101 if (status != CCS_COMMAND_COMPLETE) {
2102 tmp = readb(&pccs->var.update_param.failure_cause);
2103 DEBUG(0,"ray_cs interrupt update params failed - reason %d\n",tmp);
2104 }
2105 break;
2106 case CCS_REPORT_PARAMS:
2107 DEBUG(1,"ray_cs interrupt report params done\n");
2108 break;
2109 case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */
2110 DEBUG(1,"ray_cs interrupt CCS Update Multicast List done\n");
2111 break;
2112 case CCS_UPDATE_POWER_SAVINGS_MODE:
2113 DEBUG(1,"ray_cs interrupt update power save mode done\n");
2114 break;
2115 case CCS_START_NETWORK:
2116 case CCS_JOIN_NETWORK:
2117 if (status == CCS_COMMAND_COMPLETE) {
2118 if (readb(&pccs->var.start_network.net_initiated) == 1) {
2119 DEBUG(0,"ray_cs interrupt network \"%s\" started\n",\
2120 local->sparm.b4.a_current_ess_id);
2121 }
2122 else {
2123 DEBUG(0,"ray_cs interrupt network \"%s\" joined\n",\
2124 local->sparm.b4.a_current_ess_id);
2125 }
2126 memcpy_fromio(&local->bss_id,pccs->var.start_network.bssid,ADDRLEN);
2127
2128 if (local->fw_ver == 0x55) local->net_default_tx_rate = 3;
2129 else local->net_default_tx_rate =
2130 readb(&pccs->var.start_network.net_default_tx_rate);
2131 local->encryption = readb(&pccs->var.start_network.encryption);
2132 if (!sniffer && (local->net_type == INFRA)
2133 && !(local->sparm.b4.a_acting_as_ap_status)) {
2134 authenticate(local);
2135 }
2136 local->card_status = CARD_ACQ_COMPLETE;
2137 }
2138 else {
2139 local->card_status = CARD_ACQ_FAILED;
2140
2141 del_timer(&local->timer);
2142 local->timer.expires = jiffies + HZ*5;
2143 local->timer.data = (long)local;
2144 if (status == CCS_START_NETWORK) {
2145 DEBUG(0,"ray_cs interrupt network \"%s\" start failed\n",\
2146 local->sparm.b4.a_current_ess_id);
2147 local->timer.function = &start_net;
2148 }
2149 else {
2150 DEBUG(0,"ray_cs interrupt network \"%s\" join failed\n",\
2151 local->sparm.b4.a_current_ess_id);
2152 local->timer.function = &join_net;
2153 }
2154 add_timer(&local->timer);
2155 }
2156 break;
2157 case CCS_START_ASSOCIATION:
2158 if (status == CCS_COMMAND_COMPLETE) {
2159 local->card_status = CARD_ASSOC_COMPLETE;
2160 DEBUG(0,"ray_cs association successful\n");
2161 }
2162 else
2163 {
2164 DEBUG(0,"ray_cs association failed,\n");
2165 local->card_status = CARD_ASSOC_FAILED;
2166 join_net((u_long)local);
2167 }
2168 break;
2169 case CCS_TX_REQUEST:
2170 if (status == CCS_COMMAND_COMPLETE) {
2171 DEBUG(3,"ray_cs interrupt tx request complete\n");
2172 }
2173 else {
2174 DEBUG(1,"ray_cs interrupt tx request failed\n");
2175 }
2176 if (!sniffer) netif_start_queue(dev);
2177 netif_wake_queue(dev);
2178 break;
2179 case CCS_TEST_MEMORY:
2180 DEBUG(1,"ray_cs interrupt mem test done\n");
2181 break;
2182 case CCS_SHUTDOWN:
2183 DEBUG(1,"ray_cs interrupt Unexpected CCS returned - Shutdown\n");
2184 break;
2185 case CCS_DUMP_MEMORY:
2186 DEBUG(1,"ray_cs interrupt dump memory done\n");
2187 break;
2188 case CCS_START_TIMER:
2189 DEBUG(2,"ray_cs interrupt DING - raylink timer expired\n");
2190 break;
2191 default:
2192 DEBUG(1,"ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n",\
2193 rcsindex, cmd);
2194 }
2195 writeb(CCS_BUFFER_FREE, &pccs->buffer_status);
2196 }
2197 else /* It's an RCS */
2198 {
2199 prcs = rcs_base(local) + rcsindex;
2200
2201 switch (readb(&prcs->interrupt_id))
2202 {
2203 case PROCESS_RX_PACKET:
2204 ray_rx(dev, local, prcs);
2205 break;
2206 case REJOIN_NET_COMPLETE:
2207 DEBUG(1,"ray_cs interrupt rejoin net complete\n");
2208 local->card_status = CARD_ACQ_COMPLETE;
2209 /* do we need to clear tx buffers CCS's? */
2210 if (local->sparm.b4.a_network_type == ADHOC) {
2211 if (!sniffer) netif_start_queue(dev);
2212 }
2213 else {
2214 memcpy_fromio(&local->bss_id, prcs->var.rejoin_net_complete.bssid, ADDRLEN);
2215 DEBUG(1,"ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n",\
2216 local->bss_id[0], local->bss_id[1], local->bss_id[2],\
2217 local->bss_id[3], local->bss_id[4], local->bss_id[5]);
2218 if (!sniffer) authenticate(local);
2219 }
2220 break;
2221 case ROAMING_INITIATED:
2222 DEBUG(1,"ray_cs interrupt roaming initiated\n");
2223 netif_stop_queue(dev);
2224 local->card_status = CARD_DOING_ACQ;
2225 break;
2226 case JAPAN_CALL_SIGN_RXD:
2227 DEBUG(1,"ray_cs interrupt japan call sign rx\n");
2228 break;
2229 default:
2230 DEBUG(1,"ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n",\
2231 rcsindex, (unsigned int) readb(&prcs->interrupt_id));
2232 break;
2233 }
2234 writeb(CCS_BUFFER_FREE, &prcs->buffer_status);
2235 }
2236 clear_interrupt(local);
2237 return IRQ_HANDLED;
2238} /* ray_interrupt */
2239/*===========================================================================*/
2240static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs)
2241{
2242 int rx_len;
2243 unsigned int pkt_addr;
2244 void __iomem *pmsg;
2245 DEBUG(4,"ray_rx process rx packet\n");
2246
2247 /* Calculate address of packet within Rx buffer */
2248 pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8)
2249 + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END;
2250 /* Length of first packet fragment */
2251 rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8)
2252 + readb(&prcs->var.rx_packet.rx_data_length[1]);
2253
2254 local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev);
2255 pmsg = local->rmem + pkt_addr;
2256 switch(readb(pmsg))
2257 {
2258 case DATA_TYPE:
2259 DEBUG(4,"ray_rx data type\n");
2260 rx_data(dev, prcs, pkt_addr, rx_len);
2261 break;
2262 case AUTHENTIC_TYPE:
2263 DEBUG(4,"ray_rx authentic type\n");
2264 if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len);
2265 else rx_authenticate(local, prcs, pkt_addr, rx_len);
2266 break;
2267 case DEAUTHENTIC_TYPE:
2268 DEBUG(4,"ray_rx deauth type\n");
2269 if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len);
2270 else rx_deauthenticate(local, prcs, pkt_addr, rx_len);
2271 break;
2272 case NULL_MSG_TYPE:
2273 DEBUG(3,"ray_cs rx NULL msg\n");
2274 break;
2275 case BEACON_TYPE:
2276 DEBUG(4,"ray_rx beacon type\n");
2277 if (sniffer) rx_data(dev, prcs, pkt_addr, rx_len);
2278
2279 copy_from_rx_buff(local, (UCHAR *)&local->last_bcn, pkt_addr,
2280 rx_len < sizeof(struct beacon_rx) ?
2281 rx_len : sizeof(struct beacon_rx));
2282
2283 local->beacon_rxed = 1;
2284 /* Get the statistics so the card counters never overflow */
2285 ray_get_stats(dev);
2286 break;
2287 default:
2288 DEBUG(0,"ray_cs unknown pkt type %2x\n", (unsigned int) readb(pmsg));
2289 break;
2290 }
2291
2292} /* end ray_rx */
2293/*===========================================================================*/
2294static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, unsigned int pkt_addr,
2295 int rx_len)
2296{
2297 struct sk_buff *skb = NULL;
2298 struct rcs __iomem *prcslink = prcs;
2299 ray_dev_t *local = dev->priv;
2300 UCHAR *rx_ptr;
2301 int total_len;
2302 int tmp;
2303#ifdef WIRELESS_SPY
2304 int siglev = local->last_rsl;
2305 u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */
2306#endif
2307
2308 if (!sniffer) {
2309 if (translate) {
2310/* TBD length needs fixing for translated header */
2311 if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) ||
2312 rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN))
2313 {
2314 DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len);
2315 return;
2316 }
2317 }
2318 else /* encapsulated ethernet */ {
2319 if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) ||
2320 rx_len > (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + FCS_LEN))
2321 {
2322 DEBUG(0,"ray_cs invalid packet length %d received \n",rx_len);
2323 return;
2324 }
2325 }
2326 }
2327 DEBUG(4,"ray_cs rx_data packet\n");
2328 /* If fragmented packet, verify sizes of fragments add up */
2329 if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) {
2330 DEBUG(1,"ray_cs rx'ed fragment\n");
2331 tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8)
2332 + readb(&prcs->var.rx_packet.totalpacketlength[1]);
2333 total_len = tmp;
2334 prcslink = prcs;
2335 do {
2336 tmp -= (readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8)
2337 + readb(&prcslink->var.rx_packet.rx_data_length[1]);
2338 if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) == 0xFF
2339 || tmp < 0) break;
2340 prcslink = rcs_base(local)
2341 + readb(&prcslink->link_field);
2342 } while (1);
2343
2344 if (tmp < 0)
2345 {
2346 DEBUG(0,"ray_cs rx_data fragment lengths don't add up\n");
2347 local->stats.rx_dropped++;
2348 release_frag_chain(local, prcs);
2349 return;
2350 }
2351 }
2352 else { /* Single unfragmented packet */
2353 total_len = rx_len;
2354 }
2355
2356 skb = dev_alloc_skb( total_len+5 );
2357 if (skb == NULL)
2358 {
2359 DEBUG(0,"ray_cs rx_data could not allocate skb\n");
2360 local->stats.rx_dropped++;
2361 if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF)
2362 release_frag_chain(local, prcs);
2363 return;
2364 }
2365 skb_reserve( skb, 2); /* Align IP on 16 byte (TBD check this)*/
2366 skb->dev = dev;
2367
2368 DEBUG(4,"ray_cs rx_data total_len = %x, rx_len = %x\n",total_len,rx_len);
2369
2370/************************/
2371 /* Reserve enough room for the whole damn packet. */
2372 rx_ptr = skb_put( skb, total_len);
2373 /* Copy the whole packet to sk_buff */
2374 rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len);
2375 /* Get source address */
2376#ifdef WIRELESS_SPY
2377 memcpy(linksrcaddr, ((struct mac_header *)skb->data)->addr_2, ETH_ALEN);
2378#endif
2379 /* Now, deal with encapsulation/translation/sniffer */
2380 if (!sniffer) {
2381 if (!translate) {
2382 /* Encapsulated ethernet, so just lop off 802.11 MAC header */
2383/* TBD reserve skb_reserve( skb, RX_MAC_HEADER_LENGTH); */
2384 skb_pull( skb, RX_MAC_HEADER_LENGTH);
2385 }
2386 else {
2387 /* Do translation */
2388 untranslate(local, skb, total_len);
2389 }
2390 }
2391 else
2392 { /* sniffer mode, so just pass whole packet */ };
2393
2394/************************/
2395 /* Now pick up the rest of the fragments if any */
2396 tmp = 17;
2397 if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) {
2398 prcslink = prcs;
2399 DEBUG(1,"ray_cs rx_data in fragment loop\n");
2400 do {
2401 prcslink = rcs_base(local)
2402 + readb(&prcslink->var.rx_packet.next_frag_rcs_index);
2403 rx_len = (( readb(&prcslink->var.rx_packet.rx_data_length[0]) << 8)
2404 + readb(&prcslink->var.rx_packet.rx_data_length[1]))
2405 & RX_BUFF_END;
2406 pkt_addr = (( readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << 8)
2407 + readb(&prcslink->var.rx_packet.rx_data_ptr[1]))
2408 & RX_BUFF_END;
2409
2410 rx_ptr += copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len);
2411
2412 } while (tmp-- &&
2413 readb(&prcslink->var.rx_packet.next_frag_rcs_index) != 0xFF);
2414 release_frag_chain(local, prcs);
2415 }
2416
2417 skb->protocol = eth_type_trans(skb,dev);
2418 netif_rx(skb);
2419 dev->last_rx = jiffies;
2420 local->stats.rx_packets++;
2421 local->stats.rx_bytes += total_len;
2422
2423 /* Gather signal strength per address */
2424#ifdef WIRELESS_SPY
2425 /* For the Access Point or the node having started the ad-hoc net
2426 * note : ad-hoc work only in some specific configurations, but we
2427 * kludge in ray_get_wireless_stats... */
2428 if(!memcmp(linksrcaddr, local->bss_id, ETH_ALEN))
2429 {
2430 /* Update statistics */
2431 /*local->wstats.qual.qual = none ? */
2432 local->wstats.qual.level = siglev;
2433 /*local->wstats.qual.noise = none ? */
2434 local->wstats.qual.updated = 0x2;
2435 }
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07002436 /* Now, update the spy stuff */
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437 {
Jean Tourrilhes3d5d5ac2005-09-02 11:40:39 -07002438 struct iw_quality wstats;
2439 wstats.level = siglev;
2440 /* wstats.noise = none ? */
2441 /* wstats.qual = none ? */
2442 wstats.updated = 0x2;
2443 /* Update spy records */
2444 wireless_spy_update(dev, linksrcaddr, &wstats);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 }
2446#endif /* WIRELESS_SPY */
2447} /* end rx_data */
2448/*===========================================================================*/
2449static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len)
2450{
2451 snaphdr_t *psnap = (snaphdr_t *)(skb->data + RX_MAC_HEADER_LENGTH);
2452 struct mac_header *pmac = (struct mac_header *)skb->data;
2453 unsigned short type = *(unsigned short *)psnap->ethertype;
2454 unsigned int xsap = *(unsigned int *)psnap & 0x00ffffff;
2455 unsigned int org = (*(unsigned int *)psnap->org) & 0x00ffffff;
2456 int delta;
2457 struct ethhdr *peth;
2458 UCHAR srcaddr[ADDRLEN];
2459 UCHAR destaddr[ADDRLEN];
2460
2461 if (pmac->frame_ctl_2 & FC2_FROM_DS) {
2462 if (pmac->frame_ctl_2 & FC2_TO_DS) { /* AP to AP */
2463 memcpy(destaddr, pmac->addr_3, ADDRLEN);
2464 memcpy(srcaddr, ((unsigned char *)pmac->addr_3) + ADDRLEN, ADDRLEN);
2465 } else { /* AP to terminal */
2466 memcpy(destaddr, pmac->addr_1, ADDRLEN);
2467 memcpy(srcaddr, pmac->addr_3, ADDRLEN);
2468 }
2469 } else { /* Terminal to AP */
2470 if (pmac->frame_ctl_2 & FC2_TO_DS) {
2471 memcpy(destaddr, pmac->addr_3, ADDRLEN);
2472 memcpy(srcaddr, pmac->addr_2, ADDRLEN);
2473 } else { /* Adhoc */
2474 memcpy(destaddr, pmac->addr_1, ADDRLEN);
2475 memcpy(srcaddr, pmac->addr_2, ADDRLEN);
2476 }
2477 }
2478
2479#ifdef PCMCIA_DEBUG
2480 if (pc_debug > 3) {
2481 int i;
2482 printk(KERN_DEBUG "skb->data before untranslate");
2483 for (i=0;i<64;i++)
2484 printk("%02x ",skb->data[i]);
2485 printk("\n" KERN_DEBUG "type = %08x, xsap = %08x, org = %08x\n",
2486 type,xsap,org);
2487 printk(KERN_DEBUG "untranslate skb->data = %p\n",skb->data);
2488 }
2489#endif
2490
2491 if ( xsap != SNAP_ID) {
2492 /* not a snap type so leave it alone */
2493 DEBUG(3,"ray_cs untranslate NOT SNAP %x\n", *(unsigned int *)psnap & 0x00ffffff);
2494
2495 delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
2496 peth = (struct ethhdr *)(skb->data + delta);
2497 peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH);
2498 }
2499 else { /* Its a SNAP */
2500 if (org == BRIDGE_ENCAP) { /* EtherII and nuke the LLC */
2501 DEBUG(3,"ray_cs untranslate Bridge encap\n");
2502 delta = RX_MAC_HEADER_LENGTH
2503 + sizeof(struct snaphdr_t) - ETH_HLEN;
2504 peth = (struct ethhdr *)(skb->data + delta);
2505 peth->h_proto = type;
2506 }
2507 else {
2508 if (org == RFC1042_ENCAP) {
2509 switch (type) {
2510 case RAY_IPX_TYPE:
2511 case APPLEARP_TYPE:
2512 DEBUG(3,"ray_cs untranslate RFC IPX/AARP\n");
2513 delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
2514 peth = (struct ethhdr *)(skb->data + delta);
2515 peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH);
2516 break;
2517 default:
2518 DEBUG(3,"ray_cs untranslate RFC default\n");
2519 delta = RX_MAC_HEADER_LENGTH +
2520 sizeof(struct snaphdr_t) - ETH_HLEN;
2521 peth = (struct ethhdr *)(skb->data + delta);
2522 peth->h_proto = type;
2523 break;
2524 }
2525 }
2526 else {
2527 printk("ray_cs untranslate very confused by packet\n");
2528 delta = RX_MAC_HEADER_LENGTH - ETH_HLEN;
2529 peth = (struct ethhdr *)(skb->data + delta);
2530 peth->h_proto = type;
2531 }
2532 }
2533 }
2534/* TBD reserve skb_reserve(skb, delta); */
2535 skb_pull(skb, delta);
2536 DEBUG(3,"untranslate after skb_pull(%d), skb->data = %p\n",delta,skb->data);
2537 memcpy(peth->h_dest, destaddr, ADDRLEN);
2538 memcpy(peth->h_source, srcaddr, ADDRLEN);
2539#ifdef PCMCIA_DEBUG
2540 if (pc_debug > 3) {
2541 int i;
2542 printk(KERN_DEBUG "skb->data after untranslate:");
2543 for (i=0;i<64;i++)
2544 printk("%02x ",skb->data[i]);
2545 printk("\n");
2546 }
2547#endif
2548} /* end untranslate */
2549/*===========================================================================*/
2550/* Copy data from circular receive buffer to PC memory.
2551 * dest = destination address in PC memory
2552 * pkt_addr = source address in receive buffer
2553 * len = length of packet to copy
2554 */
2555static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int length)
2556{
2557 int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1);
2558 if (wrap_bytes <= 0)
2559 {
2560 memcpy_fromio(dest,local->rmem + pkt_addr,length);
2561 }
2562 else /* Packet wrapped in circular buffer */
2563 {
2564 memcpy_fromio(dest,local->rmem+pkt_addr,length - wrap_bytes);
2565 memcpy_fromio(dest + length - wrap_bytes, local->rmem, wrap_bytes);
2566 }
2567 return length;
2568}
2569/*===========================================================================*/
2570static void release_frag_chain(ray_dev_t *local, struct rcs __iomem * prcs)
2571{
2572 struct rcs __iomem *prcslink = prcs;
2573 int tmp = 17;
2574 unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index);
2575
2576 while (tmp--) {
2577 writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
2578 if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) {
2579 DEBUG(1,"ray_cs interrupt bad rcsindex = 0x%x\n",rcsindex);
2580 break;
2581 }
2582 prcslink = rcs_base(local) + rcsindex;
2583 rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index);
2584 }
2585 writeb(CCS_BUFFER_FREE, &prcslink->buffer_status);
2586}
2587/*===========================================================================*/
2588static void authenticate(ray_dev_t *local)
2589{
2590 dev_link_t *link = local->finder;
2591 DEBUG(0,"ray_cs Starting authentication.\n");
2592 if (!(link->state & DEV_PRESENT)) {
2593 DEBUG(2,"ray_cs authenticate - device not present\n");
2594 return;
2595 }
2596
2597 del_timer(&local->timer);
2598 if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) {
2599 local->timer.function = &join_net;
2600 }
2601 else {
2602 local->timer.function = &authenticate_timeout;
2603 }
2604 local->timer.expires = jiffies + HZ*2;
2605 local->timer.data = (long)local;
2606 add_timer(&local->timer);
2607 local->authentication_state = AWAITING_RESPONSE;
2608} /* end authenticate */
2609/*===========================================================================*/
2610static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs,
2611 unsigned int pkt_addr, int rx_len)
2612{
2613 UCHAR buff[256];
2614 struct rx_msg *msg = (struct rx_msg *)buff;
2615
2616 del_timer(&local->timer);
2617
2618 copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff);
2619 /* if we are trying to get authenticated */
2620 if (local->sparm.b4.a_network_type == ADHOC) {
2621 DEBUG(1,"ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", msg->var[0],msg->var[1],msg->var[2],msg->var[3],msg->var[4],msg->var[5]);
2622 if (msg->var[2] == 1) {
2623 DEBUG(0,"ray_cs Sending authentication response.\n");
2624 if (!build_auth_frame (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) {
2625 local->authentication_state = NEED_TO_AUTH;
2626 memcpy(local->auth_id, msg->mac.addr_2, ADDRLEN);
2627 }
2628 }
2629 }
2630 else /* Infrastructure network */
2631 {
2632 if (local->authentication_state == AWAITING_RESPONSE) {
2633 /* Verify authentication sequence #2 and success */
2634 if (msg->var[2] == 2) {
2635 if ((msg->var[3] | msg->var[4]) == 0) {
2636 DEBUG(1,"Authentication successful\n");
2637 local->card_status = CARD_AUTH_COMPLETE;
2638 associate(local);
2639 local->authentication_state = AUTHENTICATED;
2640 }
2641 else {
2642 DEBUG(0,"Authentication refused\n");
2643 local->card_status = CARD_AUTH_REFUSED;
2644 join_net((u_long)local);
2645 local->authentication_state = UNAUTHENTICATED;
2646 }
2647 }
2648 }
2649 }
2650
2651} /* end rx_authenticate */
2652/*===========================================================================*/
2653static void associate(ray_dev_t *local)
2654{
2655 struct ccs __iomem *pccs;
2656 dev_link_t *link = local->finder;
2657 struct net_device *dev = link->priv;
2658 int ccsindex;
2659 if (!(link->state & DEV_PRESENT)) {
2660 DEBUG(2,"ray_cs associate - device not present\n");
2661 return;
2662 }
2663 /* If no tx buffers available, return*/
2664 if ((ccsindex = get_free_ccs(local)) < 0)
2665 {
2666/* TBD should never be here but... what if we are? */
2667 DEBUG(1,"ray_cs associate - No free ccs\n");
2668 return;
2669 }
2670 DEBUG(1,"ray_cs Starting association with access point\n");
2671 pccs = ccs_base(local) + ccsindex;
2672 /* fill in the CCS */
2673 writeb(CCS_START_ASSOCIATION, &pccs->cmd);
2674 /* Interrupt the firmware to process the command */
2675 if (interrupt_ecf(local, ccsindex)) {
2676 DEBUG(1,"ray_cs associate failed - ECF not ready for intr\n");
2677 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
2678
2679 del_timer(&local->timer);
2680 local->timer.expires = jiffies + HZ*2;
2681 local->timer.data = (long)local;
2682 local->timer.function = &join_net;
2683 add_timer(&local->timer);
2684 local->card_status = CARD_ASSOC_FAILED;
2685 return;
2686 }
2687 if (!sniffer) netif_start_queue(dev);
2688
2689} /* end associate */
2690/*===========================================================================*/
2691static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs,
2692 unsigned int pkt_addr, int rx_len)
2693{
2694/* UCHAR buff[256];
2695 struct rx_msg *msg = (struct rx_msg *)buff;
2696*/
2697 DEBUG(0,"Deauthentication frame received\n");
2698 local->authentication_state = UNAUTHENTICATED;
2699 /* Need to reauthenticate or rejoin depending on reason code */
2700/* copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff);
2701 */
2702}
2703/*===========================================================================*/
2704static void clear_interrupt(ray_dev_t *local)
2705{
2706 writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET);
2707}
2708/*===========================================================================*/
2709#ifdef CONFIG_PROC_FS
2710#define MAXDATA (PAGE_SIZE - 80)
2711
2712static char *card_status[] = {
2713 "Card inserted - uninitialized", /* 0 */
2714 "Card not downloaded", /* 1 */
2715 "Waiting for download parameters", /* 2 */
2716 "Card doing acquisition", /* 3 */
2717 "Acquisition complete", /* 4 */
2718 "Authentication complete", /* 5 */
2719 "Association complete", /* 6 */
2720 "???", "???", "???", "???", /* 7 8 9 10 undefined */
2721 "Card init error", /* 11 */
2722 "Download parameters error", /* 12 */
2723 "???", /* 13 */
2724 "Acquisition failed", /* 14 */
2725 "Authentication refused", /* 15 */
2726 "Association failed" /* 16 */
2727};
2728
2729static char *nettype[] = {"Adhoc", "Infra "};
2730static char *framing[] = {"Encapsulation", "Translation"}
2731;
2732/*===========================================================================*/
2733static int ray_cs_proc_read(char *buf, char **start, off_t offset, int len)
2734{
2735/* Print current values which are not available via other means
2736 * eg ifconfig
2737 */
2738 int i;
2739 dev_link_t *link;
2740 struct net_device *dev;
2741 ray_dev_t *local;
2742 UCHAR *p;
2743 struct freq_hop_element *pfh;
2744 UCHAR c[33];
2745
2746 link = dev_list;
2747 if (!link)
2748 return 0;
2749 dev = (struct net_device *)link->priv;
2750 if (!dev)
2751 return 0;
2752 local = (ray_dev_t *)dev->priv;
2753 if (!local)
2754 return 0;
2755
2756 len = 0;
2757
2758 len += sprintf(buf + len, "Raylink Wireless LAN driver status\n");
2759 len += sprintf(buf + len, "%s\n", rcsid);
2760 /* build 4 does not report version, and field is 0x55 after memtest */
2761 len += sprintf(buf + len, "Firmware version = ");
2762 if (local->fw_ver == 0x55)
2763 len += sprintf(buf + len, "4 - Use dump_cis for more details\n");
2764 else
2765 len += sprintf(buf + len, "%2d.%02d.%02d\n",
2766 local->fw_ver, local->fw_bld, local->fw_var);
2767
2768 for (i=0; i<32; i++) c[i] = local->sparm.b5.a_current_ess_id[i];
2769 c[32] = 0;
2770 len += sprintf(buf + len, "%s network ESSID = \"%s\"\n",
2771 nettype[local->sparm.b5.a_network_type], c);
2772
2773 p = local->bss_id;
2774 len += sprintf(buf + len,
2775 "BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
2776 p[0],p[1],p[2],p[3],p[4],p[5]);
2777
2778 len += sprintf(buf + len, "Country code = %d\n",
2779 local->sparm.b5.a_curr_country_code);
2780
2781 i = local->card_status;
2782 if (i < 0) i = 10;
2783 if (i > 16) i = 10;
2784 len += sprintf(buf + len, "Card status = %s\n", card_status[i]);
2785
2786 len += sprintf(buf + len, "Framing mode = %s\n",framing[translate]);
2787
2788 len += sprintf(buf + len, "Last pkt signal lvl = %d\n", local->last_rsl);
2789
2790 if (local->beacon_rxed) {
2791 /* Pull some fields out of last beacon received */
2792 len += sprintf(buf + len, "Beacon Interval = %d Kus\n",
2793 local->last_bcn.beacon_intvl[0]
2794 + 256 * local->last_bcn.beacon_intvl[1]);
2795
2796 p = local->last_bcn.elements;
2797 if (p[0] == C_ESSID_ELEMENT_ID) p += p[1] + 2;
2798 else {
2799 len += sprintf(buf + len, "Parse beacon failed at essid element id = %d\n",p[0]);
2800 return len;
2801 }
2802
2803 if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) {
2804 len += sprintf(buf + len, "Supported rate codes = ");
2805 for (i=2; i<p[1] + 2; i++)
2806 len += sprintf(buf + len, "0x%02x ", p[i]);
2807 len += sprintf(buf + len, "\n");
2808 p += p[1] + 2;
2809 }
2810 else {
2811 len += sprintf(buf + len, "Parse beacon failed at rates element\n");
2812 return len;
2813 }
2814
2815 if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) {
2816 pfh = (struct freq_hop_element *)p;
2817 len += sprintf(buf + len, "Hop dwell = %d Kus\n",
2818 pfh->dwell_time[0] + 256 * pfh->dwell_time[1]);
2819 len += sprintf(buf + len, "Hop set = %d \n", pfh->hop_set);
2820 len += sprintf(buf + len, "Hop pattern = %d \n", pfh->hop_pattern);
2821 len += sprintf(buf + len, "Hop index = %d \n", pfh->hop_index);
2822 p += p[1] + 2;
2823 }
2824 else {
2825 len += sprintf(buf + len, "Parse beacon failed at FH param element\n");
2826 return len;
2827 }
2828 } else {
2829 len += sprintf(buf + len, "No beacons received\n");
2830 }
2831 return len;
2832}
2833
2834#endif
2835/*===========================================================================*/
2836static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
2837{
2838 int addr;
2839 struct ccs __iomem *pccs;
2840 struct tx_msg __iomem *ptx;
2841 int ccsindex;
2842
2843 /* If no tx buffers available, return */
2844 if ((ccsindex = get_free_tx_ccs(local)) < 0)
2845 {
2846 DEBUG(1,"ray_cs send authenticate - No free tx ccs\n");
2847 return -1;
2848 }
2849
2850 pccs = ccs_base(local) + ccsindex;
2851
2852 /* Address in card space */
2853 addr = TX_BUF_BASE + (ccsindex << 11);
2854 /* fill in the CCS */
2855 writeb(CCS_TX_REQUEST, &pccs->cmd);
2856 writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr);
2857 writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1);
2858 writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length);
2859 writeb(TX_AUTHENTICATE_LENGTH_LSB,pccs->var.tx_request.tx_data_length + 1);
2860 writeb(0, &pccs->var.tx_request.pow_sav_mode);
2861
2862 ptx = local->sram + addr;
2863 /* fill in the mac header */
2864 writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1);
2865 writeb(0, &ptx->mac.frame_ctl_2);
2866
2867 memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN);
2868 memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN);
2869 memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN);
2870
2871 /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */
2872 memset_io(ptx->var, 0, 6);
2873 writeb(auth_type & 0xff, ptx->var + 2);
2874
2875 /* Interrupt the firmware to process the command */
2876 if (interrupt_ecf(local, ccsindex)) {
2877 DEBUG(1,"ray_cs send authentication request failed - ECF not ready for intr\n");
2878 writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status);
2879 return -1;
2880 }
2881 return 0;
2882} /* End build_auth_frame */
2883
2884/*===========================================================================*/
2885#ifdef CONFIG_PROC_FS
2886static void raycs_write(const char *name, write_proc_t *w, void *data)
2887{
2888 struct proc_dir_entry * entry = create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
2889 if (entry) {
2890 entry->write_proc = w;
2891 entry->data = data;
2892 }
2893}
2894
2895static int write_essid(struct file *file, const char __user *buffer, unsigned long count, void *data)
2896{
2897 static char proc_essid[33];
2898 int len = count;
2899
2900 if (len > 32)
2901 len = 32;
2902 memset(proc_essid, 0, 33);
2903 if (copy_from_user(proc_essid, buffer, len))
2904 return -EFAULT;
2905 essid = proc_essid;
2906 return count;
2907}
2908
2909static int write_int(struct file *file, const char __user *buffer, unsigned long count, void *data)
2910{
2911 static char proc_number[10];
2912 char *p;
2913 int nr, len;
2914
2915 if (!count)
2916 return 0;
2917
2918 if (count > 9)
2919 return -EINVAL;
2920 if (copy_from_user(proc_number, buffer, count))
2921 return -EFAULT;
2922 p = proc_number;
2923 nr = 0;
2924 len = count;
2925 do {
2926 unsigned int c = *p - '0';
2927 if (c > 9)
2928 return -EINVAL;
2929 nr = nr*10 + c;
2930 p++;
2931 } while (--len);
2932 *(int *)data = nr;
2933 return count;
2934}
2935#endif
2936
Dominik Brodowskif57ea2a2005-06-27 16:28:24 -07002937static struct pcmcia_device_id ray_ids[] = {
2938 PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000),
2939 PCMCIA_DEVICE_NULL,
2940};
2941MODULE_DEVICE_TABLE(pcmcia, ray_ids);
2942
Linus Torvalds1da177e2005-04-16 15:20:36 -07002943static struct pcmcia_driver ray_driver = {
2944 .owner = THIS_MODULE,
2945 .drv = {
2946 .name = "ray_cs",
2947 },
2948 .attach = ray_attach,
Dominik Brodowski1e212f32005-07-07 17:59:00 -07002949 .event = ray_event,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002950 .detach = ray_detach,
Dominik Brodowskif57ea2a2005-06-27 16:28:24 -07002951 .id_table = ray_ids,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002952};
2953
2954static int __init init_ray_cs(void)
2955{
2956 int rc;
2957
2958 DEBUG(1, "%s\n", rcsid);
2959 rc = pcmcia_register_driver(&ray_driver);
2960 DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n",rc);
2961
2962#ifdef CONFIG_PROC_FS
2963 proc_mkdir("driver/ray_cs", NULL);
2964
2965 create_proc_info_entry("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_read);
2966 raycs_write("driver/ray_cs/essid", write_essid, NULL);
2967 raycs_write("driver/ray_cs/net_type", write_int, &net_type);
2968 raycs_write("driver/ray_cs/translate", write_int, &translate);
2969#endif
2970 if (translate != 0) translate = 1;
2971 return 0;
2972} /* init_ray_cs */
2973
2974/*===========================================================================*/
2975
2976static void __exit exit_ray_cs(void)
2977{
2978 DEBUG(0, "ray_cs: cleanup_module\n");
2979
2980#ifdef CONFIG_PROC_FS
2981 remove_proc_entry("driver/ray_cs/ray_cs", NULL);
2982 remove_proc_entry("driver/ray_cs/essid", NULL);
2983 remove_proc_entry("driver/ray_cs/net_type", NULL);
2984 remove_proc_entry("driver/ray_cs/translate", NULL);
2985 remove_proc_entry("driver/ray_cs", NULL);
2986#endif
2987
2988 pcmcia_unregister_driver(&ray_driver);
2989 BUG_ON(dev_list != NULL);
2990} /* exit_ray_cs */
2991
2992module_init(init_ray_cs);
2993module_exit(exit_ray_cs);
2994
2995/*===========================================================================*/