29 #include <linux/slab.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
35 #include <asm/uaccess.h>
37 #include <linux/pci.h>
42 #define DRIVER_VERSION "1.0.1"
44 #define DRIVER_DESC "ACPI Hot Plug PCI Controller Driver IBM extension"
54 #define MY_NAME "acpiphp_ibm"
57 #define dbg(format, arg...) \
60 printk(KERN_DEBUG "%s: " format, \
64 #define FOUND_APCI 0x61504349
66 #define IBM_HARDWARE_ID1 "IBM37D0"
67 #define IBM_HARDWARE_ID2 "IBM37D4"
69 #define hpslot_to_sun(A) (((struct slot *)((A)->private))->acpi_slot->sun)
107 static int ibm_set_attention_status(
struct hotplug_slot *
slot,
u8 status);
108 static int ibm_get_attention_status(
struct hotplug_slot *
slot,
u8 *
status);
110 static int ibm_get_table_from_acpi(
char **bufp);
116 static int __init ibm_acpiphp_init(
void);
117 static void __exit ibm_acpiphp_exit(
void);
123 .name =
"apci_table",
126 .read = ibm_read_apci_table,
131 .set_attn = ibm_set_attention_status,
132 .get_attn = ibm_get_attention_status,
151 size = ibm_get_table_from_acpi(&table);
153 if (
memcmp(des->header.sig,
"aPCI", 4) != 0)
157 while (ind <
size && (des->generic.type != 0x82 ||
158 des->slot.slot_num !=
id)) {
162 if (ind < size && des->
slot.slot_num ==
id)
182 static int ibm_set_attention_status(
struct hotplug_slot *
slot,
u8 status)
187 unsigned long long rc;
192 dbg(
"%s: set slot %d (%d) attention status to %d\n", __func__,
193 ibm_slot->
slot.slot_num, ibm_slot->
slot.slot_id,
205 err(
"APLS evaluation failed: 0x%08x\n", stat);
208 err(
"APLS method failed: 0x%08llx\n", rc);
226 static int ibm_get_attention_status(
struct hotplug_slot *slot,
u8 *status)
232 if (ibm_slot->
slot.attn & 0xa0 || ibm_slot->
slot.status[1] & 0x08)
237 dbg(
"%s: get slot %d (%d) attention status is %d\n", __func__,
238 ibm_slot->
slot.slot_num, ibm_slot->
slot.slot_id,
265 u8 detail = event & 0x0f;
266 u8 subevent = event & 0xf0;
269 dbg(
"%s: Received notification %02x\n", __func__, event);
271 if (subevent == 0x80) {
272 dbg(
"%s: generationg bus event\n", __func__);
273 acpi_bus_generate_proc_event(note->
device, note->
event, detail);
275 dev_name(¬e->
device->dev),
276 note->
event, detail);
295 static int ibm_get_table_from_acpi(
char **bufp)
305 err(
"%s: APCI evaluation failed\n", __func__);
309 package = (union acpi_object *) buffer.pointer;
312 !(package->
package.elements)) {
313 err(
"%s: Invalid APCI object\n", __func__);
314 goto read_table_done;
317 for(size = 0, i = 0; i < package->
package.count; i++) {
319 err(
"%s: Invalid APCI element %d\n", __func__, i);
320 goto read_table_done;
322 size += package->
package.elements[
i].buffer.length;
326 goto read_table_done;
329 dbg(
"%s: element count: %i, ASL table size: %i, &table = 0x%p\n",
330 __func__, package->
package.count, size, lbuf);
336 goto read_table_done;
340 for (i=0; i<package->
package.count; i++) {
342 package->
package.elements[i].buffer.pointer,
343 package->
package.elements[i].buffer.length);
344 size += package->
package.elements[
i].buffer.length;
370 char *buffer, loff_t
pos,
size_t size)
375 dbg(
"%s: pos = %d, size = %zd\n", __func__, (
int)pos, size);
378 bytes_read = ibm_get_table_from_acpi(&table);
379 if (bytes_read > 0 && bytes_read <= size)
380 memcpy(buffer, table, bytes_read);
398 u32 lvl,
void *context,
void **rv)
407 err(
"%s: Failed to get device information status=0x%x\n",
415 dbg(
"found hardware: %s, handle: %p\n",
429 static int __init ibm_acpiphp_init(
void)
433 struct acpi_device *
device;
436 dbg(
"%s\n", __func__);
441 err(
"%s: acpi_walk_namespace failed\n", __func__);
445 dbg(
"%s: found IBM aPCI device\n", __func__);
447 err(
"%s: acpi_bus_get_device failed\n", __func__);
461 err(
"%s: Failed to register notification handler\n",
467 ibm_apci_table_attr.
size = ibm_get_table_from_acpi(
NULL);
478 static void __exit ibm_acpiphp_exit(
void)
483 dbg(
"%s\n", __func__);
486 err(
"%s: attention info deregistration failed", __func__);
493 err(
"%s: Notification handler removal failed\n", __func__);