Commit | Line | Data |
---|---|---|
bb71f8b3 JG |
1 | /* |
2 | comedi/drivers/adl_pci7296.c | |
3 | ||
4 | COMEDI - Linux Control and Measurement Device Interface | |
5 | Copyright (C) 2000 David A. Schleef <ds@schleef.org> | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | ||
21 | */ | |
22 | /* | |
23 | Driver: adl_pci7296 | |
24 | Description: Driver for the Adlink PCI-7296 96 ch. digital io board | |
25 | Devices: [ADLink] PCI-7296 (adl_pci7296) | |
26 | Author: Jon Grierson <jd@renko.co.uk> | |
27 | Updated: Mon, 14 Apr 2008 15:05:56 +0100 | |
28 | Status: testing | |
29 | ||
30 | Configuration Options: | |
31 | [0] - PCI bus of device (optional) | |
32 | [1] - PCI slot of device (optional) | |
33 | If bus/slot is not specified, the first supported | |
34 | PCI device found will be used. | |
35 | */ | |
36 | ||
37 | #include "../comedidev.h" | |
38 | #include <linux/kernel.h> | |
39 | ||
40 | #include "comedi_pci.h" | |
41 | #include "8255.h" | |
42 | // #include "8253.h" | |
43 | ||
44 | #define PORT1A 0 | |
45 | #define PORT2A 4 | |
46 | #define PORT3A 8 | |
47 | #define PORT4A 12 | |
48 | ||
49 | #define PCI_DEVICE_ID_PCI7296 0x7296 | |
50 | ||
51 | static DEFINE_PCI_DEVICE_TABLE(adl_pci7296_pci_table) = { | |
52 | {PCI_VENDOR_ID_ADLINK, PCI_DEVICE_ID_PCI7296, PCI_ANY_ID, PCI_ANY_ID, 0, | |
53 | 0, 0}, | |
54 | {0} | |
55 | }; | |
56 | ||
57 | MODULE_DEVICE_TABLE(pci, adl_pci7296_pci_table); | |
58 | ||
59 | typedef struct { | |
60 | int data; | |
61 | struct pci_dev *pci_dev; | |
62 | } adl_pci7296_private; | |
63 | ||
64 | #define devpriv ((adl_pci7296_private *)dev->private) | |
65 | ||
71b5f4f1 BP |
66 | static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it); |
67 | static int adl_pci7296_detach(struct comedi_device * dev); | |
bb71f8b3 JG |
68 | static comedi_driver driver_adl_pci7296 = { |
69 | driver_name:"adl_pci7296", | |
70 | module:THIS_MODULE, | |
71 | attach:adl_pci7296_attach, | |
72 | detach:adl_pci7296_detach, | |
73 | }; | |
74 | ||
71b5f4f1 | 75 | static int adl_pci7296_attach(struct comedi_device * dev, comedi_devconfig * it) |
bb71f8b3 JG |
76 | { |
77 | struct pci_dev *pcidev; | |
78 | comedi_subdevice *s; | |
79 | int bus, slot; | |
80 | int ret; | |
81 | ||
82 | printk("comedi: attempt to attach...\n"); | |
83 | printk("comedi%d: adl_pci7432\n", dev->minor); | |
84 | ||
85 | dev->board_name = "pci7432"; | |
86 | bus = it->options[0]; | |
87 | slot = it->options[1]; | |
88 | ||
89 | if (alloc_private(dev, sizeof(adl_pci7296_private)) < 0) | |
90 | return -ENOMEM; | |
91 | ||
92 | if (alloc_subdevices(dev, 4) < 0) | |
93 | return -ENOMEM; | |
94 | ||
95 | for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); | |
96 | pcidev != NULL; | |
97 | pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) { | |
98 | ||
99 | if (pcidev->vendor == PCI_VENDOR_ID_ADLINK && | |
100 | pcidev->device == PCI_DEVICE_ID_PCI7296) { | |
101 | if (bus || slot) { | |
102 | /* requested particular bus/slot */ | |
103 | if (pcidev->bus->number != bus | |
104 | || PCI_SLOT(pcidev->devfn) != slot) { | |
105 | continue; | |
106 | } | |
107 | } | |
108 | devpriv->pci_dev = pcidev; | |
109 | if (comedi_pci_enable(pcidev, "adl_pci7296") < 0) { | |
110 | printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor); | |
111 | return -EIO; | |
112 | } | |
113 | ||
114 | dev->iobase = pci_resource_start(pcidev, 2); | |
115 | printk("comedi: base addr %4lx\n", dev->iobase); | |
116 | ||
117 | // four 8255 digital io subdevices | |
118 | s = dev->subdevices + 0; | |
119 | subdev_8255_init(dev, s, NULL, | |
120 | (unsigned long)(dev->iobase)); | |
121 | ||
122 | s = dev->subdevices + 1; | |
123 | ret = subdev_8255_init(dev, s, NULL, | |
124 | (unsigned long)(dev->iobase + PORT2A)); | |
125 | if (ret < 0) | |
126 | return ret; | |
127 | ||
128 | s = dev->subdevices + 2; | |
129 | ret = subdev_8255_init(dev, s, NULL, | |
130 | (unsigned long)(dev->iobase + PORT3A)); | |
131 | if (ret < 0) | |
132 | return ret; | |
133 | ||
134 | s = dev->subdevices + 3; | |
135 | ret = subdev_8255_init(dev, s, NULL, | |
136 | (unsigned long)(dev->iobase + PORT4A)); | |
137 | if (ret < 0) | |
138 | return ret; | |
139 | ||
140 | printk("attached\n"); | |
141 | ||
142 | return 1; | |
143 | } | |
144 | } | |
145 | ||
146 | printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", | |
147 | dev->minor, bus, slot); | |
148 | return -EIO; | |
149 | } | |
150 | ||
71b5f4f1 | 151 | static int adl_pci7296_detach(struct comedi_device * dev) |
bb71f8b3 JG |
152 | { |
153 | printk("comedi%d: pci7432: remove\n", dev->minor); | |
154 | ||
155 | if (devpriv && devpriv->pci_dev) { | |
156 | if (dev->iobase) { | |
157 | comedi_pci_disable(devpriv->pci_dev); | |
158 | } | |
159 | pci_dev_put(devpriv->pci_dev); | |
160 | } | |
161 | // detach four 8255 digital io subdevices | |
162 | if (dev->subdevices) { | |
163 | subdev_8255_cleanup(dev, dev->subdevices + 0); | |
164 | subdev_8255_cleanup(dev, dev->subdevices + 1); | |
165 | subdev_8255_cleanup(dev, dev->subdevices + 2); | |
166 | subdev_8255_cleanup(dev, dev->subdevices + 3); | |
167 | ||
168 | } | |
169 | ||
170 | return 0; | |
171 | } | |
172 | ||
173 | COMEDI_PCI_INITCLEANUP(driver_adl_pci7296, adl_pci7296_pci_table); |