lkml.org 
[lkml]   [1998]   [Sep]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Subject[PATCH] 2.1.120 APM problems
Date
From
Hi all,

I have another patch to 2.1.120 to (hopefully) put the APM
problems to rest ... I have compiled this and it looks OK
(by inspection of disassembled code), but I haven't booted
this on an APM enabled machine.

Please try this - especially those who use gcc 2.8.x as I
only use 2.7.2.3.

I was not sure why I bothered to use __asm__ or __volatile__,
so I removed them.

Cheers,
Stephen
--
Stephen Rothwell Stephen.Rothwell@canb.auug.org.au

diff -ru linux-2.1.120/drivers/char/apm_bios.c linux/drivers/char/apm_bios.c
--- linux-2.1.120/drivers/char/apm_bios.c Sun Sep 6 17:44:28 1998
+++ linux/drivers/char/apm_bios.c Mon Sep 7 02:15:05 1998
@@ -27,6 +27,7 @@
* Feb 1998, Version 1.3
* Feb 1998, Version 1.4
* Aug 1998, Version 1.5
+ * Sep 1998, Version 1.6
*
* History:
* 0.6b: first version in official kernel, Linux 1.3.46
@@ -52,6 +53,11 @@
* 1.5: Fix segment register reloading (in case of bad segments saved
* across BIOS call).
* Stephen ROthwell
+ * 1.6: Alternate solution to register reloading inspired by
+ * Gabriel Paubert <paubert@iram.es>
+ * Cope with complier/assembler differences.
+ * Only try to turn off the first display device.
+ * Stephen Rothwell
*
* APM 1.1 Reference:
*
@@ -211,11 +217,6 @@
#define APM_CHECK_TIMEOUT (HZ)

/*
- * Save a segment register away
- */
-#define savesegment(seg, where) __asm__ __volatile__("movw %%" #seg ", %0\n" : "=m" (where))
-
-/*
* Forward declarations
*/
static void suspend(void);
@@ -263,7 +264,7 @@

static struct timer_list apm_timer;

-static char driver_version[] = "1.5"; /* no spaces */
+static char driver_version[] = "1.6"; /* no spaces */

