Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-1-5]: src/sys/arch/i386/i386 Pull up revision 1.58 (via patch, re...



details:   https://anonhg.NetBSD.org/src/rev/ff79bc456674
branches:  netbsd-1-5
changeset: 490571:ff79bc456674
user:      he <he%NetBSD.org@localhost>
date:      Sat Feb 03 17:42:23 2001 +0000

description:
Pull up revision 1.58 (via patch, requested by chuck):
  Fix problem detected on IBM thinkpads causing it to suspend
  shortly after resume.  This is caused by duplicate events filling
  the event queue, so improve detection of duplicates.  Also cleanup
  and add some APMDEBUG code.

diffstat:

 sys/arch/i386/i386/apm.c |  252 +++++++++++++++++++++++++++++++++-------------
 1 files changed, 181 insertions(+), 71 deletions(-)

diffs (truncated from 381 to 300 lines):

diff -r b83221e070fa -r ff79bc456674 sys/arch/i386/i386/apm.c
--- a/sys/arch/i386/i386/apm.c  Sat Feb 03 17:36:37 2001 +0000
+++ b/sys/arch/i386/i386/apm.c  Sat Feb 03 17:42:23 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: apm.c,v 1.50.2.1 2000/08/04 05:34:29 enami Exp $ */
+/*     $NetBSD: apm.c,v 1.50.2.2 2001/02/03 17:42:23 he Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -98,16 +98,16 @@
 #else
 int    apmdebug = 0;
 #endif
-#else
+
+#else  /* APMDEBUG */
 #define        DPRINTF(f, x)           /**/
-#endif
+#endif /* APMDEBUG */
 
 #define APM_NEVENTS 16
 
 struct apm_softc {
        struct device sc_dev;
        struct selinfo sc_rsel;
-       struct selinfo sc_xsel;
        int     sc_flags;
        int     event_count;
        int     event_ptr;
@@ -143,7 +143,7 @@
 static void    apm_devpowmgt_enable __P((int, u_int));
 static void    apm_disconnect __P((void *));
 #endif
-static void    apm_event_handle __P((struct apm_softc *, struct bioscallregs *));
+static int     apm_event_handle __P((struct apm_softc *, struct bioscallregs *));
 static int     apm_get_event __P((struct bioscallregs *));
 static int     apm_get_powstat __P((struct bioscallregs *));
 #if 0
@@ -217,12 +217,98 @@
 struct apm_connect_info apminfo;
 u_char apm_majver, apm_minver;
 int    apm_inited;
-int    apm_standbys, apm_userstandbys, apm_suspends, apm_battlow;
-int    apm_damn_fool_bios, apm_op_inprog;
 int    apm_evindex;
 
+/* set if we should standby/suspend at the end of next periodic event */
+int apm_standby_now, apm_suspend_now;
+
+/* 
+ * set if kernel is planning on doing a standby/suspend, or if we are
+ * waiting for an external program to process a standby/suspend event.
+ */
+int apm_standby_pending, apm_suspend_pending;
+
 #ifdef APMDEBUG
 int    apmcall_debug(int, struct bioscallregs *, int);
+static void acallpr(int, char *, struct bioscallregs *);
+
+/* bitmask defns for printing apm call args/results */
+#define ACPF_AX                0x00000001
+#define ACPF_AX_HI     0x00000002
+#define ACPF_EAX       0x00000004
+#define ACPF_BX        0x00000008
+#define ACPF_BX_HI     0x00000010
+#define ACPF_EBX       0x00000020
+#define ACPF_CX        0x00000040
+#define ACPF_CX_HI     0x00000080
+#define ACPF_ECX       0x00000100
+#define ACPF_DX        0x00000200
+#define ACPF_DX_HI     0x00000400
+#define ACPF_EDX       0x00000800
+#define ACPF_SI        0x00001000
+#define ACPF_SI_HI     0x00002000
+#define ACPF_ESI       0x00004000
+#define ACPF_DI        0x00008000
+#define ACPF_DI_HI     0x00010000
+#define ACPF_EDI       0x00020000
+#define ACPF_FLAGS     0x00040000
+#define ACPF_FLAGS_HI  0x00080000
+#define ACPF_EFLAGS    0x00100000
+
+struct acallinfo {
+       char *name;
+       int inflag;
+       int outflag;
+};
+
+static struct acallinfo aci[] = {
+  { "install_check", ACPF_BX, ACPF_AX|ACPF_BX|ACPF_CX },
+  { "connectreal", ACPF_BX, 0 },
+  { "connect16", ACPF_BX, ACPF_AX|ACPF_BX|ACPF_CX|ACPF_SI|ACPF_DI },
+  { "connect32", ACPF_BX, ACPF_AX|ACPF_EBX|ACPF_CX|ACPF_DX|ACPF_ESI|ACPF_DI },
+  { "disconnect", ACPF_BX, 0 },
+  { "cpu_idle", 0, 0 },
+  { "cpu_busy", 0, 0 },
+  { "set_power_state", ACPF_BX|ACPF_CX, 0 },
+  { "enable_power_state", ACPF_BX|ACPF_CX, 0 }, 
+  { "restore_defaults", ACPF_BX, 0 },
+  { "get_power_status", ACPF_BX, ACPF_BX|ACPF_CX|ACPF_DX|ACPF_SI },
+  { "get_event", 0, ACPF_BX|ACPF_CX },
+  { "get_power_state" , ACPF_BX, ACPF_CX }, 
+  { "enable_dev_power_mgt", ACPF_BX|ACPF_CX, 0 },
+  { "driver_version", ACPF_BX|ACPF_CX, ACPF_AX },
+  { "engage_power_mgt",  ACPF_BX|ACPF_CX, 0 },
+  { "get_caps", ACPF_BX, ACPF_BX|ACPF_CX },
+  { "resume_timer", ACPF_BX|ACPF_CX|ACPF_SI|ACPF_DI, ACPF_CX|ACPF_SI|ACPF_DI },
+  { "resume_ring", ACPF_BX|ACPF_CX, ACPF_CX },
+  { "timer_reqs", ACPF_BX|ACPF_CX, ACPF_CX },
+};
+
+static void acallpr(int flag, char *tag, struct bioscallregs *b) {
+  if (!flag) return;
+  printf("%s ", tag);
+  if (flag & ACPF_AX)          printf("ax=%#x ", b->AX);
+  if (flag & ACPF_AX_HI)       printf("ax_hi=%#x ", b->AX_HI);
+  if (flag & ACPF_EAX)                 printf("eax=%#x ", b->EAX);
+  if (flag & ACPF_BX )                 printf("bx=%#x ", b->BX);
+  if (flag & ACPF_BX_HI )      printf("bx_hi=%#x ", b->BX_HI);
+  if (flag & ACPF_EBX )        printf("ebx=%#x ", b->EBX);
+  if (flag & ACPF_CX )                 printf("cx=%#x ", b->CX);
+  if (flag & ACPF_CX_HI )      printf("cx_hi=%#x ", b->CX_HI);
+  if (flag & ACPF_ECX )        printf("ecx=%#x ", b->ECX);
+  if (flag & ACPF_DX )                 printf("dx=%#x ", b->DX);
+  if (flag & ACPF_DX_HI )      printf("dx_hi=%#x ", b->DX_HI);
+  if (flag & ACPF_EDX )        printf("edx=%#x ", b->EDX);
+  if (flag & ACPF_SI )                 printf("si=%#x ", b->SI);
+  if (flag & ACPF_SI_HI )      printf("si_hi=%#x ", b->SI_HI);
+  if (flag & ACPF_ESI )        printf("esi=%#x ", b->ESI);
+  if (flag & ACPF_DI )                 printf("di=%#x ", b->DI);
+  if (flag & ACPF_DI_HI )      printf("di_hi=%#x ", b->DI_HI);
+  if (flag & ACPF_EDI )        printf("edi=%#x ", b->EDI);
+  if (flag & ACPF_FLAGS )      printf("flags=%#x ", b->FLAGS);
+  if (flag & ACPF_FLAGS_HI)    printf("flags_hi=%#x ", b->FLAGS_HI);
+  if (flag & ACPF_EFLAGS )     printf("eflags=%#x ", b->EFLAGS);
+}
 
 int
 apmcall_debug(func, regs, line)
@@ -231,16 +317,44 @@
        int line;
 {
        int rv;
-
-       DPRINTF(APMDEBUG_APMCALLS, ("apmcall: func %d from line %d",
-           func, line));
+       int print = (apmdebug & APMDEBUG_APMCALLS) != 0;
+       char *name;
+       int inf, outf;
+               
+       if (print) {
+               if (func >= sizeof(aci) / sizeof(aci[0])) {
+                       name = 0;
+                       inf = outf = 0;
+               } else {
+                       name = aci[func].name;
+                       inf = aci[func].inflag;
+                       outf = aci[func].outflag;
+               }
+               inittodr(time.tv_sec);  /* update timestamp */
+               if (name)
+                       printf("apmcall@%03ld: %s/%#x (line=%d) ", 
+                               time.tv_sec % 1000, name, func, line);
+               else
+                       printf("apmcall@%03ld: %#x (line=%d) ", 
+                               time.tv_sec % 1000, func, line);
+               acallpr(inf, "in:", regs);
+       }
        rv = apmcall(func, regs);
-       DPRINTF(APMDEBUG_APMCALLS, (" -> 0x%x\n", rv));
+       if (print) {
+               if (rv) {
+                       printf(" => error %#x (%s)\n", regs->AX >> 8,
+                               apm_strerror(regs->AX >> 8));
+               } else {
+                       printf(" => ");
+                       acallpr(outf, "out:", regs);
+                       printf("\n");
+               }
+       }
        return (rv);
 }
 
 #define apmcall(f, r)  apmcall_debug((f), (r), __LINE__)
-#endif
+#endif /* APMDEBUG */
 
 
 static const char *
@@ -461,8 +575,10 @@
 
        if ((sc->sc_flags & SCFLAG_OPEN) == 0)
                return 1;               /* no user waiting */
-       if (sc->event_count == APM_NEVENTS)
+       if (sc->event_count == APM_NEVENTS) {
+               DPRINTF(APMDEBUG_ANOM, ("apm_record_event: queue full!\n"));
                return 1;                       /* overflow */
+       }
        evp = &sc->event_list[sc->event_ptr];
        sc->event_count++;
        sc->event_ptr++;
@@ -473,44 +589,34 @@
        return (sc->sc_flags & SCFLAG_OWRITE) ? 0 : 1; /* user may handle */
 }
 
-static void
+/*
+ * apm_event_handle: handle an event.  returns 1 if event handled, 0 if
+ * event is a duplicate of an event we are already handling.
+ */
+static int
 apm_event_handle(sc, regs)
        struct apm_softc *sc;
        struct bioscallregs *regs;
 {
-       int error;
+       int error, retval;
        struct bioscallregs nregs;
        char *code;
 
+       retval = 1;             /* assume we are going to make progress */
+
        switch (regs->BX) {
        case APM_USER_STANDBY_REQ:
-               DPRINTF(APMDEBUG_EVENTS, ("apmev: user standby request\n"));
+       case APM_STANDBY_REQ:
+               DPRINTF(APMDEBUG_EVENTS, ("apmev: %s standby request\n",
+                 (regs->BX == APM_STANDBY_REQ) ? "system" : "user"));
                if (apm_do_standby) {
-                       if (apm_record_event(sc, regs->BX))
-                               apm_userstandbys++;
-                       apm_op_inprog++;
-                       (void)apm_set_powstate(APM_DEV_ALLDEVS,
-                           APM_LASTREQ_INPROG);
-               } else {
-                       (void)apm_set_powstate(APM_DEV_ALLDEVS,
-                           APM_LASTREQ_REJECTED);
-                       /* in case BIOS hates being spurned */
-                       apm_powmgt_enable(1);
-               }
-               break;
-
-       case APM_STANDBY_REQ:
-               DPRINTF(APMDEBUG_EVENTS, ("apmev: system standby request\n"));
-               if (apm_standbys || apm_suspends) {
-                       DPRINTF(APMDEBUG_EVENTS | APMDEBUG_ANOM,
-                           ("damn fool BIOS did not wait for answer\n"));
-                       /* just give up the fight */
-                       apm_damn_fool_bios = 1;
-               }
-               if (apm_do_standby) {
-                       if (apm_record_event(sc, regs->BX))
-                               apm_standbys++;
-                       apm_op_inprog++;
+                       if (apm_standby_pending)
+                               retval = 0;             /* duplicate request */
+                       else {
+                               if (apm_record_event(sc, regs->BX))
+                                       apm_standby_now++; /* kernel handles */
+                               apm_standby_pending++;
+                       }
                        (void)apm_set_powstate(APM_DEV_ALLDEVS,
                            APM_LASTREQ_INPROG);
                } else {
@@ -522,24 +628,16 @@
                break;
 
        case APM_USER_SUSPEND_REQ:
-               DPRINTF(APMDEBUG_EVENTS, ("apmev: user suspend request\n"));
-               if (apm_record_event(sc, regs->BX))
-                       apm_suspends++;
-               apm_op_inprog++;
-               (void)apm_set_powstate(APM_DEV_ALLDEVS, APM_LASTREQ_INPROG);
-               break;
-
        case APM_SUSPEND_REQ:
-               DPRINTF(APMDEBUG_EVENTS, ("apmev: system suspend request\n"));
-               if (apm_standbys || apm_suspends) {
-                       DPRINTF(APMDEBUG_EVENTS | APMDEBUG_ANOM,
-                           ("damn fool BIOS did not wait for answer\n"));
-                       /* just give up the fight */
-                       apm_damn_fool_bios = 1;
+               DPRINTF(APMDEBUG_EVENTS, ("apmev: %s suspend request\n",
+                 (regs->BX == APM_SUSPEND_REQ) ? "system" : "user"));
+               if (apm_suspend_pending)
+                       retval = 0;             /* duplicate request */
+               else {
+                       if (apm_record_event(sc, regs->BX))
+                               apm_suspend_now++;      /* kernel handles */
+                       apm_suspend_pending++;
                }
-               if (apm_record_event(sc, regs->BX))
-                       apm_suspends++;
-               apm_op_inprog++;
                (void)apm_set_powstate(APM_DEV_ALLDEVS, APM_LASTREQ_INPROG);
                break;
 
@@ -583,7 +681,6 @@
 
        case APM_BATTERY_LOW:



Home | Main Index | Thread Index | Old Index