📄 aironet4500_card.c
字号:
/* * Aironet 4500 PCI-ISA-i365 driver * * Elmer Joandi, Januar 1999 * Copyright GPL * * * Revision 0.1 ,started 30.12.1998 * * Revision 0.2, Feb 27, 2000 * Jeff Garzik - softnet, cleanups * */#ifdef MODULEstatic const char *awc_version ="aironet4500_cards.c v0.2 Feb 27, 2000 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>#include <linux/delay.h>#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;static int awc_pci_init(struct net_device * dev, struct pci_dev *pdev, 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; /* Static, for multiple probe calls. */ u8 pci_irq_line = 0;// int p; unsigned char awc_pci_dev, awc_pci_bus; if (!pci_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; struct pci_dev *pdev; 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; } } pdev = pci_find_slot(awc_pci_bus, awc_pci_dev); if (!pdev) continue; if (pci_enable_device(pdev)) continue; vendor = pdev->vendor; device = pdev->device; pci_irq_line = pdev->irq; pci_memaddr = pci_resource_start (pdev, 0); pci_cisaddr = pci_resource_start (pdev, 1); pci_ioaddr = pci_resource_start (pdev, 2);// 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 (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;// } if (!request_region(pci_ioaddr, AIRONET4X00_IO_SIZE, "aironet4x00 ioaddr")) continue;// request_region(pci_cisaddr, AIRONET4X00_CIS_SIZE, "aironet4x00 cis");// request_region(pci_memaddr, AIRONET4X00_MEM_SIZE, "aironet4x00 mem");// pci_write_config_word(pdev, PCI_COMMAND, 0); udelay(10000); pci_read_config_word(pdev, 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); pci_write_config_word(pdev, PCI_COMMAND, new_command); }/* if (device == PCI_DEVICE_AIRONET_4800) pci_write_config_dword(pdev, 0x40, 0x00000000); udelay(1000);*/ if (device == PCI_DEVICE_AIRONET_4800) pci_write_config_dword(pdev, 0x40, 0x40000000); if (awc_pci_init(dev, pdev, 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, struct pci_dev *pdev, int ioaddr, int cis_addr, int mem_addr, u8 pci_irq_line) { int i, allocd_dev = 0; if (!dev) { dev = init_etherdev(NULL, 0); if (!dev) return -ENOMEM; allocd_dev = 1; } 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"); if (allocd_dev) { unregister_netdev(dev); kfree(dev); } return -ENOMEM; };// 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->base_addr = ioaddr; dev->irq = pci_irq_line; dev->tx_timeout = &awc_tx_timeout; dev->watchdog_timeo = AWC_TX_TIMEOUT; i = request_irq(dev->irq,awc_interrupt, SA_SHIRQ | SA_INTERRUPT, dev->name, dev); if (i) { kfree(dev->priv); dev->priv = NULL; if (allocd_dev) { unregister_netdev(dev); kfree(dev); } return i; } 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); }// if (register_netdev(dev) != 0) {// printk(KERN_NOTICE "awc_cs: register_netdev() failed\n");// goto failed;// } return 0; // failed:// return -1;}#ifdef MODULEstatic 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(aironet4500_devices[i]->priv); kfree(aironet4500_devices[i]); aironet4500_devices[i]=0; i++; } } #endif //MODULE#endif /* CONFIG_AIRONET4500_PCI */#ifdef CONFIG_AIRONET4500_PNP#include <linux/isapnp.h>#define AIRONET4X00_IO_SIZE 0x40#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 devfnint awc4500_pnp_hw_reset(struct net_device *dev){ struct isapnp_logdev *logdev; 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; } 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; while (1) { pnp_dev = isapnp_find_device( ISAPNP_VENDOR('A','W','L'), ISAPNP_DEVICE(1), 0); 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; } isapnp_activate(logdev->PNP_DEV_NUMBER); /* activate device */ isapnp_cfg_end(); isa_irq_line = logdev->irq; isa_ioaddr = logdev->resource[0].start; 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->base_addr = isa_ioaddr; dev->irq = isa_irq_line; dev->tx_timeout = &awc_tx_timeout; dev->watchdog_timeo = AWC_TX_TIMEOUT; netif_start_queue (dev); request_irq(dev->irq,awc_interrupt , SA_SHIRQ | SA_INTERRUPT ,"Aironet 4X00",dev); 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; } card++; } if (card == 0) return -ENODEV; return 0;}#ifdef MODULEstatic 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(aironet4500_devices[i]->priv); kfree(aironet4500_devices[i]); 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);*/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");int awc4500_isa_probe(struct net_device *dev){// int cards_found = 0;// static int isa_index; /* Static, for multiple probe calls. */ int isa_irq_line = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -