Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 10 Aug 1999 17:30:30 +0900
From:      Mitsuru IWASAKI <iwasaki@jp.FreeBSD.org>
To:        sanpei@sanpei.org
Cc:        mobile@freebsd.org, iwasaki@jp.FreeBSD.org
Subject:   Re: [APM] kernel panic with apm command(Sotec WinBookPro).
Message-ID:  <199908100826.RAA01149@tasogare.imasy.or.jp>
In-Reply-To: Your message of "Tue, 10 Aug 1999 01:02:23 %2B0900" <199908091602.BAA01757@lavender.yy.cs.keio.ac.jp>
References:  <199908091602.BAA01757@lavender.yy.cs.keio.ac.jp>

next in thread | previous in thread | raw e-mail | index | archive | help
Hi,
I made new patch, please try this one.

sanpei>   I applied Iwasaki-san's patch to my sys/i386/apm/apm.c.
sanpei> 
sanpei>   And I execute apm, kernel does not panic. But I think
sanpei> /usr/sbin/apm needs some additional code(?).

Maybe yes.  It should continue here even getting error from BIOS call,
I think.  How about this?

--- apm.c.org	Tue Aug 10 11:08:01 1999
+++ apm.c	Tue Aug 10 12:16:48 1999
@@ -165,7 +165,7 @@
 	args.ebx = PMDV_APMBIOS;
 	args.ecx = 0x0001;
 	if (ioctl(fd, APMIO_BIOS, &args)) {
-		err(1,"Get resume timer");
+		printf("Resume timer: unkown\n");
 	} else {
 		apmerr = APMERR(args.eax);
 		 if (apmerr == 0x0d || apmerr == 0x86)

sanpei> >> apm: found APM BIOS v1.1, connected at v1.0
sanpei> >
sanpei> >Odd. Why it connected at v1.0???
sanpei> 
sanpei>   I added some debug code. 
sanpei>   I think my NOTE-PC has buggy BIOS.  If it call ``APM_DRVVERSION'',
sanpei> BIOS return 0x530e of APM driver version, not 0x010x(1.0?).  0x530e
sanpei> is eax value for APM_DRVVERSION...... BIOS of MY NOTE-PC does not
sanpei> recognize DRVVERSION CALL.........

Ahhh, I heard this problem from you before :)
0x530e is ((APM_BIOS << 8) | APM_DRVVERSION), that mean your BIOS
didn't touch %ax at all. Attached patch includes this fix.

sanpei> @@ -1176,7 +1182,7 @@
sanpei>  		sc->bios.r.edi = args->edi;
sanpei>  		if ((ret = apm_bioscall())) {
sanpei>  			if (ret == -1) {
sanpei> -				error = ENOSYS;
sanpei> +				error = EINVAL;
sanpei>  			} else {
sanpei>  				sc->bios.r.eax &= 0xff;
sanpei>  			}

Ummm, I found another bug in here.  We can discard %ah only in case of 
success, right?

--- apm.c.org	Tue Aug 10 12:35:01 1999
+++ apm.c	Tue Aug 10 16:19:07 1999
@@ -50,6 +50,7 @@
 static int apm_display __P((int newstate));
 static void apm_resume __P((void));
 static int apm_bioscall(void);
+static int apm_check_function_supported __P((u_int version, u_int func));
 
 static u_long	apm_version;
 
@@ -132,6 +133,15 @@
 {
 	struct apm_softc *sc = &apm_softc;
 	int errno = 0;
+	u_int apm_func = sc->bios.r.eax & 0xff;
+
+	if (!apm_check_function_supported(sc->intversion, apm_func)) {
+#ifdef APM_DEBUG
+		printf("apm_bioscall: function 0x%x is not supported in v%d.%d\n",
+			apm_func, sc->majorversion, sc->minorversion);
+#endif
+		return (-1);
+	}
 
 	sc->bios_busy = 1;
 	if (sc->connectmode == APM_PROT32CONNECT) {
@@ -146,6 +156,34 @@
 	return (errno);
 }
 
+/* check whether APM function is supported (1)  or not (0). */
+static int
+apm_check_function_supported(u_int version, u_int func)
+{
+	/* except driver version */
+	if (func == APM_DRVVERSION) {
+		return (1);
+	}
+
+	switch (version) {
+	case INTVERSION(1, 0):
+		if (func > APM_GETPMEVENT) {
+			return (0); /* not supported */
+		}
+		break;
+	case INTVERSION(1, 1):
+		if (func > APM_ENGAGEDISENGAGEPM &&
+		    func < APM_OEMFUNC) {
+			return (0); /* not supported */
+		}
+		break;
+	case INTVERSION(1, 2):
+		break;
+	}
+
+	return (1); /* supported */
+}
+
 /* enable/disable power management */
 static int
 apm_enable_disable_pm(int enable)
@@ -176,6 +214,11 @@
 
 	if (apm_bioscall() == 0 && sc->bios.r.eax == version)
 		return (0);
+
+	/* Some old BIOSes don't return the connection version in %ax. */
+	if (sc->bios.r.eax == ((APM_BIOS << 8) | APM_DRVVERSION))
+		return (0);
+
 	return (1);
 }
  
@@ -1067,6 +1110,7 @@
 	struct apm_softc *sc = &apm_softc;
 	struct apm_bios_arg *args;
 	int error = 0;
+	int ret;
 	int newstate;
 
 	if (!sc->initialized)
@@ -1135,8 +1179,23 @@
 		sc->bios.r.edx = args->edx;
 		sc->bios.r.esi = args->esi;
 		sc->bios.r.edi = args->edi;
-		if (apm_bioscall())
+		if ((ret = apm_bioscall())) {
+			/*
+			 * Return code 1 means bios call was unsuccessful.
+			 * Error code is stored in %ah.
+			 * Return code -1 means bios call was unsupported
+			 * in the APM BIOS version.
+			 */
+			if (ret == -1) {
+				error = EINVAL;
+			}
+		} else {
+			/*
+			 * Return code 0 means bios call was successful.
+			 * We need only %al and can discard %ah.
+			 */
 			sc->bios.r.eax &= 0xff;
+		}
 		args->eax = sc->bios.r.eax;
 		args->ebx = sc->bios.r.ebx;
 		args->ecx = sc->bios.r.ecx;




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199908100826.RAA01149>