Constified ranges, board structures, and miscellaneous data.
[comedi.git] / comedi / drivers / pcl724.c
1 /*
2     module/pcl724.c
3
4     Michal Dobes <dobes@tesnet.cz>
5
6     hardware driver for Advantech cards:
7      card:   PCL-724, PCL-722, PCL-731
8      driver: pcl724,  pcl722,  pcl731
9     and ADLink cards:
10      card:   ACL-7122, ACL-7124, PET-48DIO
11      driver: acl7122,  acl7124,  pet48dio
12
13     Options for PCL-724, PCL-731, ACL-7124 and PET-48DIO:
14      [0] - IO Base
15
16     Options for PCL-722 and ACL-7122:
17      [0] - IO Base
18      [1] - IRQ (0=disable IRQ) IRQ isn't supported at this time!
19      [2] -number of DIO:
20               0, 144: 144 DIO configuration
21               1,  96:  96 DIO configuration
22 */
23 /*
24 Driver: pcl724.o
25 Description: Advantech PCL-724, PCL-722, PCL-731 ADLink ACL-7122, ACL-7124,
26   PET-48DIO
27 Author: Michal Dobes <dobes@tesnet.cz>
28 Devices: [Advantech] PCL-724 (pcl724), PCL-722 (pcl722), PCL-731 (pcl731),
29   [ADLink] ACL-7122 (acl7122), ACL-7124 (acl7124), PET-48DIO (pet48dio)
30 Status: untested
31
32 This is driver for digital I/O boards PCL-722/724/731 with 144/24/48 DIO
33 and for digital I/O boards ACL-7122/7124/PET-48DIO with 144/24/48 DIO.
34 It need 8255.o for operations and only immediate mode is supported.
35 See the source for configuration details.
36 */
37 /*
38  * check_driver overrides:
39  *   comedi_insn
40  */
41
42 #include <linux/comedidev.h>
43
44 #include <linux/ioport.h>
45 #include <linux/delay.h>
46
47 #include "8255.h"
48
49 #define PCL722_SIZE    32
50 #define PCL722_96_SIZE 16
51 #define PCL724_SIZE     4
52 #define PCL731_SIZE     8
53 #define PET48_SIZE      2
54
55 #define SIZE_8255       4
56
57 // #define PCL724_IRQ   1  /* no IRQ support now */
58
59 static int pcl724_attach(comedi_device *dev,comedi_devconfig *it);
60 static int pcl724_detach(comedi_device *dev);
61
62 typedef struct {
63         const char              *name;          // board name
64         int             dio;            // num of DIO
65         int             numofports;     // num of 8255 subdevices
66         unsigned int    IRQbits;        // allowed interrupts
67         unsigned int    io_range;       // len of IO space
68         char            can_have96;
69         char            is_pet48;
70 } boardtype;
71
72 static const boardtype boardtypes[] =
73 {
74         {"pcl724",    24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
75         {"pcl722",   144, 6, 0x00fc, PCL722_SIZE, 1, 0, },
76         {"pcl731",    48, 2, 0x9cfc, PCL731_SIZE, 0, 0, },
77         {"acl7122",  144, 6, 0x9ee8, PCL722_SIZE, 1, 0, },
78         {"acl7124",   24, 1, 0x00fc, PCL724_SIZE, 0, 0, },
79         {"pet48dio",  48, 2, 0x9eb8, PET48_SIZE,  0, 1, },
80 };
81
82 #define n_boardtypes (sizeof(boardtypes)/sizeof(boardtype))
83 #define this_board ((const boardtype *)dev->board_ptr)
84
85 static comedi_driver driver_pcl724={
86         driver_name:    "pcl724",
87         module:         THIS_MODULE,
88         attach:         pcl724_attach,
89         detach:         pcl724_detach,
90         board_name:     &boardtypes[0].name,
91         num_names:      n_boardtypes,
92         offset:         sizeof(boardtype),
93 };
94 COMEDI_INITCLEANUP(driver_pcl724);
95
96
97 static int subdev_8255_cb(int dir,int port,int data,unsigned long arg)
98 {
99         unsigned long iobase=arg;
100
101         if(dir){
102                 outb(data,iobase+port);
103                 return 0;
104         }else{
105                 return inb(iobase+port);
106         }
107 }
108
109 static int subdev_8255mapped_cb(int dir,int port,int data,unsigned long iobase)
110 {
111         int movport=SIZE_8255*(iobase>>12);
112
113         iobase&=0x0fff;
114
115         if(dir){
116                 outb(port+movport,iobase);
117                 outb(data,iobase+1);
118                 return 0;
119         }else{
120                 outb(port+movport,iobase);
121                 return inb(iobase+1);
122         }
123 }
124
125 static int pcl724_attach(comedi_device *dev,comedi_devconfig *it)
126 {
127         unsigned long iobase;
128         unsigned int iorange;
129         int ret,i,n_subdevices;
130 #ifdef PCL724_IRQ
131         unsigned int irq;
132 #endif
133
134         iobase=it->options[0];
135         iorange=this_board->io_range;
136         if ((this_board->can_have96)&&((it->options[1]==1)||(it->options[1]==96)))
137                 iorange=PCL722_96_SIZE; // PCL-724 in 96 DIO configuration
138         printk("comedi%d: pcl724: board=%s, 0x%03lx ",dev->minor,
139                 this_board->name,iobase);
140         if(!request_region(iobase, iorange, "pcl724")){
141                 printk("I/O port conflict\n");
142                 return -EIO;
143         }
144
145         dev->iobase=iobase;
146
147         dev->board_name = this_board->name;
148
149 #ifdef PCL724_IRQ
150         irq=0;
151         if (this_board->IRQbits!=0) { /* board support IRQ */
152                 irq=it->options[1];
153                 if (irq)  {/* we want to use IRQ */
154                         if (((1<<irq)&this_board->IRQbits)==0) {
155                                 rt_printk(", IRQ %u is out of allowed range, DISABLING IT",irq);
156                                 irq=0; /* Bad IRQ */
157                         } else {
158                                 if (comedi_request_irq(irq, interrupt_pcl724, 0, "pcl724", dev)) {
159                                         rt_printk(", unable to allocate IRQ %u, DISABLING IT", irq);
160                                         irq=0; /* Can't use IRQ */
161                                 } else {
162                                         rt_printk(", irq=%u", irq);
163                                 }
164                         }
165                 }
166         }
167
168         dev->irq = irq;
169 #endif
170
171         printk("\n");
172
173         n_subdevices=this_board->numofports;
174         if ((this_board->can_have96)&&((it->options[1]==1)||(it->options[1]==96)))
175                 n_subdevices=4; // PCL-724 in 96 DIO configuration
176
177         if((ret=alloc_subdevices(dev, n_subdevices))<0)
178                 return ret;
179
180         for(i=0;i<dev->n_subdevices;i++){
181                 if (this_board->is_pet48) {
182                         subdev_8255_init(dev,dev->subdevices+i,
183                                 subdev_8255mapped_cb,(unsigned long)(dev->iobase+i*0x1000));
184                 } else
185                         subdev_8255_init(dev,dev->subdevices+i,
186                                 subdev_8255_cb,(unsigned long)(dev->iobase+SIZE_8255*i));
187         };
188
189         return 0;
190 }
191
192
193 static int pcl724_detach(comedi_device *dev)
194 {
195         int i;
196
197 //      printk("comedi%d: pcl724: remove\n",dev->minor);
198
199         for(i=0;i<dev->n_subdevices;i++){
200                 subdev_8255_cleanup(dev,dev->subdevices+i);
201         }
202
203 #ifdef PCL724_IRQ
204         if(dev->irq){
205                 comedi_free_irq(dev->irq,dev);
206         }
207 #endif
208
209         release_region(dev->iobase,this_board->io_range);
210
211         return 0;
212 }
213
214