#ifdef APM_DEBUG
static char * apm_event_name[] = {
@@ -349,107 +350,97 @@
* can be zeroed before the call. Unfortunately, we can't do anything
* about the stack segment/pointer. Also, we tell the compiler that
* everything could change.
+ *
+ * Also, we KNOW that for the non error case of apm_bios_call, there
+ * is no useful data returned in the low order 8 bits of eax.
*/
-
-static inline int apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
- u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
-{
- u16 old_fs;
- u16 old_gs;
- int error;
-
-#ifdef APM_ZERO_SEGS
- savesegment(fs, old_fs);
- savesegment(gs, old_gs);
-#endif
- __asm__ __volatile__(
- "pushfl\n\t"
#ifdef APM_NOINTS
- "cli\n\t"
+# define APM_DO_CLI "cli\n\t"
+#else
+# define APM_DO_CLI
#endif
#ifdef APM_ZERO_SEGS
- "pushl %%ds\n\t"
- "pushl %%es\n\t"
- "movw %9, %%ds\n\t"
- "movw %9, %%es\n\t"
- "movw %9, %%fs\n\t"
- "movw %9, %%gs\n\t"
+# define APM_DO_ZERO_SEGS \
+ "pushl %%gs\n\t" \
+ "pushl %%fs\n\t" \
+ "pushl %%es\n\t" \
+ "pushl %%ds\n\t" \
+ "xorl %%edx, %%edx\n\t" \
+ "movl %%edx, %%ds\n\t" \
+ "movl %%edx, %%es\n\t" \
+ "movl %%edx, %%fs\n\t" \
+ "movl %%edx, %%gs\n\t"
+# define APM_DO_RESTORE_SEGS \
+ "popl %%ds\n\t" \
+ "popl %%es\n" \
+ "1:\t" \
+ "popl %%fs\n" \
+ "2:\t" \
+ "popl %%gs\n\t" \
+ ".section fixup, \"ax\"\n" \
+ "3:\t" \
+ "movl $0, (%%esp)\n\t" \
+ "jmp 1b\n" \
+ "4:\t" \
+ "movl $0, (%%esp)\n\t" \
+ "jmp 2b\n\t" \
+ ".previous\n\t" \
+ ".section __ex_table, \"a\"\n\t" \
+ ".align 4\n\t" \
+ ".long 1b, 3b\n\t" \
+ ".long 2b, 4b\n\t" \
+ ".previous\n\t"
+#else
+# define APM_DO_ZERO_SEGS
+# define APM_DO_RESTORE_SEGS
#endif
+
+static inline u8 apm_bios_call(u32 eax_in, u32 ebx_in, u32 ecx_in,
+ u32 *eax, u32 *ebx, u32 *ecx, u32 *edx, u32 *esi)
+{
+ asm(
+ "pushfl\n\t"
+ APM_DO_CLI
+ APM_DO_ZERO_SEGS
"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
- "movl $0, %%edi\n\t"
- "jnc 1f\n\t"
- "movl $1, %%edi\n"
- "1:\tpopl %%es\n\t"
- "popl %%ds\n\t"
- "popfl\n\t"
+ "setc %%al\n\t"
+ APM_DO_RESTORE_SEGS
+ "popfl"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx),
- "=S" (*esi), "=D" (error)
+ "=S" (*esi)
: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-#ifdef APM_ZERO_SEGS
- , "r" (0)
-#endif
: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory");
-#ifdef APM_ZERO_SEGS
- loadsegment(fs, old_fs);
- loadsegment(gs, old_gs);
-#endif
- return error;
+ return *eax & 0xff;
}

/*
* This version only returns one value (usually an error code)
*/

-static inline int apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in, u32 *eax)
+static inline u8 apm_bios_call_simple(u32 eax_in, u32 ebx_in, u32 ecx_in,
+ u32 *eax)
{
- u16 old_fs;
- u16 old_gs;
- int error;
+ u8 error;

-#ifdef APM_ZERO_SEGS
- savesegment(fs, old_fs);
- savesegment(gs, old_gs);
-#endif
- __asm__ __volatile__(
+ asm(
"pushfl\n\t"
-#ifdef APM_NOINTS
- "cli\n\t"
-#endif
-#ifdef APM_ZERO_SEGS
- "pushl %%ds\n\t"
- "pushl %%es\n\t"
- "movw %5, %%ds\n\t"
- "movw %5, %%es\n\t"
- "movw %5, %%fs\n\t"
- "movw %5, %%gs\n\t"
-#endif
+ APM_DO_CLI
+ APM_DO_ZERO_SEGS
"lcall %%cs:" SYMBOL_NAME_STR(apm_bios_entry) "\n\t"
- "movl $0, %%edi\n\t"
- "jnc 1f\n\t"
- "movl $1, %%edi\n"
- "1:\tpopl %%es\n\t"
- "popl %%ds\n\t"
- "popfl\n\t"
- : "=a" (*eax), "=D" (error)
+ "setc %%bl\n\t"
+ APM_DO_RESTORE_SEGS
+ "popfl"
+ : "=a" (*eax), "=b" (error)
: "a" (eax_in), "b" (ebx_in), "c" (ecx_in)
-#ifdef APM_ZERO_SEGS
- , "r" (0)
-#endif
: "ax", "bx", "cx", "dx", "si", "di", "bp", "memory");
-#ifdef APM_ZERO_SEGS
- loadsegment(fs, old_fs);
- loadsegment(gs, old_gs);
-#endif
return error;
}

static int apm_driver_version(u_short *val)
{
- int error;
u32 eax;

- error = apm_bios_call_simple(0x530e, 0, *val, &eax);
- if (error)
+ if (apm_bios_call_simple(0x530e, 0, *val, &eax))
return (eax >> 8) & 0xff;
*val = eax;
return APM_SUCCESS;
@@ -457,14 +448,12 @@

static int apm_get_event(apm_event_t *event, apm_eventinfo_t *info)
{
- int error;
u32 eax;
u32 ebx;
u32 ecx;
u32 dummy;

- error = apm_bios_call(0x530b, 0, 0, &eax, &ebx, &ecx, &dummy, &dummy);
- if (error)
+ if (apm_bios_call(0x530b, 0, 0, &eax, &ebx, &ecx, &dummy, &dummy))
return (eax >> 8) & 0xff;
*event = ebx;
if (apm_bios_info.version < 0x0102)
@@ -474,13 +463,11 @@
return APM_SUCCESS;
}

-static int set_power_state(u_short what, u_short state)
+static inline int set_power_state(u_short what, u_short state)
{
- int error;
u32 eax;

- error = apm_bios_call_simple(0x5307, what, state, &eax);
- if (error)
+ if (apm_bios_call_simple(0x5307, what, state, &eax))
return (eax >> 8) & 0xff;
return APM_SUCCESS;
}
@@ -494,7 +481,7 @@
/* Called by apm_display_blank and apm_display_unblank when apm_enabled. */
static int apm_set_display_power_state(u_short state)
{
- return set_power_state(0x01ff, state);
+ return set_power_state(0x0100, state);
}
#endif

@@ -502,12 +489,11 @@
/* Called by apm_setup if apm_enabled will be true. */
static int apm_enable_power_management(void)
{
- int error;
u32 eax;

- error = apm_bios_call_simple(0x5308,
- (apm_bios_info.version > 0x100) ? 0x0001 : 0xffff, 1, &eax);
- if (error)
+ if (apm_bios_call_simple(0x5308,
+ (apm_bios_info.version > 0x100) ? 0x0001 : 0xffff,
+ 1, &eax))
return (eax >> 8) & 0xff;
return APM_SUCCESS;
}
@@ -515,15 +501,13 @@

static int apm_get_power_status(u_short *status, u_short *bat, u_short *life)
{
- int error;
u32 eax;
u32 ebx;
u32 ecx;
u32 edx;
u32 dummy;

- error = apm_bios_call(0x530a, 1, 0, &eax, &ebx, &ecx, &edx, &dummy);
- if (error)
+ if (apm_bios_call(0x530a, 1, 0, &eax, &ebx, &ecx, &edx, &dummy))
return (eax >> 8) & 0xff;
*status = ebx;
*bat = ecx;
@@ -537,7 +521,6 @@
u_short *bat, u_short *life, u_short *nbat)
{
u_short status;
- int error;
u32 eax;
u32 ebx;
u32 ecx;
@@ -552,8 +535,8 @@
return apm_get_power_status(&status, bat, life);
}

- error = apm_bios_call(0x530a, (0x8000 | (which)), 0, &eax, &ebx, &ecx, &edx, &esi);
- if (error)
+ if (apm_bios_call(0x530a, (0x8000 | (which)), 0, &eax,
+ &ebx, &ecx, &edx, &esi))
return (eax >> 8) & 0xff;
*bat = ecx;
*life = edx;
@@ -564,11 +547,9 @@

static int apm_engage_power_management(u_short device)
{
- int error;
u32 eax;

- error = apm_bios_call_simple(0x530f, device, 1, &eax);
- if (error)
+ if (apm_bios_call_simple(0x530f, device, 1, &eax))
return (eax >> 8) & 0xff;
return APM_SUCCESS;
}
@@ -876,14 +857,12 @@
int apm_do_idle(void)
{
#ifdef CONFIG_APM_CPU_IDLE
- int error;
u32 dummy;

if (!apm_enabled)
return 0;

- error = apm_bios_call_simple(0x5305, 0, 0, &dummy);
- if (error)
+ if (apm_bios_call_simple(0x5305, 0, 0, &dummy))
return 0;

clock_slowed = (apm_bios_info.flags & APM_IDLE_SLOWS_CLOCK) != 0;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/faq.html

\
 
 \ /
  Last update: 2005-03-22 13:44    [W:0.031 / U:0.612 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site