X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Finput%2Fserio%2Fi8042-x86ia64io.h;h=f606e96bc2f4b5e4f5e04f22f0440c94c3453607;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=c0a19743cdf4d79ce194663ad95ef746bf1fcefd;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index c0a19743c..f606e96bc 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -67,7 +67,7 @@ static inline void i8042_write_command(int val) #include -static struct dmi_system_id __initdata i8042_dmi_table[] = { +static struct dmi_system_id __initdata i8042_dmi_noloop_table[] = { { .ident = "Compaq Proliant 8500", .matches = { @@ -84,225 +84,334 @@ static struct dmi_system_id __initdata i8042_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "DL760"), }, }, + { + .ident = "OQO Model 01", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "OQO"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"), + DMI_MATCH(DMI_PRODUCT_VERSION, "00"), + }, + }, + { } +}; + +/* + * 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 = "Fujitsu-Siemens Lifebook T3010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK T3010"), + }, + }, + { + .ident = "Fujitsu-Siemens Lifebook E4010", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK E4010"), + }, + }, + { + .ident = "Toshiba P10", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite P10"), + }, + }, + { + .ident = "Alienware Sentia", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), + DMI_MATCH(DMI_PRODUCT_NAME, "Sentia"), + }, + }, + { + .ident = "Sharp Actius MM20", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SHARP"), + DMI_MATCH(DMI_PRODUCT_NAME, "PC-MM20 Series"), + }, + }, + { + .ident = "Sony Vaio FS-115b", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FS115B"), + }, + }, { } }; + + + #endif -#if defined(__ia64__) && defined(CONFIG_ACPI) -#include -#include -struct i8042_acpi_resources { - unsigned int port1; - unsigned int port2; - unsigned int irq; -}; +#ifdef CONFIG_PNP +#include -static int i8042_acpi_kbd_registered; -static int i8042_acpi_aux_registered; +static int i8042_pnp_kbd_registered; +static unsigned int i8042_pnp_kbd_devices; +static int i8042_pnp_aux_registered; +static unsigned int i8042_pnp_aux_devices; -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 int i8042_acpi_kbd_add(struct acpi_device *device) +static char i8042_pnp_kbd_name[32]; +static char i8042_pnp_aux_name[32]; + +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)); + } + i8042_pnp_kbd_devices++; 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)); + } + i8042_pnp_aux_devices++; 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 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 int i8042_acpi_init(void) +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 (acpi_disabled || i8042_noacpi) { - printk("i8042: ACPI detection disabled\n"); + if (i8042_pnp_aux_registered) { + i8042_pnp_aux_registered = 0; + pnp_unregister_driver(&i8042_pnp_aux_driver); + } +} + +static int __init i8042_pnp_init(void) +{ + char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 }; + int err; + + 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; + err = pnp_register_driver(&i8042_pnp_kbd_driver); + if (!err) + i8042_pnp_kbd_registered = 1; + + err = pnp_register_driver(&i8042_pnp_aux_driver); + if (!err) + i8042_pnp_aux_registered = 1; - if (result == 0) { - acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); + if (!i8042_pnp_kbd_devices && !i8042_pnp_aux_devices) { + 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 } - 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 (i8042_pnp_kbd_devices) + snprintf(kbd_irq_str, sizeof(kbd_irq_str), + "%d", i8042_pnp_kbd_irq); + if (i8042_pnp_aux_devices) + snprintf(aux_irq_str, sizeof(aux_irq_str), + "%d", i8042_pnp_aux_irq); + + printk(KERN_INFO "PNP: PS/2 Controller [%s%s%s] at %#x,%#x irq %s%s%s\n", + i8042_pnp_kbd_name, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", + i8042_pnp_aux_name, + i8042_pnp_data_reg, i8042_pnp_command_reg, + kbd_irq_str, (i8042_pnp_kbd_devices && i8042_pnp_aux_devices) ? "," : "", + aux_irq_str); + +#if defined(__ia64__) + if (!i8042_pnp_kbd_devices) + i8042_nokbd = 1; + if (!i8042_pnp_aux_devices) i8042_noaux = 1; +#endif - return 0; -} + 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; + } -static void i8042_acpi_exit(void) -{ - if (i8042_acpi_kbd_registered) - acpi_bus_unregister_driver(&i8042_acpi_kbd_driver); + 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_acpi_aux_registered) - acpi_bus_unregister_driver(&i8042_acpi_aux_driver); + if (!i8042_nokbd && !i8042_pnp_kbd_irq) { + printk(KERN_WARNING "PNP: PS/2 controller doesn't have KBD irq; using default %d\n", i8042_kbd_irq); + i8042_pnp_kbd_irq = i8042_kbd_irq; + } + + if (!i8042_noaux && !i8042_pnp_aux_irq) { + printk(KERN_WARNING "PNP: PS/2 controller doesn't have AUX irq; using default %d\n", i8042_aux_irq); + i8042_pnp_aux_irq = i8042_aux_irq; + } + + 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; + + return 0; } + +#else +static inline int i8042_pnp_init(void) { return 0; } +static inline void i8042_pnp_exit(void) { } #endif -static inline int i8042_platform_init(void) +static int __init i8042_platform_init(void) { + int retval; + /* * On ix86 platforms touching the i8042 data register region can do really * bad things. Because of this the region is always reserved on ix86 boxes. * * if (!request_region(I8042_DATA_REG, 16, "i8042")) - * return -1; + * return -EBUSY; */ i8042_kbd_irq = I8042_MAP_IRQ(1); i8042_aux_irq = I8042_MAP_IRQ(12); -#if defined(__ia64__) && defined(CONFIG_ACPI) - if (i8042_acpi_init()) - return -1; -#endif + retval = i8042_pnp_init(); + if (retval) + return retval; #if defined(__ia64__) i8042_reset = 1; #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; + return retval; } static inline void i8042_platform_exit(void) { -#if defined(__ia64__) && defined(CONFIG_ACPI) - i8042_acpi_exit(); -#endif + i8042_pnp_exit(); } #endif /* _I8042_X86IA64IO_H */