]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/staging/comedi/drivers/addi_apci_3120.c
staging: comedi: addi_common.h: remove ADDI_{EN, DIS}ABLE defines
[mirror_ubuntu-eoan-kernel.git] / drivers / staging / comedi / drivers / addi_apci_3120.c
CommitLineData
ce157f80 1#include <linux/module.h>
33782dd5
HS
2#include <linux/pci.h>
3
3d41c443
HS
4#include "../comedidev.h"
5#include "comedi_fc.h"
bf36f012 6#include "amcc_s5933.h"
3d41c443
HS
7
8#include "addi-data/addi_common.h"
3d41c443 9
bf6a1578 10#include "addi-data/hwdrv_apci3120.c"
bb6986f0 11
1df0e5b0
HS
12enum apci3120_boardid {
13 BOARD_APCI3120,
14 BOARD_APCI3001,
15};
16
20a22b70 17static const struct addi_board apci3120_boardtypes[] = {
1df0e5b0 18 [BOARD_APCI3120] = {
c0a053b8 19 .pc_DriverName = "apci3120",
c0a053b8
HS
20 .i_NbrAiChannel = 16,
21 .i_NbrAiChannelDiff = 8,
22 .i_AiChannelList = 16,
23 .i_NbrAoChannel = 8,
24 .i_AiMaxdata = 0xffff,
25 .i_AoMaxdata = 0x3fff,
c0a053b8
HS
26 .i_NbrDiChannel = 4,
27 .i_NbrDoChannel = 4,
28 .i_DoMaxdata = 0x0f,
805077b9 29 .interrupt = apci3120_interrupt,
1df0e5b0
HS
30 },
31 [BOARD_APCI3001] = {
973781a8 32 .pc_DriverName = "apci3001",
973781a8
HS
33 .i_NbrAiChannel = 16,
34 .i_NbrAiChannelDiff = 8,
35 .i_AiChannelList = 16,
36 .i_AiMaxdata = 0xfff,
973781a8
HS
37 .i_NbrDiChannel = 4,
38 .i_NbrDoChannel = 4,
39 .i_DoMaxdata = 0x0f,
805077b9 40 .interrupt = apci3120_interrupt,
c0a053b8
HS
41 },
42};
43
bb6986f0
HS
44static irqreturn_t v_ADDI_Interrupt(int irq, void *d)
45{
46 struct comedi_device *dev = d;
47 const struct addi_board *this_board = comedi_board(dev);
48
49 this_board->interrupt(irq, d);
50 return IRQ_RETVAL(1);
51}
52
a690b7e5 53static int apci3120_auto_attach(struct comedi_device *dev,
1df0e5b0 54 unsigned long context)
bb6986f0 55{
891e62c3 56 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1df0e5b0 57 const struct addi_board *this_board = NULL;
bb6986f0
HS
58 struct addi_private *devpriv;
59 struct comedi_subdevice *s;
aea9c4e2 60 int ret, pages, i;
bb6986f0 61
1df0e5b0
HS
62 if (context < ARRAY_SIZE(apci3120_boardtypes))
63 this_board = &apci3120_boardtypes[context];
bb6986f0
HS
64 if (!this_board)
65 return -ENODEV;
66 dev->board_ptr = this_board;
67 dev->board_name = this_board->pc_DriverName;
68
0bdab509 69 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
bb6986f0
HS
70 if (!devpriv)
71 return -ENOMEM;
bb6986f0 72
818f569f 73 ret = comedi_pci_enable(dev);
bb6986f0
HS
74 if (ret)
75 return ret;
4fbe36f2 76 pci_set_master(pcidev);
bb6986f0 77
65fe75a6 78 dev->iobase = pci_resource_start(pcidev, 1);
887f706e
HS
79 devpriv->iobase = dev->iobase;
80 devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
81 devpriv->i_IobaseAddon = pci_resource_start(pcidev, 2);
bb6986f0
HS
82 devpriv->i_IobaseReserved = pci_resource_start(pcidev, 3);
83
bb6986f0
HS
84 if (pcidev->irq > 0) {
85 ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED,
86 dev->board_name, dev);
87 if (ret == 0)
88 dev->irq = pcidev->irq;
89 }
90
223a6402 91 devpriv->us_UseDma = 1;
bb6986f0 92
4fbe36f2
HS
93 /* Allocate DMA buffers */
94 devpriv->b_DmaDoubleBuffer = 0;
95 for (i = 0; i < 2; i++) {
96 for (pages = 4; pages >= 0; pages--) {
97 devpriv->ul_DmaBufferVirtual[i] =
98 (void *) __get_free_pages(GFP_KERNEL, pages);
99
100 if (devpriv->ul_DmaBufferVirtual[i])
101 break;
102 }
103 if (devpriv->ul_DmaBufferVirtual[i]) {
104 devpriv->ui_DmaBufferPages[i] = pages;
105 devpriv->ui_DmaBufferSize[i] = PAGE_SIZE * pages;
4fbe36f2
HS
106 devpriv->ul_DmaBufferHw[i] =
107 virt_to_bus((void *)devpriv->
108 ul_DmaBufferVirtual[i]);
bb6986f0
HS
109 }
110 }
4fbe36f2 111 if (!devpriv->ul_DmaBufferVirtual[0])
223a6402 112 devpriv->us_UseDma = 0;
4fbe36f2
HS
113
114 if (devpriv->ul_DmaBufferVirtual[1])
115 devpriv->b_DmaDoubleBuffer = 1;
bb6986f0 116
aea9c4e2 117 ret = comedi_alloc_subdevices(dev, 5);
bb6986f0
HS
118 if (ret)
119 return ret;
120
121 /* Allocate and Initialise AI Subdevice Structures */
122 s = &dev->subdevices[0];
50231a91
HS
123 dev->read_subdev = s;
124 s->type = COMEDI_SUBD_AI;
125 s->subdev_flags =
126 SDF_READABLE | SDF_COMMON | SDF_GROUND
127 | SDF_DIFF;
301b1ffc 128 if (this_board->i_NbrAiChannel)
50231a91 129 s->n_chan = this_board->i_NbrAiChannel;
301b1ffc 130 else
50231a91 131 s->n_chan = this_board->i_NbrAiChannelDiff;
50231a91
HS
132 s->maxdata = this_board->i_AiMaxdata;
133 s->len_chanlist = this_board->i_AiChannelList;
1ba296b9 134 s->range_table = &range_apci3120_ai;
50231a91 135
805077b9
FA
136 s->insn_config = apci3120_ai_insn_config;
137 s->insn_read = apci3120_ai_insn_read;
138 s->do_cmdtest = apci3120_ai_cmdtest;
139 s->do_cmd = apci3120_ai_cmd;
140 s->cancel = apci3120_cancel;
bb6986f0
HS
141
142 /* Allocate and Initialise AO Subdevice Structures */
143 s = &dev->subdevices[1];
48fdf084 144 if (this_board->i_NbrAoChannel) {
bb6986f0
HS
145 s->type = COMEDI_SUBD_AO;
146 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
48fdf084
HS
147 s->n_chan = this_board->i_NbrAoChannel;
148 s->maxdata = this_board->i_AoMaxdata;
149 s->len_chanlist = this_board->i_NbrAoChannel;
0bb482e2 150 s->range_table = &range_apci3120_ao;
805077b9 151 s->insn_write = apci3120_ao_insn_write;
bb6986f0
HS
152 } else {
153 s->type = COMEDI_SUBD_UNUSED;
154 }
f2c872e1 155
bb6986f0
HS
156 /* Allocate and Initialise DI Subdevice Structures */
157 s = &dev->subdevices[2];
f2c872e1
HS
158 s->type = COMEDI_SUBD_DI;
159 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
160 s->n_chan = this_board->i_NbrDiChannel;
161 s->maxdata = 1;
162 s->len_chanlist = this_board->i_NbrDiChannel;
163 s->range_table = &range_digital;
a7f4b3ca 164 s->insn_bits = apci3120_di_insn_bits;
f2c872e1 165
bb6986f0
HS
166 /* Allocate and Initialise DO Subdevice Structures */
167 s = &dev->subdevices[3];
43deb75d
HS
168 s->type = COMEDI_SUBD_DO;
169 s->subdev_flags =
170 SDF_READABLE | SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
171 s->n_chan = this_board->i_NbrDoChannel;
172 s->maxdata = this_board->i_DoMaxdata;
173 s->len_chanlist = this_board->i_NbrDoChannel;
174 s->range_table = &range_digital;
66511843 175 s->insn_bits = apci3120_do_insn_bits;
bb6986f0
HS
176
177 /* Allocate and Initialise Timer Subdevice Structures */
178 s = &dev->subdevices[4];
53b168b9
HS
179 s->type = COMEDI_SUBD_TIMER;
180 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
181 s->n_chan = 1;
182 s->maxdata = 0;
183 s->len_chanlist = 1;
184 s->range_table = &range_digital;
185
805077b9
FA
186 s->insn_write = apci3120_write_insn_timer;
187 s->insn_read = apci3120_read_insn_timer;
188 s->insn_config = apci3120_config_insn_timer;
bb6986f0 189
805077b9 190 apci3120_reset(dev);
bb6986f0
HS
191 return 0;
192}
193
194static void apci3120_detach(struct comedi_device *dev)
195{
bb6986f0
HS
196 struct addi_private *devpriv = dev->private;
197
198 if (devpriv) {
199 if (dev->iobase)
805077b9 200 apci3120_reset(dev);
bb6986f0
HS
201 if (dev->irq)
202 free_irq(dev->irq, dev);
97641816
HS
203 if (devpriv->ul_DmaBufferVirtual[0]) {
204 free_pages((unsigned long)devpriv->
205 ul_DmaBufferVirtual[0],
206 devpriv->ui_DmaBufferPages[0]);
207 }
208 if (devpriv->ul_DmaBufferVirtual[1]) {
209 free_pages((unsigned long)devpriv->
210 ul_DmaBufferVirtual[1],
211 devpriv->ui_DmaBufferPages[1]);
bb6986f0
HS
212 }
213 }
7f072f54 214 comedi_pci_disable(dev);
bb6986f0
HS
215}
216
20a22b70
HS
217static struct comedi_driver apci3120_driver = {
218 .driver_name = "addi_apci_3120",
219 .module = THIS_MODULE,
891e62c3 220 .auto_attach = apci3120_auto_attach,
bb6986f0 221 .detach = apci3120_detach,
20a22b70
HS
222};
223
a690b7e5 224static int apci3120_pci_probe(struct pci_dev *dev,
b8f4ac23 225 const struct pci_device_id *id)
20a22b70 226{
b8f4ac23 227 return comedi_pci_auto_config(dev, &apci3120_driver, id->driver_data);
20a22b70
HS
228}
229
41e043fc 230static const struct pci_device_id apci3120_pci_table[] = {
aee351b2
IA
231 { PCI_VDEVICE(AMCC, 0x818d), BOARD_APCI3120 },
232 { PCI_VDEVICE(AMCC, 0x828d), BOARD_APCI3001 },
317285d7
HS
233 { 0 }
234};
20a22b70 235MODULE_DEVICE_TABLE(pci, apci3120_pci_table);
317285d7 236
20a22b70
HS
237static struct pci_driver apci3120_pci_driver = {
238 .name = "addi_apci_3120",
239 .id_table = apci3120_pci_table,
240 .probe = apci3120_pci_probe,
9901a4d7 241 .remove = comedi_pci_auto_unconfig,
20a22b70
HS
242};
243module_comedi_pci_driver(apci3120_driver, apci3120_pci_driver);
90f703d3
AT
244
245MODULE_AUTHOR("Comedi http://www.comedi.org");
b5ebcaa8 246MODULE_DESCRIPTION("ADDI-DATA APCI-3120, Analog input board");
90f703d3 247MODULE_LICENSE("GPL");