// SPDX-License-Identifier: GPL-2.0+1/*2* comedi_pci.c3* Comedi PCI driver specific functions.4*5* COMEDI - Linux Control and Measurement Device Interface6* Copyright (C) 1997-2000 David A. Schleef <[email protected]>7*/89#include <linux/module.h>10#include <linux/interrupt.h>11#include <linux/comedi/comedi_pci.h>1213/**14* comedi_to_pci_dev() - Return PCI device attached to COMEDI device15* @dev: COMEDI device.16*17* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a18* a &struct device embedded in a &struct pci_dev.19*20* Return: Attached PCI device if @dev->hw_dev is non-%NULL.21* Return %NULL if @dev->hw_dev is %NULL.22*/23struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)24{25return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;26}27EXPORT_SYMBOL_GPL(comedi_to_pci_dev);2829/**30* comedi_pci_enable() - Enable the PCI device and request the regions31* @dev: COMEDI device.32*33* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a34* a &struct device embedded in a &struct pci_dev. Enable the PCI device35* and request its regions. Set @dev->ioenabled to %true if successful,36* otherwise undo what was done.37*38* Calls to comedi_pci_enable() and comedi_pci_disable() cannot be nested.39*40* Return:41* 0 on success,42* -%ENODEV if @dev->hw_dev is %NULL,43* -%EBUSY if regions busy,44* or some negative error number if failed to enable PCI device.45*46*/47int comedi_pci_enable(struct comedi_device *dev)48{49struct pci_dev *pcidev = comedi_to_pci_dev(dev);50int rc;5152if (!pcidev)53return -ENODEV;5455rc = pci_enable_device(pcidev);56if (rc < 0)57return rc;5859rc = pci_request_regions(pcidev, dev->board_name);60if (rc < 0)61pci_disable_device(pcidev);62else63dev->ioenabled = true;6465return rc;66}67EXPORT_SYMBOL_GPL(comedi_pci_enable);6869/**70* comedi_pci_disable() - Release the regions and disable the PCI device71* @dev: COMEDI device.72*73* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a74* a &struct device embedded in a &struct pci_dev. If the earlier call75* to comedi_pci_enable() was successful, release the PCI device's regions76* and disable it. Reset @dev->ioenabled back to %false.77*/78void comedi_pci_disable(struct comedi_device *dev)79{80struct pci_dev *pcidev = comedi_to_pci_dev(dev);8182if (pcidev && dev->ioenabled) {83pci_release_regions(pcidev);84pci_disable_device(pcidev);85}86dev->ioenabled = false;87}88EXPORT_SYMBOL_GPL(comedi_pci_disable);8990/**91* comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers92* @dev: COMEDI device.93*94* COMEDI drivers for PCI devices that need no special clean-up of private data95* and have no ioremapped regions other than that pointed to by @dev->mmio may96* use this function as its "detach" handler called by the COMEDI core when a97* COMEDI device is being detached from the low-level driver. It may be also98* called from a more specific "detach" handler that does additional clean-up.99*100* Free the IRQ if @dev->irq is non-zero, iounmap @dev->mmio if it is101* non-%NULL, and call comedi_pci_disable() to release the PCI device's regions102* and disable it.103*/104void comedi_pci_detach(struct comedi_device *dev)105{106struct pci_dev *pcidev = comedi_to_pci_dev(dev);107108if (!pcidev || !dev->ioenabled)109return;110111if (dev->irq) {112free_irq(dev->irq, dev);113dev->irq = 0;114}115if (dev->mmio) {116iounmap(dev->mmio);117dev->mmio = NULL;118}119comedi_pci_disable(dev);120}121EXPORT_SYMBOL_GPL(comedi_pci_detach);122123/**124* comedi_pci_auto_config() - Configure/probe a PCI COMEDI device125* @pcidev: PCI device.126* @driver: Registered COMEDI driver.127* @context: Driver specific data, passed to comedi_auto_config().128*129* Typically called from the pci_driver (*probe) function. Auto-configure130* a COMEDI device, using the &struct device embedded in *@pcidev as the131* hardware device. The @context value gets passed through to @driver's132* "auto_attach" handler. The "auto_attach" handler may call133* comedi_to_pci_dev() on the passed in COMEDI device to recover @pcidev.134*135* Return: The result of calling comedi_auto_config() (0 on success, or136* a negative error number on failure).137*/138int comedi_pci_auto_config(struct pci_dev *pcidev,139struct comedi_driver *driver,140unsigned long context)141{142return comedi_auto_config(&pcidev->dev, driver, context);143}144EXPORT_SYMBOL_GPL(comedi_pci_auto_config);145146/**147* comedi_pci_auto_unconfig() - Unconfigure/remove a PCI COMEDI device148* @pcidev: PCI device.149*150* Typically called from the pci_driver (*remove) function. Auto-unconfigure151* a COMEDI device attached to this PCI device, using a pointer to the152* &struct device embedded in *@pcidev as the hardware device. The COMEDI153* driver's "detach" handler will be called during unconfiguration of the154* COMEDI device.155*156* Note that the COMEDI device may have already been unconfigured using the157* %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it158* again should be ignored.159*/160void comedi_pci_auto_unconfig(struct pci_dev *pcidev)161{162comedi_auto_unconfig(&pcidev->dev);163}164EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);165166/**167* comedi_pci_driver_register() - Register a PCI COMEDI driver168* @comedi_driver: COMEDI driver to be registered.169* @pci_driver: PCI driver to be registered.170*171* This function is called from the module_init() of PCI COMEDI driver modules172* to register the COMEDI driver and the PCI driver. Do not call it directly,173* use the module_comedi_pci_driver() helper macro instead.174*175* Return: 0 on success, or a negative error number on failure.176*/177int comedi_pci_driver_register(struct comedi_driver *comedi_driver,178struct pci_driver *pci_driver)179{180int ret;181182ret = comedi_driver_register(comedi_driver);183if (ret < 0)184return ret;185186ret = pci_register_driver(pci_driver);187if (ret < 0) {188comedi_driver_unregister(comedi_driver);189return ret;190}191192return 0;193}194EXPORT_SYMBOL_GPL(comedi_pci_driver_register);195196/**197* comedi_pci_driver_unregister() - Unregister a PCI COMEDI driver198* @comedi_driver: COMEDI driver to be unregistered.199* @pci_driver: PCI driver to be unregistered.200*201* This function is called from the module_exit() of PCI COMEDI driver modules202* to unregister the PCI driver and the COMEDI driver. Do not call it203* directly, use the module_comedi_pci_driver() helper macro instead.204*/205void comedi_pci_driver_unregister(struct comedi_driver *comedi_driver,206struct pci_driver *pci_driver)207{208pci_unregister_driver(pci_driver);209comedi_driver_unregister(comedi_driver);210}211EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);212213static int __init comedi_pci_init(void)214{215return 0;216}217module_init(comedi_pci_init);218219static void __exit comedi_pci_exit(void)220{221}222module_exit(comedi_pci_exit);223224MODULE_AUTHOR("https://www.comedi.org");225MODULE_DESCRIPTION("Comedi PCI interface module");226MODULE_LICENSE("GPL");227228229