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
0033
0034
0035 #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
0036
0037 #include <linux/kernel.h>
0038 #include <linux/ptrace.h>
0039 #include <linux/slab.h>
0040 #include <linux/string.h>
0041 #include <linux/timer.h>
0042 #include <linux/delay.h>
0043 #include <linux/module.h>
0044 #include <linux/netdevice.h>
0045 #include <linux/io.h>
0046 #include <pcmcia/cistpl.h>
0047 #include <pcmcia/ds.h>
0048
0049 #include "arcdevice.h"
0050 #include "com20020.h"
0051
0052 static void regdump(struct net_device *dev)
0053 {
0054 #ifdef DEBUG
0055 int ioaddr = dev->base_addr;
0056 int count;
0057
0058 netdev_dbg(dev, "register dump:\n");
0059 for (count = 0; count < 16; count++) {
0060 if (!(count % 16))
0061 pr_cont("%04X:", ioaddr + count);
0062 pr_cont(" %02X", arcnet_inb(ioaddr, count));
0063 }
0064 pr_cont("\n");
0065
0066 netdev_dbg(dev, "buffer0 dump:\n");
0067
0068 count = 0;
0069 arcnet_outb((count >> 8) | RDDATAflag | AUTOINCflag,
0070 ioaddr, COM20020_REG_W_ADDR_HI);
0071 arcnet_outb(count & 0xff, ioaddr, COM20020_REG_W_ADDR_LO);
0072
0073 for (count = 0; count < 256 + 32; count++) {
0074 if (!(count % 16))
0075 pr_cont("%04X:", count);
0076
0077
0078 pr_cont(" %02X", arcnet_inb(ioaddr, COM20020_REG_RW_MEMDATA));
0079 }
0080 pr_cont("\n");
0081 #endif
0082 }
0083
0084
0085
0086
0087
0088 static int node;
0089 static int timeout = 3;
0090 static int backplane;
0091 static int clockp;
0092 static int clockm;
0093
0094 module_param(node, int, 0);
0095 module_param(timeout, int, 0);
0096 module_param(backplane, int, 0);
0097 module_param(clockp, int, 0);
0098 module_param(clockm, int, 0);
0099
0100 MODULE_LICENSE("GPL");
0101
0102
0103
0104 static int com20020_config(struct pcmcia_device *link);
0105 static void com20020_release(struct pcmcia_device *link);
0106
0107 static void com20020_detach(struct pcmcia_device *p_dev);
0108
0109
0110
0111 static int com20020_probe(struct pcmcia_device *p_dev)
0112 {
0113 struct com20020_dev *info;
0114 struct net_device *dev;
0115 struct arcnet_local *lp;
0116
0117 dev_dbg(&p_dev->dev, "com20020_attach()\n");
0118
0119
0120 info = kzalloc(sizeof(*info), GFP_KERNEL);
0121 if (!info)
0122 goto fail_alloc_info;
0123
0124 dev = alloc_arcdev("");
0125 if (!dev)
0126 goto fail_alloc_dev;
0127
0128 lp = netdev_priv(dev);
0129 lp->timeout = timeout;
0130 lp->backplane = backplane;
0131 lp->clockp = clockp;
0132 lp->clockm = clockm & 3;
0133 lp->hw.owner = THIS_MODULE;
0134
0135
0136 arcnet_set_addr(dev, node);
0137
0138 p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
0139 p_dev->resource[0]->end = 16;
0140 p_dev->config_flags |= CONF_ENABLE_IRQ;
0141
0142 info->dev = dev;
0143 p_dev->priv = info;
0144
0145 return com20020_config(p_dev);
0146
0147 fail_alloc_dev:
0148 kfree(info);
0149 fail_alloc_info:
0150 return -ENOMEM;
0151 }
0152
0153 static void com20020_detach(struct pcmcia_device *link)
0154 {
0155 struct com20020_dev *info = link->priv;
0156 struct net_device *dev = info->dev;
0157
0158 dev_dbg(&link->dev, "detach...\n");
0159
0160 dev_dbg(&link->dev, "com20020_detach\n");
0161
0162 dev_dbg(&link->dev, "unregister...\n");
0163
0164 unregister_netdev(dev);
0165
0166
0167
0168
0169 if (dev->irq)
0170 free_irq(dev->irq, dev);
0171
0172 com20020_release(link);
0173
0174
0175 dev_dbg(&link->dev, "unlinking...\n");
0176 if (link->priv) {
0177 dev = info->dev;
0178 if (dev) {
0179 dev_dbg(&link->dev, "kfree...\n");
0180 free_arcdev(dev);
0181 }
0182 dev_dbg(&link->dev, "kfree2...\n");
0183 kfree(info);
0184 }
0185
0186 }
0187
0188 static int com20020_config(struct pcmcia_device *link)
0189 {
0190 struct arcnet_local *lp;
0191 struct com20020_dev *info;
0192 struct net_device *dev;
0193 int i, ret;
0194 int ioaddr;
0195
0196 info = link->priv;
0197 dev = info->dev;
0198
0199 dev_dbg(&link->dev, "config...\n");
0200
0201 dev_dbg(&link->dev, "com20020_config\n");
0202
0203 dev_dbg(&link->dev, "baseport1 is %Xh\n",
0204 (unsigned int)link->resource[0]->start);
0205
0206 i = -ENODEV;
0207 link->io_lines = 16;
0208
0209 if (!link->resource[0]->start) {
0210 for (ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x10) {
0211 link->resource[0]->start = ioaddr;
0212 i = pcmcia_request_io(link);
0213 if (i == 0)
0214 break;
0215 }
0216 } else {
0217 i = pcmcia_request_io(link);
0218 }
0219
0220 if (i != 0) {
0221 dev_dbg(&link->dev, "requestIO failed totally!\n");
0222 goto failed;
0223 }
0224
0225 ioaddr = dev->base_addr = link->resource[0]->start;
0226 dev_dbg(&link->dev, "got ioaddr %Xh\n", ioaddr);
0227
0228 dev_dbg(&link->dev, "request IRQ %d\n",
0229 link->irq);
0230 if (!link->irq) {
0231 dev_dbg(&link->dev, "requestIRQ failed totally!\n");
0232 goto failed;
0233 }
0234
0235 dev->irq = link->irq;
0236
0237 ret = pcmcia_enable_device(link);
0238 if (ret)
0239 goto failed;
0240
0241 if (com20020_check(dev)) {
0242 regdump(dev);
0243 goto failed;
0244 }
0245
0246 lp = netdev_priv(dev);
0247 lp->card_name = "PCMCIA COM20020";
0248 lp->card_flags = ARC_CAN_10MBIT;
0249
0250 SET_NETDEV_DEV(dev, &link->dev);
0251
0252 i = com20020_found(dev, 0);
0253
0254 if (i != 0) {
0255 dev_notice(&link->dev,
0256 "com20020_found() failed\n");
0257 goto failed;
0258 }
0259
0260 netdev_dbg(dev, "port %#3lx, irq %d\n",
0261 dev->base_addr, dev->irq);
0262 return 0;
0263
0264 failed:
0265 dev_dbg(&link->dev, "com20020_config failed...\n");
0266 com20020_release(link);
0267 return -ENODEV;
0268 }
0269
0270 static void com20020_release(struct pcmcia_device *link)
0271 {
0272 dev_dbg(&link->dev, "com20020_release\n");
0273 pcmcia_disable_device(link);
0274 }
0275
0276 static int com20020_suspend(struct pcmcia_device *link)
0277 {
0278 struct com20020_dev *info = link->priv;
0279 struct net_device *dev = info->dev;
0280
0281 if (link->open)
0282 netif_device_detach(dev);
0283
0284 return 0;
0285 }
0286
0287 static int com20020_resume(struct pcmcia_device *link)
0288 {
0289 struct com20020_dev *info = link->priv;
0290 struct net_device *dev = info->dev;
0291
0292 if (link->open) {
0293 int ioaddr = dev->base_addr;
0294 struct arcnet_local *lp = netdev_priv(dev);
0295
0296 arcnet_outb(lp->config | 0x80, ioaddr, COM20020_REG_W_CONFIG);
0297 udelay(5);
0298 arcnet_outb(lp->config, ioaddr, COM20020_REG_W_CONFIG);
0299 }
0300
0301 return 0;
0302 }
0303
0304 static const struct pcmcia_device_id com20020_ids[] = {
0305 PCMCIA_DEVICE_PROD_ID12("Contemporary Control Systems, Inc.",
0306 "PCM20 Arcnet Adapter", 0x59991666, 0x95dfffaf),
0307 PCMCIA_DEVICE_PROD_ID12("SoHard AG",
0308 "SH ARC PCMCIA", 0xf8991729, 0x69dff0c7),
0309 PCMCIA_DEVICE_NULL
0310 };
0311 MODULE_DEVICE_TABLE(pcmcia, com20020_ids);
0312
0313 static struct pcmcia_driver com20020_cs_driver = {
0314 .owner = THIS_MODULE,
0315 .name = "com20020_cs",
0316 .probe = com20020_probe,
0317 .remove = com20020_detach,
0318 .id_table = com20020_ids,
0319 .suspend = com20020_suspend,
0320 .resume = com20020_resume,
0321 };
0322 module_pcmcia_driver(com20020_cs_driver);