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