diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-02-04 07:40:19 +0000 |
commit | 33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch) | |
tree | 2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /drivers/net/aironet4500_card.c | |
parent | 216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff) |
Merge with Linux 2.3.32.
Diffstat (limited to 'drivers/net/aironet4500_card.c')
-rw-r--r-- | drivers/net/aironet4500_card.c | 1118 |
1 files changed, 1118 insertions, 0 deletions
diff --git a/drivers/net/aironet4500_card.c b/drivers/net/aironet4500_card.c new file mode 100644 index 000000000..1725f4aec --- /dev/null +++ b/drivers/net/aironet4500_card.c @@ -0,0 +1,1118 @@ +/* + * Aironet 4500 PCI-ISA-i365 driver + * + * Elmer Joandi, Januar 1999 + * Copyright Elmer Joandi, all rights restricted + * + * + * Revision 0.1 ,started 30.12.1998 + * + * + */ +#ifdef MODULE +static const char *awc_version = +"aironet4500_cards.c v0.1 28/03/99 Elmer Joandi, elmer@ylenurme.ee.\n"; +#endif + +#include <linux/version.h> +#include <linux/config.h> +#include <linux/module.h> + +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/ptrace.h> +#include <linux/malloc.h> +#include <linux/string.h> +#include <linux/timer.h> +#include <linux/interrupt.h> +#include <linux/in.h> +#include <asm/io.h> +#include <asm/system.h> +#include <asm/bitops.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/skbuff.h> +#include <linux/if_arp.h> +#include <linux/ioport.h> + +#if LINUX_VERSION_CODE < 0x20100 +#include <linux/bios32.h> +#endif + +#include "aironet4500.h" + +#define PCI_VENDOR_ID_AIRONET 0x14b9 +#define PCI_DEVICE_AIRONET_4800_1 0x1 +#define PCI_DEVICE_AIRONET_4800 0x4500 +#define PCI_DEVICE_AIRONET_4500 0x4800 +#define AIRONET4X00_IO_SIZE 0x40 +#define AIRONET4X00_CIS_SIZE 0x300 +#define AIRONET4X00_MEM_SIZE 0x300 + +#define AIRONET4500_PCI 1 +#define AIRONET4500_PNP 2 +#define AIRONET4500_ISA 3 +#define AIRONET4500_365 4 + + +#ifdef CONFIG_AIRONET4500_PCI + +#include <linux/pci.h> + + +static int reverse_probe =0 ; + + +static int awc_pci_init(struct NET_DEVICE * dev, int pci_bus, int device_nr, + int ioaddr, int cis_addr, int mem_addr,u8 pci_irq_line) ; + + +int awc4500_pci_probe(struct NET_DEVICE *dev) +{ + int cards_found = 0; + static int pci_index = 0; /* Static, for multiple probe calls. */ + u8 pci_irq_line = 0; +// int p; + + unsigned char awc_pci_dev, awc_pci_bus; + + if (!pcibios_present()) + return -1; + + for (;pci_index < 0xff; pci_index++) { + u16 vendor, device, pci_command, new_command; + u32 pci_memaddr; + u32 pci_ioaddr; + u32 pci_cisaddr; +#if LINUX_VERSION_CODE < 0x20100 + u16 pci_caps =0; + u8 pci_caps_ptr =0; +#endif + if (pcibios_find_class (PCI_CLASS_NETWORK_OTHER << 8, + reverse_probe ? 0xfe - pci_index : pci_index, + &awc_pci_bus, &awc_pci_dev) != PCIBIOS_SUCCESSFUL){ + if (reverse_probe){ + continue; + } else { + break; + } + } + pcibios_read_config_word(awc_pci_bus, awc_pci_dev, + PCI_VENDOR_ID, &vendor); + pcibios_read_config_word(awc_pci_bus, awc_pci_dev, + PCI_DEVICE_ID, &device); +#if LINUX_VERSION_CODE >= 0x20300 + pci_irq_line = pci_find_slot(awc_pci_bus, awc_pci_dev)->irq; + pci_memaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->resource[0].start; + pci_cisaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->resource[1].start; + pci_ioaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->resource[2].start; +#else +#if LINUX_VERSION_CODE >= 0x20155 + pci_irq_line = pci_find_slot(awc_pci_bus, awc_pci_dev)->irq; + pci_memaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->base_address[0]; + pci_cisaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->base_address[1]; + pci_ioaddr = pci_find_slot(awc_pci_bus, awc_pci_dev)->base_address[2]; +#else + pcibios_read_config_dword(awc_pci_bus, awc_pci_dev,PCI_BASE_ADDRESS_0, &pci_memaddr); + pcibios_read_config_dword(awc_pci_bus, awc_pci_dev,PCI_BASE_ADDRESS_1, &pci_cisaddr); + pcibios_read_config_dword(awc_pci_bus, awc_pci_dev,PCI_BASE_ADDRESS_2, &pci_ioaddr); + pcibios_read_config_byte(awc_pci_bus, awc_pci_dev, PCI_INTERRUPT_LINE, &pci_irq_line); + pcibios_read_config_word(awc_pci_bus, awc_pci_dev,PCI_STATUS, &pci_caps); + pcibios_read_config_byte(awc_pci_bus, awc_pci_dev, 0x34, &pci_caps_ptr); + +#endif // 2.2 +#endif // 2.3 +// printk("\n pci capabilities %x and ptr %x \n",pci_caps,pci_caps_ptr); + /* Remove I/O space marker in bit 0. */ + + if (vendor != PCI_VENDOR_ID_AIRONET) + continue; + if (device != PCI_DEVICE_AIRONET_4800_1 && + device != PCI_DEVICE_AIRONET_4800 && + device != PCI_DEVICE_AIRONET_4500 ) + continue; +#if LINUX_VERSION_CODE < 0x20300 + + if (!(pci_ioaddr & 1)){ + printk("awc4X00 ioaddr location mismatch \n"); + return -1; + }; + + pci_ioaddr &= ~3; + pci_cisaddr &= ~0xf; + pci_memaddr &= ~0xf; +#endif +// if (check_region(pci_ioaddr, AIRONET4X00_IO_SIZE) || +// check_region(pci_cisaddr, AIRONET4X00_CIS_SIZE) || +// check_region(pci_memaddr, AIRONET4X00_MEM_SIZE)) { +// printk(KERN_ERR "aironet4X00 mem addrs not available for maping \n"); +// continue; +// } + request_region(pci_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"); +// request_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis"); +// request_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); + +// pcibios_write_config_word(awc_pci_bus, awc_pci_dev, +// PCI_COMMAND, 0); + udelay(10000); + + pcibios_read_config_word(awc_pci_bus, awc_pci_dev, + PCI_COMMAND, &pci_command); + new_command = pci_command |0x100 | PCI_COMMAND_MEMORY|PCI_COMMAND_IO; + if (pci_command != new_command) { + printk(KERN_INFO " The PCI BIOS has not enabled this" + " device! Updating PCI command %4.4x->%4.4x.\n", + pci_command, new_command); + pcibios_write_config_word(awc_pci_bus, awc_pci_dev, + PCI_COMMAND, new_command); + } + + +/* if (device == PCI_DEVICE_AIRONET_4800) + pcibios_write_config_dword(awc_pci_bus, awc_pci_dev, + 0x40, 0x00000000); + + udelay(1000); +*/ + if (device == PCI_DEVICE_AIRONET_4800) + pcibios_write_config_dword(awc_pci_bus, awc_pci_dev, + 0x40, 0x40000000); + + if (awc_pci_init(dev, awc_pci_bus, awc_pci_dev, pci_ioaddr,pci_cisaddr,pci_memaddr,pci_irq_line)){ + printk(KERN_ERR "awc4800 pci init failed \n"); + break; + } + dev = 0; + cards_found++; + } + + return cards_found ? 0 : -ENODEV; +} + + +static int awc_pci_init(struct NET_DEVICE * dev, int pci_bus, int device_nr, + int ioaddr, int cis_addr, int mem_addr, u8 pci_irq_line) { + + int i; + + if (!dev) { + dev = init_etherdev(dev, 0 ); + } + dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); + memset(dev->priv,0,sizeof(struct awc_private)); + if (!dev->priv) { + printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); + return -1; + }; + +// ether_setup(dev); + +// dev->tx_queue_len = tx_queue_len; + + dev->hard_start_xmit = &awc_start_xmit; +// dev->set_config = &awc_config_misiganes,aga mitte awc_config; + dev->get_stats = &awc_get_stats; +// dev->set_multicast_list = &awc_set_multicast_list; + dev->change_mtu = awc_change_mtu; + dev->init = &awc_init; + dev->open = &awc_open; + dev->stop = &awc_close; + dev->tbusy = 1; + dev->start = 0; + + dev->base_addr = ioaddr; + + + dev->irq = pci_irq_line; +#if LINUX_VERSION_CODE > 0x20100 + request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); +#else + request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); +#endif + awc_private_init( dev); + awc_init(dev); + + i=0; + while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; + if (!aironet4500_devices[i]){ + aironet4500_devices[i]=dev; + ((struct awc_private *) + aironet4500_devices[i]->priv)->card_type = AIRONET4500_PCI; + + if (awc_proc_set_fun) + awc_proc_set_fun(i); + } + + dev->tbusy = 1; + dev->start = 0; + + +// if (register_netdev(dev) != 0) { +// printk(KERN_NOTICE "awc_cs: register_netdev() failed\n"); +// goto failed; +// } + + + + return 0; +// failed: +// return -1; + +} + +#ifdef MODULE +static void awc_pci_release(void) { + +// long flags; + int i=0; + + DEBUG(0, "awc_detach \n"); + + i=0; + while ( i < MAX_AWCS) { + if (!aironet4500_devices[i]) + {i++; continue;}; + if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_PCI) + {i++; continue;} + + if (awc_proc_unset_fun) + awc_proc_unset_fun(i); + release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE); +// release_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis"); +// release_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); + + unregister_netdev(aironet4500_devices[i]); + free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]); + kfree_s(aironet4500_devices[i]->priv, sizeof(struct awc_private)); + kfree_s(aironet4500_devices[i], sizeof(struct NET_DEVICE)); + + aironet4500_devices[i]=0; + + + i++; + } + + +} + + +#endif //MODULE + + +#endif /* CONFIG_AIRONET4500_PCI */ + +#ifdef CONFIG_AIRONET4500_PNP + +#if LINUX_VERSION_CODE > 0x20300 +#include <linux/isapnp.h> +#else +#include "isapnp.h" +#endif +#define AIRONET4X00_IO_SIZE 0x40 + +#if LINUX_VERSION_CODE > 0x20300 +#define isapnp_logdev pci_dev +#define isapnp_dev pci_bus +#define isapnp_find_device isapnp_find_card +#define isapnp_find_logdev isapnp_find_dev +#define PNP_BUS bus +#define PNP_BUS_NUMBER number +#define PNP_DEV_NUMBER devfn +#else +#define PNP_BUS dev +#define PNP_BUS_NUMBER csn +#define PNP_DEV_NUMBER number +#endif + +int awc4500_pnp_hw_reset(struct NET_DEVICE *dev){ + struct isapnp_logdev *logdev; +#if LINUX_VERSION_CODE < 0x20300 + struct isapnp_config cfg; +#endif + DEBUG(0, "awc_pnp_reset \n"); + + if (!dev->priv ) { + printk("awc4500 no dev->priv in hw_reset\n"); + return -1; + }; + + logdev = ((struct isapnp_logdev *) ((struct awc_private *)dev->priv)->bus); + + if (!logdev ) { + printk("awc4500 no pnp logdev in hw_reset\n"); + return -1; + }; + + if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0) + printk("isapnp cfg failed at release \n"); + isapnp_deactivate(logdev->PNP_DEV_NUMBER); + isapnp_cfg_end(); + + udelay(100); + + + if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) { + printk("%s cfg begin failed in hw_reset for csn %x devnum %x \n", + dev->name, logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER); + return -EAGAIN; + } +#if LINUX_VERSION_CODE < 0x20300 + if (isapnp_config_init(&cfg, logdev)<0) { + printk("cfg init failed \n"); + isapnp_cfg_end(); + return -EAGAIN; + } + cfg.port[0] = dev->base_addr; + cfg.irq[0] = dev->irq; + + if (isapnp_configure(&cfg)<0) { + printk("%s hw_reset, isapnp configure failed (out of resources?)\n",dev->name); + isapnp_cfg_end(); + return -ENOMEM; + } +#else + +#endif + isapnp_activate(logdev->PNP_DEV_NUMBER); /* activate device */ + isapnp_cfg_end(); + + return 0; +} + +int awc4500_pnp_probe(struct NET_DEVICE *dev) +{ + int isa_index = 0; + int isa_irq_line = 0; + int isa_ioaddr = 0; + int card = 0; + int i=0; + struct isapnp_dev * pnp_dev ; + struct isapnp_logdev *logdev; +#if LINUX_VERSION_CODE < 0x20300 + struct isapnp_config cfg; +#endif + + while (1) { + + pnp_dev = isapnp_find_device( + ISAPNP_VENDOR('A','W','L'), + ISAPNP_DEVICE(1), +#if LINUX_VERSION_CODE < 0x20300 + isa_index +#else + 0 +#endif + ); + + if (!pnp_dev) break; + + isa_index++; + + logdev = isapnp_find_logdev(pnp_dev, ISAPNP_VENDOR('A','W','L'), + ISAPNP_FUNCTION(1), + 0); + if (!logdev){ + printk("No logical device found on Aironet board \n"); + return -ENODEV; + } + if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER) < 0) { + printk("cfg begin failed for csn %x devnum %x \n", + logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER); + return -EAGAIN; + } +#if LINUX_VERSION_CODE < 0x20300 + if (isapnp_config_init(&cfg, logdev)<0) { + printk("cfg init failed \n"); + isapnp_cfg_end(); + return -EAGAIN; + } + if (isapnp_configure(&cfg)<0) { + printk("isapnp configure failed (out of resources?)\n"); + isapnp_cfg_end(); + return -ENOMEM; + } +#endif + isapnp_activate(logdev->PNP_DEV_NUMBER); /* activate device */ + isapnp_cfg_end(); + +#if LINUX_VERSION_CODE < 0x20300 + isa_ioaddr = cfg.port[0]; + isa_irq_line = cfg.irq[0]; +#else + isa_irq_line = logdev->irq; + isa_ioaddr = logdev->resource[0].start; +#endif + request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"); + + if (!dev) { + dev = init_etherdev(dev, 0 ); + } + dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); + memset(dev->priv,0,sizeof(struct awc_private)); + if (!dev->priv) { + printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); + return -1; + }; + ((struct awc_private *)dev->priv)->bus = logdev; + + // ether_setup(dev); + + // dev->tx_queue_len = tx_queue_len; + + dev->hard_start_xmit = &awc_start_xmit; + // dev->set_config = &awc_config_misiganes,aga mitte awc_config; + dev->get_stats = &awc_get_stats; + // dev->set_multicast_list = &awc_set_multicast_list; + dev->change_mtu = awc_change_mtu; + dev->init = &awc_init; + dev->open = &awc_open; + dev->stop = &awc_close; + dev->tbusy = 1; + dev->start = 0; + + dev->base_addr = isa_ioaddr; + + + dev->irq = isa_irq_line; +#if LINUX_VERSION_CODE > 0x20100 + request_irq(dev->irq,awc_interrupt , SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); +#else + request_irq(dev->irq,awc_interrupt, SA_SHIRQ ,"Aironet 4X00",dev); +#endif + + awc_private_init( dev); + + ((struct awc_private *)dev->priv)->bus = logdev; + + cli(); + if ( awc_init(dev) ){ + printk("card not found at irq %x io %lx\n",dev->irq, dev->base_addr); + if (card==0){ + sti(); + return -1; + } + sti(); + break; + } + udelay(10); + sti(); + i=0; + while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; + if (!aironet4500_devices[i] && i < MAX_AWCS-1 ){ + aironet4500_devices[i]=dev; + + ((struct awc_private *) + aironet4500_devices[i]->priv)->card_type = AIRONET4500_PNP; + + if (awc_proc_set_fun) + awc_proc_set_fun(i); + } else { + printk(KERN_CRIT "Out of resources (MAX_AWCS) \n"); + return -1; + } + + dev->tbusy = 1; + dev->start = 0; + + card++; + } + + if (card == 0) return -ENODEV; + return 0; +} + +#ifdef MODULE +static void awc_pnp_release(void) { + +// long flags; + int i=0; + struct isapnp_logdev *logdev; + + DEBUG(0, "awc_detach \n"); + + i=0; + while ( i < MAX_AWCS) { + if (!aironet4500_devices[i]) + {i++; continue;} + if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_PNP) + {i++; continue;} + + logdev = ((struct isapnp_logdev *) ((struct awc_private *)aironet4500_devices[i]->priv)->bus); + + if (!logdev ) + printk("awc4500 no pnp logdev in pnp_release\n"); + + if (awc_proc_unset_fun) + awc_proc_unset_fun(i); + if (isapnp_cfg_begin(logdev->PNP_BUS->PNP_BUS_NUMBER, logdev->PNP_DEV_NUMBER)<0) + printk("isapnp cfg failed at release \n"); + isapnp_deactivate(logdev->PNP_DEV_NUMBER); + isapnp_cfg_end(); + + release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE); +// release_region(isa_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis"); +// release_region(isa_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); + + unregister_netdev(aironet4500_devices[i]); + free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]); + kfree_s(aironet4500_devices[i]->priv, sizeof(struct awc_private)); + kfree_s(aironet4500_devices[i], sizeof(struct NET_DEVICE)); + + aironet4500_devices[i]=0; + + + i++; + } + + +} + +#endif //MODULE +#endif /* CONFIG_AIRONET4500_PNP */ + +#ifdef CONFIG_AIRONET4500_ISA + +static int irq[] = {0,0,0,0,0}; +static int io[] = {0,0,0,0,0}; + +/* + EXPORT_SYMBOL(irq); + EXPORT_SYMBOL(io); +*/ +#if LINUX_VERSION_CODE >= 0x20100 +MODULE_PARM(irq,"i"); +MODULE_PARM_DESC(irq,"Aironet 4x00 ISA non-PNP irqs,required"); +MODULE_PARM(io,"i"); +MODULE_PARM_DESC(io,"Aironet 4x00 ISA non-PNP ioports,required"); +#endif + + + +int awc4500_isa_probe(struct NET_DEVICE *dev) +{ +// int cards_found = 0; +// static int isa_index = 0; /* Static, for multiple probe calls. */ + int isa_irq_line = 0; + int isa_ioaddr = 0; +// int p; + int card = 0; + int i=0; + + if (! io[0] || ! irq[0]){ + + printk(" Both irq and io params must be supplied for ISA mode !!!\n"); + return -ENODEV; + } + + printk(KERN_WARNING " Aironet ISA Card in non-PNP(ISA) mode sometimes feels bad on interrupt \n"); + printk(KERN_WARNING " Use aironet4500_pnp if any problems(i.e. card malfunctioning). \n"); + printk(KERN_WARNING " Note that this isa probe is not friendly... must give exact parameters \n"); + + while (irq[card] !=0){ + + isa_ioaddr = io[card]; + isa_irq_line = irq[card]; + + request_region(isa_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr"); + + if (!dev) { + dev = init_etherdev(dev, 0 ); + } + dev->priv = kmalloc(sizeof(struct awc_private),GFP_KERNEL ); + memset(dev->priv,0,sizeof(struct awc_private)); + if (!dev->priv) { + printk(KERN_CRIT "aironet4x00: could not allocate device private, some unstability may follow\n"); + return -1; + }; + + // ether_setup(dev); + + // dev->tx_queue_len = tx_queue_len; + + dev->hard_start_xmit = &awc_start_xmit; + // dev->set_config = &awc_config_misiganes,aga mitte awc_config; + dev->get_stats = &awc_get_stats; + // dev->set_multicast_list = &awc_set_multicast_list; + dev->change_mtu = awc_change_mtu; + dev->init = &awc_init; + dev->open = &awc_open; + dev->stop = &awc_close; + dev->tbusy = 1; + dev->start = 0; + + dev->base_addr = isa_ioaddr; + + + dev->irq = isa_irq_line; + +#if LINUX_VERSION_CODE > 0x20100 + request_irq(dev->irq,awc_interrupt ,SA_INTERRUPT ,"Aironet 4X00",dev); +#else + request_irq(dev->irq,awc_interrupt ,0 ,"Aironet 4X00",dev); +#endif + + awc_private_init( dev); + if ( awc_init(dev) ){ + printk("card not found at irq %x mem %x\n",irq[card],io[card]); + if (card==0) + return -1; + break; + } + + i=0; + while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; + if (!aironet4500_devices[i]){ + aironet4500_devices[i]=dev; + ((struct awc_private *) + aironet4500_devices[i]->priv)->card_type = AIRONET4500_ISA; + + if (awc_proc_set_fun) + awc_proc_set_fun(i); + } + + dev->tbusy = 1; + dev->start = 0; + + card++; + } + if (card == 0 ) { + return -ENODEV; + }; + return 0; +} + +#ifdef MODULE +static void awc_isa_release(void) { + +// long flags; + int i=0; + + DEBUG(0, "awc_detach \n"); + + i=0; + while ( i < MAX_AWCS) { + + if (!aironet4500_devices[i]) + {i++; continue;} + if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_ISA) + {i++; continue;} + + if (awc_proc_unset_fun) + awc_proc_unset_fun(i); + release_region(aironet4500_devices[i]->base_addr, AIRONET4X00_IO_SIZE); +// release_region(isa_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis"); +// release_region(isa_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem"); + + unregister_netdev(aironet4500_devices[i]); + free_irq(aironet4500_devices[i]->irq,aironet4500_devices[i]); + kfree_s(aironet4500_devices[i]->priv, sizeof(struct awc_private)); + kfree_s(aironet4500_devices[i], sizeof(struct NET_DEVICE)); + + aironet4500_devices[i]=0; + + + i++; + } + + +} + +#endif //MODULE + +#endif /* CONFIG_AIRONET4500_ISA */ + +#ifdef CONFIG_AIRONET4500_365 + +#define port_range 0x40 + +int awc_i365_offset_ports[] = {0x3e0,0x3e0,0x3e2,0x3e2}; +int awc_i365_data_ports [] = {0x3e1,0x3e1,0x3e3,0x3e3}; +int awc_i365_irq[] = {5,5,11,12}; +int awc_i365_io[] = {0x140,0x100,0x400,0x440}; +int awc_i365_sockets = 0; + +struct i365_socket { + int offset_port ; + int data_port; + int socket; + int irq; + int io; + int manufacturer; + int product; +}; + +inline u8 i365_in (struct i365_socket * s, int offset) { + outb(offset + (s->socket % 2)* 0x40, s->offset_port); + return inb(s->data_port); +}; + +inline void i365_out (struct i365_socket * s, int offset,int data){ + outb(offset + (s->socket % 2)* 0x40 ,s->offset_port); + outb((data & 0xff),s->data_port) ; + +}; + +void awc_i365_card_release(struct i365_socket * s){ + + i365_out(s, 0x5, 0); // clearing ints + i365_out(s, 0x6, 0x20); // mem 16 bits + i365_out(s, 0x7, 0); // clear IO + i365_out(s, 0x3, 0); // gen ctrl reset + mem mode + i365_out(s, 0x2, 0); // reset power + i365_out(s, 0x2, i365_in(s, 0x2) & 0x7f ); // cardenable off + i365_out(s, 0x2, 0); // remove power + + +}; +int awc_i365_probe_once(struct i365_socket * s ){ + + + int caps=i365_in(s, 0); + int ret; + unsigned long jiff; +// short rev = 0x3000; + unsigned char cis [0x3e3]; + unsigned char * mem = phys_to_virt(0xd000); + int i; + int port ; + + DEBUG(1," i365 control ID %x \n", caps); + + if (caps & 0xC){ + return 1; + }; + + ret = i365_in(s, 0x1); + + if ((ret & 0xC0) != 0xC0){ + printk("card in socket %d port %x not in known state, %x \n", + s->socket, s->offset_port, ret ); + return -1; + }; + + + awc_i365_card_release(s); + + + udelay(100000); + + i365_out(s, 0x2, 0x10 ); // power enable + udelay(200000); + + i365_out(s, 0x2, 0x10 | 0x01 | 0x04 | 0x80); //power enable + + udelay(250000); + + if (!s->irq) + s->irq = 11; + + i365_out(s, 0x3, 0x40 | 0x20 | s->irq); + + jiff = jiffies; + + while (jiffies-jiff < HZ ) + if (i365_in(s,0x1) & 0x20) + break; + + if (! (i365_in(s,0x1) & 0x20) ){ + printk("irq enable timeout on socket %x \n", s->socket); + return -1; + }; + + i365_out(s,0x10,0xd0); + i365_out(s,0x11,0x0); + i365_out(s,0x12,0xd0); + i365_out(s,0x13,0x0); + i365_out(s,0x14,0x30 ); + i365_out(s,0x15,0x3f | 0x40); // enab mem reg bit + i365_out(s,0x06,0x01); // enab mem + + udelay(10000); + + cis[0] = 0x45; + +// memcpy_toio( 0xd3e0, &(cis[0]),0x1); + +// mem[0x3e0] = 0x0; +// mem[0] = 0x45; + + mem[0x3e0] = 0x45; + + udelay(10000); + + memcpy_fromio(cis,0xD000, 0x3e0); + + for (i = 0; i <= 0x3e2; i++) + printk("%02x", mem[i]); + for (i = 0; i <= 0x3e2; i++) + printk("%c", mem[i]); + + i=0; + while (i < 0x3e0){ + if (cis[i] == 0xff) + break; + if (cis[i] != 0x20 ){ + i = i + 2 + cis[i+1]; + continue; + }else { + s->manufacturer = cis[i+2] | (cis[i+3]<<8); + s->product = cis[i+4] | (cis[i+5]<<8); + break; + }; + i++; + }; + + DEBUG(1,"socket %x manufacturer %x product %x \n", + s->socket, s->manufacturer,s->product); + + i365_out(s,0x07, 0x1 | 0x2); // enable io 16bit + udelay(1000); + port = s->io; + i365_out(s,0x08, port & 0xff); + i365_out(s,0x09, (port & 0xff00)/ 0x100); + i365_out(s,0x0A, (port+port_range) & 0xff); + i365_out(s,0x0B, ((port+port_range) & 0xff00) /0x100); + + i365_out(s,0x06, 0x40); // enable io window + + udelay(1000); + + i365_out(s,0x3e0,0x45); + + outw(0x10, s->io); + + jiff = jiffies; + while (!(inw(s->io + 0x30) & 0x10)){ + + if (jiffies - jiff > HZ ){ + + printk("timed out waitin for command ack \n"); + break; + } + }; + + + outw(0x10, s->io + 0x34); + udelay(10000); + + return 0; + + + + +}; + + +static int awc_i365_init(struct i365_socket * s) { + + struct NET_DEVICE * dev; + int i; + + + dev = init_etherdev(0, sizeof(struct awc_private) ); + +// dev->tx_queue_len = tx_queue_len; + ether_setup(dev); + + dev->hard_start_xmit = &awc_start_xmit; +// dev->set_config = &awc_config_misiganes,aga mitte awc_config; + dev->get_stats = &awc_get_stats; + dev->set_multicast_list = &awc_set_multicast_list; + + dev->init = &awc_init; + dev->open = &awc_open; + dev->stop = &awc_close; + dev->tbusy = 1; + dev->start = 0; + dev->irq = s->irq; + dev->base_addr = s->io; + + + awc_private_init( dev); + + i=0; + while (aironet4500_devices[i] && i < MAX_AWCS-1) i++; + if (!aironet4500_devices[i]){ + aironet4500_devices[i]=dev; + + ((struct awc_private *) + aironet4500_devices[i]->priv)->card_type = AIRONET4500_365; + + if (awc_proc_set_fun) + awc_proc_set_fun(i); + } + + dev->tbusy = 1; + dev->start = 0; + + + if (register_netdev(dev) != 0) { + printk(KERN_NOTICE "awc_cs: register_netdev() failed\n"); + goto failed; + } + + + + return 0; + + failed: + return -1; + +} + +static void awc_i365_release(void) { + +// long flags; + int i=0; + + DEBUG(0, "awc_detach \n"); + + i=0; + while ( i < MAX_AWCS) { + + if (!aironet4500_devices[i]) + {i++; continue;} + + if (((struct awc_private *)aironet4500_devices[i]->priv)->card_type != AIRONET4500_365) + {i++; continue;} + + if (awc_proc_unset_fun) + awc_proc_unset_fun(i); + + unregister_netdev(aironet4500_devices[i]); + + //kfree_s(aironet4500_devices[i]->priv, sizeof(struct awc_private)); + kfree_s(aironet4500_devices[i], sizeof(struct NET_DEVICE)); + + aironet4500_devices[i]=0; + + + i++; + } + + +} + + + + + + + +int awc_i365_probe(void) { + + int i = 1; + int k = 0; + int ret = 0; + int found=0; + + struct i365_socket s; + /* Always emit the version, before any failure. */ + + if (!awc_i365_sockets) { + printk(" awc i82635 4x00: use bitfiel opts awc_i365_sockets=0x3 <- (1|2) to probe sockets 0 and 1\n"); + return -1; + }; + + while (k < 4){ + if (i & awc_i365_sockets){ + + s.offset_port = awc_i365_offset_ports[k]; + s.data_port = awc_i365_data_ports[k]; + s.socket = k; + s.manufacturer = 0; + s.product = 0; + s.irq = awc_i365_irq[k]; + s.io = awc_i365_io[k]; + + ret = awc_i365_probe_once(&s); + if (!ret){ + if (awc_i365_init(&s)) + goto failed; + else found++; + } else if (ret == -1) + goto failed; + }; + k++; + i *=2; + }; + + if (!found){ + printk("no aironet 4x00 cards found\n"); + return -1; + } + return 0; + +failed: + awc_i365_release(); + return -1; + + +} + +#endif /* CONFIG_AIRONET4500_365 */ + +#ifdef MODULE +int init_module(void) +{ + int found = 0; + + printk("%s\n ", awc_version); + +#ifdef CONFIG_AIRONET4500_PCI + if (awc4500_pci_probe(NULL) == -ENODEV){ + printk("PCI 4X00 aironet cards not found\n"); + } else { + found++; + printk("PCI 4X00 found some cards \n"); + } +#endif +#ifdef CONFIG_AIRONET4500_PNP + if (awc4500_pnp_probe(NULL) == -ENODEV){ + printk("PNP 4X00 aironet cards not found\n"); + } else { + found++; + printk("PNP 4X00 found some cards \n"); + } +#endif +#ifdef CONFIG_AIRONET4500_365 + if ( awc_i365_probe() == -1) { + printk("PCMCIA 4X00 aironet cards not found for i365(without card services) initialization\n"); + } else { + found++ ; + printk("PCMCIA 4X00 found some cards, take care, this code is not supposed to work yet \n"); + } +#endif +#ifdef CONFIG_AIRONET4500_ISA + if (awc4500_isa_probe(NULL) == -ENODEV){ + printk("ISA 4X00 aironet ISA-bus non-PNP-mode cards not found\n"); + } else { + found++; + printk("ISA 4X00 found some cards \n"); + } +#endif + if (!found) return -1; + return 0; + + +} + +void cleanup_module(void) +{ + DEBUG(0, "awc_cs: unloading %c ",'\n'); +#ifdef CONFIG_AIRONET4500_PCI + awc_pci_release(); +#endif +#ifdef CONFIG_AIRONET4500_PNP + awc_pnp_release(); +#endif +#ifdef CONFIG_AIRONET4500_365 + awc_i365_release(); +#endif +#ifdef CONFIG_AIRONET4500_ISA + awc_isa_release(); +#endif + +} +#endif
\ No newline at end of file |