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 #define pr_fmt(fmt) "arcnet:" KBUILD_MODNAME ": " fmt
0031
0032 #include <linux/module.h>
0033 #include <linux/moduleparam.h>
0034 #include <linux/kernel.h>
0035 #include <linux/types.h>
0036 #include <linux/ioport.h>
0037 #include <linux/errno.h>
0038 #include <linux/netdevice.h>
0039 #include <linux/init.h>
0040 #include <linux/interrupt.h>
0041 #include <linux/pci.h>
0042 #include <linux/list.h>
0043 #include <linux/io.h>
0044 #include <linux/leds.h>
0045
0046 #include "arcdevice.h"
0047 #include "com20020.h"
0048
0049
0050
0051 static int node;
0052 static char device[9];
0053 static int timeout = 3;
0054 static int backplane;
0055 static int clockp;
0056 static int clockm;
0057
0058 module_param(node, int, 0);
0059 module_param_string(device, device, sizeof(device), 0);
0060 module_param(timeout, int, 0);
0061 module_param(backplane, int, 0);
0062 module_param(clockp, int, 0);
0063 module_param(clockm, int, 0);
0064 MODULE_LICENSE("GPL");
0065
0066 static void led_tx_set(struct led_classdev *led_cdev,
0067 enum led_brightness value)
0068 {
0069 struct com20020_dev *card;
0070 struct com20020_priv *priv;
0071 struct com20020_pci_card_info *ci;
0072
0073 card = container_of(led_cdev, struct com20020_dev, tx_led);
0074
0075 priv = card->pci_priv;
0076 ci = priv->ci;
0077
0078 outb(!!value, priv->misc + ci->leds[card->index].green);
0079 }
0080
0081 static void led_recon_set(struct led_classdev *led_cdev,
0082 enum led_brightness value)
0083 {
0084 struct com20020_dev *card;
0085 struct com20020_priv *priv;
0086 struct com20020_pci_card_info *ci;
0087
0088 card = container_of(led_cdev, struct com20020_dev, recon_led);
0089
0090 priv = card->pci_priv;
0091 ci = priv->ci;
0092
0093 outb(!!value, priv->misc + ci->leds[card->index].red);
0094 }
0095
0096 static ssize_t backplane_mode_show(struct device *dev,
0097 struct device_attribute *attr,
0098 char *buf)
0099 {
0100 struct net_device *net_dev = to_net_dev(dev);
0101 struct arcnet_local *lp = netdev_priv(net_dev);
0102
0103 return sprintf(buf, "%s\n", lp->backplane ? "true" : "false");
0104 }
0105 static DEVICE_ATTR_RO(backplane_mode);
0106
0107 static struct attribute *com20020_state_attrs[] = {
0108 &dev_attr_backplane_mode.attr,
0109 NULL,
0110 };
0111
0112 static const struct attribute_group com20020_state_group = {
0113 .name = NULL,
0114 .attrs = com20020_state_attrs,
0115 };
0116
0117 static void com20020pci_remove(struct pci_dev *pdev);
0118
0119 static int com20020pci_probe(struct pci_dev *pdev,
0120 const struct pci_device_id *id)
0121 {
0122 struct com20020_pci_card_info *ci;
0123 struct com20020_pci_channel_map *mm;
0124 struct net_device *dev;
0125 struct arcnet_local *lp;
0126 struct com20020_priv *priv;
0127 int i, ioaddr, ret;
0128 struct resource *r;
0129
0130 ret = 0;
0131
0132 if (pci_enable_device(pdev))
0133 return -EIO;
0134
0135 priv = devm_kzalloc(&pdev->dev, sizeof(struct com20020_priv),
0136 GFP_KERNEL);
0137 if (!priv)
0138 return -ENOMEM;
0139
0140 ci = (struct com20020_pci_card_info *)id->driver_data;
0141 if (!ci)
0142 return -EINVAL;
0143
0144 priv->ci = ci;
0145 mm = &ci->misc_map;
0146
0147 pci_set_drvdata(pdev, priv);
0148
0149 INIT_LIST_HEAD(&priv->list_dev);
0150
0151 if (mm->size) {
0152 ioaddr = pci_resource_start(pdev, mm->bar) + mm->offset;
0153 r = devm_request_region(&pdev->dev, ioaddr, mm->size,
0154 "com20020-pci");
0155 if (!r) {
0156 pr_err("IO region %xh-%xh already allocated.\n",
0157 ioaddr, ioaddr + mm->size - 1);
0158 return -EBUSY;
0159 }
0160 priv->misc = ioaddr;
0161 }
0162
0163 for (i = 0; i < ci->devcount; i++) {
0164 struct com20020_pci_channel_map *cm = &ci->chan_map_tbl[i];
0165 struct com20020_dev *card;
0166 int dev_id_mask = 0xf;
0167
0168 dev = alloc_arcdev(device);
0169 if (!dev) {
0170 ret = -ENOMEM;
0171 break;
0172 }
0173 dev->dev_port = i;
0174
0175 dev->netdev_ops = &com20020_netdev_ops;
0176
0177 lp = netdev_priv(dev);
0178
0179 arc_printk(D_NORMAL, dev, "%s Controls\n", ci->name);
0180 ioaddr = pci_resource_start(pdev, cm->bar) + cm->offset;
0181
0182 r = devm_request_region(&pdev->dev, ioaddr, cm->size,
0183 "com20020-pci");
0184 if (!r) {
0185 pr_err("IO region %xh-%xh already allocated\n",
0186 ioaddr, ioaddr + cm->size - 1);
0187 ret = -EBUSY;
0188 goto err_free_arcdev;
0189 }
0190
0191
0192
0193
0194
0195 arcnet_outb(0x00, ioaddr, COM20020_REG_W_COMMAND);
0196 arcnet_inb(ioaddr, COM20020_REG_R_DIAGSTAT);
0197
0198 SET_NETDEV_DEV(dev, &pdev->dev);
0199 dev->base_addr = ioaddr;
0200 arcnet_set_addr(dev, node);
0201 dev->sysfs_groups[0] = &com20020_state_group;
0202 dev->irq = pdev->irq;
0203 lp->card_name = "PCI COM20020";
0204 lp->card_flags = ci->flags;
0205 lp->backplane = backplane;
0206 lp->clockp = clockp & 7;
0207 lp->clockm = clockm & 3;
0208 lp->timeout = timeout;
0209 lp->hw.owner = THIS_MODULE;
0210
0211 lp->backplane = (inb(priv->misc) >> (2 + i)) & 0x1;
0212
0213 if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15))
0214 lp->backplane = 1;
0215
0216
0217 if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15))
0218 dev_id_mask = 0x3;
0219 dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask;
0220
0221 snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i);
0222
0223 if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) {
0224 pr_err("IO address %Xh is empty!\n", ioaddr);
0225 ret = -EIO;
0226 goto err_free_arcdev;
0227 }
0228 if (com20020_check(dev)) {
0229 ret = -EIO;
0230 goto err_free_arcdev;
0231 }
0232
0233 card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev),
0234 GFP_KERNEL);
0235 if (!card) {
0236 ret = -ENOMEM;
0237 goto err_free_arcdev;
0238 }
0239
0240 card->index = i;
0241 card->pci_priv = priv;
0242 card->tx_led.brightness_set = led_tx_set;
0243 card->tx_led.default_trigger = devm_kasprintf(&pdev->dev,
0244 GFP_KERNEL, "arc%d-%d-tx",
0245 dev->dev_id, i);
0246 card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
0247 "pci:green:tx:%d-%d",
0248 dev->dev_id, i);
0249
0250 card->tx_led.dev = &dev->dev;
0251 card->recon_led.brightness_set = led_recon_set;
0252 card->recon_led.default_trigger = devm_kasprintf(&pdev->dev,
0253 GFP_KERNEL, "arc%d-%d-recon",
0254 dev->dev_id, i);
0255 card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
0256 "pci:red:recon:%d-%d",
0257 dev->dev_id, i);
0258 card->recon_led.dev = &dev->dev;
0259 card->dev = dev;
0260
0261 ret = devm_led_classdev_register(&pdev->dev, &card->tx_led);
0262 if (ret)
0263 goto err_free_arcdev;
0264
0265 ret = devm_led_classdev_register(&pdev->dev, &card->recon_led);
0266 if (ret)
0267 goto err_free_arcdev;
0268
0269 dev_set_drvdata(&dev->dev, card);
0270
0271 ret = com20020_found(dev, IRQF_SHARED);
0272 if (ret)
0273 goto err_free_arcdev;
0274
0275 devm_arcnet_led_init(dev, dev->dev_id, i);
0276
0277 list_add(&card->list, &priv->list_dev);
0278 continue;
0279
0280 err_free_arcdev:
0281 free_arcdev(dev);
0282 break;
0283 }
0284 if (ret)
0285 com20020pci_remove(pdev);
0286 return ret;
0287 }
0288
0289 static void com20020pci_remove(struct pci_dev *pdev)
0290 {
0291 struct com20020_dev *card, *tmpcard;
0292 struct com20020_priv *priv;
0293
0294 priv = pci_get_drvdata(pdev);
0295
0296 list_for_each_entry_safe(card, tmpcard, &priv->list_dev, list) {
0297 struct net_device *dev = card->dev;
0298
0299 unregister_netdev(dev);
0300 free_irq(dev->irq, dev);
0301 free_arcdev(dev);
0302 }
0303 }
0304
0305 static struct com20020_pci_card_info card_info_10mbit = {
0306 .name = "ARC-PCI",
0307 .devcount = 1,
0308 .chan_map_tbl = {
0309 {
0310 .bar = 2,
0311 .offset = 0x00,
0312 .size = 0x08,
0313 },
0314 },
0315 .flags = ARC_CAN_10MBIT,
0316 };
0317
0318 static struct com20020_pci_card_info card_info_5mbit = {
0319 .name = "ARC-PCI",
0320 .devcount = 1,
0321 .chan_map_tbl = {
0322 {
0323 .bar = 2,
0324 .offset = 0x00,
0325 .size = 0x08,
0326 },
0327 },
0328 .flags = ARC_IS_5MBIT,
0329 };
0330
0331 static struct com20020_pci_card_info card_info_sohard = {
0332 .name = "PLX-PCI",
0333 .devcount = 1,
0334
0335 .chan_map_tbl = {
0336 {
0337 .bar = 4,
0338 .offset = 0x00,
0339 .size = 0x08
0340 },
0341 },
0342 .flags = ARC_CAN_10MBIT,
0343 };
0344
0345 static struct com20020_pci_card_info card_info_eae_arc1 = {
0346 .name = "EAE PLX-PCI ARC1",
0347 .devcount = 1,
0348 .chan_map_tbl = {
0349 {
0350 .bar = 2,
0351 .offset = 0x00,
0352 .size = 0x08,
0353 },
0354 },
0355 .misc_map = {
0356 .bar = 2,
0357 .offset = 0x10,
0358 .size = 0x04,
0359 },
0360 .leds = {
0361 {
0362 .green = 0x0,
0363 .red = 0x1,
0364 },
0365 },
0366 .rotary = 0x0,
0367 .flags = ARC_CAN_10MBIT,
0368 };
0369
0370 static struct com20020_pci_card_info card_info_eae_ma1 = {
0371 .name = "EAE PLX-PCI MA1",
0372 .devcount = 2,
0373 .chan_map_tbl = {
0374 {
0375 .bar = 2,
0376 .offset = 0x00,
0377 .size = 0x08,
0378 }, {
0379 .bar = 2,
0380 .offset = 0x08,
0381 .size = 0x08,
0382 }
0383 },
0384 .misc_map = {
0385 .bar = 2,
0386 .offset = 0x10,
0387 .size = 0x04,
0388 },
0389 .leds = {
0390 {
0391 .green = 0x0,
0392 .red = 0x1,
0393 }, {
0394 .green = 0x2,
0395 .red = 0x3,
0396 },
0397 },
0398 .rotary = 0x0,
0399 .flags = ARC_CAN_10MBIT,
0400 };
0401
0402 static struct com20020_pci_card_info card_info_eae_fb2 = {
0403 .name = "EAE PLX-PCI FB2",
0404 .devcount = 1,
0405 .chan_map_tbl = {
0406 {
0407 .bar = 2,
0408 .offset = 0x00,
0409 .size = 0x08,
0410 },
0411 },
0412 .misc_map = {
0413 .bar = 2,
0414 .offset = 0x10,
0415 .size = 0x04,
0416 },
0417 .leds = {
0418 {
0419 .green = 0x0,
0420 .red = 0x1,
0421 },
0422 },
0423 .rotary = 0x0,
0424 .flags = ARC_CAN_10MBIT,
0425 };
0426
0427 static const struct pci_device_id com20020pci_id_table[] = {
0428 {
0429 0x1571, 0xa001,
0430 PCI_ANY_ID, PCI_ANY_ID,
0431 0, 0,
0432 0,
0433 },
0434 {
0435 0x1571, 0xa002,
0436 PCI_ANY_ID, PCI_ANY_ID,
0437 0, 0,
0438 0,
0439 },
0440 {
0441 0x1571, 0xa003,
0442 PCI_ANY_ID, PCI_ANY_ID,
0443 0, 0,
0444 0
0445 },
0446 {
0447 0x1571, 0xa004,
0448 PCI_ANY_ID, PCI_ANY_ID,
0449 0, 0,
0450 0,
0451 },
0452 {
0453 0x1571, 0xa005,
0454 PCI_ANY_ID, PCI_ANY_ID,
0455 0, 0,
0456 0
0457 },
0458 {
0459 0x1571, 0xa006,
0460 PCI_ANY_ID, PCI_ANY_ID,
0461 0, 0,
0462 0
0463 },
0464 {
0465 0x1571, 0xa007,
0466 PCI_ANY_ID, PCI_ANY_ID,
0467 0, 0,
0468 0
0469 },
0470 {
0471 0x1571, 0xa008,
0472 PCI_ANY_ID, PCI_ANY_ID,
0473 0, 0,
0474 0
0475 },
0476 {
0477 0x1571, 0xa009,
0478 PCI_ANY_ID, PCI_ANY_ID,
0479 0, 0,
0480 (kernel_ulong_t)&card_info_5mbit
0481 },
0482 {
0483 0x1571, 0xa00a,
0484 PCI_ANY_ID, PCI_ANY_ID,
0485 0, 0,
0486 (kernel_ulong_t)&card_info_5mbit
0487 },
0488 {
0489 0x1571, 0xa00b,
0490 PCI_ANY_ID, PCI_ANY_ID,
0491 0, 0,
0492 (kernel_ulong_t)&card_info_5mbit
0493 },
0494 {
0495 0x1571, 0xa00c,
0496 PCI_ANY_ID, PCI_ANY_ID,
0497 0, 0,
0498 (kernel_ulong_t)&card_info_5mbit
0499 },
0500 {
0501 0x1571, 0xa00d,
0502 PCI_ANY_ID, PCI_ANY_ID,
0503 0, 0,
0504 (kernel_ulong_t)&card_info_5mbit
0505 },
0506 {
0507 0x1571, 0xa00e,
0508 PCI_ANY_ID, PCI_ANY_ID,
0509 0, 0,
0510 (kernel_ulong_t)&card_info_5mbit
0511 },
0512 {
0513 0x1571, 0xa201,
0514 PCI_ANY_ID, PCI_ANY_ID,
0515 0, 0,
0516 (kernel_ulong_t)&card_info_10mbit
0517 },
0518 {
0519 0x1571, 0xa202,
0520 PCI_ANY_ID, PCI_ANY_ID,
0521 0, 0,
0522 (kernel_ulong_t)&card_info_10mbit
0523 },
0524 {
0525 0x1571, 0xa203,
0526 PCI_ANY_ID, PCI_ANY_ID,
0527 0, 0,
0528 (kernel_ulong_t)&card_info_10mbit
0529 },
0530 {
0531 0x1571, 0xa204,
0532 PCI_ANY_ID, PCI_ANY_ID,
0533 0, 0,
0534 (kernel_ulong_t)&card_info_10mbit
0535 },
0536 {
0537 0x1571, 0xa205,
0538 PCI_ANY_ID, PCI_ANY_ID,
0539 0, 0,
0540 (kernel_ulong_t)&card_info_10mbit
0541 },
0542 {
0543 0x1571, 0xa206,
0544 PCI_ANY_ID, PCI_ANY_ID,
0545 0, 0,
0546 (kernel_ulong_t)&card_info_10mbit
0547 },
0548 {
0549 0x10B5, 0x9030,
0550 0x10B5, 0x2978,
0551 0, 0,
0552 (kernel_ulong_t)&card_info_sohard
0553 },
0554 {
0555 0x10B5, 0x9050,
0556 0x10B5, 0x2273,
0557 0, 0,
0558 (kernel_ulong_t)&card_info_sohard
0559 },
0560 {
0561 0x10B5, 0x9050,
0562 0x10B5, 0x3263,
0563 0, 0,
0564 (kernel_ulong_t)&card_info_eae_arc1
0565 },
0566 {
0567 0x10B5, 0x9050,
0568 0x10B5, 0x3292,
0569 0, 0,
0570 (kernel_ulong_t)&card_info_eae_ma1
0571 },
0572 {
0573 0x10B5, 0x9050,
0574 0x10B5, 0x3294,
0575 0, 0,
0576 (kernel_ulong_t)&card_info_eae_fb2
0577 },
0578 {
0579 0x14BA, 0x6000,
0580 PCI_ANY_ID, PCI_ANY_ID,
0581 0, 0,
0582 (kernel_ulong_t)&card_info_10mbit
0583 },
0584 {
0585 0x10B5, 0x2200,
0586 PCI_ANY_ID, PCI_ANY_ID,
0587 0, 0,
0588 (kernel_ulong_t)&card_info_10mbit
0589 },
0590 { 0, }
0591 };
0592
0593 MODULE_DEVICE_TABLE(pci, com20020pci_id_table);
0594
0595 static struct pci_driver com20020pci_driver = {
0596 .name = "com20020",
0597 .id_table = com20020pci_id_table,
0598 .probe = com20020pci_probe,
0599 .remove = com20020pci_remove,
0600 };
0601
0602 static int __init com20020pci_init(void)
0603 {
0604 if (BUGLVL(D_NORMAL))
0605 pr_info("%s\n", "COM20020 PCI support");
0606 return pci_register_driver(&com20020pci_driver);
0607 }
0608
0609 static void __exit com20020pci_cleanup(void)
0610 {
0611 pci_unregister_driver(&com20020pci_driver);
0612 }
0613
0614 module_init(com20020pci_init)
0615 module_exit(com20020pci_cleanup)