Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[firefly-linux-kernel-4.4.55.git] / drivers / staging / comedi / drivers / pcmmio.c
1 /*
2     comedi/drivers/pcmmio.c
3     Driver for Winsystems PC-104 based multifunction IO board.
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2007 Calin A. Culianu <calin@ajvar.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 Driver: pcmmio
24 Description: A driver for the PCM-MIO multifunction board
25 Devices: [Winsystems] PCM-MIO (pcmmio)
26 Author: Calin Culianu <calin@ajvar.org>
27 Updated: Wed, May 16 2007 16:21:10 -0500
28 Status: works
29
30 A driver for the relatively new PCM-MIO multifunction board from
31 Winsystems.  This board is a PC-104 based I/O board.  It contains
32 four subdevices:
33   subdevice 0 - 16 channels of 16-bit AI
34   subdevice 1 - 8 channels of 16-bit AO
35   subdevice 2 - first 24 channels of the 48 channel of DIO
36         (with edge-triggered interrupt support)
37   subdevice 3 - last 24 channels of the 48 channel DIO
38         (no interrupt support for this bank of channels)
39
40   Some notes:
41
42   Synchronous reads and writes are the only things implemented for AI and AO,
43   even though the hardware itself can do streaming acquisition, etc.  Anyone
44   want to add asynchronous I/O for AI/AO as a feature?  Be my guest...
45
46   Asynchronous I/O for the DIO subdevices *is* implemented, however!  They are
47   basically edge-triggered interrupts for any configuration of the first
48   24 DIO-lines.
49
50   Also note that this interrupt support is untested.
51
52   A few words about edge-detection IRQ support (commands on DIO):
53
54   * To use edge-detection IRQ support for the DIO subdevice, pass the IRQ
55     of the board to the comedi_config command.  The board IRQ is not jumpered
56     but rather configured through software, so any IRQ from 1-15 is OK.
57
58   * Due to the genericity of the comedi API, you need to create a special
59     comedi_command in order to use edge-triggered interrupts for DIO.
60
61   * Use comedi_commands with TRIG_NOW.  Your callback will be called each
62     time an edge is detected on the specified DIO line(s), and the data
63     values will be two sample_t's, which should be concatenated to form
64     one 32-bit unsigned int.  This value is the mask of channels that had
65     edges detected from your channel list.  Note that the bits positions
66     in the mask correspond to positions in your chanlist when you
67     specified the command and *not* channel id's!
68
69  *  To set the polarity of the edge-detection interrupts pass a nonzero value
70     for either CR_RANGE or CR_AREF for edge-up polarity, or a zero
71     value for both CR_RANGE and CR_AREF if you want edge-down polarity.
72
73 Configuration Options:
74   [0] - I/O port base address
75   [1] - IRQ (optional -- for edge-detect interrupt support only,
76         leave out if you don't need this feature)
77 */
78
79 #include <linux/interrupt.h>
80 #include <linux/slab.h>
81 #include "../comedidev.h"
82 #include "pcm_common.h"
83 #include <linux/pci.h>          /* for PCI devices */
84
85 /* This stuff is all from pcmuio.c -- it refers to the DIO subdevices only */
86 #define CHANS_PER_PORT   8
87 #define PORTS_PER_ASIC   6
88 #define INTR_PORTS_PER_ASIC   3
89 #define MAX_CHANS_PER_SUBDEV 24 /* number of channels per comedi subdevice */
90 #define PORTS_PER_SUBDEV (MAX_CHANS_PER_SUBDEV/CHANS_PER_PORT)
91 #define CHANS_PER_ASIC (CHANS_PER_PORT*PORTS_PER_ASIC)
92 #define INTR_CHANS_PER_ASIC 24
93 #define INTR_PORTS_PER_SUBDEV (INTR_CHANS_PER_ASIC/CHANS_PER_PORT)
94 #define MAX_DIO_CHANS   (PORTS_PER_ASIC*1*CHANS_PER_PORT)
95 #define MAX_ASICS       (MAX_DIO_CHANS/CHANS_PER_ASIC)
96 #define SDEV_NO ((int)(s - dev->subdevices))
97 #define CALC_N_DIO_SUBDEVS(nchans) ((nchans)/MAX_CHANS_PER_SUBDEV + (!!((nchans)%MAX_CHANS_PER_SUBDEV)) /*+ (nchans > INTR_CHANS_PER_ASIC ? 2 : 1)*/)
98 /* IO Memory sizes */
99 #define ASIC_IOSIZE (0x0B)
100 #define PCMMIO48_IOSIZE ASIC_IOSIZE
101
102 /* Some offsets - these are all in the 16byte IO memory offset from
103    the base address.  Note that there is a paging scheme to swap out
104    offsets 0x8-0xA using the PAGELOCK register.  See the table below.
105
106   Register(s)       Pages        R/W?        Description
107   --------------------------------------------------------------
108   REG_PORTx         All          R/W         Read/Write/Configure IO
109   REG_INT_PENDING   All          ReadOnly    Quickly see which INT_IDx has int.
110   REG_PAGELOCK      All          WriteOnly   Select a page
111   REG_POLx          Pg. 1 only   WriteOnly   Select edge-detection polarity
112   REG_ENABx         Pg. 2 only   WriteOnly   Enable/Disable edge-detect. int.
113   REG_INT_IDx       Pg. 3 only   R/W         See which ports/bits have ints.
114  */
115 #define REG_PORT0 0x0
116 #define REG_PORT1 0x1
117 #define REG_PORT2 0x2
118 #define REG_PORT3 0x3
119 #define REG_PORT4 0x4
120 #define REG_PORT5 0x5
121 #define REG_INT_PENDING 0x6
122 #define REG_PAGELOCK 0x7        /*
123                                  * page selector register, upper 2 bits select
124                                  * a page and bits 0-5 are used to 'lock down'
125                                  * a particular port above to make it readonly.
126                                  */
127 #define REG_POL0 0x8
128 #define REG_POL1 0x9
129 #define REG_POL2 0xA
130 #define REG_ENAB0 0x8
131 #define REG_ENAB1 0x9
132 #define REG_ENAB2 0xA
133 #define REG_INT_ID0 0x8
134 #define REG_INT_ID1 0x9
135 #define REG_INT_ID2 0xA
136
137 #define NUM_PAGED_REGS 3
138 #define NUM_PAGES 4
139 #define FIRST_PAGED_REG 0x8
140 #define REG_PAGE_BITOFFSET 6
141 #define REG_LOCK_BITOFFSET 0
142 #define REG_PAGE_MASK (~((0x1<<REG_PAGE_BITOFFSET)-1))
143 #define REG_LOCK_MASK (~(REG_PAGE_MASK))
144 #define PAGE_POL 1
145 #define PAGE_ENAB 2
146 #define PAGE_INT_ID 3
147
148 /*
149  * Board descriptions for two imaginary boards.  Describing the
150  * boards in this way is optional, and completely driver-dependent.
151  * Some drivers use arrays such as this, other do not.
152  */
153 struct pcmmio_board {
154         const char *name;
155         const int dio_num_asics;
156         const int dio_num_ports;
157         const int total_iosize;
158         const int ai_bits;
159         const int ao_bits;
160         const int n_ai_chans;
161         const int n_ao_chans;
162         const struct comedi_lrange *ai_range_table, *ao_range_table;
163         int (*ai_rinsn) (struct comedi_device *dev,
164                         struct comedi_subdevice *s,
165                         struct comedi_insn *insn,
166                         unsigned int *data);
167         int (*ao_rinsn) (struct comedi_device *dev,
168                         struct comedi_subdevice *s,
169                         struct comedi_insn *insn,
170                         unsigned int *data);
171         int (*ao_winsn) (struct comedi_device *dev,
172                         struct comedi_subdevice *s,
173                         struct comedi_insn *insn,
174                         unsigned int *data);
175 };
176
177 static const struct comedi_lrange ranges_ai = {
178         4, {RANGE(-5., 5.), RANGE(-10., 10.), RANGE(0., 5.), RANGE(0., 10.)}
179 };
180
181 static const struct comedi_lrange ranges_ao = {
182         6, {RANGE(0., 5.), RANGE(0., 10.), RANGE(-5., 5.), RANGE(-10., 10.),
183           RANGE(-2.5, 2.5), RANGE(-2.5, 7.5)}
184 };
185
186 /* this structure is for data unique to this subdevice.  */
187 struct pcmmio_subdev_private {
188
189         union {
190                 /* for DIO: mapping of halfwords (bytes)
191                    in port/chanarray to iobase */
192                 unsigned long iobases[PORTS_PER_SUBDEV];
193
194                 /* for AI/AO */
195                 unsigned long iobase;
196         };
197         union {
198                 struct {
199
200                         /* The below is only used for intr subdevices */
201                         struct {
202                                 /*
203                                  * if non-negative, this subdev has an
204                                  * interrupt asic
205                                  */
206                                 int asic;
207                                 /*
208                                  * if nonnegative, the first channel id for
209                                  * interrupts.
210                                  */
211                                 int first_chan;
212                                 /*
213                                  * the number of asic channels in this subdev
214                                  * that have interrutps
215                                  */
216                                 int num_asic_chans;
217                                 /*
218                                  * if nonnegative, the first channel id with
219                                  * respect to the asic that has interrupts
220                                  */
221                                 int asic_chan;
222                                 /*
223                                  * subdev-relative channel mask for channels
224                                  * we are interested in
225                                  */
226                                 int enabled_mask;
227                                 int active;
228                                 int stop_count;
229                                 int continuous;
230                                 spinlock_t spinlock;
231                         } intr;
232                 } dio;
233                 struct {
234                         /* the last unsigned int data written */
235                         unsigned int shadow_samples[8];
236                 } ao;
237         };
238 };
239
240 /*
241  * this structure is for data unique to this hardware driver.  If
242  * several hardware drivers keep similar information in this structure,
243  * feel free to suggest moving the variable to the struct comedi_device struct.
244  */
245 struct pcmmio_private {
246         /* stuff for DIO */
247         struct {
248                 unsigned char pagelock; /* current page and lock */
249                 /* shadow of POLx registers */
250                 unsigned char pol[NUM_PAGED_REGS];
251                 /* shadow of ENABx registers */
252                 unsigned char enab[NUM_PAGED_REGS];
253                 int num;
254                 unsigned long iobase;
255                 unsigned int irq;
256                 spinlock_t spinlock;
257         } asics[MAX_ASICS];
258         struct pcmmio_subdev_private *sprivs;
259 };
260
261 /*
262  * most drivers define the following macro to make it easy to
263  * access the private structure.
264  */
265 #define devpriv ((struct pcmmio_private *)dev->private)
266 #define subpriv ((struct pcmmio_subdev_private *)s->private)
267
268 /* DIO devices are slightly special.  Although it is possible to
269  * implement the insn_read/insn_write interface, it is much more
270  * useful to applications if you implement the insn_bits interface.
271  * This allows packed reading/writing of the DIO channels.  The
272  * comedi core can convert between insn_bits and insn_read/write */
273 static int pcmmio_dio_insn_bits(struct comedi_device *dev,
274                                 struct comedi_subdevice *s,
275                                 struct comedi_insn *insn, unsigned int *data)
276 {
277         int byte_no;
278
279         /* NOTE:
280            reading a 0 means this channel was high
281            writine a 0 sets the channel high
282            reading a 1 means this channel was low
283            writing a 1 means set this channel low
284
285            Therefore everything is always inverted. */
286
287         /* The insn data is a mask in data[0] and the new data
288          * in data[1], each channel cooresponding to a bit. */
289
290 #ifdef DAMMIT_ITS_BROKEN
291         /* DEBUG */
292         printk(KERN_DEBUG "write mask: %08x  data: %08x\n", data[0], data[1]);
293 #endif
294
295         s->state = 0;
296
297         for (byte_no = 0; byte_no < s->n_chan / CHANS_PER_PORT; ++byte_no) {
298                 /* address of 8-bit port */
299                 unsigned long ioaddr = subpriv->iobases[byte_no],
300                     /* bit offset of port in 32-bit doubleword */
301                     offset = byte_no * 8;
302                 /* this 8-bit port's data */
303                 unsigned char byte = 0,
304                     /* The write mask for this port (if any) */
305                     write_mask_byte = (data[0] >> offset) & 0xff,
306                     /* The data byte for this port */
307                     data_byte = (data[1] >> offset) & 0xff;
308
309                 byte = inb(ioaddr);     /* read all 8-bits for this port */
310
311 #ifdef DAMMIT_ITS_BROKEN
312                 /* DEBUG */
313                 printk
314                     (KERN_DEBUG "byte %d wmb %02x db %02x offset %02d io %04x,"
315                      " data_in %02x ", byte_no, (unsigned)write_mask_byte,
316                      (unsigned)data_byte, offset, ioaddr, (unsigned)byte);
317 #endif
318
319                 if (write_mask_byte) {
320                         /*
321                          * this byte has some write_bits
322                          * -- so set the output lines
323                          */
324                         /* clear bits for write mask */
325                         byte &= ~write_mask_byte;
326                         /* set to inverted data_byte */
327                         byte |= ~data_byte & write_mask_byte;
328                         /* Write out the new digital output state */
329                         outb(byte, ioaddr);
330                 }
331 #ifdef DAMMIT_ITS_BROKEN
332                 /* DEBUG */
333                 printk(KERN_DEBUG "data_out_byte %02x\n", (unsigned)byte);
334 #endif
335                 /* save the digital input lines for this byte.. */
336                 s->state |= ((unsigned int)byte) << offset;
337         }
338
339         /* now return the DIO lines to data[1] - note they came inverted! */
340         data[1] = ~s->state;
341
342 #ifdef DAMMIT_ITS_BROKEN
343         /* DEBUG */
344         printk(KERN_DEBUG "s->state %08x data_out %08x\n", s->state, data[1]);
345 #endif
346
347         return insn->n;
348 }
349
350 /* The input or output configuration of each digital line is
351  * configured by a special insn_config instruction.  chanspec
352  * contains the channel to be changed, and data[0] contains the
353  * value COMEDI_INPUT or COMEDI_OUTPUT. */
354 static int pcmmio_dio_insn_config(struct comedi_device *dev,
355                                   struct comedi_subdevice *s,
356                                   struct comedi_insn *insn, unsigned int *data)
357 {
358         int chan = CR_CHAN(insn->chanspec), byte_no = chan / 8, bit_no =
359             chan % 8;
360         unsigned long ioaddr;
361         unsigned char byte;
362
363         /* Compute ioaddr for this channel */
364         ioaddr = subpriv->iobases[byte_no];
365
366         /* NOTE:
367            writing a 0 an IO channel's bit sets the channel to INPUT
368            and pulls the line high as well
369
370            writing a 1 to an IO channel's  bit pulls the line low
371
372            All channels are implicitly always in OUTPUT mode -- but when
373            they are high they can be considered to be in INPUT mode..
374
375            Thus, we only force channels low if the config request was INPUT,
376            otherwise we do nothing to the hardware.    */
377
378         switch (data[0]) {
379         case INSN_CONFIG_DIO_OUTPUT:
380                 /* save to io_bits -- don't actually do anything since
381                    all input channels are also output channels... */
382                 s->io_bits |= 1 << chan;
383                 break;
384         case INSN_CONFIG_DIO_INPUT:
385                 /* write a 0 to the actual register representing the channel
386                    to set it to 'input'.  0 means "float high". */
387                 byte = inb(ioaddr);
388                 byte &= ~(1 << bit_no);
389                                 /**< set input channel to '0' */
390
391                 /*
392                  * write out byte -- this is the only time we actually affect
393                  * the hardware as all channels are implicitly output
394                  * -- but input channels are set to float-high
395                  */
396                 outb(byte, ioaddr);
397
398                 /* save to io_bits */
399                 s->io_bits &= ~(1 << chan);
400                 break;
401
402         case INSN_CONFIG_DIO_QUERY:
403                 /* retrieve from shadow register */
404                 data[1] =
405                     (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT;
406                 return insn->n;
407                 break;
408
409         default:
410                 return -EINVAL;
411                 break;
412         }
413
414         return insn->n;
415 }
416
417 static void switch_page(struct comedi_device *dev, int asic, int page)
418 {
419         const struct pcmmio_board *board = comedi_board(dev);
420
421         if (asic < 0 || asic >= board->dio_num_asics)
422                 return;         /* paranoia */
423         if (page < 0 || page >= NUM_PAGES)
424                 return;         /* more paranoia */
425
426         devpriv->asics[asic].pagelock &= ~REG_PAGE_MASK;
427         devpriv->asics[asic].pagelock |= page << REG_PAGE_BITOFFSET;
428
429         /* now write out the shadow register */
430         outb(devpriv->asics[asic].pagelock,
431              devpriv->asics[asic].iobase + REG_PAGELOCK);
432 }
433
434 static void init_asics(struct comedi_device *dev)
435 {                               /* sets up an
436                                    ASIC chip to defaults */
437         const struct pcmmio_board *board = comedi_board(dev);
438         int asic;
439
440         for (asic = 0; asic < board->dio_num_asics; ++asic) {
441                 int port, page;
442                 unsigned long baseaddr = devpriv->asics[asic].iobase;
443
444                 switch_page(dev, asic, 0);      /* switch back to page 0 */
445
446                 /* first, clear all the DIO port bits */
447                 for (port = 0; port < PORTS_PER_ASIC; ++port)
448                         outb(0, baseaddr + REG_PORT0 + port);
449
450                 /* Next, clear all the paged registers for each page */
451                 for (page = 1; page < NUM_PAGES; ++page) {
452                         int reg;
453                         /* now clear all the paged registers */
454                         switch_page(dev, asic, page);
455                         for (reg = FIRST_PAGED_REG;
456                              reg < FIRST_PAGED_REG + NUM_PAGED_REGS; ++reg)
457                                 outb(0, baseaddr + reg);
458                 }
459
460                 /* DEBUG  set rising edge interrupts on port0 of both asics */
461                 /*switch_page(dev, asic, PAGE_POL);
462                    outb(0xff, baseaddr + REG_POL0);
463                    switch_page(dev, asic, PAGE_ENAB);
464                    outb(0xff, baseaddr + REG_ENAB0); */
465                 /* END DEBUG */
466
467                 /* switch back to default page 0 */
468                 switch_page(dev, asic, 0);
469         }
470 }
471
472 #ifdef notused
473 static void lock_port(struct comedi_device *dev, int asic, int port)
474 {
475         const struct pcmmio_board *board = comedi_board(dev);
476
477         if (asic < 0 || asic >= board->dio_num_asics)
478                 return;         /* paranoia */
479         if (port < 0 || port >= PORTS_PER_ASIC)
480                 return;         /* more paranoia */
481
482         devpriv->asics[asic].pagelock |= 0x1 << port;
483         /* now write out the shadow register */
484         outb(devpriv->asics[asic].pagelock,
485              devpriv->asics[asic].iobase + REG_PAGELOCK);
486         return;
487 }
488
489 static void unlock_port(struct comedi_device *dev, int asic, int port)
490 {
491         const struct pcmmio_board *board = comedi_board(dev);
492
493         if (asic < 0 || asic >= board->dio_num_asics)
494                 return;         /* paranoia */
495         if (port < 0 || port >= PORTS_PER_ASIC)
496                 return;         /* more paranoia */
497         devpriv->asics[asic].pagelock &= ~(0x1 << port) | REG_LOCK_MASK;
498         /* now write out the shadow register */
499         outb(devpriv->asics[asic].pagelock,
500              devpriv->asics[asic].iobase + REG_PAGELOCK);
501 }
502 #endif /* notused */
503
504 static void pcmmio_stop_intr(struct comedi_device *dev,
505                              struct comedi_subdevice *s)
506 {
507         int nports, firstport, asic, port;
508
509         asic = subpriv->dio.intr.asic;
510         if (asic < 0)
511                 return;         /* not an interrupt subdev */
512
513         subpriv->dio.intr.enabled_mask = 0;
514         subpriv->dio.intr.active = 0;
515         s->async->inttrig = NULL;
516         nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT;
517         firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT;
518         switch_page(dev, asic, PAGE_ENAB);
519         for (port = firstport; port < firstport + nports; ++port) {
520                 /* disable all intrs for this subdev.. */
521                 outb(0, devpriv->asics[asic].iobase + REG_ENAB0 + port);
522         }
523 }
524
525 static irqreturn_t interrupt_pcmmio(int irq, void *d)
526 {
527         int asic, got1 = 0;
528         struct comedi_device *dev = (struct comedi_device *)d;
529         int i;
530
531         for (asic = 0; asic < MAX_ASICS; ++asic) {
532                 if (irq == devpriv->asics[asic].irq) {
533                         unsigned long flags;
534                         unsigned triggered = 0;
535                         unsigned long iobase = devpriv->asics[asic].iobase;
536                         /* it is an interrupt for ASIC #asic */
537                         unsigned char int_pend;
538
539                         spin_lock_irqsave(&devpriv->asics[asic].spinlock,
540                                           flags);
541
542                         int_pend = inb(iobase + REG_INT_PENDING) & 0x07;
543
544                         if (int_pend) {
545                                 int port;
546                                 for (port = 0; port < INTR_PORTS_PER_ASIC;
547                                      ++port) {
548                                         if (int_pend & (0x1 << port)) {
549                                                 unsigned char
550                                                     io_lines_with_edges = 0;
551                                                 switch_page(dev, asic,
552                                                             PAGE_INT_ID);
553                                                 io_lines_with_edges =
554                                                     inb(iobase +
555                                                         REG_INT_ID0 + port);
556
557                                                 if (io_lines_with_edges)
558                                                         /*
559                                                          * clear pending
560                                                          * interrupt
561                                                          */
562                                                         outb(0, iobase +
563                                                              REG_INT_ID0 +
564                                                              port);
565
566                                                 triggered |=
567                                                     io_lines_with_edges <<
568                                                     port * 8;
569                                         }
570                                 }
571
572                                 ++got1;
573                         }
574
575                         spin_unlock_irqrestore(&devpriv->asics[asic].spinlock,
576                                                flags);
577
578                         if (triggered) {
579                                 struct comedi_subdevice *s;
580                                 /*
581                                  * TODO here: dispatch io lines to subdevs
582                                  * with commands..
583                                  */
584                                 printk
585                                     (KERN_DEBUG "got edge detect interrupt %d asic %d which_chans: %06x\n",
586                                      irq, asic, triggered);
587                                 for (i = 2; i < dev->n_subdevices; i++) {
588                                         s = &dev->subdevices[i];
589                                         /*
590                                          * this is an interrupt subdev,
591                                          * and it matches this asic!
592                                          */
593                                         if (subpriv->dio.intr.asic == asic) {
594                                                 unsigned long flags;
595                                                 unsigned oldevents;
596
597                                                 spin_lock_irqsave(&subpriv->dio.
598                                                                   intr.spinlock,
599                                                                   flags);
600
601                                                 oldevents = s->async->events;
602
603                                                 if (subpriv->dio.intr.active) {
604                                                         unsigned mytrig =
605                                                             ((triggered >>
606                                                               subpriv->dio.intr.asic_chan)
607                                                              &
608                                                              ((0x1 << subpriv->
609                                                                dio.intr.
610                                                                num_asic_chans) -
611                                                               1)) << subpriv->
612                                                             dio.intr.first_chan;
613                                                         if (mytrig &
614                                                             subpriv->dio.
615                                                             intr.enabled_mask) {
616                                                                 unsigned int val
617                                                                     = 0;
618                                                                 unsigned int n,
619                                                                     ch, len;
620
621                                                                 len =
622                                                                     s->
623                                                                     async->cmd.chanlist_len;
624                                                                 for (n = 0;
625                                                                      n < len;
626                                                                      n++) {
627                                                                         ch = CR_CHAN(s->async->cmd.chanlist[n]);
628                                                                         if (mytrig & (1U << ch))
629                                                                                 val |= (1U << n);
630                                                                 }
631                                                                 /* Write the scan to the buffer. */
632                                                                 if (comedi_buf_put(s->async, ((short *)&val)[0])
633                                                                     &&
634                                                                     comedi_buf_put
635                                                                     (s->async,
636                                                                      ((short *)
637                                                                       &val)[1])) {
638                                                                         s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
639                                                                 } else {
640                                                                         /* Overflow! Stop acquisition!! */
641                                                                         /* TODO: STOP_ACQUISITION_CALL_HERE!! */
642                                                                         pcmmio_stop_intr
643                                                                             (dev,
644                                                                              s);
645                                                                 }
646
647                                                                 /* Check for end of acquisition. */
648                                                                 if (!subpriv->dio.intr.continuous) {
649                                                                         /* stop_src == TRIG_COUNT */
650                                                                         if (subpriv->dio.intr.stop_count > 0) {
651                                                                                 subpriv->dio.intr.stop_count--;
652                                                                                 if (subpriv->dio.intr.stop_count == 0) {
653                                                                                         s->async->events |= COMEDI_CB_EOA;
654                                                                                         /* TODO: STOP_ACQUISITION_CALL_HERE!! */
655                                                                                         pcmmio_stop_intr
656                                                                                             (dev,
657                                                                                              s);
658                                                                                 }
659                                                                         }
660                                                                 }
661                                                         }
662                                                 }
663
664                                                 spin_unlock_irqrestore
665                                                     (&subpriv->dio.intr.
666                                                      spinlock, flags);
667
668                                                 if (oldevents !=
669                                                     s->async->events) {
670                                                         comedi_event(dev, s);
671                                                 }
672
673                                         }
674
675                                 }
676                         }
677
678                 }
679         }
680         if (!got1)
681                 return IRQ_NONE;        /* interrupt from other source */
682         return IRQ_HANDLED;
683 }
684
685 static int pcmmio_start_intr(struct comedi_device *dev,
686                              struct comedi_subdevice *s)
687 {
688         if (!subpriv->dio.intr.continuous && subpriv->dio.intr.stop_count == 0) {
689                 /* An empty acquisition! */
690                 s->async->events |= COMEDI_CB_EOA;
691                 subpriv->dio.intr.active = 0;
692                 return 1;
693         } else {
694                 unsigned bits = 0, pol_bits = 0, n;
695                 int nports, firstport, asic, port;
696                 struct comedi_cmd *cmd = &s->async->cmd;
697
698                 asic = subpriv->dio.intr.asic;
699                 if (asic < 0)
700                         return 1;       /* not an interrupt
701                                            subdev */
702                 subpriv->dio.intr.enabled_mask = 0;
703                 subpriv->dio.intr.active = 1;
704                 nports = subpriv->dio.intr.num_asic_chans / CHANS_PER_PORT;
705                 firstport = subpriv->dio.intr.asic_chan / CHANS_PER_PORT;
706                 if (cmd->chanlist) {
707                         for (n = 0; n < cmd->chanlist_len; n++) {
708                                 bits |= (1U << CR_CHAN(cmd->chanlist[n]));
709                                 pol_bits |= (CR_AREF(cmd->chanlist[n])
710                                              || CR_RANGE(cmd->
711                                                          chanlist[n]) ? 1U : 0U)
712                                     << CR_CHAN(cmd->chanlist[n]);
713                         }
714                 }
715                 bits &= ((0x1 << subpriv->dio.intr.num_asic_chans) -
716                          1) << subpriv->dio.intr.first_chan;
717                 subpriv->dio.intr.enabled_mask = bits;
718
719                 {
720                         /*
721                          * the below code configures the board
722                          * to use a specific IRQ from 0-15.
723                          */
724                         unsigned char b;
725                         /*
726                          * set resource enable register
727                          * to enable IRQ operation
728                          */
729                         outb(1 << 4, dev->iobase + 3);
730                         /* set bits 0-3 of b to the irq number from 0-15 */
731                         b = dev->irq & ((1 << 4) - 1);
732                         outb(b, dev->iobase + 2);
733                         /* done, we told the board what irq to use */
734                 }
735
736                 switch_page(dev, asic, PAGE_ENAB);
737                 for (port = firstport; port < firstport + nports; ++port) {
738                         unsigned enab =
739                             bits >> (subpriv->dio.intr.first_chan + (port -
740                                                                      firstport)
741                                      * 8) & 0xff, pol =
742                             pol_bits >> (subpriv->dio.intr.first_chan +
743                                          (port - firstport) * 8) & 0xff;
744                         /* set enab intrs for this subdev.. */
745                         outb(enab,
746                              devpriv->asics[asic].iobase + REG_ENAB0 + port);
747                         switch_page(dev, asic, PAGE_POL);
748                         outb(pol,
749                              devpriv->asics[asic].iobase + REG_ENAB0 + port);
750                 }
751         }
752         return 0;
753 }
754
755 static int pcmmio_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
756 {
757         unsigned long flags;
758
759         spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags);
760         if (subpriv->dio.intr.active)
761                 pcmmio_stop_intr(dev, s);
762         spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags);
763
764         return 0;
765 }
766
767 /*
768  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
769  */
770 static int
771 pcmmio_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
772                           unsigned int trignum)
773 {
774         unsigned long flags;
775         int event = 0;
776
777         if (trignum != 0)
778                 return -EINVAL;
779
780         spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags);
781         s->async->inttrig = NULL;
782         if (subpriv->dio.intr.active)
783                 event = pcmmio_start_intr(dev, s);
784         spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags);
785
786         if (event)
787                 comedi_event(dev, s);
788
789         return 1;
790 }
791
792 /*
793  * 'do_cmd' function for an 'INTERRUPT' subdevice.
794  */
795 static int pcmmio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
796 {
797         struct comedi_cmd *cmd = &s->async->cmd;
798         unsigned long flags;
799         int event = 0;
800
801         spin_lock_irqsave(&subpriv->dio.intr.spinlock, flags);
802         subpriv->dio.intr.active = 1;
803
804         /* Set up end of acquisition. */
805         switch (cmd->stop_src) {
806         case TRIG_COUNT:
807                 subpriv->dio.intr.continuous = 0;
808                 subpriv->dio.intr.stop_count = cmd->stop_arg;
809                 break;
810         default:
811                 /* TRIG_NONE */
812                 subpriv->dio.intr.continuous = 1;
813                 subpriv->dio.intr.stop_count = 0;
814                 break;
815         }
816
817         /* Set up start of acquisition. */
818         switch (cmd->start_src) {
819         case TRIG_INT:
820                 s->async->inttrig = pcmmio_inttrig_start_intr;
821                 break;
822         default:
823                 /* TRIG_NOW */
824                 event = pcmmio_start_intr(dev, s);
825                 break;
826         }
827         spin_unlock_irqrestore(&subpriv->dio.intr.spinlock, flags);
828
829         if (event)
830                 comedi_event(dev, s);
831
832         return 0;
833 }
834
835 static int
836 pcmmio_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
837                struct comedi_cmd *cmd)
838 {
839         return comedi_pcm_cmdtest(dev, s, cmd);
840 }
841
842 static int adc_wait_ready(unsigned long iobase)
843 {
844         unsigned long retry = 100000;
845         while (retry--)
846                 if (inb(iobase + 3) & 0x80)
847                         return 0;
848         return 1;
849 }
850
851 /* All this is for AI and AO */
852 static int ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
853                     struct comedi_insn *insn, unsigned int *data)
854 {
855         int n;
856         unsigned long iobase = subpriv->iobase;
857
858         /*
859            1. write the CMD byte (to BASE+2)
860            2. read junk lo byte (BASE+0)
861            3. read junk hi byte (BASE+1)
862            4. (mux settled so) write CMD byte again (BASE+2)
863            5. read valid lo byte(BASE+0)
864            6. read valid hi byte(BASE+1)
865
866            Additionally note that the BASE += 4 if the channel >= 8
867          */
868
869         /* convert n samples */
870         for (n = 0; n < insn->n; n++) {
871                 unsigned chan = CR_CHAN(insn->chanspec), range =
872                     CR_RANGE(insn->chanspec), aref = CR_AREF(insn->chanspec);
873                 unsigned char command_byte = 0;
874                 unsigned iooffset = 0;
875                 short sample, adc_adjust = 0;
876
877                 if (chan > 7)
878                         chan -= 8, iooffset = 4;        /*
879                                                          * use the second dword
880                                                          * for channels > 7
881                                                          */
882
883                 if (aref != AREF_DIFF) {
884                         aref = AREF_GROUND;
885                         command_byte |= 1 << 7; /*
886                                                  * set bit 7 to indicate
887                                                  * single-ended
888                                                  */
889                 }
890                 if (range < 2)
891                         adc_adjust = 0x8000;    /*
892                                                  * bipolar ranges
893                                                  * (-5,5 .. -10,10 need to be
894                                                  * adjusted -- that is.. they
895                                                  * need to wrap around by
896                                                  * adding 0x8000
897                                                  */
898
899                 if (chan % 2) {
900                         command_byte |= 1 << 6; /*
901                                                  * odd-numbered channels
902                                                  * have bit 6 set
903                                                  */
904                 }
905
906                 /* select the channel, bits 4-5 == chan/2 */
907                 command_byte |= ((chan / 2) & 0x3) << 4;
908
909                 /* set the range, bits 2-3 */
910                 command_byte |= (range & 0x3) << 2;
911
912                 /* need to do this twice to make sure mux settled */
913                 /* chan/range/aref select */
914                 outb(command_byte, iobase + iooffset + 2);
915
916                 /* wait for the adc to say it finised the conversion */
917                 adc_wait_ready(iobase + iooffset);
918
919                 /* select the chan/range/aref AGAIN */
920                 outb(command_byte, iobase + iooffset + 2);
921
922                 adc_wait_ready(iobase + iooffset);
923
924                 /* read data lo byte */
925                 sample = inb(iobase + iooffset + 0);
926
927                 /* read data hi byte */
928                 sample |= inb(iobase + iooffset + 1) << 8;
929                 sample += adc_adjust;   /* adjustment .. munge data */
930                 data[n] = sample;
931         }
932         /* return the number of samples read/written */
933         return n;
934 }
935
936 static int ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
937                     struct comedi_insn *insn, unsigned int *data)
938 {
939         int n;
940         for (n = 0; n < insn->n; n++) {
941                 unsigned chan = CR_CHAN(insn->chanspec);
942                 if (chan < s->n_chan)
943                         data[n] = subpriv->ao.shadow_samples[chan];
944         }
945         return n;
946 }
947
948 static int wait_dac_ready(unsigned long iobase)
949 {
950         unsigned long retry = 100000L;
951
952         /* This may seem like an absurd way to handle waiting and violates the
953            "no busy waiting" policy. The fact is that the hardware is
954            normally so fast that we usually only need one time through the loop
955            anyway. The longer timeout is for rare occasions and for detecting
956            non-existent hardware.  */
957
958         while (retry--) {
959                 if (inb(iobase + 3) & 0x80)
960                         return 0;
961
962         }
963         return 1;
964 }
965
966 static int ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
967                     struct comedi_insn *insn, unsigned int *data)
968 {
969         int n;
970         unsigned iobase = subpriv->iobase, iooffset = 0;
971
972         for (n = 0; n < insn->n; n++) {
973                 unsigned chan = CR_CHAN(insn->chanspec), range =
974                     CR_RANGE(insn->chanspec);
975                 if (chan < s->n_chan) {
976                         unsigned char command_byte = 0, range_byte =
977                             range & ((1 << 4) - 1);
978                         if (chan >= 4)
979                                 chan -= 4, iooffset += 4;
980                         /* set the range.. */
981                         outb(range_byte, iobase + iooffset + 0);
982                         outb(0, iobase + iooffset + 1);
983
984                         /* tell it to begin */
985                         command_byte = (chan << 1) | 0x60;
986                         outb(command_byte, iobase + iooffset + 2);
987
988                         wait_dac_ready(iobase + iooffset);
989
990                         /* low order byte */
991                         outb(data[n] & 0xff, iobase + iooffset + 0);
992
993                         /* high order byte */
994                         outb((data[n] >> 8) & 0xff, iobase + iooffset + 1);
995
996                         /*
997                          * set bit 4 of command byte to indicate
998                          * data is loaded and trigger conversion
999                          */
1000                         command_byte = 0x70 | (chan << 1);
1001                         /* trigger converion */
1002                         outb(command_byte, iobase + iooffset + 2);
1003
1004                         wait_dac_ready(iobase + iooffset);
1005
1006                         /* save to shadow register for ao_rinsn */
1007                         subpriv->ao.shadow_samples[chan] = data[n];
1008                 }
1009         }
1010         return n;
1011 }
1012
1013 static int pcmmio_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1014 {
1015         const struct pcmmio_board *board = comedi_board(dev);
1016         struct comedi_subdevice *s;
1017         int sdev_no, chans_left, n_dio_subdevs, n_subdevs, port, asic,
1018             thisasic_chanct = 0;
1019         unsigned long iobase;
1020         unsigned int irq[MAX_ASICS];
1021         int ret;
1022
1023         iobase = it->options[0];
1024         irq[0] = it->options[1];
1025
1026         printk(KERN_INFO "comedi%d: %s: io: %lx attaching...\n", dev->minor,
1027                         dev->driver->driver_name, iobase);
1028
1029         dev->iobase = iobase;
1030
1031         if (!iobase || !request_region(iobase,
1032                                        board->total_iosize,
1033                                        dev->driver->driver_name)) {
1034                 printk(KERN_ERR "comedi%d: I/O port conflict\n", dev->minor);
1035                 return -EIO;
1036         }
1037
1038         dev->board_name = board->name;
1039
1040 /*
1041  * Allocate the private structure area.  alloc_private() is a
1042  * convenient macro defined in comedidev.h.
1043  */
1044         if (alloc_private(dev, sizeof(struct pcmmio_private)) < 0) {
1045                 printk(KERN_ERR "comedi%d: cannot allocate private data structure\n",
1046                                 dev->minor);
1047                 return -ENOMEM;
1048         }
1049
1050         for (asic = 0; asic < MAX_ASICS; ++asic) {
1051                 devpriv->asics[asic].num = asic;
1052                 devpriv->asics[asic].iobase =
1053                     dev->iobase + 16 + asic * ASIC_IOSIZE;
1054                 /*
1055                  * this gets actually set at the end of this function when we
1056                  * request_irqs
1057                  */
1058                 devpriv->asics[asic].irq = 0;
1059                 spin_lock_init(&devpriv->asics[asic].spinlock);
1060         }
1061
1062         chans_left = CHANS_PER_ASIC * board->dio_num_asics;
1063         n_dio_subdevs = CALC_N_DIO_SUBDEVS(chans_left);
1064         n_subdevs = n_dio_subdevs + 2;
1065         devpriv->sprivs =
1066             kcalloc(n_subdevs, sizeof(struct pcmmio_subdev_private),
1067                     GFP_KERNEL);
1068         if (!devpriv->sprivs) {
1069                 printk(KERN_ERR "comedi%d: cannot allocate subdevice private data structures\n",
1070                                 dev->minor);
1071                 return -ENOMEM;
1072         }
1073
1074         ret = comedi_alloc_subdevices(dev, n_subdevs);
1075         if (ret)
1076                 return ret;
1077
1078         /* First, AI */
1079         s = &dev->subdevices[0];
1080         s->private = &devpriv->sprivs[0];
1081         s->maxdata = (1 << board->ai_bits) - 1;
1082         s->range_table = board->ai_range_table;
1083         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
1084         s->type = COMEDI_SUBD_AI;
1085         s->n_chan = board->n_ai_chans;
1086         s->len_chanlist = s->n_chan;
1087         s->insn_read = board->ai_rinsn;
1088         subpriv->iobase = dev->iobase + 0;
1089         /* initialize the resource enable register by clearing it */
1090         outb(0, subpriv->iobase + 3);
1091         outb(0, subpriv->iobase + 4 + 3);
1092
1093         /* Next, AO */
1094         s = &dev->subdevices[1];
1095         s->private = &devpriv->sprivs[1];
1096         s->maxdata = (1 << board->ao_bits) - 1;
1097         s->range_table = board->ao_range_table;
1098         s->subdev_flags = SDF_READABLE;
1099         s->type = COMEDI_SUBD_AO;
1100         s->n_chan = board->n_ao_chans;
1101         s->len_chanlist = s->n_chan;
1102         s->insn_read = board->ao_rinsn;
1103         s->insn_write = board->ao_winsn;
1104         subpriv->iobase = dev->iobase + 8;
1105         /* initialize the resource enable register by clearing it */
1106         outb(0, subpriv->iobase + 3);
1107         outb(0, subpriv->iobase + 4 + 3);
1108
1109         port = 0;
1110         asic = 0;
1111         for (sdev_no = 2; sdev_no < dev->n_subdevices; ++sdev_no) {
1112                 int byte_no;
1113
1114                 s = &dev->subdevices[sdev_no];
1115                 s->private = &devpriv->sprivs[sdev_no];
1116                 s->maxdata = 1;
1117                 s->range_table = &range_digital;
1118                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1119                 s->type = COMEDI_SUBD_DIO;
1120                 s->insn_bits = pcmmio_dio_insn_bits;
1121                 s->insn_config = pcmmio_dio_insn_config;
1122                 s->n_chan = min(chans_left, MAX_CHANS_PER_SUBDEV);
1123                 subpriv->dio.intr.asic = -1;
1124                 subpriv->dio.intr.first_chan = -1;
1125                 subpriv->dio.intr.asic_chan = -1;
1126                 subpriv->dio.intr.num_asic_chans = -1;
1127                 subpriv->dio.intr.active = 0;
1128                 s->len_chanlist = 1;
1129
1130                 /* save the ioport address for each 'port' of 8 channels in the
1131                    subdevice */
1132                 for (byte_no = 0; byte_no < PORTS_PER_SUBDEV; ++byte_no, ++port) {
1133                         if (port >= PORTS_PER_ASIC) {
1134                                 port = 0;
1135                                 ++asic;
1136                                 thisasic_chanct = 0;
1137                         }
1138                         subpriv->iobases[byte_no] =
1139                             devpriv->asics[asic].iobase + port;
1140
1141                         if (thisasic_chanct <
1142                             CHANS_PER_PORT * INTR_PORTS_PER_ASIC
1143                             && subpriv->dio.intr.asic < 0) {
1144                                 /*
1145                                  * this is an interrupt subdevice,
1146                                  * so setup the struct
1147                                  */
1148                                 subpriv->dio.intr.asic = asic;
1149                                 subpriv->dio.intr.active = 0;
1150                                 subpriv->dio.intr.stop_count = 0;
1151                                 subpriv->dio.intr.first_chan = byte_no * 8;
1152                                 subpriv->dio.intr.asic_chan = thisasic_chanct;
1153                                 subpriv->dio.intr.num_asic_chans =
1154                                     s->n_chan - subpriv->dio.intr.first_chan;
1155                                 s->cancel = pcmmio_cancel;
1156                                 s->do_cmd = pcmmio_cmd;
1157                                 s->do_cmdtest = pcmmio_cmdtest;
1158                                 s->len_chanlist =
1159                                     subpriv->dio.intr.num_asic_chans;
1160                         }
1161                         thisasic_chanct += CHANS_PER_PORT;
1162                 }
1163                 spin_lock_init(&subpriv->dio.intr.spinlock);
1164
1165                 chans_left -= s->n_chan;
1166
1167                 if (!chans_left) {
1168                         /*
1169                          * reset the asic to our first asic,
1170                          * to do intr subdevs
1171                          */
1172                         asic = 0;
1173                         port = 0;
1174                 }
1175
1176         }
1177
1178         init_asics(dev);        /* clear out all the registers, basically */
1179
1180         for (asic = 0; irq[0] && asic < MAX_ASICS; ++asic) {
1181                 if (irq[asic]
1182                     && request_irq(irq[asic], interrupt_pcmmio,
1183                                    IRQF_SHARED, board->name, dev)) {
1184                         int i;
1185                         /* unroll the allocated irqs.. */
1186                         for (i = asic - 1; i >= 0; --i) {
1187                                 free_irq(irq[i], dev);
1188                                 devpriv->asics[i].irq = irq[i] = 0;
1189                         }
1190                         irq[asic] = 0;
1191                 }
1192                 devpriv->asics[asic].irq = irq[asic];
1193         }
1194
1195         dev->irq = irq[0];      /*
1196                                  * grr.. wish comedi dev struct supported
1197                                  * multiple irqs..
1198                                  */
1199
1200         printk(KERN_INFO "comedi%d: attached\n", dev->minor);
1201
1202         return 1;
1203 }
1204
1205 static void pcmmio_detach(struct comedi_device *dev)
1206 {
1207         const struct pcmmio_board *board = comedi_board(dev);
1208         int i;
1209
1210         if (dev->iobase)
1211                 release_region(dev->iobase, board->total_iosize);
1212         for (i = 0; i < MAX_ASICS; ++i) {
1213                 if (devpriv && devpriv->asics[i].irq)
1214                         free_irq(devpriv->asics[i].irq, dev);
1215         }
1216         if (devpriv && devpriv->sprivs)
1217                 kfree(devpriv->sprivs);
1218 }
1219
1220 static const struct pcmmio_board pcmmio_boards[] = {
1221         {
1222                 .name           = "pcmmio",
1223                 .dio_num_asics  = 1,
1224                 .dio_num_ports  = 6,
1225                 .total_iosize   = 32,
1226                 .ai_bits        = 16,
1227                 .ao_bits        = 16,
1228                 .n_ai_chans     = 16,
1229                 .n_ao_chans     = 8,
1230                 .ai_range_table = &ranges_ai,
1231                 .ao_range_table = &ranges_ao,
1232                 .ai_rinsn       = ai_rinsn,
1233                 .ao_rinsn       = ao_rinsn,
1234                 .ao_winsn       = ao_winsn
1235         },
1236 };
1237
1238 static struct comedi_driver pcmmio_driver = {
1239         .driver_name    = "pcmmio",
1240         .module         = THIS_MODULE,
1241         .attach         = pcmmio_attach,
1242         .detach         = pcmmio_detach,
1243         .board_name     = &pcmmio_boards[0].name,
1244         .offset         = sizeof(struct pcmmio_board),
1245         .num_names      = ARRAY_SIZE(pcmmio_boards),
1246 };
1247 module_comedi_driver(pcmmio_driver);
1248
1249 MODULE_AUTHOR("Comedi http://www.comedi.org");
1250 MODULE_DESCRIPTION("Comedi low-level driver");
1251 MODULE_LICENSE("GPL");