2 * Aironet 4500/4800 driver core
4 * Elmer Joandi, Januar 1999
8 * Revision 0.1 ,started 30.12.1998
13 march 99, stable version 2.0
14 august 99, stable version 2.2
15 november 99, integration with 2.3
16 17.12.99: finally, got SMP near-correct.
17 timing issues remain- on SMP box its 15% slower on tcp
20 #include <linux/module.h>
21 #include <linux/config.h>
22 #include <linux/kernel.h>
23 #include <linux/netdevice.h>
24 #include <linux/etherdevice.h>
25 #include <linux/skbuff.h>
26 #include <linux/if_arp.h>
27 #include <linux/ioport.h>
30 #include <asm/bitops.h>
31 #include <asm/system.h>
32 #include <asm/byteorder.h>
34 #include <linux/time.h>
35 #include <linux/sched.h>
36 #include <linux/delay.h>
37 #include "aironet4500.h"
41 int bap_sleep_after_setup
= 1;
42 int sleep_before_command
= 1;
43 int bap_sleep_before_write
= 1;
44 int sleep_in_command
= 1;
45 int both_bap_lock
=0; /* activated at awc_init in this */
46 int bap_setup_spinlock
=0; /* file if numcpu >1 */
48 EXPORT_SYMBOL(bap_sleep
);
49 EXPORT_SYMBOL(bap_sleep_after_setup
);
50 EXPORT_SYMBOL(sleep_before_command
);
51 EXPORT_SYMBOL(bap_sleep_before_write
);
52 EXPORT_SYMBOL(sleep_in_command
);
53 EXPORT_SYMBOL(both_bap_lock
);
54 EXPORT_SYMBOL(bap_setup_spinlock
);
56 struct awc_strings awc_status_error_codes
[]=awc_reply_error_strings
;
57 struct awc_strings awc_command_names
[]=awc_command_name_strings
;
58 struct awc_strings awc_link_status_names
[]=awc_link_status_strings
;
59 struct awc_strings awc_rid_names
[]=aironet4500_RID_Select_strings
;
60 struct awc_strings awc_link_failure_reason_names
[]=IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS
;
62 const char * awc_print_string( struct awc_strings
* strings
, int code
){
64 struct awc_strings
* str
= strings
;
66 while (str
[i
].string
!= NULL
){
67 if (str
[i
].par
== (code
& str
[i
].mask
)){
75 int awc_dump_registers(struct NET_DEVICE
* dev
){
80 int status
= inw(dev
->base_addr
+4*2);
81 int r1
= inw(dev
->base_addr
+5*2);
82 int r2
= inw(dev
->base_addr
+6*2);
83 int r3
= inw(dev
->base_addr
+7*2);
85 printk(KERN_ERR
"Command %s , result: %s, at memblk %x(RID %s) , offset %x \n",
86 awc_print_string(awc_command_names
,status
),
87 awc_print_string(awc_status_error_codes
,r1
),
88 r2
, awc_print_string(awc_rid_names
,r2
),
92 printk(KERN_ERR
"%s aironet register dump ",dev
->name
);
95 for (i
=0; i
< 32; i
++){
96 printk("%4x ", inw(dev
->base_addr
+ i
*2 ) );
99 printk(KERN_ERR
"%02x",(i
+1)*2);
102 printk(KERN_ERR
" \n");
107 /****************************** COMMAND ******************/
111 int awc_command_busy_clear_wait(struct NET_DEVICE
* dev
){
112 // long long jiff = jiffies;
113 u16 active_interrupts
;
116 AWC_ENTRY_EXIT_DEBUG(" entry awc_command_busy_clear_wait ");
118 while (awc_command_busy(dev
->base_addr
)){
120 printk(KERN_ERR
"awc command busy too long, clearing\n");
121 awc_dump_registers(dev
);
122 awc_event_ack_ClrStckCmdBsy(dev
->base_addr
);
125 if (((struct awc_private
*) dev
->priv
)->ejected
)
132 while (awc_command_busy(dev
->base_addr
)){
133 //if (jiffies - jiff > (HZ/3)){
135 printk(KERN_CRIT
"awc command busy WAY too long, clearing\n");
136 awc_dump_registers(dev
);
137 awc_event_ack_ClrStckCmdBsy(dev
->base_addr
);
138 active_interrupts
= awc_event_status(dev
->base_addr
);
139 awc_event_ack(dev
->base_addr
, active_interrupts
);
141 AWC_ENTRY_EXIT_DEBUG("BAD exit\n ");
145 if (((struct awc_private
*) dev
->priv
)->ejected
)
152 AWC_ENTRY_EXIT_DEBUG(" exit\n ");
161 inline unsigned short
162 awc_issue_command_and_block(struct awc_command
* cmd
){
166 u16 enabled_interrupts
;
168 // unsigned long flags;
173 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_and_block ");
175 AWC_LOCK_COMMAND_ISSUING(cmd
->priv
);
177 if (awc_command_busy_clear_wait(cmd
->dev
)) goto final
;
179 if (cmd
->priv
->sleeping_bap
) udelay(sleep_before_command
);
181 awc4500wout(cmd
->port
,cmd
->command
,cmd
->par0
,cmd
->par1
,cmd
->par2
);
182 // awc_dump_registers(cmd->dev);
185 if (cmd
->priv
->sleeping_bap
) udelay(sleep_in_command
);
187 enabled_interrupts
= awc_ints_enabled(cmd
->dev
->base_addr
);
188 awc_ints_enable(cmd
->dev
->base_addr
, enabled_interrupts
& ~0x10);
189 if(cmd
->priv
->enabled_interrupts
& 0x10)
190 cmd
->priv
->enabled_interrupts
&= ~0x10;
193 while ( awc_command_read(cmd
->port
) == cmd
->command
) {
195 awc_command_write(cmd
->port
, cmd
->command
);
196 //if ((jiffies - jiff) > 2){
198 printk(" long wait with commmand reg busy in blocking command \n");
199 awc_dump_registers(cmd
->dev
);
202 if (cmd
->priv
->ejected
)
208 AWC_ENTRY_EXIT_DEBUG(" issued " );
211 while ( awc_event_status_Cmd(cmd
->port
) == 0) {
214 printk(" long wait with commmand reg busy \n");
215 awc_dump_registers(cmd
->dev
);
219 DEBUG(1, " long wait after issue 10mks * %d ", ticks
);
220 //printk(" long wait with command reg busy about ticks\n");
223 if (cmd
->priv
->ejected
)
227 if (cmd
->priv
->sleeping_bap
) udelay(sleep_in_command
);
229 awc_read_response(cmd
);
230 AWC_ENTRY_EXIT_DEBUG(" resp read \n");
232 if (awc_command_busy(cmd
->port
))
233 awc_event_ack_ClrStckCmdBsy(cmd
->port
);
235 awc_event_ack_Cmd(cmd
->port
);
236 if (cmd
->priv
->sleeping_bap
) udelay(sleep_in_command
);
238 if (cmd
->status
& 0xff00){
239 printk(KERN_ERR
" bad response to command %s, parameter %x \n",awc_print_string(awc_command_names
, cmd
->command
),cmd
->par0
);
240 awc_dump_registers(cmd
->dev
);
244 AWC_UNLOCK_COMMAND_ISSUING(cmd
->priv
);
245 AWC_ENTRY_EXIT_DEBUG(" exit \n");
249 AWC_UNLOCK_COMMAND_ISSUING(cmd
->priv
);
250 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
257 awc_issue_command(struct awc_command
* cmd
){
260 // long long jiff = jiffies;
261 // unsigned short enabled_ints;
265 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command");
268 printk(KERN_CRIT
"cmd == NULL in awc_issue_command\n");
273 printk(KERN_CRIT
"cmd->dev == NULL in awc_issue_command\n");
278 AWC_LOCK_COMMAND_ISSUING(cmd
->priv
);
280 if(awc_command_busy_clear_wait(cmd
->dev
)) goto final
;
282 if(!cmd
->priv
->enabled_interrupts
& 0x10){
283 cmd
->priv
->enabled_interrupts
|= 0x10;
284 awc_ints_enable(cmd
->port
, cmd
->priv
->enabled_interrupts
);
287 cmd
->priv
->async_command_start
= jiffies
;
288 cmd
->priv
->command_semaphore_on
++;
291 awc4500wout(cmd
->port
,cmd
->command
,cmd
->par0
,cmd
->par1
,cmd
->par2
);
293 while ( awc_command_read(cmd
->port
) == cmd
->command
) {
295 awc_command_write(cmd
->port
, cmd
->command
);
296 //if ((jiffies - jiff) > 2){
298 printk(" long wait with commmand reg busy in async command \n");
299 awc_dump_registers(cmd
->dev
);
302 if (cmd
->priv
->ejected
)
308 cmd
->priv
->cmd
= *cmd
;
311 AWC_ENTRY_EXIT_DEBUG(" exit \n");
314 AWC_UNLOCK_COMMAND_ISSUING(cmd
->priv
);
315 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
322 awc_issue_command_no_ack(struct NET_DEVICE
* dev
,
323 u16 com
, u16 par1
, u16 par2
, u16 par3
){
325 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
330 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_no_ack ");
333 AWC_LOCK_COMMAND_ISSUING(priv
);
335 if (awc_command_busy_clear_wait(dev
)) {
336 printk("aironet4x00 no_ack command (reset) with stuck card \n");
339 awc4500wout(dev
->base_addr
,com
, par1
, par2
,par3
);
342 while ( awc_event_status_Cmd(dev
->base_addr
) == 0) {
343 if (awc_command_read(dev
->base_addr
) == com
) {
344 awc_command_write(dev
->base_addr
, com
);
346 //if ((jiffies - jiff) > 2){
348 printk(" long wait with commmand reg busy in noack command %d par %d %d %d\n",com
,par1
,par2
,par3
);
349 awc_dump_registers(dev
);
358 if (awc_command_busy(dev
->base_addr
))
359 awc_event_ack_ClrStckCmdBsy(dev
->base_addr
);
361 AWC_UNLOCK_COMMAND_ISSUING(priv
);
362 AWC_ENTRY_EXIT_DEBUG(" exit \n");
365 AWC_UNLOCK_COMMAND_ISSUING(priv
);
366 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
371 /******************************** BAP *************************/
374 int awc_bap_setup(struct awc_command
* cmd
) {
382 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_setup ");
384 if ( cmd
->priv
->sleeping_bap
)
387 if (cmd
->priv
->ejected
)
390 if (!cmd
->bap
|| !(cmd
->lock_state
& (AWC_BAP_SEMALOCKED
|AWC_BAP_LOCKED
)))
391 DEBUG(1,"no bap or bap not locked cmd %d !!", cmd
->command
);
393 if (bap_setup_spinlock
)
394 my_spin_lock_irqsave(&cmd
->priv
->bap_setup_spinlock
,cmd
->priv
->bap_setup_spinlock_flags
);
395 status
= AWC_IN(cmd
->bap
->offset
);
397 if (status
& ~0x2000 ){
399 status
= AWC_IN(cmd
->bap
->offset
);
402 if (status
& ~0x2000 ){
404 AWC_IN(cmd
->dev
->base_addr
+ 0x26);
405 AWC_OUT(cmd
->dev
->base_addr
+ 0x26, 0);
411 status
= AWC_IN(cmd
->bap
->offset
);
415 if (status
& 0xC000){
416 printk(KERN_ERR
"bap entered with err or busy bit set %x \n",status
);
417 if (cmd
->bap
->lock
!= 1)
418 printk(KERN_ERR
"bap lock bad same time %x\n",cmd
->bap
->lock
);
419 awc_dump_registers(cmd
->dev
);
420 // AWC_OUT(cmd->bap->offset, 0x800);
426 AWC_OUT(cmd
->bap
->select
, cmd
->rid
);
428 AWC_OUT(cmd
->bap
->offset
, cmd
->offset
);
430 restore_flags(flags
);
438 status
= AWC_IN(cmd
->bap
->offset
);
439 if ( cmd
->priv
->sleeping_bap
)
441 if (cmd
->priv
->ejected
)
444 if (cycles
> 10000) {
445 printk(KERN_CRIT
"deadlock in bap\n");
446 goto return_AWC_ERROR
;
448 status
= AWC_IN(cmd
->bap
->offset
);
449 if (status
& AWC_BAP_BUSY
) {
450 if (cycles
% 100 == 99 ) {
454 AWC_IN(cmd
->dev
->base_addr
+ 0x26);
455 AWC_OUT(cmd
->dev
->base_addr
+ 0x26, 0);
459 AWC_OUT(cmd
->bap
->select
, cmd
->rid
);
461 AWC_OUT(cmd
->bap
->offset
, cmd
->offset
);
462 restore_flags(flags
);
467 if ( cmd
->priv
->sleeping_bap
)
472 if (jiffies
- jiff
> 1 ) {
473 AWC_ENTRY_EXIT_DEBUG(" BAD BUSY exit \n");
474 awc_dump_registers(cmd
->dev
);
475 goto return_AWC_ERROR
;
479 if (status
& AWC_BAP_DONE
) {
480 WAIT61x3
; WAIT61x3
; WAIT61x3
;
482 // if ((status & 0xfff) != cmd->offset)
483 // printk(KERN_ERR "awcPBD %x ",status);
484 AWC_ENTRY_EXIT_DEBUG(" exit \n");
485 if (cmd
->priv
->sleeping_bap
)
486 udelay(bap_sleep_after_setup
);
489 goto return_AWC_SUCCESS
;
492 if (status
& AWC_BAP_ERR
) {
493 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
494 // invalid rid or offset
495 printk(KERN_ERR
"bap setup error bit set for rid %x offset %x \n",cmd
->rid
,cmd
->offset
);
496 awc_dump_registers(cmd
->dev
);
497 goto return_AWC_ERROR
;
499 if ( cmd
->priv
->sleeping_bap
)
502 // -- awc missed it, try again
506 AWC_OUT(cmd
->bap
->select
, cmd
->rid
);
508 AWC_OUT(cmd
->bap
->offset
, cmd
->offset
);
510 restore_flags(flags
);
512 if (jiffies
- jiff
> HZ
)
513 if (! (status
&(AWC_BAP_ERR
|AWC_BAP_DONE
|AWC_BAP_BUSY
))){
514 printk("aironet4500: bap setup lock without any status bits set");
515 awc_dump_registers(cmd
->dev
);
516 goto return_AWC_ERROR
;
522 AWC_ENTRY_EXIT_DEBUG(" WE MUST NOT BE HERE exit \n");
525 if (bap_setup_spinlock
)
526 my_spin_unlock_irqrestore(&cmd
->priv
->bap_setup_spinlock
,cmd
->priv
->bap_setup_spinlock_flags
);
527 AWC_ENTRY_EXIT_DEBUG(" ejected_unlock_exit \n");
531 if (bap_setup_spinlock
)
532 my_spin_unlock_irqrestore(&cmd
->priv
->bap_setup_spinlock
,cmd
->priv
->bap_setup_spinlock_flags
);
533 AWC_ENTRY_EXIT_DEBUG(" AWC_ERROR_exit \n");
537 if (bap_setup_spinlock
)
538 my_spin_unlock_irqrestore(&cmd
->priv
->bap_setup_spinlock
,cmd
->priv
->bap_setup_spinlock_flags
);
539 AWC_ENTRY_EXIT_DEBUG(" exit \n");
544 // requires call to awc_bap_setup() first
547 awc_bap_read(struct awc_command
* cmd
) {
549 register u16
* buff
= (u16
*) cmd
->buff
;
550 register u16 port
= cmd
->bap
->data
;
553 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_read ");
554 if (!cmd
->bap
&& !(cmd
->lock_state
& (AWC_BAP_SEMALOCKED
|AWC_BAP_LOCKED
)))
555 DEBUG(0,"no bap or bap not locked %d !!", cmd
->command
);
556 cmd
->len
= (cmd
->len
+ 1) & (~1); // round up to even value
558 if (cmd
->priv
->ejected
)
562 if (cmd
->priv
->sleeping_bap
)
563 udelay(bap_sleep_before_write
);
565 if (!cmd
->priv
->sleeping_bap
)
567 *buff
++ = AWC_IN(port
);
570 *buff
++ = AWC_IN(port
);
572 AWC_ENTRY_EXIT_DEBUG(" exit \n");
573 if (cmd
->priv
->ejected
)
579 // requires call to awc_bap_setup() first
582 awc_bap_write(struct awc_command
* cmd
){
584 register u16
* buff
= (u16
*) cmd
->buff
;
585 register u16 port
= cmd
->bap
->data
;
588 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_write ");
589 if (!cmd
->bap
&& !(cmd
->lock_state
& (AWC_BAP_SEMALOCKED
|AWC_BAP_LOCKED
)))
590 DEBUG(0,"no bap or bap not locked %d !!", cmd
->command
);
592 cmd
->len
= (cmd
->len
+ 1) & (~1); // round up to even value
595 if (cmd
->priv
->ejected
)
598 if (cmd
->priv
->sleeping_bap
)
599 udelay(bap_sleep_before_write
);
602 if (!cmd
->priv
->sleeping_bap
)
604 AWC_OUT(port
, *buff
++);
607 AWC_OUT(port
, *buff
++);
609 if (cmd
->priv
->ejected
)
613 AWC_ENTRY_EXIT_DEBUG(" exit \n");
621 /***************************** RID READ/WRITE ********************/
623 const struct aironet4500_rid_selector aironet4500_RID_Select_General_Config
=(const struct aironet4500_rid_selector
){ 0xFF10, 1,0,0, "General Configuration" }; // See notes General Configuration Many configuration items.
624 const struct aironet4500_rid_selector aironet4500_RID_Select_SSID_list
=(const struct aironet4500_rid_selector
){ 0xFF11, 1,0,0, "Valid SSID list" }; // See notes Valid SSID list List of SSIDs which the station may associate to.
625 const struct aironet4500_rid_selector aironet4500_RID_Select_AP_list
=(const struct aironet4500_rid_selector
){ 0xFF12, 1,0,0, "Valid AP list" }; // See notes Valid AP list List of APs which the station may associate to.
626 const struct aironet4500_rid_selector aironet4500_RID_Select_Driver_name
=(const struct aironet4500_rid_selector
){ 0xFF13, 1,0,0, "Driver name" }; // See notes Driver name The name and version of the driver (for debugging)
627 const struct aironet4500_rid_selector aironet4500_RID_Select_Encapsulation
=(const struct aironet4500_rid_selector
){ 0xFF14, 1,0,0, "Ethernet Protocol" }; // See notes Ethernet Protocol Rules for encapsulating ethernet payloads onto 802.11.
628 const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_volatile
=(const struct aironet4500_rid_selector
){ 0xFF15, 1,0,0, "WEP key volatile" }; //
629 const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_nonvolatile
=(const struct aironet4500_rid_selector
){ 0xFF16, 1,0,0, "WEP key non-volatile" }; //
630 const struct aironet4500_rid_selector aironet4500_RID_Select_Modulation
=(const struct aironet4500_rid_selector
){ 0xFF17, 1,0,0, "Modulation" }; //
631 const struct aironet4500_rid_selector aironet4500_RID_Select_Active_Config
=(const struct aironet4500_rid_selector
){ 0xFF20, 0,1,1, "Actual Configuration" }; // Read only Actual Configuration This has the same format as the General Configuration.
632 const struct aironet4500_rid_selector aironet4500_RID_Select_Capabilities
=(const struct aironet4500_rid_selector
){ 0xFF00, 0,1,0, "Capabilities" }; // Read Only Capabilities PC4500 Information
633 const struct aironet4500_rid_selector aironet4500_RID_Select_AP_Info
=(const struct aironet4500_rid_selector
){ 0xFF01, 0,1,1, "AP Info" }; // Read Only AP Info Access Point Information
634 const struct aironet4500_rid_selector aironet4500_RID_Select_Radio_Info
=(const struct aironet4500_rid_selector
){ 0xFF02, 0,1,1, "Radio Info" }; // Read Only Radio Info Radio Information -- note radio specific
635 const struct aironet4500_rid_selector aironet4500_RID_Select_Status
=(const struct aironet4500_rid_selector
){ 0xFF50, 0,1,1, "Status" }; // Read Only Status PC4500 Current Status Information
636 const struct aironet4500_rid_selector aironet4500_RID_Select_16_stats
=(const struct aironet4500_rid_selector
){ 0xFF60, 0,1,1, "Cumulative 16-bit Statistics" }; // Read Only 16-bit Statistics Cumulative 16-bit Statistics
637 const struct aironet4500_rid_selector aironet4500_RID_Select_16_stats_delta
=(const struct aironet4500_rid_selector
){ 0xFF61, 0,1,1, "Delta 16-bit Statistics" }; // Read Only 16-bit Statistics Delta 16-bit Statistics (since last clear)
638 const 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" }; // Read Only / 16-bit Statistics Delta 16-bit Statistics and Clear
639 const struct aironet4500_rid_selector aironet4500_RID_Select_32_stats
=(const struct aironet4500_rid_selector
){ 0xFF68, 0,1,1, "Cumulative 32-bit Statistics" }; // Read Only 32-bit Statistics Cumulative 32-bit Statistics
640 const struct aironet4500_rid_selector aironet4500_RID_Select_32_stats_delta
=(const struct aironet4500_rid_selector
){ 0xFF69, 0,1,1, "Delta 32-bit Statistics" }; // Read Only 32-bit Statistics Delta 32-bit Statistics (since last clear)
641 const 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" }; // Read Only / 32-bit Statistics Delta 32-bit Statistics and Clear
643 EXPORT_SYMBOL(aironet4500_RID_Select_General_Config
);
644 EXPORT_SYMBOL(aironet4500_RID_Select_SSID_list
);
645 EXPORT_SYMBOL(aironet4500_RID_Select_AP_list
);
646 EXPORT_SYMBOL(aironet4500_RID_Select_Driver_name
);
647 EXPORT_SYMBOL(aironet4500_RID_Select_Encapsulation
);
648 EXPORT_SYMBOL(aironet4500_RID_Select_WEP_volatile
);
649 EXPORT_SYMBOL(aironet4500_RID_Select_WEP_nonvolatile
);
650 EXPORT_SYMBOL(aironet4500_RID_Select_Modulation
);
651 EXPORT_SYMBOL(aironet4500_RID_Select_Active_Config
);
652 EXPORT_SYMBOL(aironet4500_RID_Select_Capabilities
);
653 EXPORT_SYMBOL(aironet4500_RID_Select_AP_Info
);
654 EXPORT_SYMBOL(aironet4500_RID_Select_Radio_Info
);
655 EXPORT_SYMBOL(aironet4500_RID_Select_Status
);
656 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats
);
657 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_delta
);
658 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_clear
);
659 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats
);
660 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_delta
);
661 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_clear
);
664 struct awc_rid_dir awc_rids_temp
[]={
665 // following MUST be consistent with awc_rids_setup !!!
666 {&aironet4500_RID_Select_General_Config
, 0x100 , NULL
, NULL
, NULL
,0 },
667 {&aironet4500_RID_Select_SSID_list
, 0x68 , NULL
, NULL
, NULL
,0 },
668 {&aironet4500_RID_Select_AP_list
, 0x20 , NULL
, NULL
, NULL
,0 },
669 {&aironet4500_RID_Select_Driver_name
, 0x12 , NULL
, NULL
, NULL
,0 },
670 {&aironet4500_RID_Select_Encapsulation
, 0x22 , NULL
, NULL
, NULL
,0 },
671 {&aironet4500_RID_Select_Active_Config
, 0x100 , NULL
, NULL
, NULL
,0 },
672 {&aironet4500_RID_Select_Capabilities
, 0x80 , NULL
, NULL
, NULL
,0 },
673 {&aironet4500_RID_Select_Status
, 0x6c , NULL
, NULL
, NULL
,0 },
674 {&aironet4500_RID_Select_AP_Info
, 0x06 , NULL
, NULL
, NULL
,0 },
675 {&aironet4500_RID_Select_32_stats
, 0x184 , NULL
, NULL
, NULL
,0 },
676 {&aironet4500_RID_Select_32_stats_delta
, 0x184 , NULL
, NULL
, NULL
,0 },
677 {&aironet4500_RID_Select_32_stats_clear
, 0x184 , NULL
, NULL
, NULL
,0 },
678 {&aironet4500_RID_Select_WEP_volatile
, 0x1c , NULL
, NULL
, NULL
,0 },
679 {&aironet4500_RID_Select_WEP_nonvolatile
, 0x1c , NULL
, NULL
, NULL
,0 },
680 {&aironet4500_RID_Select_Modulation
, 0x04 , NULL
, NULL
, NULL
,0 },
682 #ifdef AWC_USE_16BIT_STATS
683 {&aironet4500_RID_Select_16_stats
, 0xC2 , NULL
, NULL
, NULL
,0 },
684 {&aironet4500_RID_Select_16_stats_delta
, 0xC2 , NULL
, NULL
, NULL
,0 },
685 {&aironet4500_RID_Select_16_stats_clear
, 0xC2 , NULL
, NULL
, NULL
,0 },
687 {NULL
},{NULL
},{NULL
},
698 awc_readrid(struct NET_DEVICE
* dev
, struct aironet4500_RID
* rid
, void *pBuf
){
699 struct awc_command cmd
;
703 AWC_ENTRY_EXIT_DEBUG(" entry awc_readrid ");
705 if (!rid
->selector
) return -1;
706 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x21, rid
->selector
->selector
,
707 rid
->selector
->selector
, rid
->offset
, (rid
->bits
/ 8),pBuf
);
709 sleep_state
= cmd
.priv
->sleeping_bap
;
710 cmd
.priv
->sleeping_bap
= 1;
712 AWC_BAP_LOCK_NOT_CLI(cmd
);
713 if (awc_issue_command_and_block(&cmd
)) goto final
;
715 if (awc_bap_setup(&cmd
)) goto final
;
717 if (awc_bap_read(&cmd
)) goto final
;
718 cmd
.priv
->sleeping_bap
= sleep_state
;
720 AWC_RELEASE_COMMAND(cmd
);
721 AWC_ENTRY_EXIT_DEBUG(" exit \n");
724 cmd
.priv
->sleeping_bap
= sleep_state
;
725 AWC_RELEASE_COMMAND(cmd
);
726 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
731 awc_writerid(struct NET_DEVICE
* dev
, struct aironet4500_RID
* rid
, void *pBuf
){
733 struct awc_command cmd
;
736 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid ");
739 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x21, rid
->selector
->selector
,
740 rid
->selector
->selector
,rid
->offset
, rid
->bits
/8,pBuf
);
742 sleep_state
= cmd
.priv
->sleeping_bap
;
743 cmd
.priv
->sleeping_bap
= 1;
746 AWC_BAP_LOCK_NOT_CLI(cmd
);
747 if (awc_issue_command_and_block(&cmd
)) goto final
;
749 if (awc_bap_setup(&cmd
)) goto final
;
751 if (awc_bap_write(&cmd
)) goto final
;
754 if (awc_issue_command_and_block(&cmd
)) goto final
;
755 cmd
.priv
->sleeping_bap
= sleep_state
;
757 AWC_RELEASE_COMMAND(cmd
);
758 AWC_ENTRY_EXIT_DEBUG(" exit \n");
761 cmd
.priv
->sleeping_bap
= sleep_state
;
762 AWC_RELEASE_COMMAND(cmd
);
763 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
768 awc_readrid_dir(struct NET_DEVICE
* dev
, struct awc_rid_dir
* rid
){
769 struct awc_command cmd
;
772 AWC_ENTRY_EXIT_DEBUG(" entry awcreadrid_dir ");
775 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x21, rid
->selector
->selector
,
776 rid
->selector
->selector
,0, rid
->bufflen
,rid
->buff
);
778 sleep_state
= cmd
.priv
->sleeping_bap
;
779 cmd
.priv
->sleeping_bap
= 1;
783 AWC_BAP_LOCK_NOT_CLI(cmd
);
784 if (awc_issue_command_and_block(&cmd
)) goto final
;
786 if (awc_bap_setup(&cmd
)) goto final
;
787 if (awc_bap_read(&cmd
)) goto final
;
788 cmd
.priv
->sleeping_bap
= sleep_state
;
790 AWC_RELEASE_COMMAND(cmd
);
791 AWC_ENTRY_EXIT_DEBUG(" exit \n");
794 cmd
.priv
->sleeping_bap
= sleep_state
;
795 AWC_RELEASE_COMMAND(cmd
);
796 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
801 awc_writerid_dir(struct NET_DEVICE
* dev
, struct awc_rid_dir
* rid
){
803 struct awc_command cmd
;
807 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid_dir ");
811 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x21, rid
->selector
->selector
,
812 rid
->selector
->selector
,0, rid
->bufflen
,((char *)rid
->buff
));
814 sleep_state
= cmd
.priv
->sleeping_bap
;
815 cmd
.priv
->sleeping_bap
= 1;
819 AWC_BAP_LOCK_NOT_CLI(cmd
);
821 if (awc_issue_command_and_block(&cmd
)) goto final
;
822 if (awc_bap_setup(&cmd
)) goto final
;
823 if (awc_bap_write(&cmd
)) goto final
;
824 cmd
.priv
->sleeping_bap
= sleep_state
;
828 if (awc_issue_command_and_block(&cmd
)) goto final
;
830 AWC_RELEASE_COMMAND(cmd
);
831 AWC_ENTRY_EXIT_DEBUG(" exit \n");
834 cmd
.priv
->sleeping_bap
= sleep_state
;
835 AWC_RELEASE_COMMAND(cmd
);
836 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
840 EXPORT_SYMBOL(awc_readrid
);
841 EXPORT_SYMBOL(awc_writerid
);
842 EXPORT_SYMBOL(awc_readrid_dir
);
843 EXPORT_SYMBOL(awc_writerid_dir
);
845 /***************************** STARTUP *******************/
850 awc_issue_blocking_command(struct NET_DEVICE
* dev
,u16 comm
){
852 struct awc_command cmd
;
853 // struct awc_private * priv = (struct awc_private *)dev->priv;
855 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_blocking_command ");
857 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,comm
,0, 0, 0, 0 ,0 );
859 AWC_BAP_LOCK_NOT_CLI(cmd
);
861 if (awc_issue_command_and_block(&cmd
))
864 AWC_RELEASE_COMMAND(cmd
);
865 AWC_ENTRY_EXIT_DEBUG(" exit \n");
868 AWC_RELEASE_COMMAND(cmd
);
869 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
875 awc_issue_soft_reset(struct NET_DEVICE
* dev
){
880 /* outw(inw(dev->base_addr + 0x30), dev->base_addr + 0x32);
882 outw(inw(dev->base_addr + 0x30), dev->base_addr + 0x34);
884 for (i=0; i< 32; i++)
885 outw(0,dev->base_addr + i*2);
887 outw(0x6,dev->base_addr + 0x34);
889 outw(0x6,dev->base_addr + 0x34);
890 outw(0x6,dev->base_addr + 0x34);
892 AWC_IN(dev->base_addr + 0x26);
893 AWC_OUT(dev->base_addr + 0x26, 0);
898 outw(0x4, dev->base_addr);
901 AWC_IN(dev->base_addr + 0x26);
902 AWC_OUT(dev->base_addr + 0x26, 0);
907 status
= awc_issue_command_no_ack(dev
, AWC_COMMAND_SOFT_RESET
,0,0,0);
909 // awc_command_busy_clear_wait(dev);
915 awc_issue_noop(struct NET_DEVICE
* dev
){
917 AWC_OUT(dev
->base_addr
+ 0x28, 0);
918 AWC_OUT(dev
->base_addr
+ 0x2A, 0);
920 retval
= awc_issue_blocking_command(dev
, AWC_COMMAND_NOOP
);
925 EXPORT_SYMBOL(awc_enable_MAC
);
928 awc_enable_MAC(struct NET_DEVICE
* dev
){
930 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
931 AWC_ENTRY_EXIT_DEBUG(" entry awc_enable_MAC ");
933 if (priv
->mac_enabled
){
935 AWC_ENTRY_EXIT_DEBUG(" mac already enabled exit \n");
939 if (awc_issue_blocking_command(dev
, AWC_COMMAND_ENABLE
)){
940 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
945 priv
->mac_enabled
= 1;
947 AWC_ENTRY_EXIT_DEBUG(" exit \n");
951 EXPORT_SYMBOL(awc_disable_MAC
);
953 awc_disable_MAC(struct NET_DEVICE
* dev
){
955 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
956 AWC_ENTRY_EXIT_DEBUG(" entry awc_disable_MAC ");
958 if (!priv
->mac_enabled
){
959 AWC_ENTRY_EXIT_DEBUG(" mac allready disabled exit \n");
963 if (awc_issue_blocking_command(dev
, AWC_COMMAND_DISABLE
)){
964 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
968 priv
->mac_enabled
= 0;
969 AWC_ENTRY_EXIT_DEBUG(" exit \n");
976 awc_read_all_rids(struct NET_DEVICE
* dev
){
978 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
980 AWC_ENTRY_EXIT_DEBUG(" entry awc_read_all_rids ");
982 for (i
=0; i
< AWC_NOF_RIDS
&& priv
->rid_dir
[i
].selector
; i
++){
983 status
= awc_readrid_dir(dev
,&priv
->rid_dir
[i
]);
985 if (status
) return status
;
990 AWC_ENTRY_EXIT_DEBUG(" exit \n");
995 awc_write_all_rids(struct NET_DEVICE
* dev
){
997 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
999 AWC_ENTRY_EXIT_DEBUG(" entry awc_write_all_rids ");
1001 for (i
=0;i
< 5 && i
< AWC_NOF_RIDS
&& priv
->rid_dir
[i
].selector
; i
++){
1002 status
= awc_writerid_dir(dev
,&priv
->rid_dir
[i
]);
1004 if(status
) return status
;
1006 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1010 /************************** FID QUEUES ****************************/
1011 /**************************** TX ALLOC / DEALLOC ***************/
1015 int awc_tx_alloc(struct NET_DEVICE
* dev
) {
1017 struct awc_command cmd
;
1020 struct awc_fid
* fid
= NULL
;
1022 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_alloc ");
1025 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x0A,0, 0,0,0,NULL
);
1026 cmd
.par0
= dev
->mtu
+ AWC_TX_HEAD_SIZE
+ 8 ;
1028 DEBUG(32,"about to allocate %x bytes ",cmd
.priv
->large_buff_mem
);
1029 DEBUG(32,"in %x large buffers ",cmd
.priv
->large_buff_mem
/ (dev
->mtu
+ AWC_TX_HEAD_SIZE
+ 8) );
1032 AWC_BAP_LOCK_NOT_CLI(cmd
);
1034 while (k
< cmd
.priv
->large_buff_mem
/ (dev
->mtu
+ AWC_TX_HEAD_SIZE
+ 8) ) {
1036 fid
= kmalloc(sizeof(struct awc_fid
),GFP_KERNEL
);
1037 if (!fid
) goto final
;
1038 memset(fid
, 0, sizeof(struct awc_fid
));
1040 if (awc_issue_command_and_block(&cmd
)) goto final
;
1042 while ( awc_event_status_Alloc(cmd
.port
) == 0) ;
1043 fid
->u
.tx
.fid
= awc_Tx_Allocated_Fid(cmd
.port
);
1044 fid
->u
.tx
.fid_size
= dev
->mtu
+ AWC_TX_HEAD_SIZE
;
1046 DEBUG(32,"allocated large tx fid %x ",fid
->u
.tx
.fid
);
1047 if(fid
->u
.tx
.fid
== 0
1048 || cmd
.status
!= 0xA){
1049 printk(KERN_ERR
"%s bad tx_alloc\n",dev
->name
);
1056 awc_event_ack_Alloc(cmd
.port
);
1058 // shoudlnt goto final after that
1059 awc_fid_queue_push_tail(&cmd
.priv
->tx_large_ready
,fid
);
1063 cmd
.priv
->tx_buffs_total
= tot
;
1064 DEBUG(32,"allocated %d large tx buffs\n",tot
);
1066 cmd
.par0
= AWC_TX_ALLOC_SMALL_SIZE
;
1069 while (k
< cmd
.priv
->small_buff_no
) {
1071 fid
= kmalloc(sizeof(struct awc_fid
),GFP_KERNEL
);
1072 if (!fid
) goto final
;
1073 memset(fid
, 0, sizeof(struct awc_fid
));
1075 cmd
.par0
= AWC_TX_ALLOC_SMALL_SIZE
;
1077 if (awc_issue_command_and_block(&cmd
)) goto final
;
1079 while ( awc_event_status_Alloc(cmd
.port
) == 0) ;
1080 fid
->u
.tx
.fid
= awc_Tx_Allocated_Fid(cmd
.port
);
1081 fid
->u
.tx
.fid_size
= AWC_TX_ALLOC_SMALL_SIZE
;
1083 DEBUG(32,"allocated large tx fid %x ",fid
->u
.tx
.fid
);
1084 if(fid
->u
.tx
.fid
== 0
1085 || cmd
.status
!= 0xA){
1086 printk(KERN_ERR
"%s bad tx_alloc\n",dev
->name
);
1093 awc_event_ack_Alloc(cmd
.port
);
1095 // shoudlnt goto final after that
1096 awc_fid_queue_push_tail(&cmd
.priv
->tx_small_ready
,fid
);
1101 cmd
.priv
->tx_small_buffs_total
= tot
;
1102 DEBUG(32,"allocated %d small tx buffs\n",tot
);
1104 AWC_RELEASE_COMMAND(cmd
);
1105 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1111 printk(KERN_CRIT
"%s awc tx prealloc failed \n",dev
->name
);
1112 AWC_RELEASE_COMMAND(cmd
);
1113 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1119 awc_tx_dealloc_fid(struct NET_DEVICE
* dev
,struct awc_fid
* fid
){
1121 struct awc_command cmd
;
1124 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0x0C,0, 0,0,0,NULL
);
1126 AWC_BAP_LOCK_NOT_CLI(cmd
);
1129 fid_handle
= cmd
.par0
= fid
->u
.tx
.fid
;
1134 if (!cmd
.priv
->ejected
)
1135 if (awc_issue_command_and_block(&cmd
)) goto final
;
1136 //awc_event_ack_Alloc(cmd.port);
1139 AWC_RELEASE_COMMAND(cmd
);
1140 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1144 printk(KERN_ERR
"awc_tx_dealloc failed for fid %x \n",fid_handle
);
1145 AWC_RELEASE_COMMAND(cmd
);
1146 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1153 awc_tx_dealloc(struct NET_DEVICE
* dev
){
1155 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1160 struct awc_fid
* fid
;
1162 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_dealloc ");
1164 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->tx_large_ready
)))
1165 awc_tx_dealloc_fid(dev
,fid
);
1166 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->tx_small_ready
)))
1167 awc_tx_dealloc_fid(dev
,fid
);
1168 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->tx_post_process
)))
1169 awc_tx_dealloc_fid(dev
,fid
);
1170 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->tx_in_transmit
)))
1171 awc_tx_dealloc_fid(dev
,fid
);
1179 inline struct awc_fid
*
1180 awc_tx_fid_lookup_and_remove(struct NET_DEVICE
* dev
, u16 fid_handle
){
1182 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1184 unsigned long flags
;
1185 struct awc_fid
* fid
= NULL
;
1188 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_fid_lookup ");
1190 my_spin_lock_irqsave(&(priv
->queues_lock
),flags
);
1193 fid
= priv
->tx_in_transmit
.head
;
1196 if (fid
->u
.tx
.fid
== fid_handle
){
1197 awc_fid_queue_remove(&priv
->tx_in_transmit
, fid
);
1198 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1204 // printk("bbb in awc_fid_queue\n");
1205 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1211 fid
= priv
->tx_post_process
.head
;
1213 if (fid
->u
.tx
.fid
== fid_handle
){
1214 awc_fid_queue_remove(&priv
->tx_post_process
, fid
);
1215 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1221 // printk("bbb in awc_fid_queue\n");
1222 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1229 fid
= priv
->tx_large_ready
.head
;
1231 if (fid
->u
.tx
.fid
== fid_handle
){
1232 awc_fid_queue_remove(&priv
->tx_large_ready
, fid
);
1233 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1239 // printk("bbb in awc_fid_queue\n");
1240 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1246 fid
= priv
->tx_small_ready
.head
;
1248 if (fid
->u
.tx
.fid
== fid_handle
){
1249 awc_fid_queue_remove(&priv
->tx_small_ready
, fid
);
1250 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1256 // printk("bbb in awc_fid_queue\n");
1257 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1263 my_spin_unlock_irqrestore(&(priv
->queues_lock
),flags
);
1265 printk(KERN_ERR
"%s tx fid %x not found \n",dev
->name
, fid_handle
);
1266 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1275 awc_queues_init(struct NET_DEVICE
* dev
){
1276 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1277 struct awc_fid
* fid
= NULL
;
1281 awc_fid_queue_init(&priv
->tx_in_transmit
);
1282 awc_fid_queue_init(&priv
->tx_post_process
);
1283 awc_fid_queue_init(&priv
->tx_large_ready
);
1284 awc_fid_queue_init(&priv
->tx_small_ready
);
1285 awc_fid_queue_init(&priv
->rx_ready
);
1286 awc_fid_queue_init(&priv
->rx_post_process
);
1288 retv
= awc_tx_alloc(dev
);
1291 while (k
< AWC_RX_BUFFS
){
1292 fid
= kmalloc(sizeof(struct awc_fid
),GFP_KERNEL
);
1293 if (!fid
) return -1;
1294 awc_fid_queue_push_tail(&priv
->rx_ready
,fid
);
1298 if (retv
) return retv
;
1305 awc_queues_destroy(struct NET_DEVICE
* dev
){
1306 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1307 struct awc_fid
* fid
= NULL
;
1312 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->rx_ready
))){
1315 while (NULL
!= (fid
= awc_fid_queue_pop_head(&priv
->rx_post_process
))){
1319 retv
= awc_tx_dealloc(dev
);
1326 /****************************** 802.11router ******************/
1328 awc_802_11_copy_path_skb(struct NET_DEVICE
* dev
, struct awc_fid
* rx_buff
){
1330 struct awc_private
* priv
= (struct awc_private
* )dev
->priv
;
1332 AWC_ENTRY_EXIT_DEBUG("awc_802_11_copy_path_skb");
1334 if (rx_buff
->pkt_len
< 22 ) rx_buff
->pkt_len
= 22;
1336 // if (!rx_buff->skb)
1337 rx_buff
->skb
= dev_alloc_skb(rx_buff
->pkt_len
+ 12 +2);
1340 if (rx_buff
->skb
== NULL
) {
1341 printk(KERN_CRIT
"couldnt alloc rx_buff->skb in rx event \n");
1342 priv
->stats
.rx_dropped
++;
1345 rx_buff
->type
|= p80211copy_path_skb
;
1347 rx_buff
->skb
->dev
= dev
;
1349 // skb_reserve(rx_buff->skb, rx_buff->pkt_len + 12 );
1351 rx_buff
->u
.rx
.payload
= skb_put(rx_buff
->skb
, rx_buff
->pkt_len
+ 12 ) ;
1352 rx_buff
->u
.rx
.payload
= ((char *)rx_buff
->u
.rx
.payload
) +12;
1354 AWC_ENTRY_EXIT_DEBUG("exit\n");
1363 awc_802_11_find_copy_path(struct NET_DEVICE
* dev
, struct awc_fid
* rx_buff
){
1365 // struct awc_private * priv = (struct awc_private * )dev->priv;
1371 return awc_802_11_copy_path_skb(dev
,rx_buff
);
1375 /* called from INTERRUPT context,
1377 must deliver the packet to where it was meant by
1378 awc_802_11_find_copy_path
1380 SHOULD be efficient and
1381 queue the packet if operations take longer
1386 int parse_not_8023
= 0;
1389 awc_802_11_router_rx(struct NET_DEVICE
* dev
,struct awc_fid
* rx_buff
){
1391 struct awc_private
* priv
= (struct awc_private
* )dev
->priv
;
1392 struct sk_buff
* skb
= rx_buff
->skb
;
1393 u8
* payload
= rx_buff
->u
.rx
.payload
;
1394 // u8 * p802_3_macs_place = payload -12;
1395 u16 pkt_len
= rx_buff
->pkt_len
;
1396 struct ieee_802_11_802_1H_header
* bridge
= NULL
;
1397 struct ieee_802_11_snap_header
* snap
= NULL
;
1398 struct ieee_802_11_802_1H_header
* bridge_tmp
;
1399 struct ieee_802_11_snap_header
* snap_tmp
;
1404 AWC_ENTRY_EXIT_DEBUG("awc_802_11_router_rx");
1406 // if (rx_buff->type & p80211_8023)
1407 rx_buff
->mac
= rx_buff
->u
.rx
.ieee_802_3
.dst_mac
;
1409 // rx_buff->mac = rx_buff->u.rx.ieee_802_11.mac1;
1411 if ( rx_buff
->u
.rx
.ieee_802_11
.frame_control
== 0x8 )
1412 memcpy(priv
->bssid
,rx_buff
->u
.rx
.ieee_802_11
.mac3
,6);
1414 while ((ptr
< pkt_len
- 1 ) && payload
&& parse_not_8023
){
1416 bridge_tmp
= (struct ieee_802_11_802_1H_header
*) &payload
[ptr
];
1417 snap_tmp
= (struct ieee_802_11_snap_header
*) &payload
[ptr
];
1418 len
= ntohs( *((u16
*)&payload
[ptr
]) );
1422 if ( len
< 0x5DC) { // not a protocol
1424 if ( len
!= pkt_len
-2 - ptr
){
1425 printk(KERN_ERR
"%s bad encapsulation lenght %x at pkt offset %x \n",dev
->name
,len
,ptr
);
1428 DEBUG(1,"parisng packet of size %x\n",len
);
1433 DEBUG(1,"parisng packet of proto %x\n",len
);
1435 if (snap_tmp
->dsap
== 0xaa && snap_tmp
->ssap
== 0xaa &&
1436 pkt_len
- ptr
> sizeof(struct ieee_802_11_snap_header
) ){
1438 DEBUG(0x200,"%s SNAP ",dev
->name
);
1439 if (snap_tmp
->ctrl
!= 0x03){
1440 printk(KERN_ERR
"%s unknown snap ctrl %x \n",dev
->name
,snap_tmp
->ctrl
);
1443 if (snap_tmp
->oui
[0] == 0 && // LLC RFC1042
1444 snap_tmp
->oui
[1] == 0 &&
1445 snap_tmp
->oui
[2] == 0 ){
1447 ptr
+= sizeof(struct ieee_802_11_snap_header
);
1448 DEBUG(0x200,"%s LLC RFC1042 \n",dev
->name
);
1451 if (snap_tmp
->oui
[0] == 0 && // LLC 802.1H
1452 snap_tmp
->oui
[1] == 0 &&
1453 snap_tmp
->oui
[2] == 0x78){
1455 DEBUG(0x200,"%s LLC 802.1H \n",dev
->name
);
1456 ptr
+= sizeof(struct ieee_802_11_snap_header
);
1459 if (snap_tmp
->oui
[0] == 0x00 && // 802.1H itself
1460 snap_tmp
->oui
[1] == 0x40 &&
1461 snap_tmp
->oui
[2] == 0x96){
1462 ptr
+= sizeof(struct ieee_802_11_802_1H_header
);
1463 if (ptr
>= pkt_len
){
1465 DEBUG(1,"%s invalid packet len in 802.1H SNAP OUI check \n",dev
->name
);
1467 DEBUG(0x200,"%s OUI 004096 \n",dev
->name
);
1468 DEBUG(0x200," 802.1H uknown1 %x ",ntohs(bridge_tmp
->unknown1
));
1469 DEBUG(0x200," 802.1H uknw type %x \n",0xf000 & ntohs(bridge_tmp
->unknown2
));
1470 DEBUG(0x200," 802.1H payloadsize %x \n",0x0fff & ntohs(bridge_tmp
->unknown2
));
1472 //goto bad_packet; // TODO
1474 bridge
= bridge_tmp
;
1475 if (bridge_tmp
->unknown1
== 0x0000 &&
1476 ((ntohs(bridge_tmp
->unknown2
) & 0xf000) == 0x1000 ) ){
1477 rx_buff
->type
|= p80211_8021H
;
1478 rx_buff
->mac
= &payload
[ptr
];
1479 DEBUG(0x200," 802.1H DATA packet of size %x\n",0xf000 & ntohs(bridge_tmp
->unknown2
) );
1480 memcpy(priv
->p2p
,rx_buff
->u
.rx
.ieee_802_11
.mac2
, 6);
1484 DEBUG(0x200,"%s droping unknown 004096 packet \n ",dev
->name
);
1492 // packet without linklevel header for us
1494 if ( len
== 0x8000 || len
== 0x8006){
1496 DEBUG(0x200,"Non IP packet %x \n",ntohs(len
));
1508 if (ptr
> pkt_len
) goto bad_packet
;
1510 if ( rx_buff
->mac
!= (payload
+ ptr
-12) )
1511 memcpy( payload
+ptr
-12, rx_buff
->mac
, 12);
1515 if (!payload
|| !skb
|| !rx_buff
->skb
|| !rx_buff
->u
.rx
.payload
)
1517 //skb->ip_summed = CHECKSUM_NONE;
1518 skb
->data
= payload
+ ptr
-12;
1521 rx_buff
->skb
->protocol
= eth_type_trans(rx_buff
->skb
,dev
);
1522 DEBUG(0x200,"eth_type_trans decided: %x\n",rx_buff
->skb
->protocol
);
1523 rx_buff
->skb
= NULL
;
1524 rx_buff
->u
.rx
.payload
= NULL
;
1525 priv
->stats
.rx_packets
++;
1527 AWC_ENTRY_EXIT_DEBUG("exit\n");
1531 DEBUG(0x200,"%s packet dropped in packet hdr parse \n ",dev
->name
);
1532 if (rx_buff
->skb
&& (rx_buff
->type
& p80211copy_path_skb
)){
1534 FREE_SKB(rx_buff
->skb
);
1535 rx_buff
->skb
= NULL
;
1536 rx_buff
->u
.rx
.payload
= NULL
;
1539 AWC_ENTRY_EXIT_DEBUG("exit\n");
1544 awc_802_11_failed_rx_copy(struct NET_DEVICE
* dev
,struct awc_fid
* rx_buff
){
1545 struct awc_private
* priv
= (struct awc_private
* )dev
->priv
;
1548 AWC_ENTRY_EXIT_DEBUG("awc_802_11_failed_rx_copy");
1550 FREE_SKB(rx_buff
->skb
);
1551 rx_buff
->skb
= NULL
;
1552 rx_buff
->u
.rx
.payload
= NULL
;
1553 priv
->stats
.rx_errors
++;
1556 AWC_ENTRY_EXIT_DEBUG("exit\n");
1560 called from kernel->driver tx routine
1561 must decide where and how to post the packet
1562 must post the packet to wherever it decides
1563 either copy to card or enqueue to destination queue
1569 awc_802_11_tx_find_path_and_post(struct NET_DEVICE
* dev
,
1570 struct sk_buff
* skb
){
1573 struct awc_private
* priv
= (struct awc_private
* )dev
->priv
;
1575 int len
= ETH_ZLEN
< skb
->len
? skb
->len
: ETH_ZLEN
; /* check min length*/
1576 struct awc_fid
* fid
= NULL
;
1578 u16 p2p_direct
=priv
->p2p_found
;
1579 // struct iphdr * ip_hdr;
1580 //buffer = skb->data;
1582 AWC_ENTRY_EXIT_DEBUG("awc_802_11_tx_find_path_and_post");
1584 DOWN(&priv
->tx_buff_semaphore
);
1585 if (len
> dev
->mtu
+ 16 ) {
1586 printk(KERN_ERR
"%s packet size too large %d \n",dev
->name
, len
);
1590 if (len
+ AWC_TX_HEAD_SIZE
< AWC_TX_ALLOC_SMALL_SIZE
)
1591 fid
= awc_fid_queue_pop_head(&priv
->tx_small_ready
);
1594 fid
= awc_fid_queue_pop_head(&priv
->tx_large_ready
);
1597 DEBUG(32,"%s buffs in use \n",dev
->name
);
1601 if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE){
1602 awc_fid_queue_push_tail(&priv->tx_small_ready, fid);
1603 fid = awc_fid_queue_pop_head(&priv->tx_large_ready);
1607 DEBUG(32,"%s buffs in use \n",dev
->name
);
1611 if (fid
->u
.tx
.fid_size
< len
+ AWC_TX_HEAD_SIZE
- 14){
1612 printk(KERN_ERR
"found too small tx fid size %d, pktlen %d \n",fid
->u
.tx
.fid_size
, len
);
1614 memset(&fid
->u
.tx
.radio_tx
, 0,sizeof(struct aironet4500_radio_tx_header
));
1615 memset(&fid
->u
.tx
.ieee_802_11
, 0,sizeof(struct ieee_802_11_header
));
1616 memset(&fid
->u
.tx
.ieee_802_3
, 0,sizeof(struct ieee_802_3_header
));
1617 fid
->u
.tx
.payload
=NULL
;
1618 fid
->u
.tx
.gap_length
=0;
1622 priv
->tx_buffs_in_use
++;
1623 DEBUG(32,"found large buff %x \n",fid
->u
.tx
.fid
);
1626 fid->type |= p80211_llc_snap;
1627 fid->snap.dsap = 0xaa;
1628 fid->snap.ssap = 0xaa;
1629 fid->snap.ctrl = 0x03;
1630 fid->snap.oui[0] = 0x0;
1631 fid->snap.oui[1] = 0x0;
1632 fid->snap.oui[2] = 0x0;
1637 if (priv
->p2p_uc
&& !priv
->p2p_found
){ // we go without encapsulation to neighbour;
1639 for (i
=0; i
< 6; i
++)
1640 if (priv
->p2p
[i
] != skb
->data
[i
]){
1646 if (tx_rate
== 2 || tx_rate
== 4 || tx_rate
== 20 || tx_rate
== 22)
1647 fid
->u
.tx
.radio_tx
.tx_bit_rate
= tx_rate
;
1648 fid
->u
.tx
.radio_tx
.TX_Control
=
1649 aironet4500_tx_control_tx_ok_event_enable
|
1650 aironet4500_tx_control_tx_fail_event_enable
|
1651 aironet4500_tx_control_no_release
;
1654 fid->u.tx.radio_tx.TX_Control |=
1655 aironet4500_tx_control_use_rts;
1658 /* ip_hdr = skb->data + 14;
1659 if (ip_hdr && skb->data[12] == 0x80 ){
1660 if (ip_hdr->tos & IPTOS_RELIABILITY)
1661 fid->u.tx.radio_tx.TX_Control |=
1662 aironet4500_tx_control_use_rts;
1663 if (ip_hdr->tos & IPTOS_THROUGHPUT)
1664 fid->u.tx.radio_tx.TX_Control |=
1665 aironet4500_tx_control_no_retries;
1668 if (priv
->p802_11_send
|| memcmp(dev
->dev_addr
, skb
->data
+6, 6) ){
1669 fid
->u
.tx
.radio_tx
.TX_Control
|=
1670 aironet4500_tx_control_header_type_802_11
;
1671 DEBUG(0x200,"%s bridging, forcing 802_11 send \n ",dev
->name
);
1675 if (!priv
->p2p_uc
|| p2p_direct
) {
1676 if ((fid
->u
.tx
.radio_tx
.TX_Control
&
1677 aironet4500_tx_control_header_type_802_11
)){
1679 // including 802.3 header into 802.11 packet
1680 fid
->u
.tx
.radio_tx
.PayloadLength
= len
-12;
1681 fid
->u
.tx
.ieee_802_3
.payload_length
= len
-12 ;
1682 fid
->pkt_len
= len
-12;
1683 fid
->u
.tx
.payload
= skb
->data
+12;
1685 if (!memcmp(dev
->dev_addr
, skb
->data
+6, 6)){
1686 memcpy(fid
->u
.tx
.ieee_802_11
.mac1
,skb
->data
,6);
1687 memcpy(fid
->u
.tx
.ieee_802_11
.mac2
,skb
->data
+6,6);
1688 memcpy(fid
->u
.tx
.ieee_802_11
.mac3
,priv
->status
.CurrentBssid
,6);
1689 memset(fid
->u
.tx
.ieee_802_11
.mac4
,0,6);
1690 fid
->u
.tx
.ieee_802_11
.frame_control
= 0x8;
1691 fid
->u
.tx
.ieee_802_11
.gapLen
=6;
1694 memcpy(fid
->u
.tx
.ieee_802_11
.mac1
,skb
->data
,6);
1695 memcpy(fid
->u
.tx
.ieee_802_11
.mac2
,dev
->dev_addr
,6);
1696 memcpy(fid
->u
.tx
.ieee_802_11
.mac3
,skb
->data
+6 ,6);
1697 memset(fid
->u
.tx
.ieee_802_11
.mac4
,0 ,6);
1698 fid
->u
.tx
.ieee_802_11
.frame_control
= 0x108;
1699 fid
->u
.tx
.ieee_802_11
.gapLen
=6;
1702 } else { // plain old 802.3, with hdr copied
1703 fid
->u
.tx
.radio_tx
.PayloadLength
= len
-12;
1704 fid
->u
.tx
.ieee_802_3
.payload_length
= len
-12;
1705 fid
->pkt_len
= len
- 12;
1706 fid
->u
.tx
.payload
= skb
->data
+12;
1708 memcpy(fid
->u
.tx
.ieee_802_3
.dst_mac
,skb
->data
, 12);
1709 DEBUG(0x200,"%s tx simply 802.3 type \n ",dev
->name
);
1711 } else {// 802.1H bridgeing
1712 fid
->type
|= p80211_8021H
;
1713 fid
->bridge_size
= len
+ sizeof(fid
->bridge
) ;
1714 fid
->bridge
.dsap
= 0xaa;
1715 fid
->bridge
.ssap
= 0xaa;
1716 fid
->bridge
.ctrl
= 0x03;
1717 fid
->bridge
.oui
[0] = 0x0;
1718 fid
->bridge
.oui
[1] = 0x40;
1719 fid
->bridge
.oui
[2] = 0x96;
1720 fid
->bridge
.unknown1
= 0x0000;
1721 fid
->bridge
.unknown2
= htons((len
) & 0x1000);
1722 fid
->u
.tx
.radio_tx
.PayloadLength
= fid
->bridge_size
+ 2;
1723 fid
->u
.tx
.ieee_802_3
.payload_length
= fid
->u
.tx
.radio_tx
.PayloadLength
;
1726 fid
->u
.tx
.payload
= skb
->data
+12;
1727 if ((fid
->u
.tx
.radio_tx
.TX_Control
&
1728 aironet4500_tx_control_header_type_802_11
)){
1730 memcpy(fid
->u
.tx
.ieee_802_11
.mac1
,priv
->p2p
,6);
1731 memcpy(fid
->u
.tx
.ieee_802_11
.mac2
,skb
->data
+6,6);
1732 memcpy(fid
->u
.tx
.ieee_802_11
.mac3
,priv
->bssid
,6);
1733 memset(fid
->u
.tx
.ieee_802_11
.mac4
,0,6);
1734 fid
->u
.tx
.ieee_802_11
.gapLen
=6;
1736 fid
->u
.tx
.ieee_802_11
.frame_control
= 0x8;
1738 memcpy(fid
->u
.tx
.ieee_802_3
.dst_mac
,priv
->p2p
, 6);
1739 memcpy(fid
->u
.tx
.ieee_802_3
.src_mac
,dev
->dev_addr
, 6);
1740 fid
->u
.tx
.payload
= skb
->data
+ 2 + sizeof(fid
->bridge
);
1741 fid
->pkt_len
= len
;
1743 DEBUG(0x200,"%s tx simply 802.1H type \n ",dev
->name
);
1749 awc_fid_queue_push_tail(&priv
->tx_in_transmit
,fid
);
1751 awc_transmit_packet(dev
,fid
);
1752 UP(&priv
->tx_buff_semaphore
);
1753 if (priv
->tx_large_ready
.size
> 0 ){
1757 AWC_ENTRY_EXIT_DEBUG("exit\n");
1762 DEBUG(32,"%s tx buffs not found \n ",dev
->name
);
1766 dev
->tbusy
= 1; //weell, here it must be set anyway and before
1767 //priv->stats.tx_fifo_errors++;
1768 UP(&priv
->tx_buff_semaphore
);
1769 AWC_ENTRY_EXIT_DEBUG("NoSpaceExit\n");
1772 priv
->stats
.tx_errors
++;
1773 UP(&priv
->tx_buff_semaphore
);
1777 AWC_ENTRY_EXIT_DEBUG("BADExit\n");
1783 called from low level driver->card tx copy routine
1784 probably wants to free skbuf if failed transmits won't be
1785 resubmitted to another device (if more than one path)
1786 or tried again (if tx buffer in card needs to be filled again)
1791 awc_802_11_after_tx_packet_to_card_write(struct NET_DEVICE
* dev
,
1792 struct awc_fid
* tx_buff
){
1795 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_packet_to_card_write");
1798 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_tx_packet_to_card_write \n",dev
->name
);
1802 FREE_SKB(tx_buff
->skb
);
1803 tx_buff
->skb
= NULL
;
1807 AWC_ENTRY_EXIT_DEBUG("exit\n");
1811 called from low level driver->card tx copy routine
1812 probably wants to free skbuf if failed writes won't be
1813 resubmitted to another device (if more than one path)
1814 or tried again (if tx buffer in card needs to be filled again)
1818 awc_802_11_after_failed_tx_packet_to_card_write(struct NET_DEVICE
* dev
,
1819 struct awc_fid
* tx_buff
){
1820 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1823 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_failed_tx_packet_to_card_write");
1826 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_failed_tx_packet_to_card_write \n",dev
->name
);
1830 FREE_SKB(tx_buff
->skb
);
1831 tx_buff
->skb
= NULL
;
1833 printk(KERN_ERR
"%s packet to card write failed \n",dev
->name
);
1836 awc_fid_queue_remove(&priv
->tx_in_transmit
,tx_buff
);
1838 if (tx_buff
->u
.tx
.fid_size
<= AWC_TX_ALLOC_SMALL_SIZE
)
1839 awc_fid_queue_push_tail(&priv
->tx_small_ready
,tx_buff
);
1841 awc_fid_queue_push_tail(&priv
->tx_large_ready
,tx_buff
);
1843 AWC_ENTRY_EXIT_DEBUG("exit\n");
1848 awc_802_11_after_tx_complete(struct NET_DEVICE
* dev
, struct awc_fid
* tx_buff
){
1850 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
1852 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_complete");
1854 DEBUG(32,"tx complete status %x \n ",tx_buff
->u
.tx
.radio_tx
.Status
);
1857 if (tx_buff
->u
.tx
.radio_tx
.Status
)
1858 printk("tf%x ",tx_buff
->u
.tx
.radio_tx
.Status
);
1860 if (tx_buff
->u
.tx
.fid_size
<= AWC_TX_ALLOC_SMALL_SIZE
){
1861 awc_fid_queue_push_tail(&priv
->tx_small_ready
,tx_buff
);
1862 priv
->tx_small_buffs_in_use
--;
1864 awc_fid_queue_push_tail(&priv
->tx_large_ready
,tx_buff
);
1865 priv
->tx_buffs_in_use
--;
1872 AWC_ENTRY_EXIT_DEBUG("exit\n");
1878 /******************************** R X ***********************/
1883 awc_receive_packet(struct NET_DEVICE
* dev
){
1885 struct awc_command cmd
;
1887 // struct sk_buff *skb = NULL;
1888 struct awc_fid
* rx_buff
;
1891 struct awc_private
* priv
;
1894 priv
= (struct awc_private
*)dev
->priv
;
1895 rx_buff
= priv
->rx_ready
.head
;
1897 AWC_ENTRY_EXIT_DEBUG(" entry awc_receive_packet ");
1899 Fid
= awc_Rx_Fid(dev
->base_addr
);
1901 DEBUG(128," RX FID %x \n",Fid
);
1904 printk(KERN_CRIT
"No RxFid when rx event \n");
1911 printk(KERN_CRIT
"No rx_buff in rx event \n");
1918 AWC_INIT_COMMAND(AWC_CLI
,cmd
,dev
,0,0,
1919 Fid
, 0, 0x14 , &(rx_buff
->u
.rx
.radio_rx
));
1922 // header reading , order is important
1923 AWC_BAP_LOCK_UNDER_CLI(cmd
);
1925 if (awc_bap_setup(&cmd
)) goto final
;
1926 if (awc_bap_read(&cmd
)) goto final
;
1928 DEBUG(128, "rx receive radio header, length %x \n",rx_buff
->u
.rx
.radio_rx
.PayloadLength
);
1930 cmd
.buff
= &(rx_buff
->u
.rx
.ieee_802_11
);
1933 if (awc_bap_read(&cmd
)) goto final
;
1935 DEBUG(128, "rx receive 802_11 header, framecontrol %x \n",rx_buff
->u
.rx
.ieee_802_11
.frame_control
);
1937 if (rx_buff
->u
.rx
.ieee_802_11
.gapLen
> 8) {
1938 printk(KERN_ERR
"%s: 802.11 gap lenght huge %d \n",dev
->name
,rx_buff
->u
.rx
.ieee_802_11
.gapLen
);
1941 DEBUG(128,"SeqCtl %x, 802_11 macs: ",rx_buff
->u
.rx
.ieee_802_11
.SeqCtl
);
1942 if (awc_debug
& 0x7000){
1943 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
] )) ;
1944 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
] )) ;
1945 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
] )) ;
1946 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
] )) ;
1948 DEBUG(128,"\n GapLen %d ",rx_buff
->u
.rx
.ieee_802_11
.gapLen
);
1950 if (rx_buff
->u
.rx
.ieee_802_11
.gapLen
> 0) {
1951 cmd
.buff
= rx_buff
->u
.rx
.ieee_802_11
.gap
;
1952 cmd
.len
= rx_buff
->u
.rx
.ieee_802_11
.gapLen
;
1953 if (awc_bap_read(&cmd
)) goto final
;
1954 DEBUG(128, "rx receive gap header , gap length %x \n",rx_buff
->u
.rx
.gap_length
);
1956 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
] )) ;
1959 if ( !(priv
->config
.ReceiveMode
& RXMODE_DISABLE_802_3_HEADER
)
1961 cmd
.buff
= &(rx_buff
->u
.rx
.ieee_802_3
);
1963 rx_buff
->type
|= p80211_8023
;
1964 if (awc_bap_read(&cmd
)) goto final
;
1965 DEBUG(128, "rx receive 802_3 header, payload length %x \n",rx_buff
->u
.rx
.ieee_802_3
.payload_length
);
1966 DEBUG(128,"\n 802_3 status %x ",rx_buff
->u
.rx
.ieee_802_3
.status
);
1967 DEBUG(128," RX payloadLen %x, dst,src: ",rx_buff
->u
.rx
.ieee_802_3
.payload_length
);
1968 if (awc_debug
& 0x7000){
1969 for (i
= 0; i
< 6; i
++) printk("%02x:",((unsigned char)rx_buff
->u
.rx
.ieee_802_3
.dst_mac
[i
] )) ;
1970 for (i
= 0; i
< 6; i
++) printk("%02x:",((unsigned char)rx_buff
->u
.rx
.ieee_802_3
.src_mac
[i
] )) ;
1974 rx_buff
->pkt_len
= rx_buff
->u
.rx
.radio_rx
.PayloadLength
;
1976 if (priv
->config
.OperatingMode
& MODE_LLC_HOST
)
1977 rx_buff
->type
|= p80211_llc_snap
;
1980 if (awc_802_11_find_copy_path(dev
,rx_buff
)) goto final
;
1983 if (rx_buff
->u
.rx
.payload
){
1984 cmd
.buff
= rx_buff
->u
.rx
.payload
;
1985 cmd
.len
= rx_buff
->pkt_len
;
1986 if (awc_bap_read(&cmd
)) goto final
;
1987 DEBUG(128, "rx payload read %x \n",rx_buff
->u
.rx
.ieee_802_3
.payload_length
);
1990 AWC_RELEASE_COMMAND(cmd
);
1992 DEBUG(128,"\n payload hdr %x ",rx_buff
->u
.rx
.ieee_802_3
.status
);
1993 if (awc_debug
&& rx_buff
->u
.rx
.payload
)
1994 for (i
= 0; i
< 20; i
++) DEBUG(128,"%x",((unsigned char)rx_buff
->u
.rx
.payload
[i
] )) ;
1995 DEBUG(128,"%c",'\n');
1997 awc_802_11_router_rx(dev
,rx_buff
);
1999 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2003 awc_802_11_failed_rx_copy(dev
,rx_buff
);
2004 // if (skb) dev_kfree_skb(skb, FREE_WRITE);
2005 AWC_RELEASE_COMMAND(cmd
);
2006 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2013 awc_transmit_packet(struct NET_DEVICE
* dev
, struct awc_fid
* tx_buff
) {
2015 struct awc_command cmd
;
2017 // unsigned long flags;
2019 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
2021 AWC_ENTRY_EXIT_DEBUG(" entry awc_transmit_packet ");
2023 if (priv
->link_status_changed
){
2024 priv
->link_status_changed
=0;
2025 awc_readrid_dir(dev
,&priv
->rid_dir
[7]);
2029 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0xB, tx_buff
->u
.tx
.fid
,
2030 tx_buff
->u
.tx
.fid
, 0, 0x14 , &(tx_buff
->u
.tx
.radio_tx
));
2032 AWC_BAP_LOCK_NOT_CLI(cmd
);
2035 #warning By books is bad, AWC_BY_BOOK
2036 #error cli sti bad here
2037 if ( !(tx_buff
->type
&(p80211_llc_snap
|p80211_8021H
) )
2038 && !(tx_buff
->u
.tx
.radio_tx
.TX_Control
&
2039 aironet4500_tx_control_header_type_802_11
)){
2041 cmd
.buff
=&(tx_buff
->u
.tx
.radio_tx
.TX_Control
);
2046 if (awc_bap_setup(&cmd
)) goto final
;
2047 if (awc_bap_write(&cmd
)) goto final
;
2049 cmd
.buff
=&(tx_buff
->u
.tx
.ieee_802_3
.payload_length
);
2052 if (awc_bap_setup(&cmd
)) goto final
;
2053 if (awc_bap_write(&cmd
)) goto final
;
2054 restore_flags(flags
);
2059 if (awc_bap_setup(&cmd
)) goto final
;
2060 if (awc_bap_write(&cmd
)) goto final
;
2062 DEBUG(64," wrote radio tx header for fid %x \n",tx_buff
->u
.tx
.fid
);
2065 cmd
.buff
=&(tx_buff
->u
.tx
.ieee_802_11
);
2067 if (awc_bap_write(&cmd
)) goto final
;
2070 if (tx_buff
->u
.tx
.ieee_802_11
.gapLen
) {
2071 cmd
.buff
=&(tx_buff
->u
.tx
.ieee_802_11
.gap
);
2072 cmd
.len
= tx_buff
->u
.tx
.ieee_802_11
.gapLen
;
2073 if (awc_bap_write(&cmd
)) goto final
;
2076 if ( ! (tx_buff
->u
.tx
.radio_tx
.TX_Control
&
2077 aironet4500_tx_control_header_type_802_11
)){
2079 cmd
.buff
=&(tx_buff
->u
.tx
.ieee_802_3
);
2080 if (awc_debug
& 0x7000){
2081 printk("%s TX dst ",dev
->name
);
2082 for (i
=0; i
< 6; i
++) printk ("%02x:",(unsigned char) tx_buff
->u
.tx
.ieee_802_3
.dst_mac
[i
]);
2084 for (i
=0; i
< 6; i
++) printk ("%02x:",(unsigned char) tx_buff
->u
.tx
.ieee_802_3
.src_mac
[i
]);
2088 if (awc_bap_write(&cmd
)) goto final
;
2091 if (tx_buff
->type
& p80211_llc_snap
) {
2092 cmd
.buff
= & tx_buff
->snap
;
2093 cmd
.len
= sizeof(tx_buff
->snap
);
2094 if (awc_bap_write(&cmd
)) goto final
;
2097 if (tx_buff
->type
& p80211_8021H
) {
2098 size
= htons(tx_buff
->bridge_size
);
2099 // size = tx_buff->bridge_size;// to seasure raw speed of f** UC
2102 if (awc_bap_write(&cmd
)) goto final
;
2104 cmd
.buff
= & tx_buff
->bridge
;
2105 cmd
.len
= sizeof(tx_buff
->bridge
);
2106 if (awc_bap_write(&cmd
)) goto final
;
2113 cmd
.buff
= tx_buff
->u
.tx
.payload
;
2114 cmd
.len
= tx_buff
->pkt_len
;
2116 if (awc_bap_write(&cmd
)) goto final
;
2117 AWC_RELEASE_COMMAND(cmd
);
2118 // locking probs, these two lines below and above, swithc order
2119 if (awc_issue_command_and_block(&cmd
)) goto final_unlocked
;
2122 tx_buff
->transmit_start_time
= jiffies
;
2123 awc_802_11_after_tx_packet_to_card_write(dev
,tx_buff
);
2124 // issue the transmit command
2127 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2130 awc_802_11_after_failed_tx_packet_to_card_write(dev
,tx_buff
);
2131 printk(KERN_CRIT
"%s awc tx command failed \n",dev
->name
);
2132 AWC_RELEASE_COMMAND(cmd
);
2133 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2137 awc_802_11_after_failed_tx_packet_to_card_write(dev
,tx_buff
);
2138 printk(KERN_CRIT
"%s awc tx command failed \n",dev
->name
);
2139 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2146 awc_tx_complete_check(struct NET_DEVICE
* dev
){
2148 struct awc_fid
* fid
;
2149 struct awc_command cmd
;
2152 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_complete_check ");
2156 fid
= awc_fid_queue_pop_head(&((struct awc_private
*)dev
->priv
)->tx_post_process
);
2159 printk("awc_tx_complete_check with empty queue \n ");
2163 DEBUG(64," tx_complete fid %x \n",fid
->u
.tx
.fid
);
2165 AWC_INIT_COMMAND(AWC_NOT_CLI
,cmd
,dev
,0,0, fid
->u
.tx
.fid
,
2166 0, 0x14 , &(fid
->u
.tx
.radio_tx
));
2168 fid
->state
|= awc_tx_fid_complete_read
;
2170 AWC_BAP_LOCK_NOT_CLI(cmd
);
2171 if (awc_bap_setup(&cmd
)) goto final
;
2172 if (awc_bap_read(&cmd
)) goto final
;
2173 AWC_RELEASE_COMMAND(cmd
);
2175 awc_802_11_after_tx_complete(dev
,fid
);
2178 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2182 awc_802_11_after_tx_complete(dev
,fid
);
2183 printk(KERN_ERR
"%s awc_tx_complete_check failed \n",dev
->name
);
2184 AWC_RELEASE_COMMAND(cmd
);
2185 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2190 #define AWC_QUEUE_BH {\
2191 if (!priv->bh_active && !priv->bh_running){\
2192 priv->bh_active = 1;\
2193 queue_task(&priv->immediate_bh, &tq_immediate);\
2194 mark_bh(IMMEDIATE_BH);\
2200 awc_bh(struct NET_DEVICE
*dev
){
2202 struct awc_private
* priv
= (struct awc_private
*)dev
->priv
;
2203 int active_interrupts
;
2204 int enabled_interrupts
;
2208 // unsigned long flags;
2210 DEBUG(8, "awc_bh awoken on jiffie %ld \n",jiffies
);
2212 priv
->bh_running
= 1;
2214 active_interrupts
= awc_event_status(dev
->base_addr
);
2216 enabled_interrupts
= awc_ints_enabled(dev
->base_addr
);
2218 DEBUG(8, "awc_bh active ints %x \n",active_interrupts
);
2220 if (test_and_set_bit( 0, (void *) &priv
->tx_chain_active
) ) {
2221 // printk(KERN_ERR "tx chain active in bh \n");
2222 // queue_task(&priv->immediate_bh, &tq_immediate);
2226 if (active_interrupts
== 0xffff){
2228 printk(KERN_CRIT
"%s device ejected in interrupt, disabling\n",dev
->name
);
2231 if (priv
->command_semaphore_on
){
2232 priv
->command_semaphore_on
--;
2233 AWC_UNLOCK_COMMAND_ISSUING(priv
);
2235 priv
->tx_chain_active
=0;
2240 if (priv
->unlock_command_postponed
){
2242 priv
->unlock_command_postponed
-- ;
2243 if( priv
->command_semaphore_on
){
2245 awc_read_response((&priv
->cmd
));
2246 priv
->async_command_start
= 0;
2247 if (priv
->command_semaphore_on
){
2249 priv
->command_semaphore_on
--;
2250 AWC_UNLOCK_COMMAND_ISSUING(priv
);
2255 /* if ( active_interrupts & 0x1 ){
2256 awc_receive_packet(dev) ;
2257 awc_event_ack_Rx(dev->base_addr);
2258 priv->waiting_interrupts &= ~0x1;
2261 while (priv
->tx_post_process
.size
)
2262 if (awc_tx_complete_check(dev
)) break;
2264 active_interrupts
= awc_event_status(dev
->base_addr
);
2266 if (priv
->command_semaphore_on
|| priv
->tx_post_process
.size
){
2267 if (multi_ints
++ < 10000){
2271 priv
->bh_active
= 0;
2272 priv
->bh_running
= 0;
2274 priv
->tx_chain_active
= 0;
2279 // if (!priv->tx_chain_active)
2280 // wake_up(&priv->tx_chain_wait_queue);
2282 priv
->bh_running
= 0;
2283 priv
->bh_active
= 0;
2289 awc_interrupt_process(struct NET_DEVICE
* dev
){
2291 struct awc_private
* priv
;
2292 int active_interrupts
;
2293 int enabled_interrupts
;
2297 // u16 ints_to_ack =0;
2298 struct awc_fid
* fid
= NULL
;
2299 // int interrupt_reenter = 0;
2300 // unsigned long flags;
2302 // save_flags(flags);
2304 // disable_irq(dev->irq);
2306 DEBUG(2," entering interrupt handler %s ",dev
->name
);
2309 printk(KERN_ERR
"No dev in interrupt \n");
2313 priv
= (struct awc_private
*)dev
->priv
;
2316 printk(KERN_ERR
"No PRIV in interrupt \n");
2321 enabled_interrupts
= awc_ints_enabled(dev
->base_addr
);
2322 active_interrupts
= awc_event_status(dev
->base_addr
);
2324 DEBUG(2,"entry: processing interrupts waiting %x \n",priv
->waiting_interrupts
);
2325 DEBUG(2,"entry: processing interrupts active %x \n",active_interrupts
);
2326 DEBUG(2,"entry: processing interrupts enabled %x \n",enabled_interrupts
);
2327 // printk("ikka interruptis\n");
2330 if (test_and_set_bit( 0, (void *) &dev
->interrupt
) ) {
2332 goto reenter_end_here
;
2334 priv
->interrupt_count
++;
2335 if (priv
->interrupt_count
> 1 )
2336 printk(" interrupt count on\n ");
2340 if (priv
->waiting_interrupts
& active_interrupts
)
2341 printk(KERN_ERR
"double interrupt waiting %x active %x \n",
2342 priv
->waiting_interrupts
, active_interrupts
);
2344 // priv->waiting_interrupts |= active_interrupts;
2351 DEBUG(2,"Start processing int, times %d\n",multi_ints
);
2353 if (active_interrupts
== 0xffff){
2355 printk(KERN_CRIT
"%s device ejected, got interrupt, disabling\n",dev
->name
);
2360 if (priv
->bh_active
|| priv
->bh_running
){
2361 priv
->interrupt_count
--;
2364 } else if (priv
->command_semaphore_on
){
2366 printk(KERN_ERR
"ejected, last BH fired \n");
2370 priv
->interrupt_count
--;
2377 if (active_interrupts
& 0x100 ){
2378 awc_event_ack_Awaken(dev
->base_addr
);
2380 DEBUG(1,"%s device awoke \n",dev
->name
);
2381 priv
->waiting_interrupts
&= ~0x100;
2383 if (active_interrupts
& 0x80 ){
2385 priv
->link_status
= awc_Link_Status(dev
->base_addr
);
2386 DEBUG(1,"link status changed %x \n",priv
->link_status
);
2387 awc_event_ack_Link(dev
->base_addr
);
2388 priv
->waiting_interrupts
&= ~0x80;
2389 if(priv
->link_status
== 0x400)
2390 printk(KERN_INFO
"%s Associated\n",dev
->name
);
2392 printk(KERN_INFO
"%s Link status change : %s \n",dev
->name
, awc_print_string(awc_link_status_names
, priv
->link_status
) );
2393 if ( priv
->link_status
& 0x8100 ||
2394 priv
->link_status
& 0x0100 ||
2395 priv
->link_status
& 0x8200 ||
2396 priv
->link_status
& 0x8400 ||
2397 priv
->link_status
& 0x0300 )
2398 printk(KERN_INFO
"%s Link status change reason : %s \n",dev
->name
, awc_print_string(awc_link_failure_reason_names
, priv
->link_status
& 0xff) );
2404 if (active_interrupts
& 0x10 & enabled_interrupts
){
2406 // printk(KERN_ERR "cmd int shouldnt be active in interrupt routine\n");
2408 awc_event_ack_Cmd(priv
->cmd
.port
);
2410 if ( priv
->enabled_interrupts
& 0x10)
2411 priv
->enabled_interrupts
&= ~0x10;
2413 enabled_interrupts
= awc_ints_enabled(dev
->base_addr
);
2415 if (enabled_interrupts
& 0x10){
2416 awc_ints_enable(dev
->base_addr
, enabled_interrupts
& ~0x10);
2419 if (priv
->command_semaphore_on
){
2420 priv
->unlock_command_postponed
++;
2426 if ((active_interrupts
& 0x10) && !(0x10 & enabled_interrupts
) ){
2428 // printk(KERN_ERR "%s: aironet4500: cmd int shouldnt be active in interrupt routine\n",dev->name);
2430 //awc_event_ack_Cmd(priv->cmd.port);
2434 // active_interrupts = awc_event_status(dev->base_addr);
2436 tx_status
= active_interrupts
& 0x6 ;
2442 tx_fid
= awc_Tx_Compl_Fid(dev
->base_addr
);
2445 tx_fid
= awc_Tx_Compl_Fid(dev
->base_addr
);
2448 printk(KERN_ERR
"No tx fid when tx int active\n");
2450 fid
= awc_tx_fid_lookup_and_remove(dev
, tx_fid
);
2453 if (priv
->process_tx_results
) {
2454 awc_fid_queue_push_tail(&priv
->tx_post_process
,fid
);
2457 if (fid
->u
.tx
.fid_size
<= AWC_TX_ALLOC_SMALL_SIZE
)
2458 awc_fid_queue_push_tail(&priv
->tx_small_ready
,fid
);
2460 awc_fid_queue_push_tail(&priv
->tx_large_ready
,fid
);
2465 printk(KERN_ERR
"awc fid %x not found\n",tx_fid
);
2469 awc_event_ack_Tx(dev
->base_addr
);
2470 priv
->stats
.tx_packets
++;
2471 priv
->waiting_interrupts
&= ~0x2;
2474 priv
->stats
.tx_errors
++;
2475 awc_event_ack_TxExc(dev
->base_addr
);
2476 priv
->waiting_interrupts
&= ~0x4;
2478 if ((tx_status
&6) == 6)
2479 printk(KERN_NOTICE
"%s: both tx and txExc up\n",dev
->name
);
2484 // active_interrupts = awc_event_status(dev->base_addr);
2486 if ( active_interrupts
& 0x1 ){
2487 awc_receive_packet(dev
);
2488 awc_event_ack_Rx(dev
->base_addr
);
2489 priv
->waiting_interrupts
&= ~0x1;
2492 active_interrupts
= awc_event_status(dev
->base_addr
);
2494 if ((active_interrupts
& 0x7) &&
2496 !priv
->bh_running
){
2497 if (multi_ints
++ < 5)
2500 if (multi_ints
>=5 )
2501 printk(KERN_ERR
"%s multi_ints > 5 interrupts still active %x\n",dev
->name
,active_interrupts
);
2504 priv
->interrupt_count
--;
2507 awc_ints_enable(dev
->base_addr
, 0x0000);
2510 DEBUG(0x8, " enabling ints in interrupt_process %x \n",
2511 priv
->enabled_interrupts
& ~priv
->waiting_interrupts
);
2515 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2517 awc_ints_enable(dev
->base_addr
,
2518 priv
->enabled_interrupts
);
2522 // enable_irq(dev->irq);
2523 // restore_flags(flags);
2528 AWC_ENTRY_EXIT_DEBUG(" reenter-bad end exit \n");
2529 // enable_irq(dev->irq);
2530 // restore_flags(flags);
2535 AWC_ENTRY_EXIT_DEBUG(" bad_end exit \n");
2536 // enable_irq(dev->irq);
2537 // restore_flags(flags);
2543 static const char *aironet4500_core_version
=
2544 "aironet4500.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
2546 struct NET_DEVICE
* aironet4500_devices
[MAX_AWCS
] = {NULL
,NULL
,NULL
,NULL
};
2548 static int awc_debug
= 0; // 0xffffff;
2549 static int p802_11_send
= 0; // 1
2551 static int awc_process_tx_results
= 0;
2552 int tx_queue_len
= 10;
2554 static int channel
= 5;
2555 //static int tx_full_rate = 0;
2556 static int max_mtu
= 2312;
2557 static int adhoc
= 0;
2558 static int large_buff_mem
= 1700 * 10;
2559 static int small_buff_no
= 20;
2560 static int awc_full_stats
= 0;
2561 static char SSID
[33] = {0};
2562 static int master
= 0;
2563 static int slave
= 0;
2566 #if LINUX_VERSION_CODE >= 0x20100
2568 MODULE_PARM(awc_debug
,"i");
2569 MODULE_PARM(rx_queue_len
,"i");
2570 MODULE_PARM(tx_rate
,"i");
2571 MODULE_PARM(channel
,"i");
2572 MODULE_PARM(tx_full_rate
,"i");
2573 MODULE_PARM(adhoc
,"i");
2574 MODULE_PARM(master
,"i");
2575 MODULE_PARM(slave
,"i");
2576 MODULE_PARM(max_mtu
,"i");
2577 MODULE_PARM(large_buff_mem
,"i");
2578 MODULE_PARM(small_buff_no
,"i");
2579 MODULE_PARM(SSID
,"1-4c31");
2582 /*EXPORT_SYMBOL(tx_queue_len);
2583 EXPORT_SYMBOL(awc_debug);
2585 EXPORT_SYMBOL(awc_init
);
2586 EXPORT_SYMBOL(awc_open
);
2587 EXPORT_SYMBOL(awc_close
);
2588 EXPORT_SYMBOL(awc_reset
);
2589 EXPORT_SYMBOL(awc_config
);
2591 EXPORT_SYMBOL(aironet4500_devices
);
2592 EXPORT_SYMBOL(awc_debug
);
2595 EXPORT_SYMBOL(awc_private_init
);
2596 EXPORT_SYMBOL(awc_tx_timeout
);
2597 EXPORT_SYMBOL(awc_start_xmit
);
2598 EXPORT_SYMBOL(awc_tx_done
);
2599 EXPORT_SYMBOL(awc_rx
);
2600 EXPORT_SYMBOL(awc_interrupt
);
2601 EXPORT_SYMBOL(awc_get_stats
);
2602 EXPORT_SYMBOL(awc_change_mtu
);
2603 EXPORT_SYMBOL(awc_set_multicast_list
);
2605 EXPORT_SYMBOL(awc_proc_set_fun
);
2606 EXPORT_SYMBOL(awc_proc_unset_fun
);
2607 EXPORT_SYMBOL(awc_register_proc
);
2608 EXPORT_SYMBOL(awc_unregister_proc
);
2611 /*************************** RESET INIT CONFIG ***********************/
2614 void awc_reset(struct NET_DEVICE
*dev
)
2619 DEBUG(2, " awc_reset dev %x \n", (int)dev
);
2620 DEBUG(2, "%s: awc_reset \n", dev
->name
);
2622 awc_issue_soft_reset(dev
);
2626 while (awc_command_read(dev
->base_addr
)){
2628 if (jiffies
- jiff
> 5*HZ
){
2629 printk(KERN_CRIT
"%s bad reset\n",dev
->name
);
2636 int awc_config(struct NET_DEVICE
*dev
)
2638 // struct awc_private *priv = (struct awc_private *)dev->priv;
2640 DEBUG(2, "%s: awc_config \n", dev
->name
);
2643 if( awc_disable_MAC(dev
)) goto final
;
2645 if( awc_write_all_rids(dev
) ) goto final
;
2647 if( awc_enable_MAC(dev
)) goto final
;
2655 char name
[] = "ElmerLinux";
2657 int awc_init(struct NET_DEVICE
*dev
){
2658 struct awc_private
*priv
= (struct awc_private
*)dev
->priv
;
2660 const char * radioType
;
2662 DEBUG(2, "%s: awc_init \n", dev
->name
);
2664 /* both_bap_lock decreases performance about 15%
2665 * but without it card gets screwed up
2668 if(smp_num_cpus
> 1){
2670 bap_setup_spinlock
= 1;
2673 //awc_dump_registers(dev);
2675 if (adhoc
& !max_mtu
)
2680 priv
->sleeping_bap
= 1;
2683 priv
->enabled_interrupts
= awc_ints_enabled(dev
->base_addr
);
2685 if( awc_issue_noop(dev
) ) goto final
;
2687 awc_ints_enable(dev
->base_addr
,0);
2689 if( awc_disable_MAC(dev
) ) goto final
;
2692 // awc_rids_setup(dev);
2694 while ( i
< AWC_NOF_RIDS
){
2695 if (awc_rids_temp
[i
].selector
)
2696 memcpy(&priv
->rid_dir
[i
],&awc_rids_temp
[i
],sizeof(priv
->rid_dir
[0]) );
2697 else priv
->rid_dir
[i
].selector
= NULL
;
2701 // following MUST be consistent with awc_rids !!!
2702 priv
->rid_dir
[0].buff
= &priv
->config
; // card RID mirrors
2703 priv
->rid_dir
[1].buff
= &priv
->SSIDs
;
2704 priv
->rid_dir
[2].buff
= &priv
->fixed_APs
;
2705 priv
->rid_dir
[3].buff
= &priv
->driver_name
;
2706 priv
->rid_dir
[4].buff
= &priv
->enc_trans
;
2707 priv
->rid_dir
[5].buff
= &priv
->general_config
; //
2708 priv
->rid_dir
[6].buff
= &priv
->capabilities
;
2709 priv
->rid_dir
[7].buff
= &priv
->status
;
2710 priv
->rid_dir
[8].buff
= &priv
->AP
;
2711 priv
->rid_dir
[9].buff
= &priv
->statistics
;
2712 priv
->rid_dir
[10].buff
= &priv
->statistics_delta
;
2713 priv
->rid_dir
[11].buff
= &priv
->statistics_delta_clear
;
2714 priv
->rid_dir
[12].buff
= &priv
->wep_volatile
;
2715 priv
->rid_dir
[13].buff
= &priv
->wep_nonvolatile
;
2716 priv
->rid_dir
[14].buff
= &priv
->modulation
;
2718 priv
->rid_dir
[15].buff
= &priv
->statistics16
;
2719 priv
->rid_dir
[16].buff
= &priv
->statistics16_delta
;
2720 priv
->rid_dir
[17].buff
= &priv
->statistics16_delta_clear
;
2722 priv
->rid_dir
[0].bufflen
= sizeof(priv
->config
); // card RID mirrors
2723 priv
->rid_dir
[1].bufflen
= sizeof(priv
->SSIDs
);
2724 priv
->rid_dir
[2].bufflen
= sizeof(priv
->fixed_APs
);
2725 priv
->rid_dir
[3].bufflen
= sizeof(priv
->driver_name
);
2726 priv
->rid_dir
[4].bufflen
= sizeof(priv
->enc_trans
);
2727 priv
->rid_dir
[5].bufflen
= sizeof(priv
->general_config
); //
2728 priv
->rid_dir
[6].bufflen
= sizeof(priv
->capabilities
);
2729 priv
->rid_dir
[7].bufflen
= sizeof(priv
->status
);
2730 priv
->rid_dir
[8].bufflen
= sizeof(priv
->AP
);
2731 priv
->rid_dir
[9].bufflen
= sizeof(priv
->statistics
);
2732 priv
->rid_dir
[10].bufflen
= sizeof(priv
->statistics_delta
);
2733 priv
->rid_dir
[11].bufflen
= sizeof(priv
->statistics_delta_clear
);
2734 priv
->rid_dir
[12].bufflen
= sizeof(priv
->wep_volatile
);
2735 priv
->rid_dir
[13].bufflen
= sizeof(priv
->wep_nonvolatile
);
2736 priv
->rid_dir
[14].bufflen
= sizeof(priv
->modulation
);
2738 priv
->rid_dir
[15].bufflen
= sizeof(priv
->statistics16
);
2739 priv
->rid_dir
[16].bufflen
= sizeof(priv
->statistics16_delta
);
2740 priv
->rid_dir
[17].bufflen
= sizeof(priv
->statistics16_delta_clear
);
2743 if( awc_read_all_rids(dev
) ) goto final
;
2746 priv
->config
.OperatingMode
= 0;// MODE_LLC_HOST;
2747 DEBUG(1,"ReceiveMode %x \n",priv
->config
.ReceiveMode
);
2748 // priv->config.ReceiveMode = RXMODE_DISABLE_802_3_HEADER;
2751 priv
->config
.OperatingMode
= MODE_STA_ESS
;
2752 // priv->config.OperatingMode = MODE_AP;
2753 // priv->config.Rates[0] =0x82;
2754 // priv->config.Rates[1] =0x4;
2755 // priv->config.Rates[2] =tx_full_rate;
2756 // priv->config.Rates[3] =0;
2757 // priv->config.Rates[4] =0;
2758 // priv->config.Rates[5] =0;
2759 // priv->config.Rates[6] =0;
2760 // priv->config.Rates[7] =0;
2761 priv
->config
.Channel
= channel
;
2762 if (adhoc
&& master
){
2763 priv
->config
.JoinNetTimeout
= 0x1;//0 is facotry default
2764 } else if (adhoc
&& slave
){
2765 priv
->config
.JoinNetTimeout
= 0xffff;
2767 // priv->config.AuthenticationType = 1;
2768 priv
->config
.Stationary
=1;
2769 // priv->config.ScanMode = 1;
2770 // priv->config.LinkLossDelay = 100;
2771 priv
->config
.FragmentThreshold
= 1700;
2772 priv
->config
.RtsThreshold
= 1700;
2773 memcpy(priv
->config
.NodeName
, name
, 10);
2775 DEBUG(1,"%s supported Rates \n",dev
->name
);
2776 for (i
=0; i
< 8; i
++)
2777 DEBUG(1,"%x ",priv
->capabilities
.SupportedRates
[i
]);
2779 DEBUG(1,"%s default Rates \n",dev
->name
);
2780 for (i
=0; i
< 8; i
++)
2781 DEBUG(1,"%x ",priv
->config
.Rates
[i
]);
2785 // here we go, bad aironet
2786 memset(&priv
->SSIDs
,0,sizeof(priv
->SSIDs
));
2788 my_spin_lock_init(&priv
->queues_lock
);
2790 priv
->SSIDs
.ridLen
=0;
2792 priv
->SSIDs
.SSID
[0].SSID
[0] ='a';
2793 priv
->SSIDs
.SSID
[0].SSID
[1] ='b';
2794 priv
->SSIDs
.SSID
[0].SSID
[2] ='c';
2795 priv
->SSIDs
.SSID
[0].lenght
=3;
2797 int sidlen
= strlen(SSID
);
2798 memcpy(priv
->SSIDs
.SSID
[0].SSID
,SSID
,sidlen
);
2799 priv
->SSIDs
.SSID
[0].lenght
= sidlen
;
2802 priv
->SSIDs
.SSID
[1].lenght
=0;
2803 priv
->SSIDs
.SSID
[1].SSID
[0] =0;
2804 priv
->SSIDs
.SSID
[1].SSID
[1] =0;
2805 priv
->SSIDs
.SSID
[2].lenght
=0;
2806 priv
->SSIDs
.SSID
[2].SSID
[0] =0;
2807 priv
->SSIDs
.SSID
[2].SSID
[1] =0;
2810 // priv->enc_trans.rules[0].etherType= 0x0008;
2811 // priv->enc_trans.rules[0].Action = 1;
2813 memcpy( priv
->config
.StationMacAddress
,
2814 priv
->capabilities
.FactoryAddress
, 6 );
2816 memcpy(dev
->dev_addr
, priv
->config
.StationMacAddress
, 6);
2818 DEBUG(2, "%s: awc_init success \n", dev
->name
);
2820 if (priv
->capabilities
.RadioType
== 1) radioType
= "802.11 Frequency Hoping";
2821 else if (priv
->capabilities
.RadioType
== 2) radioType
= "802.11 Direct Sequence";
2822 else if (priv
->capabilities
.RadioType
== 4) radioType
= "LM2000";
2823 else radioType
= "Multiple Radio Types";
2825 printk("%s: %s %s found @ 0x%lx irq %d firmwareVersion %d \n",dev
->name
,
2826 priv
->capabilities
.ProductName
,radioType
,
2827 dev
->base_addr
,dev
->irq
,
2828 priv
->capabilities
.SoftwareVersion
);
2832 printk(KERN_ERR
"aironet init failed \n");
2837 int awc_private_init(struct NET_DEVICE
* dev
){
2838 struct awc_private
* priv
= (struct awc_private
*) dev
->priv
;
2841 DEBUG(2, "%s: awc_private_init \n", dev
->name
);
2844 memset(priv
, 0, sizeof(struct awc_private
));
2846 my_spin_lock_init(&priv
->queues_lock
);
2848 priv
->bap0
.select
= dev
->base_addr
+ awc_Select0_register
;
2849 priv
->bap0
.offset
= dev
->base_addr
+ awc_Offset0_register
;
2850 priv
->bap0
.data
= dev
->base_addr
+ awc_Data0_register
;
2851 priv
->bap0
.lock
= 0;
2852 priv
->bap0
.status
= 0;
2853 my_spin_lock_init(&priv
->bap0
.spinlock
);
2854 init_MUTEX(&priv
->bap0
.sem
);
2855 priv
->bap1
.select
= dev
->base_addr
+ awc_Select1_register
;
2856 priv
->bap1
.offset
= dev
->base_addr
+ awc_Offset1_register
;
2857 priv
->bap1
.data
= dev
->base_addr
+ awc_Data1_register
;
2858 priv
->bap1
.lock
= 0;
2859 priv
->bap1
.status
= 0;
2860 my_spin_lock_init(&priv
->bap1
.spinlock
);
2861 init_MUTEX(&priv
->bap1
.sem
);
2862 priv
->sleeping_bap
= 1;
2864 //spinlock now init_MUTEX(&priv->command_semaphore);
2865 my_spin_lock_init(&priv
->command_issuing_spinlock
);
2866 my_spin_lock_init(&priv
->both_bap_spinlock
);
2867 my_spin_lock_init(&priv
->bap_setup_spinlock
);
2869 priv
->command_semaphore_on
= 0;
2870 priv
->unlock_command_postponed
= 0;
2871 priv
->immediate_bh
.next
= NULL
;
2872 priv
->immediate_bh
.sync
= 0;
2873 priv
->immediate_bh
.routine
= (void *)(void *)awc_bh
;
2874 priv
->immediate_bh
.data
= dev
;
2875 priv
->bh_running
= 0;
2876 priv
->bh_active
= 0;
2877 priv
->tx_chain_active
= 0;
2878 priv
->enabled_interrupts
= 0x00;
2879 priv
->waiting_interrupts
= 0x00;
2882 init_MUTEX(&priv
->tx_buff_semaphore
);
2883 priv
->tx_buffs_in_use
= 0;
2884 priv
->tx_small_buffs_in_use
= 0;
2885 priv
->mac_enabled
=0;
2886 priv
->link_status
=0;
2887 priv
->large_buff_mem
= large_buff_mem
;
2888 if (priv
->large_buff_mem
< max_mtu
+ AWC_TX_HEAD_SIZE
+ 10 )
2889 priv
->large_buff_mem
= max_mtu
+ AWC_TX_HEAD_SIZE
+ 10;
2890 priv
->small_buff_no
= small_buff_no
;
2891 if (priv
->small_buff_no
< 1 )
2892 priv
->small_buff_no
= 1 ;
2894 priv
->process_tx_results
= awc_process_tx_results
;
2896 //init_waitqueue(&priv->tx_chain_wait_queue);
2898 for (i
=0; i
< 6 ; i
++ ) {
2899 priv
->p2p
[i
] = 0xff;
2905 priv
->p802_11_send
=p802_11_send
;
2910 priv
->interrupt_count
=0;
2916 /**************************** OPEN CLOSE **********************/
2919 int awc_open(struct NET_DEVICE
*dev
)
2921 struct awc_private
*priv
= (struct awc_private
*)dev
->priv
;
2925 DEBUG(2, "%s: awc_open \n", dev
->name
);
2927 dev
->interrupt
= 0; dev
->tbusy
= 1; dev
->start
= 0;
2930 if( awc_queues_init(dev
) ) goto final
;
2931 if( awc_config(dev
) ) goto final
;
2933 memcpy(dev
->dev_addr
, priv
->config
.StationMacAddress
, 6);
2935 priv
->enabled_interrupts
= 0x87;
2936 awc_ints_enable(dev
->base_addr
,priv
->enabled_interrupts
);
2938 // priv->p8022_client = register_8022_client;
2939 // priv->snap_client = register_snap_client;
2940 DEBUG(2, "%s: opened \n", dev
->name
);
2942 priv
->sleeping_bap
= 0;
2946 // kernel_thread(awc_thread,dev,0);
2948 dev
->tbusy
= 0; dev
->start
= 1;
2949 return 0; /* Always succeed */
2952 dev
->tbusy
= 0; dev
->start
= 0;
2953 printk(KERN_ERR
"aironet open failed \n");
2958 int awc_close(struct NET_DEVICE
*dev
)
2960 struct awc_private
* priv
= (struct awc_private
*) dev
->priv
;
2962 DEBUG(2, "%s: closing device.\n", dev
->name
);
2967 awc_disable_MAC(dev
);
2968 awc_queues_destroy(dev
);
2974 AWC_LOCK_COMMAND_ISSUING(priv
);
2978 AWC_UNLOCK_COMMAND_ISSUING(priv
);
2985 /****************************** TX RX STUFF ******************/
2989 void awc_tx_timeout(struct NET_DEVICE
*dev
)
2991 struct awc_private
*priv
= (struct awc_private
*)dev
->priv
;
2993 DEBUG(2, "%s: awc_tx_timeout \n", dev
->name
);
2995 printk(KERN_NOTICE
"%s: Transmit timed out , buffs %d %d, queues tx %d pp %d lrg %d sm %d \n ",
2996 dev
->name
,priv
->tx_small_buffs_total
,priv
->tx_buffs_total
,
2997 priv
->tx_in_transmit
.size
,priv
->tx_post_process
.size
,
2998 priv
->tx_large_ready
.size
,priv
->tx_small_ready
.size
);
2999 priv
->stats
.tx_errors
++;
3001 dev
->trans_start
= jiffies
;
3005 long long last_tx_q_hack
= 0;
3008 int awc_start_xmit(struct sk_buff
*skb
, struct NET_DEVICE
*dev
) {
3010 struct awc_private
*priv
= (struct awc_private
*)dev
->priv
;
3012 // unsigned long flags;
3013 struct awc_fid
* fid
= NULL
;
3016 DEBUG(2, "%s: awc_start_xmit \n", dev
->name
);
3020 DEBUG(1, " xmit dev=NULL, jiffie %ld \n",jiffies
);
3024 /* Transmitter timeout, serious problems. */
3025 if (test_and_set_bit( 0, (void *) &dev
->tbusy
) ) {
3026 if (jiffies
- dev
->trans_start
> 3* HZ
){
3027 // save_flags(flags);
3029 fid
= priv
->tx_in_transmit
.head
;
3032 if (jiffies
- fid
->transmit_start_time
> (HZ
)){
3033 // printk(KERN_ERR "%s staled tx_buff found, age %uld jiffies\n",dev->name,
3034 // jiffies - fid->transmit_start_time );
3035 awc_fid_queue_remove(&priv
->tx_in_transmit
, fid
);
3036 if (fid
->u
.tx
.fid_size
<= AWC_TX_ALLOC_SMALL_SIZE
)
3037 awc_fid_queue_push_tail(&priv
->tx_small_ready
,fid
);
3039 awc_fid_queue_push_tail(&priv
->tx_large_ready
,fid
);
3044 printk("bbb in awc_fid_queue\n");
3045 // restore_flags(flags);
3050 //restore_flags(flags);
3053 if (jiffies
- dev
->trans_start
>= (5* HZ
) ) {
3054 awc_tx_timeout(dev
);
3060 DEBUG(1, " xmit skb=NULL, jiffie %ld \n",jiffies
);
3064 if (test_and_set_bit( 0, (void *) &priv
->tx_chain_active
) ) {
3069 dev
->trans_start
= jiffies
;
3070 retval
= awc_802_11_tx_find_path_and_post(dev
,skb
);
3071 priv
->tx_chain_active
= 0;
3072 // wake_up_interruptible(&priv->tx_chain_wait_queue);
3074 // if (!dev->tbusy) dev_tint(dev);
3078 int awc_tx_done(struct awc_fid
* rx_fid
){
3086 int awc_rx(struct NET_DEVICE
*dev
, struct awc_fid
* rx_fid
) {
3088 // struct awc_private *lp = (struct awc_private *)dev->priv;
3090 DEBUG(3, "%s: in rx_packet \n",dev
->name
);
3093 DEBUG(3, "%s: not rx_buff in rx_packet \n",dev
->name
);
3097 DEBUG(3, "%s: not rx_buff->skb in rx_packet \n",dev
->name
);
3102 rx_fid
->skb
->protocol
= eth_type_trans(rx_fid
->skb
,dev
);
3103 netif_rx(rx_fid
->skb
);
3110 void awc_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
3112 struct NET_DEVICE
*dev
= (struct NET_DEVICE
*)dev_id
;
3113 // struct awc_private *lp;
3114 // unsigned long flags;
3116 // if ((dev == NULL)) return;
3118 // lp = (struct awc_private *)dev->priv;
3123 DEBUG(2, "%s: awc_interrupt \n", dev
->name
);
3125 awc_interrupt_process(dev
);
3132 /************************ STATS, MULTICAST & STUFF ****************/
3136 struct enet_statistics
*awc_get_stats(struct NET_DEVICE
*dev
)
3138 struct awc_private
*priv
= (struct awc_private
*)dev
->priv
;
3139 // unsigned long flags;
3141 // int unlocked_stats_in_interrupt=0;
3143 DEBUG(2, "%s: awc_get_stats \n", dev
->name
);
3148 // save_flags(flags);
3151 awc_readrid_dir(dev
, &priv
->rid_dir
[9]);
3152 // restore_flags(flags);
3154 // the very following is the very wrong very probably
3155 if (awc_full_stats
){
3156 priv
->stats
.rx_fifo_errors
= priv
->statistics
.RxOverrunErr
;
3157 priv
->stats
.rx_crc_errors
= priv
->statistics
.RxPlcpCrcErr
+ priv
->statistics
.RxMacCrcErr
;
3158 priv
->stats
.rx_frame_errors
= priv
->statistics
.RxPlcpFormat
;
3159 priv
->stats
.rx_length_errors
= priv
->statistics
.RxPlcpLength
;
3160 priv
->stats
.rx_missed_errors
= priv
->statistics
.RxAged
;
3161 priv
->stats
.rx_over_errors
= priv
->statistics
.RxOverrunErr
;
3163 priv
->stats
.collisions
= priv
->statistics
.TxSinColl
;
3164 priv
->stats
.tx_aborted_errors
= priv
->statistics
.TxAged
;
3165 priv
->stats
.tx_fifo_errors
= priv
->statistics
.HostTxFail
;
3166 priv
->stats
.tx_window_errors
= priv
->statistics
.TxMulColl
;
3167 priv
->stats
.tx_heartbeat_errors
= priv
->statistics
.DefersProt
+priv
->statistics
.DefersEngy
;
3168 priv
->stats
.tx_carrier_errors
= priv
->statistics
.RetryLong
+priv
->statistics
.RetryShort
;
3169 priv
->stats
.multicast
= priv
->statistics
.HostRxMc
;
3173 // printk("rx_packets %d\n",priv->stats.rx_packets);
3174 return &(priv
->stats
);
3178 int awc_change_mtu(struct NET_DEVICE
*dev
, int new_mtu
){
3180 // struct awc_private *priv = (struct awc_private *)dev->priv;
3181 // unsigned long flags;
3183 if ((new_mtu
< 256 ) || (new_mtu
> 2312) || (max_mtu
&& new_mtu
> max_mtu
) )
3187 printk("PLEASE, ifconfig %s down for mtu change\n",dev
->name
);
3190 if (dev
->mtu
!= new_mtu
) {
3191 // save_flags(flags);
3193 awc_disable_MAC(dev
);
3194 awc_tx_dealloc(dev
);
3197 awc_enable_MAC(dev
);
3198 // restore_flags(flags);
3200 printk("%s mtu has been changed to %d \n ",dev
->name
,dev
->mtu
);
3210 awc_set_multicast_list(struct NET_DEVICE
*dev
) {
3211 // int ioaddr = dev->base_addr;
3213 /* if (dev->flags & IFF_PROMISC)
3215 else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
3226 int (* awc_proc_set_fun
) (int) = NULL
;
3227 int (* awc_proc_unset_fun
) (int) = NULL
;
3230 int awc_register_proc(int (*awc_proc_set_device
)(int),int (*awc_proc_unset_device
)(int)){
3232 AWC_ENTRY_EXIT_DEBUG("awc_register_proc");
3233 awc_proc_set_fun
= awc_proc_set_device
;
3234 awc_proc_unset_fun
= awc_proc_unset_device
;
3235 AWC_ENTRY_EXIT_DEBUG("exit");
3239 int awc_unregister_proc(void){
3241 AWC_ENTRY_EXIT_DEBUG("awc_unregister_proc");
3243 awc_proc_set_fun
= NULL
;
3244 awc_proc_unset_fun
= NULL
;
3245 AWC_ENTRY_EXIT_DEBUG("exit");
3251 int init_module(void)
3253 // unsigned long flags;
3256 printk(KERN_INFO
"%s", aironet4500_core_version
);
3262 void cleanup_module(void)
3264 printk(KERN_INFO
"aironet4500 unloading core module \n");