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