1 #include "../comedidev.h"
4 #define PCI_VENDOR_ID_MF614 0x186c
5 #define PCI_DEVICE_ID_MF614 0x0614
11 static struct pci_device_id mf614_pci_table[] __devinitdata = {
12 { PCI_VENDOR_ID_MF614, PCI_DEVICE_ID_MF614, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
15 MODULE_DEVICE_TABLE(pci, mf614_pci_table);
18 typedef struct mf614_board_struct {
20 unsigned short device_id;
21 unsigned int ai_chans;
23 unsigned int ao_chans;
25 unsigned int di_chans;
26 unsigned int do_chans;
29 static const mf614_board mf614_boards[] = {
31 name: "mf614", /* device name */
32 device_id: PCI_DEVICE_ID_MF614, /* PCI dev ID */
33 ai_chans: 8, /* Num of ADC channels */
34 ai_bits: 14, /* Num of ADC bits */
35 ao_chans: 8, /* Num of DAC channels */
36 ao_bits: 14, /* Num of DAC bits */
37 di_chans: 8, /* Num of digital in */
38 do_chans: 8, /* Num of digital out */
42 static int mf614_attach(struct comedi_device *dev, struct comedi_devconfig *it);
43 static int mf614_detach(struct comedi_device *dev);
44 static struct comedi_driver driver_mf614 = {
51 /* Private data structure */
53 struct pci_dev *pci_dev;
55 void __iomem *BAR0_io;
56 void __iomem *BAR2_io;
59 /* Used for AO readback */
60 //lsampl_t ao_readback[8];
65 ==============================================================================
69 static int mf614_do_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
70 struct comedi_insn *insn, unsigned int *data);
71 static int mf614_di_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s,
72 struct comedi_insn *insn, unsigned int *data);
74 #define devpriv ((mf614_private *) dev->private)
75 #define thisboard ((mf614_board *) dev->board_ptr)
76 static int mf614_attach(struct comedi_device *dev, struct comedi_devconfig *it)
78 struct comedi_subdevice *s;
79 struct pci_dev* pcidev;
80 //unsigned int channel;
81 //unsigned int status;
83 printk("comedi%d: mf614: ", dev->minor);
85 if(alloc_private(dev, sizeof(mf614_private)) < 0) { // No need to free() later
91 /* Probe the device to determine what device in the series it is */
92 for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
94 pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
97 if(pcidev->vendor != PCI_VENDOR_ID_MF614) {
101 if(mf614_boards[0].device_id != pcidev->device) {
105 /* was a particular bus/slot requested ? */
106 if(it->options[0] || it->options[1])
108 /* are we on the wrong bus/slot ? */
109 if(pcidev->bus->number != it->options[0] ||
110 PCI_SLOT(pcidev->devfn) != it->options[1]) {
115 devpriv->pci_dev = pcidev;
116 dev->board_ptr = mf614_boards + 0; // Zero offset; Only One card is supported
120 comedi_error(dev, "Can't find MF614 card on requested position\n");
124 printk("Found %s on bus %i, slot %i\n",
125 mf614_boards[0].name, pcidev->bus->number, PCI_SLOT(pcidev->devfn));
127 /* comedi_pci_enable(struct pci_dev *pdev, const char *res_name) */
128 if(pci_enable_device(devpriv->pci_dev)) {
129 comedi_error(dev, "Failed to enable PCI device\n");
132 if(pci_request_regions(devpriv->pci_dev, "mf614")) {
133 comedi_error(dev, "Card's IO ports allready in use\n");
137 /* pci_ioremap_bar(devpriv->pci_dev, 0) is for memory regions; This are IO ports */
138 devpriv->BAR0_io = pci_iomap(devpriv->pci_dev, 0, 0);
139 if (!devpriv->BAR0_io) {
142 devpriv->BAR2_io = pci_iomap(devpriv->pci_dev, 2, 0);
143 if (!devpriv->BAR2_io) {
148 dev->board_name = thisboard->name;
150 /* Allocate subdevices */
151 if(alloc_subdevices(dev, 2) < 0) {
156 s = dev->subdevices + 0;
157 s->type = COMEDI_SUBD_DI;
158 s->subdev_flags = SDF_READABLE;
159 s->n_chan = thisboard->di_chans;
161 s->range_table = &range_digital;
162 s->insn_bits = mf614_di_insn_bits;
165 s = dev->subdevices + 1;
166 s->type = COMEDI_SUBD_DO;
167 s->subdev_flags = SDF_WRITABLE;
168 s->n_chan = thisboard->do_chans;
170 s->range_table = &range_digital;
171 s->insn_bits = mf614_do_insn_bits;
173 printk("comedi%d: mf614: Driver attached\n", dev->minor);
178 pci_iounmap(devpriv->pci_dev, devpriv->BAR0_io);
180 pci_release_regions(devpriv->pci_dev);
182 pci_disable_device(devpriv->pci_dev);
187 static int mf614_detach(struct comedi_device *dev)
189 if(devpriv && devpriv->pci_dev)
191 if(devpriv->in_use == 1)
193 pci_release_regions(devpriv->pci_dev);
194 pci_disable_device(devpriv->pci_dev);
195 pci_iounmap(devpriv->pci_dev, devpriv->BAR0_io);
196 pci_iounmap(devpriv->pci_dev, devpriv->BAR2_io);
199 pci_dev_put(devpriv->pci_dev);
205 /* Write digital data */
206 static int mf614_do_insn_bits(struct comedi_device *dev,
207 struct comedi_subdevice *s,
208 struct comedi_insn *insn, unsigned int *data)
215 s->state &= ~data[0];
216 s->state |= data[0] & data[1];
218 iowrite8(s->state, devpriv->BAR0_io + DOUT_reg);
223 /* Read digital data */
224 static int mf614_di_insn_bits(struct comedi_device *dev,
225 struct comedi_subdevice *s,
226 struct comedi_insn *insn, unsigned int *data)
232 data[1] = ioread8(devpriv->BAR0_io + DIN_reg);
238 ==============================================================================
240 static int __devinit mf614_probe(struct pci_dev *dev, const struct pci_device_id *ent)
242 return comedi_pci_auto_config(dev, driver_mf614.driver_name);
245 static void __devexit mf614_remove(struct pci_dev *dev)
247 comedi_pci_auto_unconfig(dev);
250 static struct pci_driver driver_mf614_pci = {
251 .id_table = mf614_pci_table,
252 .probe = &mf614_probe,
253 .remove = __devexit_p(&mf614_remove)
256 static int __init mf614_init_module(void)
260 retval = comedi_driver_register(&driver_mf614);
264 /* Copy "name" from Comedi driver struct into pci_driver_struct*/
265 driver_mf614_pci.name = (char *)driver_mf614.driver_name;
266 return pci_register_driver(&driver_mf614_pci);
269 static void __exit mf614_cleanup_module(void)
271 pci_unregister_driver(&driver_mf614_pci);
272 comedi_driver_unregister(&driver_mf614);
275 module_init(mf614_init_module);
276 module_exit(mf614_cleanup_module);
278 MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");
279 MODULE_DESCRIPTION("Humusoft MF614 DAQ Card");
280 MODULE_LICENSE("GPL v2");