diff -ru linux/Documentation/Configure.help linux-DC1RN/Documentation/Configure.help --- linux/Documentation/Configure.help Wed Aug 7 18:48:51 2001 +++ linux-DC1RN/Documentation/Configure.patch Wed Aug 7 19:35:31 2001 @@ -11290,9 +11290,20 @@ Use real mode APM BIOS call to power off CONFIG_APM_REAL_MODE_POWER_OFF - Use real mode APM BIOS calls to switch off the computer. This is - a work-around for a number of buggy BIOSes. Switch this option on if - your computer crashes instead of powering off properly. + Use workaround to be able to switch off the computer by software. + This patch is necessary for the TYAN S1590S mainboard. For + systems that do not have this chipset, this patch will have no + effect except enlarging the kernel by about 150 bytes. This + workaround should also work on other systems which have the same + chipset (south bridge) as these mainboards, but does not have to be + necessary (since other mainboards do not necessarily have the same + problem). + + Say Y if you have this crappy TYAN mainboard, or N if not. + + Tell TYAN what you think of them! + Other versions of this patch can be found on + http://www.qsl.net/dc1rn/software/download/ Watchdog Timer Support CONFIG_WATCHDOG --- linux/arch/i386/kernel/apm.c Tue Jan 4 19:12:11 2000 +++ linux-DC1RN/arch/i386/kernel/apm.c Wed Aug 7 19:28:09 2001 @@ -165,6 +165,8 @@ #include #include #include +#include +#include #include #include @@ -605,20 +607,47 @@ static void apm_power_off(void) { #ifdef CONFIG_APM_REAL_MODE_POWER_OFF - unsigned char po_bios_call[] = { - 0xb8, 0x00, 0x10, /* movw $0x1000,ax */ - 0x8e, 0xd0, /* movw ax,ss */ - 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */ - 0xb8, 0x07, 0x53, /* movw $0x5307,ax */ - 0xbb, 0x01, 0x00, /* movw $0x0001,bx */ - 0xb9, 0x03, 0x00, /* movw $0x0003,cx */ - 0xcd, 0x15 /* int $0x15 */ - }; + { + if ( pcibios_present( ) ) + { + unsigned char Bus; /* Bus on which device is found */ + unsigned char FunctionNr; /* Function number of the device */ + unsigned short Data; /* Data to be read or written */ + if ( pcibios_find_device( 0x1106, 0x3040, 0x0000, &Bus, + &FunctionNr ) != PCIBIOS_SUCCESSFUL ) + { + (void) apm_set_power_state(APM_STATE_OFF); + } + if( pcibios_read_config_word( Bus, FunctionNr, 0x08, &Data ) != + PCIBIOS_SUCCESSFUL ) + { + (void) apm_set_power_state(APM_STATE_OFF); + } + Data&=0x00FF; + if( Data == 0x0000 ) + { + if( pcibios_read_config_word( Bus, FunctionNr, 0x20, &Data ) + != PCIBIOS_SUCCESSFUL ) + { + (void) apm_set_power_state(APM_STATE_OFF); + } + } + else + { + if( pcibios_read_config_word( Bus, FunctionNr, 0x48, &Data ) + != PCIBIOS_SUCCESSFUL ) + { + (void) apm_set_power_state(APM_STATE_OFF); + } + } + Data&=0xFF00; + Data+=0x0004; + outw_p( 0x2000, Data ); + } + (void) apm_set_power_state(APM_STATE_OFF); + } + #endif - - /* - * This may be called on an SMP machine. - */ #ifdef CONFIG_SMP /* Some bioses don't like being called from CPU != 0 */ while (cpu_number_map[smp_processor_id()] != 0) { @@ -628,7 +657,7 @@ } #endif #ifdef CONFIG_APM_REAL_MODE_POWER_OFF - machine_real_restart(po_bios_call, sizeof(po_bios_call)); + apm_power_off(); #else (void) apm_set_power_state(APM_STATE_OFF); #endif