vserver 2.0 rc7
[linux-2.6.git] / drivers / input / serio / i8042-x86ia64io.h
index c0a1974..0487ecb 100644 (file)
@@ -67,7 +67,7 @@ static inline void i8042_write_command(int val)
 
 #include <linux/dmi.h>
 
-static struct dmi_system_id __initdata i8042_dmi_table[] = {
+static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = {
        {
                .ident = "Compaq Proliant 8500",
                .matches = {
@@ -86,186 +86,228 @@ static struct dmi_system_id __initdata i8042_dmi_table[] = {
        },
        { }
 };
+
+/*
+ * Some Fujitsu notebooks are having trouble with touchpads if
+ * active multiplexing mode is activated. Luckily they don't have
+ * external PS/2 ports so we can safely disable it.
+ * ... apparently some Toshibas don't like MUX mode either and
+ * die horrible death on reboot.
+ */
+static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
+       {
+               .ident = "Fujitsu Lifebook P7010/P7010D",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "P7010"),
+               },
+       },
+       {
+               .ident = "Fujitsu Lifebook P5020D",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook P Series"),
+               },
+       },
+       {
+               .ident = "Fujitsu Lifebook S2000",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S Series"),
+               },
+       },
+       {
+               .ident = "Fujitsu Lifebook S6230",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook S6230"),
+               },
+       },
+       {
+               .ident = "Fujitsu T70H",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "FMVLT70H"),
+               },
+       },
+       {
+               .ident = "Toshiba P10",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"),
+               },
+       },
+       { }
+};
+
+
+
 #endif
 
-#if defined(__ia64__) && defined(CONFIG_ACPI)
-#include <linux/acpi.h>
-#include <acpi/acpi_bus.h>
 
-struct i8042_acpi_resources {
-       unsigned int port1;
-       unsigned int port2;
-       unsigned int irq;
-};
+#ifdef CONFIG_PNP
+#include <linux/pnp.h>
 
-static int i8042_acpi_kbd_registered;
-static int i8042_acpi_aux_registered;
+static int i8042_pnp_kbd_registered;
+static int i8042_pnp_aux_registered;
 
-static acpi_status i8042_acpi_parse_resource(struct acpi_resource *res, void *data)
-{
-       struct i8042_acpi_resources *i8042_res = data;
-       struct acpi_resource_io *io;
-       struct acpi_resource_fixed_io *fixed_io;
-       struct acpi_resource_irq *irq;
-       struct acpi_resource_ext_irq *ext_irq;
-
-       switch (res->id) {
-               case ACPI_RSTYPE_IO:
-                       io = &res->data.io;
-                       if (io->range_length) {
-                               if (!i8042_res->port1)
-                                       i8042_res->port1 = io->min_base_address;
-                               else
-                                       i8042_res->port2 = io->min_base_address;
-                       }
-                       break;
-
-               case ACPI_RSTYPE_FIXED_IO:
-                       fixed_io = &res->data.fixed_io;
-                       if (fixed_io->range_length) {
-                               if (!i8042_res->port1)
-                                       i8042_res->port1 = fixed_io->base_address;
-                               else
-                                       i8042_res->port2 = fixed_io->base_address;
-                       }
-                       break;
-
-               case ACPI_RSTYPE_IRQ:
-                       irq = &res->data.irq;
-                       if (irq->number_of_interrupts > 0)
-                               i8042_res->irq =
-                                       acpi_register_gsi(irq->interrupts[0],
-                                                         irq->edge_level,
-                                                         irq->active_high_low);
-                       break;
-
-               case ACPI_RSTYPE_EXT_IRQ:
-                       ext_irq = &res->data.extended_irq;
-                       if (ext_irq->number_of_interrupts > 0)
-                               i8042_res->irq =
-                                       acpi_register_gsi(ext_irq->interrupts[0],
-                                                         ext_irq->edge_level,
-                                                         ext_irq->active_high_low);
-                       break;
-       }
-       return AE_OK;
-}
+static int i8042_pnp_command_reg;
+static int i8042_pnp_data_reg;
+static int i8042_pnp_kbd_irq;
+static int i8042_pnp_aux_irq;
+
+static char i8042_pnp_kbd_name[32];
+static char i8042_pnp_aux_name[32];
 
