xref: /openbmc/linux/drivers/comedi/comedi_pcmcia.c (revision 1136fa0c07de570dc17858745af8be169d1440ba)
1  // SPDX-License-Identifier: GPL-2.0+
2  /*
3   * comedi_pcmcia.c
4   * Comedi PCMCIA driver specific functions.
5   *
6   * COMEDI - Linux Control and Measurement Device Interface
7   * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
8   */
9  
10  #include <linux/module.h>
11  #include <linux/kernel.h>
12  #include <linux/comedi/comedi_pcmcia.h>
13  
14  /**
15   * comedi_to_pcmcia_dev() - Return PCMCIA 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 pcmcia_device.
20   *
21   * Return: Attached PCMCIA device if @dev->hw_dev is non-%NULL.
22   * Return %NULL if @dev->hw_dev is %NULL.
23   */
24  struct pcmcia_device *comedi_to_pcmcia_dev(struct comedi_device *dev)
25  {
26  	return dev->hw_dev ? to_pcmcia_dev(dev->hw_dev) : NULL;
27  }
28  EXPORT_SYMBOL_GPL(comedi_to_pcmcia_dev);
29  
30  static int comedi_pcmcia_conf_check(struct pcmcia_device *link,
31  				    void *priv_data)
32  {
33  	if (link->config_index == 0)
34  		return -EINVAL;
35  
36  	return pcmcia_request_io(link);
37  }
38  
39  /**
40   * comedi_pcmcia_enable() - Request the regions and enable the PCMCIA device
41   * @dev: COMEDI device.
42   * @conf_check: Optional callback to check each configuration option of the
43   *	PCMCIA device and request I/O regions.
44   *
45   * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a a
46   * &struct device embedded in a &struct pcmcia_device.  The comedi PCMCIA
47   * driver needs to set the 'config_flags' member in the &struct pcmcia_device,
48   * as appropriate for that driver, before calling this function in order to
49   * allow pcmcia_loop_config() to do its internal autoconfiguration.
50   *
51   * If @conf_check is %NULL it is set to a default function.  If is
52   * passed to pcmcia_loop_config() and should return %0 if the configuration
53   * is valid and I/O regions requested successfully, otherwise it should return
54   * a negative error value.  The default function returns -%EINVAL if the
55   * 'config_index' member is %0, otherwise it calls pcmcia_request_io() and
56   * returns the result.
57   *
58   * If the above configuration check passes, pcmcia_enable_device() is called
59   * to set up and activate the PCMCIA device.
60   *
61   * If this function returns an error, comedi_pcmcia_disable() should be called
62   * to release requested resources.
63   *
64   * Return:
65   *	0 on success,
66   *	-%ENODEV id @dev->hw_dev is %NULL,
67   *	a negative error number from pcmcia_loop_config() if it fails,
68   *	or a negative error number from pcmcia_enable_device() if it fails.
69   */
70  int comedi_pcmcia_enable(struct comedi_device *dev,
71  			 int (*conf_check)(struct pcmcia_device *p_dev,
72  					   void *priv_data))
73  {
74  	struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
75  	int ret;
76  
77  	if (!link)
78  		return -ENODEV;
79  
80  	if (!conf_check)
81  		conf_check = comedi_pcmcia_conf_check;
82  
83  	ret = pcmcia_loop_config(link, conf_check, NULL);
84  	if (ret)
85  		return ret;
86  
87  	return pcmcia_enable_device(link);
88  }
89  EXPORT_SYMBOL_GPL(comedi_pcmcia_enable);
90  
91  /**
92   * comedi_pcmcia_disable() - Disable the PCMCIA device and release the regions
93   * @dev: COMEDI device.
94   *
95   * Assuming @dev->hw_dev is non-%NULL, it is assumed to be pointing to a
96   * a &struct device embedded in a &struct pcmcia_device.  Call
97   * pcmcia_disable_device() to disable and clean up the PCMCIA device.
98   */
99  void comedi_pcmcia_disable(struct comedi_device *dev)
100  {
101  	struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
102  
103  	if (link)
104  		pcmcia_disable_device(link);
105  }
106  EXPORT_SYMBOL_GPL(comedi_pcmcia_disable);
107  
108  /**
109   * comedi_pcmcia_auto_config() - Configure/probe a PCMCIA COMEDI device
110   * @link: PCMCIA device.
111   * @driver: Registered COMEDI driver.
112   *
113   * Typically called from the pcmcia_driver (*probe) function.  Auto-configure
114   * a COMEDI device, using a pointer to the &struct device embedded in *@link
115   * as the hardware device.  The @driver's "auto_attach" handler may call
116   * comedi_to_pcmcia_dev() on the passed in COMEDI device to recover @link.
117   *
118   * Return: The result of calling comedi_auto_config() (0 on success, or a
119   * negative error number on failure).
120   */
121  int comedi_pcmcia_auto_config(struct pcmcia_device *link,
122  			      struct comedi_driver *driver)
123  {
124  	return comedi_auto_config(&link->dev, driver, 0);
125  }
126  EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_config);
127  
128  /**
129   * comedi_pcmcia_auto_unconfig() - Unconfigure/remove a PCMCIA COMEDI device
130   * @link: PCMCIA device.
131   *
132   * Typically called from the pcmcia_driver (*remove) function.
133   * Auto-unconfigure a COMEDI device attached to this PCMCIA device, using a
134   * pointer to the &struct device embedded in *@link as the hardware device.
135   * The COMEDI driver's "detach" handler will be called during unconfiguration
136   * of the COMEDI device.
137   *
138   * Note that the COMEDI device may have already been unconfigured using the
139   * %COMEDI_DEVCONFIG ioctl, in which case this attempt to unconfigure it
140   * again should be ignored.
141   */
142  void comedi_pcmcia_auto_unconfig(struct pcmcia_device *link)
143  {
144  	comedi_auto_unconfig(&link->dev);
145  }
146  EXPORT_SYMBOL_GPL(comedi_pcmcia_auto_unconfig);
147  
148  /**
149   * comedi_pcmcia_driver_register() - Register a PCMCIA COMEDI driver
150   * @comedi_driver: COMEDI driver to be registered.
151   * @pcmcia_driver: PCMCIA driver to be registered.
152   *
153   * This function is used for the module_init() of PCMCIA COMEDI driver modules
154   * to register the COMEDI driver and the PCMCIA driver.  Do not call it
155   * directly, use the module_comedi_pcmcia_driver() helper macro instead.
156   *
157   * Return: 0 on success, or a negative error number on failure.
158   */
159  int comedi_pcmcia_driver_register(struct comedi_driver *comedi_driver,
160  				  struct pcmcia_driver *pcmcia_driver)
161  {
162  	int ret;
163  
164  	ret = comedi_driver_register(comedi_driver);
165  	if (ret < 0)
166  		return ret;
167  
168  	ret = pcmcia_register_driver(pcmcia_driver);
169  	if (ret < 0) {
170  		comedi_driver_unregister(comedi_driver);
171  		return ret;
172  	}
173  
174  	return 0;
175  }
176  EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_register);
177  
178  /**
179   * comedi_pcmcia_driver_unregister() - Unregister a PCMCIA COMEDI driver
180   * @comedi_driver: COMEDI driver to be registered.
181   * @pcmcia_driver: PCMCIA driver to be registered.
182   *
183   * This function is called from the module_exit() of PCMCIA COMEDI driver
184   * modules to unregister the PCMCIA driver and the COMEDI driver.  Do not call
185   * it directly, use the module_comedi_pcmcia_driver() helper macro instead.
186   */
187  void comedi_pcmcia_driver_unregister(struct comedi_driver *comedi_driver,
188  				     struct pcmcia_driver *pcmcia_driver)
189  {
190  	pcmcia_unregister_driver(pcmcia_driver);
191  	comedi_driver_unregister(comedi_driver);
192  }
193  EXPORT_SYMBOL_GPL(comedi_pcmcia_driver_unregister);
194  
195  static int __init comedi_pcmcia_init(void)
196  {
197  	return 0;
198  }
199  module_init(comedi_pcmcia_init);
200  
201  static void __exit comedi_pcmcia_exit(void)
202  {
203  }
204  module_exit(comedi_pcmcia_exit);
205  
206  MODULE_AUTHOR("https://www.comedi.org");
207  MODULE_DESCRIPTION("Comedi PCMCIA interface module");
208  MODULE_LICENSE("GPL");
209