Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / drivers / cb_pcidio.c
CommitLineData
028d4864
YM
1/*
2 comedi/drivers/cb_pcidio.c
3 A Comedi driver for PCI-DIO24H & PCI-DIO48H of ComputerBoards (currently MeasurementComputing)
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21
22*/
23/*
24Driver: cb_pcidio
25Description: ComputerBoards' DIO boards with PCI interface
26Devices: [Measurement Computing] PCI-DIO24 (cb_pcidio), PCI-DIO24H, PCI-DIO48H
27Author: Yoshiya Matsuzaka
28Updated: Mon, 29 Oct 2007 15:40:47 +0000
29Status: experimental
30
31This driver has been modified from skel.c of comedi-0.7.70.
32
33Configuration Options:
34 [0] - PCI bus of device (optional)
35 [1] - PCI slot of device (optional)
36 If bus/slot is not specified, the first available PCI device will
37 be used.
38
39Passing a zero for an option is the same as leaving it unspecified.
40*/
41
42/*------------------------------ HEADER FILES ---------------------------------*/
43#include "../comedidev.h"
44#include "comedi_pci.h"
45#include "8255.h"
46
47/*-------------------------- MACROS and DATATYPES -----------------------------*/
48#define PCI_VENDOR_ID_CB 0x1307
49
50/*
51 * Board descriptions for two imaginary boards. Describing the
52 * boards in this way is optional, and completely driver-dependent.
53 * Some drivers use arrays such as this, other do not.
54 */
c98d3deb 55struct pcidio_board {
aa65d22a
IA
56 const char *name; /* name of the board */
57 int dev_id;
2696fb57 58 int n_8255; /* number of 8255 chips on board */
028d4864 59
2696fb57 60 /* indices of base address regions */
028d4864
YM
61 int pcicontroler_badrindex;
62 int dioregs_badrindex;
c98d3deb 63};
028d4864 64
c98d3deb 65static const struct pcidio_board pcidio_boards[] = {
028d4864 66 {
0a85b6f0 67 .name = "pci-dio24",
aa65d22a 68 .dev_id = 0x0028,
0a85b6f0
MT
69 .n_8255 = 1,
70 .pcicontroler_badrindex = 1,
71 .dioregs_badrindex = 2,
72 },
028d4864 73 {
0a85b6f0 74 .name = "pci-dio24h",
aa65d22a 75 .dev_id = 0x0014,
0a85b6f0
MT
76 .n_8255 = 1,
77 .pcicontroler_badrindex = 1,
78 .dioregs_badrindex = 2,
79 },
028d4864 80 {
0a85b6f0 81 .name = "pci-dio48h",
aa65d22a 82 .dev_id = 0x000b,
0a85b6f0
MT
83 .n_8255 = 2,
84 .pcicontroler_badrindex = 0,
85 .dioregs_badrindex = 1,
86 },
028d4864
YM
87};
88
89/* This is used by modprobe to translate PCI IDs to drivers. Should
90 * only be used for PCI and ISA-PnP devices */
91/* Please add your PCI vendor ID to comedidev.h, and it will be forwarded
92 * upstream. */
93static DEFINE_PCI_DEVICE_TABLE(pcidio_pci_table) = {
0a85b6f0
MT
94 {
95 PCI_VENDOR_ID_CB, 0x0028, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
96 PCI_VENDOR_ID_CB, 0x0014, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
97 PCI_VENDOR_ID_CB, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
98 0}
028d4864
YM
99};
100
101MODULE_DEVICE_TABLE(pci, pcidio_pci_table);
102
103/*
104 * Useful for shorthand access to the particular board structure
105 */
c98d3deb 106#define thisboard ((const struct pcidio_board *)dev->board_ptr)
028d4864
YM
107
108/* this structure is for data unique to this hardware driver. If
109 several hardware drivers keep similar information in this structure,
71b5f4f1 110 feel free to suggest moving the variable to the struct comedi_device struct. */
fe7858af 111struct pcidio_private {
bbc9a991 112 int data; /* currently unused */
028d4864
YM
113
114 /* would be useful for a PCI device */
115 struct pci_dev *pci_dev;
116
bbc9a991 117 /* used for DO readback, currently unused */
790c5541 118 unsigned int do_readback[4]; /* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
028d4864 119
2696fb57 120 unsigned long dio_reg_base; /* address of port A of the first 8255 chip on board */
fe7858af 121};
028d4864
YM
122
123/*
124 * most drivers define the following macro to make it easy to
125 * access the private structure.
126 */
fe7858af 127#define devpriv ((struct pcidio_private *)dev->private)
028d4864
YM
128
129/*
139dfbdf 130 * The struct comedi_driver structure tells the Comedi core module
028d4864
YM
131 * which functions to call to configure/deconfigure (attach/detach)
132 * the board, and also about the kernel module that contains
133 * the device code.
134 */
0a85b6f0
MT
135static int pcidio_attach(struct comedi_device *dev,
136 struct comedi_devconfig *it);
da91b269 137static int pcidio_detach(struct comedi_device *dev);
139dfbdf 138static struct comedi_driver driver_cb_pcidio = {
68c3dbff
BP
139 .driver_name = "cb_pcidio",
140 .module = THIS_MODULE,
141 .attach = pcidio_attach,
142 .detach = pcidio_detach,
2696fb57 143
028d4864
YM
144/* It is not necessary to implement the following members if you are
145 * writing a driver for a ISA PnP or PCI card */
2696fb57 146
028d4864
YM
147 /* Most drivers will support multiple types of boards by
148 * having an array of board structures. These were defined
149 * in pcidio_boards[] above. Note that the element 'name'
150 * was first in the structure -- Comedi uses this fact to
151 * extract the name of the board without knowing any details
152 * about the structure except for its length.
153 * When a device is attached (by comedi_config), the name
154 * of the device is given to Comedi, and Comedi tries to
155 * match it by going through the list of board names. If
156 * there is a match, the address of the pointer is put
157 * into dev->board_ptr and driver->attach() is called.
158 *
159 * Note that these are not necessary if you can determine
160 * the type of board in software. ISA PnP, PCI, and PCMCIA
161 * devices are such boards.
162 */
2696fb57
BP
163
164/* The following fields should NOT be initialized if you are dealing
165 * with PCI devices
166 *
68c3dbff
BP
167 * .board_name = pcidio_boards,
168 * .offset = sizeof(struct pcidio_board),
169 * .num_names = sizeof(pcidio_boards) / sizeof(structpcidio_board),
2696fb57
BP
170 */
171
028d4864
YM
172};
173
174/*------------------------------- FUNCTIONS -----------------------------------*/
175
176/*
177 * Attach is called by the Comedi core to configure the driver
178 * for a particular board. If you specified a board_name array
179 * in the driver structure, dev->board_ptr contains that
180 * address.
181 */
da91b269 182static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
028d4864
YM
183{
184 struct pci_dev *pcidev = NULL;
185 int index;
186 int i;
187
188 printk("comedi%d: cb_pcidio: \n", dev->minor);
189
190/*
191 * Allocate the private structure area. alloc_private() is a
192 * convenient macro defined in comedidev.h.
193 */
fe7858af 194 if (alloc_private(dev, sizeof(struct pcidio_private)) < 0)
028d4864
YM
195 return -ENOMEM;
196/*
197 * If you can probe the device to determine what device in a series
198 * it is, this is the place to do it. Otherwise, dev->board_ptr
199 * should already be initialized.
200 */
201/*
202 * Probe the device to determine what device in the series it is.
203 */
204
20fb2280 205 for_each_pci_dev(pcidev) {
2696fb57 206 /* is it not a computer boards card? */
028d4864
YM
207 if (pcidev->vendor != PCI_VENDOR_ID_CB)
208 continue;
2696fb57 209 /* loop through cards supported by this driver */
0a85b6f0 210 for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
aa65d22a 211 if (pcidio_boards[index].dev_id != pcidev->device)
028d4864
YM
212 continue;
213
2696fb57 214 /* was a particular bus/slot requested? */
028d4864 215 if (it->options[0] || it->options[1]) {
2696fb57 216 /* are we on the wrong bus/slot? */
028d4864 217 if (pcidev->bus->number != it->options[0] ||
0a85b6f0 218 PCI_SLOT(pcidev->devfn) != it->options[1]) {
028d4864
YM
219 continue;
220 }
221 }
222 dev->board_ptr = pcidio_boards + index;
223 goto found;
224 }
225 }
226
227 printk("No supported ComputerBoards/MeasurementComputing card found on "
0a85b6f0 228 "requested position\n");
028d4864
YM
229 return -EIO;
230
0a85b6f0 231found:
028d4864
YM
232
233/*
234 * Initialize dev->board_name. Note that we can use the "thisboard"
235 * macro now, since we just initialized it in the last line.
236 */
237 dev->board_name = thisboard->name;
238
239 devpriv->pci_dev = pcidev;
240 printk("Found %s on bus %i, slot %i\n", thisboard->name,
0a85b6f0
MT
241 devpriv->pci_dev->bus->number,
242 PCI_SLOT(devpriv->pci_dev->devfn));
028d4864 243 if (comedi_pci_enable(pcidev, thisboard->name)) {
0a85b6f0
MT
244 printk
245 ("cb_pcidio: failed to enable PCI device and request regions\n");
028d4864
YM
246 return -EIO;
247 }
248 devpriv->dio_reg_base
0a85b6f0
MT
249 =
250 pci_resource_start(devpriv->pci_dev,
251 pcidio_boards[index].dioregs_badrindex);
028d4864
YM
252
253/*
254 * Allocate the subdevice structures. alloc_subdevice() is a
255 * convenient macro defined in comedidev.h.
256 */
257 if (alloc_subdevices(dev, thisboard->n_8255) < 0)
258 return -ENOMEM;
259
260 for (i = 0; i < thisboard->n_8255; i++) {
261 subdev_8255_init(dev, dev->subdevices + i,
0a85b6f0 262 NULL, devpriv->dio_reg_base + i * 4);
028d4864 263 printk(" subdev %d: base = 0x%lx\n", i,
0a85b6f0 264 devpriv->dio_reg_base + i * 4);
028d4864
YM
265 }
266
267 printk("attached\n");
268 return 1;
269}
270
271/*
272 * _detach is called to deconfigure a device. It should deallocate
273 * resources.
274 * This function is also called when _attach() fails, so it should be
275 * careful not to release resources that were not necessarily
276 * allocated by _attach(). dev->private and dev->subdevices are
277 * deallocated automatically by the core.
278 */
da91b269 279static int pcidio_detach(struct comedi_device *dev)
028d4864
YM
280{
281 printk("comedi%d: cb_pcidio: remove\n", dev->minor);
282 if (devpriv) {
283 if (devpriv->pci_dev) {
e3a21d0a 284 if (devpriv->dio_reg_base)
028d4864 285 comedi_pci_disable(devpriv->pci_dev);
028d4864
YM
286 pci_dev_put(devpriv->pci_dev);
287 }
288 }
289 if (dev->subdevices) {
290 int i;
e3a21d0a 291 for (i = 0; i < thisboard->n_8255; i++)
028d4864 292 subdev_8255_cleanup(dev, dev->subdevices + i);
028d4864
YM
293 }
294 return 0;
295}
296
297/*
298 * A convenient macro that defines init_module() and cleanup_module(),
299 * as necessary.
300 */
727b286b
AT
301static int __devinit driver_cb_pcidio_pci_probe(struct pci_dev *dev,
302 const struct pci_device_id *ent)
303{
304 return comedi_pci_auto_config(dev, driver_cb_pcidio.driver_name);
305}
306
307static void __devexit driver_cb_pcidio_pci_remove(struct pci_dev *dev)
308{
309 comedi_pci_auto_unconfig(dev);
310}
311
312static struct pci_driver driver_cb_pcidio_pci_driver = {
313 .id_table = pcidio_pci_table,
314 .probe = &driver_cb_pcidio_pci_probe,
315 .remove = __devexit_p(&driver_cb_pcidio_pci_remove)
316};
317
318static int __init driver_cb_pcidio_init_module(void)
319{
320 int retval;
321
322 retval = comedi_driver_register(&driver_cb_pcidio);
323 if (retval < 0)
324 return retval;
325
326 driver_cb_pcidio_pci_driver.name = (char *)driver_cb_pcidio.driver_name;
327 return pci_register_driver(&driver_cb_pcidio_pci_driver);
328}
329
330static void __exit driver_cb_pcidio_cleanup_module(void)
331{
332 pci_unregister_driver(&driver_cb_pcidio_pci_driver);
333 comedi_driver_unregister(&driver_cb_pcidio);
334}
335
336module_init(driver_cb_pcidio_init_module);
337module_exit(driver_cb_pcidio_cleanup_module);
90f703d3
AT
338
339MODULE_AUTHOR("Comedi http://www.comedi.org");
340MODULE_DESCRIPTION("Comedi low-level driver");
341MODULE_LICENSE("GPL");