-static int i8042_acpi_kbd_add(struct acpi_device *device)
+static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
-       struct i8042_acpi_resources kbd_res;
-       acpi_status status;
+       if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+               i8042_pnp_data_reg = pnp_port_start(dev,0);
 
-       memset(&kbd_res, 0, sizeof(kbd_res));
-       status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-                                    i8042_acpi_parse_resource, &kbd_res);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
+       if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+               i8042_pnp_command_reg = pnp_port_start(dev, 1);
+
+       if (pnp_irq_valid(dev,0))
+               i8042_pnp_kbd_irq = pnp_irq(dev, 0);
 
-       if (kbd_res.port1)
-               i8042_data_reg = kbd_res.port1;
-       else
-               printk(KERN_WARNING "ACPI: [%s] has no data port; default is 0x%x\n",
-                       acpi_device_bid(device), i8042_data_reg);
-
-       if (kbd_res.port2)
-               i8042_command_reg = kbd_res.port2;
-       else
-               printk(KERN_WARNING "ACPI: [%s] has no command port; default is 0x%x\n",
-                       acpi_device_bid(device), i8042_command_reg);
-
-       if (kbd_res.irq)
-               i8042_kbd_irq = kbd_res.irq;
-       else
-               printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
-                       acpi_device_bid(device), i8042_kbd_irq);
-
-       strncpy(acpi_device_name(device), "PS/2 Keyboard Controller",
-               sizeof(acpi_device_name(device)));
-       printk("ACPI: %s [%s] at I/O 0x%x, 0x%x, irq %d\n",
-               acpi_device_name(device), acpi_device_bid(device),
-               i8042_data_reg, i8042_command_reg, i8042_kbd_irq);
+       strncpy(i8042_pnp_kbd_name, did->id, sizeof(i8042_pnp_kbd_name));
+       if (strlen(pnp_dev_name(dev))) {
+               strncat(i8042_pnp_kbd_name, ":", sizeof(i8042_pnp_kbd_name));
+               strncat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name));
+       }
 
        return 0;
 }
 
-static int i8042_acpi_aux_add(struct acpi_device *device)
+static int i8042_pnp_aux_probe(struct pnp_dev *dev, const struct pnp_device_id *did)
 {
-       struct i8042_acpi_resources aux_res;
-       acpi_status status;
+       if (pnp_port_valid(dev, 0) && pnp_port_len(dev, 0) == 1)
+               i8042_pnp_data_reg = pnp_port_start(dev,0);
 
-       memset(&aux_res, 0, sizeof(aux_res));
-       status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-                                    i8042_acpi_parse_resource, &aux_res);
-       if (ACPI_FAILURE(status))
-               return -ENODEV;
+       if (pnp_port_valid(dev, 1) && pnp_port_len(dev, 1) == 1)
+               i8042_pnp_command_reg = pnp_port_start(dev, 1);
 
-       if (aux_res.irq)
-               i8042_aux_irq = aux_res.irq;
-       else
-               printk(KERN_WARNING "ACPI: [%s] has no IRQ; default is %d\n",
-                       acpi_device_bid(device), i8042_aux_irq);
+       if (pnp_irq_valid(dev, 0))
+               i8042_pnp_aux_irq = pnp_irq(dev, 0);
 
