]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/ni_6527.c
staging: comedi: remove inline alloc_private()
[~andy/linux] / drivers / staging / comedi / drivers / ni_6527.c
1 /*
2     comedi/drivers/ni_6527.c
3     driver for National Instruments PCI-6527
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 1999,2002,2003 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: ni_6527
25 Description: National Instruments 6527
26 Author: ds
27 Status: works
28 Devices: [National Instruments] PCI-6527 (ni6527), PXI-6527
29 Updated: Sat, 25 Jan 2003 13:24:40 -0800
30
31
32 */
33
34 /*
35    Manuals (available from ftp://ftp.natinst.com/support/manuals)
36
37         370106b.pdf     6527 Register Level Programmer Manual
38
39  */
40
41 #define DEBUG 1
42 #define DEBUG_FLAGS
43
44 #include <linux/interrupt.h>
45 #include "../comedidev.h"
46
47 #include "comedi_fc.h"
48 #include "mite.h"
49
50 #define DRIVER_NAME "ni_6527"
51
52 #define NI6527_DIO_SIZE 4096
53 #define NI6527_MITE_SIZE 4096
54
55 #define Port_Register(x)                        (0x00+(x))
56 #define ID_Register                             0x06
57
58 #define Clear_Register                          0x07
59 #define ClrEdge                         0x08
60 #define ClrOverflow                     0x04
61 #define ClrFilter                       0x02
62 #define ClrInterval                     0x01
63
64 #define Filter_Interval(x)                      (0x08+(x))
65 #define Filter_Enable(x)                        (0x0c+(x))
66
67 #define Change_Status                           0x14
68 #define MasterInterruptStatus           0x04
69 #define Overflow                        0x02
70 #define EdgeStatus                      0x01
71
72 #define Master_Interrupt_Control                0x15
73 #define FallingEdgeIntEnable            0x10
74 #define RisingEdgeIntEnable             0x08
75 #define MasterInterruptEnable           0x04
76 #define OverflowIntEnable               0x02
77 #define EdgeIntEnable                   0x01
78
79 #define Rising_Edge_Detection_Enable(x)         (0x018+(x))
80 #define Falling_Edge_Detection_Enable(x)        (0x020+(x))
81
82 struct ni6527_board {
83
84         int dev_id;
85         const char *name;
86 };
87
88 static const struct ni6527_board ni6527_boards[] = {
89         {
90          .dev_id = 0x2b20,
91          .name = "pci-6527",
92          },
93         {
94          .dev_id = 0x2b10,
95          .name = "pxi-6527",
96          },
97 };
98
99 #define this_board ((const struct ni6527_board *)dev->board_ptr)
100
101 static DEFINE_PCI_DEVICE_TABLE(ni6527_pci_table) = {
102         {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b10)},
103         {PCI_DEVICE(PCI_VENDOR_ID_NI, 0x2b20)},
104         {0}
105 };
106
107 MODULE_DEVICE_TABLE(pci, ni6527_pci_table);
108
109 struct ni6527_private {
110         struct mite_struct *mite;
111         unsigned int filter_interval;
112         unsigned int filter_enable;
113 };
114
115 static int ni6527_di_insn_config(struct comedi_device *dev,
116                                  struct comedi_subdevice *s,
117                                  struct comedi_insn *insn, unsigned int *data)
118 {
119         struct ni6527_private *devpriv = dev->private;
120         int chan = CR_CHAN(insn->chanspec);
121         unsigned int interval;
122
123         if (insn->n != 2)
124                 return -EINVAL;
125
126         if (data[0] != INSN_CONFIG_FILTER)
127                 return -EINVAL;
128
129         if (data[1]) {
130                 interval = (data[1] + 100) / 200;
131                 data[1] = interval * 200;
132
133                 if (interval != devpriv->filter_interval) {
134                         writeb(interval & 0xff,
135                                devpriv->mite->daq_io_addr + Filter_Interval(0));
136                         writeb((interval >> 8) & 0xff,
137                                devpriv->mite->daq_io_addr + Filter_Interval(1));
138                         writeb((interval >> 16) & 0x0f,
139                                devpriv->mite->daq_io_addr + Filter_Interval(2));
140
141                         writeb(ClrInterval,
142                                devpriv->mite->daq_io_addr + Clear_Register);
143
144                         devpriv->filter_interval = interval;
145                 }
146
147                 devpriv->filter_enable |= 1 << chan;
148         } else {
149                 devpriv->filter_enable &= ~(1 << chan);
150         }
151
152         writeb(devpriv->filter_enable,
153                devpriv->mite->daq_io_addr + Filter_Enable(0));
154         writeb(devpriv->filter_enable >> 8,
155                devpriv->mite->daq_io_addr + Filter_Enable(1));
156         writeb(devpriv->filter_enable >> 16,
157                devpriv->mite->daq_io_addr + Filter_Enable(2));
158
159         return 2;
160 }
161
162 static int ni6527_di_insn_bits(struct comedi_device *dev,
163                                struct comedi_subdevice *s,
164                                struct comedi_insn *insn, unsigned int *data)
165 {
166         struct ni6527_private *devpriv = dev->private;
167
168         data[1] = readb(devpriv->mite->daq_io_addr + Port_Register(0));
169         data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(1)) << 8;
170         data[1] |= readb(devpriv->mite->daq_io_addr + Port_Register(2)) << 16;
171
172         return insn->n;
173 }
174
175 static int ni6527_do_insn_bits(struct comedi_device *dev,
176                                struct comedi_subdevice *s,
177                                struct comedi_insn *insn, unsigned int *data)
178 {
179         struct ni6527_private *devpriv = dev->private;
180
181         if (data[0]) {
182                 s->state &= ~data[0];
183                 s->state |= (data[0] & data[1]);
184
185                 /* The open relay state on the board cooresponds to 1,
186                  * but in Comedi, it is represented by 0. */
187                 if (data[0] & 0x0000ff) {
188                         writeb((s->state ^ 0xff),
189                                devpriv->mite->daq_io_addr + Port_Register(3));
190                 }
191                 if (data[0] & 0x00ff00) {
192                         writeb((s->state >> 8) ^ 0xff,
193                                devpriv->mite->daq_io_addr + Port_Register(4));
194                 }
195                 if (data[0] & 0xff0000) {
196                         writeb((s->state >> 16) ^ 0xff,
197                                devpriv->mite->daq_io_addr + Port_Register(5));
198                 }
199         }
200         data[1] = s->state;
201
202         return insn->n;
203 }
204
205 static irqreturn_t ni6527_interrupt(int irq, void *d)
206 {
207         struct comedi_device *dev = d;
208         struct ni6527_private *devpriv = dev->private;
209         struct comedi_subdevice *s = &dev->subdevices[2];
210         unsigned int status;
211
212         status = readb(devpriv->mite->daq_io_addr + Change_Status);
213         if ((status & MasterInterruptStatus) == 0)
214                 return IRQ_NONE;
215         if ((status & EdgeStatus) == 0)
216                 return IRQ_NONE;
217
218         writeb(ClrEdge | ClrOverflow,
219                devpriv->mite->daq_io_addr + Clear_Register);
220
221         comedi_buf_put(s->async, 0);
222         s->async->events |= COMEDI_CB_EOS;
223         comedi_event(dev, s);
224         return IRQ_HANDLED;
225 }
226
227 static int ni6527_intr_cmdtest(struct comedi_device *dev,
228                                struct comedi_subdevice *s,
229                                struct comedi_cmd *cmd)
230 {
231         int err = 0;
232
233         /* Step 1 : check if triggers are trivially valid */
234
235         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
236         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_OTHER);
237         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
238         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
239         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT);
240
241         if (err)
242                 return 1;
243
244         /* Step 2a : make sure trigger sources are unique */
245         /* Step 2b : and mutually compatible */
246
247         if (err)
248                 return 2;
249
250         /* step 3: make sure arguments are trivially compatible */
251
252         if (cmd->start_arg != 0) {
253                 cmd->start_arg = 0;
254                 err++;
255         }
256         if (cmd->scan_begin_arg != 0) {
257                 cmd->scan_begin_arg = 0;
258                 err++;
259         }
260         if (cmd->convert_arg != 0) {
261                 cmd->convert_arg = 0;
262                 err++;
263         }
264
265         if (cmd->scan_end_arg != 1) {
266                 cmd->scan_end_arg = 1;
267                 err++;
268         }
269         if (cmd->stop_arg != 0) {
270                 cmd->stop_arg = 0;
271                 err++;
272         }
273
274         if (err)
275                 return 3;
276
277         /* step 4: fix up any arguments */
278
279         if (err)
280                 return 4;
281
282         return 0;
283 }
284
285 static int ni6527_intr_cmd(struct comedi_device *dev,
286                            struct comedi_subdevice *s)
287 {
288         struct ni6527_private *devpriv = dev->private;
289         /* struct comedi_cmd *cmd = &s->async->cmd; */
290
291         writeb(ClrEdge | ClrOverflow,
292                devpriv->mite->daq_io_addr + Clear_Register);
293         writeb(FallingEdgeIntEnable | RisingEdgeIntEnable |
294                MasterInterruptEnable | EdgeIntEnable,
295                devpriv->mite->daq_io_addr + Master_Interrupt_Control);
296
297         return 0;
298 }
299
300 static int ni6527_intr_cancel(struct comedi_device *dev,
301                               struct comedi_subdevice *s)
302 {
303         struct ni6527_private *devpriv = dev->private;
304
305         writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
306
307         return 0;
308 }
309
310 static int ni6527_intr_insn_bits(struct comedi_device *dev,
311                                  struct comedi_subdevice *s,
312                                  struct comedi_insn *insn, unsigned int *data)
313 {
314         data[1] = 0;
315         return insn->n;
316 }
317
318 static int ni6527_intr_insn_config(struct comedi_device *dev,
319                                    struct comedi_subdevice *s,
320                                    struct comedi_insn *insn, unsigned int *data)
321 {
322         struct ni6527_private *devpriv = dev->private;
323
324         if (insn->n < 1)
325                 return -EINVAL;
326         if (data[0] != INSN_CONFIG_CHANGE_NOTIFY)
327                 return -EINVAL;
328
329         writeb(data[1],
330                devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(0));
331         writeb(data[1] >> 8,
332                devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(1));
333         writeb(data[1] >> 16,
334                devpriv->mite->daq_io_addr + Rising_Edge_Detection_Enable(2));
335
336         writeb(data[2],
337                devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(0));
338         writeb(data[2] >> 8,
339                devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(1));
340         writeb(data[2] >> 16,
341                devpriv->mite->daq_io_addr + Falling_Edge_Detection_Enable(2));
342
343         return 2;
344 }
345
346 static const struct ni6527_board *
347 ni6527_find_boardinfo(struct pci_dev *pcidev)
348 {
349         unsigned int dev_id = pcidev->device;
350         unsigned int n;
351
352         for (n = 0; n < ARRAY_SIZE(ni6527_boards); n++) {
353                 const struct ni6527_board *board = &ni6527_boards[n];
354                 if (board->dev_id == dev_id)
355                         return board;
356         }
357         return NULL;
358 }
359
360 static int __devinit ni6527_attach_pci(struct comedi_device *dev,
361                                        struct pci_dev *pcidev)
362 {
363         struct ni6527_private *devpriv;
364         struct comedi_subdevice *s;
365         int ret;
366
367         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
368         if (!devpriv)
369                 return -ENOMEM;
370         dev->private = devpriv;
371
372         dev->board_ptr = ni6527_find_boardinfo(pcidev);
373         if (!dev->board_ptr)
374                 return -ENODEV;
375
376         devpriv->mite = mite_alloc(pcidev);
377         if (!devpriv->mite)
378                 return -ENOMEM;
379
380         ret = mite_setup(devpriv->mite);
381         if (ret < 0) {
382                 dev_err(dev->class_dev, "error setting up mite\n");
383                 return ret;
384         }
385
386         dev->board_name = this_board->name;
387         dev_info(dev->class_dev, "board: %s, ID=0x%02x\n", dev->board_name,
388                  readb(devpriv->mite->daq_io_addr + ID_Register));
389
390         ret = comedi_alloc_subdevices(dev, 3);
391         if (ret)
392                 return ret;
393
394         s = &dev->subdevices[0];
395         s->type = COMEDI_SUBD_DI;
396         s->subdev_flags = SDF_READABLE;
397         s->n_chan = 24;
398         s->range_table = &range_digital;
399         s->maxdata = 1;
400         s->insn_config = ni6527_di_insn_config;
401         s->insn_bits = ni6527_di_insn_bits;
402
403         s = &dev->subdevices[1];
404         s->type = COMEDI_SUBD_DO;
405         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
406         s->n_chan = 24;
407         s->range_table = &range_unknown;  /* FIXME: actually conductance */
408         s->maxdata = 1;
409         s->insn_bits = ni6527_do_insn_bits;
410
411         s = &dev->subdevices[2];
412         dev->read_subdev = s;
413         s->type = COMEDI_SUBD_DI;
414         s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
415         s->n_chan = 1;
416         s->range_table = &range_unknown;
417         s->maxdata = 1;
418         s->do_cmdtest = ni6527_intr_cmdtest;
419         s->do_cmd = ni6527_intr_cmd;
420         s->cancel = ni6527_intr_cancel;
421         s->insn_bits = ni6527_intr_insn_bits;
422         s->insn_config = ni6527_intr_insn_config;
423
424         writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(0));
425         writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(1));
426         writeb(0x00, devpriv->mite->daq_io_addr + Filter_Enable(2));
427
428         writeb(ClrEdge | ClrOverflow | ClrFilter | ClrInterval,
429                devpriv->mite->daq_io_addr + Clear_Register);
430         writeb(0x00, devpriv->mite->daq_io_addr + Master_Interrupt_Control);
431
432         ret = request_irq(mite_irq(devpriv->mite), ni6527_interrupt,
433                           IRQF_SHARED, DRIVER_NAME, dev);
434         if (ret < 0)
435                 dev_warn(dev->class_dev, "irq not available\n");
436         else
437                 dev->irq = mite_irq(devpriv->mite);
438
439         return 0;
440 }
441
442 static void ni6527_detach(struct comedi_device *dev)
443 {
444         struct ni6527_private *devpriv = dev->private;
445
446         if (devpriv && devpriv->mite && devpriv->mite->daq_io_addr)
447                 writeb(0x00,
448                        devpriv->mite->daq_io_addr + Master_Interrupt_Control);
449         if (dev->irq)
450                 free_irq(dev->irq, dev);
451         if (devpriv && devpriv->mite) {
452                 mite_unsetup(devpriv->mite);
453                 mite_free(devpriv->mite);
454         }
455 }
456
457 static struct comedi_driver ni6527_driver = {
458         .driver_name = DRIVER_NAME,
459         .module = THIS_MODULE,
460         .attach_pci = ni6527_attach_pci,
461         .detach = ni6527_detach,
462 };
463
464 static int __devinit ni6527_pci_probe(struct pci_dev *dev,
465                                       const struct pci_device_id *ent)
466 {
467         return comedi_pci_auto_config(dev, &ni6527_driver);
468 }
469
470 static void __devexit ni6527_pci_remove(struct pci_dev *dev)
471 {
472         comedi_pci_auto_unconfig(dev);
473 }
474
475 static struct pci_driver ni6527_pci_driver = {
476         .name = DRIVER_NAME,
477         .id_table = ni6527_pci_table,
478         .probe = ni6527_pci_probe,
479         .remove = __devexit_p(ni6527_pci_remove)
480 };
481 module_comedi_pci_driver(ni6527_driver, ni6527_pci_driver);
482
483 MODULE_AUTHOR("Comedi http://www.comedi.org");
484 MODULE_DESCRIPTION("Comedi low-level driver");
485 MODULE_LICENSE("GPL");