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
18 10.03.00 looks like softnet take us back to normal on SMP
21 #include <linux/module.h>
22 #include <linux/init.h>
23 #include <linux/config.h>
24 #include <linux/kernel.h>
25 #include <linux/netdevice.h>
26 #include <linux/etherdevice.h>
27 #include <linux/skbuff.h>
28 #include <linux/if_arp.h>
29 #include <linux/ioport.h>
32 #include <asm/bitops.h>
33 #include <asm/system.h>
34 #include <asm/byteorder.h>
36 #include <linux/time.h>
37 #include <linux/sched.h>
38 #include <linux/delay.h>
39 #include "aironet4500.h"
44 int bap_sleep_after_setup = 1;
45 int sleep_before_command = 1;
46 int bap_sleep_before_write= 1;
47 int sleep_in_command = 1;
48 int both_bap_lock; /* activated at awc_init in this */
49 int bap_setup_spinlock; /* file if numcpu >1 */
51 EXPORT_SYMBOL(bap_sleep);
52 EXPORT_SYMBOL(bap_sleep_after_setup);
53 EXPORT_SYMBOL(sleep_before_command);
54 EXPORT_SYMBOL(bap_sleep_before_write);
55 EXPORT_SYMBOL(sleep_in_command);
56 EXPORT_SYMBOL(both_bap_lock);
57 EXPORT_SYMBOL(bap_setup_spinlock);
59 struct awc_strings awc_status_error_codes[]=awc_reply_error_strings;
60 struct awc_strings awc_command_names[]=awc_command_name_strings;
61 struct awc_strings awc_link_status_names[]=awc_link_status_strings;
62 struct awc_strings awc_rid_names[]=aironet4500_RID_Select_strings;
63 struct awc_strings awc_link_failure_reason_names[]=IEEE_802_11_LINK_STATUS_FAILURE_REASON_STRINGS;
65 const char * awc_print_string( struct awc_strings* strings, int code){
67 struct awc_strings * str = strings;
69 while (str[i].string != NULL){
70 if (str[i].par == (code & str[i].mask )){
78 int awc_dump_registers(struct net_device * dev){
83 int status= inw(dev->base_addr +4*2);
84 int r1= inw(dev->base_addr +5*2);
85 int r2= inw(dev->base_addr +6*2);
86 int r3= inw(dev->base_addr +7*2);
88 printk(KERN_ERR "Command %s , result: %s, at memblk %x(RID %s) , offset %x \n",
89 awc_print_string(awc_command_names,status),
90 awc_print_string(awc_status_error_codes,r1),
91 r2, awc_print_string(awc_rid_names,r2),
95 printk(KERN_ERR "%s aironet register dump ",dev->name );
98 for (i=0; i < 32; i++){
99 printk("%4x ", inw(dev->base_addr + i*2 ) );
102 printk(KERN_ERR "%02x",(i+1)*2);
105 printk(KERN_ERR " \n");
110 /****************************** COMMAND ******************/
114 int awc_command_busy_clear_wait(struct net_device * dev){
115 // long long jiff = jiffies;
116 u16 active_interrupts;
119 AWC_ENTRY_EXIT_DEBUG(" entry awc_command_busy_clear_wait ");
121 while (awc_command_busy(dev->base_addr)){
123 printk(KERN_ERR "awc command busy too long, clearing\n");
124 awc_dump_registers(dev);
125 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
128 if (((struct awc_private*) dev->priv)->ejected)
135 while (awc_command_busy(dev->base_addr)){
136 //if (jiffies - jiff > (HZ/3)){
138 printk(KERN_CRIT "awc command busy WAY too long, clearing\n");
139 awc_dump_registers(dev);
140 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
141 active_interrupts = awc_event_status(dev->base_addr);
142 awc_event_ack(dev->base_addr, active_interrupts);
144 AWC_ENTRY_EXIT_DEBUG("BAD exit\n ");
148 if (((struct awc_private*) dev->priv)->ejected)
155 AWC_ENTRY_EXIT_DEBUG(" exit\n ");
164 inline unsigned short
165 awc_issue_command_and_block(struct awc_command * cmd){
169 u16 enabled_interrupts;
171 // unsigned long flags;
176 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_and_block ");
178 AWC_LOCK_COMMAND_ISSUING(cmd->priv);
180 if (awc_command_busy_clear_wait(cmd->dev)) goto final;
182 if (cmd->priv->sleeping_bap) udelay(sleep_before_command);
184 awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);
185 // awc_dump_registers(cmd->dev);
188 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
190 enabled_interrupts = awc_ints_enabled(cmd->dev->base_addr);
191 awc_ints_enable(cmd->dev->base_addr, enabled_interrupts & ~0x10);
192 if(cmd->priv->enabled_interrupts & 0x10)
193 cmd->priv->enabled_interrupts &= ~0x10;
196 while ( awc_command_read(cmd->port) == cmd->command) {
198 awc_command_write(cmd->port, cmd->command);
199 //if ((jiffies - jiff) > 2){
201 printk(" long wait with commmand reg busy in blocking command \n");
202 awc_dump_registers(cmd->dev);
205 if (cmd->priv->ejected)
211 AWC_ENTRY_EXIT_DEBUG(" issued " );
214 while ( awc_event_status_Cmd(cmd->port) == 0) {
217 printk(" long wait with commmand reg busy \n");
218 awc_dump_registers(cmd->dev);
222 DEBUG(1, " long wait after issue 10mks * %d ", ticks );
223 //printk(" long wait with command reg busy about ticks\n");
226 if (cmd->priv->ejected)
230 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
232 awc_read_response(cmd);
233 AWC_ENTRY_EXIT_DEBUG(" resp read \n");
235 if (awc_command_busy(cmd->port))
236 awc_event_ack_ClrStckCmdBsy(cmd->port);
238 awc_event_ack_Cmd(cmd->port);
239 if (cmd->priv->sleeping_bap) udelay(sleep_in_command);
241 if (cmd->status & 0xff00){
242 printk(KERN_ERR " bad response to command %s, parameter %x \n",awc_print_string(awc_command_names, cmd->command),cmd->par0);
243 awc_dump_registers(cmd->dev);
247 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
248 AWC_ENTRY_EXIT_DEBUG(" exit \n");
252 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
253 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
260 awc_issue_command(struct awc_command * cmd){
263 // long long jiff = jiffies;
264 // unsigned short enabled_ints;
268 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command");
271 printk(KERN_CRIT "cmd == NULL in awc_issue_command\n");
276 printk(KERN_CRIT "cmd->dev == NULL in awc_issue_command\n");
281 AWC_LOCK_COMMAND_ISSUING(cmd->priv);
283 if(awc_command_busy_clear_wait(cmd->dev)) goto final;
285 if(!cmd->priv->enabled_interrupts & 0x10){
286 cmd->priv->enabled_interrupts |= 0x10;
287 awc_ints_enable(cmd->port, cmd->priv->enabled_interrupts );
290 cmd->priv->async_command_start = jiffies;
291 cmd->priv->command_semaphore_on++;
294 awc4500wout(cmd->port,cmd->command,cmd->par0,cmd->par1,cmd->par2);
296 while ( awc_command_read(cmd->port) == cmd->command) {
298 awc_command_write(cmd->port, cmd->command);
299 //if ((jiffies - jiff) > 2){
301 printk(" long wait with commmand reg busy in async command \n");
302 awc_dump_registers(cmd->dev);
305 if (cmd->priv->ejected)
311 cmd->priv->cmd = *cmd;
314 AWC_ENTRY_EXIT_DEBUG(" exit \n");
317 AWC_UNLOCK_COMMAND_ISSUING(cmd->priv);
318 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
325 awc_issue_command_no_ack(struct net_device * dev,
326 u16 com, u16 par1, u16 par2, u16 par3){
328 struct awc_private * priv = (struct awc_private *)dev->priv;
333 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_command_no_ack ");
336 AWC_LOCK_COMMAND_ISSUING(priv);
338 if (awc_command_busy_clear_wait(dev)) {
339 printk("aironet4x00 no_ack command (reset) with stuck card \n");
342 awc4500wout(dev->base_addr,com, par1, par2,par3);
345 while ( awc_event_status_Cmd(dev->base_addr) == 0) {
346 if (awc_command_read(dev->base_addr) == com) {
347 awc_command_write(dev->base_addr, com);
349 //if ((jiffies - jiff) > 2){
351 printk(" long wait with commmand reg busy in noack command %d par %d %d %d\n",com,par1,par2,par3);
352 awc_dump_registers(dev);
361 if (awc_command_busy(dev->base_addr))
362 awc_event_ack_ClrStckCmdBsy(dev->base_addr);
364 AWC_UNLOCK_COMMAND_ISSUING(priv);
365 AWC_ENTRY_EXIT_DEBUG(" exit \n");
368 AWC_UNLOCK_COMMAND_ISSUING(priv);
369 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
374 /******************************** BAP *************************/
376 // inline // too long for inline
377 int awc_bap_setup(struct awc_command * cmd) {
385 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_setup ");
387 if ( cmd->priv->sleeping_bap)
390 if (cmd->priv->ejected)
393 if (!cmd->bap || !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
394 DEBUG(1,"no bap or bap not locked cmd %d !!", cmd->command);
396 if (bap_setup_spinlock)
397 spin_lock_irqsave(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
398 status = AWC_IN(cmd->bap->offset);
400 if (status & ~0x2000 ){
402 status = AWC_IN(cmd->bap->offset);
405 if (status & ~0x2000 ){
407 AWC_IN(cmd->dev->base_addr + 0x26);
408 AWC_OUT(cmd->dev->base_addr + 0x26, 0);
414 status = AWC_IN(cmd->bap->offset);
418 if (status & 0xC000){
419 printk(KERN_ERR "bap entered with err or busy bit set %x \n",status);
420 if (cmd->bap->lock != 1)
421 printk(KERN_ERR "bap lock bad same time %x\n",cmd->bap->lock);
422 awc_dump_registers(cmd->dev);
423 // AWC_OUT(cmd->bap->offset, 0x800);
429 AWC_OUT(cmd->bap->select, cmd->rid);
431 AWC_OUT(cmd->bap->offset, cmd->offset);
433 restore_flags(flags);
441 status = AWC_IN(cmd->bap->offset);
442 if ( cmd->priv->sleeping_bap)
444 if (cmd->priv->ejected)
447 if (cycles > 10000) {
448 printk(KERN_CRIT "deadlock in bap\n");
449 goto return_AWC_ERROR;
451 status = AWC_IN(cmd->bap->offset);
452 if (status & AWC_BAP_BUSY) {
453 if (cycles % 100 == 99 ) {
457 AWC_IN(cmd->dev->base_addr + 0x26);
458 AWC_OUT(cmd->dev->base_addr + 0x26, 0);
462 AWC_OUT(cmd->bap->select, cmd->rid);
464 AWC_OUT(cmd->bap->offset, cmd->offset);
465 restore_flags(flags);
470 if ( cmd->priv->sleeping_bap)
475 if (jiffies - jiff > 1 ) {
476 AWC_ENTRY_EXIT_DEBUG(" BAD BUSY exit \n");
477 awc_dump_registers(cmd->dev);
478 goto return_AWC_ERROR;
482 if (status & AWC_BAP_DONE) {
483 WAIT61x3; WAIT61x3; WAIT61x3;
485 // if ((status & 0xfff) != cmd->offset)
486 // printk(KERN_ERR "awcPBD %x ",status);
487 AWC_ENTRY_EXIT_DEBUG(" exit \n");
488 if (cmd->priv->sleeping_bap)
489 udelay(bap_sleep_after_setup);
492 goto return_AWC_SUCCESS;
495 if (status & AWC_BAP_ERR) {
496 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
497 // invalid rid or offset
498 printk(KERN_ERR "bap setup error bit set for rid %x offset %x \n",cmd->rid,cmd->offset);
499 awc_dump_registers(cmd->dev);
500 goto return_AWC_ERROR;
502 if ( cmd->priv->sleeping_bap)
505 // -- awc missed it, try again
509 AWC_OUT(cmd->bap->select, cmd->rid);
511 AWC_OUT(cmd->bap->offset, cmd->offset);
513 restore_flags(flags);
515 if (jiffies - jiff > HZ)
516 if (! (status &(AWC_BAP_ERR |AWC_BAP_DONE |AWC_BAP_BUSY))){
517 printk("aironet4500: bap setup lock without any status bits set");
518 awc_dump_registers(cmd->dev);
519 goto return_AWC_ERROR;
525 AWC_ENTRY_EXIT_DEBUG(" WE MUST NOT BE HERE exit \n");
528 if (bap_setup_spinlock)
529 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
530 AWC_ENTRY_EXIT_DEBUG(" ejected_unlock_exit \n");
534 if (bap_setup_spinlock)
535 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
536 AWC_ENTRY_EXIT_DEBUG(" AWC_ERROR_exit \n");
540 if (bap_setup_spinlock)
541 spin_unlock_irqrestore(&cmd->priv->bap_setup_spinlock,cmd->priv->bap_setup_spinlock_flags);
542 AWC_ENTRY_EXIT_DEBUG(" exit \n");
547 // requires call to awc_bap_setup() first
550 awc_bap_read(struct awc_command * cmd) {
552 register u16 * buff = (u16 *) cmd->buff;
553 register u16 port= cmd->bap->data;
556 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_read ");
557 if (!cmd->bap && !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
558 DEBUG(0,"no bap or bap not locked %d !!", cmd->command);
559 cmd->len = (cmd->len + 1) & (~1); // round up to even value
561 if (cmd->priv->ejected)
565 if (cmd->priv->sleeping_bap)
566 udelay(bap_sleep_before_write);
568 if (!cmd->priv->sleeping_bap)
570 *buff++ = AWC_IN(port);
573 *buff++ = AWC_IN(port);
575 AWC_ENTRY_EXIT_DEBUG(" exit \n");
576 if (cmd->priv->ejected)
582 // requires call to awc_bap_setup() first
585 awc_bap_write(struct awc_command * cmd){
587 register u16 * buff = (u16 *) cmd->buff;
588 register u16 port= cmd->bap->data;
591 AWC_ENTRY_EXIT_DEBUG(" entry awc_bap_write ");
592 if (!cmd->bap && !(cmd->lock_state & (AWC_BAP_SEMALOCKED |AWC_BAP_LOCKED)))
593 DEBUG(0,"no bap or bap not locked %d !!", cmd->command);
595 cmd->len = (cmd->len + 1) & (~1); // round up to even value
598 if (cmd->priv->ejected)
601 if (cmd->priv->sleeping_bap)
602 udelay(bap_sleep_before_write);
605 if (!cmd->priv->sleeping_bap)
607 AWC_OUT(port, *buff++);
610 AWC_OUT(port, *buff++);
612 if (cmd->priv->ejected)
616 AWC_ENTRY_EXIT_DEBUG(" exit \n");
624 /***************************** RID READ/WRITE ********************/
626 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.
627 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.
628 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.
629 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)
630 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.
631 const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_volatile =(const struct aironet4500_rid_selector){ 0xFF15, 1,0,0, "WEP key volatile" }; //
632 const struct aironet4500_rid_selector aironet4500_RID_Select_WEP_nonvolatile =(const struct aironet4500_rid_selector){ 0xFF16, 1,0,0, "WEP key non-volatile" }; //
633 const struct aironet4500_rid_selector aironet4500_RID_Select_Modulation =(const struct aironet4500_rid_selector){ 0xFF17, 1,0,0, "Modulation" }; //
634 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.
635 const struct aironet4500_rid_selector aironet4500_RID_Select_Capabilities =(const struct aironet4500_rid_selector){ 0xFF00, 0,1,0, "Capabilities" }; // Read Only Capabilities PC4500 Information
636 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
637 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
638 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
639 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
640 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)
641 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
642 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
643 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)
644 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
646 EXPORT_SYMBOL(aironet4500_RID_Select_General_Config);
647 EXPORT_SYMBOL(aironet4500_RID_Select_SSID_list);
648 EXPORT_SYMBOL(aironet4500_RID_Select_AP_list);
649 EXPORT_SYMBOL(aironet4500_RID_Select_Driver_name);
650 EXPORT_SYMBOL(aironet4500_RID_Select_Encapsulation);
651 EXPORT_SYMBOL(aironet4500_RID_Select_WEP_volatile);
652 EXPORT_SYMBOL(aironet4500_RID_Select_WEP_nonvolatile);
653 EXPORT_SYMBOL(aironet4500_RID_Select_Modulation);
654 EXPORT_SYMBOL(aironet4500_RID_Select_Active_Config);
655 EXPORT_SYMBOL(aironet4500_RID_Select_Capabilities);
656 EXPORT_SYMBOL(aironet4500_RID_Select_AP_Info);
657 EXPORT_SYMBOL(aironet4500_RID_Select_Radio_Info);
658 EXPORT_SYMBOL(aironet4500_RID_Select_Status);
659 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats);
660 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_delta);
661 EXPORT_SYMBOL(aironet4500_RID_Select_16_stats_clear);
662 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats);
663 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_delta);
664 EXPORT_SYMBOL(aironet4500_RID_Select_32_stats_clear);
667 struct awc_rid_dir awc_rids_temp[]={
668 // following MUST be consistent with awc_rids_setup !!!
669 {&aironet4500_RID_Select_General_Config, 0x100 , NULL, NULL, NULL,0 },
670 {&aironet4500_RID_Select_SSID_list, 0x68 , NULL, NULL, NULL,0 },
671 {&aironet4500_RID_Select_AP_list, 0x20 , NULL, NULL, NULL,0 },
672 {&aironet4500_RID_Select_Driver_name, 0x12 , NULL, NULL, NULL,0 },
673 {&aironet4500_RID_Select_Encapsulation, 0x22 , NULL, NULL, NULL,0 },
674 {&aironet4500_RID_Select_Active_Config, 0x100 , NULL, NULL, NULL,0 },
675 {&aironet4500_RID_Select_Capabilities, 0x80 , NULL, NULL, NULL,0 },
676 {&aironet4500_RID_Select_Status, 0x6c , NULL, NULL, NULL,0 },
677 {&aironet4500_RID_Select_AP_Info, 0x06 , NULL, NULL, NULL,0 },
678 {&aironet4500_RID_Select_32_stats, 0x184 , NULL, NULL, NULL,0 },
679 {&aironet4500_RID_Select_32_stats_delta, 0x184 , NULL, NULL, NULL,0 },
680 {&aironet4500_RID_Select_32_stats_clear, 0x184 , NULL, NULL, NULL,0 },
681 {&aironet4500_RID_Select_WEP_volatile, 0x1c , NULL, NULL, NULL,0 },
682 {&aironet4500_RID_Select_WEP_nonvolatile, 0x1c , NULL, NULL, NULL,0 },
683 {&aironet4500_RID_Select_Modulation, 0x04 , NULL, NULL, NULL,0 },
685 #ifdef AWC_USE_16BIT_STATS
686 {&aironet4500_RID_Select_16_stats, 0xC2 , NULL, NULL, NULL,0 },
687 {&aironet4500_RID_Select_16_stats_delta, 0xC2 , NULL, NULL, NULL,0 },
688 {&aironet4500_RID_Select_16_stats_clear, 0xC2 , NULL, NULL, NULL,0 },
690 {NULL},{NULL},{NULL},
701 awc_readrid(struct net_device * dev, struct aironet4500_RID * rid, void *pBuf ){
702 struct awc_command cmd;
706 AWC_ENTRY_EXIT_DEBUG(" entry awc_readrid ");
708 if (!rid->selector) return -1;
709 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
710 rid->selector->selector, rid->offset, (rid->bits / 8),pBuf);
712 sleep_state = cmd.priv->sleeping_bap ;
713 cmd.priv->sleeping_bap = 1;
715 AWC_BAP_LOCK_NOT_CLI(cmd);
716 if (awc_issue_command_and_block(&cmd)) goto final;
718 if (awc_bap_setup(&cmd)) goto final;
720 if (awc_bap_read(&cmd)) goto final;
721 cmd.priv->sleeping_bap = sleep_state;
723 AWC_RELEASE_COMMAND(cmd);
724 AWC_ENTRY_EXIT_DEBUG(" exit \n");
727 cmd.priv->sleeping_bap = sleep_state;
728 AWC_RELEASE_COMMAND(cmd);
729 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
734 awc_writerid(struct net_device * dev, struct aironet4500_RID * rid, void *pBuf){
736 struct awc_command cmd;
739 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid ");
742 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
743 rid->selector->selector,rid->offset, rid->bits/8,pBuf);
745 sleep_state = cmd.priv->sleeping_bap ;
746 cmd.priv->sleeping_bap = 1;
749 AWC_BAP_LOCK_NOT_CLI(cmd);
750 if (awc_issue_command_and_block(&cmd)) goto final;
752 if (awc_bap_setup(&cmd)) goto final;
754 if (awc_bap_write(&cmd)) goto final;
757 if (awc_issue_command_and_block(&cmd)) goto final;
758 cmd.priv->sleeping_bap = sleep_state;
760 AWC_RELEASE_COMMAND(cmd);
761 AWC_ENTRY_EXIT_DEBUG(" exit \n");
764 cmd.priv->sleeping_bap = sleep_state;
765 AWC_RELEASE_COMMAND(cmd);
766 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
771 awc_readrid_dir(struct net_device * dev, struct awc_rid_dir * rid ){
772 struct awc_command cmd;
775 AWC_ENTRY_EXIT_DEBUG(" entry awcreadrid_dir ");
778 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
779 rid->selector->selector,0, rid->bufflen,rid->buff);
781 sleep_state = cmd.priv->sleeping_bap ;
782 cmd.priv->sleeping_bap = 1;
786 AWC_BAP_LOCK_NOT_CLI(cmd);
787 if (awc_issue_command_and_block(&cmd)) goto final;
789 if (awc_bap_setup(&cmd)) goto final;
790 if (awc_bap_read(&cmd)) goto final;
791 cmd.priv->sleeping_bap = sleep_state;
793 AWC_RELEASE_COMMAND(cmd);
794 AWC_ENTRY_EXIT_DEBUG(" exit \n");
797 cmd.priv->sleeping_bap = sleep_state;
798 AWC_RELEASE_COMMAND(cmd);
799 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
804 awc_writerid_dir(struct net_device * dev, struct awc_rid_dir * rid){
806 struct awc_command cmd;
810 AWC_ENTRY_EXIT_DEBUG(" entry awc_writerid_dir ");
814 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x21, rid->selector->selector,
815 rid->selector->selector,0, rid->bufflen,((char *)rid->buff));
817 sleep_state = cmd.priv->sleeping_bap ;
818 cmd.priv->sleeping_bap = 1;
822 AWC_BAP_LOCK_NOT_CLI(cmd);
824 if (awc_issue_command_and_block(&cmd)) goto final;
825 if (awc_bap_setup(&cmd)) goto final;
826 if (awc_bap_write(&cmd)) goto final;
827 cmd.priv->sleeping_bap = sleep_state;
831 if (awc_issue_command_and_block(&cmd)) goto final;
833 AWC_RELEASE_COMMAND(cmd);
834 AWC_ENTRY_EXIT_DEBUG(" exit \n");
837 cmd.priv->sleeping_bap = sleep_state;
838 AWC_RELEASE_COMMAND(cmd);
839 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
843 EXPORT_SYMBOL(awc_readrid);
844 EXPORT_SYMBOL(awc_writerid);
845 EXPORT_SYMBOL(awc_readrid_dir);
846 EXPORT_SYMBOL(awc_writerid_dir);
848 /***************************** STARTUP *******************/
853 awc_issue_blocking_command(struct net_device * dev,u16 comm){
855 struct awc_command cmd;
856 // struct awc_private * priv = (struct awc_private *)dev->priv;
858 AWC_ENTRY_EXIT_DEBUG(" entry awc_issue_blocking_command ");
860 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,comm,0, 0, 0, 0 ,0 );
862 AWC_BAP_LOCK_NOT_CLI(cmd);
864 if (awc_issue_command_and_block(&cmd))
867 AWC_RELEASE_COMMAND(cmd);
868 AWC_ENTRY_EXIT_DEBUG(" exit \n");
871 AWC_RELEASE_COMMAND(cmd);
872 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
878 awc_issue_soft_reset(struct net_device * dev){
883 /* outw(inw(dev->base_addr + 0x30), dev->base_addr + 0x32);
885 outw(inw(dev->base_addr + 0x30), dev->base_addr + 0x34);
887 for (i=0; i< 32; i++)
888 outw(0,dev->base_addr + i*2);
890 outw(0x6,dev->base_addr + 0x34);
892 outw(0x6,dev->base_addr + 0x34);
893 outw(0x6,dev->base_addr + 0x34);
895 AWC_IN(dev->base_addr + 0x26);
896 AWC_OUT(dev->base_addr + 0x26, 0);
901 outw(0x4, dev->base_addr);
904 AWC_IN(dev->base_addr + 0x26);
905 AWC_OUT(dev->base_addr + 0x26, 0);
910 status = awc_issue_command_no_ack(dev, AWC_COMMAND_SOFT_RESET,0,0,0);
912 // awc_command_busy_clear_wait(dev);
918 awc_issue_noop(struct net_device * dev){
920 AWC_OUT(dev->base_addr + 0x28, 0);
921 AWC_OUT(dev->base_addr + 0x2A, 0);
923 retval= awc_issue_blocking_command(dev, AWC_COMMAND_NOOP);
928 EXPORT_SYMBOL(awc_enable_MAC);
931 awc_enable_MAC(struct net_device * dev){
933 struct awc_private * priv = (struct awc_private *)dev->priv;
934 AWC_ENTRY_EXIT_DEBUG(" entry awc_enable_MAC ");
936 if (priv->mac_enabled){
938 AWC_ENTRY_EXIT_DEBUG(" mac already enabled exit \n");
942 if (awc_issue_blocking_command(dev, AWC_COMMAND_ENABLE)){
943 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
948 priv->mac_enabled = 1;
950 AWC_ENTRY_EXIT_DEBUG(" exit \n");
954 EXPORT_SYMBOL(awc_disable_MAC);
956 awc_disable_MAC(struct net_device * dev){
958 struct awc_private * priv = (struct awc_private *)dev->priv;
959 AWC_ENTRY_EXIT_DEBUG(" entry awc_disable_MAC ");
961 if (!priv->mac_enabled){
962 AWC_ENTRY_EXIT_DEBUG(" mac allready disabled exit \n");
966 if (awc_issue_blocking_command(dev, AWC_COMMAND_DISABLE)){
967 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
971 priv->mac_enabled = 0;
972 AWC_ENTRY_EXIT_DEBUG(" exit \n");
979 awc_read_all_rids(struct net_device * dev){
981 struct awc_private * priv = (struct awc_private *)dev->priv;
983 AWC_ENTRY_EXIT_DEBUG(" entry awc_read_all_rids ");
985 for (i=0; i< AWC_NOF_RIDS && priv->rid_dir[i].selector ; i++){
986 status = awc_readrid_dir(dev,&priv->rid_dir[i]);
988 if (status) return status;
993 AWC_ENTRY_EXIT_DEBUG(" exit \n");
998 awc_write_all_rids(struct net_device * dev){
1000 struct awc_private * priv = (struct awc_private *)dev->priv;
1002 AWC_ENTRY_EXIT_DEBUG(" entry awc_write_all_rids ");
1004 for (i=0;i < 5 && i< AWC_NOF_RIDS && priv->rid_dir[i].selector ; i++){
1005 status = awc_writerid_dir(dev,&priv->rid_dir[i]);
1007 if(status) return status;
1009 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1013 /************************** FID QUEUES ****************************/
1014 /**************************** TX ALLOC / DEALLOC ***************/
1018 int awc_tx_alloc(struct net_device * dev) {
1020 struct awc_command cmd;
1023 struct awc_fid * fid = NULL;
1025 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_alloc ");
1028 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x0A,0, 0,0,0,NULL);
1029 cmd.par0 = dev->mtu + AWC_TX_HEAD_SIZE + 8 ;
1031 DEBUG(32,"about to allocate %x bytes ",cmd.priv->large_buff_mem);
1032 DEBUG(32,"in %x large buffers ",cmd.priv->large_buff_mem / (dev->mtu + AWC_TX_HEAD_SIZE + 8) );
1035 AWC_BAP_LOCK_NOT_CLI(cmd);
1037 while (k < cmd.priv->large_buff_mem / (dev->mtu + AWC_TX_HEAD_SIZE + 8) ) {
1039 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL );
1040 if (!fid) goto final;
1041 memset(fid, 0, sizeof(struct awc_fid));
1043 if (awc_issue_command_and_block(&cmd)) goto final;
1045 while ( awc_event_status_Alloc(cmd.port) == 0) ;
1046 fid->u.tx.fid = awc_Tx_Allocated_Fid(cmd.port);
1047 fid->u.tx.fid_size = dev->mtu + AWC_TX_HEAD_SIZE ;
1049 DEBUG(32,"allocated large tx fid %x ",fid->u.tx.fid);
1050 if(fid->u.tx.fid == 0
1051 || cmd.status != 0xA){
1052 printk(KERN_ERR "%s bad tx_alloc\n",dev->name);
1059 awc_event_ack_Alloc(cmd.port);
1061 // shoudlnt goto final after that
1062 awc_fid_queue_push_tail(&cmd.priv->tx_large_ready,fid);
1066 cmd.priv->tx_buffs_total = tot;
1067 DEBUG(32,"allocated %d large tx buffs\n",tot);
1069 cmd.par0 = AWC_TX_ALLOC_SMALL_SIZE ;
1072 while (k < cmd.priv->small_buff_no) {
1074 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL );
1075 if (!fid) goto final;
1076 memset(fid, 0, sizeof(struct awc_fid));
1078 cmd.par0 = AWC_TX_ALLOC_SMALL_SIZE ;
1080 if (awc_issue_command_and_block(&cmd)) goto final;
1082 while ( awc_event_status_Alloc(cmd.port) == 0) ;
1083 fid->u.tx.fid = awc_Tx_Allocated_Fid(cmd.port);
1084 fid->u.tx.fid_size = AWC_TX_ALLOC_SMALL_SIZE;
1086 DEBUG(32,"allocated large tx fid %x ",fid->u.tx.fid);
1087 if(fid->u.tx.fid == 0
1088 || cmd.status != 0xA){
1089 printk(KERN_ERR "%s bad tx_alloc\n",dev->name);
1096 awc_event_ack_Alloc(cmd.port);
1098 // shoudlnt goto final after that
1099 awc_fid_queue_push_tail(&cmd.priv->tx_small_ready,fid);
1104 cmd.priv->tx_small_buffs_total = tot;
1105 DEBUG(32,"allocated %d small tx buffs\n",tot);
1107 AWC_RELEASE_COMMAND(cmd);
1108 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1114 printk(KERN_CRIT "%s awc tx prealloc failed \n",dev->name);
1115 AWC_RELEASE_COMMAND(cmd);
1116 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1122 awc_tx_dealloc_fid(struct net_device * dev,struct awc_fid * fid){
1124 struct awc_command cmd;
1127 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0x0C,0, 0,0,0,NULL);
1129 AWC_BAP_LOCK_NOT_CLI(cmd);
1132 fid_handle = cmd.par0 = fid->u.tx.fid;
1137 if (!cmd.priv->ejected)
1138 if (awc_issue_command_and_block(&cmd)) goto final;
1139 //awc_event_ack_Alloc(cmd.port);
1142 AWC_RELEASE_COMMAND(cmd);
1143 AWC_ENTRY_EXIT_DEBUG(" exit \n");
1147 printk(KERN_ERR "awc_tx_dealloc failed for fid %x \n",fid_handle);
1148 AWC_RELEASE_COMMAND(cmd);
1149 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1156 awc_tx_dealloc(struct net_device * dev){
1158 struct awc_private * priv = (struct awc_private *)dev->priv;
1163 struct awc_fid * fid;
1165 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_dealloc ");
1167 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_large_ready)))
1168 awc_tx_dealloc_fid(dev,fid);
1169 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_small_ready)))
1170 awc_tx_dealloc_fid(dev,fid);
1171 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_post_process)))
1172 awc_tx_dealloc_fid(dev,fid);
1173 while (NULL != (fid = awc_fid_queue_pop_head(&priv->tx_in_transmit)))
1174 awc_tx_dealloc_fid(dev,fid);
1182 inline struct awc_fid *
1183 awc_tx_fid_lookup_and_remove(struct net_device * dev, u16 fid_handle){
1185 struct awc_private * priv = (struct awc_private *)dev->priv;
1187 unsigned long flags;
1188 struct awc_fid * fid = NULL;
1191 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_fid_lookup ");
1193 spin_lock_irqsave(&(priv->queues_lock),flags);
1196 fid = priv->tx_in_transmit.head;
1199 if (fid->u.tx.fid == fid_handle){
1200 awc_fid_queue_remove(&priv->tx_in_transmit, fid);
1201 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1207 // printk("bbb in awc_fid_queue\n");
1208 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1214 fid = priv->tx_post_process.head;
1216 if (fid->u.tx.fid == fid_handle){
1217 awc_fid_queue_remove(&priv->tx_post_process, fid);
1218 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1224 // printk("bbb in awc_fid_queue\n");
1225 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1232 fid = priv->tx_large_ready.head;
1234 if (fid->u.tx.fid == fid_handle){
1235 awc_fid_queue_remove(&priv->tx_large_ready, fid);
1236 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1242 // printk("bbb in awc_fid_queue\n");
1243 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1249 fid = priv->tx_small_ready.head;
1251 if (fid->u.tx.fid == fid_handle){
1252 awc_fid_queue_remove(&priv->tx_small_ready, fid);
1253 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1259 // printk("bbb in awc_fid_queue\n");
1260 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1266 spin_unlock_irqrestore(&(priv->queues_lock),flags);
1268 printk(KERN_ERR "%s tx fid %x not found \n",dev->name, fid_handle);
1269 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
1278 awc_queues_init(struct net_device * dev){
1279 struct awc_private * priv = (struct awc_private *)dev->priv;
1280 struct awc_fid * fid = NULL;
1284 awc_fid_queue_init(&priv->tx_in_transmit);
1285 awc_fid_queue_init(&priv->tx_post_process);
1286 awc_fid_queue_init(&priv->tx_large_ready);
1287 awc_fid_queue_init(&priv->tx_small_ready);
1288 awc_fid_queue_init(&priv->rx_ready);
1289 awc_fid_queue_init(&priv->rx_post_process);
1291 retv = awc_tx_alloc(dev);
1294 while (k < AWC_RX_BUFFS){
1295 fid = kmalloc(sizeof(struct awc_fid),GFP_KERNEL);
1296 if (!fid) return -1;
1297 awc_fid_queue_push_tail(&priv->rx_ready,fid);
1301 if (retv) return retv;
1308 awc_queues_destroy(struct net_device * dev){
1309 struct awc_private * priv = (struct awc_private *)dev->priv;
1310 struct awc_fid * fid = NULL;
1315 while (NULL != (fid = awc_fid_queue_pop_head(&priv->rx_ready))){
1318 while (NULL != (fid = awc_fid_queue_pop_head(&priv->rx_post_process))){
1322 retv = awc_tx_dealloc(dev);
1329 /****************************** 802.11router ******************/
1331 awc_802_11_copy_path_skb(struct net_device * dev, struct awc_fid * rx_buff){
1333 struct awc_private * priv = (struct awc_private * )dev->priv;
1335 AWC_ENTRY_EXIT_DEBUG("awc_802_11_copy_path_skb");
1337 if (rx_buff->pkt_len < 22 ) rx_buff->pkt_len = 22;
1339 // if (!rx_buff->skb)
1340 rx_buff->skb = dev_alloc_skb(rx_buff->pkt_len + 12 +2);
1343 if (rx_buff->skb == NULL) {
1344 printk(KERN_CRIT "couldnt alloc rx_buff->skb in rx event \n");
1345 priv->stats.rx_dropped++;
1348 rx_buff->type |= p80211copy_path_skb;
1350 rx_buff->skb->dev = dev;
1352 // skb_reserve(rx_buff->skb, rx_buff->pkt_len + 12 );
1354 rx_buff->u.rx.payload = skb_put(rx_buff->skb, rx_buff->pkt_len + 12 ) ;
1355 rx_buff->u.rx.payload = ((char *)rx_buff->u.rx.payload ) +12;
1357 AWC_ENTRY_EXIT_DEBUG("exit\n");
1366 awc_802_11_find_copy_path(struct net_device * dev, struct awc_fid * rx_buff){
1368 // struct awc_private * priv = (struct awc_private * )dev->priv;
1374 return awc_802_11_copy_path_skb(dev,rx_buff);
1378 /* called from INTERRUPT context,
1380 must deliver the packet to where it was meant by
1381 awc_802_11_find_copy_path
1383 SHOULD be efficient and
1384 queue the packet if operations take longer
1392 awc_802_11_router_rx(struct net_device * dev,struct awc_fid * rx_buff){
1394 struct awc_private * priv = (struct awc_private * )dev->priv;
1395 struct sk_buff * skb = rx_buff->skb;
1396 u8 * payload = rx_buff->u.rx.payload;
1397 // u8 * p802_3_macs_place = payload -12;
1398 u16 pkt_len = rx_buff->pkt_len;
1399 struct ieee_802_11_802_1H_header * bridge = NULL;
1400 struct ieee_802_11_snap_header * snap = NULL;
1401 struct ieee_802_11_802_1H_header * bridge_tmp;
1402 struct ieee_802_11_snap_header * snap_tmp;
1407 AWC_ENTRY_EXIT_DEBUG("awc_802_11_router_rx");
1409 // if (rx_buff->type & p80211_8023)
1410 rx_buff->mac = rx_buff->u.rx.ieee_802_3.dst_mac;
1412 // rx_buff->mac = rx_buff->u.rx.ieee_802_11.mac1;
1414 if ( rx_buff->u.rx.ieee_802_11.frame_control == 0x8 )
1415 memcpy(priv->bssid,rx_buff->u.rx.ieee_802_11.mac3,6);
1417 while ((ptr < pkt_len - 1 ) && payload && parse_not_8023){
1419 bridge_tmp = (struct ieee_802_11_802_1H_header*) &payload[ptr];
1420 snap_tmp = (struct ieee_802_11_snap_header*) &payload[ptr];
1421 len = ntohs( *((u16*)&payload[ptr]) );
1425 if ( len < 0x5DC) { // not a protocol
1427 if ( len != pkt_len-2 - ptr){
1428 printk(KERN_ERR "%s bad encapsulation lenght %x at pkt offset %x \n",dev->name,len,ptr);
1431 DEBUG(1,"parisng packet of size %x\n",len);
1436 DEBUG(1,"parisng packet of proto %x\n",len);
1438 if (snap_tmp->dsap == 0xaa && snap_tmp->ssap == 0xaa &&
1439 pkt_len - ptr > sizeof(struct ieee_802_11_snap_header) ){
1441 DEBUG(0x200,"%s SNAP ",dev->name);
1442 if (snap_tmp->ctrl != 0x03){
1443 printk(KERN_ERR "%s unknown snap ctrl %x \n",dev->name,snap_tmp->ctrl);
1446 if (snap_tmp->oui[0] == 0 && // LLC RFC1042
1447 snap_tmp->oui[1] == 0 &&
1448 snap_tmp->oui[2] == 0 ){
1450 ptr += sizeof(struct ieee_802_11_snap_header);
1451 DEBUG(0x200,"%s LLC RFC1042 \n",dev->name);
1454 if (snap_tmp->oui[0] == 0 && // LLC 802.1H
1455 snap_tmp->oui[1] == 0 &&
1456 snap_tmp->oui[2] == 0x78){
1458 DEBUG(0x200,"%s LLC 802.1H \n",dev->name);
1459 ptr += sizeof(struct ieee_802_11_snap_header);
1462 if (snap_tmp->oui[0] == 0x00 && // 802.1H itself
1463 snap_tmp->oui[1] == 0x40 &&
1464 snap_tmp->oui[2] == 0x96){
1465 ptr += sizeof(struct ieee_802_11_802_1H_header);
1466 if (ptr >= pkt_len){
1468 DEBUG(1,"%s invalid packet len in 802.1H SNAP OUI check \n",dev->name);
1470 DEBUG(0x200,"%s OUI 004096 \n",dev->name);
1471 DEBUG(0x200," 802.1H uknown1 %x ",ntohs(bridge_tmp->unknown1));
1472 DEBUG(0x200," 802.1H uknw type %x \n",0xf000 & ntohs(bridge_tmp->unknown2));
1473 DEBUG(0x200," 802.1H payloadsize %x \n",0x0fff & ntohs(bridge_tmp->unknown2));
1475 //goto bad_packet; // TODO
1477 bridge = bridge_tmp;
1478 if (bridge_tmp->unknown1 == 0x0000 &&
1479 ((ntohs(bridge_tmp->unknown2) & 0xf000) == 0x1000 ) ){
1480 rx_buff->type |= p80211_8021H;
1481 rx_buff->mac = &payload[ptr];
1482 DEBUG(0x200," 802.1H DATA packet of size %x\n",0xf000 & ntohs(bridge_tmp->unknown2) );
1483 memcpy(priv->p2p,rx_buff->u.rx.ieee_802_11.mac2, 6);
1487 DEBUG(0x200,"%s droping unknown 004096 packet \n ",dev->name);
1495 // packet without linklevel header for us
1497 if ( len == 0x8000 || len == 0x8006){
1499 DEBUG(0x200,"Non IP packet %x \n",ntohs(len));
1511 if (ptr > pkt_len) goto bad_packet;
1513 if ( rx_buff->mac != (payload + ptr -12) )
1514 memcpy( payload +ptr -12, rx_buff->mac , 12);
1518 if (!payload || !skb || !rx_buff->skb || !rx_buff->u.rx.payload)
1520 //skb->ip_summed = CHECKSUM_NONE;
1521 skb->data = payload + ptr -12;
1524 rx_buff->skb->protocol = eth_type_trans(rx_buff->skb,dev);
1525 DEBUG(0x200,"eth_type_trans decided: %x\n",rx_buff->skb->protocol);
1526 rx_buff->skb = NULL;
1527 rx_buff->u.rx.payload = NULL;
1528 priv->stats.rx_packets++;
1529 priv->stats.rx_bytes += skb->len;
1532 dev->last_rx = jiffies;
1533 AWC_ENTRY_EXIT_DEBUG("exit\n");
1537 DEBUG(0x200,"%s packet dropped in packet hdr parse \n ",dev->name);
1538 if (rx_buff->skb && (rx_buff->type & p80211copy_path_skb)){
1540 dev_kfree_skb_irq(rx_buff->skb);
1541 rx_buff->skb = NULL;
1542 rx_buff->u.rx.payload = NULL;
1545 AWC_ENTRY_EXIT_DEBUG("exit\n");
1550 awc_802_11_failed_rx_copy(struct net_device * dev,struct awc_fid * rx_buff){
1551 struct awc_private * priv = (struct awc_private * )dev->priv;
1554 AWC_ENTRY_EXIT_DEBUG("awc_802_11_failed_rx_copy");
1556 dev_kfree_skb_irq(rx_buff->skb);
1557 rx_buff->skb = NULL;
1558 rx_buff->u.rx.payload = NULL;
1559 priv->stats.rx_errors++;
1562 AWC_ENTRY_EXIT_DEBUG("exit\n");
1566 called from kernel->driver tx routine
1567 must decide where and how to post the packet
1568 must post the packet to wherever it decides
1569 either copy to card or enqueue to destination queue
1575 awc_802_11_tx_find_path_and_post(struct net_device * dev,
1576 struct sk_buff * skb){
1579 struct awc_private * priv = (struct awc_private * )dev->priv;
1581 int len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; /* check min length*/
1582 struct awc_fid * fid = NULL;
1584 u16 p2p_direct =priv->p2p_found;
1585 struct iphdr * ip_hdr;
1586 //buffer = skb->data;
1588 AWC_ENTRY_EXIT_DEBUG("awc_802_11_tx_find_path_and_post");
1590 // netif_stop_queue(dev);
1591 DOWN(&priv->tx_buff_semaphore);
1592 if (len > dev->mtu + 16 ) {
1593 printk(KERN_ERR "%s packet size too large %d \n",dev->name, len);
1597 if (len + AWC_TX_HEAD_SIZE < AWC_TX_ALLOC_SMALL_SIZE )
1598 fid = awc_fid_queue_pop_head(&priv->tx_small_ready);
1601 fid = awc_fid_queue_pop_head(&priv->tx_large_ready);
1604 DEBUG(32,"%s buffs in use \n",dev->name);
1608 if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE){
1609 awc_fid_queue_push_tail(&priv->tx_small_ready, fid);
1610 fid = awc_fid_queue_pop_head(&priv->tx_large_ready);
1614 DEBUG(32,"%s buffs in use \n",dev->name);
1618 if (fid->u.tx.fid_size < len + AWC_TX_HEAD_SIZE - 14){
1619 printk(KERN_ERR "found too small tx fid size %d, pktlen %d \n",fid->u.tx.fid_size, len);
1621 memset(&fid->u.tx.radio_tx, 0,sizeof(struct aironet4500_radio_tx_header));
1622 memset(&fid->u.tx.ieee_802_11, 0,sizeof(struct ieee_802_11_header));
1623 memset(&fid->u.tx.ieee_802_3, 0,sizeof(struct ieee_802_3_header));
1624 fid->u.tx.payload =NULL;
1625 fid->u.tx.gap_length =0;
1629 priv->tx_buffs_in_use++;
1630 DEBUG(32,"found large buff %x \n",fid->u.tx.fid);
1633 fid->type |= p80211_llc_snap;
1634 fid->snap.dsap = 0xaa;
1635 fid->snap.ssap = 0xaa;
1636 fid->snap.ctrl = 0x03;
1637 fid->snap.oui[0] = 0x0;
1638 fid->snap.oui[1] = 0x0;
1639 fid->snap.oui[2] = 0x0;
1644 if (priv->p2p_uc && !priv->p2p_found){ // we go without encapsulation to neighbour;
1646 for (i=0; i < 6; i++)
1647 if (priv->p2p[i] != skb->data[i]){
1653 if (priv->force_tx_rate == 2 || priv->force_tx_rate == 4 ||
1654 priv->force_tx_rate== 11 || priv->force_tx_rate == 22){
1655 fid->u.tx.radio_tx.tx_bit_rate = priv->force_tx_rate;
1656 } else if (priv->force_tx_rate != 0 ) {
1657 printk(KERN_ERR "wrong force_tx_rate=%d changed to default \n", priv->force_tx_rate);
1658 priv->force_tx_rate = 0;
1660 fid->u.tx.radio_tx.TX_Control =
1661 aironet4500_tx_control_tx_ok_event_enable |
1662 aironet4500_tx_control_tx_fail_event_enable |
1663 aironet4500_tx_control_no_release;
1665 if (len < priv->force_rts_on_shorter){
1666 fid->u.tx.radio_tx.TX_Control |=
1667 aironet4500_tx_control_use_rts;
1670 ip_hdr = (struct iphdr * ) ((( char * ) skb->data) + 14);
1671 if (ip_hdr && skb->data[12] == 0x80 ){
1672 if (ip_hdr->tos & IPTOS_RELIABILITY && priv->ip_tos_reliability_rts)
1673 fid->u.tx.radio_tx.TX_Control |=
1674 aironet4500_tx_control_use_rts;
1675 if (ip_hdr->tos & IPTOS_THROUGHPUT && priv->ip_tos_troughput_no_retries)
1676 fid->u.tx.radio_tx.TX_Control |=
1677 aironet4500_tx_control_no_retries;
1680 if (priv->p802_11_send || memcmp(dev->dev_addr, skb->data +6, 6) ){
1681 fid->u.tx.radio_tx.TX_Control |=
1682 aironet4500_tx_control_header_type_802_11;
1683 DEBUG(0x200,"%s bridging, forcing 802_11 send \n ",dev->name);
1687 if (!priv->p2p_uc || p2p_direct) {
1688 if ((fid->u.tx.radio_tx.TX_Control &
1689 aironet4500_tx_control_header_type_802_11 )){
1691 // including 802.3 header into 802.11 packet
1692 fid->u.tx.radio_tx.PayloadLength = len -12;
1693 fid->u.tx.ieee_802_3.payload_length = len -12 ;
1694 fid->pkt_len = len -12;
1695 fid->u.tx.payload = skb->data +12;
1697 if (priv->simple_bridge){
1698 memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
1699 memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);
1700 memcpy(fid->u.tx.ieee_802_11.mac3,priv->status.CurrentBssid ,6);
1701 memset(fid->u.tx.ieee_802_11.mac4,0,6);
1702 fid->u.tx.ieee_802_11.frame_control = 0x8;
1703 fid->u.tx.ieee_802_11.gapLen=6;
1705 memcpy(fid->u.tx.ieee_802_11.mac1,skb->data,6);
1706 memcpy(fid->u.tx.ieee_802_11.mac2,dev->dev_addr,6);
1707 memcpy(fid->u.tx.ieee_802_11.mac3,skb->data +6 ,6);
1708 memset(fid->u.tx.ieee_802_11.mac4,0 ,6);
1709 fid->u.tx.ieee_802_11.frame_control = 0x108;
1710 fid->u.tx.ieee_802_11.gapLen=6;
1712 } else { // plain old 802.3, with hdr copied
1713 fid->u.tx.radio_tx.PayloadLength = len -12;
1714 fid->u.tx.ieee_802_3.payload_length = len -12;
1715 fid->pkt_len = len - 12;
1716 fid->u.tx.payload = skb->data +12;
1718 memcpy(fid->u.tx.ieee_802_3.dst_mac,skb->data, 12);
1719 DEBUG(0x200,"%s tx simply 802.3 type \n ",dev->name);
1721 } else {// 802.1H bridgeing
1722 fid->type |= p80211_8021H;
1723 fid->bridge_size = len + sizeof(fid->bridge) ;
1724 fid->bridge.dsap = 0xaa;
1725 fid->bridge.ssap = 0xaa;
1726 fid->bridge.ctrl = 0x03;
1727 fid->bridge.oui[0] = 0x0;
1728 fid->bridge.oui[1] = 0x40;
1729 fid->bridge.oui[2] = 0x96;
1730 fid->bridge.unknown1= 0x0000;
1731 fid->bridge.unknown2= htons((len) & 0x1000);
1732 fid->u.tx.radio_tx.PayloadLength = fid->bridge_size + 2;
1733 fid->u.tx.ieee_802_3.payload_length = fid->u.tx.radio_tx.PayloadLength ;
1736 fid->u.tx.payload = skb->data +12;
1737 if ((fid->u.tx.radio_tx.TX_Control &
1738 aironet4500_tx_control_header_type_802_11 )){
1740 memcpy(fid->u.tx.ieee_802_11.mac1,priv->p2p,6);
1741 memcpy(fid->u.tx.ieee_802_11.mac2,skb->data +6,6);
1742 memcpy(fid->u.tx.ieee_802_11.mac3,priv->bssid ,6);
1743 memset(fid->u.tx.ieee_802_11.mac4,0,6);
1744 fid->u.tx.ieee_802_11.gapLen=6;
1746 fid->u.tx.ieee_802_11.frame_control = 0x8;
1748 memcpy(fid->u.tx.ieee_802_3.dst_mac,priv->p2p, 6);
1749 memcpy(fid->u.tx.ieee_802_3.src_mac,dev->dev_addr, 6);
1750 fid->u.tx.payload = skb->data + 2 + sizeof(fid->bridge);
1751 fid->pkt_len = len ;
1753 DEBUG(0x200,"%s tx simply 802.1H type \n ",dev->name);
1757 priv->stats.tx_bytes += fid->u.tx.ieee_802_3.payload_length;
1758 priv->stats.tx_packets++;
1761 awc_fid_queue_push_tail(&priv->tx_in_transmit,fid);
1763 awc_transmit_packet(dev,fid);
1764 if (priv->tx_large_ready.size <= 2 || priv->tx_small_ready.size <= 2 ){
1765 if (netif_running(dev))
1766 netif_stop_queue(dev);
1768 if (netif_running(dev))
1769 netif_wake_queue(dev);
1771 UP(&priv->tx_buff_semaphore);
1772 AWC_ENTRY_EXIT_DEBUG("exit\n");
1777 DEBUG(32,"%s tx buffs not found \n ",dev->name);
1781 netif_stop_queue (dev); //weell, here it must be set anyway and before
1782 //priv->stats.tx_fifo_errors++;
1783 UP(&priv->tx_buff_semaphore);
1784 AWC_ENTRY_EXIT_DEBUG("NoSpaceExit\n");
1787 priv->stats.tx_errors++;
1788 UP(&priv->tx_buff_semaphore);
1789 if (!netif_running(dev))
1790 netif_start_queue(dev);
1792 AWC_ENTRY_EXIT_DEBUG("BADExit\n");
1798 called from low level driver->card tx copy routine
1799 probably wants to free skbuf if failed transmits won't be
1800 resubmitted to another device (if more than one path)
1801 or tried again (if tx buffer in card needs to be filled again)
1806 awc_802_11_after_tx_packet_to_card_write(struct net_device * dev,
1807 struct awc_fid * tx_buff){
1810 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_packet_to_card_write");
1813 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_tx_packet_to_card_write \n",dev->name);
1817 dev_kfree_skb(tx_buff->skb);
1818 tx_buff->skb = NULL;
1821 AWC_ENTRY_EXIT_DEBUG("exit\n");
1825 called from low level driver->card tx copy routine
1826 probably wants to free skbuf if failed writes won't be
1827 resubmitted to another device (if more than one path)
1828 or tried again (if tx buffer in card needs to be filled again)
1832 awc_802_11_after_failed_tx_packet_to_card_write(struct net_device * dev,
1833 struct awc_fid * tx_buff){
1834 struct awc_private * priv = (struct awc_private *)dev->priv;
1837 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_failed_tx_packet_to_card_write");
1840 DEBUG(1,"%s no damn tx_buff in awc_802_11_after_failed_tx_packet_to_card_write \n",dev->name);
1844 dev_kfree_skb(tx_buff->skb);
1845 tx_buff->skb = NULL;
1847 printk(KERN_ERR "%s packet to card write failed \n",dev->name);
1850 awc_fid_queue_remove(&priv->tx_in_transmit,tx_buff);
1852 if (tx_buff->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
1853 awc_fid_queue_push_tail(&priv->tx_small_ready,tx_buff);
1855 awc_fid_queue_push_tail(&priv->tx_large_ready,tx_buff);
1857 AWC_ENTRY_EXIT_DEBUG("exit\n");
1862 awc_802_11_after_tx_complete(struct net_device * dev, struct awc_fid * tx_buff){
1864 struct awc_private * priv = (struct awc_private *)dev->priv;
1866 AWC_ENTRY_EXIT_DEBUG("awc_802_11_after_tx_complete");
1868 DEBUG(32,"tx complete status %x \n ",tx_buff->u.tx.radio_tx.Status);
1871 if (tx_buff->u.tx.radio_tx.Status)
1872 printk("tf%x ",tx_buff->u.tx.radio_tx.Status);
1874 if (tx_buff->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE){
1875 awc_fid_queue_push_tail(&priv->tx_small_ready,tx_buff);
1876 priv->tx_small_buffs_in_use--;
1878 awc_fid_queue_push_tail(&priv->tx_large_ready,tx_buff);
1879 priv->tx_buffs_in_use--;
1883 // netif_wake_queue (dev);
1885 AWC_ENTRY_EXIT_DEBUG("exit\n");
1891 /******************************** R X ***********************/
1896 awc_receive_packet(struct net_device * dev){
1898 struct awc_command cmd;
1900 // struct sk_buff *skb = NULL;
1901 struct awc_fid * rx_buff;
1904 struct awc_private * priv ;
1907 priv= (struct awc_private *)dev->priv;
1908 rx_buff = priv->rx_ready.head ;
1910 AWC_ENTRY_EXIT_DEBUG(" entry awc_receive_packet ");
1912 Fid = awc_Rx_Fid(dev->base_addr);
1914 DEBUG(128," RX FID %x \n",Fid);
1917 printk(KERN_CRIT "No RxFid when rx event \n");
1924 printk(KERN_CRIT "No rx_buff in rx event \n");
1931 AWC_INIT_COMMAND(AWC_CLI,cmd,dev,0,0,
1932 Fid, 0, 0x14 , &(rx_buff->u.rx.radio_rx));
1935 // header reading , order is important
1936 AWC_BAP_LOCK_UNDER_CLI(cmd);
1938 if (awc_bap_setup(&cmd)) goto final;
1939 if (awc_bap_read(&cmd)) goto final;
1941 DEBUG(128, "rx receive radio header, length %x \n",rx_buff->u.rx.radio_rx.PayloadLength);
1943 cmd.buff = &(rx_buff->u.rx.ieee_802_11);
1946 if (awc_bap_read(&cmd)) goto final;
1948 DEBUG(128, "rx receive 802_11 header, framecontrol %x \n",rx_buff->u.rx.ieee_802_11.frame_control);
1950 if (rx_buff->u.rx.ieee_802_11.gapLen > 8) {
1951 printk(KERN_ERR "%s: 802.11 gap lenght huge %d \n",dev->name,rx_buff->u.rx.ieee_802_11.gapLen);
1954 DEBUG(128,"SeqCtl %x, 802_11 macs: ",rx_buff->u.rx.ieee_802_11.SeqCtl);
1955 if (awc_debug & 0x7000){
1956 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] )) ;
1957 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] )) ;
1958 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] )) ;
1959 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 DEBUG(128,"\n GapLen %d ",rx_buff->u.rx.ieee_802_11.gapLen );
1963 if (rx_buff->u.rx.ieee_802_11.gapLen > 0) {
1964 cmd.buff = rx_buff->u.rx.ieee_802_11.gap;
1965 cmd.len = rx_buff->u.rx.ieee_802_11.gapLen;
1966 if (awc_bap_read(&cmd)) goto final;
1967 DEBUG(128, "rx receive gap header , gap length %x \n",rx_buff->u.rx.gap_length);
1969 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] )) ;
1972 if ( !(priv->config.ReceiveMode & RXMODE_DISABLE_802_3_HEADER )
1974 cmd.buff = &(rx_buff->u.rx.ieee_802_3);
1976 rx_buff->type |= p80211_8023;
1977 if (awc_bap_read(&cmd)) goto final;
1978 DEBUG(128, "rx receive 802_3 header, payload length %x \n",rx_buff->u.rx.ieee_802_3.payload_length);
1979 DEBUG(128,"\n 802_3 status %x ",rx_buff->u.rx.ieee_802_3.status );
1980 DEBUG(128," RX payloadLen %x, dst,src: ",rx_buff->u.rx.ieee_802_3.payload_length);
1981 if (awc_debug & 0x7000){
1982 for (i = 0; i < 6; i++) printk("%02x:",((unsigned char)rx_buff->u.rx.ieee_802_3.dst_mac[i] )) ;
1983 for (i = 0; i < 6; i++) printk("%02x:",((unsigned char)rx_buff->u.rx.ieee_802_3.src_mac[i] )) ;
1987 rx_buff->pkt_len = rx_buff->u.rx.radio_rx.PayloadLength;
1989 if (priv->config.OperatingMode & MODE_LLC_HOST)
1990 rx_buff->type |= p80211_llc_snap;
1993 if (awc_802_11_find_copy_path(dev,rx_buff)) goto final;
1996 if (rx_buff->u.rx.payload ){
1997 cmd.buff = rx_buff->u.rx.payload;
1998 cmd.len = rx_buff->pkt_len;
1999 if (awc_bap_read(&cmd)) goto final;
2000 DEBUG(128, "rx payload read %x \n",rx_buff->u.rx.ieee_802_3.payload_length);
2003 AWC_RELEASE_COMMAND(cmd);
2005 DEBUG(128,"\n payload hdr %x ",rx_buff->u.rx.ieee_802_3.status );
2006 if (awc_debug && rx_buff->u.rx.payload)
2007 for (i = 0; i < 20; i++) DEBUG(128,"%x",((unsigned char)rx_buff->u.rx.payload[i] )) ;
2008 DEBUG(128,"%c",'\n');
2010 awc_802_11_router_rx(dev,rx_buff);
2012 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2016 awc_802_11_failed_rx_copy(dev,rx_buff);
2017 // if (skb) dev_kfree_skb(skb, FREE_WRITE);
2018 AWC_RELEASE_COMMAND(cmd);
2019 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2026 awc_transmit_packet(struct net_device * dev, struct awc_fid * tx_buff) {
2028 struct awc_command cmd;
2030 // unsigned long flags;
2032 struct awc_private * priv= (struct awc_private *)dev->priv;
2034 AWC_ENTRY_EXIT_DEBUG(" entry awc_transmit_packet ");
2036 if (priv->link_status_changed ){
2037 priv->link_status_changed =0;
2038 awc_readrid_dir(dev,&priv->rid_dir[7]);
2042 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0xB, tx_buff->u.tx.fid,
2043 tx_buff->u.tx.fid, 0, 0x14 , &(tx_buff->u.tx.radio_tx));
2045 AWC_BAP_LOCK_NOT_CLI(cmd);
2048 #warning By books is bad, AWC_BY_BOOK
2049 #error cli sti bad here
2050 if ( !(tx_buff->type &(p80211_llc_snap|p80211_8021H) )
2051 && !(tx_buff->u.tx.radio_tx.TX_Control &
2052 aironet4500_tx_control_header_type_802_11 )){
2054 cmd.buff=&(tx_buff->u.tx.radio_tx.TX_Control);
2059 if (awc_bap_setup(&cmd)) goto final;
2060 if (awc_bap_write(&cmd)) goto final;
2062 cmd.buff=&(tx_buff->u.tx.ieee_802_3.payload_length);
2065 if (awc_bap_setup(&cmd)) goto final;
2066 if (awc_bap_write(&cmd)) goto final;
2067 restore_flags(flags);
2072 if (awc_bap_setup(&cmd)) goto final;
2073 if (awc_bap_write(&cmd)) goto final;
2075 DEBUG(64," wrote radio tx header for fid %x \n",tx_buff->u.tx.fid);
2078 cmd.buff=&(tx_buff->u.tx.ieee_802_11);
2080 if (awc_bap_write(&cmd)) goto final;
2083 if (tx_buff->u.tx.ieee_802_11.gapLen) {
2084 cmd.buff=&(tx_buff->u.tx.ieee_802_11.gap);
2085 cmd.len = tx_buff->u.tx.ieee_802_11.gapLen;
2086 if (awc_bap_write(&cmd)) goto final;
2089 if ( ! (tx_buff->u.tx.radio_tx.TX_Control &
2090 aironet4500_tx_control_header_type_802_11 )){
2092 cmd.buff=&(tx_buff->u.tx.ieee_802_3);
2093 if (awc_debug & 0x7000){
2094 printk("%s TX dst ",dev->name);
2095 for (i=0; i < 6; i++) printk ("%02x:",(unsigned char) tx_buff->u.tx.ieee_802_3.dst_mac[i]);
2097 for (i=0; i < 6; i++) printk ("%02x:",(unsigned char) tx_buff->u.tx.ieee_802_3.src_mac[i]);
2101 if (awc_bap_write(&cmd)) goto final;
2104 if (tx_buff->type & p80211_llc_snap) {
2105 cmd.buff= & tx_buff->snap;
2106 cmd.len = sizeof(tx_buff->snap);
2107 if (awc_bap_write(&cmd)) goto final;
2110 if (tx_buff->type & p80211_8021H) {
2111 size = htons(tx_buff->bridge_size);
2112 // size = tx_buff->bridge_size;// to seasure raw speed of f** UC
2115 if (awc_bap_write(&cmd)) goto final;
2117 cmd.buff= & tx_buff->bridge;
2118 cmd.len = sizeof(tx_buff->bridge);
2119 if (awc_bap_write(&cmd)) goto final;
2126 cmd.buff= tx_buff->u.tx.payload;
2127 cmd.len = tx_buff->pkt_len;
2129 if (awc_bap_write(&cmd)) goto final;
2130 AWC_RELEASE_COMMAND(cmd);
2131 // locking probs, these two lines below and above, swithc order
2132 if (awc_issue_command_and_block(&cmd)) goto final_unlocked;
2135 tx_buff->transmit_start_time = jiffies;
2136 awc_802_11_after_tx_packet_to_card_write(dev,tx_buff);
2137 // issue the transmit command
2140 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2143 awc_802_11_after_failed_tx_packet_to_card_write(dev,tx_buff);
2144 printk(KERN_CRIT "%s awc tx command failed \n",dev->name);
2145 AWC_RELEASE_COMMAND(cmd);
2146 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2150 awc_802_11_after_failed_tx_packet_to_card_write(dev,tx_buff);
2151 printk(KERN_CRIT "%s awc tx command failed \n",dev->name);
2152 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2159 awc_tx_complete_check(struct net_device * dev){
2161 struct awc_fid * fid;
2162 struct awc_command cmd;
2165 AWC_ENTRY_EXIT_DEBUG(" entry awc_tx_complete_check ");
2169 fid = awc_fid_queue_pop_head(&((struct awc_private *)dev->priv)->tx_post_process);
2172 printk("awc_tx_complete_check with empty queue \n ");
2176 DEBUG(64," tx_complete fid %x \n",fid->u.tx.fid);
2178 AWC_INIT_COMMAND(AWC_NOT_CLI,cmd,dev,0,0, fid->u.tx.fid,
2179 0, 0x14 , &(fid->u.tx.radio_tx));
2181 fid->state |= awc_tx_fid_complete_read;
2183 AWC_BAP_LOCK_NOT_CLI(cmd);
2184 if (awc_bap_setup(&cmd)) goto final;
2185 if (awc_bap_read(&cmd)) goto final;
2186 AWC_RELEASE_COMMAND(cmd);
2188 awc_802_11_after_tx_complete(dev,fid);
2191 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2195 awc_802_11_after_tx_complete(dev,fid);
2196 printk(KERN_ERR "%s awc_tx_complete_check failed \n",dev->name);
2197 AWC_RELEASE_COMMAND(cmd);
2198 AWC_ENTRY_EXIT_DEBUG(" BAD exit \n");
2203 #define AWC_QUEUE_BH {\
2204 if (!priv->bh_active && !priv->bh_running){\
2205 priv->bh_active = 1;\
2206 queue_task(&priv->immediate_bh, &tq_immediate);\
2207 mark_bh(IMMEDIATE_BH);\
2213 awc_bh(struct net_device *dev){
2215 struct awc_private * priv = (struct awc_private *)dev->priv;
2216 int active_interrupts;
2217 int enabled_interrupts;
2221 // unsigned long flags;
2223 DEBUG(8, "awc_bh awoken on jiffie %ld \n",jiffies);
2225 priv->bh_running = 1;
2227 active_interrupts = awc_event_status(dev->base_addr);
2229 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2231 DEBUG(8, "awc_bh active ints %x \n",active_interrupts);
2233 if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
2234 // printk(KERN_ERR "tx chain active in bh \n");
2235 // queue_task(&priv->immediate_bh, &tq_immediate);
2239 if (active_interrupts == 0xffff){
2241 printk(KERN_CRIT "%s device ejected in interrupt, disabling\n",dev->name);
2242 netif_device_detach (dev);
2243 if (priv->command_semaphore_on){
2244 priv->command_semaphore_on--;
2245 AWC_UNLOCK_COMMAND_ISSUING(priv);
2247 priv->tx_chain_active =0;
2252 if (priv->unlock_command_postponed ){
2254 priv->unlock_command_postponed-- ;
2255 if( priv->command_semaphore_on ){
2257 awc_read_response((&priv->cmd));
2258 priv->async_command_start = 0;
2259 if (priv->command_semaphore_on){
2261 priv->command_semaphore_on--;
2262 AWC_UNLOCK_COMMAND_ISSUING(priv);
2267 /* if ( active_interrupts & 0x1 ){
2268 awc_receive_packet(dev) ;
2269 awc_event_ack_Rx(dev->base_addr);
2270 priv->waiting_interrupts &= ~0x1;
2273 while (priv->tx_post_process.size)
2274 if (awc_tx_complete_check(dev)) break;
2276 active_interrupts = awc_event_status(dev->base_addr);
2278 if (priv->command_semaphore_on || priv->tx_post_process.size){
2279 if (multi_ints++ < 10000){
2283 priv->bh_active = 0;
2284 priv->bh_running = 0;
2286 priv->tx_chain_active = 0;
2291 // if (!priv->tx_chain_active)
2292 // wake_up(&priv->tx_chain_wait_queue);
2294 priv->bh_running = 0;
2295 priv->bh_active = 0;
2301 awc_interrupt_process(struct net_device * dev){
2303 struct awc_private * priv ;
2304 int active_interrupts;
2305 int enabled_interrupts;
2309 // u16 ints_to_ack =0;
2310 struct awc_fid * fid = NULL;
2311 // int interrupt_reenter = 0;
2312 // unsigned long flags;
2314 // save_flags(flags);
2316 // here we need it, because on 2.3 SMP there are truly parallel irqs
2317 disable_irq(dev->irq);
2319 DEBUG(2," entering interrupt handler %s ",dev->name);
2322 printk(KERN_ERR "No dev in interrupt \n");
2326 priv = (struct awc_private *)dev->priv;
2329 printk(KERN_ERR "No PRIV in interrupt \n");
2334 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2335 active_interrupts = awc_event_status(dev->base_addr);
2337 DEBUG(2,"entry: processing interrupts waiting %x \n",priv->waiting_interrupts);
2338 DEBUG(2,"entry: processing interrupts active %x \n",active_interrupts);
2339 DEBUG(2,"entry: processing interrupts enabled %x \n",enabled_interrupts);
2340 // printk("ikka interruptis\n");
2343 priv->interrupt_count++;
2344 if (priv->interrupt_count > 1 )
2345 printk(" interrupt count on\n ");
2349 if (priv->waiting_interrupts & active_interrupts)
2350 printk(KERN_ERR "double interrupt waiting %x active %x \n",
2351 priv->waiting_interrupts, active_interrupts);
2353 // priv->waiting_interrupts |= active_interrupts;
2360 DEBUG(2,"Start processing int, times %d\n",multi_ints);
2362 if (active_interrupts == 0xffff){
2364 printk(KERN_CRIT "%s device ejected, got interrupt, disabling\n",dev->name);
2366 netif_device_detach (dev);
2368 if (priv->bh_active || priv->bh_running){
2369 priv->interrupt_count--;
2371 } else if (priv->command_semaphore_on){
2373 printk(KERN_ERR "ejected, last BH fired \n");
2377 priv->interrupt_count--;
2383 if (active_interrupts & 0x100 ){
2384 awc_event_ack_Awaken(dev->base_addr);
2386 DEBUG(1,"%s device awoke \n",dev->name);
2387 priv->waiting_interrupts &= ~0x100;
2389 if (active_interrupts & 0x80 ){
2391 priv->link_status = awc_Link_Status(dev->base_addr);
2392 DEBUG(1,"link status changed %x \n",priv->link_status);
2393 awc_event_ack_Link(dev->base_addr);
2394 priv->waiting_interrupts &= ~0x80;
2395 if(priv->link_status == 0x400)
2396 printk(KERN_INFO "%s Associated\n",dev->name );
2398 printk(KERN_INFO "%s Link status change : %s \n",dev->name, awc_print_string(awc_link_status_names, priv->link_status) );
2399 if ( priv->link_status & 0x8100 ||
2400 priv->link_status & 0x0100 ||
2401 priv->link_status & 0x8200 ||
2402 priv->link_status & 0x8400 ||
2403 priv->link_status & 0x0300 )
2404 printk(KERN_INFO "%s Link status change reason : %s \n",dev->name, awc_print_string(awc_link_failure_reason_names, priv->link_status & 0xff) );
2410 if (active_interrupts & 0x10 & enabled_interrupts ){
2412 // printk(KERN_ERR "cmd int shouldnt be active in interrupt routine\n");
2414 awc_event_ack_Cmd(priv->cmd.port);
2416 if ( priv->enabled_interrupts & 0x10)
2417 priv->enabled_interrupts &= ~0x10;
2419 enabled_interrupts = awc_ints_enabled(dev->base_addr);
2421 if (enabled_interrupts & 0x10){
2422 awc_ints_enable(dev->base_addr, enabled_interrupts & ~0x10);
2425 if (priv->command_semaphore_on){
2426 priv->unlock_command_postponed++;
2432 if ((active_interrupts & 0x10) && !(0x10 & enabled_interrupts) ){
2434 // printk(KERN_ERR "%s: aironet4500: cmd int shouldnt be active in interrupt routine\n",dev->name);
2436 //awc_event_ack_Cmd(priv->cmd.port);
2440 // active_interrupts = awc_event_status(dev->base_addr);
2442 tx_status = active_interrupts & 0x6 ;
2448 tx_fid = awc_Tx_Compl_Fid(dev->base_addr);
2451 tx_fid = awc_Tx_Compl_Fid(dev->base_addr);
2454 printk(KERN_ERR "No tx fid when tx int active\n");
2456 fid = awc_tx_fid_lookup_and_remove(dev, tx_fid);
2459 if (priv->process_tx_results) {
2460 awc_fid_queue_push_tail(&priv->tx_post_process,fid);
2463 if (fid->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
2464 awc_fid_queue_push_tail(&priv->tx_small_ready,fid);
2466 awc_fid_queue_push_tail(&priv->tx_large_ready,fid);
2467 netif_wake_queue (dev);
2470 printk(KERN_ERR "awc fid %x not found\n",tx_fid);
2474 awc_event_ack_Tx(dev->base_addr);
2475 priv->stats.tx_packets++;
2476 priv->waiting_interrupts &= ~0x2;
2479 priv->stats.tx_errors++;
2480 awc_event_ack_TxExc(dev->base_addr);
2481 priv->waiting_interrupts &= ~0x4;
2483 if ((tx_status&6) == 6)
2484 printk(KERN_NOTICE "%s: both tx and txExc up\n",dev->name);
2489 // active_interrupts = awc_event_status(dev->base_addr);
2491 if ( active_interrupts & 0x1 ){
2492 awc_receive_packet(dev);
2493 awc_event_ack_Rx(dev->base_addr);
2494 priv->waiting_interrupts &= ~0x1;
2497 active_interrupts = awc_event_status(dev->base_addr);
2499 if ((active_interrupts & 0x7) &&
2501 !priv->bh_running ){
2502 if (multi_ints++ < 5)
2505 if (multi_ints >=5 )
2506 printk(KERN_ERR "%s multi_ints > 5 interrupts still active %x\n",dev->name,active_interrupts);
2509 priv->interrupt_count--;
2511 awc_ints_enable(dev->base_addr, 0x0000);
2514 DEBUG(0x8, " enabling ints in interrupt_process %x \n",
2515 priv->enabled_interrupts & ~priv->waiting_interrupts);
2519 AWC_ENTRY_EXIT_DEBUG(" exit \n");
2521 awc_ints_enable(dev->base_addr,
2522 priv->enabled_interrupts);
2526 enable_irq(dev->irq);
2527 // restore_flags(flags);
2532 AWC_ENTRY_EXIT_DEBUG(" bad_end exit \n");
2533 enable_irq(dev->irq);
2534 // restore_flags(flags);
2540 static const char *aironet4500_core_version =
2541 "aironet4500.c v0.1 1/1/99 Elmer Joandi, elmer@ylenurme.ee.\n";
2543 struct net_device * aironet4500_devices[MAX_AWCS];
2545 int awc_debug; // 0xffffff;
2546 static int p802_11_send; // 1
2548 static int awc_process_tx_results;
2549 int tx_queue_len = 10;
2552 //static int tx_full_rate;
2555 int large_buff_mem = 1700 * 10;
2556 int small_buff_no = 20;
2561 int awc_simple_bridge;
2564 #if LINUX_VERSION_CODE >= 0x20100
2566 MODULE_PARM(awc_debug,"i");
2567 MODULE_PARM(tx_rate,"i");
2568 MODULE_PARM(channel,"i");
2569 //MODULE_PARM(tx_full_rate,"i");
2570 MODULE_PARM(adhoc,"i");
2571 MODULE_PARM(master,"i");
2572 MODULE_PARM(slave,"i");
2573 MODULE_PARM(awc_simple_bridge,"i");
2574 MODULE_PARM(max_mtu,"i");
2575 MODULE_PARM(large_buff_mem,"i");
2576 MODULE_PARM(small_buff_no,"i");
2577 MODULE_PARM(SSID,"c33");
2578 MODULE_PARM_DESC(awc_debug,"Aironet debug mask");
2579 MODULE_PARM_DESC(channel,"Aironet ");
2580 MODULE_PARM_DESC(adhoc,"Aironet Access Points not available (0-1)");
2581 MODULE_PARM_DESC(master,"Aironet is Adhoc master (creates network sync) (0-1)");
2582 MODULE_PARM_DESC(slave,"Aironet is Adhoc slave (0-1)");
2583 MODULE_PARM_DESC(max_mtu,"Aironet MTU limit (256-2312)");
2585 MODULE_LICENSE("GPL");
2588 /*EXPORT_SYMBOL(tx_queue_len);
2589 EXPORT_SYMBOL(awc_debug);
2591 EXPORT_SYMBOL(awc_init);
2592 EXPORT_SYMBOL(awc_open);
2593 EXPORT_SYMBOL(awc_close);
2594 EXPORT_SYMBOL(awc_reset);
2595 EXPORT_SYMBOL(awc_config);
2597 EXPORT_SYMBOL(aironet4500_devices);
2598 EXPORT_SYMBOL(awc_debug);
2601 EXPORT_SYMBOL(awc_private_init);
2602 EXPORT_SYMBOL(awc_tx_timeout);
2603 EXPORT_SYMBOL(awc_start_xmit);
2604 EXPORT_SYMBOL(awc_interrupt);
2605 EXPORT_SYMBOL(awc_get_stats);
2606 EXPORT_SYMBOL(awc_change_mtu);
2607 EXPORT_SYMBOL(awc_set_multicast_list);
2609 EXPORT_SYMBOL(awc_proc_set_fun);
2610 EXPORT_SYMBOL(awc_proc_unset_fun);
2611 EXPORT_SYMBOL(awc_register_proc);
2612 EXPORT_SYMBOL(awc_unregister_proc);
2615 /*************************** RESET INIT CONFIG ***********************/
2618 void awc_reset(struct net_device *dev)
2623 DEBUG(2, " awc_reset dev %p \n", dev);
2624 DEBUG(2, "%s: awc_reset \n", dev->name);
2626 awc_issue_soft_reset(dev);
2630 while (awc_command_read(dev->base_addr)){
2632 if (jiffies - jiff > 5*HZ){
2633 printk(KERN_CRIT "%s bad reset\n",dev->name);
2640 int awc_config(struct net_device *dev)
2642 // struct awc_private *priv = (struct awc_private *)dev->priv;
2644 DEBUG(2, "%s: awc_config \n", dev->name);
2647 if( awc_disable_MAC(dev)) goto final;
2649 if( awc_write_all_rids(dev) ) goto final;
2651 if( awc_enable_MAC(dev)) goto final;
2659 char name[] = "ElmerLinux";
2661 int awc_init(struct net_device *dev){
2662 struct awc_private *priv = (struct awc_private *)dev->priv;
2664 const char * radioType;
2666 DEBUG(2, "%s: awc_init \n", dev->name);
2668 /* both_bap_lock decreases performance about 15%
2669 * but without it card gets screwed up
2672 if(smp_num_cpus > 1){
2674 bap_setup_spinlock = 1;
2677 //awc_dump_registers(dev);
2679 if (adhoc & !max_mtu)
2684 priv->sleeping_bap = 1;
2687 priv->enabled_interrupts = awc_ints_enabled(dev->base_addr);
2689 if( awc_issue_noop(dev) ) goto final;
2691 awc_ints_enable(dev->base_addr,0);
2693 if( awc_disable_MAC(dev) ) goto final;
2696 // awc_rids_setup(dev);
2698 while ( i < AWC_NOF_RIDS){
2699 if (awc_rids_temp[i].selector)
2700 memcpy(&priv->rid_dir[i],&awc_rids_temp[i],sizeof(priv->rid_dir[0]) );
2701 else priv->rid_dir[i].selector = NULL;
2705 // following MUST be consistent with awc_rids in count and ordrering !!!
2706 priv->rid_dir[0].buff = &priv->config; // card RID mirrors
2707 priv->rid_dir[1].buff = &priv->SSIDs;
2708 priv->rid_dir[2].buff = &priv->fixed_APs;
2709 priv->rid_dir[3].buff = &priv->driver_name;
2710 priv->rid_dir[4].buff = &priv->enc_trans;
2711 priv->rid_dir[5].buff = &priv->general_config; //
2712 priv->rid_dir[6].buff = &priv->capabilities;
2713 priv->rid_dir[7].buff = &priv->status;
2714 priv->rid_dir[8].buff = &priv->AP;
2715 priv->rid_dir[9].buff = &priv->statistics;
2716 priv->rid_dir[10].buff = &priv->statistics_delta;
2717 priv->rid_dir[11].buff = &priv->statistics_delta_clear;
2718 priv->rid_dir[12].buff = &priv->wep_volatile;
2719 priv->rid_dir[13].buff = &priv->wep_nonvolatile;
2720 priv->rid_dir[14].buff = &priv->modulation;
2722 priv->rid_dir[15].buff = &priv->statistics16;
2723 priv->rid_dir[16].buff = &priv->statistics16_delta;
2724 priv->rid_dir[17].buff = &priv->statistics16_delta_clear;
2726 priv->rid_dir[0].bufflen = sizeof(priv->config); // card RID mirrors
2727 priv->rid_dir[1].bufflen = sizeof(priv->SSIDs);
2728 priv->rid_dir[2].bufflen = sizeof(priv->fixed_APs);
2729 priv->rid_dir[3].bufflen = sizeof(priv->driver_name);
2730 priv->rid_dir[4].bufflen = sizeof(priv->enc_trans);
2731 priv->rid_dir[5].bufflen = sizeof(priv->general_config); //
2732 priv->rid_dir[6].bufflen = sizeof(priv->capabilities);
2733 priv->rid_dir[7].bufflen = sizeof(priv->status);
2734 priv->rid_dir[8].bufflen = sizeof(priv->AP);
2735 priv->rid_dir[9].bufflen = sizeof(priv->statistics);
2736 priv->rid_dir[10].bufflen = sizeof(priv->statistics_delta);
2737 priv->rid_dir[11].bufflen = sizeof(priv->statistics_delta_clear);
2738 priv->rid_dir[12].bufflen = sizeof(priv->wep_volatile);
2739 priv->rid_dir[13].bufflen = sizeof(priv->wep_nonvolatile);
2740 priv->rid_dir[14].bufflen = sizeof(priv->modulation);
2742 priv->rid_dir[15].bufflen = sizeof(priv->statistics16);
2743 priv->rid_dir[16].bufflen = sizeof(priv->statistics16_delta);
2744 priv->rid_dir[17].bufflen = sizeof(priv->statistics16_delta_clear);
2747 if( awc_read_all_rids(dev) ) goto final;
2750 priv->config.OperatingMode = 0;// MODE_LLC_HOST;
2751 DEBUG(1,"ReceiveMode %x \n",priv->config.ReceiveMode);
2752 // priv->config.ReceiveMode = RXMODE_DISABLE_802_3_HEADER;
2755 priv->config.OperatingMode = MODE_STA_ESS;
2756 // priv->config.OperatingMode = MODE_AP;
2757 // Setting rates does not work with new hardware, use force_tx_rate via proc
2758 // priv->config.Rates[0] =0x82;
2759 // priv->config.Rates[1] =0x4;
2760 // priv->config.Rates[2] =tx_full_rate;
2761 // priv->config.Rates[3] =0;
2762 // priv->config.Rates[4] =0;
2763 // priv->config.Rates[5] =0;
2764 // priv->config.Rates[6] =0;
2765 // priv->config.Rates[7] =0;
2766 priv->config.Channel = channel;
2767 if (adhoc && master){
2768 priv->config.JoinNetTimeout = 0x1;//0 is facotry default
2769 } else if (adhoc && slave){
2770 // by spec 0xffff, but, this causes immediate bad behaviour
2771 // firmware behvaiour changed somehere around ver 2??
2772 priv->config.JoinNetTimeout = 0x7fff;
2774 // priv->config.AuthenticationType = 1;
2775 priv->config.Stationary =1;
2776 // priv->config.ScanMode = 1;
2777 // priv->config.LinkLossDelay = 100;
2778 priv->config.FragmentThreshold = 1700;
2779 priv->config.RtsThreshold = 1700;
2780 memcpy(priv->config.NodeName, name, 10);
2782 DEBUG(1,"%s supported Rates \n",dev->name);
2783 for (i=0; i< 8; i++)
2784 DEBUG(1,"%x ",priv->capabilities.SupportedRates[i]);
2786 DEBUG(1,"%s default Rates \n",dev->name);
2787 for (i=0; i< 8; i++)
2788 DEBUG(1,"%x ",priv->config.Rates[i]);
2792 // here we go, bad aironet
2793 memset(&priv->SSIDs,0,sizeof(priv->SSIDs));
2795 spin_lock_init(&priv->queues_lock);
2796 priv->SSIDs.ridLen =0;
2798 priv->SSIDs.SSID[0].SSID[0] ='a';
2799 priv->SSIDs.SSID[0].SSID[1] ='b';
2800 priv->SSIDs.SSID[0].SSID[2] ='c';
2801 priv->SSIDs.SSID[0].lenght =3;
2803 int sidlen = strlen(SSID);
2804 memcpy(priv->SSIDs.SSID[0].SSID,SSID,sidlen);
2805 priv->SSIDs.SSID[0].lenght = sidlen;
2808 priv->SSIDs.SSID[1].lenght =0;
2809 priv->SSIDs.SSID[1].SSID[0] =0;
2810 priv->SSIDs.SSID[1].SSID[1] =0;
2811 priv->SSIDs.SSID[2].lenght =0;
2812 priv->SSIDs.SSID[2].SSID[0] =0;
2813 priv->SSIDs.SSID[2].SSID[1] =0;
2816 // priv->enc_trans.rules[0].etherType= 0x0008;
2817 // priv->enc_trans.rules[0].Action = 1;
2819 memcpy( priv->config.StationMacAddress,
2820 priv->capabilities.FactoryAddress, 6 );
2822 memcpy(dev->dev_addr, priv->config.StationMacAddress, 6);
2824 DEBUG(2, "%s: awc_init success \n", dev->name);
2826 if (priv->capabilities.RadioType == 1) radioType = "802.11 Frequency Hoping";
2827 else if (priv->capabilities.RadioType == 2) radioType = "802.11 Direct Sequence";
2828 else if (priv->capabilities.RadioType == 4) radioType = "LM2000";
2829 else radioType = "Multiple Radio Types";
2831 printk("%s: %s %s found @ 0x%lx irq %d firmwareVersion %d \n",dev->name,
2832 priv->capabilities.ProductName,radioType,
2833 dev->base_addr,dev->irq,
2834 priv->capabilities.SoftwareVersion);
2838 printk(KERN_ERR "aironet init failed \n");
2843 int awc_private_init(struct net_device * dev){
2844 struct awc_private * priv = (struct awc_private *) dev->priv;
2847 DEBUG(2, "%s: awc_private_init \n", dev->name);
2850 memset(priv, 0, sizeof(struct awc_private));
2852 spin_lock_init(&priv->queues_lock);
2854 priv->bap0.select = dev->base_addr + awc_Select0_register;
2855 priv->bap0.offset = dev->base_addr + awc_Offset0_register;
2856 priv->bap0.data = dev->base_addr + awc_Data0_register;
2857 priv->bap0.lock = 0;
2858 priv->bap0.status = 0;
2859 spin_lock_init(&priv->bap0.spinlock);
2860 init_MUTEX(&priv->bap0.sem);
2861 priv->bap1.select = dev->base_addr + awc_Select1_register;
2862 priv->bap1.offset = dev->base_addr + awc_Offset1_register;
2863 priv->bap1.data = dev->base_addr + awc_Data1_register;
2864 priv->bap1.lock = 0;
2865 priv->bap1.status = 0;
2866 spin_lock_init(&priv->bap1.spinlock);
2867 init_MUTEX(&priv->bap1.sem);
2868 priv->sleeping_bap = 1;
2870 //spinlock now init_MUTEX(&priv->command_semaphore);
2871 spin_lock_init(&priv->command_issuing_spinlock);
2872 spin_lock_init(&priv->both_bap_spinlock);
2873 spin_lock_init(&priv->bap_setup_spinlock);
2874 spin_lock_init(&priv->interrupt_spinlock);
2876 priv->command_semaphore_on = 0;
2877 priv->unlock_command_postponed = 0;
2878 INIT_LIST_HEAD(&priv->immediate_bh.list);
2879 priv->immediate_bh.sync = 0;
2880 priv->immediate_bh.routine = (void *)(void *)awc_bh;
2881 priv->immediate_bh.data = dev;
2882 priv->bh_running = 0;
2883 priv->bh_active = 0;
2884 priv->tx_chain_active = 0;
2885 priv->enabled_interrupts= 0x00;
2886 priv->waiting_interrupts= 0x00;
2889 init_MUTEX(&priv->tx_buff_semaphore);
2890 priv->tx_buffs_in_use = 0;
2891 priv->tx_small_buffs_in_use = 0;
2892 priv->mac_enabled =0;
2893 priv->link_status =0;
2894 priv->large_buff_mem = large_buff_mem;
2895 if (priv->large_buff_mem < max_mtu + AWC_TX_HEAD_SIZE + 10 )
2896 priv->large_buff_mem = max_mtu + AWC_TX_HEAD_SIZE + 10;
2897 priv->small_buff_no = small_buff_no;
2898 if (priv->small_buff_no < 1 )
2899 priv->small_buff_no = 1 ;
2901 priv->process_tx_results = awc_process_tx_results;
2903 //init_waitqueue(&priv->tx_chain_wait_queue);
2905 for (i=0; i< 6 ; i++ ) {
2906 priv->p2p[i] = 0xff;
2912 priv->p802_11_send =p802_11_send;
2913 priv->full_stats = awc_full_stats;
2914 priv->simple_bridge = awc_simple_bridge;
2915 priv->force_rts_on_shorter = 0;
2916 priv->force_tx_rate = tx_rate;
2917 priv->ip_tos_reliability_rts = 0;
2918 priv->ip_tos_troughput_no_retries = 0 ;
2921 priv->interrupt_count =0;
2927 /**************************** OPEN CLOSE **********************/
2930 int awc_open(struct net_device *dev)
2932 struct awc_private *priv = (struct awc_private *)dev->priv;
2936 DEBUG(2, "%s: awc_open \n", dev->name);
2938 if( awc_queues_init(dev) ) goto final;
2939 if( awc_config(dev) ) goto final;
2941 memcpy(dev->dev_addr, priv->config.StationMacAddress, 6);
2943 priv->enabled_interrupts = 0x87;
2944 awc_ints_enable(dev->base_addr,priv->enabled_interrupts);
2946 // priv->p8022_client = register_8022_client;
2947 // priv->snap_client = register_snap_client;
2948 DEBUG(2, "%s: opened \n", dev->name);
2950 priv->sleeping_bap = 0;
2954 // kernel_thread(awc_thread,dev,0);
2956 netif_start_queue (dev);
2957 return 0; /* Always succeed */
2960 netif_device_detach (dev);
2961 printk(KERN_ERR "aironet open failed \n");
2966 int awc_close(struct net_device *dev)
2968 struct awc_private * priv = (struct awc_private *) dev->priv;
2970 DEBUG(2, "%s: closing device.\n", dev->name);
2972 netif_stop_queue (dev);
2974 awc_disable_MAC(dev);
2975 awc_queues_destroy(dev);
2981 AWC_LOCK_COMMAND_ISSUING(priv);
2985 AWC_UNLOCK_COMMAND_ISSUING(priv);
2992 /****************************** TX RX STUFF ******************/
2996 void awc_tx_timeout (struct net_device *dev)
2998 struct awc_private *priv = (struct awc_private *) dev->priv;
2999 struct awc_fid * fid;
3001 unsigned long flags;
3003 DEBUG (2, "%s: awc_tx_timeout \n", dev->name);
3005 printk (KERN_NOTICE "%s: Transmit timed out , buffs %d %d, queues tx %d pp %d lrg %d sm %d \n ",
3006 dev->name, priv->tx_small_buffs_total, priv->tx_buffs_total,
3007 priv->tx_in_transmit.size, priv->tx_post_process.size,
3008 priv->tx_large_ready.size, priv->tx_small_ready.size);
3009 priv->stats.tx_errors++;
3013 fid = priv->tx_in_transmit.head;
3015 while (fid) { // removing all fids older that that
3016 if (jiffies - fid->transmit_start_time > (HZ)) {
3017 // printk(KERN_ERR "%s staled tx_buff found, age %uld jiffies\n",dev->name,
3018 // jiffies - fid->transmit_start_time );
3019 awc_fid_queue_remove (&priv->tx_in_transmit, fid);
3020 if (fid->u.tx.fid_size <= AWC_TX_ALLOC_SMALL_SIZE)
3021 awc_fid_queue_push_tail (&priv->tx_small_ready, fid);
3023 awc_fid_queue_push_tail (&priv->tx_large_ready, fid);
3027 printk ("bbb in awc_fid_queue\n");
3028 restore_flags(flags);
3033 restore_flags(flags);
3034 dev->trans_start = jiffies;
3035 netif_wake_queue (dev);
3039 long long last_tx_q_hack;
3042 int awc_start_xmit(struct sk_buff *skb, struct net_device *dev) {
3044 struct awc_private *priv = (struct awc_private *)dev->priv;
3046 // unsigned long flags;
3048 DEBUG(2, "%s: awc_start_xmit \n", dev->name);
3052 DEBUG(1, " xmit dev=NULL, jiffie %ld \n",jiffies);
3057 DEBUG(1, " xmit skb=NULL, jiffie %ld \n",jiffies);
3061 // if (test_and_set_bit( 0, (void *) &priv->tx_chain_active) ) {
3062 // netif_start_queue (dev);
3066 dev->trans_start = jiffies;
3067 retval = awc_802_11_tx_find_path_and_post(dev,skb);
3068 priv->tx_chain_active = 0;
3069 // wake_up_interruptible(&priv->tx_chain_wait_queue);
3071 // if (!dev->tbusy) dev_tint(dev);
3075 void awc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
3077 struct net_device *dev = dev_id;
3078 struct awc_private *priv;
3079 unsigned long flags;
3081 // if ((dev == NULL)) return;
3083 priv = (struct awc_private *)dev->priv;
3088 DEBUG(2, "%s: awc_interrupt \n", dev->name);
3089 spin_lock_irqsave(&priv->interrupt_spinlock, flags);
3091 awc_interrupt_process(dev);
3093 spin_unlock_irqrestore(&priv->interrupt_spinlock, flags);
3098 /************************ STATS, MULTICAST & STUFF ****************/
3102 struct net_device_stats *awc_get_stats(struct net_device *dev)
3104 struct awc_private *priv = (struct awc_private *)dev->priv;
3105 // unsigned long flags;
3107 // int unlocked_stats_in_interrupt=0;
3109 DEBUG(2, "%s: awc_get_stats \n", dev->name);
3111 if (!netif_running(dev)) {
3114 // save_flags(flags);
3117 awc_readrid_dir(dev, &priv->rid_dir[9]);
3118 // restore_flags(flags);
3120 // the very following is the very wrong very probably
3121 if (awc_full_stats){
3122 priv->stats.rx_bytes = priv->statistics.HostRxBytes;
3123 priv->stats.tx_bytes = priv->statistics.HostTxBytes;
3124 priv->stats.rx_fifo_errors = priv->statistics.RxOverrunErr ;
3125 priv->stats.rx_crc_errors = priv->statistics.RxPlcpCrcErr + priv->statistics.RxMacCrcErr ;
3126 priv->stats.rx_frame_errors = priv->statistics.RxPlcpFormat ;
3127 priv->stats.rx_length_errors = priv->statistics.RxPlcpLength ;
3128 priv->stats.rx_missed_errors = priv->statistics.RxAged ;
3129 priv->stats.rx_over_errors = priv->statistics.RxOverrunErr ;
3131 priv->stats.collisions = priv->statistics.TxSinColl;
3132 priv->stats.tx_aborted_errors = priv->statistics.TxAged ;
3133 priv->stats.tx_fifo_errors = priv->statistics.HostTxFail ;
3134 priv->stats.tx_window_errors = priv->statistics.TxMulColl ;
3135 priv->stats.tx_heartbeat_errors = priv->statistics.DefersProt +priv->statistics.DefersEngy ;
3136 priv->stats.tx_carrier_errors = priv->statistics.RetryLong +priv->statistics.RetryShort ;
3137 priv->stats.multicast = priv->statistics.HostRxMc;
3141 // printk("rx_packets %d\n",priv->stats.rx_packets);
3142 return &(priv->stats);
3146 int awc_change_mtu(struct net_device *dev, int new_mtu){
3148 // struct awc_private *priv = (struct awc_private *)dev->priv;
3149 unsigned long flags;
3151 if ((new_mtu < 256 ) || (new_mtu > 2312) || (max_mtu && new_mtu > max_mtu) )
3154 if (netif_running(dev)) {
3155 printk("PLEASE, ifconfig %s down for mtu change\n",dev->name);
3158 if (dev->mtu != new_mtu) {
3161 netif_stop_queue(dev);
3162 awc_disable_MAC(dev);
3163 restore_flags(flags);
3165 awc_tx_dealloc(dev);
3168 awc_enable_MAC(dev);
3169 netif_start_queue(dev);
3171 printk("%s mtu has been changed to %d \n ",dev->name,dev->mtu);
3181 awc_set_multicast_list(struct net_device *dev) {
3182 // int ioaddr = dev->base_addr;
3184 /* if (dev->flags & IFF_PROMISC)
3186 else if (dev->mc_count || (dev->flags & IFF_ALLMULTI))
3197 int (* awc_proc_set_fun) (int);
3198 int (* awc_proc_unset_fun) (int);
3201 int awc_register_proc(int (*awc_proc_set_device)(int),int (*awc_proc_unset_device)(int)){
3203 AWC_ENTRY_EXIT_DEBUG("awc_register_proc");
3204 awc_proc_set_fun = awc_proc_set_device;
3205 awc_proc_unset_fun = awc_proc_unset_device;
3206 AWC_ENTRY_EXIT_DEBUG("exit");
3210 int awc_unregister_proc(void){
3212 AWC_ENTRY_EXIT_DEBUG("awc_unregister_proc");
3214 awc_proc_set_fun = NULL;
3215 awc_proc_unset_fun = NULL;
3216 AWC_ENTRY_EXIT_DEBUG("exit");
3220 static int aironet_core_init(void)
3222 // unsigned long flags;
3225 printk(KERN_INFO"%s", aironet4500_core_version);
3231 static void aironet_core_exit(void)
3233 printk(KERN_INFO "aironet4500 unloading core module \n");
3237 module_init(aironet_core_init);
3238 module_exit(aironet_core_exit);