2 comedi/drivers/adl_pci8164.c
4 Hardware comedi driver fot PCI-8164 Adlink card
5 Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 Description: Driver for the Adlink PCI-8164 4 Axes Motion Control board
25 Devices: [ADLink] PCI-8164 (adl_pci8164)
26 Author: Michel Lachaine <mike@mikelachaine.ca>
28 Updated: Mon, 14 Apr 2008 15:10:32 +0100
30 Configuration Options: not applicable, uses PCI auto config
33 #include <linux/kernel.h>
34 #include <linux/pci.h>
35 #include <linux/delay.h>
37 #include "../comedidev.h"
38 #include "comedi_fc.h"
41 #define PCI8164_AXIS_X 0x00
42 #define PCI8164_AXIS_Y 0x08
43 #define PCI8164_AXIS_Z 0x10
44 #define PCI8164_AXIS_U 0x18
46 #define PCI8164_MSTS 0x00
47 #define PCI8164_SSTS 0x02
48 #define PCI8164_BUF0 0x04
49 #define PCI8164_BUF1 0x06
51 #define PCI8164_CMD 0x00
52 #define PCI8164_OTP 0x02
54 #define PCI_DEVICE_ID_PCI8164 0x8164
57 all the read commands are the same except for the addition a constant
58 * const to the data for inw()
60 static void adl_pci8164_insn_read(struct comedi_device
*dev
,
61 struct comedi_subdevice
*s
,
62 struct comedi_insn
*insn
,
64 char *action
, unsigned short offset
)
69 axis
= CR_CHAN(insn
->chanspec
);
73 axis_reg
= PCI8164_AXIS_X
;
77 axis_reg
= PCI8164_AXIS_Y
;
81 axis_reg
= PCI8164_AXIS_Z
;
85 axis_reg
= PCI8164_AXIS_U
;
89 axis_reg
= PCI8164_AXIS_X
;
93 data
[0] = inw(dev
->iobase
+ axis_reg
+ offset
);
94 dev_dbg(dev
->class_dev
,
95 "pci8164 %s read -> %04X:%04X on axis %c\n",
96 action
, data
[0], data
[1], axisname
);
99 static int adl_pci8164_insn_read_msts(struct comedi_device
*dev
,
100 struct comedi_subdevice
*s
,
101 struct comedi_insn
*insn
,
104 adl_pci8164_insn_read(dev
, s
, insn
, data
, "MSTS", PCI8164_MSTS
);
108 static int adl_pci8164_insn_read_ssts(struct comedi_device
*dev
,
109 struct comedi_subdevice
*s
,
110 struct comedi_insn
*insn
,
113 adl_pci8164_insn_read(dev
, s
, insn
, data
, "SSTS", PCI8164_SSTS
);
117 static int adl_pci8164_insn_read_buf0(struct comedi_device
*dev
,
118 struct comedi_subdevice
*s
,
119 struct comedi_insn
*insn
,
122 adl_pci8164_insn_read(dev
, s
, insn
, data
, "BUF0", PCI8164_BUF0
);
126 static int adl_pci8164_insn_read_buf1(struct comedi_device
*dev
,
127 struct comedi_subdevice
*s
,
128 struct comedi_insn
*insn
,
131 adl_pci8164_insn_read(dev
, s
, insn
, data
, "BUF1", PCI8164_BUF1
);
136 all the write commands are the same except for the addition a constant
137 * const to the data for outw()
139 static void adl_pci8164_insn_out(struct comedi_device
*dev
,
140 struct comedi_subdevice
*s
,
141 struct comedi_insn
*insn
,
143 char *action
, unsigned short offset
)
145 unsigned int axis
, axis_reg
;
149 axis
= CR_CHAN(insn
->chanspec
);
153 axis_reg
= PCI8164_AXIS_X
;
157 axis_reg
= PCI8164_AXIS_Y
;
161 axis_reg
= PCI8164_AXIS_Z
;
165 axis_reg
= PCI8164_AXIS_U
;
169 axis_reg
= PCI8164_AXIS_X
;
173 outw(data
[0], dev
->iobase
+ axis_reg
+ offset
);
175 dev_dbg(dev
->class_dev
,
176 "pci8164 %s write -> %04X:%04X on axis %c\n",
177 action
, data
[0], data
[1], axisname
);
181 static int adl_pci8164_insn_write_cmd(struct comedi_device
*dev
,
182 struct comedi_subdevice
*s
,
183 struct comedi_insn
*insn
,
186 adl_pci8164_insn_out(dev
, s
, insn
, data
, "CMD", PCI8164_CMD
);
190 static int adl_pci8164_insn_write_otp(struct comedi_device
*dev
,
191 struct comedi_subdevice
*s
,
192 struct comedi_insn
*insn
,
195 adl_pci8164_insn_out(dev
, s
, insn
, data
, "OTP", PCI8164_OTP
);
199 static int adl_pci8164_insn_write_buf0(struct comedi_device
*dev
,
200 struct comedi_subdevice
*s
,
201 struct comedi_insn
*insn
,
204 adl_pci8164_insn_out(dev
, s
, insn
, data
, "BUF0", PCI8164_BUF0
);
208 static int adl_pci8164_insn_write_buf1(struct comedi_device
*dev
,
209 struct comedi_subdevice
*s
,
210 struct comedi_insn
*insn
,
213 adl_pci8164_insn_out(dev
, s
, insn
, data
, "BUF1", PCI8164_BUF1
);
217 static int adl_pci8164_auto_attach(struct comedi_device
*dev
,
218 unsigned long context_unused
)
220 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
221 struct comedi_subdevice
*s
;
224 dev
->board_name
= dev
->driver
->driver_name
;
226 ret
= comedi_pci_enable(pcidev
, dev
->board_name
);
229 dev
->iobase
= pci_resource_start(pcidev
, 2);
231 ret
= comedi_alloc_subdevices(dev
, 4);
235 s
= &dev
->subdevices
[0];
236 s
->type
= COMEDI_SUBD_PROC
;
237 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
241 /* s->range_table = &range_axis; */
242 s
->insn_read
= adl_pci8164_insn_read_msts
;
243 s
->insn_write
= adl_pci8164_insn_write_cmd
;
245 s
= &dev
->subdevices
[1];
246 s
->type
= COMEDI_SUBD_PROC
;
247 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
251 /* s->range_table = &range_axis; */
252 s
->insn_read
= adl_pci8164_insn_read_ssts
;
253 s
->insn_write
= adl_pci8164_insn_write_otp
;
255 s
= &dev
->subdevices
[2];
256 s
->type
= COMEDI_SUBD_PROC
;
257 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
261 /* s->range_table = &range_axis; */
262 s
->insn_read
= adl_pci8164_insn_read_buf0
;
263 s
->insn_write
= adl_pci8164_insn_write_buf0
;
265 s
= &dev
->subdevices
[3];
266 s
->type
= COMEDI_SUBD_PROC
;
267 s
->subdev_flags
= SDF_READABLE
| SDF_WRITABLE
;
271 /* s->range_table = &range_axis; */
272 s
->insn_read
= adl_pci8164_insn_read_buf1
;
273 s
->insn_write
= adl_pci8164_insn_write_buf1
;
275 dev_info(dev
->class_dev
, "%s attached\n", dev
->board_name
);
280 static void adl_pci8164_detach(struct comedi_device
*dev
)
282 struct pci_dev
*pcidev
= comedi_to_pci_dev(dev
);
286 comedi_pci_disable(pcidev
);
290 static struct comedi_driver adl_pci8164_driver
= {
291 .driver_name
= "adl_pci8164",
292 .module
= THIS_MODULE
,
293 .auto_attach
= adl_pci8164_auto_attach
,
294 .detach
= adl_pci8164_detach
,
297 static int adl_pci8164_pci_probe(struct pci_dev
*dev
,
298 const struct pci_device_id
*ent
)
300 return comedi_pci_auto_config(dev
, &adl_pci8164_driver
);
303 static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table
) = {
304 { PCI_DEVICE(PCI_VENDOR_ID_ADLINK
, PCI_DEVICE_ID_PCI8164
) },
307 MODULE_DEVICE_TABLE(pci
, adl_pci8164_pci_table
);
309 static struct pci_driver adl_pci8164_pci_driver
= {
310 .name
= "adl_pci8164",
311 .id_table
= adl_pci8164_pci_table
,
312 .probe
= adl_pci8164_pci_probe
,
313 .remove
= comedi_pci_auto_unconfig
,
315 module_comedi_pci_driver(adl_pci8164_driver
, adl_pci8164_pci_driver
);
317 MODULE_AUTHOR("Comedi http://www.comedi.org");
318 MODULE_DESCRIPTION("Comedi low-level driver");
319 MODULE_LICENSE("GPL");