0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
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
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 }
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
0098
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
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
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283