]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/comedi/drivers/cb_pcidio.c
Merge tag 'sound-3.6' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
[karo-tx-linux.git] / drivers / staging / comedi / drivers / cb_pcidio.c
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 /*
24 Driver: cb_pcidio
25 Description: ComputerBoards' DIO boards with PCI interface
26 Devices: [Measurement Computing] PCI-DIO24 (cb_pcidio), PCI-DIO24H, PCI-DIO48H
27 Author: Yoshiya Matsuzaka
28 Updated: Mon, 29 Oct 2007 15:40:47 +0000
29 Status: experimental
30
31 This driver has been modified from skel.c of comedi-0.7.70.
32
33 Configuration 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
39 Passing a zero for an option is the same as leaving it unspecified.
40 */
41
42 /*------------------------------ HEADER FILES ---------------------------------*/
43 #include "../comedidev.h"
44 #include "8255.h"
45
46 /*-------------------------- MACROS and DATATYPES -----------------------------*/
47 #define PCI_VENDOR_ID_CB        0x1307
48
49 /*
50  * Board descriptions for two imaginary boards.  Describing the
51  * boards in this way is optional, and completely driver-dependent.
52  * Some drivers use arrays such as this, other do not.
53  */
54 struct pcidio_board {
55         const char *name;       /*  name of the board */
56         int dev_id;
57         int n_8255;             /*  number of 8255 chips on board */
58
59         /*  indices of base address regions */
60         int pcicontroler_badrindex;
61         int dioregs_badrindex;
62 };
63
64 static const struct pcidio_board pcidio_boards[] = {
65         {
66          .name = "pci-dio24",
67          .dev_id = 0x0028,
68          .n_8255 = 1,
69          .pcicontroler_badrindex = 1,
70          .dioregs_badrindex = 2,
71          },
72         {
73          .name = "pci-dio24h",
74          .dev_id = 0x0014,
75          .n_8255 = 1,
76          .pcicontroler_badrindex = 1,
77          .dioregs_badrindex = 2,
78          },
79         {
80          .name = "pci-dio48h",
81          .dev_id = 0x000b,
82          .n_8255 = 2,
83          .pcicontroler_badrindex = 0,
84          .dioregs_badrindex = 1,
85          },
86 };
87
88 /*
89  * Useful for shorthand access to the particular board structure
90  */
91 #define thisboard ((const struct pcidio_board *)dev->board_ptr)
92
93 static struct pci_dev *pcidio_find_pci_dev(struct comedi_device *dev,
94                                            struct comedi_devconfig *it)
95 {
96         struct pci_dev *pcidev = NULL;
97         int bus = it->options[0];
98         int slot = it->options[1];
99         int i;
100
101         for_each_pci_dev(pcidev) {
102                 if (bus || slot) {
103                         if (bus != pcidev->bus->number ||
104                                 slot != PCI_SLOT(pcidev->devfn))
105                                 continue;
106                 }
107                 if (pcidev->vendor != PCI_VENDOR_ID_CB)
108                         continue;
109                 for (i = 0; i < ARRAY_SIZE(pcidio_boards); i++) {
110                         if (pcidio_boards[i].dev_id != pcidev->device)
111                                 continue;
112
113                         dev->board_ptr = pcidio_boards + i;
114                         return pcidev;
115                 }
116         }
117         dev_err(dev->class_dev,
118                 "No supported board found! (req. bus %d, slot %d)\n",
119                 bus, slot);
120         return NULL;
121 }
122
123 static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
124 {
125         struct pci_dev *pcidev;
126         int i;
127         int ret;
128
129         pcidev = pcidio_find_pci_dev(dev, it);
130         if (!pcidev)
131                 return -EIO;
132         comedi_set_hw_dev(dev, &pcidev->dev);
133
134 /*
135  * Initialize dev->board_name.  Note that we can use the "thisboard"
136  * macro now, since we just initialized it in the last line.
137  */
138         dev->board_name = thisboard->name;
139
140         if (comedi_pci_enable(pcidev, thisboard->name))
141                 return -EIO;
142
143         dev->iobase = pci_resource_start(pcidev, thisboard->dioregs_badrindex);
144
145         ret = comedi_alloc_subdevices(dev, thisboard->n_8255);
146         if (ret)
147                 return ret;
148
149         for (i = 0; i < thisboard->n_8255; i++) {
150                 subdev_8255_init(dev, dev->subdevices + i,
151                                  NULL, dev->iobase + i * 4);
152                 dev_dbg(dev->class_dev, "subdev %d: base = 0x%lx\n", i,
153                         dev->iobase + i * 4);
154         }
155
156         return 1;
157 }
158
159 static void pcidio_detach(struct comedi_device *dev)
160 {
161         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
162
163         if (pcidev) {
164                 if (dev->iobase)
165                         comedi_pci_disable(pcidev);
166                 pci_dev_put(pcidev);
167         }
168         if (dev->subdevices) {
169                 int i;
170                 for (i = 0; i < thisboard->n_8255; i++)
171                         subdev_8255_cleanup(dev, dev->subdevices + i);
172         }
173 }
174
175 static struct comedi_driver cb_pcidio_driver = {
176         .driver_name    = "cb_pcidio",
177         .module         = THIS_MODULE,
178         .attach         = pcidio_attach,
179         .detach         = pcidio_detach,
180 };
181
182 static int __devinit cb_pcidio_pci_probe(struct pci_dev *dev,
183                                                 const struct pci_device_id *ent)
184 {
185         return comedi_pci_auto_config(dev, &cb_pcidio_driver);
186 }
187
188 static void __devexit cb_pcidio_pci_remove(struct pci_dev *dev)
189 {
190         comedi_pci_auto_unconfig(dev);
191 }
192
193 static DEFINE_PCI_DEVICE_TABLE(cb_pcidio_pci_table) = {
194         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
195         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
196         { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
197         { 0 }
198 };
199 MODULE_DEVICE_TABLE(pci, cb_pcidio_pci_table);
200
201 static struct pci_driver cb_pcidio_pci_driver = {
202         .name           = "cb_pcidio",
203         .id_table       = cb_pcidio_pci_table,
204         .probe          = cb_pcidio_pci_probe,
205         .remove         = __devexit_p(cb_pcidio_pci_remove),
206 };
207 module_comedi_pci_driver(cb_pcidio_driver, cb_pcidio_pci_driver);
208
209 MODULE_AUTHOR("Comedi http://www.comedi.org");
210 MODULE_DESCRIPTION("Comedi low-level driver");
211 MODULE_LICENSE("GPL");