summaryrefslogtreecommitdiffstats
path: root/drivers/net/aironet4500_card.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-02-04 07:40:19 +0000
commit33263fc5f9ac8e8cb2b22d06af3ce5ac1dd815e4 (patch)
tree2d1b86a40bef0958a68cf1a2eafbeb0667a70543 /drivers/net/aironet4500_card.c
parent216f5f51aa02f8b113aa620ebc14a9631a217a00 (diff)
Merge with Linux 2.3.32.
Diffstat (limited to 'drivers/net/aironet4500_card.c')
-rw-r--r--drivers/net/aironet4500_card.c1118
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