]>
Commit | Line | Data |
---|---|---|
bb71f8b3 | 1 | /* |
f7c22868 HS |
2 | * COMEDI driver for generic PCI based 8255 digital i/o boards |
3 | * Copyright (C) 2012 H Hartley Sweeten <hsweeten@visionengravers.com> | |
4 | * | |
5 | * Based on the tested adl_pci7296 driver written by: | |
6 | * Jon Grierson <jd@renko.co.uk> | |
32bb1544 HS |
7 | * |
8 | * COMEDI - Linux Control and Measurement Device Interface | |
9 | * Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or modify | |
12 | * it under the terms of the GNU General Public License as published by | |
13 | * the Free Software Foundation; either version 2 of the License, or | |
14 | * (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | * You should have received a copy of the GNU General Public License | |
22 | * along with this program; if not, write to the Free Software | |
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | */ | |
bb71f8b3 | 25 | |
bb71f8b3 | 26 | /* |
f7c22868 HS |
27 | Driver: 8255_pci |
28 | Description: Generic PCI based 8255 Digital I/O boards | |
29 | Devices: (ADLink) PCI-7224 [adl_pci-7224] - 24 channels | |
30 | (ADLink) PCI-7248 [adl_pci-7248] - 48 channels | |
31 | (ADLink) PCI-7296 [adl_pci-7296] - 96 channels | |
32 | Author: H Hartley Sweeten <hsweeten@visionengravers.com> | |
33 | Updated: Wed, 12 Sep 2012 11:52:01 -0700 | |
34 | Status: untested | |
35 | ||
36 | Some of these boards also have an 8254 programmable timer/counter | |
37 | chip. This chip is not currently supported by this driver. | |
32bb1544 HS |
38 | |
39 | Interrupt support for these boards is also not currently supported. | |
40 | ||
f7c22868 | 41 | Configuration Options: not applicable, uses PCI auto config |
bb71f8b3 JG |
42 | */ |
43 | ||
44 | #include "../comedidev.h" | |
bb71f8b3 | 45 | |
bb71f8b3 | 46 | #include "8255.h" |
bb71f8b3 | 47 | |
32bb1544 HS |
48 | /* |
49 | * PCI Device ID's supported by this driver | |
50 | */ | |
f7c22868 HS |
51 | #define PCI_DEVICE_ID_ADLINK_PCI7224 0x7224 |
52 | #define PCI_DEVICE_ID_ADLINK_PCI7248 0x7248 | |
53 | #define PCI_DEVICE_ID_ADLINK_PCI7296 0x7296 | |
32bb1544 | 54 | |
f7c22868 | 55 | struct pci_8255_boardinfo { |
32bb1544 HS |
56 | const char *name; |
57 | unsigned short device; | |
f7c22868 | 58 | int n_8255; |
32bb1544 | 59 | }; |
bb71f8b3 | 60 | |
f7c22868 | 61 | static const struct pci_8255_boardinfo pci_8255_boards[] = { |
32bb1544 | 62 | { |
f7c22868 HS |
63 | .name = "adl_pci-7224", |
64 | .device = PCI_DEVICE_ID_ADLINK_PCI7224, | |
65 | .n_8255 = 1, | |
32bb1544 | 66 | }, { |
f7c22868 HS |
67 | .name = "adl_pci-7248", |
68 | .device = PCI_DEVICE_ID_ADLINK_PCI7248, | |
69 | .n_8255 = 2, | |
32bb1544 | 70 | }, { |
f7c22868 HS |
71 | .name = "adl_pci-7296", |
72 | .device = PCI_DEVICE_ID_ADLINK_PCI7296, | |
73 | .n_8255 = 4, | |
32bb1544 HS |
74 | }, |
75 | }; | |
bb71f8b3 | 76 | |
f7c22868 | 77 | static const void *pci_8255_find_boardinfo(struct comedi_device *dev, |
32bb1544 | 78 | struct pci_dev *pcidev) |
262ea0d4 | 79 | { |
f7c22868 | 80 | const struct pci_8255_boardinfo *board; |
32bb1544 HS |
81 | int i; |
82 | ||
f7c22868 HS |
83 | for (i = 0; i < ARRAY_SIZE(pci_8255_boards); i++) { |
84 | board = &pci_8255_boards[i]; | |
32bb1544 HS |
85 | if (pcidev->device == board->device) |
86 | return board; | |
262ea0d4 | 87 | } |
262ea0d4 HS |
88 | return NULL; |
89 | } | |
90 | ||
f7c22868 HS |
91 | static int pci_8255_attach_pci(struct comedi_device *dev, |
92 | struct pci_dev *pcidev) | |
bb71f8b3 | 93 | { |
f7c22868 | 94 | const struct pci_8255_boardinfo *board; |
34c43922 | 95 | struct comedi_subdevice *s; |
bb71f8b3 | 96 | int ret; |
32bb1544 | 97 | int i; |
bb71f8b3 | 98 | |
32bb1544 | 99 | comedi_set_hw_dev(dev, &pcidev->dev); |
bb71f8b3 | 100 | |
f7c22868 | 101 | board = pci_8255_find_boardinfo(dev, pcidev); |
32bb1544 HS |
102 | if (!board) |
103 | return -ENODEV; | |
104 | dev->board_ptr = board; | |
105 | dev->board_name = board->name; | |
bb71f8b3 | 106 | |
32bb1544 | 107 | ret = comedi_pci_enable(pcidev, dev->board_name); |
8b6c5694 HS |
108 | if (ret) |
109 | return ret; | |
caeb2490 | 110 | dev->iobase = pci_resource_start(pcidev, 2); |
262ea0d4 | 111 | |
32bb1544 HS |
112 | /* |
113 | * One, two, or four subdevices are setup by this driver depending | |
114 | * on the number of channels provided by the board. Each subdevice | |
115 | * has 24 channels supported by the 8255 module. | |
116 | */ | |
f7c22868 | 117 | ret = comedi_alloc_subdevices(dev, board->n_8255); |
32bb1544 | 118 | if (ret) |
262ea0d4 HS |
119 | return ret; |
120 | ||
f7c22868 | 121 | for (i = 0; i < board->n_8255; i++) { |
630b713b | 122 | s = &dev->subdevices[i]; |
32bb1544 HS |
123 | ret = subdev_8255_init(dev, s, NULL, dev->iobase + (i * 4)); |
124 | if (ret) | |
125 | return ret; | |
126 | } | |
262ea0d4 | 127 | |
32bb1544 | 128 | dev_info(dev->class_dev, "%s attached (%d digital i/o channels)\n", |
f7c22868 | 129 | dev->board_name, board->n_8255 * 24); |
262ea0d4 HS |
130 | |
131 | return 0; | |
bb71f8b3 JG |
132 | } |
133 | ||
f7c22868 | 134 | static void pci_8255_detach(struct comedi_device *dev) |
bb71f8b3 | 135 | { |
caeb2490 | 136 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
f7c22868 | 137 | const struct pci_8255_boardinfo *board = comedi_board(dev); |
32bb1544 HS |
138 | struct comedi_subdevice *s; |
139 | int i; | |
caeb2490 | 140 | |
32bb1544 | 141 | if (dev->subdevices) { |
f7c22868 | 142 | for (i = 0; i < board->n_8255; i++) { |
630b713b | 143 | s = &dev->subdevices[i]; |
32bb1544 HS |
144 | subdev_8255_cleanup(dev, s); |
145 | } | |
146 | } | |
caeb2490 | 147 | if (pcidev) { |
1ab1774f | 148 | if (dev->iobase) |
caeb2490 | 149 | comedi_pci_disable(pcidev); |
bb71f8b3 | 150 | } |
bb71f8b3 JG |
151 | } |
152 | ||
f7c22868 HS |
153 | static struct comedi_driver pci_8255_driver = { |
154 | .driver_name = "8255_pci", | |
db0eaeed | 155 | .module = THIS_MODULE, |
f7c22868 HS |
156 | .attach_pci = pci_8255_attach_pci, |
157 | .detach = pci_8255_detach, | |
db0eaeed HS |
158 | }; |
159 | ||
f7c22868 HS |
160 | static int __devinit pci_8255_pci_probe(struct pci_dev *dev, |
161 | const struct pci_device_id *ent) | |
727b286b | 162 | { |
f7c22868 | 163 | return comedi_pci_auto_config(dev, &pci_8255_driver); |
727b286b AT |
164 | } |
165 | ||
f7c22868 | 166 | static void __devexit pci_8255_pci_remove(struct pci_dev *dev) |
727b286b AT |
167 | { |
168 | comedi_pci_auto_unconfig(dev); | |
169 | } | |
170 | ||
f7c22868 HS |
171 | static DEFINE_PCI_DEVICE_TABLE(pci_8255_pci_table) = { |
172 | { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7224) }, | |
173 | { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7248) }, | |
174 | { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_ADLINK_PCI7296) }, | |
75e6301b | 175 | { 0 } |
db0eaeed | 176 | }; |
f7c22868 | 177 | MODULE_DEVICE_TABLE(pci, pci_8255_pci_table); |
db0eaeed | 178 | |
f7c22868 HS |
179 | static struct pci_driver pci_8255_pci_driver = { |
180 | .name = "8255_pci", | |
181 | .id_table = pci_8255_pci_table, | |
182 | .probe = pci_8255_pci_probe, | |
183 | .remove = __devexit_p(pci_8255_pci_remove), | |
727b286b | 184 | }; |
f7c22868 | 185 | module_comedi_pci_driver(pci_8255_driver, pci_8255_pci_driver); |
90f703d3 | 186 | |
f7c22868 | 187 | MODULE_DESCRIPTION("COMEDI - Generic PCI based 8255 Digital I/O boards"); |
90f703d3 | 188 | MODULE_AUTHOR("Comedi http://www.comedi.org"); |
90f703d3 | 189 | MODULE_LICENSE("GPL"); |