2017-11-07 16:58:43 +03:00
// SPDX-License-Identifier: GPL-2.0+
2013-01-31 02:22:21 +04:00
/*
* comedi_pci . c
* Comedi PCI driver specific functions .
*
* COMEDI - Linux Control and Measurement Device Interface
* Copyright ( C ) 1997 - 2000 David A . Schleef < ds @ schleef . org >
*/
2014-10-31 20:47:39 +03:00
# include <linux/module.h>
2014-08-26 04:55:48 +04:00
# include <linux/interrupt.h>
2021-11-17 15:05:59 +03:00
# include <linux/comedi/comedi_pci.h>
2013-01-31 02:22:21 +04:00
/**
2015-09-23 21:35:56 +03:00
* comedi_to_pci_dev ( ) - Return PCI device attached to COMEDI device
* @ dev : COMEDI device .
*
* Assuming @ dev - > hw_dev is non - % NULL , it is assumed to be pointing to a
* a & struct device embedded in a & struct pci_dev .
*
2015-09-30 18:43:55 +03:00
* Return : Attached PCI device if @ dev - > hw_dev is non - % NULL .
* Return % NULL if @ dev - > hw_dev is % NULL .
2013-01-31 02:22:21 +04:00
*/
struct pci_dev * comedi_to_pci_dev ( struct comedi_device * dev )
{
return dev - > hw_dev ? to_pci_dev ( dev - > hw_dev ) : NULL ;
}
EXPORT_SYMBOL_GPL ( comedi_to_pci_dev ) ;
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_enable ( ) - Enable the PCI device and request the regions
* @ dev : COMEDI device .
*
* Assuming @ dev - > hw_dev is non - % NULL , it is assumed to be pointing to a
* a & struct device embedded in a & struct pci_dev . Enable the PCI device
* and request its regions . Set @ dev - > ioenabled to % true if successful ,
* otherwise undo what was done .
*
* Calls to comedi_pci_enable ( ) and comedi_pci_disable ( ) cannot be nested .
*
2015-09-30 18:43:55 +03:00
* Return :
2015-09-23 21:35:56 +03:00
* 0 on success ,
* - % ENODEV if @ dev - > hw_dev is % NULL ,
* - % EBUSY if regions busy ,
* or some negative error number if failed to enable PCI device .
*
2013-01-31 02:22:21 +04:00
*/
2013-03-13 21:36:31 +04:00
int comedi_pci_enable ( struct comedi_device * dev )
2013-01-31 02:22:21 +04:00
{
2013-03-13 21:36:31 +04:00
struct pci_dev * pcidev = comedi_to_pci_dev ( dev ) ;
2013-01-31 02:22:21 +04:00
int rc ;
2013-03-13 21:36:31 +04:00
if ( ! pcidev )
return - ENODEV ;
2013-01-31 02:22:21 +04:00
rc = pci_enable_device ( pcidev ) ;
if ( rc < 0 )
return rc ;
2013-04-08 21:56:20 +04:00
rc = pci_request_regions ( pcidev , dev - > board_name ) ;
2013-01-31 02:22:21 +04:00
if ( rc < 0 )
pci_disable_device ( pcidev ) ;
2013-03-15 17:15:35 +04:00
else
dev - > ioenabled = true ;
2013-01-31 02:22:21 +04:00
return rc ;
}
EXPORT_SYMBOL_GPL ( comedi_pci_enable ) ;
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_disable ( ) - Release the regions and disable the PCI device
* @ dev : COMEDI device .
*
* Assuming @ dev - > hw_dev is non - % NULL , it is assumed to be pointing to a
* a & struct device embedded in a & struct pci_dev . If the earlier call
* to comedi_pci_enable ( ) was successful , release the PCI device ' s regions
* and disable it . Reset @ dev - > ioenabled back to % false .
2013-01-31 02:22:21 +04:00
*/
2013-03-13 21:35:51 +04:00
void comedi_pci_disable ( struct comedi_device * dev )
2013-01-31 02:22:21 +04:00
{
2013-03-13 21:35:51 +04:00
struct pci_dev * pcidev = comedi_to_pci_dev ( dev ) ;
2013-03-15 17:15:35 +04:00
if ( pcidev & & dev - > ioenabled ) {
2013-03-13 21:35:51 +04:00
pci_release_regions ( pcidev ) ;
pci_disable_device ( pcidev ) ;
}
2013-03-15 17:15:35 +04:00
dev - > ioenabled = false ;
2013-01-31 02:22:21 +04:00
}
EXPORT_SYMBOL_GPL ( comedi_pci_disable ) ;
2014-08-26 04:55:48 +04:00
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_detach ( ) - A generic " detach " handler for PCI COMEDI drivers
* @ dev : COMEDI device .
*
* COMEDI drivers for PCI devices that need no special clean - up of private data
* and have no ioremapped regions other than that pointed to by @ dev - > mmio may
* use this function as its " detach " handler called by the COMEDI core when a
* COMEDI device is being detached from the low - level driver . It may be also
* called from a more specific " detach " handler that does additional clean - up .
*
* Free the IRQ if @ dev - > irq is non - zero , iounmap @ dev - > mmio if it is
* non - % NULL , and call comedi_pci_disable ( ) to release the PCI device ' s regions
* and disable it .
2014-08-26 04:55:48 +04:00
*/
void comedi_pci_detach ( struct comedi_device * dev )
{
struct pci_dev * pcidev = comedi_to_pci_dev ( dev ) ;
if ( ! pcidev | | ! dev - > ioenabled )
return ;
if ( dev - > irq ) {
free_irq ( dev - > irq , dev ) ;
dev - > irq = 0 ;
}
if ( dev - > mmio ) {
iounmap ( dev - > mmio ) ;
dev - > mmio = NULL ;
}
comedi_pci_disable ( dev ) ;
}
EXPORT_SYMBOL_GPL ( comedi_pci_detach ) ;
2013-01-31 02:22:21 +04:00
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_auto_config ( ) - Configure / probe a PCI COMEDI device
* @ pcidev : PCI device .
* @ driver : Registered COMEDI driver .
* @ context : Driver specific data , passed to comedi_auto_config ( ) .
2013-01-31 02:22:21 +04:00
*
2015-09-23 21:35:56 +03:00
* Typically called from the pci_driver ( * probe ) function . Auto - configure
* a COMEDI device , using the & struct device embedded in * @ pcidev as the
* hardware device . The @ context value gets passed through to @ driver ' s
* " auto_attach " handler . The " auto_attach " handler may call
* comedi_to_pci_dev ( ) on the passed in COMEDI device to recover @ pcidev .
*
2015-09-30 18:43:55 +03:00
* Return : The result of calling comedi_auto_config ( ) ( 0 on success , or
2015-09-23 21:35:56 +03:00
* a negative error number on failure ) .
2013-01-31 02:22:21 +04:00
*/
int comedi_pci_auto_config ( struct pci_dev * pcidev ,
2013-03-05 20:53:41 +04:00
struct comedi_driver * driver ,
unsigned long context )
2013-01-31 02:22:21 +04:00
{
2013-03-05 20:53:41 +04:00
return comedi_auto_config ( & pcidev - > dev , driver , context ) ;
2013-01-31 02:22:21 +04:00
}
EXPORT_SYMBOL_GPL ( comedi_pci_auto_config ) ;
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_auto_unconfig ( ) - Unconfigure / remove a PCI COMEDI device
* @ pcidev : PCI device .
*
* Typically called from the pci_driver ( * remove ) function . Auto - unconfigure
* a COMEDI device attached to this PCI device , using a pointer to the
* & struct device embedded in * @ pcidev as the hardware device . The COMEDI
* driver ' s " detach " handler will be called during unconfiguration of the
* COMEDI device .
2013-01-31 02:22:21 +04:00
*
2015-09-23 21:35:56 +03:00
* Note that the COMEDI device may have already been unconfigured using the
* % COMEDI_DEVCONFIG ioctl , in which case this attempt to unconfigure it
* again should be ignored .
2013-01-31 02:22:21 +04:00
*/
void comedi_pci_auto_unconfig ( struct pci_dev * pcidev )
{
comedi_auto_unconfig ( & pcidev - > dev ) ;
}
EXPORT_SYMBOL_GPL ( comedi_pci_auto_unconfig ) ;
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_driver_register ( ) - Register a PCI COMEDI driver
* @ comedi_driver : COMEDI driver to be registered .
* @ pci_driver : PCI driver to be registered .
*
* This function is called from the module_init ( ) of PCI COMEDI driver modules
* to register the COMEDI driver and the PCI driver . Do not call it directly ,
* use the module_comedi_pci_driver ( ) helper macro instead .
2013-01-31 02:22:21 +04:00
*
2015-09-30 18:43:55 +03:00
* Return : 0 on success , or a negative error number on failure .
2013-01-31 02:22:21 +04:00
*/
int comedi_pci_driver_register ( struct comedi_driver * comedi_driver ,
struct pci_driver * pci_driver )
{
int ret ;
ret = comedi_driver_register ( comedi_driver ) ;
if ( ret < 0 )
return ret ;
ret = pci_register_driver ( pci_driver ) ;
if ( ret < 0 ) {
comedi_driver_unregister ( comedi_driver ) ;
return ret ;
}
return 0 ;
}
EXPORT_SYMBOL_GPL ( comedi_pci_driver_register ) ;
/**
2015-09-23 21:35:56 +03:00
* comedi_pci_driver_unregister ( ) - Unregister a PCI COMEDI driver
* @ comedi_driver : COMEDI driver to be unregistered .
* @ pci_driver : PCI driver to be unregistered .
2013-01-31 02:22:21 +04:00
*
2015-09-23 21:35:56 +03:00
* This function is called from the module_exit ( ) of PCI COMEDI driver modules
* to unregister the PCI driver and the COMEDI driver . Do not call it
* directly , use the module_comedi_pci_driver ( ) helper macro instead .
2013-01-31 02:22:21 +04:00
*/
void comedi_pci_driver_unregister ( struct comedi_driver * comedi_driver ,
struct pci_driver * pci_driver )
{
pci_unregister_driver ( pci_driver ) ;
comedi_driver_unregister ( comedi_driver ) ;
}
EXPORT_SYMBOL_GPL ( comedi_pci_driver_unregister ) ;
2014-10-31 20:47:39 +03:00
static int __init comedi_pci_init ( void )
{
return 0 ;
}
module_init ( comedi_pci_init ) ;
static void __exit comedi_pci_exit ( void )
{
}
module_exit ( comedi_pci_exit ) ;
2020-07-23 22:40:53 +03:00
MODULE_AUTHOR ( " https://www.comedi.org " ) ;
2014-10-31 20:47:39 +03:00
MODULE_DESCRIPTION ( " Comedi PCI interface module " ) ;
MODULE_LICENSE ( " GPL " ) ;