2 * card.c - contains functions for managing groups of PnP devices
4 * Copyright 2002 Adam Belay <ambx1@neo.rr.com>
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/slab.h>
12 #ifdef CONFIG_PNP_DEBUG
18 #include <linux/pnp.h>
22 LIST_HEAD(pnp_card_drivers
);
25 static const struct pnp_card_device_id
* match_card(struct pnp_card_driver
* drv
, struct pnp_card
* card
)
27 const struct pnp_card_device_id
* drv_id
= drv
->id_table
;
29 if (compare_pnp_id(card
->id
,drv_id
->id
))
36 static void card_remove(struct pnp_dev
* dev
)
38 dev
->card_link
= NULL
;
41 static void card_remove_first(struct pnp_dev
* dev
)
43 struct pnp_card_driver
* drv
= to_pnp_card_driver(dev
->driver
);
44 if (!dev
->card
|| !drv
)
47 drv
->remove(dev
->card_link
);
48 drv
->link
.remove
= &card_remove
;
49 kfree(dev
->card_link
);
53 static int card_probe(struct pnp_card
* card
, struct pnp_card_driver
* drv
)
55 const struct pnp_card_device_id
*id
= match_card(drv
,card
);
57 struct pnp_card_link
* clink
= pnp_alloc(sizeof(struct pnp_card_link
));
63 if (drv
->probe(clink
, id
)>=0)
67 card_for_each_dev(card
, dev
) {
68 if (dev
->card_link
== clink
)
69 pnp_release_card_device(dev
);
80 * pnp_add_card_id - adds an EISA id to the specified card
81 * @id: pointer to a pnp_id structure
82 * @card: pointer to the desired card
86 int pnp_add_card_id(struct pnp_id
*id
, struct pnp_card
* card
)
95 while (ptr
&& ptr
->next
)
104 static void pnp_free_card_ids(struct pnp_card
* card
)
118 static void pnp_release_card(struct device
*dmdev
)
120 struct pnp_card
* card
= to_pnp_card(dmdev
);
121 pnp_free_card_ids(card
);
126 * pnp_add_card - adds a PnP card to the PnP Layer
127 * @card: pointer to the card to add
130 int pnp_add_card(struct pnp_card
* card
)
133 struct list_head
* pos
, * temp
;
134 if (!card
|| !card
->protocol
)
137 sprintf(card
->dev
.bus_id
, "%02x:%02x", card
->protocol
->number
, card
->number
);
138 card
->dev
.parent
= &card
->protocol
->dev
;
139 card
->dev
.bus
= NULL
;
140 card
->dev
.release
= &pnp_release_card
;
141 error
= device_register(&card
->dev
);
144 spin_lock(&pnp_lock
);
145 list_add_tail(&card
->global_list
, &pnp_cards
);
146 list_add_tail(&card
->protocol_list
, &card
->protocol
->cards
);
147 spin_unlock(&pnp_lock
);
149 /* we wait until now to add devices in order to ensure the drivers
150 * will be able to use all of the related devices on the card
151 * without waiting any unresonable length of time */
152 list_for_each(pos
,&card
->devices
){
153 struct pnp_dev
*dev
= card_to_pnp_dev(pos
);
154 __pnp_add_device(dev
);
157 /* match with card drivers */
158 list_for_each_safe(pos
,temp
,&pnp_card_drivers
){
159 struct pnp_card_driver
* drv
= list_entry(pos
, struct pnp_card_driver
, global_list
);
160 card_probe(card
,drv
);
163 pnp_err("sysfs failure, card '%s' will be unavailable", card
->dev
.bus_id
);
168 * pnp_remove_card - removes a PnP card from the PnP Layer
169 * @card: pointer to the card to remove
172 void pnp_remove_card(struct pnp_card
* card
)
174 struct list_head
*pos
, *temp
;
177 device_unregister(&card
->dev
);
178 spin_lock(&pnp_lock
);
179 list_del(&card
->global_list
);
180 list_del(&card
->protocol_list
);
181 spin_unlock(&pnp_lock
);
182 list_for_each_safe(pos
,temp
,&card
->devices
){
183 struct pnp_dev
*dev
= card_to_pnp_dev(pos
);
184 pnp_remove_card_device(dev
);
189 * pnp_add_card_device - adds a device to the specified card
190 * @card: pointer to the card to add to
191 * @dev: pointer to the device to add
194 int pnp_add_card_device(struct pnp_card
* card
, struct pnp_dev
* dev
)
196 if (!card
|| !dev
|| !dev
->protocol
)
198 dev
->dev
.parent
= &card
->dev
;
199 dev
->card_link
= NULL
;
200 snprintf(dev
->dev
.bus_id
, BUS_ID_SIZE
, "%02x:%02x.%02x", dev
->protocol
->number
,
201 card
->number
,dev
->number
);
202 spin_lock(&pnp_lock
);
204 list_add_tail(&dev
->card_list
, &card
->devices
);
205 spin_unlock(&pnp_lock
);
210 * pnp_remove_card_device- removes a device from the specified card
211 * @card: pointer to the card to remove from
212 * @dev: pointer to the device to remove
215 void pnp_remove_card_device(struct pnp_dev
* dev
)
217 spin_lock(&pnp_lock
);
219 list_del(&dev
->card_list
);
220 spin_unlock(&pnp_lock
);
221 __pnp_remove_device(dev
);
225 * pnp_request_card_device - Searches for a PnP device under the specified card
226 * @lcard: pointer to the card link, cannot be NULL
227 * @id: pointer to a PnP ID structure that explains the rules for finding the device
228 * @from: Starting place to search from. If NULL it will start from the begining.
231 struct pnp_dev
* pnp_request_card_device(struct pnp_card_link
*clink
, const char * id
, struct pnp_dev
* from
)
233 struct list_head
* pos
;
234 struct pnp_dev
* dev
;
235 struct pnp_card_driver
* drv
;
236 struct pnp_card
* card
;
242 pos
= card
->devices
.next
;
244 if (from
->card
!= card
)
246 pos
= from
->card_list
.next
;
248 while (pos
!= &card
->devices
) {
249 dev
= card_to_pnp_dev(pos
);
250 if ((!dev
->card_link
) && compare_pnp_id(dev
->id
,id
))
259 down_write(&dev
->dev
.bus
->subsys
.rwsem
);
260 dev
->card_link
= clink
;
261 dev
->dev
.driver
= &drv
->link
.driver
;
262 if (drv
->link
.driver
.probe
) {
263 if (drv
->link
.driver
.probe(&dev
->dev
)) {
264 dev
->dev
.driver
= NULL
;
268 device_bind_driver(&dev
->dev
);
269 up_write(&dev
->dev
.bus
->subsys
.rwsem
);
275 * pnp_release_card_device - call this when the driver no longer needs the device
276 * @dev: pointer to the PnP device stucture
279 void pnp_release_card_device(struct pnp_dev
* dev
)
281 struct pnp_card_driver
* drv
= dev
->card_link
->driver
;
284 down_write(&dev
->dev
.bus
->subsys
.rwsem
);
285 drv
->link
.remove
= &card_remove
;
286 device_release_driver(&dev
->dev
);
287 drv
->link
.remove
= &card_remove_first
;
288 up_write(&dev
->dev
.bus
->subsys
.rwsem
);
292 * pnp_register_card_driver - registers a PnP card driver with the PnP Layer
293 * @drv: pointer to the driver to register
296 int pnp_register_card_driver(struct pnp_card_driver
* drv
)
299 struct list_head
*pos
, *temp
;
301 drv
->link
.name
= drv
->name
;
302 drv
->link
.id_table
= NULL
; /* this will disable auto matching */
303 drv
->link
.flags
= drv
->flags
;
304 drv
->link
.probe
= NULL
;
305 drv
->link
.remove
= &card_remove_first
;
307 spin_lock(&pnp_lock
);
308 list_add_tail(&drv
->global_list
, &pnp_card_drivers
);
309 spin_unlock(&pnp_lock
);
310 pnp_register_driver(&drv
->link
);
312 list_for_each_safe(pos
,temp
,&pnp_cards
){
313 struct pnp_card
*card
= list_entry(pos
, struct pnp_card
, global_list
);
314 count
+= card_probe(card
,drv
);
320 * pnp_unregister_card_driver - unregisters a PnP card driver from the PnP Layer
321 * @drv: pointer to the driver to unregister
324 void pnp_unregister_card_driver(struct pnp_card_driver
* drv
)
326 spin_lock(&pnp_lock
);
327 list_del(&drv
->global_list
);
328 spin_unlock(&pnp_lock
);
329 pnp_unregister_driver(&drv
->link
);
332 EXPORT_SYMBOL(pnp_add_card
);
333 EXPORT_SYMBOL(pnp_remove_card
);
334 EXPORT_SYMBOL(pnp_add_card_device
);
335 EXPORT_SYMBOL(pnp_remove_card_device
);
336 EXPORT_SYMBOL(pnp_add_card_id
);
337 EXPORT_SYMBOL(pnp_request_card_device
);
338 EXPORT_SYMBOL(pnp_release_card_device
);
339 EXPORT_SYMBOL(pnp_register_card_driver
);
340 EXPORT_SYMBOL(pnp_unregister_card_driver
);