Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/comedi/comedi_pci.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
* comedi_pci.c
4
* Comedi PCI driver specific functions.
5
*
6
* COMEDI - Linux Control and Measurement Device Interface
7
* Copyright (C) 1997-2000 David A. Schleef <[email protected]>
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 device
16
* @dev: COMEDI device.
17
*
18
* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
19
* 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
*/
24
struct pci_dev *comedi_to_pci_dev(struct comedi_device *dev)
25
{
26
return dev->hw_dev ? to_pci_dev(dev->hw_dev) : NULL;
27
}
28
EXPORT_SYMBOL_GPL(comedi_to_pci_dev);
29
30
/**
31
* comedi_pci_enable() - Enable the PCI device and request the regions
32
* @dev: COMEDI device.
33
*
34
* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
35
* a &struct device embedded in a &struct pci_dev. Enable the PCI device
36
* 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
*/
48
int 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
else
64
dev->ioenabled = true;
65
66
return rc;
67
}
68
EXPORT_SYMBOL_GPL(comedi_pci_enable);
69
70
/**
71
* comedi_pci_disable() - Release the regions and disable the PCI device
72
* @dev: COMEDI device.
73
*
74
* Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
75
* a &struct device embedded in a &struct pci_dev. If the earlier call
76
* to comedi_pci_enable() was successful, release the PCI device's regions
77
* and disable it. Reset @dev->ioenabled back to %false.
78
*/
79
void 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
}
89
EXPORT_SYMBOL_GPL(comedi_pci_disable);
90
91
/**
92
* comedi_pci_detach() - A generic "detach" handler for PCI COMEDI drivers
93
* @dev: COMEDI device.
94
*
95
* COMEDI drivers for PCI devices that need no special clean-up of private data
96
* and have no ioremapped regions other than that pointed to by @dev->mmio may
97
* use this function as its "detach" handler called by the COMEDI core when a
98
* COMEDI device is being detached from the low-level driver. It may be also
99
* 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 is
102
* non-%NULL, and call comedi_pci_disable() to release the PCI device's regions
103
* and disable it.
104
*/
105
void 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
}
122
EXPORT_SYMBOL_GPL(comedi_pci_detach);
123
124
/**
125
* comedi_pci_auto_config() - Configure/probe a PCI COMEDI device
126
* @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-configure
131
* a COMEDI device, using the &struct device embedded in *@pcidev as the
132
* hardware device. The @context value gets passed through to @driver's
133
* "auto_attach" handler. The "auto_attach" handler may call
134
* 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, or
137
* a negative error number on failure).
138
*/
139
int 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
}
145
EXPORT_SYMBOL_GPL(comedi_pci_auto_config);
146
147
/**
148
* comedi_pci_auto_unconfig() - Unconfigure/remove a PCI COMEDI device
149
* @pcidev: PCI device.
150
*
151
* Typically called from the pci_driver (*remove) function. Auto-unconfigure
152
* a COMEDI device attached to this PCI device, using a pointer to the
153
* &struct device embedded in *@pcidev as the hardware device. The COMEDI
154
* driver's "detach" handler will be called during unconfiguration of the
155
* COMEDI device.
156
*
157
* Note that the COMEDI device may have already been unconfigured using the
158
* %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it
159
* again should be ignored.
160
*/
161
void comedi_pci_auto_unconfig(struct pci_dev *pcidev)
162
{
163
comedi_auto_unconfig(&pcidev->dev);
164
}
165
EXPORT_SYMBOL_GPL(comedi_pci_auto_unconfig);
166
167
/**
168
* comedi_pci_driver_register() - Register a PCI COMEDI driver
169
* @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 modules
173
* 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
*/
178
int 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
}
195
EXPORT_SYMBOL_GPL(comedi_pci_driver_register);
196
197
/**
198
* comedi_pci_driver_unregister() - Unregister a PCI COMEDI driver
199
* @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 modules
203
* to unregister the PCI driver and the COMEDI driver. Do not call it
204
* directly, use the module_comedi_pci_driver() helper macro instead.
205
*/
206
void 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
}
212
EXPORT_SYMBOL_GPL(comedi_pci_driver_unregister);
213
214
static int __init comedi_pci_init(void)
215
{
216
return 0;
217
}
218
module_init(comedi_pci_init);
219
220
static void __exit comedi_pci_exit(void)
221
{
222
}
223
module_exit(comedi_pci_exit);
224
225
MODULE_AUTHOR("https://www.comedi.org");
226
MODULE_DESCRIPTION("Comedi PCI interface module");
227
MODULE_LICENSE("GPL");
228
229