1 /* 2 * Linux ARCnet driver - COM20020 PCI support 3 * Contemporary Controls PCI20 and SOHARD SH-ARC PCI 4 * 5 * Written 1994-1999 by Avery Pennarun, 6 * based on an ISA version by David Woodhouse. 7 * Written 1999-2000 by Martin Mares <mj@ucw.cz>. 8 * Derived from skeleton.c by Donald Becker. 9 * 10 * Special thanks to Contemporary Controls, Inc. (www.ccontrols.com) 11 * for sponsoring the further development of this driver. 12 * 13 * ********************** 14 * 15 * The original copyright of skeleton.c was as follows: 16 * 17 * skeleton.c Written 1993 by Donald Becker. 18 * Copyright 1993 United States Government as represented by the 19 * Director, National Security Agency. This software may only be used 20 * and distributed according to the terms of the GNU General Public License as 21 * modified by SRC, incorporated herein by reference. 22 * 23 * ********************** 24 * 25 * For more details, see drivers/net/arcnet.c 26 * 27 * ********************** 28 */ 29 #include <linux/module.h> 30 #include <linux/moduleparam.h> 31 #include <linux/kernel.h> 32 #include <linux/types.h> 33 #include <linux/ioport.h> 34 #include <linux/errno.h> 35 #include <linux/netdevice.h> 36 #include <linux/init.h> 37 #include <linux/pci.h> 38 #include <linux/arcdevice.h> 39 #include <linux/com20020.h> 40 41 #include <asm/io.h> 42 43 44 #define VERSION "arcnet: COM20020 PCI support\n" 45 46 /* Module parameters */ 47 48 static int node; 49 static char device[9]; /* use eg. device="arc1" to change name */ 50 static int timeout = 3; 51 static int backplane; 52 static int clockp; 53 static int clockm; 54 55 module_param(node, int, 0); 56 module_param_string(device, device, sizeof(device), 0); 57 module_param(timeout, int, 0); 58 module_param(backplane, int, 0); 59 module_param(clockp, int, 0); 60 module_param(clockm, int, 0); 61 MODULE_LICENSE("GPL"); 62 63 static int __devinit com20020pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) 64 { 65 struct net_device *dev; 66 struct arcnet_local *lp; 67 int ioaddr, err; 68 69 if (pci_enable_device(pdev)) 70 return -EIO; 71 dev = alloc_arcdev(device); 72 if (!dev) 73 return -ENOMEM; 74 75 dev->netdev_ops = &com20020_netdev_ops; 76 77 lp = netdev_priv(dev); 78 79 pci_set_drvdata(pdev, dev); 80 81 // SOHARD needs PCI base addr 4 82 if (pdev->vendor==0x10B5) { 83 BUGMSG(D_NORMAL, "SOHARD\n"); 84 ioaddr = pci_resource_start(pdev, 4); 85 } 86 else { 87 BUGMSG(D_NORMAL, "Contemporary Controls\n"); 88 ioaddr = pci_resource_start(pdev, 2); 89 } 90 91 if (!request_region(ioaddr, ARCNET_TOTAL_SIZE, "com20020-pci")) { 92 BUGMSG(D_INIT, "IO region %xh-%xh already allocated.\n", 93 ioaddr, ioaddr + ARCNET_TOTAL_SIZE - 1); 94 err = -EBUSY; 95 goto out_dev; 96 } 97 98 // Dummy access after Reset 99 // ARCNET controller needs this access to detect bustype 100 outb(0x00,ioaddr+1); 101 inb(ioaddr+1); 102 103 dev->base_addr = ioaddr; 104 dev->irq = pdev->irq; 105 dev->dev_addr[0] = node; 106 lp->card_name = "PCI COM20020"; 107 lp->card_flags = id->driver_data; 108 lp->backplane = backplane; 109 lp->clockp = clockp & 7; 110 lp->clockm = clockm & 3; 111 lp->timeout = timeout; 112 lp->hw.owner = THIS_MODULE; 113 114 if (ASTATUS() == 0xFF) { 115 BUGMSG(D_NORMAL, "IO address %Xh was reported by PCI BIOS, " 116 "but seems empty!\n", ioaddr); 117 err = -EIO; 118 goto out_port; 119 } 120 if (com20020_check(dev)) { 121 err = -EIO; 122 goto out_port; 123 } 124 125 if ((err = com20020_found(dev, IRQF_SHARED)) != 0) 126 goto out_port; 127 128 return 0; 129 130 out_port: 131 release_region(ioaddr, ARCNET_TOTAL_SIZE); 132 out_dev: 133 free_netdev(dev); 134 return err; 135 } 136 137 static void __devexit com20020pci_remove(struct pci_dev *pdev) 138 { 139 struct net_device *dev = pci_get_drvdata(pdev); 140 unregister_netdev(dev); 141 free_irq(dev->irq, dev); 142 release_region(dev->base_addr, ARCNET_TOTAL_SIZE); 143 free_netdev(dev); 144 } 145 146 static DEFINE_PCI_DEVICE_TABLE(com20020pci_id_table) = { 147 { 0x1571, 0xa001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 148 { 0x1571, 0xa002, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 149 { 0x1571, 0xa003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 150 { 0x1571, 0xa004, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 151 { 0x1571, 0xa005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 152 { 0x1571, 0xa006, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 153 { 0x1571, 0xa007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 154 { 0x1571, 0xa008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 155 { 0x1571, 0xa009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 156 { 0x1571, 0xa00a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 157 { 0x1571, 0xa00b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 158 { 0x1571, 0xa00c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 159 { 0x1571, 0xa00d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 160 { 0x1571, 0xa00e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_IS_5MBIT }, 161 { 0x1571, 0xa201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 162 { 0x1571, 0xa202, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 163 { 0x1571, 0xa203, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 164 { 0x1571, 0xa204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 165 { 0x1571, 0xa205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 166 { 0x1571, 0xa206, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 167 { 0x10B5, 0x9030, 0x10B5, 0x2978, 0, 0, ARC_CAN_10MBIT }, 168 { 0x10B5, 0x9050, 0x10B5, 0x2273, 0, 0, ARC_CAN_10MBIT }, 169 { 0x14BA, 0x6000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 170 { 0x10B5, 0x2200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ARC_CAN_10MBIT }, 171 {0,} 172 }; 173 174 MODULE_DEVICE_TABLE(pci, com20020pci_id_table); 175 176 static struct pci_driver com20020pci_driver = { 177 .name = "com20020", 178 .id_table = com20020pci_id_table, 179 .probe = com20020pci_probe, 180 .remove = __devexit_p(com20020pci_remove), 181 }; 182 183 static int __init com20020pci_init(void) 184 { 185 BUGLVL(D_NORMAL) printk(VERSION); 186 return pci_register_driver(&com20020pci_driver); 187 } 188 189 static void __exit com20020pci_cleanup(void) 190 { 191 pci_unregister_driver(&com20020pci_driver); 192 } 193 194 module_init(com20020pci_init) 195 module_exit(com20020pci_cleanup) 196