Back to home page

OSCL-LXR

 
 

    


0001 /*** -*- linux-c -*- **********************************************************
0002 
0003      Driver for Atmel at76c502 at76c504 and at76c506 wireless cards.
0004 
0005         Copyright 2000-2001 ATMEL Corporation.
0006         Copyright 2003 Simon Kelley.
0007 
0008     This code was developed from version 2.1.1 of the Atmel drivers,
0009     released by Atmel corp. under the GPL in December 2002. It also
0010     includes code from the Linux aironet drivers (C) Benjamin Reed,
0011     and the Linux PCMCIA package, (C) David Hinds.
0012 
0013     For all queries about this code, please contact the current author,
0014     Simon Kelley <simon@thekelleys.org.uk> and not Atmel Corporation.
0015 
0016     This program is free software; you can redistribute it and/or modify
0017     it under the terms of the GNU General Public License as published by
0018     the Free Software Foundation; either version 2 of the License, or
0019     (at your option) any later version.
0020 
0021     This software is distributed in the hope that it will be useful,
0022     but WITHOUT ANY WARRANTY; without even the implied warranty of
0023     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0024     GNU General Public License for more details.
0025 
0026     You should have received a copy of the GNU General Public License
0027     along with Atmel wireless lan drivers; if not, see
0028     <http://www.gnu.org/licenses/>.
0029 
0030 ******************************************************************************/
0031 
0032 #ifdef __IN_PCMCIA_PACKAGE__
0033 #include <pcmcia/k_compat.h>
0034 #endif
0035 #include <linux/kernel.h>
0036 #include <linux/module.h>
0037 #include <linux/ptrace.h>
0038 #include <linux/slab.h>
0039 #include <linux/string.h>
0040 #include <linux/netdevice.h>
0041 #include <linux/moduleparam.h>
0042 #include <linux/device.h>
0043 
0044 #include <pcmcia/cistpl.h>
0045 #include <pcmcia/cisreg.h>
0046 #include <pcmcia/ds.h>
0047 #include <pcmcia/ciscode.h>
0048 
0049 #include <asm/io.h>
0050 #include <linux/wireless.h>
0051 
0052 #include "atmel.h"
0053 
0054 
0055 /*====================================================================*/
0056 
0057 MODULE_AUTHOR("Simon Kelley");
0058 MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards.");
0059 MODULE_LICENSE("GPL");
0060 
0061 /*====================================================================*/
0062 
0063 static int atmel_config(struct pcmcia_device *link);
0064 static void atmel_release(struct pcmcia_device *link);
0065 
0066 static void atmel_detach(struct pcmcia_device *p_dev);
0067 
0068 struct local_info {
0069     struct net_device *eth_dev;
0070 };
0071 
0072 static int atmel_probe(struct pcmcia_device *p_dev)
0073 {
0074     struct local_info *local;
0075 
0076     dev_dbg(&p_dev->dev, "atmel_attach()\n");
0077 
0078     /* Allocate space for private device-specific data */
0079     local = kzalloc(sizeof(*local), GFP_KERNEL);
0080     if (!local)
0081         return -ENOMEM;
0082 
0083     p_dev->priv = local;
0084 
0085     return atmel_config(p_dev);
0086 } /* atmel_attach */
0087 
0088 static void atmel_detach(struct pcmcia_device *link)
0089 {
0090     dev_dbg(&link->dev, "atmel_detach\n");
0091 
0092     atmel_release(link);
0093 
0094     kfree(link->priv);
0095 }
0096 
0097 /* Call-back function to interrogate PCMCIA-specific information
0098    about the current existence of the card */
0099 static int card_present(void *arg)
0100 {
0101     struct pcmcia_device *link = (struct pcmcia_device *)arg;
0102 
0103     if (pcmcia_dev_present(link))
0104         return 1;
0105 
0106     return 0;
0107 }
0108 
0109 static int atmel_config_check(struct pcmcia_device *p_dev, void *priv_data)
0110 {
0111     if (p_dev->config_index == 0)
0112         return -EINVAL;
0113 
0114     return pcmcia_request_io(p_dev);
0115 }
0116 
0117 static int atmel_config(struct pcmcia_device *link)
0118 {
0119     int ret;
0120     const struct pcmcia_device_id *did;
0121 
0122     did = dev_get_drvdata(&link->dev);
0123 
0124     dev_dbg(&link->dev, "atmel_config\n");
0125 
0126     link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_VPP |
0127         CONF_AUTO_AUDIO | CONF_AUTO_SET_IO;
0128 
0129     if (pcmcia_loop_config(link, atmel_config_check, NULL))
0130         goto failed;
0131 
0132     if (!link->irq) {
0133         dev_err(&link->dev, "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config.");
0134         goto failed;
0135     }
0136 
0137     ret = pcmcia_enable_device(link);
0138     if (ret)
0139         goto failed;
0140 
0141     ((struct local_info *)link->priv)->eth_dev =
0142         init_atmel_card(link->irq,
0143                 link->resource[0]->start,
0144                 did ? did->driver_info : ATMEL_FW_TYPE_NONE,
0145                 &link->dev,
0146                 card_present,
0147                 link);
0148     if (!((struct local_info *)link->priv)->eth_dev)
0149             goto failed;
0150 
0151 
0152     return 0;
0153 
0154  failed:
0155     atmel_release(link);
0156     return -ENODEV;
0157 }
0158 
0159 static void atmel_release(struct pcmcia_device *link)
0160 {
0161     struct net_device *dev = ((struct local_info *)link->priv)->eth_dev;
0162 
0163     dev_dbg(&link->dev, "atmel_release\n");
0164 
0165     if (dev)
0166         stop_atmel_card(dev);
0167     ((struct local_info *)link->priv)->eth_dev = NULL;
0168 
0169     pcmcia_disable_device(link);
0170 }
0171 
0172 static int atmel_suspend(struct pcmcia_device *link)
0173 {
0174     struct local_info *local = link->priv;
0175 
0176     netif_device_detach(local->eth_dev);
0177 
0178     return 0;
0179 }
0180 
0181 static int atmel_resume(struct pcmcia_device *link)
0182 {
0183     struct local_info *local = link->priv;
0184 
0185     atmel_open(local->eth_dev);
0186     netif_device_attach(local->eth_dev);
0187 
0188     return 0;
0189 }
0190 
0191 /*====================================================================*/
0192 /* We use the driver_info field to store the correct firmware type for a card. */
0193 
0194 #define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \
0195     .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \
0196             PCMCIA_DEV_ID_MATCH_CARD_ID, \
0197     .manf_id = (manf), \
0198     .card_id = (card), \
0199         .driver_info = (kernel_ulong_t)(info), }
0200 
0201 #define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \
0202     .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \
0203             PCMCIA_DEV_ID_MATCH_PROD_ID2, \
0204     .prod_id = { (v1), (v2), NULL, NULL }, \
0205     .prod_id_hash = { (vh1), (vh2), 0, 0 }, \
0206         .driver_info = (kernel_ulong_t)(info), }
0207 
0208 static const struct pcmcia_device_id atmel_ids[] = {
0209     PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM),
0210     PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM),
0211     PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E),
0212     PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502),
0213     PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E),
0214     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502),
0215     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D),
0216     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E),
0217     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958),
0218     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504),
0219     PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958),
0220     PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502),
0221     PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E),
0222     PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502),
0223     PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958),
0224     PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502),
0225     PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D),
0226     PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502),
0227     PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D),
0228     PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D),
0229     PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E),
0230     PCMCIA_DEVICE_NULL
0231 };
0232 
0233 MODULE_DEVICE_TABLE(pcmcia, atmel_ids);
0234 
0235 static struct pcmcia_driver atmel_driver = {
0236     .owner      = THIS_MODULE,
0237     .name       = "atmel_cs",
0238     .probe          = atmel_probe,
0239     .remove     = atmel_detach,
0240     .id_table   = atmel_ids,
0241     .suspend    = atmel_suspend,
0242     .resume     = atmel_resume,
0243 };
0244 module_pcmcia_driver(atmel_driver);
0245 
0246 /*
0247     This program is free software; you can redistribute it and/or
0248     modify it under the terms of the GNU General Public License
0249     as published by the Free Software Foundation; either version 2
0250     of the License, or (at your option) any later version.
0251 
0252     This program is distributed in the hope that it will be useful,
0253     but WITHOUT ANY WARRANTY; without even the implied warranty of
0254     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0255     GNU General Public License for more details.
0256 
0257     In addition:
0258 
0259     Redistribution and use in source and binary forms, with or without
0260     modification, are permitted provided that the following conditions
0261     are met:
0262 
0263     1. Redistributions of source code must retain the above copyright
0264        notice, this list of conditions and the following disclaimer.
0265     2. Redistributions in binary form must reproduce the above copyright
0266        notice, this list of conditions and the following disclaimer in the
0267        documentation and/or other materials provided with the distribution.
0268     3. The name of the author may not be used to endorse or promote
0269        products derived from this software without specific prior written
0270        permission.
0271 
0272     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0273     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0274     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0275     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
0276     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
0277     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
0278     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0279     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
0280     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0281     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0282     POSSIBILITY OF SUCH DAMAGE.
0283 */