linux-bk/drivers/net/aironet4500_card.c
<<
>>
Prefs
   1/*
   2 *       Aironet 4500 PCI-ISA-i365 driver
   3 *
   4 *              Elmer Joandi, Januar 1999
   5 *      Copyright GPL
   6 *      
   7 *
   8 *      Revision 0.1 ,started  30.12.1998
   9 *
  10 *      Revision 0.2, Feb 27, 2000
  11 *              Jeff Garzik - softnet, cleanups
  12 *
  13 */
  14#ifdef MODULE
  15static const char *awc_version =
  16"aironet4500_cards.c v0.2  Feb 27, 2000  Elmer Joandi, elmer@ylenurme.ee.\n";
  17#endif
  18
  19#include <linux/version.h>
  20#include <linux/config.h>
  21#include <linux/module.h>
  22
  23#include <linux/kernel.h>
  24#include <linux/sched.h>
  25#include <linux/tqueue.h>
  26#include <linux/slab.h>
  27#include <linux/string.h>
  28#include <linux/timer.h>
  29#include <linux/interrupt.h>
  30#include <linux/in.h>
  31#include <asm/io.h>
  32#include <asm/system.h>
  33#include <asm/bitops.h>
  34
  35#include <linux/netdevice.h>
  36#include <linux/etherdevice.h>
  37#include <linux/skbuff.h>
  38#include <linux/if_arp.h>
  39#include <linux/ioport.h>
  40#include <linux/delay.h>
  41#include <linux/init.h>
  42
  43#include "aironet4500.h"
  44
  45#define PCI_VENDOR_ID_AIRONET   0x14b9
  46#define PCI_DEVICE_AIRONET_4800_1 0x1
  47#define PCI_DEVICE_AIRONET_4800 0x4500
  48#define PCI_DEVICE_AIRONET_4500 0x4800
  49#define AIRONET4X00_IO_SIZE     0x40
  50#define AIRONET4X00_CIS_SIZE    0x300
  51#define AIRONET4X00_MEM_SIZE    0x300
  52
  53#define AIRONET4500_PCI         1
  54#define AIRONET4500_PNP         2
  55#define AIRONET4500_ISA         3
  56#define AIRONET4500_365         4
  57
  58
  59#ifdef CONFIG_AIRONET4500_PCI
  60
  61#include <linux/pci.h>
  62
  63static struct pci_device_id aironet4500_card_pci_tbl[] __devinitdata = {
  64        { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4800_1, PCI_ANY_ID, PCI_ANY_ID, },
  65        { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4800, PCI_ANY_ID, PCI_ANY_ID, },
  66        { PCI_VENDOR_ID_AIRONET, PCI_DEVICE_AIRONET_4500, PCI_ANY_ID, PCI_ANY_ID, },
  67        { }                     /* Terminating entry */
  68};
  69MODULE_DEVICE_TABLE(pci, aironet4500_card_pci_tbl);
  70MODULE_LICENSE("GPL");
  71
  72
  73static int reverse_probe;
  74
  75
  76static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev,
  77                        int ioaddr, int cis_addr, int mem_addr,u8 pci_irq_line) ;
  78
  79
  80int awc4500_pci_probe(struct net_device *dev)
  81{
  82        int cards_found = 0;
  83        static int pci_index;   /* Static, for multiple probe calls. */
  84        u8 pci_irq_line = 0;
  85//      int p;
  86
  87        unsigned char awc_pci_dev, awc_pci_bus;
  88
  89        if (!pci_present()) 
  90                return -1;
  91
  92        for (;pci_index < 0xff; pci_index++) {
  93                u16 vendor, device, pci_command, new_command;
  94                u32 pci_memaddr;
  95                u32 pci_ioaddr;
  96                u32 pci_cisaddr;
  97                struct pci_dev *pdev;
  98
  99                if (pcibios_find_class  (PCI_CLASS_NETWORK_OTHER << 8,
 100                         reverse_probe ? 0xfe - pci_index : pci_index,
 101                                 &awc_pci_bus, &awc_pci_dev) != PCIBIOS_SUCCESSFUL){
 102                                if (reverse_probe){
 103                                        continue;
 104                                } else {
 105                                        break;
 106                                }
 107                }
 108                pdev = pci_find_slot(awc_pci_bus, awc_pci_dev);
 109                if (!pdev)
 110                        continue;
 111                if (pci_enable_device(pdev))
 112                        continue;
 113                vendor = pdev->vendor;
 114                device = pdev->device;
 115                pci_irq_line = pdev->irq;
 116                pci_memaddr = pci_resource_start (pdev, 0);
 117                pci_cisaddr = pci_resource_start (pdev, 1);
 118                pci_ioaddr = pci_resource_start (pdev, 2);
 119
 120//              printk("\n pci capabilities %x and ptr %x \n",pci_caps,pci_caps_ptr);
 121                /* Remove I/O space marker in bit 0. */
 122
 123                if (vendor != PCI_VENDOR_ID_AIRONET)
 124                        continue;
 125                if (device != PCI_DEVICE_AIRONET_4800_1 && 
 126                                device != PCI_DEVICE_AIRONET_4800 &&
 127                                device != PCI_DEVICE_AIRONET_4500 )
 128                        continue;
 129
 130//              if (check_region(pci_ioaddr, AIRONET4X00_IO_SIZE) ||
 131//                      check_region(pci_cisaddr, AIRONET4X00_CIS_SIZE) ||
 132//                      check_region(pci_memaddr, AIRONET4X00_MEM_SIZE)) {
 133//                              printk(KERN_ERR "aironet4X00 mem addrs not available for maping \n");
 134//                              continue;
 135//              }
 136                if (!request_region(pci_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"))
 137                        continue;
 138//              request_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");
 139//              request_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem");
 140
 141                mdelay(10);
 142
 143                pci_read_config_word(pdev, PCI_COMMAND, &pci_command);
 144                new_command = pci_command | PCI_COMMAND_SERR;
 145                if (pci_command != new_command)
 146                        pci_write_config_word(pdev, PCI_COMMAND, new_command);
 147
 148
 149/*              if (device == PCI_DEVICE_AIRONET_4800)
 150                        pci_write_config_dword(pdev, 0x40, 0x00000000);
 151
 152                udelay(1000);
 153*/
 154                if (device == PCI_DEVICE_AIRONET_4800)
 155                        pci_write_config_dword(pdev, 0x40, 0x40000000);
 156
 157                if (awc_pci_init(dev, pdev, pci_ioaddr,pci_cisaddr,pci_memaddr,pci_irq_line)){
 158                        printk(KERN_ERR "awc4800 pci init failed \n");
 159                        break;
 160                }
 161                dev = 0;
 162                cards_found++;
 163        }
 164
 165        return cards_found ? 0 : -ENODEV;
 166}
 167
 168
 169static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev,
 170                        int ioaddr, int cis_addr, int mem_addr, u8 pci_irq_line) {
 171
 172        int i, allocd_dev = 0;
 173
 174        if (!dev) {
 175                dev = init_etherdev(NULL, 0);   
 176                if (!dev)
 177                        return -ENOMEM;
 178                allocd_dev = 1;
 179        }
 180        dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL );
 181        if (!dev->priv) {
 182                if (allocd_dev) {
 183                        unregister_netdev(dev);
 184                        kfree(dev);
 185                }
 186                return -ENOMEM;
 187        }       
 188        memset(dev->priv,0,sizeof(struct awc_private));
 189        if (!dev->priv) {
 190                printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n");
 191                if (allocd_dev) {
 192                        unregister_netdev(dev);
 193                        kfree(dev);
 194                }
 195                return -ENOMEM;
 196        };
 197
 198//      ether_setup(dev);
 199
 200//      dev->tx_queue_len = tx_queue_len;
 201
 202        dev->hard_start_xmit =          &awc_start_xmit;
 203//      dev->set_config =               &awc_config_misiganes,aga mitte awc_config;
 204        dev->get_stats =                &awc_get_stats;
 205//      dev->set_multicast_list =       &awc_set_multicast_list;
 206        dev->change_mtu         =       awc_change_mtu;
 207        dev->init = &awc_init;
 208        dev->open = &awc_open;
 209        dev->stop = &awc_close;
 210        dev->base_addr = ioaddr;
 211        dev->irq = pci_irq_line;
 212        dev->tx_timeout = &awc_tx_timeout;
 213        dev->watchdog_timeo = AWC_TX_TIMEOUT;
 214        
 215
 216        i = request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, dev);
 217        if (i) {
 218                kfree(dev->priv);
 219                dev->priv = NULL;
 220                if (allocd_dev) {
 221                        unregister_netdev(dev);
 222                        kfree(dev);
 223                }
 224                return i;
 225        }
 226
 227        awc_private_init( dev);
 228        awc_init(dev);
 229
 230        i=0;
 231        while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
 232        if (!aironet4500_devices[i]){
 233                aironet4500_devices[i]=dev;
 234                ((struct awc_private *)
 235                aironet4500_devices[i]->priv)->card_type = AIRONET4500_PCI;
 236
 237                if (awc_proc_set_fun)
 238                        awc_proc_set_fun(i);
 239        }
 240
 241//      if (register_netdev(dev) != 0) {
 242//              printk(KERN_NOTICE "awc_cs: register_netdev() failed\n");
 243//              goto failed;
 244//      }
 245
 246        return 0; 
 247//  failed:
 248//      return -1;
 249
 250}
 251
 252#ifdef MODULE
 253static void awc_pci_release(void) {
 254
 255//      long flags;
 256        int i=0;
 257
 258        DEBUG(0, "awc_detach \n");
 259
 260        i=0;
 261        while ( i < MAX_AWCS) {
 262                if (!aironet4500_devices[i])
 263                        {i++; continue;};
 264                if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_PCI)
 265                                  {i++;      continue;}
 266
 267                if (awc_proc_unset_fun)
 268                        awc_proc_unset_fun(i);
 269                release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE);
 270//              release_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");
 271//              release_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem");
 272
 273                unregister_netdev(aironet4500_devices[i]);
 274                free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]);
 275                kfree(aironet4500_devices[i]->priv);
 276                kfree(aironet4500_devices[i]);
 277
 278                aironet4500_devices[i]=0;
 279
 280
 281                i++;
 282        }
 283        
 284
 285} 
 286
 287
 288#endif //MODULE
 289
 290
 291#endif /* CONFIG_AIRONET4500_PCI */
 292
 293#ifdef CONFIG_AIRONET4500_PNP
 294
 295#include <linux/isapnp.h>
 296#define AIRONET4X00_IO_SIZE     0x40
 297
 298#define isapnp_logdev pci_dev
 299#define isapnp_dev    pci_bus
 300#define isapnp_find_device isapnp_find_card
 301#define isapnp_find_logdev isapnp_find_dev
 302#define PNP_BUS bus
 303#define PNP_BUS_NUMBER number
 304#define PNP_DEV_NUMBER devfn
 305
 306
 307int awc4500_pnp_hw_reset(struct net_device *dev){
 308        struct isapnp_logdev *logdev;
 309
 310        DEBUG(0, "awc_pnp_reset \n");
 311
 312        if (!dev->priv ) {
 313                printk("awc4500 no dev->priv in hw_reset\n");
 314                return -1;
 315        };
 316
 317        logdev = ((struct isapnp_logdev *) ((struct awc_private *)dev->priv)->bus);
 318
 319        if (!logdev ) {
 320                printk("awc4500 no pnp logdev in hw_reset\n");
 321                return -1;
 322        };
 323
 324        if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0)
 325                printk("isapnp cfg failed at release \n");
 326        isapnp_deactivate(logdev->PNP_DEV_NUMBER);
 327        isapnp_cfg_end();
 328
 329        udelay(100);
 330
 331
 332        if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) {
 333                printk("%s cfg begin failed in hw_reset for csn %x devnum %x \n",
 334                                dev->name, logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER);
 335                return -EAGAIN;
 336        }
 337
 338        isapnp_activate(logdev->PNP_DEV_NUMBER);        /* activate device */
 339        isapnp_cfg_end();
 340
 341        return 0;
 342}
 343
 344int awc4500_pnp_probe(struct net_device *dev)
 345{
 346        int isa_index = 0;
 347        int isa_irq_line = 0;
 348        int isa_ioaddr = 0;
 349        int card = 0;
 350        int i=0;
 351        struct isapnp_dev * pnp_dev ;
 352        struct isapnp_logdev *logdev;
 353
 354        while (1) {
 355
 356                pnp_dev = isapnp_find_device(
 357                                                ISAPNP_VENDOR('A','W','L'), 
 358                                                ISAPNP_DEVICE(1),
 359                                                0);
 360        
 361                if (!pnp_dev) break;  
 362                
 363                isa_index++;
 364
 365                logdev = isapnp_find_logdev(pnp_dev, ISAPNP_VENDOR('A','W','L'),
 366                                    ISAPNP_FUNCTION(1),
 367                                    0);
 368                if (!logdev){
 369                        printk("No logical device found on Aironet board \n");
 370                        return -ENODEV;
 371                }
 372                if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) {
 373                        printk("cfg begin failed for csn %x devnum %x \n",
 374                                        logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER);
 375                        return -EAGAIN;
 376                }
 377                isapnp_activate(logdev->PNP_DEV_NUMBER);        /* activate device */
 378                isapnp_cfg_end();
 379
 380                isa_irq_line = logdev->irq;
 381                isa_ioaddr = logdev->resource[0].start;
 382                request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr");
 383
 384                if (!dev) {
 385                        dev = init_etherdev(NULL, 0);   
 386                        if (!dev) {
 387                                release_region(isa_ioaddr, AIRONET4X00_IO_SIZE);
 388                                isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER,
 389                                                 logdev->PNP_DEV_NUMBER);
 390                                isapnp_deactivate(logdev->PNP_DEV_NUMBER);
 391                                isapnp_cfg_end();
 392                                return -ENOMEM;
 393                        }
 394                }
 395                dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL );
 396                memset(dev->priv,0,sizeof(struct awc_private));
 397                if (!dev->priv) {
 398                        printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n");
 399                        return -1;
 400                };
 401                ((struct awc_private *)dev->priv)->bus =  logdev;
 402
 403        //      ether_setup(dev);
 404        
 405        //      dev->tx_queue_len = tx_queue_len;
 406        
 407                dev->hard_start_xmit =          &awc_start_xmit;
 408        //      dev->set_config =               &awc_config_misiganes,aga mitte awc_config;
 409                dev->get_stats =                &awc_get_stats;
 410        //      dev->set_multicast_list =       &awc_set_multicast_list;        
 411                dev->change_mtu         =       awc_change_mtu; 
 412                dev->init = &awc_init;
 413                dev->open = &awc_open;
 414                dev->stop = &awc_close;
 415                dev->base_addr = isa_ioaddr;
 416                dev->irq = isa_irq_line;
 417                dev->tx_timeout = &awc_tx_timeout;
 418                dev->watchdog_timeo = AWC_TX_TIMEOUT;
 419                
 420                netif_start_queue (dev);
 421                
 422                request_irq(dev->irq,awc_interrupt , SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev);
 423
 424                awc_private_init( dev);
 425
 426                ((struct awc_private *)dev->priv)->bus =  logdev;
 427
 428                cli();
 429                if ( awc_init(dev) ){
 430                        printk("card not found at irq %x io %lx\n",dev->irq, dev->base_addr);
 431                        if (card==0){
 432                                sti();
 433                                return -1;
 434                        }
 435                        sti();
 436                        break;
 437                }
 438                udelay(10);
 439                sti();
 440                i=0;
 441                while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
 442                if (!aironet4500_devices[i] && i < MAX_AWCS-1 ){
 443                        aironet4500_devices[i]=dev;
 444
 445                ((struct awc_private *)
 446                aironet4500_devices[i]->priv)->card_type = AIRONET4500_PNP;
 447
 448                        if (awc_proc_set_fun)
 449                                awc_proc_set_fun(i);    
 450                } else { 
 451                        printk(KERN_CRIT "Out of resources (MAX_AWCS) \n");
 452                        return -1;
 453                }
 454
 455                card++; 
 456        }
 457
 458        if (card == 0) return -ENODEV;
 459        return 0;
 460}
 461
 462#ifdef MODULE
 463static void awc_pnp_release(void) {
 464
 465//      long flags;
 466        int i=0;
 467        struct isapnp_logdev *logdev;
 468
 469        DEBUG(0, "awc_detach \n");
 470
 471        i=0;
 472        while ( i < MAX_AWCS) {
 473                if (!aironet4500_devices[i])
 474                                  {i++;      continue;}
 475                if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_PNP)
 476                                  {i++;      continue;}
 477
 478                logdev = ((struct isapnp_logdev *) ((struct awc_private *)aironet4500_devices[i]->priv)->bus);
 479
 480                if (!logdev ) 
 481                        printk("awc4500 no pnp logdev in pnp_release\n");
 482
 483                if (awc_proc_unset_fun)
 484                        awc_proc_unset_fun(i);
 485                if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0)
 486                        printk("isapnp cfg failed at release \n");
 487                isapnp_deactivate(logdev->PNP_DEV_NUMBER);
 488                isapnp_cfg_end();
 489
 490                release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE);
 491//              release_region(isa_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");
 492//              release_region(isa_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem");
 493
 494                unregister_netdev(aironet4500_devices[i]);
 495                free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]);
 496                kfree(aironet4500_devices[i]->priv);
 497                kfree(aironet4500_devices[i]);
 498
 499                aironet4500_devices[i]=0;
 500
 501
 502                i++;
 503        }
 504        
 505
 506} 
 507
 508static struct isapnp_device_id id_table[] = {
 509        {       ISAPNP_ANY_ID, ISAPNP_ANY_ID,
 510                ISAPNP_VENDOR('A','W','L'), ISAPNP_DEVICE(1), 0 },
 511        {0}
 512};
 513
 514MODULE_DEVICE_TABLE(isapnp, id_table);
 515
 516#endif //MODULE
 517#endif /* CONFIG_AIRONET4500_PNP */
 518
 519#ifdef  CONFIG_AIRONET4500_ISA 
 520
 521static int irq[] = {0,0,0,0,0};
 522static int io[] = {0,0,0,0,0};
 523
 524/* 
 525        EXPORT_SYMBOL(irq);
 526        EXPORT_SYMBOL(io);
 527*/
 528MODULE_PARM(irq,"i");
 529MODULE_PARM_DESC(irq,"Aironet 4x00 ISA non-PNP irqs,required");
 530MODULE_PARM(io,"i");
 531MODULE_PARM_DESC(io,"Aironet 4x00 ISA non-PNP ioports,required");
 532
 533
 534
 535int awc4500_isa_probe(struct net_device *dev)
 536{
 537//      int cards_found = 0;
 538//      static int isa_index;   /* Static, for multiple probe calls. */
 539        int isa_irq_line = 0;
 540        int isa_ioaddr = 0;
 541//      int p;
 542        int card = 0;
 543        int i=0;
 544
 545        if (! io[0] || ! irq[0]){
 546        
 547//              printk("       Both irq and io params must be supplied  for ISA mode !!!\n");
 548                return -ENODEV;
 549        }
 550
 551        printk(KERN_WARNING "     Aironet ISA Card in non-PNP(ISA) mode sometimes feels bad on interrupt \n");
 552        printk(KERN_WARNING "     Use aironet4500_pnp if any problems(i.e. card malfunctioning). \n");
 553        printk(KERN_WARNING "     Note that this isa probe is not friendly... must give exact parameters \n");
 554
 555        while (irq[card] != 0){
 556        
 557                isa_ioaddr = io[card];
 558                isa_irq_line = irq[card];
 559
 560                request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr");
 561
 562                if (!dev) {
 563                        dev = init_etherdev(NULL, 0);   
 564                        if (!dev) {
 565                                release_region(isa_ioaddr, AIRONET4X00_IO_SIZE);
 566                                return (card == 0) ? -ENOMEM : 0;
 567                        }
 568                }
 569                dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL );
 570                memset(dev->priv,0,sizeof(struct awc_private));
 571                if (!dev->priv) {
 572                        printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n");
 573                        return -1;
 574                };
 575
 576        //      ether_setup(dev);
 577        
 578        //      dev->tx_queue_len = tx_queue_len;
 579        
 580                dev->hard_start_xmit =          &awc_start_xmit;
 581        //      dev->set_config =               &awc_config_misiganes,aga mitte awc_config;
 582                dev->get_stats =                &awc_get_stats;
 583        //      dev->set_multicast_list =       &awc_set_multicast_list;        
 584                dev->change_mtu         =       awc_change_mtu; 
 585                dev->init = &awc_init;
 586                dev->open = &awc_open;
 587                dev->stop = &awc_close;
 588                dev->base_addr = isa_ioaddr;
 589                dev->irq = isa_irq_line;
 590                dev->tx_timeout = &awc_tx_timeout;
 591                dev->watchdog_timeo = AWC_TX_TIMEOUT;
 592                
 593                request_irq(dev->irq,awc_interrupt ,SA_INTERRUPT ,"Aironet 4X00",dev);
 594
 595                awc_private_init( dev);
 596                if ( awc_init(dev) ){
 597                        printk("card not found at irq %x mem %x\n",irq[card],io[card]);
 598                        if (card==0)
 599                                return -1;
 600                        break;
 601                }
 602
 603                i=0;
 604                while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
 605                if (!aironet4500_devices[i]){
 606                        aironet4500_devices[i]=dev;
 607                ((struct awc_private *)
 608                aironet4500_devices[i]->priv)->card_type = AIRONET4500_ISA;
 609
 610                        if (awc_proc_set_fun)
 611                                awc_proc_set_fun(i);    
 612                }
 613
 614                card++; 
 615        }
 616        if (card == 0 ) {
 617                return -ENODEV;
 618        };
 619        return 0;
 620}
 621
 622#ifdef MODULE
 623static void awc_isa_release(void) {
 624
 625//      long flags;
 626        int i=0;
 627
 628        DEBUG(0, "awc_detach \n");
 629
 630        i=0;
 631        while ( i < MAX_AWCS) {
 632        
 633                if (!aironet4500_devices[i])
 634                                  {i++;      continue;}
 635                if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_ISA)
 636                                  {i++;      continue;}
 637
 638                if (awc_proc_unset_fun)
 639                        awc_proc_unset_fun(i);
 640                release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE);
 641//              release_region(isa_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");
 642//              release_region(isa_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem");
 643
 644                unregister_netdev(aironet4500_devices[i]);
 645                free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]);
 646                kfree(aironet4500_devices[i]->priv);
 647                kfree(aironet4500_devices[i]);
 648
 649                aironet4500_devices[i]=0;
 650
 651
 652                i++;
 653        }
 654        
 655
 656} 
 657           
 658#endif //MODULE   
 659
 660#endif /* CONFIG_AIRONET4500_ISA */
 661
 662#ifdef  CONFIG_AIRONET4500_I365 
 663
 664#define port_range 0x40
 665
 666int awc_i365_offset_ports[] = {0x3e0,0x3e0,0x3e2,0x3e2};
 667int awc_i365_data_ports [] = {0x3e1,0x3e1,0x3e3,0x3e3};
 668int awc_i365_irq[]      = {5,5,11,12};
 669int awc_i365_io[]       = {0x140,0x100,0x400,0x440};
 670int awc_i365_sockets    = 0;
 671
 672struct i365_socket {
 673        int offset_port ;
 674        int data_port;
 675        int socket;
 676        int irq; 
 677        int io;
 678        int manufacturer;
 679        int product;
 680};
 681        
 682inline u8 i365_in (struct i365_socket * s, int offset) { 
 683        outb(offset  + (s->socket % 2)* 0x40, s->offset_port);
 684        return inb(s->data_port); 
 685};
 686
 687inline void i365_out (struct i365_socket * s, int offset,int data){
 688        outb(offset + (s->socket % 2)* 0x40 ,s->offset_port);
 689        outb((data & 0xff),s->data_port)        ;
 690        
 691};
 692
 693void awc_i365_card_release(struct i365_socket * s){
 694        
 695        i365_out(s, 0x5, 0);            // clearing ints
 696        i365_out(s, 0x6, 0x20);         // mem 16 bits
 697        i365_out(s, 0x7, 0);            // clear IO
 698        i365_out(s, 0x3, 0);            // gen ctrl reset + mem mode
 699        i365_out(s, 0x2, 0);            // reset power
 700        i365_out(s, 0x2, i365_in(s, 0x2) & 0x7f ); // cardenable off
 701        i365_out(s, 0x2, 0);            // remove power
 702        
 703
 704};
 705int awc_i365_probe_once(struct i365_socket * s ){
 706
 707
 708        int caps=i365_in(s, 0);
 709        int ret;
 710        unsigned long jiff;
 711//      short rev       = 0x3000;
 712        unsigned char cis [0x3e3];
 713        unsigned char * mem = phys_to_virt(0xd000);
 714        int i;
 715        int port ;
 716        
 717        DEBUG(1," i365 control ID %x \n", caps);
 718
 719        if (caps & 0xC){
 720                return 1;
 721        };
 722        
 723        ret = i365_in(s, 0x1);
 724
 725        if ((ret & 0xC0) != 0xC0){
 726                printk("card in socket %d port %x not in known state, %x \n",
 727                        s->socket, s->offset_port, ret );
 728                return -1;
 729        };
 730
 731        
 732        awc_i365_card_release(s);
 733
 734
 735        mdelay(100);
 736        
 737        i365_out(s, 0x2, 0x10 );        // power enable
 738        mdelay(200);
 739        
 740        i365_out(s, 0x2, 0x10 | 0x01 | 0x04 | 0x80);    //power enable
 741        
 742        mdelay(250);
 743        
 744        if (!s->irq)
 745                s->irq = 11;
 746        
 747        i365_out(s, 0x3, 0x40 | 0x20 | s->irq);
 748        
 749        jiff = jiffies;
 750        
 751        while (jiffies-jiff < HZ ) 
 752                if (i365_in(s,0x1) & 0x20)
 753                        break;
 754                        
 755        if (! (i365_in(s,0x1) & 0x20) ){
 756                printk("irq enable timeout on socket %x \n", s->socket);
 757                return -1;
 758        };
 759        
 760        i365_out(s,0x10,0xd0);
 761        i365_out(s,0x11,0x0);
 762        i365_out(s,0x12,0xd0);
 763        i365_out(s,0x13,0x0);
 764        i365_out(s,0x14,0x30 );
 765        i365_out(s,0x15,0x3f | 0x40);           // enab mem reg bit
 766        i365_out(s,0x06,0x01);                  // enab mem 
 767        
 768        mdelay(10);
 769        
 770        cis[0] = 0x45;
 771        
 772//      memcpy_toio( 0xd3e0, &(cis[0]),0x1);
 773
 774//      mem[0x3e0] = 0x0;
 775//      mem[0] = 0x45;
 776
 777        mem[0x3e0] = 0x45;
 778
 779        mdelay(10);
 780        
 781        memcpy_fromio(cis,0xD000, 0x3e0);
 782        
 783        for (i = 0; i <= 0x3e2; i++)
 784                printk("%02x", mem[i]);
 785        for (i = 0; i <= 0x3e2; i++)
 786                printk("%c", mem[i]);
 787
 788        i=0;    
 789        while (i < 0x3e0){
 790                if (cis[i] == 0xff)
 791                        break;
 792                if (cis[i] != 0x20 ){
 793                        i = i + 2 + cis[i+1];
 794                        continue;
 795                }else {
 796                        s->manufacturer = cis[i+2] | (cis[i+3]<<8);
 797                        s->product      = cis[i+4] | (cis[i+5]<<8);
 798                        break;
 799                };
 800                i++;
 801        };
 802        
 803        DEBUG(1,"socket %x manufacturer %x product %x \n",
 804                s->socket, s->manufacturer,s->product);
 805
 806        i365_out(s,0x07, 0x1 | 0x2);            // enable io 16bit
 807        mdelay(1);
 808        port = s->io;
 809        i365_out(s,0x08, port & 0xff);
 810        i365_out(s,0x09, (port & 0xff00)/ 0x100);
 811        i365_out(s,0x0A, (port+port_range) & 0xff);
 812        i365_out(s,0x0B, ((port+port_range) & 0xff00) /0x100);  
 813
 814        i365_out(s,0x06, 0x40);                 // enable io window
 815
 816        mdelay(1);
 817
 818        i365_out(s,0x3e0,0x45);
 819        
 820        outw(0x10, s->io);
 821
 822        jiff = jiffies;
 823        while (!(inw(s->io + 0x30) & 0x10)){
 824        
 825                if (jiffies - jiff > HZ ){
 826                
 827                        printk("timed out waitin for command ack \n");
 828                        break;
 829                }
 830        };
 831
 832        
 833        outw(0x10, s->io + 0x34);
 834        mdelay(10);
 835        
 836        return 0;
 837
 838};
 839
 840
 841static int awc_i365_init(struct i365_socket * s) {
 842
 843        struct net_device * dev;
 844        int i;
 845
 846
 847        dev = init_etherdev(0, sizeof(struct awc_private) );
 848
 849//      dev->tx_queue_len = tx_queue_len;
 850        ether_setup(dev);
 851
 852        dev->hard_start_xmit =          &awc_start_xmit;
 853//      dev->set_config =               &awc_config_misiganes,aga mitte awc_config;
 854        dev->get_stats =                &awc_get_stats;
 855        dev->set_multicast_list =       &awc_set_multicast_list;
 856
 857        dev->init = &awc_init;
 858        dev->open = &awc_open;
 859        dev->stop = &awc_close;
 860        dev->irq = s->irq;
 861        dev->base_addr = s->io;
 862        dev->tx_timeout = &awc_tx_timeout;
 863        dev->watchdog_timeo = AWC_TX_TIMEOUT;
 864
 865
 866        awc_private_init( dev);
 867
 868        i=0;
 869        while (aironet4500_devices[i] && i < MAX_AWCS-1) i++;
 870        if (!aironet4500_devices[i]){
 871                aironet4500_devices[i]=dev;
 872
 873                ((struct awc_private *)
 874                aironet4500_devices[i]->priv)->card_type = AIRONET4500_365;
 875
 876                if (awc_proc_set_fun)
 877                        awc_proc_set_fun(i);
 878        }
 879
 880        if (register_netdev(dev) != 0) {
 881                printk(KERN_NOTICE "awc_cs: register_netdev() failed\n");
 882                goto failed;
 883        }
 884
 885        return 0;
 886 
 887  failed:
 888        return -1;
 889}
 890
 891
 892static void awc_i365_release(void) {
 893
 894//      long flags;
 895        int i=0;
 896
 897        DEBUG(0, "awc_detach \n");
 898
 899        i=0;
 900        while ( i < MAX_AWCS) {
 901        
 902                if (!aironet4500_devices[i])
 903                         {i++; continue;}
 904
 905                if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_365)
 906                                  {i++;      continue;}
 907
 908                if (awc_proc_unset_fun)
 909                        awc_proc_unset_fun(i);
 910
 911                unregister_netdev(aironet4500_devices[i]);
 912
 913                //kfree(aironet4500_devices[i]->priv);
 914                kfree(aironet4500_devices[i]);
 915
 916                aironet4500_devices[i]=0;
 917
 918
 919                i++;
 920        }
 921        
 922
 923} 
 924
 925
 926
 927
 928
 929        
 930        
 931int awc_i365_probe(void) {
 932
 933        int i = 1;
 934        int k = 0;
 935        int ret = 0;
 936        int found=0;
 937        
 938        struct i365_socket s;
 939        /* Always emit the version, before any failure. */
 940
 941        if (!awc_i365_sockets) {
 942                printk("        awc i82635 4x00: use bitfiel opts awc_i365_sockets=0x3 <- (1|2) to probe sockets 0 and 1\n");
 943                return -1;
 944        };
 945
 946        while (k < 4){
 947                if (i & awc_i365_sockets){
 948
 949                        s.offset_port   = awc_i365_offset_ports[k];
 950                        s.data_port     = awc_i365_data_ports[k];
 951                        s.socket        = k;
 952                        s.manufacturer  = 0;
 953                        s.product       = 0;
 954                        s.irq           = awc_i365_irq[k];
 955                        s.io            = awc_i365_io[k];
 956                        
 957                        ret = awc_i365_probe_once(&s);
 958                        if (!ret){
 959                                if (awc_i365_init(&s))
 960                                        goto failed;
 961                                else found++;
 962                        } else if (ret == -1)
 963                                goto failed;
 964                };
 965                k++;
 966                i *=2;
 967        };
 968
 969        if (!found){
 970                printk("no aironet 4x00 cards found\n");
 971                return -1;
 972        }
 973        return 0;
 974
 975failed: 
 976        awc_i365_release();
 977        return -1;
 978        
 979
 980}
 981
 982#endif /* CONFIG_AIRONET4500_I365 */
 983
 984#ifdef MODULE        
 985int init_module(void)
 986{
 987        int found = 0;
 988
 989        printk("%s\n ", awc_version);
 990                
 991#ifdef CONFIG_AIRONET4500_PCI
 992        if (awc4500_pci_probe(NULL) == -ENODEV){
 993//              printk("PCI 4X00 aironet cards not found\n");
 994        } else {
 995                found++;
 996//              printk("PCI 4X00 found some cards \n");
 997        }
 998#endif
 999#ifdef CONFIG_AIRONET4500_PNP
1000        if (awc4500_pnp_probe(NULL) == -ENODEV){
1001//              printk("PNP 4X00 aironet cards not found\n");
1002        } else {
1003                found++;
1004//              printk("PNP 4X00 found some cards \n");
1005        }
1006#endif
1007#ifdef CONFIG_AIRONET4500_365
1008        if ( awc_i365_probe() == -1) {
1009//              printk("PCMCIA 4X00 aironet cards not found for i365(without card services) initialization\n");
1010        } else {
1011                 found++ ;
1012//               printk("PCMCIA 4X00 found some cards, take care, this code is not supposed to work yet \n");
1013        }
1014#endif
1015#ifdef CONFIG_AIRONET4500_ISA
1016        if (awc4500_isa_probe(NULL) == -ENODEV){
1017//              printk("ISA 4X00 aironet ISA-bus non-PNP-mode cards not found\n");
1018        } else {
1019                found++;
1020//              printk("ISA 4X00 found some cards \n");
1021        }
1022#endif
1023        if (!found) {
1024                printk(KERN_ERR "No Aironet 4X00 cards were found. Note that for ISA \n cards you should use either automatic PNP mode or \n ISA mode with both io and irq param \n Aironet is also afraid of: being second PNP controller(by slot), having anything(brandname bios weirdnesses) in range 0x100-0x180 and maybe around  0xd0000\n If you PNP type card does not get found, try non-PNP switch before complainig. \n");
1025                return -1;
1026        }
1027        return 0;
1028        
1029
1030}
1031
1032void cleanup_module(void)
1033{
1034        DEBUG(0, "awc_cs: unloading %c ",'\n');
1035#ifdef CONFIG_AIRONET4500_PCI   
1036        awc_pci_release();
1037#endif
1038#ifdef CONFIG_AIRONET4500_PNP
1039        awc_pnp_release();
1040#endif
1041#ifdef CONFIG_AIRONET4500_365
1042        awc_i365_release();
1043#endif
1044#ifdef CONFIG_AIRONET4500_ISA
1045        awc_isa_release();
1046#endif
1047
1048}
1049#endif
1050
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.