Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * comedi_pci.c
0004  * Comedi PCI driver specific functions.
0005  *
0006  * COMEDI - Linux Control and Measurement Device Interface
0007  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
0008  */
0009 
0010 #include <linux/module.h>
0011 #include <linux/interrupt.h>
0012 #include <linux/comedi/comedi_pci.h>
0013 
0014 /**
0015  * comedi_to_pci_dev() - Return PCI device attached to COMEDI device
0016  * @dev: COMEDI device.
0017  *
0018  * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
0019  * a &struct device embedded in a &struct pci_dev.
0020  *
0021  * Return: Attached PCI device if @dev->hw_dev is non-%NULL.
0022  * Return %NULL if @dev->hw_dev is %NULL.
0023  */
0024 struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
0025 {
0026     return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;
0027 }
0028 EXPORT_SYMBOL_GPL(comedi_to_pci_dev);
0029 
0030 /**
0031  * comedi_pci_enable() - Enable the PCI device and request the regions
0032  * @dev: COMEDI device.
0033  *
0034  * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
0035  * a &struct device embedded in a &struct pci_dev.  Enable the PCI device
0036  * and request its regions.  Set @dev->ioenabled to %true if successful,
0037  * otherwise undo what was done.
0038  *
0039  * Calls to comedi_pci_enable() and comedi_pci_disable() cannot be nested.
0040  *
0041  * Return:
0042  *  0 on success,
0043  *  -%ENODEV if @dev->hw_dev is %NULL,
0044  *  -%EBUSY if regions busy,
0045  *  or some negative error number if failed to enable PCI device.
0046  *
0047  */
0048 int comedi_pci_enable(struct comedi_device *dev)
0049 {
0050     struct pci_dev *pcidev = comedi_to_pci_dev(dev);
0051     int rc;
0052 
0053     if (!pcidev)
0054         return -ENODEV;
0055 
0056     rc = pci_enable_device(pcidev);
0057     if (rc < 0)
0058         return rc;
0059 
0060     rc = pci_request_regions(pcidev, dev->board_name);
0061     if (rc < 0)
0062         pci_disable_device(pcidev);
0063     else
0064         dev->ioenabled = true;
0065 
0066     return rc;
0067 }
0068 EXPORT_SYMBOL_GPL(comedi_pci_enable);
0069 
0070 /**
0071  * comedi_pci_disable() - Release the regions and disable the PCI device
0072  * @dev: COMEDI device.
0073  *
0074  * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
0075  * a &struct device embedded in a &struct pci_dev.  If the earlier call
0076  * to comedi_pci_enable() was successful, release the PCI device's regions
0077  * and disable it.  Reset @dev->ioenabled back to %false.
0078  */
0079 void comedi_pci_disable(struct comedi_device *dev)
0080 {
0081     struct pci_dev *pcidev = comedi_to_pci_dev(dev);
0082 
0083     if (pcidev && dev->ioenabled) {
0084         pci_release_regions(pcidev);
0085         pci_disable_device(pcidev);
0086     }
0087     dev->ioenabled = false;
0088 }
0089 EXPORT_SYMBOL_GPL(comedi_pci_disable);
0090 
0091 /**
0092  * comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers
0093  * @dev: COMEDI device.
0094  *
0095  * COMEDI drivers for PCI devices that need no special clean-up of private data
0096  * and have no ioremapped regions other than that pointed to by @dev->mmio may
0097  * use this function as its "detach" handler called by the COMEDI core when a
0098  * COMEDI device is being detached from the low-level driver.  It may be also
0099  * called from a more specific "detach" handler that does additional clean-up.
0100  *
0101  * Free the IRQ if @dev->irq is non-zero, iounmap @dev->mmio if it is
0102  * non-%NULL, and call comedi_pci_disable() to release the PCI device's regions
0103  * and disable it.
0104  */
0105 void comedi_pci_detach(struct comedi_device *dev)
0106 {
0107     struct pci_dev *pcidev = comedi_to_pci_dev(dev);
0108 
0109     if (!pcidev || !dev->ioenabled)
0110         return;
0111 
0112     if (dev->irq) {
0113         free_irq(dev->irq, dev);
0114         dev->irq = 0;
0115     }
0116     if (dev->mmio) {
0117         iounmap(dev->mmio);
0118         dev->mmio = NULL;
0119     }
0120     comedi_pci_disable(dev);
0121 }
0122 EXPORT_SYMBOL_GPL(comedi_pci_detach);
0123 
0124 /**
0125  * comedi_pci_auto_config() - Configure/probe a PCI COMEDI device
0126  * @pcidev: PCI device.
0127  * @driver: Registered COMEDI driver.
0128  * @context: Driver specific data, passed to comedi_auto_config().
0129  *
0130  * Typically called from the pci_driver (*probe) function.  Auto-configure
0131  * a COMEDI device, using the &struct device embedded in *@pcidev as the
0132  * hardware device.  The @context value gets passed through to @driver's
0133  * "auto_attach" handler.  The "auto_attach" handler may call
0134  * comedi_to_pci_dev() on the passed in COMEDI device to recover @pcidev.
0135  *
0136  * Return: The result of calling comedi_auto_config() (0 on success, or
0137  * a negative error number on failure).
0138  */
0139 int comedi_pci_auto_config(struct pci_dev *pcidev,
0140                struct comedi_driver *driver,
0141                unsigned long context)
0142 {
0143     return comedi_auto_config(&pcidev->dev, driver, context);
0144 }
0145 EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
0146 
0147 /**
0148  * comedi_pci_auto_unconfig() - Unconfigure/remove a PCI COMEDI device
0149  * @pcidev: PCI device.
0150  *
0151  * Typically called from the pci_driver (*remove) function.  Auto-unconfigure
0152  * a COMEDI device attached to this PCI device, using a pointer to the
0153  * &struct device embedded in *@pcidev as the hardware device.  The COMEDI
0154  * driver's "detach" handler will be called during unconfiguration of the
0155  * COMEDI device.
0156  *
0157  * Note that the COMEDI device may have already been unconfigured using the
0158  * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it
0159  * again should be ignored.
0160  */
0161 void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
0162 {
0163     comedi_auto_unconfig(&pcidev->dev);
0164 }
0165 EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
0166 
0167 /**
0168  * comedi_pci_driver_register() - Register a PCI COMEDI driver
0169  * @comedi_driver: COMEDI driver to be registered.
0170  * @pci_driver: PCI driver to be registered.
0171  *
0172  * This function is called from the module_init() of PCI COMEDI driver modules
0173  * to register the COMEDI driver and the PCI driver.  Do not call it directly,
0174  * use the module_comedi_pci_driver() helper macro instead.
0175  *
0176  * Return: 0 on success, or a negative error number on failure.
0177  */
0178 int comedi_pci_driver_register(struct comedi_driver *comedi_driver,
0179                    struct pci_driver *pci_driver)
0180 {
0181     int ret;
0182 
0183     ret = comedi_driver_register(comedi_driver);
0184     if (ret < 0)
0185         return ret;
0186 
0187     ret = pci_register_driver(pci_driver);
0188     if (ret < 0) {
0189         comedi_driver_unregister(comedi_driver);
0190         return ret;
0191     }
0192 
0193     return 0;
0194 }
0195 EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
0196 
0197 /**
0198  * comedi_pci_driver_unregister() - Unregister a PCI COMEDI driver
0199  * @comedi_driver: COMEDI driver to be unregistered.
0200  * @pci_driver: PCI driver to be unregistered.
0201  *
0202  * This function is called from the module_exit() of PCI COMEDI driver modules
0203  * to unregister the PCI driver and the COMEDI driver.  Do not call it
0204  * directly, use the module_comedi_pci_driver() helper macro instead.
0205  */
0206 void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,
0207                   struct pci_driver *pci_driver)
0208 {
0209     pci_unregister_driver(pci_driver);
0210     comedi_driver_unregister(comedi_driver);
0211 }
0212 EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
0213 
0214 static int __init comedi_pci_init(void)
0215 {
0216     return 0;
0217 }
0218 module_init(comedi_pci_init);
0219 
0220 static void __exit comedi_pci_exit(void)
0221 {
0222 }
0223 module_exit(comedi_pci_exit);
0224 
0225 MODULE_AUTHOR("https://www.comedi.org");
0226 MODULE_DESCRIPTION("Comedi PCI interface module");
0227 MODULE_LICENSE("GPL");