]> rtime.felk.cvut.cz Git - mf6xx.git/commitdiff
MF614 Comedi driver skeleton. Some parts missing. Not tested.
authorRostislav Lisovy <lisovy@gmail.com>
Sun, 17 Apr 2011 23:51:21 +0000 (01:51 +0200)
committerRostislav Lisovy <lisovy@gmail.com>
Sun, 17 Apr 2011 23:51:21 +0000 (01:51 +0200)
src/comedi/mf614_simple_driver/kernel/mf614.c [new file with mode: 0644]

diff --git a/src/comedi/mf614_simple_driver/kernel/mf614.c b/src/comedi/mf614_simple_driver/kernel/mf614.c
new file mode 100644 (file)
index 0000000..3cf5dc4
--- /dev/null
@@ -0,0 +1,239 @@
+#include "../comedidev.h"
+#include <linux/pci.h>
+
+#define PCI_VENDOR_ID_MF614 0x186c
+#define PCI_DEVICE_ID_MF614 0x0614
+
+
+static struct pci_device_id mf614_pci_table[] __devinitdata = {
+       { PCI_VENDOR_ID_MF614, PCI_DEVICE_ID_MF614, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+       { 0 }
+};
+MODULE_DEVICE_TABLE(pci, mf614_pci_table);
+
+
+typedef struct mf614_board_struct {
+       char *name;
+       unsigned short device_id;
+       unsigned int ai_chans;
+       unsigned int ai_bits;
+       unsigned int ao_chans;
+       unsigned int ao_bits;
+       unsigned int di_chans;
+       unsigned int do_chans;
+} mf614_board;
+
+static const mf614_board mf614_boards[] = {
+       {
+               name:           "mf614",        /* device name          */
+               device_id:      PCI_DEVICE_ID_MF614,    /* PCI dev ID   */
+               ai_chans:       8,              /* Num of ADC channels  */
+               ai_bits:        14,             /* Num of ADC bits      */
+               ao_chans:       8,              /* Num of DAC channels  */
+               ao_bits:        14,             /* Num of DAC bits      */
+               di_chans:       8,              /* Num of digital in    */
+               do_chans:       8,              /* Num of digital out   */
+       }
+};
+
+static struct comedi_driver driver_mf614 = {
+       driver_name:    "mf614",
+       module:         THIS_MODULE,
+       attach:         mf614_attach,
+       detach:         mf614_detach,
+};
+
+/* Private data structure */
+typedef struct {
+       struct pci_dev *pci_dev;
+
+       void __iomem *BAR0_io;
+       void __iomem *BAR2_io;
+
+       u8 in_use;
+       /* Used for AO readback */
+       //lsampl_t ao_readback[8];
+} mf614_private;
+
+static int mf614_attach(struct comedi_device *dev, struct comedi_devconfig *it);
+static int mf614_detach(struct comedi_device *dev);
+
+/*
+==============================================================================
+*/
+#define devpriv                ((mf614_private *) dev->private)
+#define thisboard              ((mf614_board *) dev->board_ptr)
+static int mf614_attach(struct comedi_device *dev, struct comedi_devconfig *it)
+{
+       struct comedi_subdevice *s;
+       struct pci_dev* pcidev;
+       //unsigned int channel; 
+       unsigned int status;
+
+       printk("comedi%d: mf614: ", dev->minor);
+
+       if(alloc_private(dev, sizeof(mf614_private)) < 0) { // No need to free() later
+               return -ENOMEM;
+       }
+       
+       devpriv->in_use = -1;
+
+       /* Probe the device to determine what device in the series it is */
+       for(pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 
+               pcidev != NULL; 
+               pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev))
+               {
+
+               if(pcidev->vendor != PCI_VENDOR_ID_MF614) {
+                       continue;
+               }
+
+               if(mf614_boards.device_id != pcidev->device) {
+                       continue;
+               }
+
+               /* was a particular bus/slot requested ? */
+               if(it->options[0] || it->options[1])
+               {
+                       /* are we on the wrong bus/slot ? */
+                       if(pcidev->bus->number != it->options[0] ||
+                          PCI_SLOT(pcidev->devfn) != it->options[1]) {
+                               continue;
+                       }
+               }
+
+               devpriv->pci_dev = pcidev;
+               dev->board_ptr = mf614_boards + 0; // Zero offset; Only One card is supported
+               goto found;     
+       }
+
+       comedi_error(dev, "Can't find MF614 card on requested position\n");
+       return -EIO;
+
+found:
+       printk("Found %s on bus %i, slot %i\n",  
+               mf614_boards.name, pcidev->bus->number, PCI_SLOT(pcidev->devfn));
+
+       /* comedi_pci_enable(struct pci_dev *pdev, const char *res_name) */
+       if(pci_enable_device(devpriv->pci_dev)) {
+               comedi_error(dev, "Failed to enable PCI device\n");
+               goto out_exit;
+       }
+       if(pci_request_regions(devpriv->pci_dev, "mf614")) {
+               comedi_error(dev, "Card's IO ports allready in use\n");
+               goto out_disable;
+       }
+
+       /* pci_ioremap_bar(devpriv->pci_dev, 0) is for memory regions; This are IO ports */
+       devpriv->BAR0_io = pci_iomap(devpriv->pci_dev, 0, 0);
+       if (!devpriv->BAR0_io) {
+               goto out_release;
+       }       
+       devpriv->BAR2_io = pci_iomap(devpriv->pci_dev, 2, 0);
+       if (!devpriv->BAR2_io) {
+               goto out_unmap;
+       }
+       
+       devpriv->in_use = 1;
+       dev->board_name = thisboard->name;
+       
+       /* Allocate subdevices */
+       if(alloc_subdevices(dev, 2) < 0) {
+               return -ENOMEM;
+       }
+       
+       /* DIN */       
+       s = dev->subdevices + 0;
+       s->type = COMEDI_SUBD_DI;
+       s->subdev_flags = SDF_READABLE;
+       s->n_chan = thisboard->di_chans;
+       s->maxdata = 1;
+       s->range_table = &range_digital;
+       s->insn_bits = mf614_di_insn_bits;
+
+       /* DOUT */      
+       s = dev->subdevices + 1;
+       s->type = COMEDI_SUBD_DO;
+       s->subdev_flags = SDF_WRITABLE;
+       s->n_chan = thisboard->do_chans;
+       s->maxdata = 1;
+       s->range_table = &range_digital;
+       s->insn_bits  = mf614_do_insn_bits;
+
+       printk("comedi%d: mf614: Driver attached\n", dev->minor);
+       
+       return 0;
+
+out_unmap:
+       pci_iounmap(devpriv->pci_dev, devpriv->BAR0_io);
+out_release:
+       pci_release_regions(devpriv->pci_dev);
+out_disable:
+       pci_disable_device(devpriv->pcidev);
+out_exit:
+       return -ENODEV;
+}
+
+static int mf614_detach(struct comedi_device *dev)
+{
+       if(devpriv && devpriv->pci_dev)
+       {
+               if(devpriv->in_use == 1)
+               {
+                       pci_release_regions(devpriv->pci_dev);
+                       pci_disable_device(devpriv->pci_dev);
+                       pci_iounmap(devpriv->pci_dev, devpriv->BAR0_io);
+                       pci_iounmap(devpriv->pci_dev, devpriv->BAR2_io);
+               }
+               
+               pci_dev_put(devpriv->pci_dev);
+       }
+
+       return 0;
+}
+
+
+/*
+==============================================================================
+*/
+static int __devinit mf614_probe(struct pci_dev *dev, const struct pci_device_id *ent)
+{
+       return comedi_pci_auto_config(dev, driver_mf614.driver_name);
+}
+
+static void __devexit mf614_remove(struct pci_dev *dev)
+{
+       comedi_pci_auto_unconfig(dev);
+}
+
+static struct pci_driver driver_mf614_pci = {
+       .id_table = mf614_pci_table,
+       .probe = &mf614_probe,
+       .remove = __devexit_p(&mf614_remove)
+};
+
+static int __init mf614_init_module(void)
+{
+       int retval;
+
+       retval = comedi_driver_register(&driver_mf614);
+       if (retval < 0)
+               return retval;
+
+       /* Copy "name" from Comedi driver struct into pci_driver_struct*/
+       driver_mf614_pci.name = (char *)driver_mf614.driver_name; 
+       return pci_register_driver(&driver_mf614_pci);
+}
+
+static void __exit mf614_cleanup_module(void)
+{
+       pci_unregister_driver(&driver_mf614_pci);
+       comedi_driver_unregister(&driver_mf614);
+}
+
+module_init(mf614_init_module);
+module_exit(mf614_cleanup_module);
+
+MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");
+MODULE_DESCRIPTION("Humusoft MF614 DAQ Card");
+MODULE_LICENSE("GPL v2");