228 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * comedi_pci.c4 * Comedi PCI driver specific functions.5 *6 * COMEDI - Linux Control and Measurement Device Interface7 * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>8 */9 10#include <linux/module.h>11#include <linux/interrupt.h>12#include <linux/comedi/comedi_pci.h>13 14/**15 * comedi_to_pci_dev() - Return PCI device attached to COMEDI device16 * @dev: COMEDI device.17 *18 * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a19 * a &struct device embedded in a &struct pci_dev.20 *21 * Return: Attached PCI device if @dev->hw_dev is non-%NULL.22 * Return %NULL if @dev->hw_dev is %NULL.23 */24struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)25{26 return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;27}28EXPORT_SYMBOL_GPL(comedi_to_pci_dev);29 30/**31 * comedi_pci_enable() - Enable the PCI device and request the regions32 * @dev: COMEDI device.33 *34 * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a35 * a &struct device embedded in a &struct pci_dev. Enable the PCI device36 * and request its regions. Set @dev->ioenabled to %true if successful,37 * otherwise undo what was done.38 *39 * Calls to comedi_pci_enable() and comedi_pci_disable() cannot be nested.40 *41 * Return:42 * 0 on success,43 * -%ENODEV if @dev->hw_dev is %NULL,44 * -%EBUSY if regions busy,45 * or some negative error number if failed to enable PCI device.46 *47 */48int comedi_pci_enable(struct comedi_device *dev)49{50 struct pci_dev *pcidev = comedi_to_pci_dev(dev);51 int rc;52 53 if (!pcidev)54 return -ENODEV;55 56 rc = pci_enable_device(pcidev);57 if (rc < 0)58 return rc;59 60 rc = pci_request_regions(pcidev, dev->board_name);61 if (rc < 0)62 pci_disable_device(pcidev);63 else64 dev->ioenabled = true;65 66 return rc;67}68EXPORT_SYMBOL_GPL(comedi_pci_enable);69 70/**71 * comedi_pci_disable() - Release the regions and disable the PCI device72 * @dev: COMEDI device.73 *74 * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a75 * a &struct device embedded in a &struct pci_dev. If the earlier call76 * to comedi_pci_enable() was successful, release the PCI device's regions77 * and disable it. Reset @dev->ioenabled back to %false.78 */79void comedi_pci_disable(struct comedi_device *dev)80{81 struct pci_dev *pcidev = comedi_to_pci_dev(dev);82 83 if (pcidev && dev->ioenabled) {84 pci_release_regions(pcidev);85 pci_disable_device(pcidev);86 }87 dev->ioenabled = false;88}89EXPORT_SYMBOL_GPL(comedi_pci_disable);90 91/**92 * comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers93 * @dev: COMEDI device.94 *95 * COMEDI drivers for PCI devices that need no special clean-up of private data96 * and have no ioremapped regions other than that pointed to by @dev->mmio may97 * use this function as its "detach" handler called by the COMEDI core when a98 * COMEDI device is being detached from the low-level driver. It may be also99 * called from a more specific "detach" handler that does additional clean-up.100 *101 * Free the IRQ if @dev->irq is non-zero, iounmap @dev->mmio if it is102 * non-%NULL, and call comedi_pci_disable() to release the PCI device's regions103 * and disable it.104 */105void comedi_pci_detach(struct comedi_device *dev)106{107 struct pci_dev *pcidev = comedi_to_pci_dev(dev);108 109 if (!pcidev || !dev->ioenabled)110 return;111 112 if (dev->irq) {113 free_irq(dev->irq, dev);114 dev->irq = 0;115 }116 if (dev->mmio) {117 iounmap(dev->mmio);118 dev->mmio = NULL;119 }120 comedi_pci_disable(dev);121}122EXPORT_SYMBOL_GPL(comedi_pci_detach);123 124/**125 * comedi_pci_auto_config() - Configure/probe a PCI COMEDI device126 * @pcidev: PCI device.127 * @driver: Registered COMEDI driver.128 * @context: Driver specific data, passed to comedi_auto_config().129 *130 * Typically called from the pci_driver (*probe) function. Auto-configure131 * a COMEDI device, using the &struct device embedded in *@pcidev as the132 * hardware device. The @context value gets passed through to @driver's133 * "auto_attach" handler. The "auto_attach" handler may call134 * comedi_to_pci_dev() on the passed in COMEDI device to recover @pcidev.135 *136 * Return: The result of calling comedi_auto_config() (0 on success, or137 * a negative error number on failure).138 */139int comedi_pci_auto_config(struct pci_dev *pcidev,140 struct comedi_driver *driver,141 unsigned long context)142{143 return comedi_auto_config(&pcidev->dev, driver, context);144}145EXPORT_SYMBOL_GPL(comedi_pci_auto_config);146 147/**148 * comedi_pci_auto_unconfig() - Unconfigure/remove a PCI COMEDI device149 * @pcidev: PCI device.150 *151 * Typically called from the pci_driver (*remove) function. Auto-unconfigure152 * a COMEDI device attached to this PCI device, using a pointer to the153 * &struct device embedded in *@pcidev as the hardware device. The COMEDI154 * driver's "detach" handler will be called during unconfiguration of the155 * COMEDI device.156 *157 * Note that the COMEDI device may have already been unconfigured using the158 * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it159 * again should be ignored.160 */161void comedi_pci_auto_unconfig(struct pci_dev *pcidev)162{163 comedi_auto_unconfig(&pcidev->dev);164}165EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);166 167/**168 * comedi_pci_driver_register() - Register a PCI COMEDI driver169 * @comedi_driver: COMEDI driver to be registered.170 * @pci_driver: PCI driver to be registered.171 *172 * This function is called from the module_init() of PCI COMEDI driver modules173 * to register the COMEDI driver and the PCI driver. Do not call it directly,174 * use the module_comedi_pci_driver() helper macro instead.175 *176 * Return: 0 on success, or a negative error number on failure.177 */178int comedi_pci_driver_register(struct comedi_driver *comedi_driver,179 struct pci_driver *pci_driver)180{181 int ret;182 183 ret = comedi_driver_register(comedi_driver);184 if (ret < 0)185 return ret;186 187 ret = pci_register_driver(pci_driver);188 if (ret < 0) {189 comedi_driver_unregister(comedi_driver);190 return ret;191 }192 193 return 0;194}195EXPORT_SYMBOL_GPL(comedi_pci_driver_register);196 197/**198 * comedi_pci_driver_unregister() - Unregister a PCI COMEDI driver199 * @comedi_driver: COMEDI driver to be unregistered.200 * @pci_driver: PCI driver to be unregistered.201 *202 * This function is called from the module_exit() of PCI COMEDI driver modules203 * to unregister the PCI driver and the COMEDI driver. Do not call it204 * directly, use the module_comedi_pci_driver() helper macro instead.205 */206void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,207 struct pci_driver *pci_driver)208{209 pci_unregister_driver(pci_driver);210 comedi_driver_unregister(comedi_driver);211}212EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);213 214static int __init comedi_pci_init(void)215{216 return 0;217}218module_init(comedi_pci_init);219 220static void __exit comedi_pci_exit(void)221{222}223module_exit(comedi_pci_exit);224 225MODULE_AUTHOR("https://www.comedi.org");226MODULE_DESCRIPTION("Comedi PCI interface module");227MODULE_LICENSE("GPL");228