Main Page | Data Structures | Directories | File List | Data Fields | Globals

if_ath_pci.c

Go to the documentation of this file.
00001 
00002 
00003 /*-
00004  * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer,
00012  *    without modification.
00013  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
00014  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
00015  *    redistribution must be conditioned upon including a substantially
00016  *    similar Disclaimer requirement for further binary redistribution.
00017  * 3. Neither the names of the above-listed copyright holders nor the names
00018  *    of any contributors may be used to endorse or promote products derived
00019  *    from this software without specific prior written permission.
00020  *
00021  * Alternatively, this software may be distributed under the terms of the
00022  * GNU General Public License ("GPL") version 2 as published by the Free
00023  * Software Foundation.
00024  *
00025  * NO WARRANTY
00026  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00027  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00028  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
00029  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00030  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
00031  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00032  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00033  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
00034  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00035  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
00036  * THE POSSIBILITY OF SUCH DAMAGES.
00037  *
00038  * $Id: if_ath_pci.c,v 1.7 2005/05/03 16:36:03 jbicket Exp $
00039  */
00040 #include "opt_ah.h"
00041 
00042 #ifndef EXPORT_SYMTAB
00043 #define EXPORT_SYMTAB
00044 #endif
00045 
00046 #include <linux/config.h>
00047 #include <linux/version.h>
00048 #include <linux/module.h>
00049 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0))
00050 #include <linux/moduleparam.h>
00051 #endif
00052 #include <linux/init.h>
00053 #include <linux/if.h>
00054 #include <linux/netdevice.h>
00055 #include <linux/cache.h>
00056 
00057 #include <linux/pci.h>
00058 
00059 #include <asm/uaccess.h>
00060 #include "if_athvar.h"
00061 #include "if_ath_pci.h"
00062 
00063 /* support for module parameters */
00064 static char *ifname = "ath";
00065 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,52))
00066 MODULE_PARM(ifname, "s");
00067 #else
00068 module_param(ifname, charp, 0);
00069 #endif
00070 
00071 MODULE_PARM_DESC(ifname, "Interface name prefix (default: ath)");
00072 
00073 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
00074 /*
00075  * PCI initialization uses Linux 2.4.x version and
00076  * older kernels do not support this
00077  */
00078 #error Atheros PCI version requires at least Linux kernel version 2.4.0
00079 #endif /* kernel < 2.4.0 */
00080 
00081 struct ath_pci_softc {
00082         struct ath_softc        aps_sc;
00083 #ifdef CONFIG_PM
00084         u32                     aps_pmstate[16];
00085 #endif
00086 };
00087 
00088 /*
00089  * User a static table of PCI id's for now.  While this is the
00090  * "new way" to do things, we may want to switch back to having
00091  * the HAL check them by defining a probe method.
00092  */
00093 static struct pci_device_id ath_pci_id_table[] __devinitdata = {
00094         { 0x168c, 0x0007, PCI_ANY_ID, PCI_ANY_ID },
00095         { 0x168c, 0x0012, PCI_ANY_ID, PCI_ANY_ID },
00096         { 0x168c, 0x0013, PCI_ANY_ID, PCI_ANY_ID },
00097         { 0xa727, 0x0013, PCI_ANY_ID, PCI_ANY_ID },     /* 3com */
00098         { 0x10b7, 0x0013, PCI_ANY_ID, PCI_ANY_ID },     /* 3com 3CRDAG675 */
00099         { 0x168c, 0x1014, PCI_ANY_ID, PCI_ANY_ID },     /* IBM minipci 5212 */
00100         { 0x168c, 0x0015, PCI_ANY_ID, PCI_ANY_ID },
00101         { 0x168c, 0x0016, PCI_ANY_ID, PCI_ANY_ID },
00102         { 0x168c, 0x0017, PCI_ANY_ID, PCI_ANY_ID },
00103         { 0x168c, 0x0018, PCI_ANY_ID, PCI_ANY_ID },
00104         { 0x168c, 0x0019, PCI_ANY_ID, PCI_ANY_ID },
00105         { 0x168c, 0x001a, PCI_ANY_ID, PCI_ANY_ID },
00106         { 0 }
00107 };
00108 
00109 static int
00110 ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
00111 {
00112         unsigned long phymem;
00113         unsigned long mem;
00114         struct ath_pci_softc *sc;
00115         struct net_device *dev;
00116         const char *athname;
00117         u_int8_t csz;
00118         u32 val;
00119 
00120         if (pci_enable_device(pdev))
00121                 return (-EIO);
00122 
00123         /* XXX 32-bit addressing only */
00124         if (pci_set_dma_mask(pdev, 0xffffffff)) {
00125                 printk(KERN_ERR "ath_pci: 32-bit DMA not available\n");
00126                 goto bad;
00127         }
00128 
00129         /*
00130          * Cache line size is used to size and align various
00131          * structures used to communicate with the hardware.
00132          */
00133         pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz);
00134         if (csz == 0) {
00135                 /*
00136                  * Linux 2.4.18 (at least) writes the cache line size
00137                  * register as a 16-bit wide register which is wrong.
00138                  * We must have this setup properly for rx buffer
00139                  * DMA to work so force a reasonable value here if it
00140                  * comes up zero.
00141                  */
00142                 csz = L1_CACHE_BYTES / sizeof(u_int32_t);
00143                 printk("ath_pci: cache line size not set; forcing %u\n", csz);
00144                 pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
00145         }
00146         /*
00147          * The default setting of latency timer yields poor results,
00148          * set it to the value used by other systems.  It may be worth
00149          * tweaking this setting more.
00150          */
00151         pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8);
00152 
00153         pci_set_master(pdev);
00154 
00155         /*
00156          * Disable the RETRY_TIMEOUT register (0x41) to keep
00157          * PCI Tx retries from interfering with C3 CPU state.
00158          *
00159          * Code taken from ipw2100 driver - jg
00160          */
00161         pci_read_config_dword(pdev, 0x40, &val);
00162         if ((val & 0x0000ff00) != 0)
00163                 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
00164 
00165 
00166         phymem = pci_resource_start(pdev, 0);
00167         if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "ath")) {
00168                 printk(KERN_ERR "ath_pci: cannot reserve PCI memory region\n");
00169                 goto bad;
00170         }
00171 
00172         mem = (unsigned long) ioremap(phymem, pci_resource_len(pdev, 0));
00173         if (!mem) {
00174                 printk(KERN_ERR "ath_pci: cannot remap PCI memory region\n") ;
00175                 release_mem_region(phymem, pci_resource_len(pdev, 0));
00176                 goto bad1;
00177         }
00178 
00179         sc = kmalloc(sizeof(struct ath_pci_softc), GFP_KERNEL);
00180         if (sc == NULL) {
00181                 printk(KERN_ERR "ath_pci: no memory for device state\n");
00182                 goto bad2;
00183         }
00184         memset(sc, 0, sizeof(struct ath_pci_softc));
00185 
00186         dev = &sc->aps_sc.dev; /* XXX blech, violate layering */
00187         memcpy(dev->name, "ath%d", sizeof("ath%d"));
00188 
00189         dev->irq = pdev->irq;
00190         dev->mem_start = mem;
00191         dev->mem_end = mem + pci_resource_len(pdev, 0);
00192         dev->priv = sc;
00193 
00194         SET_MODULE_OWNER(dev);
00195         SET_NETDEV_DEV(dev, &pdev->dev);
00196 
00197 
00198         sc->aps_sc.sc_bdev = (void *) pdev;
00199 
00200         pci_set_drvdata(pdev, dev);
00201 
00202         if (request_irq(dev->irq, ath_intr, SA_SHIRQ, dev->name, dev)) {
00203                 printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
00204                 goto bad3;
00205         }
00206 
00207         /*
00208          *  jbicket moved this up
00209          * 
00210          *ready to process interrupts */
00211         sc->aps_sc.sc_invalid = 0;
00212 
00213         if (ath_attach(id->device, dev) != 0)
00214                 goto bad4;
00215 
00216         athname = ath_hal_probe(id->vendor, id->device);
00217         printk(KERN_INFO "%s: %s: mem=0x%lx, irq=%d\n",
00218                 dev->name, athname ? athname : "Atheros ???", phymem, dev->irq);
00219 
00220         return 0;
00221 bad4:
00222         free_irq(dev->irq, dev);
00223 bad3:
00224         kfree(sc);
00225 bad2:
00226         iounmap((void *) mem);
00227 bad1:
00228         release_mem_region(phymem, pci_resource_len(pdev, 0));
00229 bad:
00230         pci_disable_device(pdev);
00231         return (-ENODEV);
00232 }
00233 
00234 static void
00235 ath_pci_remove(struct pci_dev *pdev)
00236 {
00237         struct net_device *dev = pci_get_drvdata(pdev);
00238         
00239         ath_detach(dev);
00240         if (dev->irq)
00241                 free_irq(dev->irq, dev);
00242         iounmap((void *) dev->mem_start);
00243         release_mem_region(pci_resource_start(pdev, 0),
00244                            pci_resource_len(pdev, 0));
00245         pci_disable_device(pdev);
00246 
00247 #ifdef HAVE_FREE_NETDEV
00248         free_netdev(dev);
00249 #endif
00250 }
00251 
00252 #ifdef CONFIG_PM
00253 static int
00254 ath_pci_suspend(struct pci_dev *pdev, u32 state)
00255 {
00256         struct net_device *dev = pci_get_drvdata(pdev);
00257         
00258         ath_suspend(dev);
00259         PCI_SAVE_STATE(pdev,
00260                 ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
00261         pci_disable_device(pdev);
00262         pci_set_power_state(pdev, 3);
00263 
00264         return (0);
00265 }
00266 
00267 static int
00268 ath_pci_resume(struct pci_dev *pdev)
00269 {
00270         struct net_device *dev = pci_get_drvdata(pdev);
00271         u32 val;
00272 
00273         pci_enable_device(pdev);
00274         PCI_RESTORE_STATE(pdev,
00275                 ((struct ath_pci_softc *)dev->priv)->aps_pmstate);
00276         /*
00277          * Suspend/Resume resets the PCI configuration space, so we have to
00278          * re-disable the RETRY_TIMEOUT register (0x41) to keep
00279          * PCI Tx retries from interfering with C3 CPU state
00280          *
00281          * Code taken from ipw2100 driver - jg
00282          */
00283         pci_read_config_dword(pdev, 0x40, &val);
00284         if ((val & 0x0000ff00) != 0)
00285                 pci_write_config_dword(pdev, 0x40, val & 0xffff00ff);
00286         ath_resume(dev);
00287 
00288         return (0);
00289 }
00290 #endif /* CONFIG_PM */
00291 
00292 MODULE_DEVICE_TABLE(pci, ath_pci_id_table);
00293 
00294 static struct pci_driver ath_pci_drv_id = {
00295         .name           = "ath_pci",
00296         .id_table       = ath_pci_id_table,
00297         .probe          = ath_pci_probe,
00298         .remove         = ath_pci_remove,
00299 #ifdef CONFIG_PM
00300         .suspend        = ath_pci_suspend,
00301         .resume         = ath_pci_resume,
00302 #endif /* CONFIG_PM */
00303         /* Linux 2.4.6 has save_state and enable_wake that are not used here */
00304 };
00305 
00306 /*
00307  * Module glue.
00308  */
00309 #include "release.h"
00310 #include "version.h"
00311 
00312 char *version = ATH_PCI_VERSION " " RELEASE_TYPE;
00313 char *dev_info = "ath_pci";
00314 
00315 #include <linux/ethtool.h>
00316 
00317 int
00318 ath_ioctl_ethtool(struct ath_softc *sc, int cmd, void *addr)
00319 {
00320         struct ethtool_drvinfo info;
00321 
00322         if (cmd != ETHTOOL_GDRVINFO)
00323                 return -EOPNOTSUPP;
00324         memset(&info, 0, sizeof(info));
00325         info.cmd = cmd;
00326         strncpy(info.driver, dev_info, sizeof(info.driver)-1);
00327         strncpy(info.version, version, sizeof(info.version)-1);
00328 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,22)
00329         /* include the device name so later versions of kudzu DTRT */
00330         strncpy(info.bus_info, pci_name((struct pci_dev *)sc->sc_bdev),
00331                 sizeof(info.bus_info)-1);
00332 #endif
00333         
00334         return copy_to_user(addr, &info, sizeof(info)) ? -EFAULT : 0;
00335 }
00336 MODULE_AUTHOR("Errno Consulting, Sam Leffler");
00337 MODULE_DESCRIPTION("Support for Atheros 802.11 wireless LAN cards.");
00338 MODULE_SUPPORTED_DEVICE("Atheros WLAN cards");
00339 #ifdef MODULE_LICENSE
00340 MODULE_LICENSE("Dual BSD/GPL");
00341 #endif
00342 
00343 static int __init
00344 init_ath_pci(void)
00345 {
00346         printk(KERN_INFO "%s: %s\n", dev_info, version);
00347 
00348         if (pci_register_driver(&ath_pci_drv_id) < 0) {
00349                 printk("ath_pci: No devices found, driver not installed.\n");
00350                 pci_unregister_driver(&ath_pci_drv_id);
00351                 return (-ENODEV);
00352         }
00353 #ifdef CONFIG_SYSCTL
00354         ath_sysctl_register();
00355 #endif
00356         return (0);
00357 }
00358 module_init(init_ath_pci);
00359 
00360 static void __exit
00361 exit_ath_pci(void)
00362 {
00363 #ifdef CONFIG_SYSCTL
00364         ath_sysctl_unregister();
00365 #endif
00366   
00367   pci_unregister_driver(&ath_pci_drv_id);
00368   
00369   printk(KERN_INFO "%s: driver unloaded\n", dev_info);
00370 }
00371 module_exit(exit_ath_pci);
00372 
00373 /* return bus cachesize in 4B word units */
00374 void
00375 bus_read_cachesize(struct ath_softc *sc, u_int8_t *csz)
00376 {
00377         pci_read_config_byte(sc->sc_bdev, PCI_CACHE_LINE_SIZE, csz);
00378 }
00379 
00380 

Generated on Mon Nov 21 15:58:10 2005 for openwifi by  doxygen 1.4.1