(Message week:9487) X-url: http://www.isi.edu/~johnh/ To: Rik Faith Subject: work-around for APM problem on Gateway Solo 9100 Date: Mon, 04 Aug 1997 15:53:43 -0700 From: John Heidemann After some gnashing of teeth and a little hacking I settled on the following work-around for APM on the Gateway Solo 9100. Apparently there's a bug in the BIOS wrt get_power_status that crashes Linux. This patch works around the bug by disabling calls to get_power_status. All other APM functions appear to work. The patch also adds some more debugging support. Rik, please let me know if this patch is OK with you and I'll announce it on linux-laptop. I'll leave it to your judgement about forwarding this to Linus. Thanks for the help, -John Heidemann ---------------------------------------------------------------------- --- apm_bios.c- Tue May 14 23:06:55 1996 +++ apm_bios.c Sat Aug 2 09:13:11 1997 @@ -52,6 +52,8 @@ * ftp://ftp.intel.com/pub/IAL/software_specs/apmv11.doc. It is also * available from Microsoft by calling 206.882.8080.] * + * See also the APM 1.2 spec at . + * */ #include @@ -178,6 +180,15 @@ #define APM_RELAX_SEGMENTS /* + * Define to make apm avoid caling get_power_status. + * This hack is apparently needed on the Gateway Solo 9100 + * (PhoenixBIOS 4.0 Release 5.1 resale version Q3B11 build time + * 5/13/97 20:35:15). + */ +/* #undef APM_AVOID_GET_POWER_STATUS */ +#define APM_AVOID_GET_POWER_STATUS + +/* * Need to poll the APM BIOS every second */ #define APM_CHECK_TIMEOUT (HZ) @@ -397,6 +408,33 @@ char * msg; } lookup_t; +#if 0 +static void apm_debug_message_pause() +{ +} + +static void apm_debug_message(char *s) +{ + int i; + int n = 20000000 /* 60000000*/ ; + printk ("apm_debug_message: %s\n", s ? s : "!"); + if (s == 0) + n *= 20; + for (i = 0; i < n; i++) + apm_debug_message_pause(); +} +#else +#if 1 +static void apm_debug_message(char *s) +{ + printk("apm: %s\n", s); +} +#else +#define apm_debug_message(s) /**/ +#endif +#endif /* 1 */ + + static const lookup_t error_table[] = { /* N/A { APM_SUCCESS, "Operation succeeded" }, */ { APM_DISABLED, "Power management disabled" }, @@ -419,6 +457,7 @@ { u_short error; + apm_debug_message("apm_driver_version"); APM_DRIVER_VERSION(*val, *val, error); if (error & 0xff) @@ -430,6 +469,7 @@ { u_short error; + /* apm_debug_message("apm_get_event"); */ APM_GET_EVENT(*event, error); if (error & 0xff) return (error >> 8); @@ -440,6 +480,7 @@ { u_short error; + apm_debug_message("apm_set_power_state"); APM_SET_POWER_STATE(state, error); if (error & 0xff) return (error >> 8); @@ -452,6 +493,7 @@ { u_short error; + apm_debug_message("apm_set_display_power_state"); APM_SET_DISPLAY_POWER_STATE(state, error); if (error & 0xff) return (error >> 8); @@ -465,6 +507,7 @@ { u_short error; + apm_debug_message("apm_enable_power_management"); APM_ENABLE_POWER_MANAGEMENT((apm_bios_info.version > 0x100) ? 0x0001 : 0xffff, error); @@ -478,6 +521,10 @@ { u_short error; + apm_debug_message("apm_get_power_status"); +#ifdef APM_AVOID_GET_POWER_STATUS + return APM_NO_EVENTS; /* some hacky error message */ +#endif /* APM_AVOID_GET_POWER_STATUS */ APM_GET_POWER_STATUS(*status, *bat, *life, error); if (error & 0xff) return (error >> 8); @@ -488,6 +535,7 @@ { u_short error; + apm_debug_message("apm_engage_power_management"); APM_ENGAGE_POWER_MANAGEMENT(device, error); if (error & 0xff) return (error >> 8); @@ -998,6 +1046,7 @@ return 0; p = buf; + apm_debug_message("apm_get_info"); if (!(error = apm_get_power_status(&bx, &cx, &dx))) { ac_line_status = (bx >> 8) & 0xff; battery_status = bx & 0xff; @@ -1142,7 +1191,7 @@ printk( " Connection version %d.%d\n", (apm_bios_info.version >> 8) & 0xff, apm_bios_info.version & 0xff ); - apm_bios_info.version = 0x0101; +/* johnh apm_bios_info.version = 0x0101; */ } }