brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · cc25819 Raw
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