2005-04-17 02:20:36 +04:00
# ifndef _I8042_X86IA64IO_H
# define _I8042_X86IA64IO_H
/*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation .
*/
/*
* Names .
*/
# define I8042_KBD_PHYS_DESC "isa0060 / serio0"
# define I8042_AUX_PHYS_DESC "isa0060 / serio1"
# define I8042_MUX_PHYS_DESC "isa0060 / serio%d"
/*
* IRQs .
*/
# if defined(__ia64__)
# define I8042_MAP_IRQ(x) isa_irq_to_vector((x))
# else
# define I8042_MAP_IRQ(x) (x)
# endif
# define I8042_KBD_IRQ i8042_kbd_irq
# define I8042_AUX_IRQ i8042_aux_irq
static int i8042_kbd_irq ;
static int i8042_aux_irq ;
/*
* Register numbers .
*/
# define I8042_COMMAND_REG i8042_command_reg
# define I8042_STATUS_REG i8042_command_reg
# define I8042_DATA_REG i8042_data_reg
static int i8042_command_reg = 0x64 ;
static int i8042_data_reg = 0x60 ;
static inline int i8042_read_data ( void )
{
return inb ( I8042_DATA_REG ) ;
}
static inline int i8042_read_status ( void )
{
return inb ( I8042_STATUS_REG ) ;
}
static inline void i8042_write_data ( int val )
{
outb ( val , I8042_DATA_REG ) ;
}
static inline void i8042_write_command ( int val )
{
outb ( val , I8042_COMMAND_REG ) ;
}
# if defined(__i386__)
# include <linux/dmi.h>
static struct dmi_system_id __initdata i8042_dmi_noloop_table [ ] = {
{
. ident = " Compaq Proliant 8500 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Compaq " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ProLiant " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 8500 " ) ,
} ,
} ,
{
. ident = " Compaq Proliant DL760 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Compaq " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ProLiant " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " DL760 " ) ,
} ,
} ,
2006-01-06 07:00:38 +03:00
{
. ident = " OQO Model 01 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " OQO " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " ZEPTO " ) ,
DMI_MATCH ( DMI_PRODUCT_VERSION , " 00 " ) ,
} ,
} ,
2005-04-17 02:20:36 +04:00
{ }
} ;
/*
2005-05-28 11:12:05 +04:00
* Some Fujitsu notebooks are having trouble with touchpads if
2005-04-17 02:20:36 +04:00
* active multiplexing mode is activated . Luckily they don ' t have
* external PS / 2 ports so we can safely disable it .
2005-05-28 11:12:05 +04:00
* . . . apparently some Toshibas don ' t like MUX mode either and
* die horrible death on reboot .
2005-04-17 02:20:36 +04:00
*/
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 " ) ,
} ,
} ,
2005-05-28 11:12:10 +04:00
{
. ident = " Fujitsu Lifebook S6230 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " FUJITSU " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " LifeBook S6230 " ) ,
} ,
} ,
2005-04-17 02:20:36 +04:00
{
. ident = " Fujitsu T70H " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " FUJITSU " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " FMVLT70H " ) ,
} ,
} ,
2005-07-11 10:06:28 +04:00
{
. ident = " Fujitsu-Siemens Lifebook T3010 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " FUJITSU SIEMENS " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " LIFEBOOK T3010 " ) ,
} ,
} ,
2005-09-04 10:42:10 +04:00
{
. ident = " Fujitsu-Siemens Lifebook E4010 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " FUJITSU SIEMENS " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " LIFEBOOK E4010 " ) ,
} ,
} ,
2005-05-28 11:12:05 +04:00
{
. ident = " Toshiba P10 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " TOSHIBA " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Satellite P10 " ) ,
} ,
} ,
2006-09-14 09:31:06 +04:00
{
. ident = " Toshiba Equium A110 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " TOSHIBA " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " EQUIUM A110 " ) ,
} ,
} ,
2005-07-11 10:06:06 +04:00
{
. ident = " Alienware Sentia " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " ALIENWARE " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " Sentia " ) ,
} ,
} ,
2005-12-21 08:51:51 +03:00
{
. ident = " Sharp Actius MM20 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " SHARP " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " PC-MM20 Series " ) ,
} ,
} ,
2006-01-14 08:24:06 +03:00
{
. ident = " Sony Vaio FS-115b " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Sony Corporation " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " VGN-FS115B " ) ,
} ,
} ,
2006-08-09 07:38:22 +04:00
{
. ident = " Amoi M636/A737 " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " Amoi Electronics CO.,LTD. " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " M636/A737 platform " ) ,
} ,
} ,
2005-04-17 02:20:36 +04:00
{ }
} ;
# endif
# ifdef CONFIG_PNP
# include <linux/pnp.h>
static int i8042_pnp_kbd_registered ;
2006-03-14 08:12:24 +03:00
static unsigned int i8042_pnp_kbd_devices ;
2005-04-17 02:20:36 +04:00
static int i8042_pnp_aux_registered ;
2006-03-14 08:12:24 +03:00
static unsigned int i8042_pnp_aux_devices ;
2005-04-17 02:20:36 +04:00
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_pnp_kbd_probe ( struct pnp_dev * dev , const struct pnp_device_id * did )
{
if ( pnp_port_valid ( dev , 0 ) & & pnp_port_len ( dev , 0 ) = = 1 )
i8042_pnp_data_reg = pnp_port_start ( dev , 0 ) ;
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 ) ;
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 ) ) ;
}
2006-03-14 08:12:24 +03:00
i8042_pnp_kbd_devices + + ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static int i8042_pnp_aux_probe ( struct pnp_dev * dev , const struct pnp_device_id * did )
{
if ( pnp_port_valid ( dev , 0 ) & & pnp_port_len ( dev , 0 ) = = 1 )
i8042_pnp_data_reg = pnp_port_start ( dev , 0 ) ;
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_aux_irq = pnp_irq ( dev , 0 ) ;
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 ) ) ;
}
2006-03-14 08:12:24 +03:00
i8042_pnp_aux_devices + + ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
static struct pnp_device_id pnp_kbd_devids [ ] = {
{ . id = " PNP0303 " , . driver_data = 0 } ,
{ . id = " PNP030b " , . driver_data = 0 } ,
{ . id = " " , } ,
} ;
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 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 )
{
2005-05-28 11:11:38 +04:00
if ( i8042_pnp_kbd_registered ) {
i8042_pnp_kbd_registered = 0 ;
2005-04-17 02:20:36 +04:00
pnp_unregister_driver ( & i8042_pnp_kbd_driver ) ;
2005-05-28 11:11:38 +04:00
}
2005-04-17 02:20:36 +04:00
2005-05-28 11:11:38 +04:00
if ( i8042_pnp_aux_registered ) {
i8042_pnp_aux_registered = 0 ;
2005-04-17 02:20:36 +04:00
pnp_unregister_driver ( & i8042_pnp_aux_driver ) ;
2005-05-28 11:11:38 +04:00
}
2005-04-17 02:20:36 +04:00
}
2005-09-04 10:41:38 +04:00
static int __init i8042_pnp_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-09-04 10:41:51 +04:00
char kbd_irq_str [ 4 ] = { 0 } , aux_irq_str [ 4 ] = { 0 } ;
2006-03-14 08:12:24 +03:00
int err ;
2005-04-17 02:20:36 +04:00
if ( i8042_nopnp ) {
2005-05-28 11:11:16 +04:00
printk ( KERN_INFO " i8042: PNP detection disabled \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2006-03-14 08:12:24 +03:00
err = pnp_register_driver ( & i8042_pnp_kbd_driver ) ;
if ( ! err )
2005-04-17 02:20:36 +04:00
i8042_pnp_kbd_registered = 1 ;
2005-09-04 10:41:51 +04:00
2006-03-14 08:12:24 +03:00
err = pnp_register_driver ( & i8042_pnp_aux_driver ) ;
if ( ! err )
2005-04-17 02:20:36 +04:00
i8042_pnp_aux_registered = 1 ;
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_kbd_devices & & ! i8042_pnp_aux_devices ) {
2005-04-17 02:20:36 +04:00
i8042_pnp_exit ( ) ;
# if defined(__ia64__)
return - ENODEV ;
# else
2005-05-28 11:11:32 +04:00
printk ( KERN_INFO " PNP: No PS/2 controller found. Probing ports directly. \n " ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
# endif
}
2006-03-14 08:12:24 +03:00
if ( i8042_pnp_kbd_devices )
2005-09-04 10:41:51 +04:00
snprintf ( kbd_irq_str , sizeof ( kbd_irq_str ) ,
" %d " , i8042_pnp_kbd_irq ) ;
2006-03-14 08:12:24 +03:00
if ( i8042_pnp_aux_devices )
2005-09-04 10:41:51 +04:00
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 " ,
2006-03-14 08:12:24 +03:00
i8042_pnp_kbd_name , ( i8042_pnp_kbd_devices & & i8042_pnp_aux_devices ) ? " , " : " " ,
2005-09-04 10:41:51 +04:00
i8042_pnp_aux_name ,
i8042_pnp_data_reg , i8042_pnp_command_reg ,
2006-03-14 08:12:24 +03:00
kbd_irq_str , ( i8042_pnp_kbd_devices & & i8042_pnp_aux_devices ) ? " , " : " " ,
2005-09-04 10:41:51 +04:00
aux_irq_str ) ;
# if defined(__ia64__)
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_kbd_devices )
2005-09-04 10:42:00 +04:00
i8042_nokbd = 1 ;
2006-03-14 08:12:24 +03:00
if ( ! i8042_pnp_aux_devices )
2005-09-04 10:41:51 +04:00
i8042_noaux = 1 ;
# endif
2005-04-17 02:20:36 +04:00
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 ;
}
2005-09-04 10:42:00 +04:00
if ( ! i8042_nokbd & & ! i8042_pnp_kbd_irq ) {
2005-09-04 10:41:51 +04:00
printk ( KERN_WARNING " PNP: PS/2 controller doesn't have KBD irq; using default %d \n " , i8042_kbd_irq ) ;
2005-04-17 02:20:36 +04:00
i8042_pnp_kbd_irq = i8042_kbd_irq ;
}
2005-09-04 10:41:51 +04:00
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 ) ;
2005-04-17 02:20:36 +04:00
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 ;
}
2005-09-04 10:41:38 +04:00
# else
static inline int i8042_pnp_init ( void ) { return 0 ; }
static inline void i8042_pnp_exit ( void ) { }
2005-04-17 02:20:36 +04:00
# endif
2005-09-04 10:41:38 +04:00
static int __init i8042_platform_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-09-04 10:41:38 +04:00
int retval ;
2005-04-17 02:20:36 +04:00
/*
* 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 " ) )
2005-09-04 10:41:38 +04:00
* return - EBUSY ;
2005-04-17 02:20:36 +04:00
*/
i8042_kbd_irq = I8042_MAP_IRQ ( 1 ) ;
i8042_aux_irq = I8042_MAP_IRQ ( 12 ) ;
2005-09-04 10:41:38 +04:00
retval = i8042_pnp_init ( ) ;
if ( retval )
return retval ;
2005-04-17 02:20:36 +04:00
# if defined(__ia64__)
i8042_reset = 1 ;
# endif
# if defined(__i386__)
if ( dmi_check_system ( i8042_dmi_noloop_table ) )
i8042_noloop = 1 ;
if ( dmi_check_system ( i8042_dmi_nomux_table ) )
i8042_nomux = 1 ;
# endif
2005-09-04 10:41:38 +04:00
return retval ;
2005-04-17 02:20:36 +04:00
}
static inline void i8042_platform_exit ( void )
{
i8042_pnp_exit ( ) ;
}
# endif /* _I8042_X86IA64IO_H */