staging: comedi: propogate error code from comedi_alloc_subdevices
[deliverable/linux.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"
028d4864
YM
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 */
c98d3deb 54struct pcidio_board {
aa65d22a
IA
55 const char *name; /* name of the board */
56 int dev_id;
2696fb57 57 int n_8255; /* number of 8255 chips on board */
028d4864 58
2696fb57 59 /* indices of base address regions */
028d4864
YM
60 int pcicontroler_badrindex;
61 int dioregs_badrindex;
c98d3deb 62};
028d4864 63
c98d3deb 64static const struct pcidio_board pcidio_boards[] = {
028d4864 65 {
0a85b6f0 66 .name = "pci-dio24",
aa65d22a 67 .dev_id = 0x0028,
0a85b6f0
MT
68 .n_8255 = 1,
69 .pcicontroler_badrindex = 1,
70 .dioregs_badrindex = 2,
71 },
028d4864 72 {
0a85b6f0 73 .name = "pci-dio24h",
aa65d22a 74 .dev_id = 0x0014,
0a85b6f0
MT
75 .n_8255 = 1,
76 .pcicontroler_badrindex = 1,
77 .dioregs_badrindex = 2,
78 },
028d4864 79 {
0a85b6f0 80 .name = "pci-dio48h",
aa65d22a 81 .dev_id = 0x000b,
0a85b6f0
MT
82 .n_8255 = 2,
83 .pcicontroler_badrindex = 0,
84 .dioregs_badrindex = 1,
85 },
028d4864
YM
86};
87
028d4864
YM
88/*
89 * Useful for shorthand access to the particular board structure
90 */
c98d3deb 91#define thisboard ((const struct pcidio_board *)dev->board_ptr)
028d4864
YM
92
93/* this structure is for data unique to this hardware driver. If
94 several hardware drivers keep similar information in this structure,
71b5f4f1 95 feel free to suggest moving the variable to the struct comedi_device struct. */
fe7858af 96struct pcidio_private {
bbc9a991 97 int data; /* currently unused */
028d4864
YM
98
99 /* would be useful for a PCI device */
100 struct pci_dev *pci_dev;
101
bbc9a991 102 /* used for DO readback, currently unused */
790c5541 103 unsigned int do_readback[4]; /* up to 4 unsigned int suffice to hold 96 bits for PCI-DIO96 */
028d4864 104
2696fb57 105 unsigned long dio_reg_base; /* address of port A of the first 8255 chip on board */
fe7858af 106};
028d4864
YM
107
108/*
109 * most drivers define the following macro to make it easy to
110 * access the private structure.
111 */
fe7858af 112#define devpriv ((struct pcidio_private *)dev->private)
028d4864 113
da91b269 114static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
028d4864
YM
115{
116 struct pci_dev *pcidev = NULL;
117 int index;
118 int i;
8b6c5694 119 int ret;
028d4864 120
028d4864
YM
121/*
122 * Allocate the private structure area. alloc_private() is a
123 * convenient macro defined in comedidev.h.
124 */
fe7858af 125 if (alloc_private(dev, sizeof(struct pcidio_private)) < 0)
028d4864
YM
126 return -ENOMEM;
127/*
128 * If you can probe the device to determine what device in a series
129 * it is, this is the place to do it. Otherwise, dev->board_ptr
130 * should already be initialized.
131 */
132/*
133 * Probe the device to determine what device in the series it is.
134 */
135
20fb2280 136 for_each_pci_dev(pcidev) {
2696fb57 137 /* is it not a computer boards card? */
028d4864
YM
138 if (pcidev->vendor != PCI_VENDOR_ID_CB)
139 continue;
2696fb57 140 /* loop through cards supported by this driver */
0a85b6f0 141 for (index = 0; index < ARRAY_SIZE(pcidio_boards); index++) {
aa65d22a 142 if (pcidio_boards[index].dev_id != pcidev->device)
028d4864
YM
143 continue;
144
2696fb57 145 /* was a particular bus/slot requested? */
028d4864 146 if (it->options[0] || it->options[1]) {
2696fb57 147 /* are we on the wrong bus/slot? */
028d4864 148 if (pcidev->bus->number != it->options[0] ||
0a85b6f0 149 PCI_SLOT(pcidev->devfn) != it->options[1]) {
028d4864
YM
150 continue;
151 }
152 }
153 dev->board_ptr = pcidio_boards + index;
154 goto found;
155 }
156 }
157
610b8ed9 158 dev_err(dev->hw_dev, "No supported ComputerBoards/MeasurementComputing card found on requested position\n");
028d4864
YM
159 return -EIO;
160
0a85b6f0 161found:
028d4864
YM
162
163/*
164 * Initialize dev->board_name. Note that we can use the "thisboard"
165 * macro now, since we just initialized it in the last line.
166 */
167 dev->board_name = thisboard->name;
168
169 devpriv->pci_dev = pcidev;
610b8ed9
RM
170 dev_dbg(dev->hw_dev, "Found %s on bus %i, slot %i\n", thisboard->name,
171 devpriv->pci_dev->bus->number,
172 PCI_SLOT(devpriv->pci_dev->devfn));
173 if (comedi_pci_enable(pcidev, thisboard->name))
028d4864 174 return -EIO;
610b8ed9 175
028d4864 176 devpriv->dio_reg_base
0a85b6f0
MT
177 =
178 pci_resource_start(devpriv->pci_dev,
179 pcidio_boards[index].dioregs_badrindex);
028d4864 180
8b6c5694
HS
181 ret = comedi_alloc_subdevices(dev, thisboard->n_8255);
182 if (ret)
183 return ret;
028d4864
YM
184
185 for (i = 0; i < thisboard->n_8255; i++) {
186 subdev_8255_init(dev, dev->subdevices + i,
0a85b6f0 187 NULL, devpriv->dio_reg_base + i * 4);
610b8ed9
RM
188 dev_dbg(dev->hw_dev, "subdev %d: base = 0x%lx\n", i,
189 devpriv->dio_reg_base + i * 4);
028d4864
YM
190 }
191
028d4864
YM
192 return 1;
193}
194
484ecc95 195static void pcidio_detach(struct comedi_device *dev)
028d4864 196{
028d4864
YM
197 if (devpriv) {
198 if (devpriv->pci_dev) {
e3a21d0a 199 if (devpriv->dio_reg_base)
028d4864 200 comedi_pci_disable(devpriv->pci_dev);
028d4864
YM
201 pci_dev_put(devpriv->pci_dev);
202 }
203 }
204 if (dev->subdevices) {
205 int i;
e3a21d0a 206 for (i = 0; i < thisboard->n_8255; i++)
028d4864 207 subdev_8255_cleanup(dev, dev->subdevices + i);
028d4864 208 }
028d4864
YM
209}
210
b93707d6
HS
211static struct comedi_driver cb_pcidio_driver = {
212 .driver_name = "cb_pcidio",
213 .module = THIS_MODULE,
214 .attach = pcidio_attach,
215 .detach = pcidio_detach,
216};
217
218static int __devinit cb_pcidio_pci_probe(struct pci_dev *dev,
727b286b
AT
219 const struct pci_device_id *ent)
220{
b93707d6 221 return comedi_pci_auto_config(dev, &cb_pcidio_driver);
727b286b
AT
222}
223
b93707d6 224static void __devexit cb_pcidio_pci_remove(struct pci_dev *dev)
727b286b
AT
225{
226 comedi_pci_auto_unconfig(dev);
227}
228
b93707d6
HS
229static DEFINE_PCI_DEVICE_TABLE(cb_pcidio_pci_table) = {
230 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0028) },
231 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0014) },
232 { PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000b) },
233 { 0 }
727b286b 234};
b93707d6 235MODULE_DEVICE_TABLE(pci, cb_pcidio_pci_table);
727b286b 236
b93707d6
HS
237static struct pci_driver cb_pcidio_pci_driver = {
238 .name = "cb_pcidio",
239 .id_table = cb_pcidio_pci_table,
240 .probe = cb_pcidio_pci_probe,
241 .remove = __devexit_p(cb_pcidio_pci_remove),
242};
243module_comedi_pci_driver(cb_pcidio_driver, cb_pcidio_pci_driver);
90f703d3
AT
244
245MODULE_AUTHOR("Comedi http://www.comedi.org");
246MODULE_DESCRIPTION("Comedi low-level driver");
247MODULE_LICENSE("GPL");
This page took 0.317463 seconds and 5 git commands to generate.