Commit | Line | Data |
---|---|---|
6eb78a1b | 1 | /* |
92d7323b HS |
2 | * comedi/drivers/adl_pci8164.c |
3 | * | |
4 | * Hardware comedi driver for PCI-8164 Adlink card | |
5 | * Copyright (C) 2004 Michel Lachine <mike@mikelachaine.ca> | |
6 | * | |
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. | |
11 | * | |
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. | |
16 | * | |
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. | |
20 | */ | |
6eb78a1b | 21 | |
6eb78a1b | 22 | /* |
92d7323b HS |
23 | * Driver: adl_pci8164 |
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> | |
27 | * Status: experimental | |
28 | * Updated: Mon, 14 Apr 2008 15:10:32 +0100 | |
29 | * | |
30 | * Configuration Options: not applicable, uses PCI auto config | |
31 | */ | |
6eb78a1b | 32 | |
bacf58a8 | 33 | #include <linux/kernel.h> |
33782dd5 | 34 | #include <linux/pci.h> |
33782dd5 HS |
35 | |
36 | #include "../comedidev.h" | |
6eb78a1b | 37 | |
d99fc2c3 | 38 | #define PCI8164_AXIS(x) ((x) * 0x08) |
a6c57d2e HS |
39 | #define PCI8164_CMD_MSTS_REG 0x00 |
40 | #define PCI8164_OTP_SSTS_REG 0x02 | |
41 | #define PCI8164_BUF0_REG 0x04 | |
42 | #define PCI8164_BUF1_REG 0x06 | |
6eb78a1b | 43 | |
a6c57d2e | 44 | static int adl_pci8164_insn_read(struct comedi_device *dev, |
0a85b6f0 MT |
45 | struct comedi_subdevice *s, |
46 | struct comedi_insn *insn, | |
a6c57d2e | 47 | unsigned int *data) |
6eb78a1b | 48 | { |
a6c57d2e | 49 | unsigned long offset = (unsigned long)s->private; |
d99fc2c3 | 50 | unsigned int chan = CR_CHAN(insn->chanspec); |
a6c57d2e | 51 | int i; |
d99fc2c3 | 52 | |
a6c57d2e HS |
53 | for (i = 0; i < insn->n; i++) |
54 | data[i] = inw(dev->iobase + PCI8164_AXIS(chan) + offset); | |
ba7834b3 | 55 | |
a6c57d2e | 56 | return insn->n; |
6eb78a1b ML |
57 | } |
58 | ||
a6c57d2e HS |
59 | static int adl_pci8164_insn_write(struct comedi_device *dev, |
60 | struct comedi_subdevice *s, | |
61 | struct comedi_insn *insn, | |
62 | unsigned int *data) | |
6eb78a1b | 63 | { |
a6c57d2e HS |
64 | unsigned long offset = (unsigned long)s->private; |
65 | unsigned int chan = CR_CHAN(insn->chanspec); | |
66 | int i; | |
6eb78a1b | 67 | |
a6c57d2e HS |
68 | for (i = 0; i < insn->n; i++) |
69 | outw(data[i], dev->iobase + PCI8164_AXIS(chan) + offset); | |
6eb78a1b | 70 | |
a6c57d2e | 71 | return insn->n; |
6eb78a1b ML |
72 | } |
73 | ||
a690b7e5 | 74 | static int adl_pci8164_auto_attach(struct comedi_device *dev, |
750af5e5 | 75 | unsigned long context_unused) |
d3ff7b93 | 76 | { |
750af5e5 | 77 | struct pci_dev *pcidev = comedi_to_pci_dev(dev); |
bb4806ae | 78 | struct comedi_subdevice *s; |
8b6c5694 | 79 | int ret; |
bb4806ae | 80 | |
6bfbd988 | 81 | dev->board_name = dev->driver->driver_name; |
bb4806ae | 82 | |
818f569f | 83 | ret = comedi_pci_enable(dev); |
8b6c5694 HS |
84 | if (ret) |
85 | return ret; | |
35260aa6 | 86 | dev->iobase = pci_resource_start(pcidev, 2); |
6bfbd988 HS |
87 | |
88 | ret = comedi_alloc_subdevices(dev, 4); | |
89 | if (ret) | |
90 | return ret; | |
d3ff7b93 | 91 | |
a6c57d2e | 92 | /* read MSTS register / write CMD register for each axis (channel) */ |
b23faec8 | 93 | s = &dev->subdevices[0]; |
a6c57d2e HS |
94 | s->type = COMEDI_SUBD_PROC; |
95 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
96 | s->n_chan = 4; | |
97 | s->maxdata = 0xffff; | |
98 | s->len_chanlist = 4; | |
99 | s->insn_read = adl_pci8164_insn_read; | |
100 | s->insn_write = adl_pci8164_insn_write; | |
101 | s->private = (void *)PCI8164_CMD_MSTS_REG; | |
102 | ||
103 | /* read SSTS register / write OTP register for each axis (channel) */ | |
b23faec8 | 104 | s = &dev->subdevices[1]; |
a6c57d2e HS |
105 | s->type = COMEDI_SUBD_PROC; |
106 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
107 | s->n_chan = 4; | |
108 | s->maxdata = 0xffff; | |
109 | s->len_chanlist = 4; | |
110 | s->insn_read = adl_pci8164_insn_read; | |
111 | s->insn_write = adl_pci8164_insn_write; | |
112 | s->private = (void *)PCI8164_OTP_SSTS_REG; | |
113 | ||
114 | /* read/write BUF0 register for each axis (channel) */ | |
b23faec8 | 115 | s = &dev->subdevices[2]; |
a6c57d2e HS |
116 | s->type = COMEDI_SUBD_PROC; |
117 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
118 | s->n_chan = 4; | |
119 | s->maxdata = 0xffff; | |
120 | s->len_chanlist = 4; | |
121 | s->insn_read = adl_pci8164_insn_read; | |
122 | s->insn_write = adl_pci8164_insn_write; | |
123 | s->private = (void *)PCI8164_BUF0_REG; | |
124 | ||
125 | /* read/write BUF1 register for each axis (channel) */ | |
b23faec8 | 126 | s = &dev->subdevices[3]; |
a6c57d2e HS |
127 | s->type = COMEDI_SUBD_PROC; |
128 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; | |
129 | s->n_chan = 4; | |
130 | s->maxdata = 0xffff; | |
131 | s->len_chanlist = 4; | |
132 | s->insn_read = adl_pci8164_insn_read; | |
133 | s->insn_write = adl_pci8164_insn_write; | |
134 | s->private = (void *)PCI8164_BUF1_REG; | |
6bfbd988 | 135 | |
d3ff7b93 | 136 | return 0; |
bb4806ae HS |
137 | } |
138 | ||
75e6301b | 139 | static struct comedi_driver adl_pci8164_driver = { |
bb4806ae HS |
140 | .driver_name = "adl_pci8164", |
141 | .module = THIS_MODULE, | |
750af5e5 | 142 | .auto_attach = adl_pci8164_auto_attach, |
7f072f54 | 143 | .detach = comedi_pci_disable, |
bb4806ae HS |
144 | }; |
145 | ||
a690b7e5 | 146 | static int adl_pci8164_pci_probe(struct pci_dev *dev, |
b8f4ac23 | 147 | const struct pci_device_id *id) |
727b286b | 148 | { |
b8f4ac23 HS |
149 | return comedi_pci_auto_config(dev, &adl_pci8164_driver, |
150 | id->driver_data); | |
727b286b AT |
151 | } |
152 | ||
bb4806ae | 153 | static DEFINE_PCI_DEVICE_TABLE(adl_pci8164_pci_table) = { |
83dcad47 HS |
154 | { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, 0x8164) }, |
155 | { 0 } | |
bb4806ae HS |
156 | }; |
157 | MODULE_DEVICE_TABLE(pci, adl_pci8164_pci_table); | |
158 | ||
75e6301b HS |
159 | static struct pci_driver adl_pci8164_pci_driver = { |
160 | .name = "adl_pci8164", | |
bb4806ae | 161 | .id_table = adl_pci8164_pci_table, |
75e6301b | 162 | .probe = adl_pci8164_pci_probe, |
9901a4d7 | 163 | .remove = comedi_pci_auto_unconfig, |
727b286b | 164 | }; |
75e6301b | 165 | module_comedi_pci_driver(adl_pci8164_driver, adl_pci8164_pci_driver); |
90f703d3 AT |
166 | |
167 | MODULE_AUTHOR("Comedi http://www.comedi.org"); | |
168 | MODULE_DESCRIPTION("Comedi low-level driver"); | |
169 | MODULE_LICENSE("GPL"); |