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