1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include <linux/module.h>
22#include <linux/init.h>
23#include <linux/config.h>
24#include <linux/kernel.h>
25#include <linux/tqueue.h>
26#include <linux/netdevice.h>
27#include <linux/etherdevice.h>
28#include <linux/skbuff.h>
29#include <linux/if_arp.h>
30#include <linux/ioport.h>
31
32#include <asm/io.h>
33#include <asm/bitops.h>
34#include <asm/system.h>
35#include <asm/byteorder.h>
36#include <asm/irq.h>
37#include <linux/time.h>
38#include <linux/sched.h>
39#include <linux/delay.h>
40#include "aironet4500.h"
41#include <linux/ip.h>
42
43
44int bap_sleep = 10 ;
45int bap_sleep_after_setup = 1;
46int sleep_before_command = 1;
47int bap_sleep_before_write= 1;
48int sleep_in_command = 1;
49int both_bap_lock;
50int bap_setup_spinlock;
51
52EXPORT_SYMBOL(bap_sleep);
53EXPORT_SYMBOL(bap_sleep_after_setup);
54EXPORT_SYMBOL(sleep_before_command);
55EXPORT_SYMBOL(bap_sleep_before_write);
56EXPORT_SYMBOL(sleep_in_command);
57EXPORT_SYMBOL(both_bap_lock);
58EXPORT_SYMBOL(bap_setup_spinlock);
59
60struct awc_strings awc_status_error_codes[]=awc_reply_error_strings;
61struct awc_strings awc_command_names[]=awc_command_name_strings;
62struct awc_strings awc_link_status_names[]=awc_link_status_strings;
63struct awc_strings awc_rid_names[]=aironet4500_RID_Select_strings;
64struct awc_strings awc_link_failure_reason_names[]=IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS;
65
66const char * awc_print_string( struct awc_strings* strings, int code){
67
68 struct awc_strings * str = strings;
69 int i = 0;
70 while (str[i].string != NULL){
71 if (str[i].par == (code & str[i].mask )){
72 return str[i].string;
73 };
74 i++;
75 };
76 return "UNKNOWN";
77};
78
79int awc_dump_registers(struct net_device * dev){
80
81#ifdef AWC_DEBUG
82 int i;
83#endif
84 int status= inw(dev->base_addr +4*2);
85 int r1= inw(dev->base_addr +5*2);
86 int r2= inw(dev->base_addr +6*2);
87 int r3= inw(dev->base_addr +7*2);
88
89 printk(KERN_ERR "Command %s , result: %s, at memblk %x(RID %s) , offset %x \n",
90 awc_print_string(awc_command_names,status),
91 awc_print_string(awc_status_error_codes,r1),
92 r2, awc_print_string(awc_rid_names,r2),
93 r3);
94
95#ifdef AWC_DEBUG
96 printk(KERN_ERR "%s aironet register dump ",dev->name );
97
98
99 for (i=0; i < 32; i++){
100 printk("%4x ", inw(dev->base_addr + i*2 ) );
101 if ( (i+1)%8 == 0){
102 printk("\n");
103 printk(KERN_ERR "%02x",(i+1)*2);
104 }
105 };
106 printk(KERN_ERR " \n");
107#endif
108 return 0;
109};
110
111
112
113
114inline
115int awc_command_busy_clear_wait(struct net_device * dev){
116
117 u16 active_interrupts;
118 int cnt= 0;
119
120 AWC_ENTRY_EXIT_DEBUG(" entry awc_command_busy_clear_wait ");
121
122 while (awc_command_busy(dev->base_addr)){
123 if (cnt > 1000 ){
124 printk(KERN_ERR "awc command busy too long, clearing\n");
125 awc_dump_registers(dev);
126 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
127 break;
128 };
129 if (((struct awc_private*) dev->priv)->ejected)
130 return -1;
131 cnt++;
132 udelay(10);
133 }
134
135 cnt = 0;
136 while (awc_command_busy(dev->base_addr)){
137
138 if (cnt > 30000 ){
139 printk(KERN_CRIT "awc command busy WAY too long, clearing\n");
140 awc_dump_registers(dev);
141 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
142 active_interrupts = awc_event_status(dev->base_addr);
143 awc_event_ack(dev->base_addr, active_interrupts);
144
145 AWC_ENTRY_EXIT_DEBUG("BAD exit\n ");
146 return -1 ;
147
148 };
149 if (((struct awc_private*) dev->priv)->ejected)
150 return -1;
151 cnt++;
152 udelay(10);
153 }
154
155
156 AWC_ENTRY_EXIT_DEBUG(" exit\n ");
157
158 return 0;
159
160
161};
162
163
164
165inline unsigned short
166awc_issue_command_and_block(struct awc_command * cmd){
167
168 int ticks;
169 long long jiff;
170 u16 enabled_interrupts;
171 int cnt = 0;
172
173
174 jiff = jiffies;
175
176
177 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_and_block ");
178
179 AWC_LOCK_COMMAND_ISSUING(cmd->priv);
180
181 if (awc_command_busy_clear_wait(cmd->dev)) goto final;
182
183 if (cmd->priv->sleeping_bap) udelay(sleep_before_command);
184
185 awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);
186
187
188
189 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
190
191 enabled_interrupts = awc_ints_enabled(cmd->dev->base_addr);
192 awc_ints_enable(cmd->dev->base_addr, enabled_interrupts & ~0x10);
193 if(cmd->priv->enabled_interrupts & 0x10)
194 cmd->priv->enabled_interrupts &= ~0x10;
195
196
197 while ( awc_command_read(cmd->port) == cmd->command) {
198 udelay(1);
199 awc_command_write(cmd->port, cmd->command);
200
201 if (cnt > 2000 ){
202 printk(" long wait with commmand reg busy in blocking command \n");
203 awc_dump_registers(cmd->dev);
204 goto final;
205 };
206 if (cmd->priv->ejected)
207 goto final;
208 cnt++;
209 udelay(10);
210
211 };
212 AWC_ENTRY_EXIT_DEBUG(" issued " );
213
214 ticks = 0;
215 while ( awc_event_status_Cmd(cmd->port) == 0) {
216 ticks++;
217 if (ticks > 100000){
218 printk(" long wait with commmand reg busy \n");
219 awc_dump_registers(cmd->dev);
220 goto final;
221 };
222 if (ticks > 500){
223 DEBUG(1, " long wait after issue 10mks * %d ", ticks );
224
225
226 }
227 if (cmd->priv->ejected)
228 goto final;
229 udelay(10);
230 }
231 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
232
233 awc_read_response(cmd);
234 AWC_ENTRY_EXIT_DEBUG(" resp read \n");
235
236 if (awc_command_busy(cmd->port))
237 awc_event_ack_ClrStckCmdBsy(cmd->port);
238
239 awc_event_ack_Cmd(cmd->port);
240 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
241
242 if (cmd->status & 0xff00){
243 printk(KERN_ERR " bad response to command %s, parameter %x \n",awc_print_string(awc_command_names, cmd->command),cmd->par0);
244 awc_dump_registers(cmd->dev);
245 goto final;
246 }
247
248 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
249 AWC_ENTRY_EXIT_DEBUG(" exit \n");
250 udelay(1);
251 return 0;
252final:
253 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
254 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
255 return -1; ;
256};
257
258
259inline
260unsigned short
261awc_issue_command(struct awc_command * cmd){
262
263
264
265
266 int cnt = 0;
267
268
269 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command");
270
271 if (!cmd){
272 printk(KERN_CRIT "cmd == NULL in awc_issue_command\n");
273 return -1;
274
275 }
276 if (!cmd->dev){
277 printk(KERN_CRIT "cmd->dev == NULL in awc_issue_command\n");
278 return -1;
279
280 }
281
282 AWC_LOCK_COMMAND_ISSUING(cmd->priv);
283
284 if(awc_command_busy_clear_wait(cmd->dev)) goto final;
285
286 if(!cmd->priv->enabled_interrupts & 0x10){
287 cmd->priv->enabled_interrupts |= 0x10;
288 awc_ints_enable(cmd->port, cmd->priv->enabled_interrupts );
289 }
290
291 cmd->priv->async_command_start = jiffies;
292 cmd->priv->command_semaphore_on++;
293
294
295 awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);
296
297 while ( awc_command_read(cmd->port) == cmd->command) {
298
299 awc_command_write(cmd->port, cmd->command);
300
301 if (cnt > 2000) {
302 printk(" long wait with commmand reg busy in async command \n");
303 awc_dump_registers(cmd->dev);
304 goto final;
305 };
306 if (cmd->priv->ejected)
307 goto final;
308 cnt++;
309 udelay(10);
310 };
311
312 cmd->priv->cmd = *cmd;
313
314
315 AWC_ENTRY_EXIT_DEBUG(" exit \n");
316 return 0;
317 final:
318 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
319 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
320 return -1; ;
321
322};
323
324inline
325unsigned short
326awc_issue_command_no_ack(struct net_device * dev,
327 u16 com, u16 par1, u16 par2, u16 par3){
328
329 struct awc_private * priv = (struct awc_private *)dev->priv;
330 int cnt = 0;
331 long long jiff;
332 jiff = jiffies;
333
334 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_no_ack ");
335
336
337 AWC_LOCK_COMMAND_ISSUING(priv);
338
339 if (awc_command_busy_clear_wait(dev)) {
340 printk("aironet4x00 no_ack command (reset) with stuck card \n");
341 }
342
343 awc4500wout(dev->base_addr,com, par1, par2,par3);
344
345 udelay(10);
346 while ( awc_event_status_Cmd(dev->base_addr) == 0) {
347 if (awc_command_read(dev->base_addr) == com) {
348 awc_command_write(dev->base_addr, com);
349 }
350
351 if (cnt > 2000) {
352 printk(" long wait with commmand reg busy in noack command %d par %d %d %d\n",com,par1,par2,par3);
353 awc_dump_registers(dev);
354 goto final;
355 };
356 if (priv->ejected)
357 goto final;
358 udelay(10);
359 cnt++;
360 }
361
362 if (awc_command_busy(dev->base_addr))
363 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
364
365 AWC_UNLOCK_COMMAND_ISSUING(priv);
366 AWC_ENTRY_EXIT_DEBUG(" exit \n");
367 return 0;
368final:
369 AWC_UNLOCK_COMMAND_ISSUING(priv);
370 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
371 return -1; ;
372};
373
374
375
376
377
378int awc_bap_setup(struct awc_command * cmd) {
379
380 int status;
381 long long jiff;
382 unsigned long flags;
383 int cleared = 0;
384 int cycles = 0;
385
386 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_setup ");
387
388 if ( cmd->priv->sleeping_bap)
389 udelay(bap_sleep);
390
391 if (cmd->priv->ejected)
392 return -1;
393
394 if (!cmd->bap || !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
395 DEBUG(1,"no bap or bap not locked cmd %d !!", cmd->command);
396
397 if (bap_setup_spinlock)
398 spin_lock_irqsave(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
399 status = AWC_IN(cmd->bap->offset);
400
401 if (status & ~0x2000 ){
402 WAIT61x3;
403 status = AWC_IN(cmd->bap->offset);
404 }
405
406 if (status & ~0x2000 ){
407 WAIT61x3;
408 AWC_IN(cmd->dev->base_addr + 0x26);
409 AWC_OUT(cmd->dev->base_addr + 0x26, 0);
410 WAIT61x3;
411 udelay(60);
412 #ifdef AWC_DEBUG
413 printk("b");
414 #endif
415 status = AWC_IN(cmd->bap->offset);
416 }
417
418
419 if (status & 0xC000){
420 printk(KERN_ERR "bap entered with err or busy bit set %x \n",status);
421 if (cmd->bap->lock != 1)
422 printk(KERN_ERR "bap lock bad same time %x\n",cmd->bap->lock);
423 awc_dump_registers(cmd->dev);
424
425 }
426
427 save_flags(flags);
428 cli();
429
430 AWC_OUT(cmd->bap->select, cmd->rid);
431 WAIT61x3;
432 AWC_OUT(cmd->bap->offset, cmd->offset);
433
434 restore_flags(flags);
435
436 WAIT61x3;
437
438 jiff = jiffies;
439
440 while (1) {
441 cycles++;
442 status = AWC_IN(cmd->bap->offset);
443 if ( cmd->priv->sleeping_bap)
444 udelay(bap_sleep);
445 if (cmd->priv->ejected)
446 goto ejected_unlock;
447 udelay(1);
448 if (cycles > 10000) {
449 printk(KERN_CRIT "deadlock in bap\n");
450 goto return_AWC_ERROR;
451 };
452 status = AWC_IN(cmd->bap->offset);
453 if (status & AWC_BAP_BUSY) {
454 if (cycles % 100 == 99 ) {
455 save_flags(flags);
456 cli();
457 if (!cleared){
458 AWC_IN(cmd->dev->base_addr + 0x26);
459 AWC_OUT(cmd->dev->base_addr + 0x26, 0);
460 WAIT61x3;
461 cleared = 1;
462 }
463 AWC_OUT(cmd->bap->select, cmd->rid);
464 WAIT61x3;
465 AWC_OUT(cmd->bap->offset, cmd->offset);
466 restore_flags(flags);
467 #ifdef AWC_DEBUG
468 printk("B");
469 #endif
470
471 if ( cmd->priv->sleeping_bap)
472 udelay(bap_sleep);
473 else udelay(30);
474
475 }
476 if (jiffies - jiff > 1 ) {
477 AWC_ENTRY_EXIT_DEBUG(" BAD BUSY exit \n");
478 awc_dump_registers(cmd->dev);
479 goto return_AWC_ERROR;
480 }
481 continue;
482 }
483 if (status & AWC_BAP_DONE) {
484 WAIT61x3; WAIT61x3; WAIT61x3;
485
486
487
488 AWC_ENTRY_EXIT_DEBUG(" exit \n");
489 if (cmd->priv->sleeping_bap)
490 udelay(bap_sleep_after_setup);
491
492
493 goto return_AWC_SUCCESS;
494 }
495
496 if (status & AWC_BAP_ERR) {
497 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
498
499 printk(KERN_ERR "bap setup error bit set for rid %x offset %x \n",cmd->rid,cmd->offset);
500 awc_dump_registers(cmd->dev);
501 goto return_AWC_ERROR;
502 }
503 if ( cmd->priv->sleeping_bap)
504 udelay(bap_sleep);
505 else udelay(1);
506
507
508 save_flags(flags);
509 cli();
510 AWC_OUT(cmd->bap->select, cmd->rid);
511 WAIT61x3;
512 AWC_OUT(cmd->bap->offset, cmd->offset);
513 WAIT61x3;
514 restore_flags(flags);
515
516 if (jiffies - jiff > HZ)
517 if (! (status &(AWC_BAP_ERR |AWC_BAP_DONE |AWC_BAP_BUSY))){
518 printk("aironet4500: bap setup lock without any status bits set");
519 awc_dump_registers(cmd->dev);
520 goto return_AWC_ERROR;
521
522 };
523
524 }
525
526 AWC_ENTRY_EXIT_DEBUG(" WE MUST NOT BE HERE exit \n");
527
528ejected_unlock:
529 if (bap_setup_spinlock)
530 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
531 AWC_ENTRY_EXIT_DEBUG(" ejected_unlock_exit \n");
532 return -1;
533
534return_AWC_ERROR:
535 if (bap_setup_spinlock)
536 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
537 AWC_ENTRY_EXIT_DEBUG(" AWC_ERROR_exit \n");
538 return AWC_ERROR;
539
540return_AWC_SUCCESS:
541 if (bap_setup_spinlock)
542 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
543 AWC_ENTRY_EXIT_DEBUG(" exit \n");
544 return AWC_SUCCESS;
545}
546
547
548
549inline
550int
551awc_bap_read(struct awc_command * cmd) {
552 register u16 len;
553 register u16 * buff = (u16 *) cmd->buff;
554 register u16 port= cmd->bap->data;
555
556
557 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_read ");
558 if (!cmd->bap && !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
559 DEBUG(0,"no bap or bap not locked %d !!", cmd->command);
560 cmd->len = (cmd->len + 1) & (~1);
561 len = cmd->len / 2;
562 if (cmd->priv->ejected)
563 return -1;
564
565
566 if (cmd->priv->sleeping_bap)
567 udelay(bap_sleep_before_write);
568
569 if (!cmd->priv->sleeping_bap)
570 while ( len-- > 0)
571 *buff++ = AWC_IN(port);
572 else
573 while ( len-- > 0){
574 *buff++ = AWC_IN(port);
575 }
576 AWC_ENTRY_EXIT_DEBUG(" exit \n");
577 if (cmd->priv->ejected)
578 return -1;
579
580 return AWC_SUCCESS;
581}
582
583
584inline
585int
586awc_bap_write(struct awc_command * cmd){
587 register u16 len;
588 register u16 * buff = (u16 *) cmd->buff;
589 register u16 port= cmd->bap->data;
590
591
592 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_write ");
593 if (!cmd->bap && !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
594 DEBUG(0,"no bap or bap not locked %d !!", cmd->command);
595
596 cmd->len = (cmd->len + 1) & (~1);
597 len = cmd->len / 2;
598
599 if (cmd->priv->ejected)
600 return -1;
601
602 if (cmd->priv->sleeping_bap)
603 udelay(bap_sleep_before_write);
604
605
606 if (!cmd->priv->sleeping_bap)
607 while (len-- > 0)
608 AWC_OUT(port, *buff++);
609 else
610 while ( len-- > 0){
611 AWC_OUT(port, *buff++);
612 }
613 if (cmd->priv->ejected)
614 return -1;
615
616
617 AWC_ENTRY_EXIT_DEBUG(" exit \n");
618
619 return AWC_SUCCESS;
620}
621
622
623
624
625
626
627const struct aironet4500_rid_selector aironet4500_RID_Select_General_Config =(const struct aironet4500_rid_selector){ 0xFF10, 1,0,0, "General Configuration" };
628const struct aironet4500_rid_selector aironet4500_RID_Select_SSID_list =(const struct aironet4500_rid_selector){ 0xFF11, 1,0,0, "Valid SSID list" };
629const struct aironet4500_rid_selector aironet4500_RID_Select_AP_list =(const struct aironet4500_rid_selector){ 0xFF12, 1,0,0, "Valid AP list" };
630const struct aironet4500_rid_selector aironet4500_RID_Select_Driver_name =(const struct aironet4500_rid_selector){ 0xFF13, 1,0,0, "Driver name" };
631const struct aironet4500_rid_selector aironet4500_RID_Select_Encapsulation =(const struct aironet4500_rid_selector){ 0xFF14, 1,0,0, "Ethernet Protocol" };
632const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_volatile =(const struct aironet4500_rid_selector){ 0xFF15, 1,0,0, "WEP key volatile" };
633const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_nonvolatile =(const struct aironet4500_rid_selector){ 0xFF16, 1,0,0, "WEP key non-volatile" };
634const struct aironet4500_rid_selector aironet4500_RID_Select_Modulation =(const struct aironet4500_rid_selector){ 0xFF17, 1,0,0, "Modulation" };
635const struct aironet4500_rid_selector aironet4500_RID_Select_Active_Config =(const struct aironet4500_rid_selector){ 0xFF20, 0,1,1, "Actual Configuration" };
636const struct aironet4500_rid_selector aironet4500_RID_Select_Capabilities =(const struct aironet4500_rid_selector){ 0xFF00, 0,1,0, "Capabilities" };
637const struct aironet4500_rid_selector aironet4500_RID_Select_AP_Info =(const struct aironet4500_rid_selector){ 0xFF01, 0,1,1, "AP Info" };
638const struct aironet4500_rid_selector aironet4500_RID_Select_Radio_Info =(const struct aironet4500_rid_selector){ 0xFF02, 0,1,1, "Radio Info" };
639const struct aironet4500_rid_selector aironet4500_RID_Select_Status =(const struct aironet4500_rid_selector){ 0xFF50, 0,1,1, "Status" };
640const struct aironet4500_rid_selector aironet4500_RID_Select_16_stats =(const struct aironet4500_rid_selector){ 0xFF60, 0,1,1, "Cumulative 16-bit Statistics" };
641const struct aironet4500_rid_selector aironet4500_RID_Select_16_stats_delta =(const struct aironet4500_rid_selector){ 0xFF61, 0,1,1, "Delta 16-bit Statistics" };
642const struct aironet4500_rid_selector aironet4500_RID_Select_16_stats_clear =(const struct aironet4500_rid_selector){ 0xFF62, 0,1,1, "Delta 16-bit Statistics and Clear" };
643const struct aironet4500_rid_selector aironet4500_RID_Select_32_stats =(const struct aironet4500_rid_selector){ 0xFF68, 0,1,1, "Cumulative 32-bit Statistics" };
644const struct aironet4500_rid_selector aironet4500_RID_Select_32_stats_delta =(const struct aironet4500_rid_selector){ 0xFF69, 0,1,1, "Delta 32-bit Statistics" };
645const struct aironet4500_rid_selector aironet4500_RID_Select_32_stats_clear =(const struct aironet4500_rid_selector){ 0xFF6A, 0,1,1, "Delta 32-bit Statistics and Clear" };
646
647EXPORT_SYMBOL(aironet4500_RID_Select_General_Config);
648EXPORT_SYMBOL(aironet4500_RID_Select_SSID_list);
649EXPORT_SYMBOL(aironet4500_RID_Select_AP_list);
650EXPORT_SYMBOL(aironet4500_RID_Select_Driver_name);
651EXPORT_SYMBOL(aironet4500_RID_Select_Encapsulation);
652EXPORT_SYMBOL(aironet4500_RID_Select_WEP_volatile);
653EXPORT_SYMBOL(aironet4500_RID_Select_WEP_nonvolatile);
654EXPORT_SYMBOL(aironet4500_RID_Select_Modulation);
655EXPORT_SYMBOL(aironet4500_RID_Select_Active_Config);
656EXPORT_SYMBOL(aironet4500_RID_Select_Capabilities);
657EXPORT_SYMBOL(aironet4500_RID_Select_AP_Info);
658EXPORT_SYMBOL(aironet4500_RID_Select_Radio_Info);
659EXPORT_SYMBOL(aironet4500_RID_Select_Status);
660EXPORT_SYMBOL(aironet4500_RID_Select_16_stats);
661EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_delta);
662EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_clear);
663EXPORT_SYMBOL(aironet4500_RID_Select_32_stats);
664EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_delta);
665EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_clear);
666
667
668struct awc_rid_dir awc_rids_temp[]={
669
670 {&aironet4500_RID_Select_General_Config, 0x100 , NULL, NULL, NULL,0 },
671 {&aironet4500_RID_Select_SSID_list, 0x68 , NULL, NULL, NULL,0 },
672 {&aironet4500_RID_Select_AP_list, 0x20 , NULL, NULL, NULL,0 },
673 {&aironet4500_RID_Select_Driver_name, 0x12 , NULL, NULL, NULL,0 },
674 {&aironet4500_RID_Select_Encapsulation, 0x22 , NULL, NULL, NULL,0 },
675 {&aironet4500_RID_Select_Active_Config, 0x100 , NULL, NULL, NULL,0 },
676 {&aironet4500_RID_Select_Capabilities, 0x80 , NULL, NULL, NULL,0 },
677 {&aironet4500_RID_Select_Status, 0x6c , NULL, NULL, NULL,0 },
678 {&aironet4500_RID_Select_AP_Info, 0x06 , NULL, NULL, NULL,0 },
679 {&aironet4500_RID_Select_32_stats, 0x184 , NULL, NULL, NULL,0 },
680 {&aironet4500_RID_Select_32_stats_delta, 0x184 , NULL, NULL, NULL,0 },
681 {&aironet4500_RID_Select_32_stats_clear, 0x184 , NULL, NULL, NULL,0 },
682 {&aironet4500_RID_Select_WEP_volatile, 0x1c , NULL, NULL, NULL,0 },
683 {&aironet4500_RID_Select_WEP_nonvolatile, 0x1c , NULL, NULL, NULL,0 },
684 {&aironet4500_RID_Select_Modulation, 0x04 , NULL, NULL, NULL,0 },
685
686#ifdef AWC_USE_16BIT_STATS
687 {&aironet4500_RID_Select_16_stats, 0xC2 , NULL, NULL, NULL,0 },
688 {&aironet4500_RID_Select_16_stats_delta, 0xC2 , NULL, NULL, NULL,0 },
689 {&aironet4500_RID_Select_16_stats_clear, 0xC2 , NULL, NULL, NULL,0 },
690#else
691 {NULL},{NULL},{NULL},
692#endif
693
694 {0}
695
696
697};
698
699
700
701int
702awc_readrid(struct net_device * dev, struct aironet4500_RID * rid, void *pBuf ){
703 struct awc_command cmd;
704
705 int sleep_state ;
706
707 AWC_ENTRY_EXIT_DEBUG(" entry awc_readrid ");
708 if (!rid) return -1;
709 if (!rid->selector) return -1;
710 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
711 rid->selector->selector, rid->offset, (rid->bits / 8),pBuf);
712
713 sleep_state = cmd.priv->sleeping_bap ;
714 cmd.priv->sleeping_bap = 1;
715 udelay(500);
716 AWC_BAP_LOCK_NOT_CLI(cmd);
717 if (awc_issue_command_and_block(&cmd)) goto final;
718 udelay(1);
719 if (awc_bap_setup(&cmd)) goto final;
720 udelay(1);
721 if (awc_bap_read(&cmd)) goto final;
722 cmd.priv->sleeping_bap = sleep_state;
723
724 AWC_RELEASE_COMMAND(cmd);
725 AWC_ENTRY_EXIT_DEBUG(" exit \n");
726 return 0;
727 final:
728 cmd.priv->sleeping_bap = sleep_state;
729 AWC_RELEASE_COMMAND(cmd);
730 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
731 return -1; ;
732}
733
734int
735awc_writerid(struct net_device * dev, struct aironet4500_RID * rid, void *pBuf){
736
737 struct awc_command cmd;
738 int sleep_state ;
739
740 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid ");
741
742
743 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
744 rid->selector->selector,rid->offset, rid->bits/8,pBuf);
745
746 sleep_state = cmd.priv->sleeping_bap ;
747 cmd.priv->sleeping_bap = 1;
748
749 udelay(500);
750 AWC_BAP_LOCK_NOT_CLI(cmd);
751 if (awc_issue_command_and_block(&cmd)) goto final;
752 udelay(10);
753 if (awc_bap_setup(&cmd)) goto final;
754 udelay(10);
755 if (awc_bap_write(&cmd)) goto final;
756 udelay(10);
757 cmd.command=0x121;
758 if (awc_issue_command_and_block(&cmd)) goto final;
759 cmd.priv->sleeping_bap = sleep_state;
760
761 AWC_RELEASE_COMMAND(cmd);
762 AWC_ENTRY_EXIT_DEBUG(" exit \n");
763 return 0;
764 final:
765 cmd.priv->sleeping_bap = sleep_state;
766 AWC_RELEASE_COMMAND(cmd);
767 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
768 return -1; ;
769}
770
771int
772awc_readrid_dir(struct net_device * dev, struct awc_rid_dir * rid ){
773 struct awc_command cmd;
774 int sleep_state;
775
776 AWC_ENTRY_EXIT_DEBUG(" entry awcreadrid_dir ");
777
778
779 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
780 rid->selector->selector,0, rid->bufflen,rid->buff);
781
782 sleep_state = cmd.priv->sleeping_bap ;
783 cmd.priv->sleeping_bap = 1;
784
785 udelay(500);
786
787 AWC_BAP_LOCK_NOT_CLI(cmd);
788 if (awc_issue_command_and_block(&cmd)) goto final;
789
790 if (awc_bap_setup(&cmd)) goto final;
791 if (awc_bap_read(&cmd)) goto final;
792 cmd.priv->sleeping_bap = sleep_state;
793
794 AWC_RELEASE_COMMAND(cmd);
795 AWC_ENTRY_EXIT_DEBUG(" exit \n");
796 return 0;
797 final:
798 cmd.priv->sleeping_bap = sleep_state;
799 AWC_RELEASE_COMMAND(cmd);
800 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
801 return -1; ;
802}
803
804int
805awc_writerid_dir(struct net_device * dev, struct awc_rid_dir * rid){
806
807 struct awc_command cmd;
808 int sleep_state ;
809
810
811 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid_dir ");
812
813
814
815 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
816 rid->selector->selector,0, rid->bufflen,((char *)rid->buff));
817
818 sleep_state = cmd.priv->sleeping_bap ;
819 cmd.priv->sleeping_bap = 1;
820
821 udelay(500);
822
823 AWC_BAP_LOCK_NOT_CLI(cmd);
824
825 if (awc_issue_command_and_block(&cmd)) goto final;
826 if (awc_bap_setup(&cmd)) goto final;
827 if (awc_bap_write(&cmd)) goto final;
828 cmd.priv->sleeping_bap = sleep_state;
829
830 cmd.command=0x121;
831 udelay(500);
832 if (awc_issue_command_and_block(&cmd)) goto final;
833
834 AWC_RELEASE_COMMAND(cmd);
835 AWC_ENTRY_EXIT_DEBUG(" exit \n");
836 return 0;
837 final:
838 cmd.priv->sleeping_bap = sleep_state;
839 AWC_RELEASE_COMMAND(cmd);
840 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
841 return -1; ;
842}
843
844EXPORT_SYMBOL(awc_readrid);
845EXPORT_SYMBOL(awc_writerid);
846EXPORT_SYMBOL(awc_readrid_dir);
847EXPORT_SYMBOL(awc_writerid_dir);
848
849
850
851
852inline
853int
854awc_issue_blocking_command(struct net_device * dev,u16 comm){
855
856 struct awc_command cmd;
857
858
859 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_blocking_command ");
860
861 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,comm,0, 0, 0, 0 ,0 );
862
863 AWC_BAP_LOCK_NOT_CLI(cmd);
864
865 if (awc_issue_command_and_block(&cmd))
866 goto final;
867
868 AWC_RELEASE_COMMAND(cmd);
869 AWC_ENTRY_EXIT_DEBUG(" exit \n");
870 return 0;
871 final:
872 AWC_RELEASE_COMMAND(cmd);
873 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
874 return -1; ;
875
876};
877
878int
879awc_issue_soft_reset(struct net_device * dev){
880
881 u16 status ;
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911 status = awc_issue_command_no_ack(dev, AWC_COMMAND_SOFT_RESET,0,0,0);
912
913
914
915 return status;
916};
917
918int
919awc_issue_noop(struct net_device * dev){
920 int retval;
921 AWC_OUT(dev->base_addr + 0x28, 0);
922 AWC_OUT(dev->base_addr + 0x2A, 0);
923 udelay(1000);
924 retval= awc_issue_blocking_command(dev, AWC_COMMAND_NOOP);
925 udelay(1000);
926 return retval;
927};
928
929EXPORT_SYMBOL(awc_enable_MAC);
930
931int
932awc_enable_MAC(struct net_device * dev){
933
934 struct awc_private * priv = (struct awc_private *)dev->priv;
935 AWC_ENTRY_EXIT_DEBUG(" entry awc_enable_MAC ");
936
937 if (priv->mac_enabled){
938
939 AWC_ENTRY_EXIT_DEBUG(" mac already enabled exit \n");
940 return 0;
941 }
942 udelay(500);
943 if (awc_issue_blocking_command(dev, AWC_COMMAND_ENABLE)){
944 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
945 return -1; ;
946 }
947 udelay(500);
948
949 priv->mac_enabled = 1;
950
951 AWC_ENTRY_EXIT_DEBUG(" exit \n");
952 return 0;
953};
954
955EXPORT_SYMBOL(awc_disable_MAC);
956int
957awc_disable_MAC(struct net_device * dev){
958
959 struct awc_private * priv = (struct awc_private *)dev->priv;
960 AWC_ENTRY_EXIT_DEBUG(" entry awc_disable_MAC ");
961
962 if (!priv->mac_enabled){
963 AWC_ENTRY_EXIT_DEBUG(" mac allready disabled exit \n");
964 return 0;
965 }
966 udelay(1000);
967 if (awc_issue_blocking_command(dev, AWC_COMMAND_DISABLE)){
968 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
969 return -1; ;
970 }
971 udelay(1000);
972 priv->mac_enabled = 0;
973 AWC_ENTRY_EXIT_DEBUG(" exit \n");
974 return 0;
975};
976
977
978
979int
980awc_read_all_rids(struct net_device * dev){
981
982 struct awc_private * priv = (struct awc_private *)dev->priv;
983 int status,i;
984 AWC_ENTRY_EXIT_DEBUG(" entry awc_read_all_rids ");
985
986 for (i=0; i< AWC_NOF_RIDS && priv->rid_dir[i].selector ; i++){
987 status = awc_readrid_dir(dev,&priv->rid_dir[i]);
988 udelay(50);
989 if (status) return status;
990
991 }
992 priv->rids_read = 1;
993
994 AWC_ENTRY_EXIT_DEBUG(" exit \n");
995 return 0;
996}
997
998int
999awc_write_all_rids(struct net_device * dev){
1000
1001 struct awc_private * priv = (struct awc_private *)dev->priv;
1002 int i,status ;
1003 AWC_ENTRY_EXIT_DEBUG(" entry awc_write_all_rids ");
1004
1005 for (i=0;i < 5 && i< AWC_NOF_RIDS && priv->rid_dir[i].selector ; i++){
1006 status = awc_writerid_dir(dev,&priv->rid_dir[i]);
1007 udelay(10);
1008 if(status) return status;
1009 }
1010 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1011 return 0;
1012}
1013
1014
1015
1016
1017
1018
1019int awc_tx_alloc(struct net_device * dev) {
1020
1021 struct awc_command cmd;
1022 int k=0;
1023 int tot=0;
1024 struct awc_fid * fid = NULL;
1025
1026 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_alloc ");
1027
1028
1029 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x0A,0, 0,0,0,NULL);
1030 cmd.par0 = dev->mtu + AWC_TX_HEAD_SIZE + 8 ;
1031
1032 DEBUG(32,"about to allocate %x bytes ",cmd.priv->large_buff_mem);
1033 DEBUG(32,"in %x large buffers ",cmd.priv->large_buff_mem / (dev->mtu + AWC_TX_HEAD_SIZE + 8) );
1034
1035 k=0;tot=0;
1036 AWC_BAP_LOCK_NOT_CLI(cmd);
1037
1038 while (k < cmd.priv->large_buff_mem / (dev->mtu + AWC_TX_HEAD_SIZE + 8) ) {
1039
1040 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL );
1041 if (!fid) goto final;
1042 memset(fid, 0, sizeof(struct awc_fid));
1043
1044 if (awc_issue_command_and_block(&cmd)) goto final;
1045
1046 while ( awc_event_status_Alloc(cmd.port) == 0) ;
1047 fid->u.tx.fid = awc_Tx_Allocated_Fid(cmd.port);
1048 fid->u.tx.fid_size = dev->mtu + AWC_TX_HEAD_SIZE ;
1049
1050 DEBUG(32,"allocated large tx fid %x ",fid->u.tx.fid);
1051 if(fid->u.tx.fid == 0
1052 || cmd.status != 0xA){
1053 printk(KERN_ERR "%s bad tx_alloc\n",dev->name);
1054 fid->busy =1;
1055 goto final;
1056 } else {
1057 fid->busy =0;
1058 tot++;
1059 }
1060 awc_event_ack_Alloc(cmd.port);
1061
1062
1063 awc_fid_queue_push_tail(&cmd.priv->tx_large_ready,fid);
1064
1065 k++;
1066 }
1067 cmd.priv->tx_buffs_total = tot;
1068 DEBUG(32,"allocated %d large tx buffs\n",tot);
1069
1070 cmd.par0 = AWC_TX_ALLOC_SMALL_SIZE ;
1071 k =0; tot = 0;
1072
1073 while (k < cmd.priv->small_buff_no) {
1074
1075 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL );
1076 if (!fid) goto final;
1077 memset(fid, 0, sizeof(struct awc_fid));
1078
1079 cmd.par0 = AWC_TX_ALLOC_SMALL_SIZE ;
1080
1081 if (awc_issue_command_and_block(&cmd)) goto final;
1082
1083 while ( awc_event_status_Alloc(cmd.port) == 0) ;
1084 fid->u.tx.fid = awc_Tx_Allocated_Fid(cmd.port);
1085 fid->u.tx.fid_size = AWC_TX_ALLOC_SMALL_SIZE;
1086
1087 DEBUG(32,"allocated large tx fid %x ",fid->u.tx.fid);
1088 if(fid->u.tx.fid == 0
1089 || cmd.status != 0xA){
1090 printk(KERN_ERR "%s bad tx_alloc\n",dev->name);
1091 fid->busy =1;
1092 goto final;
1093 } else {
1094 fid->busy =0;
1095 tot++;
1096 }
1097 awc_event_ack_Alloc(cmd.port);
1098
1099
1100 awc_fid_queue_push_tail(&cmd.priv->tx_small_ready,fid);
1101
1102 k++;
1103 }
1104
1105 cmd.priv->tx_small_buffs_total = tot;
1106 DEBUG(32,"allocated %d small tx buffs\n",tot);
1107
1108 AWC_RELEASE_COMMAND(cmd);
1109 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1110 return 0;
1111
1112 final:
1113 if (fid )
1114 kfree(fid);
1115 printk(KERN_CRIT "%s awc tx prealloc failed \n",dev->name);
1116 AWC_RELEASE_COMMAND(cmd);
1117 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1118 return -1; ;
1119
1120};
1121
1122int
1123awc_tx_dealloc_fid(struct net_device * dev,struct awc_fid * fid){
1124
1125 struct awc_command cmd;
1126 int fid_handle = 0;
1127
1128 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x0C,0, 0,0,0,NULL);
1129
1130 AWC_BAP_LOCK_NOT_CLI(cmd);
1131
1132 if (fid->u.tx.fid){
1133 fid_handle = cmd.par0 = fid->u.tx.fid;
1134 fid->u.tx.fid = 0;
1135 fid->busy =0;
1136 kfree(fid);
1137
1138 if (!cmd.priv->ejected)
1139 if (awc_issue_command_and_block(&cmd)) goto final;
1140
1141 }
1142
1143 AWC_RELEASE_COMMAND(cmd);
1144 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1145 return 0;
1146
1147 final:
1148 printk(KERN_ERR "awc_tx_dealloc failed for fid %x \n",fid_handle);
1149 AWC_RELEASE_COMMAND(cmd);
1150 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1151 return -1; ;
1152
1153
1154};
1155
1156int
1157awc_tx_dealloc(struct net_device * dev){
1158
1159 struct awc_private * priv = (struct awc_private *)dev->priv;
1160
1161
1162
1163
1164 struct awc_fid * fid;
1165
1166 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_dealloc ");
1167
1168 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_large_ready)))
1169 awc_tx_dealloc_fid(dev,fid);
1170 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_small_ready)))
1171 awc_tx_dealloc_fid(dev,fid);
1172 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_post_process)))
1173 awc_tx_dealloc_fid(dev,fid);
1174 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_in_transmit)))
1175 awc_tx_dealloc_fid(dev,fid);
1176
1177 return 0;
1178
1179};
1180
1181
1182
1183inline struct awc_fid *
1184awc_tx_fid_lookup_and_remove(struct net_device * dev, u16 fid_handle){
1185
1186 struct awc_private * priv = (struct awc_private *)dev->priv;
1187
1188 unsigned long flags;
1189 struct awc_fid * fid = NULL;
1190 int cnt=0;
1191
1192 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_fid_lookup ");
1193
1194 spin_lock_irqsave(&(priv->queues_lock),flags);
1195
1196
1197 fid = priv->tx_in_transmit.head;
1198 cnt = 0;
1199 while (fid){
1200 if (fid->u.tx.fid == fid_handle){
1201 awc_fid_queue_remove(&priv->tx_in_transmit, fid);
1202 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1203 return fid;
1204 }
1205 fid = fid->next;
1206
1207 if (cnt++ > 200) {
1208
1209 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1210 return 0;
1211 };
1212 };
1213
1214 cnt=0;
1215 fid = priv->tx_post_process.head;
1216 while (fid){
1217 if (fid->u.tx.fid == fid_handle){
1218 awc_fid_queue_remove(&priv->tx_post_process, fid);
1219 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1220 return fid;
1221 }
1222 fid = fid->next;
1223
1224 if (cnt++ > 200) {
1225
1226 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1227 return 0;
1228 };
1229
1230 };
1231
1232 cnt=0;
1233 fid = priv->tx_large_ready.head;
1234 while (fid){
1235 if (fid->u.tx.fid == fid_handle){
1236 awc_fid_queue_remove(&priv->tx_large_ready, fid);
1237 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1238 return fid;
1239 }
1240 fid = fid->next;
1241
1242 if (cnt++ > 200) {
1243
1244 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1245 return 0;
1246 };
1247
1248 };
1249 cnt=0;
1250 fid = priv->tx_small_ready.head;
1251 while (fid){
1252 if (fid->u.tx.fid == fid_handle){
1253 awc_fid_queue_remove(&priv->tx_small_ready, fid);
1254 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1255 return fid;
1256 }
1257 fid = fid->next;
1258
1259 if (cnt++ > 200) {
1260
1261 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1262 return 0;
1263 };
1264
1265 };
1266
1267 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1268
1269 printk(KERN_ERR "%s tx fid %x not found \n",dev->name, fid_handle);
1270 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1271 return NULL;
1272}
1273
1274
1275
1276
1277
1278int
1279awc_queues_init(struct net_device * dev){
1280 struct awc_private * priv = (struct awc_private *)dev->priv;
1281 struct awc_fid * fid = NULL;
1282 int retv =0;
1283 int k = 0;
1284
1285 awc_fid_queue_init(&priv->tx_in_transmit);
1286 awc_fid_queue_init(&priv->tx_post_process);
1287 awc_fid_queue_init(&priv->tx_large_ready);
1288 awc_fid_queue_init(&priv->tx_small_ready);
1289 awc_fid_queue_init(&priv->rx_ready);
1290 awc_fid_queue_init(&priv->rx_post_process);
1291
1292 retv = awc_tx_alloc(dev);
1293
1294 k = 0;
1295 while (k < AWC_RX_BUFFS){
1296 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL);
1297 if (!fid) return -1;
1298 awc_fid_queue_push_tail(&priv->rx_ready,fid);
1299 k++;
1300 };
1301
1302 if (retv) return retv;
1303
1304 return 0;
1305};
1306
1307
1308int
1309awc_queues_destroy(struct net_device * dev){
1310 struct awc_private * priv = (struct awc_private *)dev->priv;
1311 struct awc_fid * fid = NULL;
1312 int retv =0;
1313
1314
1315
1316 while (NULL != (fid = awc_fid_queue_pop_head(&priv->rx_ready))){
1317 kfree(fid);
1318 }
1319 while (NULL != (fid = awc_fid_queue_pop_head(&priv->rx_post_process))){
1320 kfree(fid);
1321 }
1322
1323 retv = awc_tx_dealloc(dev);
1324
1325 return retv;
1326};
1327
1328
1329
1330
1331inline int
1332awc_802_11_copy_path_skb(struct net_device * dev, struct awc_fid * rx_buff){
1333
1334 struct awc_private * priv = (struct awc_private * )dev->priv;
1335
1336 AWC_ENTRY_EXIT_DEBUG("awc_802_11_copy_path_skb");
1337
1338 if (rx_buff->pkt_len < 22 ) rx_buff->pkt_len = 22;
1339
1340
1341 rx_buff->skb = dev_alloc_skb(rx_buff->pkt_len + 12 +2);
1342
1343
1344 if (rx_buff->skb == NULL) {
1345 printk(KERN_CRIT "couldnt alloc rx_buff->skb in rx event \n");
1346 priv->stats.rx_dropped++;
1347 return -1;
1348 }
1349 rx_buff->type |= p80211copy_path_skb;
1350
1351 rx_buff->skb->dev = dev;
1352
1353
1354
1355 rx_buff->u.rx.payload = skb_put(rx_buff->skb, rx_buff->pkt_len + 12 ) ;
1356 rx_buff->u.rx.payload = ((char *)rx_buff->u.rx.payload ) +12;
1357
1358 AWC_ENTRY_EXIT_DEBUG("exit\n");
1359
1360 return 0;
1361
1362
1363};
1364
1365
1366int
1367awc_802_11_find_copy_path(struct net_device * dev, struct awc_fid * rx_buff){
1368
1369
1370
1371
1372
1373 rx_buff->type =0;
1374
1375 return awc_802_11_copy_path_skb(dev,rx_buff);
1376};
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390int parse_not_8023;
1391
1392void
1393awc_802_11_router_rx(struct net_device * dev,struct awc_fid * rx_buff){
1394
1395 struct awc_private * priv = (struct awc_private * )dev->priv;
1396 struct sk_buff * skb = rx_buff->skb;
1397 u8 * payload = rx_buff->u.rx.payload;
1398
1399 u16 pkt_len = rx_buff->pkt_len;
1400 struct ieee_802_11_802_1H_header * bridge = NULL;
1401 struct ieee_802_11_snap_header * snap = NULL;
1402 struct ieee_802_11_802_1H_header * bridge_tmp;
1403 struct ieee_802_11_snap_header * snap_tmp;
1404
1405 u16 ptr = 0;
1406 u16 len;
1407
1408 AWC_ENTRY_EXIT_DEBUG("awc_802_11_router_rx");
1409
1410
1411 rx_buff->mac = rx_buff->u.rx.ieee_802_3.dst_mac;
1412
1413
1414
1415 if ( rx_buff->u.rx.ieee_802_11.frame_control == 0x8 )
1416 memcpy(priv->bssid,rx_buff->u.rx.ieee_802_11.mac3,6);
1417
1418 while ((ptr < pkt_len - 1 ) && payload && parse_not_8023){
1419
1420 bridge_tmp = (struct ieee_802_11_802_1H_header*) &payload[ptr];
1421 snap_tmp = (struct ieee_802_11_snap_header*) &payload[ptr];
1422 len = ntohs( *((u16*)&payload[ptr]) );
1423
1424
1425
1426 if ( len < 0x5DC) {
1427
1428 if ( len != pkt_len-2 - ptr){
1429 printk(KERN_ERR "%s bad encapsulation lenght %x at pkt offset %x \n",dev->name,len,ptr);
1430 goto bad_packet;
1431 }
1432 DEBUG(1,"parisng packet of size %x\n",len);
1433 ptr +=2;
1434 continue;
1435 }
1436
1437 DEBUG(1,"parisng packet of proto %x\n",len);
1438
1439 if (snap_tmp->dsap == 0xaa && snap_tmp->ssap == 0xaa &&
1440 pkt_len - ptr > sizeof(struct ieee_802_11_snap_header) ){
1441
1442 DEBUG(0x200,"%s SNAP ",dev->name);
1443 if (snap_tmp->ctrl != 0x03){
1444 printk(KERN_ERR "%s unknown snap ctrl %x \n",dev->name,snap_tmp->ctrl);
1445 goto bad_packet;
1446 };
1447 if (snap_tmp->oui[0] == 0 &&
1448 snap_tmp->oui[1] == 0 &&
1449 snap_tmp->oui[2] == 0 ){
1450 snap = snap_tmp;
1451 ptr += sizeof(struct ieee_802_11_snap_header);
1452 DEBUG(0x200,"%s LLC RFC1042 \n",dev->name);
1453 continue;
1454 }
1455 if (snap_tmp->oui[0] == 0 &&
1456 snap_tmp->oui[1] == 0 &&
1457 snap_tmp->oui[2] == 0x78){
1458 snap = snap_tmp;
1459 DEBUG(0x200,"%s LLC 802.1H \n",dev->name);
1460 ptr += sizeof(struct ieee_802_11_snap_header);
1461 continue;
1462 };
1463 if (snap_tmp->oui[0] == 0x00 &&
1464 snap_tmp->oui[1] == 0x40 &&
1465 snap_tmp->oui[2] == 0x96){
1466 ptr += sizeof(struct ieee_802_11_802_1H_header);
1467 if (ptr >= pkt_len){
1468 goto bad_packet;
1469 DEBUG(1,"%s invalid packet len in 802.1H SNAP OUI check \n",dev->name);
1470 }
1471 DEBUG(0x200,"%s OUI 004096 \n",dev->name);
1472 DEBUG(0x200," 802.1H uknown1 %x ",ntohs(bridge_tmp->unknown1));
1473 DEBUG(0x200," 802.1H uknw type %x \n",0xf000 & ntohs(bridge_tmp->unknown2));
1474 DEBUG(0x200," 802.1H payloadsize %x \n",0x0fff & ntohs(bridge_tmp->unknown2));
1475
1476
1477
1478 bridge = bridge_tmp;
1479 if (bridge_tmp->unknown1 == 0x0000 &&
1480 ((ntohs(bridge_tmp->unknown2) & 0xf000) == 0x1000 ) ){
1481 rx_buff->type |= p80211_8021H;
1482 rx_buff->mac = &payload[ptr];
1483 DEBUG(0x200," 802.1H DATA packet of size %x\n",0xf000 & ntohs(bridge_tmp->unknown2) );
1484 memcpy(priv->p2p,rx_buff->u.rx.ieee_802_11.mac2, 6);
1485 ptr +=12;
1486 continue;
1487 };
1488 DEBUG(0x200,"%s droping unknown 004096 packet \n ",dev->name);
1489 goto bad_packet;
1490
1491
1492 }
1493 goto bad_packet;
1494 }
1495 if ( len > 0x5DC){
1496
1497
1498 if ( len == 0x8000 || len == 0x8006){
1499
1500 DEBUG(0x200,"Non IP packet %x \n",ntohs(len));
1501
1502 };
1503 goto good_packet;
1504
1505 };
1506
1507 goto good_packet;
1508 }
1509
1510 good_packet:
1511
1512 if (ptr > pkt_len) goto bad_packet;
1513
1514 if ( rx_buff->mac != (payload + ptr -12) )
1515 memcpy( payload +ptr -12, rx_buff->mac , 12);
1516
1517
1518
1519 if (!payload || !skb || !rx_buff->skb || !rx_buff->u.rx.payload)
1520 return ;
1521
1522 skb->data = payload + ptr -12;
1523 skb->len += ptr ;
1524
1525 rx_buff->skb->protocol = eth_type_trans(rx_buff->skb,dev);
1526 DEBUG(0x200,"eth_type_trans decided: %x\n",rx_buff->skb->protocol);
1527 rx_buff->skb = NULL;
1528 rx_buff->u.rx.payload = NULL;
1529 priv->stats.rx_packets++;
1530 priv->stats.rx_bytes += skb->len;
1531
1532 netif_rx(skb);
1533 dev->last_rx = jiffies;
1534 AWC_ENTRY_EXIT_DEBUG("exit\n");
1535 return ;
1536
1537 bad_packet:
1538 DEBUG(0x200,"%s packet dropped in packet hdr parse \n ",dev->name);
1539 if (rx_buff->skb && (rx_buff->type & p80211copy_path_skb)){
1540
1541 dev_kfree_skb_irq(rx_buff->skb);
1542 rx_buff->skb = NULL;
1543 rx_buff->u.rx.payload = NULL;
1544 };
1545
1546 AWC_ENTRY_EXIT_DEBUG("exit\n");
1547
1548};
1549
1550void
1551awc_802_11_failed_rx_copy(struct net_device * dev,struct awc_fid * rx_buff){
1552 struct awc_private * priv = (struct awc_private * )dev->priv;
1553
1554
1555 AWC_ENTRY_EXIT_DEBUG("awc_802_11_failed_rx_copy");
1556 if (rx_buff->skb)
1557 dev_kfree_skb_irq(rx_buff->skb);
1558 rx_buff->skb = NULL;
1559 rx_buff->u.rx.payload = NULL;
1560 priv->stats.rx_errors++;
1561
1562
1563 AWC_ENTRY_EXIT_DEBUG("exit\n");
1564};
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575int
1576awc_802_11_tx_find_path_and_post(struct net_device * dev,
1577 struct sk_buff * skb){
1578
1579
1580 struct awc_private * priv = (struct awc_private * )dev->priv;
1581 int i;
1582 int len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
1583 struct awc_fid * fid = NULL;
1584
1585 u16 p2p_direct =priv->p2p_found;
1586 struct iphdr * ip_hdr;
1587
1588
1589 AWC_ENTRY_EXIT_DEBUG("awc_802_11_tx_find_path_and_post");
1590
1591
1592 DOWN(&priv->tx_buff_semaphore);
1593 if (len > dev->mtu + 16 ) {
1594 printk(KERN_ERR "%s packet size too large %d \n",dev->name, len);
1595 goto final;
1596 }
1597
1598 if (len + AWC_TX_HEAD_SIZE < AWC_TX_ALLOC_SMALL_SIZE )
1599 fid = awc_fid_queue_pop_head(&priv->tx_small_ready);
1600
1601 if (!fid)
1602 fid = awc_fid_queue_pop_head(&priv->tx_large_ready);
1603
1604 if (!fid) {
1605 DEBUG(32,"%s buffs in use \n",dev->name);
1606 goto no_space;
1607 }
1608
1609
1610
1611
1612
1613
1614 if (!fid) {
1615 DEBUG(32,"%s buffs in use \n",dev->name);
1616 goto no_space;
1617 }
1618
1619 if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE - 14){
1620 printk(KERN_ERR "found too small tx fid size %d, pktlen %d \n",fid->u.tx.fid_size, len);
1621 }
1622 memset(&fid->u.tx.radio_tx, 0,sizeof(struct aironet4500_radio_tx_header));
1623 memset(&fid->u.tx.ieee_802_11, 0,sizeof(struct ieee_802_11_header));
1624 memset(&fid->u.tx.ieee_802_3, 0,sizeof(struct ieee_802_3_header));
1625 fid->u.tx.payload =NULL;
1626 fid->u.tx.gap_length =0;
1627 fid->busy = 1;
1628
1629
1630 priv->tx_buffs_in_use++;
1631 DEBUG(32,"found large buff %x \n",fid->u.tx.fid);
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642 fid->skb = skb;
1643
1644
1645 if (priv->p2p_uc && !priv->p2p_found){
1646
1647 for (i=0; i < 6; i++)
1648 if (priv->p2p[i] != skb->data[i]){
1649 p2p_direct = 1;
1650 break;
1651 }
1652 };
1653
1654 if (priv->force_tx_rate == 2 || priv->force_tx_rate == 4 ||
1655 priv->force_tx_rate== 11 || priv->force_tx_rate == 22){
1656 fid->u.tx.radio_tx.tx_bit_rate = priv->force_tx_rate;
1657 } else if (priv->force_tx_rate != 0 ) {
1658 printk(KERN_ERR "wrong force_tx_rate=%d changed to default \n", priv->force_tx_rate);
1659 priv->force_tx_rate = 0;
1660 };
1661 fid->u.tx.radio_tx.TX_Control =
1662 aironet4500_tx_control_tx_ok_event_enable |
1663 aironet4500_tx_control_tx_fail_event_enable |
1664 aironet4500_tx_control_no_release;
1665
1666 if (len < priv->force_rts_on_shorter){
1667 fid->u.tx.radio_tx.TX_Control |=
1668 aironet4500_tx_control_use_rts;
1669 };
1670
1671 ip_hdr = (struct iphdr * ) ((( char * ) skb->data) + 14);
1672 if (ip_hdr && skb->data[12] == 0x80 ){
1673 if (ip_hdr->tos & IPTOS_RELIABILITY && priv->ip_tos_reliability_rts)
1674 fid->u.tx.radio_tx.TX_Control |=
1675 aironet4500_tx_control_use_rts;
1676 if (ip_hdr->tos & IPTOS_THROUGHPUT && priv->ip_tos_troughput_no_retries)
1677 fid->u.tx.radio_tx.TX_Control |=
1678 aironet4500_tx_control_no_retries;
1679 };
1680
1681 if (priv->p802_11_send || memcmp(dev->dev_addr, skb->data +6, 6) ){
1682 fid->u.tx.radio_tx.TX_Control |=
1683 aironet4500_tx_control_header_type_802_11;
1684 DEBUG(0x200,"%s bridging, forcing 802_11 send \n ",dev->name);
1685 }
1686
1687
1688 if (!priv->p2p_uc || p2p_direct) {
1689 if ((fid->u.tx.radio_tx.TX_Control &
1690 aironet4500_tx_control_header_type_802_11 )){
1691
1692
1693 fid->u.tx.radio_tx.PayloadLength = len -12;
1694 fid->u.tx.ieee_802_3.payload_length = len -12 ;
1695 fid->pkt_len = len -12;
1696 fid->u.tx.payload = skb->data +12;
1697
1698 if (priv->simple_bridge){
1699 memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
1700 memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);
1701 memcpy(fid->u.tx.ieee_802_11.mac3,priv->status.CurrentBssid ,6);
1702 memset(fid->u.tx.ieee_802_11.mac4,0,6);
1703 fid->u.tx.ieee_802_11.frame_control = 0x8;
1704 fid->u.tx.ieee_802_11.gapLen=6;
1705 } else {
1706 memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
1707 memcpy(fid->u.tx.ieee_802_11.mac2,dev->dev_addr,6);
1708 memcpy(fid->u.tx.ieee_802_11.mac3,skb->data +6 ,6);
1709 memset(fid->u.tx.ieee_802_11.mac4,0 ,6);
1710 fid->u.tx.ieee_802_11.frame_control = 0x108;
1711 fid->u.tx.ieee_802_11.gapLen=6;
1712 }
1713 } else {
1714 fid->u.tx.radio_tx.PayloadLength = len -12;
1715 fid->u.tx.ieee_802_3.payload_length = len -12;
1716 fid->pkt_len = len - 12;
1717 fid->u.tx.payload = skb->data +12;
1718 };
1719 memcpy(fid->u.tx.ieee_802_3.dst_mac,skb->data, 12);
1720 DEBUG(0x200,"%s tx simply 802.3 type \n ",dev->name);
1721
1722 } else {
1723 fid->type |= p80211_8021H;
1724 fid->bridge_size = len + sizeof(fid->bridge) ;
1725 fid->bridge.dsap = 0xaa;
1726 fid->bridge.ssap = 0xaa;
1727 fid->bridge.ctrl = 0x03;
1728 fid->bridge.oui[0] = 0x0;
1729 fid->bridge.oui[1] = 0x40;
1730 fid->bridge.oui[2] = 0x96;
1731 fid->bridge.unknown1= 0x0000;
1732 fid->bridge.unknown2= htons((len) & 0x1000);
1733 fid->u.tx.radio_tx.PayloadLength = fid->bridge_size + 2;
1734 fid->u.tx.ieee_802_3.payload_length = fid->u.tx.radio_tx.PayloadLength ;
1735
1736
1737 fid->u.tx.payload = skb->data +12;
1738 if ((fid->u.tx.radio_tx.TX_Control &
1739 aironet4500_tx_control_header_type_802_11 )){
1740
1741 memcpy(fid->u.tx.ieee_802_11.mac1,priv->p2p,6);
1742 memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);
1743 memcpy(fid->u.tx.ieee_802_11.mac3,priv->bssid ,6);
1744 memset(fid->u.tx.ieee_802_11.mac4,0,6);
1745 fid->u.tx.ieee_802_11.gapLen=6;
1746
1747 fid->u.tx.ieee_802_11.frame_control = 0x8;
1748 }
1749 memcpy(fid->u.tx.ieee_802_3.dst_mac,priv->p2p, 6);
1750 memcpy(fid->u.tx.ieee_802_3.src_mac,dev->dev_addr, 6);
1751 fid->u.tx.payload = skb->data + 2 + sizeof(fid->bridge);
1752 fid->pkt_len = len ;
1753
1754 DEBUG(0x200,"%s tx simply 802.1H type \n ",dev->name);
1755
1756 };
1757
1758 priv->stats.tx_bytes += fid->u.tx.ieee_802_3.payload_length;
1759 priv->stats.tx_packets++;
1760
1761
1762 awc_fid_queue_push_tail(&priv->tx_in_transmit,fid);
1763 udelay(1);
1764 awc_transmit_packet(dev,fid);
1765 if (priv->tx_large_ready.size <= 2 || priv->tx_small_ready.size <= 2 ){
1766 if (netif_running(dev))
1767 netif_stop_queue(dev);
1768 } else {
1769 if (netif_running(dev))
1770 netif_wake_queue(dev);
1771 }
1772 UP(&priv->tx_buff_semaphore);
1773 AWC_ENTRY_EXIT_DEBUG("exit\n");
1774 return 0;
1775
1776
1777 no_space:
1778 DEBUG(32,"%s tx buffs not found \n ",dev->name);
1779 #ifdef AWC_DEBUG
1780
1781 #endif
1782 netif_stop_queue (dev);
1783
1784 UP(&priv->tx_buff_semaphore);
1785 AWC_ENTRY_EXIT_DEBUG("NoSpaceExit\n");
1786 return 1 ;
1787 final:
1788 priv->stats.tx_errors++;
1789 UP(&priv->tx_buff_semaphore);
1790 if (!netif_running(dev))
1791 netif_start_queue(dev);
1792 dev_kfree_skb(skb);
1793 AWC_ENTRY_EXIT_DEBUG("BADExit\n");
1794 return -1;
1795
1796};
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806void
1807awc_802_11_after_tx_packet_to_card_write(struct net_device * dev,
1808 struct awc_fid * tx_buff){
1809
1810
1811 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_packet_to_card_write");
1812
1813 if (!tx_buff){
1814 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_tx_packet_to_card_write \n",dev->name);
1815 };
1816
1817 if(tx_buff->skb){
1818 dev_kfree_skb(tx_buff->skb);
1819 tx_buff->skb = NULL;
1820 }
1821
1822 AWC_ENTRY_EXIT_DEBUG("exit\n");
1823};
1824
1825
1826
1827
1828
1829
1830
1831
1832void
1833awc_802_11_after_failed_tx_packet_to_card_write(struct net_device * dev,
1834 struct awc_fid * tx_buff){
1835 struct awc_private * priv = (struct awc_private *)dev->priv;
1836
1837
1838 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_failed_tx_packet_to_card_write");
1839
1840 if (!tx_buff){
1841 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_failed_tx_packet_to_card_write \n",dev->name);
1842 };
1843
1844 if(tx_buff->skb){
1845 dev_kfree_skb(tx_buff->skb);
1846 tx_buff->skb = NULL;
1847 tx_buff->busy =0;
1848 printk(KERN_ERR "%s packet to card write failed \n",dev->name);
1849 }
1850
1851 awc_fid_queue_remove(&priv->tx_in_transmit,tx_buff);
1852
1853 if (tx_buff->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
1854 awc_fid_queue_push_tail(&priv->tx_small_ready,tx_buff);
1855 else
1856 awc_fid_queue_push_tail(&priv->tx_large_ready,tx_buff);
1857
1858 AWC_ENTRY_EXIT_DEBUG("exit\n");
1859
1860};
1861
1862inline void
1863awc_802_11_after_tx_complete(struct net_device * dev, struct awc_fid * tx_buff){
1864
1865 struct awc_private * priv = (struct awc_private *)dev->priv;
1866
1867 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_complete");
1868
1869 DEBUG(32,"tx complete status %x \n ",tx_buff->u.tx.radio_tx.Status);
1870
1871 #ifdef AWC_DEBUG
1872 if (tx_buff->u.tx.radio_tx.Status)
1873 printk("tf%x ",tx_buff->u.tx.radio_tx.Status);
1874 #endif
1875 if (tx_buff->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE){
1876 awc_fid_queue_push_tail(&priv->tx_small_ready,tx_buff);
1877 priv->tx_small_buffs_in_use--;
1878 } else {
1879 awc_fid_queue_push_tail(&priv->tx_large_ready,tx_buff);
1880 priv->tx_buffs_in_use--;
1881 }
1882
1883 tx_buff->busy = 0;
1884
1885
1886 AWC_ENTRY_EXIT_DEBUG("exit\n");
1887};
1888
1889
1890
1891
1892
1893
1894
1895
1896inline int
1897awc_receive_packet(struct net_device * dev){
1898
1899 struct awc_command cmd;
1900 u16 Fid;
1901
1902 struct awc_fid * rx_buff;
1903
1904
1905 struct awc_private * priv ;
1906 int i;
1907
1908 priv= (struct awc_private *)dev->priv;
1909 rx_buff = priv->rx_ready.head ;
1910
1911 AWC_ENTRY_EXIT_DEBUG(" entry awc_receive_packet ");
1912
1913 Fid = awc_Rx_Fid(dev->base_addr);
1914
1915 DEBUG(128," RX FID %x \n",Fid);
1916
1917 if (!Fid){
1918 printk(KERN_CRIT "No RxFid when rx event \n");
1919 return -1;
1920 }
1921
1922
1923
1924 if (!rx_buff){
1925 printk(KERN_CRIT "No rx_buff in rx event \n");
1926 return -1;
1927 }
1928
1929 rx_buff->type = 0;
1930
1931
1932 AWC_INIT_COMMAND(AWC_CLI,cmd,dev,0,0,
1933 Fid, 0, 0x14 , &(rx_buff->u.rx.radio_rx));
1934
1935
1936
1937 AWC_BAP_LOCK_UNDER_CLI(cmd);
1938
1939 if (awc_bap_setup(&cmd)) goto final;
1940 if (awc_bap_read(&cmd)) goto final;
1941
1942 DEBUG(128, "rx receive radio header, length %x \n",rx_buff->u.rx.radio_rx.PayloadLength);
1943
1944 cmd.buff = &(rx_buff->u.rx.ieee_802_11);
1945 cmd.len = 0x20;
1946
1947 if (awc_bap_read(&cmd)) goto final;
1948
1949 DEBUG(128, "rx receive 802_11 header, framecontrol %x \n",rx_buff->u.rx.ieee_802_11.frame_control);
1950
1951 if (rx_buff->u.rx.ieee_802_11.gapLen > 8) {
1952 printk(KERN_ERR "%s: 802.11 gap lenght huge %d \n",dev->name,rx_buff->u.rx.ieee_802_11.gapLen);
1953 goto final;
1954 }
1955 DEBUG(128,"SeqCtl %x, 802_11 macs: ",rx_buff->u.rx.ieee_802_11.SeqCtl);
1956 if (awc_debug & 0x7000){
1957 DEBUG(0x7000, " %s mac1 ",dev->name); for (i = 0; i < 6; i++) DEBUG(0x7000, "%02x:",((unsigned char)rx_buff->u.rx.ieee_802_11.mac1[i] )) ;
1958 DEBUG(0x7000, " %s mac2 ",dev->name); for (i = 0; i < 6; i++) DEBUG(0x7000, "%02x:",((unsigned char)rx_buff->u.rx.ieee_802_11.mac2[i] )) ;
1959 DEBUG(0x7000, " %s mac3 ",dev->name); for (i = 0; i < 6; i++) DEBUG(0x7000, "%02x:",((unsigned char)rx_buff->u.rx.ieee_802_11.mac3[i] )) ;
1960 DEBUG(0x7000, " %s mac4 ",dev->name); for (i = 0; i < 6; i++) DEBUG(0x7000, "%02x:",((unsigned char)rx_buff->u.rx.ieee_802_11.mac4[i] )) ;
1961 }
1962 DEBUG(128,"\n GapLen %d ",rx_buff->u.rx.ieee_802_11.gapLen );
1963
1964 if (rx_buff->u.rx.ieee_802_11.gapLen > 0) {
1965 cmd.buff = rx_buff->u.rx.ieee_802_11.gap;
1966 cmd.len = rx_buff->u.rx.ieee_802_11.gapLen;
1967 if (awc_bap_read(&cmd)) goto final;
1968 DEBUG(128, "rx receive gap header , gap length %x \n",rx_buff->u.rx.gap_length);
1969 }
1970 for (i = 0; i < rx_buff->u.rx.ieee_802_11.gapLen ; i++) DEBUG(128,"%x",((unsigned char)rx_buff->u.rx.ieee_802_11.gap[i] )) ;
1971
1972
1973 if ( !(priv->config.ReceiveMode & RXMODE_DISABLE_802_3_HEADER )
1974 ){
1975 cmd.buff = &(rx_buff->u.rx.ieee_802_3);
1976 cmd.len = 0x10;
1977 rx_buff->type |= p80211_8023;
1978 if (awc_bap_read(&cmd)) goto final;
1979 DEBUG(128, "rx receive 802_3 header, payload length %x \n",rx_buff->u.rx.ieee_802_3.payload_length);
1980 DEBUG(128,"\n 802_3 status %x ",rx_buff->u.rx.ieee_802_3.status );
1981 DEBUG(128," RX payloadLen %x, dst,src: ",rx_buff->u.rx.ieee_802_3.payload_length);
1982 if (awc_debug & 0x7000){
1983 for (i = 0; i < 6; i++) printk("%02x:",((unsigned char)rx_buff->u.rx.ieee_802_3.dst_mac[i] )) ;
1984 for (i = 0; i < 6; i++) printk("%02x:",((unsigned char)rx_buff->u.rx.ieee_802_3.src_mac[i] )) ;
1985 }
1986 };
1987
1988 rx_buff->pkt_len = rx_buff->u.rx.radio_rx.PayloadLength;
1989
1990 if (priv->config.OperatingMode & MODE_LLC_HOST)
1991 rx_buff->type |= p80211_llc_snap;
1992
1993
1994 if (awc_802_11_find_copy_path(dev,rx_buff)) goto final;
1995
1996
1997 if (rx_buff->u.rx.payload ){
1998 cmd.buff = rx_buff->u.rx.payload;
1999 cmd.len = rx_buff->pkt_len;
2000 if (awc_bap_read(&cmd)) goto final;
2001 DEBUG(128, "rx payload read %x \n",rx_buff->u.rx.ieee_802_3.payload_length);
2002 };
2003
2004 AWC_RELEASE_COMMAND(cmd);
2005
2006 DEBUG(128,"\n payload hdr %x ",rx_buff->u.rx.ieee_802_3.status );
2007 if (awc_debug && rx_buff->u.rx.payload)
2008 for (i = 0; i < 20; i++) DEBUG(128,"%x",((unsigned char)rx_buff->u.rx.payload[i] )) ;
2009 DEBUG(128,"%c",'\n');
2010
2011 awc_802_11_router_rx(dev,rx_buff);
2012
2013 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2014 return 0;
2015 final:
2016
2017 awc_802_11_failed_rx_copy(dev,rx_buff);
2018
2019 AWC_RELEASE_COMMAND(cmd);
2020 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2021 return -1; ;
2022
2023};
2024
2025
2026int
2027awc_transmit_packet(struct net_device * dev, struct awc_fid * tx_buff) {
2028
2029 struct awc_command cmd;
2030 u16 size ;
2031
2032 int i;
2033 struct awc_private * priv= (struct awc_private *)dev->priv;
2034
2035 AWC_ENTRY_EXIT_DEBUG(" entry awc_transmit_packet ");
2036
2037 if (priv->link_status_changed ){
2038 priv->link_status_changed =0;
2039 awc_readrid_dir(dev,&priv->rid_dir[7]);
2040 }
2041
2042
2043 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0xB, tx_buff->u.tx.fid,
2044 tx_buff->u.tx.fid, 0, 0x14 , &(tx_buff->u.tx.radio_tx));
2045
2046 AWC_BAP_LOCK_NOT_CLI(cmd);
2047
2048#ifdef AWC_BY_BOOK
2049#warning By books is bad, AWC_BY_BOOK
2050#error cli sti bad here
2051 if ( !(tx_buff->type &(p80211_llc_snap|p80211_8021H) )
2052 && !(tx_buff->u.tx.radio_tx.TX_Control &
2053 aironet4500_tx_control_header_type_802_11 )){
2054
2055 cmd.buff=&(tx_buff->u.tx.radio_tx.TX_Control);
2056 cmd.len = 0x2 ;
2057 cmd.offset = 0x8;
2058 save_flags(flags);
2059 cli();
2060 if (awc_bap_setup(&cmd)) goto final;
2061 if (awc_bap_write(&cmd)) goto final;
2062
2063 cmd.buff=&(tx_buff->u.tx.ieee_802_3.payload_length);
2064 cmd.len = 14;
2065 cmd.offset = 0x36;
2066 if (awc_bap_setup(&cmd)) goto final;
2067 if (awc_bap_write(&cmd)) goto final;
2068 restore_flags(flags);
2069
2070 } else {
2071#endif
2072
2073 if (awc_bap_setup(&cmd)) goto final;
2074 if (awc_bap_write(&cmd)) goto final;
2075
2076 DEBUG(64," wrote radio tx header for fid %x \n",tx_buff->u.tx.fid);
2077
2078
2079 cmd.buff=&(tx_buff->u.tx.ieee_802_11);
2080 cmd.len = 0x20;
2081 if (awc_bap_write(&cmd)) goto final;
2082
2083
2084 if (tx_buff->u.tx.ieee_802_11.gapLen) {
2085 cmd.buff=&(tx_buff->u.tx.ieee_802_11.gap);
2086 cmd.len = tx_buff->u.tx.ieee_802_11.gapLen;
2087 if (awc_bap_write(&cmd)) goto final;
2088 }
2089
2090 if ( ! (tx_buff->u.tx.radio_tx.TX_Control &
2091 aironet4500_tx_control_header_type_802_11 )){
2092
2093 cmd.buff=&(tx_buff->u.tx.ieee_802_3);
2094 if (awc_debug & 0x7000){
2095 printk("%s TX dst ",dev->name);
2096 for (i=0; i < 6; i++) printk ("%02x:",(unsigned char) tx_buff->u.tx.ieee_802_3.dst_mac[i]);
2097 printk(" src ");
2098 for (i=0; i < 6; i++) printk ("%02x:",(unsigned char) tx_buff->u.tx.ieee_802_3.src_mac[i]);
2099 printk(" \n ");
2100 }
2101 cmd.len = 0x10;
2102 if (awc_bap_write(&cmd)) goto final;
2103 };
2104
2105 if (tx_buff->type & p80211_llc_snap) {
2106 cmd.buff= & tx_buff->snap;
2107 cmd.len = sizeof(tx_buff->snap);
2108 if (awc_bap_write(&cmd)) goto final;
2109 };
2110
2111 if (tx_buff->type & p80211_8021H) {
2112 size = htons(tx_buff->bridge_size);
2113
2114 cmd.buff= & size;
2115 cmd.len = 2 ;
2116 if (awc_bap_write(&cmd)) goto final;
2117
2118 cmd.buff= & tx_buff->bridge;
2119 cmd.len = sizeof(tx_buff->bridge);
2120 if (awc_bap_write(&cmd)) goto final;
2121 };
2122
2123#ifdef AWC_BY_BOOK
2124
2125 }
2126#endif
2127 cmd.buff= tx_buff->u.tx.payload;
2128 cmd.len = tx_buff->pkt_len;
2129
2130 if (awc_bap_write(&cmd)) goto final;
2131 AWC_RELEASE_COMMAND(cmd);
2132
2133 if (awc_issue_command_and_block(&cmd)) goto final_unlocked;
2134
2135
2136 tx_buff->transmit_start_time = jiffies;
2137 awc_802_11_after_tx_packet_to_card_write(dev,tx_buff);
2138
2139
2140
2141 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2142 return 0;
2143 final:
2144 awc_802_11_after_failed_tx_packet_to_card_write(dev,tx_buff);
2145 printk(KERN_CRIT "%s awc tx command failed \n",dev->name);
2146 AWC_RELEASE_COMMAND(cmd);
2147 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2148 return -1; ;
2149
2150 final_unlocked:
2151 awc_802_11_after_failed_tx_packet_to_card_write(dev,tx_buff);
2152 printk(KERN_CRIT "%s awc tx command failed \n",dev->name);
2153 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2154 return -1; ;
2155
2156}
2157
2158
2159inline int
2160awc_tx_complete_check(struct net_device * dev){
2161
2162 struct awc_fid * fid;
2163 struct awc_command cmd;
2164
2165
2166 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_complete_check ");
2167
2168
2169
2170 fid = awc_fid_queue_pop_head(&((struct awc_private *)dev->priv)->tx_post_process);
2171
2172 if (!fid) {
2173 printk("awc_tx_complete_check with empty queue \n ");
2174 return -1;
2175 }
2176
2177 DEBUG(64," tx_complete fid %x \n",fid->u.tx.fid);
2178
2179 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0,0, fid->u.tx.fid,
2180 0, 0x14 , &(fid->u.tx.radio_tx));
2181
2182 fid->state |= awc_tx_fid_complete_read;
2183
2184 AWC_BAP_LOCK_NOT_CLI(cmd);
2185 if (awc_bap_setup(&cmd)) goto final;
2186 if (awc_bap_read(&cmd)) goto final;
2187 AWC_RELEASE_COMMAND(cmd);
2188
2189 awc_802_11_after_tx_complete(dev,fid);
2190
2191
2192 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2193 return 0;
2194
2195 final:
2196 awc_802_11_after_tx_complete(dev,fid);
2197 printk(KERN_ERR "%s awc_tx_complete_check failed \n",dev->name);
2198 AWC_RELEASE_COMMAND(cmd);
2199 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2200 return -1; ;
2201}
2202
2203
2204#define AWC_QUEUE_BH {\
2205 if (!priv->bh_active && !priv->bh_running){\
2206 priv->bh_active = 1;\
2207 queue_task(&priv->immediate_bh, &tq_immediate);\
2208 mark_bh(IMMEDIATE_BH);\
2209 }\
2210 }
2211
2212
2213void
2214awc_bh(struct net_device *dev){
2215
2216 struct awc_private * priv = (struct awc_private *)dev->priv;
2217 int active_interrupts;
2218 int enabled_interrupts;
2219
2220 int multi_ints = 0;
2221
2222
2223
2224 DEBUG(8, "awc_bh awoken on jiffie %ld \n",jiffies);
2225
2226 priv->bh_running = 1;
2227
2228 active_interrupts = awc_event_status(dev->base_addr);
2229
2230 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2231
2232 DEBUG(8, "awc_bh active ints %x \n",active_interrupts);
2233
2234 if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
2235
2236
2237 goto bad_end;
2238 }
2239start:
2240 if (active_interrupts == 0xffff){
2241
2242 printk(KERN_CRIT "%s device ejected in interrupt, disabling\n",dev->name);
2243 netif_device_detach (dev);
2244 if (priv->command_semaphore_on){
2245 priv->command_semaphore_on--;
2246 AWC_UNLOCK_COMMAND_ISSUING(priv);
2247 }
2248 priv->tx_chain_active =0;
2249 goto bad_end;
2250
2251 }
2252
2253 if (priv->unlock_command_postponed ){
2254
2255 priv->unlock_command_postponed-- ;
2256 if( priv->command_semaphore_on ){
2257
2258 awc_read_response((&priv->cmd));
2259 priv->async_command_start = 0;
2260 if (priv->command_semaphore_on){
2261
2262 priv->command_semaphore_on--;
2263 AWC_UNLOCK_COMMAND_ISSUING(priv);
2264 }
2265 }
2266 };
2267
2268
2269
2270
2271
2272
2273
2274 while (priv->tx_post_process.size)
2275 if (awc_tx_complete_check(dev)) break;
2276
2277 active_interrupts = awc_event_status(dev->base_addr);
2278
2279 if (priv->command_semaphore_on || priv->tx_post_process.size){
2280 if (multi_ints++ < 10000){
2281 goto start;
2282 }
2283 };
2284 priv->bh_active = 0;
2285 priv->bh_running = 0;
2286
2287 priv->tx_chain_active = 0;
2288
2289
2290
2291 bad_end:
2292
2293
2294
2295 priv->bh_running = 0;
2296 priv->bh_active = 0;
2297 return ;
2298};
2299
2300
2301inline int
2302awc_interrupt_process(struct net_device * dev){
2303
2304 struct awc_private * priv ;
2305 int active_interrupts;
2306 int enabled_interrupts;
2307 u16 tx_status;
2308 int multi_ints = 0;
2309 u16 tx_fid = 0;
2310
2311 struct awc_fid * fid = NULL;
2312
2313
2314
2315
2316
2317
2318 disable_irq(dev->irq);
2319
2320 DEBUG(2," entering interrupt handler %s ",dev->name);
2321
2322 if (!dev) {
2323 printk(KERN_ERR "No dev in interrupt \n");
2324 goto bad_end;
2325 };
2326
2327 priv = (struct awc_private *)dev->priv;
2328
2329 if (!priv) {
2330 printk(KERN_ERR "No PRIV in interrupt \n");
2331 goto bad_end;
2332 };
2333
2334
2335 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2336 active_interrupts = awc_event_status(dev->base_addr);
2337
2338 DEBUG(2,"entry: processing interrupts waiting %x \n",priv->waiting_interrupts);
2339 DEBUG(2,"entry: processing interrupts active %x \n",active_interrupts);
2340 DEBUG(2,"entry: processing interrupts enabled %x \n",enabled_interrupts);
2341
2342
2343
2344 priv->interrupt_count++;
2345 if (priv->interrupt_count > 1 )
2346 printk(" interrupt count on\n ");
2347
2348
2349
2350 if (priv->waiting_interrupts & active_interrupts)
2351 printk(KERN_ERR "double interrupt waiting %x active %x \n",
2352 priv->waiting_interrupts, active_interrupts);
2353
2354
2355
2356
2357
2358
2359
2360start:
2361 DEBUG(2,"Start processing int, times %d\n",multi_ints);
2362
2363 if (active_interrupts == 0xffff){
2364
2365 printk(KERN_CRIT "%s device ejected, got interrupt, disabling\n",dev->name);
2366
2367 netif_device_detach (dev);
2368 priv->ejected = 1;
2369 if (priv->bh_active || priv->bh_running){
2370 priv->interrupt_count--;
2371 goto bad_end;
2372 } else if (priv->command_semaphore_on){
2373
2374 printk(KERN_ERR "ejected, last BH fired \n");
2375
2376 AWC_QUEUE_BH;
2377 }
2378 priv->interrupt_count--;
2379 goto bad_end;
2380 }
2381
2382
2383
2384 if (active_interrupts & 0x100 ){
2385 awc_event_ack_Awaken(dev->base_addr);
2386 udelay(10);
2387 DEBUG(1,"%s device awoke \n",dev->name);
2388 priv->waiting_interrupts &= ~0x100;
2389 };
2390 if (active_interrupts & 0x80 ){
2391
2392 priv->link_status = awc_Link_Status(dev->base_addr);
2393 DEBUG(1,"link status changed %x \n",priv->link_status);
2394 awc_event_ack_Link(dev->base_addr);
2395 priv->waiting_interrupts &= ~0x80;
2396 if(priv->link_status == 0x400)
2397 printk(KERN_INFO "%s Associated\n",dev->name );
2398 else {
2399 printk(KERN_INFO "%s Link status change : %s \n",dev->name, awc_print_string(awc_link_status_names, priv->link_status) );
2400 if ( priv->link_status & 0x8100 ||
2401 priv->link_status & 0x0100 ||
2402 priv->link_status & 0x8200 ||
2403 priv->link_status & 0x8400 ||
2404 priv->link_status & 0x0300 )
2405 printk(KERN_INFO "%s Link status change reason : %s \n",dev->name, awc_print_string(awc_link_failure_reason_names, priv->link_status & 0xff) );
2406
2407 }
2408 };
2409
2410
2411 if (active_interrupts & 0x10 & enabled_interrupts ){
2412
2413
2414
2415 awc_event_ack_Cmd(priv->cmd.port);
2416
2417 if ( priv->enabled_interrupts & 0x10)
2418 priv->enabled_interrupts &= ~0x10;
2419
2420 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2421
2422 if (enabled_interrupts & 0x10){
2423 awc_ints_enable(dev->base_addr, enabled_interrupts & ~0x10);
2424 }
2425
2426 if (priv->command_semaphore_on){
2427 priv->unlock_command_postponed++;
2428
2429 AWC_QUEUE_BH;
2430 }
2431 }
2432
2433 if ((active_interrupts & 0x10) && !(0x10 & enabled_interrupts) ){
2434
2435
2436
2437
2438 }
2439
2440
2441
2442
2443 tx_status = active_interrupts & 0x6 ;
2444
2445
2446
2447 if (tx_status) {
2448
2449 tx_fid = awc_Tx_Compl_Fid(dev->base_addr);
2450 if (!tx_fid){
2451 udelay(10);
2452 tx_fid = awc_Tx_Compl_Fid(dev->base_addr);
2453 }
2454 if (!tx_fid)
2455 printk(KERN_ERR "No tx fid when tx int active\n");
2456
2457 fid = awc_tx_fid_lookup_and_remove(dev, tx_fid);
2458
2459 if (fid) {
2460 if (priv->process_tx_results) {
2461 awc_fid_queue_push_tail(&priv->tx_post_process,fid);
2462 AWC_QUEUE_BH;
2463 }else {
2464 if (fid->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
2465 awc_fid_queue_push_tail(&priv->tx_small_ready,fid);
2466 else
2467 awc_fid_queue_push_tail(&priv->tx_large_ready,fid);
2468 netif_wake_queue (dev);
2469 }
2470 } else
2471 printk(KERN_ERR "awc fid %x not found\n",tx_fid);
2472
2473
2474 if (tx_status & 2){
2475 awc_event_ack_Tx(dev->base_addr);
2476 priv->stats.tx_packets++;
2477 priv->waiting_interrupts &= ~0x2;
2478 }
2479 if (tx_status & 4){
2480 priv->stats.tx_errors++;
2481 awc_event_ack_TxExc(dev->base_addr);
2482 priv->waiting_interrupts &= ~0x4;
2483 }
2484 if ((tx_status&6) == 6)
2485 printk(KERN_NOTICE "%s: both tx and txExc up\n",dev->name);
2486
2487
2488 }
2489
2490
2491
2492 if ( active_interrupts & 0x1 ){
2493 awc_receive_packet(dev);
2494 awc_event_ack_Rx(dev->base_addr);
2495 priv->waiting_interrupts &= ~0x1;
2496 }
2497
2498 active_interrupts = awc_event_status(dev->base_addr);
2499
2500 if ((active_interrupts & 0x7) &&
2501 !priv->bh_active &&
2502 !priv->bh_running ){
2503 if (multi_ints++ < 5)
2504 goto start;
2505 }
2506 if (multi_ints >=5 )
2507 printk(KERN_ERR "%s multi_ints > 5 interrupts still active %x\n",dev->name,active_interrupts);
2508
2509
2510 priv->interrupt_count--;
2511
2512 awc_ints_enable(dev->base_addr, 0x0000);
2513
2514
2515 DEBUG(0x8, " enabling ints in interrupt_process %x \n",
2516 priv->enabled_interrupts & ~priv->waiting_interrupts);
2517
2518
2519
2520 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2521
2522 awc_ints_enable(dev->base_addr,
2523 priv->enabled_interrupts);
2524
2525
2526
2527 enable_irq(dev->irq);
2528
2529
2530 return 0;
2531
2532bad_end:
2533 AWC_ENTRY_EXIT_DEBUG(" bad_end exit \n");
2534 enable_irq(dev->irq);
2535
2536 return -1;
2537
2538
2539};
2540
2541static const char *aironet4500_core_version =
2542"aironet4500.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
2543
2544struct net_device * aironet4500_devices[MAX_AWCS];
2545
2546int awc_debug;
2547static int p802_11_send;
2548
2549static int awc_process_tx_results;
2550int tx_queue_len = 10;
2551int tx_rate;
2552int channel = 5;
2553
2554int max_mtu = 2312;
2555int adhoc;
2556int large_buff_mem = 1700 * 10;
2557int small_buff_no = 20;
2558int awc_full_stats;
2559char SSID[33];
2560int master;
2561int slave;
2562int awc_simple_bridge;
2563
2564
2565#if LINUX_VERSION_CODE >= 0x20100
2566
2567MODULE_PARM(awc_debug,"i");
2568MODULE_PARM(tx_rate,"i");
2569MODULE_PARM(channel,"i");
2570
2571MODULE_PARM(adhoc,"i");
2572MODULE_PARM(master,"i");
2573MODULE_PARM(slave,"i");
2574MODULE_PARM(awc_simple_bridge,"i");
2575MODULE_PARM(max_mtu,"i");
2576MODULE_PARM(large_buff_mem,"i");
2577MODULE_PARM(small_buff_no,"i");
2578MODULE_PARM(SSID,"c33");
2579MODULE_PARM_DESC(awc_debug,"Aironet debug mask");
2580MODULE_PARM_DESC(channel,"Aironet ");
2581MODULE_PARM_DESC(adhoc,"Aironet Access Points not available (0-1)");
2582MODULE_PARM_DESC(master,"Aironet is Adhoc master (creates network sync) (0-1)");
2583MODULE_PARM_DESC(slave,"Aironet is Adhoc slave (0-1)");
2584MODULE_PARM_DESC(max_mtu,"Aironet MTU limit (256-2312)");
2585#endif
2586MODULE_LICENSE("GPL");
2587
2588
2589
2590
2591
2592EXPORT_SYMBOL(awc_init);
2593EXPORT_SYMBOL(awc_open);
2594EXPORT_SYMBOL(awc_close);
2595EXPORT_SYMBOL(awc_reset);
2596EXPORT_SYMBOL(awc_config);
2597
2598EXPORT_SYMBOL(aironet4500_devices);
2599EXPORT_SYMBOL(awc_debug);
2600
2601
2602EXPORT_SYMBOL(awc_private_init);
2603EXPORT_SYMBOL(awc_tx_timeout);
2604EXPORT_SYMBOL(awc_start_xmit);
2605EXPORT_SYMBOL(awc_interrupt);
2606EXPORT_SYMBOL(awc_get_stats);
2607EXPORT_SYMBOL(awc_change_mtu);
2608EXPORT_SYMBOL(awc_set_multicast_list);
2609
2610EXPORT_SYMBOL(awc_proc_set_fun);
2611EXPORT_SYMBOL(awc_proc_unset_fun);
2612EXPORT_SYMBOL(awc_register_proc);
2613EXPORT_SYMBOL(awc_unregister_proc);
2614
2615
2616
2617
2618
2619 void awc_reset(struct net_device *dev)
2620{
2621
2622 long long jiff;
2623
2624 DEBUG(2, " awc_reset dev %p \n", dev);
2625 DEBUG(2, "%s: awc_reset \n", dev->name);
2626
2627 awc_issue_soft_reset(dev);
2628
2629 jiff = jiffies;
2630 udelay(1000);
2631 while (awc_command_read(dev->base_addr)){
2632 udelay(1000);
2633 if (jiffies - jiff > 5*HZ){
2634 printk(KERN_CRIT "%s bad reset\n",dev->name);
2635 break;
2636 }
2637 };
2638
2639}
2640
2641 int awc_config(struct net_device *dev)
2642{
2643
2644
2645 DEBUG(2, "%s: awc_config \n", dev->name);
2646
2647
2648 if( awc_disable_MAC(dev)) goto final;
2649 udelay(100);
2650 if( awc_write_all_rids(dev) ) goto final;
2651 udelay(100);
2652 if( awc_enable_MAC(dev)) goto final;
2653
2654 return 0;
2655 final:
2656 return -1;
2657}
2658
2659
2660char name[] = "ElmerLinux";
2661
2662 int awc_init(struct net_device *dev){
2663 struct awc_private *priv = (struct awc_private *)dev->priv;
2664 int i;
2665 const char * radioType;
2666
2667 DEBUG(2, "%s: awc_init \n", dev->name);
2668
2669
2670
2671
2672#ifdef CONFIG_SMP
2673 both_bap_lock = 1;
2674 bap_setup_spinlock = 1;
2675#endif
2676
2677
2678 if (adhoc & !max_mtu)
2679 max_mtu= 2250;
2680 else if (!max_mtu)
2681 max_mtu= 1500;
2682
2683 priv->sleeping_bap = 1;
2684
2685
2686 priv->enabled_interrupts = awc_ints_enabled(dev->base_addr);
2687
2688 if( awc_issue_noop(dev) ) goto final;
2689
2690 awc_ints_enable(dev->base_addr,0);
2691
2692 if( awc_disable_MAC(dev) ) goto final;
2693
2694
2695
2696 i=0;
2697 while ( i < AWC_NOF_RIDS){
2698 if (awc_rids_temp[i].selector)
2699 memcpy(&priv->rid_dir[i],&awc_rids_temp[i],sizeof(priv->rid_dir[0]) );
2700 else priv->rid_dir[i].selector = NULL;
2701 i++;
2702 }
2703
2704
2705 priv->rid_dir[0].buff = &priv->config;
2706 priv->rid_dir[1].buff = &priv->SSIDs;
2707 priv->rid_dir[2].buff = &priv->fixed_APs;
2708 priv->rid_dir[3].buff = &priv->driver_name;
2709 priv->rid_dir[4].buff = &priv->enc_trans;
2710 priv->rid_dir[5].buff = &priv->general_config;
2711 priv->rid_dir[6].buff = &priv->capabilities;
2712 priv->rid_dir[7].buff = &priv->status;
2713 priv->rid_dir[8].buff = &priv->AP;
2714 priv->rid_dir[9].buff = &priv->statistics;
2715 priv->rid_dir[10].buff = &priv->statistics_delta;
2716 priv->rid_dir[11].buff = &priv->statistics_delta_clear;
2717 priv->rid_dir[12].buff = &priv->wep_volatile;
2718 priv->rid_dir[13].buff = &priv->wep_nonvolatile;
2719 priv->rid_dir[14].buff = &priv->modulation;
2720
2721 priv->rid_dir[15].buff = &priv->statistics16;
2722 priv->rid_dir[16].buff = &priv->statistics16_delta;
2723 priv->rid_dir[17].buff = &priv->statistics16_delta_clear;
2724
2725 priv->rid_dir[0].bufflen = sizeof(priv->config);
2726 priv->rid_dir[1].bufflen = sizeof(priv->SSIDs);
2727 priv->rid_dir[2].bufflen = sizeof(priv->fixed_APs);
2728 priv->rid_dir[3].bufflen = sizeof(priv->driver_name);
2729 priv->rid_dir[4].bufflen = sizeof(priv->enc_trans);
2730 priv->rid_dir[5].bufflen = sizeof(priv->general_config);
2731 priv->rid_dir[6].bufflen = sizeof(priv->capabilities);
2732 priv->rid_dir[7].bufflen = sizeof(priv->status);
2733 priv->rid_dir[8].bufflen = sizeof(priv->AP);
2734 priv->rid_dir[9].bufflen = sizeof(priv->statistics);
2735 priv->rid_dir[10].bufflen = sizeof(priv->statistics_delta);
2736 priv->rid_dir[11].bufflen = sizeof(priv->statistics_delta_clear);
2737 priv->rid_dir[12].bufflen = sizeof(priv->wep_volatile);
2738 priv->rid_dir[13].bufflen = sizeof(priv->wep_nonvolatile);
2739 priv->rid_dir[14].bufflen = sizeof(priv->modulation);
2740
2741 priv->rid_dir[15].bufflen = sizeof(priv->statistics16);
2742 priv->rid_dir[16].bufflen = sizeof(priv->statistics16_delta);
2743 priv->rid_dir[17].bufflen = sizeof(priv->statistics16_delta_clear);
2744
2745
2746 if( awc_read_all_rids(dev) ) goto final;
2747
2748
2749 priv->config.OperatingMode = 0;
2750 DEBUG(1,"ReceiveMode %x \n",priv->config.ReceiveMode);
2751
2752
2753 if (!adhoc)
2754 priv->config.OperatingMode = MODE_STA_ESS;
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765 priv->config.Channel = channel;
2766 if (adhoc && master){
2767 priv->config.JoinNetTimeout = 0x1;
2768 } else if (adhoc && slave){
2769
2770
2771 priv->config.JoinNetTimeout = 0x7fff;
2772 };
2773
2774 priv->config.Stationary =1;
2775
2776
2777 priv->config.FragmentThreshold = 1700;
2778 priv->config.RtsThreshold = 1700;
2779 memcpy(priv->config.NodeName, name, 10);
2780
2781 DEBUG(1,"%s supported Rates \n",dev->name);
2782 for (i=0; i< 8; i++)
2783 DEBUG(1,"%x ",priv->capabilities.SupportedRates[i]);
2784 DEBUG(1,"%c",'\n');
2785 DEBUG(1,"%s default Rates \n",dev->name);
2786 for (i=0; i< 8; i++)
2787 DEBUG(1,"%x ",priv->config.Rates[i]);
2788 DEBUG(1,"%c",'\n');
2789
2790
2791
2792 memset(&priv->SSIDs,0,sizeof(priv->SSIDs));
2793
2794 spin_lock_init(&priv->queues_lock);
2795 priv->SSIDs.ridLen =0;
2796 if (!SSID) {
2797 priv->SSIDs.SSID[0].SSID[0] ='a';
2798 priv->SSIDs.SSID[0].SSID[1] ='b';
2799 priv->SSIDs.SSID[0].SSID[2] ='c';
2800 priv->SSIDs.SSID[0].lenght =3;
2801 } else {
2802 int sidlen = strlen(SSID);
2803 memcpy(priv->SSIDs.SSID[0].SSID,SSID,sidlen);
2804 priv->SSIDs.SSID[0].lenght = sidlen;
2805 };
2806
2807 priv->SSIDs.SSID[1].lenght =0;
2808 priv->SSIDs.SSID[1].SSID[0] =0;
2809 priv->SSIDs.SSID[1].SSID[1] =0;
2810 priv->SSIDs.SSID[2].lenght =0;
2811 priv->SSIDs.SSID[2].SSID[0] =0;
2812 priv->SSIDs.SSID[2].SSID[1] =0;
2813
2814
2815
2816
2817
2818 memcpy( priv->config.StationMacAddress,
2819 priv->capabilities.FactoryAddress, 6 );
2820
2821 memcpy(dev->dev_addr, priv->config.StationMacAddress, 6);
2822
2823 DEBUG(2, "%s: awc_init success \n", dev->name);
2824
2825 if (priv->capabilities.RadioType == 1) radioType = "802.11 Frequency Hoping";
2826 else if (priv->capabilities.RadioType == 2) radioType = "802.11 Direct Sequence";
2827 else if (priv->capabilities.RadioType == 4) radioType = "LM2000";
2828 else radioType = "Multiple Radio Types";
2829
2830 printk("%s: %s %s found @ 0x%lx irq %d firmwareVersion %d \n",dev->name,
2831 priv->capabilities.ProductName,radioType,
2832 dev->base_addr,dev->irq,
2833 priv->capabilities.SoftwareVersion);
2834
2835 return 0;
2836 final:
2837 printk(KERN_ERR "aironet init failed \n");
2838 return -ENODEV;
2839
2840 };
2841
2842int awc_private_init(struct net_device * dev){
2843 struct awc_private * priv = (struct awc_private *) dev->priv;
2844 int i = 0;
2845
2846 DEBUG(2, "%s: awc_private_init \n", dev->name);
2847
2848
2849 memset(priv, 0, sizeof(struct awc_private));
2850
2851 spin_lock_init(&priv->queues_lock);
2852
2853 priv->bap0.select = dev->base_addr + awc_Select0_register;
2854 priv->bap0.offset = dev->base_addr + awc_Offset0_register;
2855 priv->bap0.data = dev->base_addr + awc_Data0_register;
2856 priv->bap0.lock = 0;
2857 priv->bap0.status = 0;
2858 spin_lock_init(&priv->bap0.spinlock);
2859 init_MUTEX(&priv->bap0.sem);
2860 priv->bap1.select = dev->base_addr + awc_Select1_register;
2861 priv->bap1.offset = dev->base_addr + awc_Offset1_register;
2862 priv->bap1.data = dev->base_addr + awc_Data1_register;
2863 priv->bap1.lock = 0;
2864 priv->bap1.status = 0;
2865 spin_lock_init(&priv->bap1.spinlock);
2866 init_MUTEX(&priv->bap1.sem);
2867 priv->sleeping_bap = 1;
2868
2869
2870 spin_lock_init(&priv->command_issuing_spinlock);
2871 spin_lock_init(&priv->both_bap_spinlock);
2872 spin_lock_init(&priv->bap_setup_spinlock);
2873 spin_lock_init(&priv->interrupt_spinlock);
2874
2875 priv->command_semaphore_on = 0;
2876 priv->unlock_command_postponed = 0;
2877 INIT_LIST_HEAD(&priv->immediate_bh.list);
2878 priv->immediate_bh.sync = 0;
2879 priv->immediate_bh.routine = (void *)(void *)awc_bh;
2880 priv->immediate_bh.data = dev;
2881 priv->bh_running = 0;
2882 priv->bh_active = 0;
2883 priv->tx_chain_active = 0;
2884 priv->enabled_interrupts= 0x00;
2885 priv->waiting_interrupts= 0x00;
2886
2887
2888 init_MUTEX(&priv->tx_buff_semaphore);
2889 priv->tx_buffs_in_use = 0;
2890 priv->tx_small_buffs_in_use = 0;
2891 priv->mac_enabled =0;
2892 priv->link_status =0;
2893 priv->large_buff_mem = large_buff_mem;
2894 if (priv->large_buff_mem < max_mtu + AWC_TX_HEAD_SIZE + 10 )
2895 priv->large_buff_mem = max_mtu + AWC_TX_HEAD_SIZE + 10;
2896 priv->small_buff_no = small_buff_no;
2897 if (priv->small_buff_no < 1 )
2898 priv->small_buff_no = 1 ;
2899
2900 priv->process_tx_results = awc_process_tx_results;
2901
2902
2903
2904 for (i=0; i< 6 ; i++ ) {
2905 priv->p2p[i] = 0xff;
2906 priv->bssid[i] =0;
2907 }
2908
2909 priv->p2p_found =0;
2910
2911 priv->p802_11_send =p802_11_send;
2912 priv->full_stats = awc_full_stats;
2913 priv->simple_bridge = awc_simple_bridge;
2914 priv->force_rts_on_shorter = 0;
2915 priv->force_tx_rate = tx_rate;
2916 priv->ip_tos_reliability_rts = 0;
2917 priv->ip_tos_troughput_no_retries = 0 ;
2918
2919 priv->ejected =0;
2920 priv->interrupt_count =0;
2921
2922 return 0;
2923
2924};
2925
2926
2927
2928
2929 int awc_open(struct net_device *dev)
2930{
2931 struct awc_private *priv = (struct awc_private *)dev->priv;
2932
2933
2934
2935 DEBUG(2, "%s: awc_open \n", dev->name);
2936
2937 if( awc_queues_init(dev) ) goto final;
2938 if( awc_config(dev) ) goto final;
2939
2940 memcpy(dev->dev_addr, priv->config.StationMacAddress, 6);
2941
2942 priv->enabled_interrupts = 0x87;
2943 awc_ints_enable(dev->base_addr,priv->enabled_interrupts);
2944
2945
2946
2947 DEBUG(2, "%s: opened \n", dev->name);
2948
2949 priv->sleeping_bap = 0;
2950
2951
2952 MOD_INC_USE_COUNT;
2953
2954
2955 netif_start_queue (dev);
2956 return 0;
2957
2958 final:
2959 netif_device_detach (dev);
2960 printk(KERN_ERR "aironet open failed \n");
2961 return -1;
2962}
2963
2964
2965 int awc_close(struct net_device *dev)
2966{
2967 struct awc_private * priv = (struct awc_private *) dev->priv;
2968
2969 DEBUG(2, "%s: closing device.\n", dev->name);
2970
2971 netif_stop_queue (dev);
2972
2973 awc_disable_MAC(dev);
2974 awc_queues_destroy(dev);
2975
2976 awc_reset(dev);
2977
2978 mdelay(10);
2979
2980 AWC_LOCK_COMMAND_ISSUING(priv);
2981
2982 MOD_DEC_USE_COUNT;
2983
2984 AWC_UNLOCK_COMMAND_ISSUING(priv);
2985
2986 return 0;
2987}
2988
2989
2990
2991
2992
2993
2994
2995void awc_tx_timeout (struct net_device *dev)
2996{
2997 struct awc_private *priv = (struct awc_private *) dev->priv;
2998 struct awc_fid * fid;
2999 int cnt;
3000 unsigned long flags;
3001
3002 DEBUG (2, "%s: awc_tx_timeout \n", dev->name);
3003
3004 printk (KERN_NOTICE "%s: Transmit timed out , buffs %d %d, queues tx %d pp %d lrg %d sm %d \n ",
3005 dev->name, priv->tx_small_buffs_total, priv->tx_buffs_total,
3006 priv->tx_in_transmit.size, priv->tx_post_process.size,
3007 priv->tx_large_ready.size, priv->tx_small_ready.size);
3008 priv->stats.tx_errors++;
3009
3010 save_flags(flags);
3011 cli();
3012 fid = priv->tx_in_transmit.head;
3013 cnt = 0;
3014 while (fid) {
3015 if (jiffies - fid->transmit_start_time > (HZ)) {
3016
3017
3018 awc_fid_queue_remove (&priv->tx_in_transmit, fid);
3019 if (fid->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
3020 awc_fid_queue_push_tail (&priv->tx_small_ready, fid);
3021 else
3022 awc_fid_queue_push_tail (&priv->tx_large_ready, fid);
3023 }
3024 fid = fid->next;
3025 if (cnt++ > 200) {
3026 printk ("bbb in awc_fid_queue\n");
3027 restore_flags(flags);
3028 return;
3029 };
3030
3031 }
3032 restore_flags(flags);
3033 dev->trans_start = jiffies;
3034 netif_wake_queue (dev);
3035}
3036
3037
3038long long last_tx_q_hack;
3039int direction = 1;
3040
3041int awc_start_xmit(struct sk_buff *skb, struct net_device *dev) {
3042
3043 struct awc_private *priv = (struct awc_private *)dev->priv;
3044 int retval = 0;
3045
3046
3047 DEBUG(2, "%s: awc_start_xmit \n", dev->name);
3048
3049
3050 if (!dev) {
3051 DEBUG(1, " xmit dev=NULL, jiffie %ld \n",jiffies);
3052 return -1;
3053 };
3054
3055 if (!skb) {
3056 DEBUG(1, " xmit skb=NULL, jiffie %ld \n",jiffies);
3057 return -1;
3058 };
3059
3060
3061
3062
3063
3064
3065 dev->trans_start = jiffies;
3066 retval = awc_802_11_tx_find_path_and_post(dev,skb);
3067 priv->tx_chain_active = 0;
3068
3069
3070
3071 return retval;
3072}
3073
3074void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3075{
3076 struct net_device *dev = dev_id;
3077 struct awc_private *priv;
3078 unsigned long flags;
3079
3080
3081
3082 priv = (struct awc_private *)dev->priv;
3083
3084
3085
3086
3087 DEBUG(2, "%s: awc_interrupt \n", dev->name);
3088 spin_lock_irqsave(&priv->interrupt_spinlock, flags);
3089
3090 awc_interrupt_process(dev);
3091
3092 spin_unlock_irqrestore(&priv->interrupt_spinlock, flags);
3093}
3094
3095
3096
3097
3098
3099
3100
3101 struct net_device_stats *awc_get_stats(struct net_device *dev)
3102{
3103 struct awc_private *priv = (struct awc_private *)dev->priv;
3104
3105
3106
3107
3108 DEBUG(2, "%s: awc_get_stats \n", dev->name);
3109
3110 if (!netif_running(dev)) {
3111 return 0;
3112 }
3113
3114
3115 if (awc_full_stats)
3116 awc_readrid_dir(dev, &priv->rid_dir[9]);
3117
3118
3119
3120 if (awc_full_stats){
3121 priv->stats.rx_bytes = priv->statistics.HostRxBytes;
3122 priv->stats.tx_bytes = priv->statistics.HostTxBytes;
3123 priv->stats.rx_fifo_errors = priv->statistics.RxOverrunErr ;
3124 priv->stats.rx_crc_errors = priv->statistics.RxPlcpCrcErr + priv->statistics.RxMacCrcErr ;
3125 priv->stats.rx_frame_errors = priv->statistics.RxPlcpFormat ;
3126 priv->stats.rx_length_errors = priv->statistics.RxPlcpLength ;
3127 priv->stats.rx_missed_errors = priv->statistics.RxAged ;
3128 priv->stats.rx_over_errors = priv->statistics.RxOverrunErr ;
3129
3130 priv->stats.collisions = priv->statistics.TxSinColl;
3131 priv->stats.tx_aborted_errors = priv->statistics.TxAged ;
3132 priv->stats.tx_fifo_errors = priv->statistics.HostTxFail ;
3133 priv->stats.tx_window_errors = priv->statistics.TxMulColl ;
3134 priv->stats.tx_heartbeat_errors = priv->statistics.DefersProt +priv->statistics.DefersEngy ;
3135 priv->stats.tx_carrier_errors = priv->statistics.RetryLong +priv->statistics.RetryShort ;
3136 priv->stats.multicast = priv->statistics.HostRxMc;
3137 }
3138
3139
3140
3141 return &(priv->stats);
3142}
3143
3144
3145int awc_change_mtu(struct net_device *dev, int new_mtu){
3146
3147
3148 unsigned long flags;
3149
3150 if ((new_mtu < 256 ) || (new_mtu > 2312) || (max_mtu && new_mtu > max_mtu) )
3151 return -EINVAL;
3152
3153 if (netif_running(dev)) {
3154 printk("PLEASE, ifconfig %s down for mtu change\n",dev->name);
3155
3156 };
3157 if (dev->mtu != new_mtu) {
3158 save_flags(flags);
3159 cli();
3160 netif_stop_queue(dev);
3161 awc_disable_MAC(dev);
3162 restore_flags(flags);
3163
3164 awc_tx_dealloc(dev);
3165 dev->mtu = new_mtu;
3166 awc_tx_alloc(dev);
3167 awc_enable_MAC(dev);
3168 netif_start_queue(dev);
3169
3170 printk("%s mtu has been changed to %d \n ",dev->name,dev->mtu);
3171
3172 }
3173
3174 return 0;
3175
3176};
3177
3178
3179 void
3180awc_set_multicast_list(struct net_device *dev) {
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192}
3193
3194
3195
3196int (* awc_proc_set_fun) (int);
3197int (* awc_proc_unset_fun) (int);
3198
3199
3200int awc_register_proc(int (*awc_proc_set_device)(int),int (*awc_proc_unset_device)(int)){
3201
3202 AWC_ENTRY_EXIT_DEBUG("awc_register_proc");
3203 awc_proc_set_fun = awc_proc_set_device;
3204 awc_proc_unset_fun = awc_proc_unset_device;
3205 AWC_ENTRY_EXIT_DEBUG("exit");
3206 return 0;
3207};
3208
3209int awc_unregister_proc(void){
3210
3211 AWC_ENTRY_EXIT_DEBUG("awc_unregister_proc");
3212
3213 awc_proc_set_fun = NULL;
3214 awc_proc_unset_fun = NULL;
3215 AWC_ENTRY_EXIT_DEBUG("exit");
3216 return 0;
3217};
3218
3219static int aironet_core_init(void)
3220{
3221
3222
3223
3224 printk(KERN_INFO"%s", aironet4500_core_version);
3225 return 0;
3226
3227
3228}
3229
3230static void aironet_core_exit(void)
3231{
3232 printk(KERN_INFO "aironet4500 unloading core module \n");
3233
3234}
3235
3236module_init(aironet_core_init);
3237module_exit(aironet_core_exit);
3238
3239