-       strncpy(acpi_device_name(device), "PS/2 Mouse Controller",
-               sizeof(acpi_device_name(device)));
-       printk("ACPI: %s [%s] at irq %d\n",
-               acpi_device_name(device), acpi_device_bid(device), i8042_aux_irq);
+       strncpy(i8042_pnp_aux_name, did->id, sizeof(i8042_pnp_aux_name));
+       if (strlen(pnp_dev_name(dev))) {
+               strncat(i8042_pnp_aux_name, ":", sizeof(i8042_pnp_aux_name));
+               strncat(i8042_pnp_aux_name, pnp_dev_name(dev), sizeof(i8042_pnp_aux_name));
+       }
 
        return 0;
 }
 
-static struct acpi_driver i8042_acpi_kbd_driver = {
-       .name           = "i8042",
-       .ids            = "PNP0303,PNP030B",
-       .ops            = {
-               .add            = i8042_acpi_kbd_add,
-       },
+static struct pnp_device_id pnp_kbd_devids[] = {
+       { .id = "PNP0303", .driver_data = 0 },
+       { .id = "PNP030b", .driver_data = 0 },
+       { .id = "", },
 };
 
-static struct acpi_driver i8042_acpi_aux_driver = {
-       .name           = "i8042",
-       .ids            = "PNP0F03,PNP0F0B,PNP0F0E,PNP0F12,PNP0F13,SYN0801",
-       .ops            = {
-               .add            = i8042_acpi_aux_add,
-       },
+static struct pnp_driver i8042_pnp_kbd_driver = {
+       .name           = "i8042 kbd",
+       .id_table       = pnp_kbd_devids,
+       .probe          = i8042_pnp_kbd_probe,
 };
 
-static int i8042_acpi_init(void)
+static struct pnp_device_id pnp_aux_devids[] = {
+       { .id = "PNP0f03", .driver_data = 0 },
+       { .id = "PNP0f0b", .driver_data = 0 },
+       { .id = "PNP0f0e", .driver_data = 0 },
+       { .id = "PNP0f12", .driver_data = 0 },
+       { .id = "PNP0f13", .driver_data = 0 },
+       { .id = "PNP0f19", .driver_data = 0 },
+       { .id = "PNP0f1c", .driver_data = 0 },
+       { .id = "SYN0801", .driver_data = 0 },
+       { .id = "", },
+};
+
+static struct pnp_driver i8042_pnp_aux_driver = {
+       .name           = "i8042 aux",
+       .id_table       = pnp_aux_devids,
+       .probe          = i8042_pnp_aux_probe,
+};
+
+static void i8042_pnp_exit(void)
 {
-       int result;
+       if (i8042_pnp_kbd_registered) {
+               i8042_pnp_kbd_registered = 0;
+               pnp_unregister_driver(&i8042_pnp_kbd_driver);
+       }
+
+       if (i8042_pnp_aux_registered) {
+               i8042_pnp_aux_registered = 0;
+               pnp_unregister_driver(&i8042_pnp_aux_driver);
+       }
+}
 
-       if (acpi_disabled || i8042_noacpi) {
-               printk("i8042: ACPI detection disabled\n");
+static int i8042_pnp_init(void)
+{
+       int result_kbd, result_aux;
+
+       if (i8042_nopnp) {
+               printk(KERN_INFO "i8042: PNP detection disabled\n");
                return 0;
        }
 
-       result = acpi_bus_register_driver(&i8042_acpi_kbd_driver);
-       if (result < 0)
-               return result;
+       if ((result_kbd = pnp_register_driver(&i8042_pnp_kbd_driver)) >= 0)
+               i8042_pnp_kbd_registered = 1;
+       if ((result_aux = pnp_register_driver(&i8042_pnp_aux_driver)) >= 0)
+               i8042_pnp_aux_registered = 1;
 
-       if (result == 0) {
-               acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
+       if (result_kbd <= 0 && result_aux <= 0) {
+               i8042_pnp_exit();
+#if defined(__ia64__)
                return -ENODEV;
+#else
+               printk(KERN_INFO "PNP: No PS/2 controller found. Probing ports directly.\n");
+               return 0;
+#endif
+       }
+
+       if (((i8042_pnp_data_reg & ~0xf) == (i8042_data_reg & ~0xf) &&
+             i8042_pnp_data_reg != i8042_data_reg) || !i8042_pnp_data_reg) {
+               printk(KERN_WARNING "PNP: PS/2 controller has invalid data port %#x; using default %#x\n",
+                       i8042_pnp_data_reg, i8042_data_reg);
+               i8042_pnp_data_reg = i8042_data_reg;
+       }
+
+       if (((i8042_pnp_command_reg & ~0xf) == (i8042_command_reg & ~0xf) &&
+             i8042_pnp_command_reg != i8042_command_reg) || !i8042_pnp_command_reg) {
+               printk(KERN_WARNING "PNP: PS/2 controller has invalid command port %#x; using default %#x\n",
+                       i8042_pnp_command_reg, i8042_command_reg);
+               i8042_pnp_command_reg = i8042_command_reg;
+       }
+
+       if (!i8042_pnp_kbd_irq) {
+               printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %#x\n", i8042_kbd_irq);
+               i8042_pnp_kbd_irq = i8042_kbd_irq;
+       }
+
+       if (!i8042_pnp_aux_irq) {
+               printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %#x\n", i8042_aux_irq);
+               i8042_pnp_aux_irq = i8042_aux_irq;
        }
-       i8042_acpi_kbd_registered = 1;
 
-       result = acpi_bus_register_driver(&i8042_acpi_aux_driver);
-       if (result >= 0)
-               i8042_acpi_aux_registered = 1;
-       if (result == 0)
+#if defined(__ia64__)
+       if (result_aux <= 0)
                i8042_noaux = 1;
+#endif
 
-       return 0;
-}
+       i8042_data_reg = i8042_pnp_data_reg;
+       i8042_command_reg = i8042_pnp_command_reg;
+       i8042_kbd_irq = i8042_pnp_kbd_irq;
+       i8042_aux_irq = i8042_pnp_aux_irq;
 
-static void i8042_acpi_exit(void)
-{
-       if (i8042_acpi_kbd_registered)
-               acpi_bus_unregister_driver(&i8042_acpi_kbd_driver);
+       printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %d%s%d\n",
+               i8042_pnp_kbd_name, (result_kbd > 0 && result_aux > 0) ? "," : "", i8042_pnp_aux_name,
+               i8042_data_reg, i8042_command_reg, i8042_kbd_irq,
+               (result_aux > 0) ? "," : "", i8042_aux_irq);
 
-       if (i8042_acpi_aux_registered)
-               acpi_bus_unregister_driver(&i8042_acpi_aux_driver);
+       return 0;
 }
+
 #endif
 
 static inline int i8042_platform_init(void)
@@ -281,8 +323,8 @@ static inline int i8042_platform_init(void)
        i8042_kbd_irq = I8042_MAP_IRQ(1);
        i8042_aux_irq = I8042_MAP_IRQ(12);
 
-#if defined(__ia64__) && defined(CONFIG_ACPI)
-       if (i8042_acpi_init())
+#ifdef CONFIG_PNP
+       if (i8042_pnp_init())
                return -1;
 #endif
 
@@ -291,8 +333,11 @@ static inline int i8042_platform_init(void)
 #endif
 
 #if defined(__i386__)
-       if (dmi_check_system(i8042_dmi_table))
+       if (dmi_check_system(i8042_dmi_noloop_table))
                i8042_noloop = 1;
+
+       if (dmi_check_system(i8042_dmi_nomux_table))
+               i8042_nomux = 1;
 #endif
 
        return 0;
@@ -300,8 +345,8 @@ static inline int i8042_platform_init(void)
 
 static inline void i8042_platform_exit(void)
 {
-#if defined(__ia64__) && defined(CONFIG_ACPI)
-       i8042_acpi_exit();
+#ifdef CONFIG_PNP
+       i8042_pnp_exit();
 #endif
 }