28 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/types.h>
32 #include <linux/list.h>
40 #include <linux/pci.h>
42 #include <asm/uaccess.h>
45 #define MY_NAME "pci_hotplug"
47 #define dbg(fmt, arg...) do { if (debug) printk(KERN_DEBUG "%s: %s: " fmt , MY_NAME , __func__ , ## arg); } while (0)
48 #define err(format, arg...) printk(KERN_ERR "%s: " format , MY_NAME , ## arg)
49 #define info(format, arg...) printk(KERN_INFO "%s: " format , MY_NAME , ## arg)
50 #define warn(format, arg...) printk(KERN_WARNING "%s: " format , MY_NAME , ## arg)
56 #define DRIVER_VERSION "0.5"
58 #define DRIVER_DESC "PCI Hot Plug PCI Core"
66 #ifdef CONFIG_HOTPLUG_PCI_CPCI
75 #define GET_STATUS(name,type) \
76 static int get_##name (struct hotplug_slot *slot, type *value) \
78 struct hotplug_slot_ops *ops = slot->ops; \
80 if (!try_module_get(ops->owner)) \
82 if (ops->get_##name) \
83 retval = ops->get_##name(slot, value); \
85 *value = slot->info->name; \
86 module_put(ops->owner); \
100 retval = get_power_status(slot->hotplug, &value);
103 retval =
sprintf (buf,
"%d\n", value);
112 unsigned long lpower;
117 power = (
u8)(lpower & 0xff);
118 dbg (
"power = %d\n", power);
120 if (!try_module_get(slot->ops->owner)) {
126 if (slot->ops->disable_slot)
127 retval = slot->ops->disable_slot(slot);
131 if (slot->ops->enable_slot)
132 retval = slot->ops->enable_slot(slot);
136 err (
"Illegal value specified for power\n");
139 module_put(slot->ops->owner);
149 .show = power_read_file,
150 .store = power_write_file
153 static ssize_t attention_read_file(
struct pci_slot *slot,
char *buf)
158 retval = get_attention_status(slot->
hotplug, &value);
161 retval =
sprintf(buf,
"%d\n", value);
167 static ssize_t attention_write_file(
struct pci_slot *slot,
const char *buf,
171 unsigned long lattention;
176 attention = (
u8)(lattention & 0xff);
177 dbg (
" - attention = %d\n", attention);
179 if (!try_module_get(ops->
owner)) {
185 module_put(ops->
owner);
195 .show = attention_read_file,
196 .store = attention_write_file
199 static ssize_t latch_read_file(
struct pci_slot *slot,
char *buf)
204 retval = get_latch_status(slot->
hotplug, &value);
207 retval =
sprintf (buf,
"%d\n", value);
215 .show = latch_read_file,
218 static ssize_t presence_read_file(
struct pci_slot *slot,
char *buf)
223 retval = get_adapter_status(slot->
hotplug, &value);
226 retval =
sprintf (buf,
"%d\n", value);
234 .show = presence_read_file,
237 static ssize_t test_write_file(
struct pci_slot *pci_slot,
const char *buf,
240 struct hotplug_slot *slot = pci_slot->
hotplug;
246 test = (
u32)(ltest & 0xffffffff);
247 dbg (
"test = %d\n", test);
249 if (!try_module_get(slot->ops->owner)) {
253 if (slot->ops->hardware_test)
254 retval = slot->ops->hardware_test(slot, test);
255 module_put(slot->ops->owner);
265 .store = test_write_file
268 static bool has_power_file(
struct pci_slot *pci_slot)
270 struct hotplug_slot *slot = pci_slot->
hotplug;
271 if ((!slot) || (!slot->ops))
273 if ((slot->ops->enable_slot) ||
274 (slot->ops->disable_slot) ||
275 (slot->ops->get_power_status))
280 static bool has_attention_file(
struct pci_slot *pci_slot)
282 struct hotplug_slot *slot = pci_slot->
hotplug;
283 if ((!slot) || (!slot->ops))
285 if ((slot->ops->set_attention_status) ||
286 (slot->ops->get_attention_status))
291 static bool has_latch_file(
struct pci_slot *pci_slot)
293 struct hotplug_slot *slot = pci_slot->
hotplug;
294 if ((!slot) || (!slot->ops))
296 if (slot->ops->get_latch_status)
301 static bool has_adapter_file(
struct pci_slot *pci_slot)
303 struct hotplug_slot *slot = pci_slot->
hotplug;
304 if ((!slot) || (!slot->ops))
306 if (slot->ops->get_adapter_status)
311 static bool has_test_file(
struct pci_slot *pci_slot)
313 struct hotplug_slot *slot = pci_slot->
hotplug;
314 if ((!slot) || (!slot->ops))
316 if (slot->ops->hardware_test)
321 static int fs_add_slot(
struct pci_slot *slot)
326 pci_hp_create_module_link(slot);
328 if (has_power_file(slot)) {
330 &hotplug_slot_attr_power.
attr);
335 if (has_attention_file(slot)) {
337 &hotplug_slot_attr_attention.
attr);
342 if (has_latch_file(slot)) {
344 &hotplug_slot_attr_latch.
attr);
349 if (has_adapter_file(slot)) {
351 &hotplug_slot_attr_presence.
attr);
356 if (has_test_file(slot)) {
358 &hotplug_slot_attr_test.
attr);
366 if (has_adapter_file(slot))
368 &hotplug_slot_attr_presence.
attr);
370 if (has_latch_file(slot))
373 if (has_attention_file(slot))
375 &hotplug_slot_attr_attention.
attr);
377 if (has_power_file(slot))
380 pci_hp_remove_module_link(slot);
385 static void fs_remove_slot(
struct pci_slot *slot)
387 if (has_power_file(slot))
390 if (has_attention_file(slot))
392 &hotplug_slot_attr_attention.
attr);
394 if (has_latch_file(slot))
397 if (has_adapter_file(slot))
399 &hotplug_slot_attr_presence.
attr);
401 if (has_test_file(slot))
404 pci_hp_remove_module_link(slot);
407 static struct hotplug_slot *get_slot_from_name (
const char *
name)
409 struct hotplug_slot *
slot;
413 slot =
list_entry (tmp,
struct hotplug_slot, slot_list);
414 if (
strcmp(hotplug_slot_name(slot), name) == 0)
435 int devnr,
const char *name,
443 if ((slot->info ==
NULL) || (slot->ops ==
NULL))
445 if (slot->release ==
NULL) {
446 dbg(
"Why are you trying to register a hotplug slot "
447 "without a proper release function?\n");
451 slot->ops->owner =
owner;
452 slot->ops->mod_name = mod_name;
461 if (IS_ERR(pci_slot)) {
462 result = PTR_ERR(pci_slot);
469 list_add(&slot->slot_list, &pci_hotplug_slot_list);
471 result = fs_add_slot(pci_slot);
473 dbg(
"Added slot %s to the list\n", name);
490 struct hotplug_slot *
temp;
491 struct pci_slot *
slot;
497 temp = get_slot_from_name(hotplug_slot_name(hotplug));
498 if (temp != hotplug) {
505 slot = hotplug->pci_slot;
506 fs_remove_slot(slot);
507 dbg(
"Removed slot %s from the list\n", hotplug_slot_name(hotplug));
509 hotplug->release(hotplug);
530 struct pci_slot *
slot;
531 if (!hotplug || !info)
533 slot = hotplug->pci_slot;
540 static int __init pci_hotplug_init (
void)
546 err (
"cpci_hotplug_init with error %d\n", result);
556 static void __exit pci_hotplug_exit (
void)