summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1994-10-01 02:56:21 +0000
committerdg <dg@FreeBSD.org>1994-10-01 02:56:21 +0000
commitb329c8342570e9501a8be46799c51d49939ba5b7 (patch)
treecae0fc2309e6ae1169ee8bdcf42212d2f39fb3ea /sys
parent071d84b9b9d00df243a9bce6702804627afc1037 (diff)
downloadFreeBSD-src-b329c8342570e9501a8be46799c51d49939ba5b7.zip
FreeBSD-src-b329c8342570e9501a8be46799c51d49939ba5b7.tar.gz
Laptop Advanced Power Management support by HOSOKAWA Tatsumi.
Submitted by: HOSOKAWA Tatsumi
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/include/console.h3
-rw-r--r--sys/amd64/amd64/cpu_switch.S7
-rw-r--r--sys/amd64/amd64/locore.S100
-rw-r--r--sys/amd64/amd64/locore.s100
-rw-r--r--sys/amd64/amd64/machdep.c74
-rw-r--r--sys/amd64/amd64/swtch.s7
-rw-r--r--sys/amd64/amd64/trap.c10
-rw-r--r--sys/amd64/include/segments.h8
-rw-r--r--sys/amd64/isa/icu.h9
-rw-r--r--sys/amd64/isa/isa.c137
-rw-r--r--sys/amd64/isa/isa.h8
-rw-r--r--sys/conf/Makefile.i3864
-rw-r--r--sys/conf/Makefile.powerpc4
-rw-r--r--sys/conf/files.i3864
-rw-r--r--sys/dev/kbd/kbdtables.h4
-rw-r--r--sys/dev/syscons/syscons.c28
-rw-r--r--sys/i386/apm/apm.c823
-rw-r--r--sys/i386/apm/apm_init/Makefile50
-rw-r--r--sys/i386/apm/apm_init/apm_init.S207
-rw-r--r--sys/i386/apm/apm_init/apm_init.inc59
-rw-r--r--sys/i386/apm/apm_init/bin2asm.c64
-rw-r--r--sys/i386/apm/apm_init/real_prot.S185
-rw-r--r--sys/i386/apm/apm_init/real_prot.h56
-rw-r--r--sys/i386/apm/apm_init/rmaouthdr6
-rw-r--r--sys/i386/apm/apm_init/table.c24
-rw-r--r--sys/i386/apm/apm_setup.h23
-rw-r--r--sys/i386/apm/apm_setup.s126
-rw-r--r--sys/i386/bios/apm.c823
-rw-r--r--sys/i386/bios/apm_init/Makefile50
-rw-r--r--sys/i386/bios/apm_init/apm_init.S207
-rw-r--r--sys/i386/bios/apm_init/apm_init.inc59
-rw-r--r--sys/i386/bios/apm_init/bin2asm.c64
-rw-r--r--sys/i386/bios/apm_init/real_prot.S185
-rw-r--r--sys/i386/bios/apm_init/real_prot.h56
-rw-r--r--sys/i386/bios/apm_init/rmaouthdr6
-rw-r--r--sys/i386/bios/apm_init/table.c24
-rw-r--r--sys/i386/bios/apm_setup.h23
-rw-r--r--sys/i386/bios/apm_setup.s126
-rw-r--r--sys/i386/conf/Makefile.i3864
-rw-r--r--sys/i386/conf/files.i3864
-rw-r--r--sys/i386/i386/conf.c20
-rw-r--r--sys/i386/i386/locore.s100
-rw-r--r--sys/i386/i386/machdep.c74
-rw-r--r--sys/i386/i386/swtch.s7
-rw-r--r--sys/i386/i386/trap.c10
-rw-r--r--sys/i386/include/console.h3
-rw-r--r--sys/i386/include/segments.h8
-rw-r--r--sys/i386/isa/icu.h9
-rw-r--r--sys/i386/isa/if_ze.c101
-rw-r--r--sys/i386/isa/isa.c137
-rw-r--r--sys/i386/isa/isa.h8
-rw-r--r--sys/i386/isa/isa_device.h3
-rw-r--r--sys/i386/isa/kbdtables.h4
-rw-r--r--sys/i386/isa/syscons.c28
-rw-r--r--sys/i386/isa/wd.c25
-rw-r--r--sys/isa/kbdtables.h4
-rw-r--r--sys/isa/syscons.c28
-rw-r--r--sys/kern/subr_trap.c10
58 files changed, 4180 insertions, 160 deletions
diff --git a/sys/alpha/include/console.h b/sys/alpha/include/console.h
index 209baa4..ad441e1 100644
--- a/sys/alpha/include/console.h
+++ b/sys/alpha/include/console.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: console.h,v 1.10 1994/09/15 07:26:04 sos Exp $
+ * $Id: console.h,v 1.11 1994/09/29 08:31:39 sos Exp $
*/
#ifndef _CONSOLE_H_
@@ -218,6 +218,7 @@ typedef struct ssaver ssaver_t;
#define META 0x7f /* meta key */
#define RBT 0x80 /* boot machine */
#define DBG 0x81 /* call debugger */
+#define SUSP 0x82 /* suspend power (APM BIOS) */
#define F(x) ((x)+F_FN-1)
#define S(x) ((x)+F_SCR-1)
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S
index 7031c64..ad83a9a 100644
--- a/sys/amd64/amd64/cpu_switch.S
+++ b/sys/amd64/amd64/cpu_switch.S
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.12 1994/09/01 05:12:18 davidg Exp $
+ * $Id: swtch.s,v 1.13 1994/09/02 05:58:51 davidg Exp $
*/
#include "npx.h" /* for NNPX */
@@ -204,8 +204,13 @@ idle_loop:
jne sw1a
cmpl $0,_whichqs
jne nortqr
+#ifdef APM
+ call _apm_cpu_idle
+ call _apm_cpu_busy
+#else
sti
hlt /* wait for interrupt */
+#endif
jmp idle_loop
badsw:
diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S
index 72973aa..bc7b854 100644
--- a/sys/amd64/amd64/locore.S
+++ b/sys/amd64/amd64/locore.S
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.28 1994/09/15 07:26:31 sos Exp $
+ * $Id: locore.s,v 1.29 1994/09/26 16:56:22 pst Exp $
*/
/*
@@ -54,6 +54,11 @@
#include <machine/cputypes.h> /* x86 cpu type definitions */
#include <sys/syscall.h> /* system call numbers */
#include <machine/asmacros.h> /* miscellaneous asm macros */
+#ifdef APM
+#define ASM
+#include <machine/apm_bios.h>
+#include <machine/apm_segments.h>
+#endif
/*
* XXX
@@ -130,7 +135,15 @@ _proc0paddr: .long 0 /* address of proc 0 address space */
.globl _bdb_exists /* flag to indicate BDE debugger is available */
_bdb_exists: .long 0
#endif
-
+#ifdef APM
+ .globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */
+_apm_current_gdt_pdesc:
+ .byte 0, 0, 0
+
+ .globl _bootstrap_gdt
+_bootstrap_gdt:
+ .space SIZEOF_GDT * BOOTSTRAP_GDT_NUM
+#endif /* APM */
.globl tmpstk
.space 0x1000
tmpstk:
@@ -195,6 +208,89 @@ NON_GPROF_ENTRY(btext)
rep
movsb
#endif
+#ifdef APM
+ /*
+ * Setup APM BIOS:
+ *
+ * APM BIOS initialization should be done from real mode or V86 mode.
+ *
+ * (by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>)
+ */
+
+ /*
+ * Copy APM initializer under 1MB boundary:
+ *
+ * APM initializer program must switch the CPU to real mode.
+ * But FreeBSD kernel runs above 1MB boundary. So we must
+ * copy the initializer code to conventional memory.
+ */
+ movl _apm_init_image_size-KERNBASE, %ecx /* size */
+ lea _apm_init_image-KERNBASE, %esi /* source */
+ movl $ APM_OURADDR, %edi /* destination */
+ cld
+ rep
+ movsb
+
+ /* get GDT base */
+ sgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* copy GDT to _bootstrap_gdt */
+ xorl %ecx, %ecx
+ movw _apm_current_gdt_pdesc-KERNBASE, %cx
+ movl _apm_current_gdt_pdesc-KERNBASE+2, %esi
+ lea _bootstrap_gdt-KERNBASE, %edi
+ cld
+ rep
+ movsb
+
+ /* setup GDT pseudo descriptor */
+ movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax
+ movw %ax, _apm_current_gdt_pdesc-KERNBASE
+ leal _bootstrap_gdt-KERNBASE, %eax
+ movl %eax, _apm_current_gdt_pdesc-KERNBASE+2
+
+ /* load new GDTR */
+ lgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* setup GDT for APM initializer */
+ lea _bootstrap_gdt-KERNBASE, %ecx
+ movl $(APM_OURADDR), %eax /* use %ax for 15..0 */
+ movl %eax, %ebx
+ shrl $16, %ebx /* use %bl for 23..16 */
+ /* use %bh for 31..24 */
+#define APM_SETUP_GDT(index, attrib) \
+ movl $(index), %si ; \
+ lea 0(%ecx,%esi,8), %edx ; \
+ movw $0xffff, (%edx) ; \
+ movw %ax, 2(%edx) ; \
+ movb %bl, 4(%edx) ; \
+ movw $(attrib), 5(%edx) ; \
+ movb %bh, 7(%edx)
+
+ APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB)
+
+ /*
+ * Call the initializer:
+ *
+ * direct intersegment call to conventional memory code
+ */
+ .byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */
+ .long 0
+ .word APM_INIT_CS_SEL
+
+ movw %ax, _apm_version-KERNBASE
+ movl %ebx, _apm_cs_entry-KERNBASE
+ movw %cx, _apm_cs32_base-KERNBASE
+ shrl $16, %ecx
+ movw %cx, _apm_cs16_base-KERNBASE
+ movw %dx, _apm_ds_base-KERNBASE
+ movw %si, _apm_cs_limit-KERNBASE
+ shrl $16, %esi
+ movw %si, _apm_ds_limit-KERNBASE
+ movw %di, _apm_flags-KERNBASE
+#endif /* APM */
/* Find out our CPU type. */
diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s
index 72973aa..bc7b854 100644
--- a/sys/amd64/amd64/locore.s
+++ b/sys/amd64/amd64/locore.s
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.28 1994/09/15 07:26:31 sos Exp $
+ * $Id: locore.s,v 1.29 1994/09/26 16:56:22 pst Exp $
*/
/*
@@ -54,6 +54,11 @@
#include <machine/cputypes.h> /* x86 cpu type definitions */
#include <sys/syscall.h> /* system call numbers */
#include <machine/asmacros.h> /* miscellaneous asm macros */
+#ifdef APM
+#define ASM
+#include <machine/apm_bios.h>
+#include <machine/apm_segments.h>
+#endif
/*
* XXX
@@ -130,7 +135,15 @@ _proc0paddr: .long 0 /* address of proc 0 address space */
.globl _bdb_exists /* flag to indicate BDE debugger is available */
_bdb_exists: .long 0
#endif
-
+#ifdef APM
+ .globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */
+_apm_current_gdt_pdesc:
+ .byte 0, 0, 0
+
+ .globl _bootstrap_gdt
+_bootstrap_gdt:
+ .space SIZEOF_GDT * BOOTSTRAP_GDT_NUM
+#endif /* APM */
.globl tmpstk
.space 0x1000
tmpstk:
@@ -195,6 +208,89 @@ NON_GPROF_ENTRY(btext)
rep
movsb
#endif
+#ifdef APM
+ /*
+ * Setup APM BIOS:
+ *
+ * APM BIOS initialization should be done from real mode or V86 mode.
+ *
+ * (by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>)
+ */
+
+ /*
+ * Copy APM initializer under 1MB boundary:
+ *
+ * APM initializer program must switch the CPU to real mode.
+ * But FreeBSD kernel runs above 1MB boundary. So we must
+ * copy the initializer code to conventional memory.
+ */
+ movl _apm_init_image_size-KERNBASE, %ecx /* size */
+ lea _apm_init_image-KERNBASE, %esi /* source */
+ movl $ APM_OURADDR, %edi /* destination */
+ cld
+ rep
+ movsb
+
+ /* get GDT base */
+ sgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* copy GDT to _bootstrap_gdt */
+ xorl %ecx, %ecx
+ movw _apm_current_gdt_pdesc-KERNBASE, %cx
+ movl _apm_current_gdt_pdesc-KERNBASE+2, %esi
+ lea _bootstrap_gdt-KERNBASE, %edi
+ cld
+ rep
+ movsb
+
+ /* setup GDT pseudo descriptor */
+ movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax
+ movw %ax, _apm_current_gdt_pdesc-KERNBASE
+ leal _bootstrap_gdt-KERNBASE, %eax
+ movl %eax, _apm_current_gdt_pdesc-KERNBASE+2
+
+ /* load new GDTR */
+ lgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* setup GDT for APM initializer */
+ lea _bootstrap_gdt-KERNBASE, %ecx
+ movl $(APM_OURADDR), %eax /* use %ax for 15..0 */
+ movl %eax, %ebx
+ shrl $16, %ebx /* use %bl for 23..16 */
+ /* use %bh for 31..24 */
+#define APM_SETUP_GDT(index, attrib) \
+ movl $(index), %si ; \
+ lea 0(%ecx,%esi,8), %edx ; \
+ movw $0xffff, (%edx) ; \
+ movw %ax, 2(%edx) ; \
+ movb %bl, 4(%edx) ; \
+ movw $(attrib), 5(%edx) ; \
+ movb %bh, 7(%edx)
+
+ APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB)
+
+ /*
+ * Call the initializer:
+ *
+ * direct intersegment call to conventional memory code
+ */
+ .byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */
+ .long 0
+ .word APM_INIT_CS_SEL
+
+ movw %ax, _apm_version-KERNBASE
+ movl %ebx, _apm_cs_entry-KERNBASE
+ movw %cx, _apm_cs32_base-KERNBASE
+ shrl $16, %ecx
+ movw %cx, _apm_cs16_base-KERNBASE
+ movw %dx, _apm_ds_base-KERNBASE
+ movw %si, _apm_cs_limit-KERNBASE
+ shrl $16, %esi
+ movw %si, _apm_ds_limit-KERNBASE
+ movw %di, _apm_flags-KERNBASE
+#endif /* APM */
/* Find out our CPU type. */
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index 46df0ca..3242846 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.65 1994/09/16 05:46:54 phk Exp $
+ * $Id: machdep.c,v 1.66 1994/09/24 12:22:47 davidg Exp $
*/
#include "npx.h"
@@ -1012,7 +1012,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* User LDT Descriptor per process */
-{ (int) ldt, /* segment base address */
+{ (int) ldt, /* segment base address */
(512 * sizeof(union descriptor)-1), /* length */
SDT_SYSLDT, /* segment type */
0, /* segment descriptor priority level */
@@ -1020,6 +1020,60 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
+#ifdef APM
+ /* APM BIOS 32-bit interface (32bit Code) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMERA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+ /* APM BIOS 32-bit interface (16bit Code) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMERA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 0, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+ /* APM BIOS 32-bit interface (Data) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMRWA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+#else /* APM */
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+#endif /* APMBIOS */
};
struct soft_segment_descriptor ldt_segs[] = {
@@ -1103,6 +1157,22 @@ extern idtvec_t
int _gsel_tss;
+/* added sdtossd() by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp> */
+int
+sdtossd(sd, ssd)
+ struct segment_descriptor *sd;
+ struct soft_segment_descriptor *ssd;
+{
+ ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
+ ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
+ ssd->ssd_type = sd->sd_type;
+ ssd->ssd_dpl = sd->sd_dpl;
+ ssd->ssd_p = sd->sd_p;
+ ssd->ssd_def32 = sd->sd_def32;
+ ssd->ssd_gran = sd->sd_gran;
+ return 0;
+}
+
void
init386(first)
int first;
diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s
index 7031c64..ad83a9a 100644
--- a/sys/amd64/amd64/swtch.s
+++ b/sys/amd64/amd64/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.12 1994/09/01 05:12:18 davidg Exp $
+ * $Id: swtch.s,v 1.13 1994/09/02 05:58:51 davidg Exp $
*/
#include "npx.h" /* for NNPX */
@@ -204,8 +204,13 @@ idle_loop:
jne sw1a
cmpl $0,_whichqs
jne nortqr
+#ifdef APM
+ call _apm_cpu_idle
+ call _apm_cpu_busy
+#else
sti
hlt /* wait for interrupt */
+#endif
jmp idle_loop
badsw:
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 49b4ffd..fcaa6e9 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.33 1994/09/08 11:48:52 bde Exp $
+ * $Id: trap.c,v 1.34 1994/09/11 11:26:18 davidg Exp $
*/
/*
@@ -459,10 +459,12 @@ trap_fatal(frame)
struct trapframe *frame;
{
int code, type, eva;
+ struct soft_segment_descriptor softseg;
code = frame->tf_err;
type = frame->tf_trapno;
eva = rcr2();
+ sdtossd(gdt + IDXSEL(frame->tf_cs & 0xffff), &softseg);
if (type <= MAX_TRAP_MSG)
printf("\n\nFatal trap %d: %s while in %s mode\n",
@@ -475,7 +477,11 @@ trap_fatal(frame)
code & PGEX_W ? "write" : "read",
code & PGEX_P ? "protection violation" : "page not present");
}
- printf("instruction pointer = 0x%x\n", frame->tf_eip);
+ printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip);
+ printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n",
+ softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
+ printf(" = DPL %d, pres %d, def32 %d, gran %d\n",
+ softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran);
printf("processor eflags = ");
if (frame->tf_eflags & PSL_T)
printf("trace/trap, ");
diff --git a/sys/amd64/include/segments.h b/sys/amd64/include/segments.h
index 023a0cf..0e996e6 100644
--- a/sys/amd64/include/segments.h
+++ b/sys/amd64/include/segments.h
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)segments.h 7.1 (Berkeley) 5/9/91
- * $Id: segments.h,v 1.3 1993/11/07 17:43:08 wollman Exp $
+ * $Id: segments.h,v 1.4 1994/01/31 10:27:13 davidg Exp $
*/
#ifndef _MACHINE_SEGMENTS_H_
@@ -211,7 +211,11 @@ struct region_descriptor {
#define GPANIC_SEL 5 /* Task state to consider panic from */
#define GPROC0_SEL 6 /* Task state process slot zero and up */
#define GUSERLDT_SEL 7 /* User LDT */
-#define NGDT GUSERLDT_SEL+1
+#define GAPMCODE32_SEL 8 /* APM BIOS 32-bit interface (32bit Code) */
+#define GAPMCODE16_SEL 9 /* APM BIOS 32-bit interface (16bit Code) */
+#define GAPMDATA_SEL 10 /* APM BIOS 32-bit interface (Data) */
+
+#define NGDT (GAPMDATA_SEL+1)
/*
* Entries in the Local Descriptor Table (LDT)
diff --git a/sys/amd64/isa/icu.h b/sys/amd64/isa/icu.h
index 5cecf65..a68269b 100644
--- a/sys/amd64/isa/icu.h
+++ b/sys/amd64/isa/icu.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)icu.h 5.6 (Berkeley) 5/9/91
- * $Id: icu.h,v 1.5 1994/09/18 23:08:56 bde Exp $
+ * $Id: icu.h,v 1.6 1994/09/18 23:18:32 bde Exp $
*/
/*
@@ -52,9 +52,10 @@
*/
extern unsigned imen; /* interrupt mask enable */
-#define INTREN(s) (imen &= ~(s), SET_ICUS())
-#define INTRDIS(s) (imen |= (s), SET_ICUS())
-#define INTRMASK(msk,s) (msk |= (s))
+#define INTREN(s) (imen &= ~(s), SET_ICUS())
+#define INTRDIS(s) (imen |= (s), SET_ICUS())
+#define INTRMASK(msk,s) (msk |= (s))
+#define INTRUNMASK(msk,s) (msk &= ~(s))
#if 0
#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IU_ICU2 + 1, imen >> 8))
#else
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c
index 2cd9d23..2f93fcc 100644
--- a/sys/amd64/isa/isa.c
+++ b/sys/amd64/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.25 1994/09/20 05:07:11 bde Exp $
+ * $Id: isa.c,v 1.26 1994/09/30 05:35:55 swallace Exp $
*/
/*
@@ -317,13 +317,35 @@ isa_configure() {
/*
* Configure an ISA device.
*/
+
+
+static void config_isadev_c();
+
static void
config_isadev(isdp, mp)
+ struct isa_device *isdp;
+ u_int *mp;
+{
+ config_isadev_c(isdp, mp, 0);
+}
+
+void
+reconfig_isadev(isdp, mp)
+ struct isa_device *isdp;
+ u_int *mp;
+{
+ config_isadev_c(isdp, mp, 1);
+}
+
+static void
+config_isadev_c(isdp, mp, reconfig)
struct isa_device *isdp;
u_int *mp;
+ int reconfig;
{
u_int checkbits;
int id_alive;
+ int last_alive;
struct isa_driver *dp = isdp->id_driver;
checkbits = 0;
@@ -339,12 +361,18 @@ config_isadev(isdp, mp)
#ifndef ALLOW_CONFLICT_MEMADDR
checkbits |= CC_MEMADDR;
#endif
- if (haveseen_isadev(isdp, checkbits))
+ if (!reconfig && haveseen_isadev(isdp, checkbits))
return;
- if (isdp->id_maddr) {
+ if (!reconfig && isdp->id_maddr) {
isdp->id_maddr -= 0xa0000; /* XXX should be a define */
isdp->id_maddr += atdevbase;
}
+ if (reconfig) {
+ last_alive = isdp->id_alive;
+ }
+ else {
+ last_alive = 0;
+ }
id_alive = (*dp->probe)(isdp);
if (id_alive) {
/*
@@ -354,50 +382,52 @@ config_isadev(isdp, mp)
* 16 it will not report I/O addresses.
* Rod Grimes 04/26/94
*/
- printf("%s%d", dp->name, isdp->id_unit);
- if (id_alive != -1) {
- printf(" at 0x%x", isdp->id_iobase);
- if ((isdp->id_iobase + id_alive - 1) !=
- isdp->id_iobase) {
- printf("-0x%x",
- isdp->id_iobase + id_alive - 1);
+ if (!isdp->id_reconfig) {
+ printf("%s%d", dp->name, isdp->id_unit);
+ if (id_alive != -1) {
+ printf(" at 0x%x", isdp->id_iobase);
+ if ((isdp->id_iobase + id_alive - 1) !=
+ isdp->id_iobase) {
+ printf("-0x%x",
+ isdp->id_iobase + id_alive - 1);
+ }
}
- }
- if (isdp->id_irq)
- printf(" irq %d", ffs(isdp->id_irq) - 1);
- if (isdp->id_drq != -1)
- printf(" drq %d", isdp->id_drq);
- if (isdp->id_maddr)
- printf(" maddr 0x%lx", kvtop(isdp->id_maddr));
- if (isdp->id_msize)
- printf(" msize %d", isdp->id_msize);
- if (isdp->id_flags)
- printf(" flags 0x%x", isdp->id_flags);
- if (isdp->id_iobase) {
- if (isdp->id_iobase < 0x100) {
- printf(" on motherboard\n");
- } else {
- if (isdp->id_iobase >= 0x1000) {
- printf (" on eisa\n");
+ if (isdp->id_irq)
+ printf(" irq %d", ffs(isdp->id_irq) - 1);
+ if (isdp->id_drq != -1)
+ printf(" drq %d", isdp->id_drq);
+ if (isdp->id_maddr)
+ printf(" maddr 0x%lx", kvtop(isdp->id_maddr));
+ if (isdp->id_msize)
+ printf(" msize %d", isdp->id_msize);
+ if (isdp->id_flags)
+ printf(" flags 0x%x", isdp->id_flags);
+ if (isdp->id_iobase) {
+ if (isdp->id_iobase < 0x100) {
+ printf(" on motherboard\n");
} else {
- printf (" on isa\n");
+ if (isdp->id_iobase >= 0x1000) {
+ printf (" on eisa\n");
+ } else {
+ printf (" on isa\n");
+ }
}
}
- }
- /*
- * Check for conflicts again. The driver may have changed
- * *dvp. We should weaken the early check since the
- * driver may have been able to change *dvp to avoid
- * conflicts if given a chance. We already skip the early
- * check for IRQs and force a check for IRQs in the next
- * group of checks.
- */
+ /*
+ * Check for conflicts again. The driver may have
+ * changed *dvp. We should weaken the early check
+ * since the driver may have been able to change
+ * *dvp to avoid conflicts if given a chance. We
+ * already skip the early check for IRQs and force
+ * a check for IRQs in the next group of checks.
+ */
#ifndef ALLOW_CONFLICT_IRQ
- checkbits |= CC_IRQ;
+ checkbits |= CC_IRQ;
#endif
- if (haveseen_isadev(isdp, checkbits))
- return;
- isdp->id_alive = id_alive;
+ if (haveseen_isadev(isdp, checkbits))
+ return;
+ isdp->id_alive = id_alive;
+ }
(*dp->attach)(isdp);
if (isdp->id_irq) {
if (mp)
@@ -408,11 +438,28 @@ config_isadev(isdp, mp)
INTREN(isdp->id_irq);
}
} else {
- printf("%s%d not found", dp->name, isdp->id_unit);
- if (isdp->id_iobase) {
- printf(" at 0x%x", isdp->id_iobase);
+ if (isdp->id_reconfig) {
+ (*dp->attach)(isdp); /* reconfiguration attach */
+ }
+ if (!last_alive) {
+ if (!isdp->id_reconfig) {
+ printf("%s%d not found", dp->name, isdp->id_unit);
+ if (isdp->id_iobase) {
+ printf(" at 0x%x", isdp->id_iobase);
+ }
+ printf("\n");
+ }
+ }
+ else {
+ /* This code has not been tested.... */
+ if (isdp->id_irq) {
+ INTRDIS(isdp->id_irq);
+ unregister_intr(ffs(isdp->id_irq) - 1,
+ isdp->id_intr);
+ if (mp)
+ INTRUNMASK(*mp, isdp->id_irq);
+ }
}
- printf("\n");
}
}
diff --git a/sys/amd64/isa/isa.h b/sys/amd64/isa/isa.h
index e2a26e7..7f6b02a 100644
--- a/sys/amd64/isa/isa.h
+++ b/sys/amd64/isa/isa.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.h 5.7 (Berkeley) 5/9/91
- * $Id: isa.h,v 1.4 1994/01/05 15:03:28 rgrimes Exp $
+ * $Id: isa.h,v 1.5 1994/04/21 14:20:54 sos Exp $
*/
#ifndef _I386_ISA_ISA_H_
@@ -62,6 +62,7 @@ unsigned char rtcin __P((int));
/* CPU Board */
#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */
#define IO_ICU1 0x020 /* 8259A Interrupt Controller #1 */
+#define IO_PMP1 0x026 /* 82347 Power Management Peripheral */
#define IO_TIMER1 0x040 /* 8253 Timer #1 */
#define IO_TIMER2 0x048 /* 8253 Timer #2 */
#define IO_KBD 0x060 /* 8042 Keyboard */
@@ -78,7 +79,9 @@ unsigned char rtcin __P((int));
#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */
- /* 0x178 - 0x1EF Open */
+#define IO_PMP2 0x178 /* 82347 Power Management Peripheral */
+
+ /* 0x17A - 0x1EF Open */
#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */
#define IO_GAME 0x200 /* Game Controller */
@@ -146,6 +149,7 @@ unsigned char rtcin __P((int));
#define IO_TMRSIZE 16 /* 8253 programmable timers */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
#define IO_VGASIZE 16 /* VGA controllers */
+#define IO_PMPSIZE 2 /* 82347 power management peripheral */
#endif /* IO_ISASIZES */
diff --git a/sys/conf/Makefile.i386 b/sys/conf/Makefile.i386
index 097d688..b4f6efc 100644
--- a/sys/conf/Makefile.i386
+++ b/sys/conf/Makefile.i386
@@ -1,6 +1,6 @@
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
-# $Id: Makefile.i386,v 1.38 1994/09/23 07:01:59 phk Exp $
+# $Id: Makefile.i386,v 1.39 1994/09/29 14:02:40 csgr Exp $
#
# Makefile for FreeBSD
#
@@ -66,7 +66,7 @@ DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
SFILES= ${I386}/i386/exception.s ${I386}/i386/microtime.s \
- ${I386}/i386/support.s ${I386}/i386/swtch.s
+ ${I386}/i386/support.s ${I386}/i386/swtch.s ${I386}/apm/apm_setup.s
SYSTEM_CFILES= ioconf.c param.c vnode_if.c
SYSTEM_SFILES= ${I386}/i386/locore.s
SYSTEM_OBJS=locore.o vnode_if.o ${OBJS} ioconf.o param.o
diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc
index 097d688..b4f6efc 100644
--- a/sys/conf/Makefile.powerpc
+++ b/sys/conf/Makefile.powerpc
@@ -1,6 +1,6 @@
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
-# $Id: Makefile.i386,v 1.38 1994/09/23 07:01:59 phk Exp $
+# $Id: Makefile.i386,v 1.39 1994/09/29 14:02:40 csgr Exp $
#
# Makefile for FreeBSD
#
@@ -66,7 +66,7 @@ DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
SFILES= ${I386}/i386/exception.s ${I386}/i386/microtime.s \
- ${I386}/i386/support.s ${I386}/i386/swtch.s
+ ${I386}/i386/support.s ${I386}/i386/swtch.s ${I386}/apm/apm_setup.s
SYSTEM_CFILES= ioconf.c param.c vnode_if.c
SYSTEM_SFILES= ${I386}/i386/locore.s
SYSTEM_OBJS=locore.o vnode_if.o ${OBJS} ioconf.o param.o
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 5ccdaab..c08c577 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -1,8 +1,10 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.49 1994/09/26 16:15:06 jkh Exp $
+# $Id: files.i386,v 1.50 1994/10/01 02:36:24 swallace Exp $
#
+i386/apm/apm.c optional apm device-driver
+i386/apm/apm_setup.s optional apm
i386/i386/autoconf.c standard device-driver
i386/i386/conf.c standard
i386/i386/cons.c standard
diff --git a/sys/dev/kbd/kbdtables.h b/sys/dev/kbd/kbdtables.h
index 7e8318f..a48b6a6 100644
--- a/sys/dev/kbd/kbdtables.h
+++ b/sys/dev/kbd/kbdtables.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * $Id: kbdtables.h,v 1.14 1994/09/29 08:29:17 sos Exp $
*/
#define SET8 0x80 /* eight bit for emacs SET8-key */
@@ -799,7 +799,7 @@ keymap_t key_map = { 0x69, /* US iso8859 keymap */
/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00,
/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00,
/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00,
-/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 0x00, 0x00,
+/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00,
/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00,
/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00,
/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00,
diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c
index 0479f76..230c945 100644
--- a/sys/dev/syscons/syscons.c
+++ b/sys/dev/syscons/syscons.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.59 1994/09/29 08:29:21 sos Exp $
+ * $Id: syscons.c,v 1.60 1994/09/29 15:49:09 ache Exp $
*/
#include "sc.h"
@@ -64,6 +64,9 @@
#include <i386/isa/timerreg.h>
#include <i386/isa/kbdtables.h>
#include <i386/i386/cons.h>
+#ifdef APM
+#include <machine/apm_bios.h>
+#endif
#if !defined(NCONS)
#define NCONS 12
@@ -288,6 +291,16 @@ struct isa_driver scdriver = {
pcprobe, pcattach, "sc",
};
+#ifdef APM
+static int
+pc_resume(void)
+{
+ /* when the system wakes up, modifier keys must be re-initialized */
+ shfts = ctls = alts = agrs = metas = 0;
+ return 0;
+}
+#endif /* APM */
+
int
pcprobe(struct isa_device *dev)
{
@@ -391,6 +404,9 @@ pcattach(struct isa_device *dev)
#endif
cursor_pos(1);
update_leds(console[0].status);
+#ifdef APM
+ apm_resume_hook_init(pc_resume, "Syscons console", APM_MID_ORDER);
+#endif
return 0;
}
@@ -2081,7 +2097,11 @@ scinit(void)
scp->ysize = ROW;
scp->bell_pitch = BELL_PITCH;
scp->bell_duration = BELL_DURATION;
+#ifndef LAPTOP
scp->status = NLKED;
+#else
+ scp->status = 0;
+#endif
scp->pid = 0;
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
@@ -2429,6 +2449,12 @@ next_code:
case RBT:
shutdown_nice();
break;
+ case SUSP:
+#ifdef APM
+ apm_suspend_resume();
+#endif /* APM */
+ break;
+
case DBG:
#ifdef DDB /* try to switch to console 0 */
if (cur_console->smode.mode == VT_AUTO &&
diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c
new file mode 100644
index 0000000..3660844
--- /dev/null
+++ b/sys/i386/apm/apm.c
@@ -0,0 +1,823 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (c) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include "apm.h"
+
+#if NAPM > 0
+
+#include <sys/param.h>
+#include "conf.h"
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include "i386/isa/isa.h"
+#include "i386/isa/isa_device.h"
+#include <machine/apm_bios.h>
+#include <machine/segments.h>
+#include <vm/vm.h>
+#include <sys/syslog.h>
+#include "apm_setup.h"
+
+/* static data */
+static int apm_initialized = 0, active = 0, halt_cpu = 1;
+static u_int minorversion, majorversion;
+static u_int cs32_base, cs16_base, ds_base;
+static u_int cs_limit, ds_limit;
+static u_int cs_entry;
+static u_int intversion;
+static int idle_cpu, disabled, disengaged;
+
+/* Map version number to integer (keeps ordering of version numbers) */
+#define INTVERSION(major, minor) ((major)*100 + (minor))
+
+static timeout_t apm_timeout;
+
+/* setup APM GDT discriptors */
+static void
+setup_apm_gdt(u_int code32_base, u_int code16_base, u_int data_base, u_int code_limit, u_int data_limit)
+{
+ /* setup 32bit code segment */
+ gdt_segs[GAPMCODE32_SEL].ssd_base = code32_base;
+ gdt_segs[GAPMCODE32_SEL].ssd_limit = code_limit;
+
+ /* setup 16bit code segment */
+ gdt_segs[GAPMCODE16_SEL].ssd_base = code16_base;
+ gdt_segs[GAPMCODE16_SEL].ssd_limit = code_limit;
+
+ /* setup data segment */
+ gdt_segs[GAPMDATA_SEL ].ssd_base = data_base;
+ gdt_segs[GAPMDATA_SEL ].ssd_limit = data_limit;
+
+ /* reflect these changes on physical GDT */
+ ssdtosd(gdt_segs + GAPMCODE32_SEL, gdt + GAPMCODE32_SEL);
+ ssdtosd(gdt_segs + GAPMCODE16_SEL, gdt + GAPMCODE16_SEL);
+ ssdtosd(gdt_segs + GAPMDATA_SEL , gdt + GAPMDATA_SEL );
+}
+
+/* 48bit far pointer */
+struct addr48 {
+ u_long offset;
+ u_short segment;
+} apm_addr;
+
+
+/* register structure for BIOS call */
+union real_regs {
+ struct xregs {
+ u_short ax;
+ u_short bx __attribute__ ((packed));
+ u_short cx __attribute__ ((packed));
+ u_short dx __attribute__ ((packed));
+ u_short si __attribute__ ((packed));
+ u_short di __attribute__ ((packed));
+ u_short cf __attribute__ ((packed)); /* carry */
+ } x;
+ struct hlregs {
+ u_char al;
+ u_char ah __attribute__ ((packed));
+ u_char bl __attribute__ ((packed));
+ u_char bh __attribute__ ((packed));
+ u_char cl __attribute__ ((packed));
+ u_char ch __attribute__ ((packed));
+ u_char dl __attribute__ ((packed));
+ u_char dh __attribute__ ((packed));
+ u_short si __attribute__ ((packed));
+ u_short di __attribute__ ((packed));
+ u_short cf __attribute__ ((packed)); /* carry */
+ } hl;
+};
+
+
+/* call APM BIOS */
+extern void call_apm(union real_regs* regs);
+
+extern u_char apm_errno;
+
+/* enable/disable power management */
+static int
+apm_enable_disable_pm(int enable)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_ENABLEDISABLEPM;
+ if (intversion >= INTVERSION(1, 1)) {
+ regs.x.bx = PMDV_ALLDEV;
+ }
+ else {
+ regs.x.bx = 0xffff; /* APM version 1.0 only */
+ }
+ regs.x.cx = enable;
+ call_apm(&regs);
+ return regs.x.cf;
+}
+
+/* engage/disengage power management (APM 1.1 or later) */
+static int
+apm_engage_disengage_pm(int engage)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_ENGAGEDISENGAGEPM;
+ regs.x.bx = PMDV_ALLDEV;
+ regs.x.cx = engage;
+ call_apm(&regs);
+ return regs.x.cf;
+}
+
+/* get PM event */
+static u_int
+apm_getevent(void)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_GETPMEVENT;
+ call_apm(&regs);
+ if (regs.x.cf) {
+#if 0
+ printf("No event: errcode = %d\n", apm_errno);
+#endif
+ return PMEV_NOEVENT;
+ }
+ return (u_int)regs.x.bx;
+}
+
+/*
+ * In many cases, the first event that occured after resume, needs
+ * special treatment. This binary flag make this process possible.
+ * Initial value of this variable is 1, because the bootstrap
+ * condition is equivalent to resumed condition for the power
+ * manager.
+ */
+static int resumed_event = 1;
+
+/* suspend entire system */
+static int
+apm_suspend_system(void)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_SETPWSTATE;
+ regs.x.bx = PMDV_ALLDEV;
+ regs.x.cx = PMST_SUSPEND;
+ call_apm(&regs);
+ if (regs.x.cf) {
+ printf("Entire system suspend failure: errcode = %d\n", apm_errno);
+ return 1;
+ }
+ resumed_event = 1;
+
+ return 0;
+}
+
+/* APM Battery low handler */
+static void
+apm_battery_low(void)
+{
+ /* Currently, this routine has not been implemented. Sorry... */
+}
+
+
+/* APM driver calls some functions automatically when the system wakes up */
+static void
+apm_execute_hook(apm_hook_func_t list)
+{
+ apm_hook_func_t p;
+
+ for (p = list; p != NULL; p = p->next) {
+ if ((*(p->func))()) {
+ printf("Warning: APM hook of %s failed", p->name);
+ }
+ }
+}
+
+
+/* APM hook manager */
+static apm_hook_func_t
+apm_hook_init(apm_hook_func_t *list, int (*func)(void), char *name, int order)
+{
+ int pl;
+ apm_hook_func_t p, prev, new_node;
+
+ pl = splhigh();
+ new_node = malloc(sizeof(*new_node), M_DEVBUF, M_NOWAIT);
+ if (new_node == NULL) {
+ panic("Can't allocate device buffer for apm_resume_hook.");
+ }
+ new_node->func = func;
+ new_node->name = name;
+#if 0
+ new_node->next = *list;
+ *list = new_node;
+#else
+ prev = NULL;
+ for (p = *list; p != NULL; prev = p, p = p->next) {
+ if (p->order > order) {
+ break;
+ }
+ }
+
+ if (prev == NULL) {
+ new_node->next = *list;
+ *list = new_node;
+ }
+ else {
+ new_node->next = prev->next;
+ prev->next = new_node;
+ }
+#endif
+ splx(pl);
+ return new_node;
+}
+
+void
+apm_hook_delete(apm_hook_func_t *list, apm_hook_func_t delete_node)
+{
+ int pl;
+ apm_hook_func_t p, prev;
+
+ pl = splhigh();
+ prev = NULL;
+ for (p = *list; p != NULL; prev = p, p = p->next) {
+ if (p == delete_node) {
+ goto deleteit;
+ }
+ }
+ panic("Tried to delete unregistered apm_resume_hook.");
+ goto nosuchnode;
+deleteit:
+ if (prev != NULL) {
+ prev->next = p->next;
+ }
+ else {
+ *list = p->next;
+ }
+ free(delete_node, M_DEVBUF);
+nosuchnode:
+ splx(pl);
+}
+
+static struct timeval suspend_time;
+
+/* default APM hook functions */
+static int
+apm_default_resume(void)
+{
+ u_int second, minute, hour;
+ struct timeval resume_time;
+
+ inittodr(0); /* adjust time to RTC */
+ microtime(&resume_time);
+ second = resume_time.tv_sec - suspend_time.tv_sec;
+ hour = second / 3600;
+ second %= 3600;
+ minute = second / 60;
+ second %= 60;
+ log(LOG_NOTICE, "resumed from suspended mode (slept %02d:%02d:%02d)\n", hour, minute, second);
+ return 0;
+}
+
+static int
+apm_default_suspend(void)
+{
+ int pl;
+#if 0
+ pl = splhigh();
+ sync(curproc, NULL, NULL);
+ splx(pl);
+#endif
+ microtime(&suspend_time);
+ return 0;
+}
+
+/* list structure for hook */
+static apm_hook_func_t apm_resume_hook = NULL;
+static apm_hook_func_t apm_suspend_hook = NULL;
+
+/* execute resume hook */
+static void
+apm_execute_resume_hook(void)
+{
+ apm_execute_hook(apm_resume_hook);
+}
+
+/* add a node on resume hook */
+apm_hook_func_t
+apm_resume_hook_init(int (*func)(void), char *name, int order)
+{
+ return apm_hook_init(&apm_resume_hook, func, name, order);
+}
+
+/* delete a node from resume hook */
+void
+apm_resume_hook_delete(apm_hook_func_t delete_node)
+{
+ apm_hook_delete(&apm_resume_hook, delete_node);
+}
+
+/* execute suspend hook */
+static void
+apm_execute_suspend_hook(void)
+{
+ apm_execute_hook(apm_suspend_hook);
+}
+
+/* add a node on resume hook */
+apm_hook_func_t
+apm_suspend_hook_init(int (*func)(void), char *name, int order)
+{
+ return apm_hook_init(&apm_suspend_hook, func, name, order);
+}
+
+/* delete a node from resume hook */
+void
+apm_suspend_hook_delete(apm_hook_func_t delete_node)
+{
+ apm_hook_delete(&apm_suspend_hook, delete_node);
+}
+
+/* get APM information */
+static int
+apm_get_info(apm_info_t aip)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_GETPWSTATUS;
+ regs.x.bx = PMDV_ALLDEV;
+ call_apm(&regs);
+ if (regs.x.cf) {
+ printf("Get APM info failure: errcode = %d\n", apm_errno);
+ return 1;
+ }
+ aip->ai_major = (u_int)majorversion;
+ aip->ai_minor = (u_int)minorversion;
+ aip->ai_acline = (u_int)regs.hl.bh;
+ aip->ai_batt_stat = (u_int)regs.hl.bl;
+ aip->ai_batt_life = (u_int)regs.hl.cl;
+ return 0;
+}
+
+
+/* Define equivalent event sets */
+
+static int equiv_event_num = 0;
+static struct apm_eqv_event equiv_events[APM_MAX_EQUIV_EVENTS];
+
+static int
+apm_def_eqv(apm_eqv_event_t aee)
+{
+ if (equiv_event_num == APM_MAX_EQUIV_EVENTS) {
+ return 1;
+ }
+ memcpy(&equiv_events[equiv_event_num], aee, sizeof(struct apm_eqv_event));
+ equiv_event_num++;
+ return 0;
+}
+
+static void
+apm_flush_eqv(void)
+{
+ equiv_event_num = 0;
+}
+
+static void apm_processevent(void);
+
+/*
+ * Public interface to the suspend/resume:
+ *
+ * Execute suspend and resume hook before and after sleep, respectively.
+ */
+
+void
+apm_suspend_resume(void)
+{
+ int pl;
+#if 0
+ printf("Called apm_suspend_resume();\n");
+#endif
+ if (apm_initialized) {
+ apm_execute_suspend_hook();
+ apm_suspend_system();
+ apm_execute_resume_hook();
+ apm_processevent();
+ }
+}
+
+/* inform APM BIOS that CPU is idle */
+void
+apm_cpu_idle(void)
+{
+ if (idle_cpu) {
+ if (active) {
+ asm("movw $0x5305, %ax; lcall _apm_addr");
+ }
+ }
+ /*
+ * Some APM implementation halts CPU in BIOS, whenever
+ * "CPU-idle" function are invoked, but swtch() of
+ * FreeBSD halts CPU, therefore, CPU is halted twice
+ * in the sched loop. It makes the interrupt latency
+ * terribly long and be able to cause a serious problem
+ * in interrupt processing. We prevent it by removing
+ * "hlt" operation from swtch() and managed it under
+ * APM driver.
+ */
+ if (!active || halt_cpu) {
+ asm("sti ; hlt"); /* wait for interrupt */
+ }
+}
+
+/* inform APM BIOS that CPU is busy */
+void
+apm_cpu_busy(void)
+{
+ if (idle_cpu && active) {
+ asm("movw $0x5306, %ax; lcall _apm_addr");
+ }
+}
+
+
+/*
+ * APM timeout routine:
+ *
+ * This routine is automatically called by timer two times within one
+ * seconed.
+ */
+
+static void
+apm_timeout(void *arg1)
+{
+#if 0
+ printf("Called apm_timeout\n");
+#endif
+ apm_processevent();
+ timeout(apm_timeout, NULL, hz / 2); /* 2 Hz */
+ /* APM driver must polls APM event a time per second */
+}
+
+/* enable APM BIOS */
+static void
+apm_event_enable(void)
+{
+#if 0
+ printf("called apm_event_enable()\n");
+#endif
+ if (apm_initialized) {
+ active = 1;
+ timeout(apm_timeout, NULL, 2 * hz);
+ }
+}
+
+/* disable APM BIOS */
+static void
+apm_event_disable(void)
+{
+#if 0
+ printf("called apm_event_disable()\n");
+#endif
+ if (apm_initialized) {
+ untimeout(apm_timeout, NULL);
+ active = 0;
+ }
+}
+
+/* halt CPU in scheduling loop */
+static void apm_halt_cpu(void)
+{
+ if (apm_initialized) {
+ halt_cpu = 1;
+ }
+}
+
+/* don't halt CPU in scheduling loop */
+static void apm_not_halt_cpu(void)
+{
+ if (apm_initialized) {
+ halt_cpu = 0;
+ }
+}
+
+/* device driver definitions */
+int apmprobe (struct isa_device *);
+int apmattach(struct isa_device *);
+
+struct isa_driver apmdriver = { apmprobe, apmattach, "apm" };
+
+
+/*
+ * probe APM (dummy):
+ *
+ * APM probing routine is placed on locore.s and apm_init.S because
+ * this process forces the CPU to turn to real mode or V86 mode.
+ * Current version uses real mode, but on future version, we want
+ * to use V86 mode in APM initialization.
+ */
+int
+apmprobe(struct isa_device *dvp)
+{
+ switch (apm_version) {
+ case APMINI_CANTFIND:
+ /* silent */
+ return 0;
+ case APMINI_NOT32BIT:
+ printf("apm%d: 32bit connection is not supported.\n", dvp->id_unit);
+ return 0;
+ case APMINI_CONNECTERR:
+ printf("apm%d: 32-bit connection error.\n", dvp->id_unit);
+ return 0;
+ }
+ return -1;
+}
+
+static const char *
+is_enabled(int enabled)
+{
+ if (enabled) {
+ return "enabled";
+ }
+ return "disabled";
+}
+
+static const char *
+apm_error(void)
+{
+ static char buffer[64];
+
+ switch (apm_errno) {
+ case 0:
+ return "APM OK.";
+ default:
+ sprintf(buffer, "Unknown Error 0x%x", (u_int)apm_errno);
+ return buffer;
+ }
+}
+
+
+
+/* Process APM event */
+static void
+apm_processevent(void)
+{
+ int i, apm_event;
+
+getevent:
+ while (1) {
+ if ((apm_event = apm_getevent()) == PMEV_NOEVENT) {
+ break;
+ }
+#if 0
+#if 1
+#define OPMEV_DEBUGMESSAGE(symbol) case symbol: break;
+#else
+#define OPMEV_DEBUGMESSAGE(symbol) case symbol: printf("Original APM Event: " #symbol "\n"); break
+#endif
+ switch (apm_event) {
+ OPMEV_DEBUGMESSAGE(PMEV_NOEVENT);
+ OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
+ OPMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
+ OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
+ OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
+ OPMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
+ OPMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
+ OPMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
+ default:
+ printf("Unknown Original APM Event 0x%x\n", apm_event);
+ break;
+ }
+#endif
+ for (i = 0; i < equiv_event_num; i++) {
+ if (equiv_events[i].aee_event == apm_event) {
+ u_int tmp = PMEV_DEFAULT;
+ if (resumed_event) {
+ tmp = equiv_events[i].aee_resume;
+ }
+ else {
+ tmp = equiv_events[i].aee_equiv;
+ }
+ if (tmp != PMEV_DEFAULT) {
+ apm_event = tmp;
+ break;
+ }
+ }
+ }
+#if 1
+#if 1
+#define PMEV_DEBUGMESSAGE(symbol) case symbol: break;
+#else
+#define PMEV_DEBUGMESSAGE(symbol) case symbol: printf("APM Event: " #symbol "\n"); break
+#endif
+ switch (apm_event) {
+ PMEV_DEBUGMESSAGE(PMEV_NOEVENT);
+ PMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
+ PMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
+ PMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
+ PMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
+ PMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
+ PMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
+ PMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
+ PMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
+ PMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
+ PMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
+ default:
+ printf("Unknown APM Event 0x%x\n", apm_event);
+ break;
+ }
+#endif
+ switch (apm_event) {
+ case PMEV_NOEVENT:
+ case PMEV_STANDBYREQ:
+ case PMEV_POWERSTATECHANGE:
+ case PMEV_CRITSUSPEND:
+ case PMEV_USERSTANDBYREQ:
+ case PMEV_USERSUSPENDREQ:
+ break;
+ case PMEV_BATTERYLOW:
+ apm_battery_low();
+ break;
+ case PMEV_SUSPENDREQ:
+ apm_suspend_resume();
+ break;
+ case PMEV_NORMRESUME:
+ case PMEV_CRITRESUME:
+ case PMEV_UPDATETIME:
+ case PMEV_STANDBYRESUME:
+ inittodr(0); /* adjust time to RTC */
+ break;
+ }
+ }
+ resumed_event = 0;
+}
+
+
+/*
+ * Attach APM:
+ *
+ * Initialize APM driver (APM BIOS itself has been initialized in locore.s)
+ */
+
+int
+apmattach(struct isa_device *dvp)
+{
+
+ /* setup APM parameters */
+ minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0);
+ majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8);
+ intversion = INTVERSION(majorversion, minorversion);
+ cs32_base = (apm_cs32_base << 4) + KERNBASE;
+ cs16_base = (apm_cs16_base << 4) + KERNBASE;
+ ds_base = (apm_ds_base << 4) + KERNBASE;
+ cs_limit = apm_cs_limit;
+ ds_limit = apm_ds_limit;
+ cs_entry = apm_cs_entry;
+ idle_cpu = ((apm_flags & APM_CPUIDLE_SLOW) != 0);
+ disabled = ((apm_flags & APM_DISABLED) != 0);
+ disengaged = ((apm_flags & APM_DISENGAGED) != 0);
+
+ /* print bootstrap messages */
+ printf(" found APM BIOS version %d.%d\n", dvp->id_unit, majorversion, minorversion);
+ printf("apm%d: Code32 0x%08x, Code16 0x%08x, Data 0x%08x\n", dvp->id_unit, cs32_base, cs16_base, ds_base);
+ printf("apm%d: Code entry 0x%08x, Idling CPU %s, Management %s\n", dvp->id_unit, cs_entry, is_enabled(idle_cpu), is_enabled(!disabled));
+
+ /*
+ * APM 1.0 does not have:
+ *
+ * 1. segment limit parameters
+ *
+ * 2. engage/disengage operations
+ */
+ if (intversion >= INTVERSION(1, 1)) {
+ printf("apm%d: Engaged control %s\n", dvp->id_unit, is_enabled(!disengaged));
+ }
+ else {
+ cs_limit = 0xffff;
+ ds_limit = 0xffff;
+ }
+
+ /* setup GDT */
+ setup_apm_gdt(cs32_base, cs16_base, ds_base, cs_limit, ds_limit);
+
+ /* setup entry point 48bit pointer */
+ apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL);
+ apm_addr.offset = cs_entry;
+
+ /* enable power management */
+ if (disabled) {
+ if (apm_enable_disable_pm(1)) {
+ printf("Warning: APM enable function failed! [%s]\n", apm_error());
+ }
+ }
+
+ /* engage power managment (APM 1.1 or later) */
+ if (intversion >= INTVERSION(1, 1) && disengaged) {
+ if (apm_engage_disengage_pm(1)) {
+ printf("Warning: APM engage function failed [%s]\n", apm_error());
+ }
+ }
+
+ apm_suspend_hook_init(apm_default_suspend, "default suspend", APM_MAX_ORDER);
+ apm_resume_hook_init (apm_default_resume , "default resume" , APM_MIN_ORDER);
+ apm_initialized = 1;
+
+ return 0;
+}
+
+int
+apmopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ if (!apm_initialized) {
+ return ENXIO;
+ }
+ switch (minor(dev)) {
+ case 0: /* apm0 */
+ break;
+ defaults:
+ return (ENXIO);
+ }
+ return 0;
+}
+
+int
+apmclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ return 0;
+}
+
+int
+apmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ int error = 0;
+ int pl;
+
+#if 0
+ printf("APM ioctl: minor = %d, cmd = 0x%x\n", minor(dev), cmd);
+#endif
+
+ pl = splhigh();
+ if (minor(dev) != 0) {
+ return ENXIO;
+ }
+ if (!apm_initialized) {
+ return ENXIO;
+ }
+ switch (cmd) {
+ case APMIO_SUSPEND:
+ apm_suspend_resume();
+ break;
+ case APMIO_GETINFO:
+ if (apm_get_info((apm_info_t)addr)) {
+ error = ENXIO;
+ }
+ break;
+ case APMIO_DEFEQV:
+ if (apm_def_eqv((apm_eqv_event_t)addr)) {
+ error = ENOSPC;
+ }
+ break;
+ case APMIO_FLUSHEQV:
+ apm_flush_eqv();
+ break;
+ case APMIO_ENABLE:
+ apm_event_enable();
+ break;
+ case APMIO_DISABLE:
+ apm_event_disable();
+ break;
+ case APMIO_HALTCPU:
+ apm_halt_cpu();
+ break;
+ case APMIO_NOTHALTCPU:
+ apm_not_halt_cpu();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(pl);
+ return error;
+}
+
+#endif /* NAPM > 0 */
diff --git a/sys/i386/apm/apm_init/Makefile b/sys/i386/apm/apm_init/Makefile
new file mode 100644
index 0000000..22d6d60
--- /dev/null
+++ b/sys/i386/apm/apm_init/Makefile
@@ -0,0 +1,50 @@
+#
+# LP (Laptop Package)
+#
+# (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+#
+# This software may be used, modified, copied, and distributed in
+# both source and binary form provided that the above copyright and
+# these terms are retained. Under no circumstances is the author
+# responsible for the proper functioning of this software, nor does
+# the author assume any responsibility for damages incurred with its
+# use.
+#
+# Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+#
+
+OBJS = apm_init.o real_prot.o table.o
+CFLAGS = -DKERNEL -DINITIALIZER
+OPTFLAGS = -O2
+I386INCDIR = ${.CURDIR}/../../include
+INC= -I$(I386INCDIR)
+
+all: apm_init.inc
+
+.SUFFIXES: .c .S .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(OPTFLAGS) $(INC) -c $<
+
+.S.o:
+ $(CC) $(CFLAGS) $(INC) -c $<
+
+apm_init.inc: apm_init bin2asm
+ ./bin2asm apm_init apm_init.inc
+
+apm_init: $(OBJS)
+ $(LD) -Bstatic -N -T 0 -o apm_init $(OBJS)
+ cp apm_init apm_init.sym
+ @strip apm_init
+ @sh ${.CURDIR}/rmaouthdr apm_init apm_init.tmp
+ @mv -f apm_init.tmp apm_init
+
+bin2asm: bin2asm.c
+ $(CC) -o bin2asm ${.CURDIR}/bin2asm.c
+
+allclean: clean
+ @rm -f apm_init.inc
+clean:
+ @rm -f *.o apm_init apm_init.sym bin2asm
+
+.include <bsd.prog.mk>
diff --git a/sys/i386/apm/apm_init/apm_init.S b/sys/i386/apm/apm_init/apm_init.S
new file mode 100644
index 0000000..6c22571
--- /dev/null
+++ b/sys/i386/apm/apm_init/apm_init.S
@@ -0,0 +1,207 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * If you want to know the specification of APM BIOS, see the following
+ * documentations,
+ *
+ * [1] Intel Corporation and Microsoft Corporation, "Advanced Power
+ * Management, The Next Generation, Version 1.0", Feb.,1992.
+ *
+ * [2] Intel Corporation and Microsoft Corporation, "Advanced Power
+ * Management (APM) BIOS Interface Specification Revision 1.1",
+ * Sep.,1993, Intel Order Number: 241704-001, Microsoft Part
+ * Number: 781-110-X01
+ *
+ * or contact
+ *
+ * APM Support Desk (Intel Corporation, US)
+ * TEL: (800)628-8686
+ * FAX: (916)356-6100.
+ */
+
+ .file "apm_init.S"
+
+#define ASM
+
+#include "real_prot.h"
+#include "apm_bios.h"
+#include "apm_segments.h"
+
+/*
+ * APM BIOS initializer
+ *
+ * Return value:
+ * %eax 0xfffffff Can't find APM BIOS
+ * 0xffffffe Don't support 32bit connection
+ * 0xffffffd Connection error
+ * otherwise APM version (16bit BCD format)
+ * %ebx APM cs entry offset (32bit)
+ * %ecx lower 16bit APM 16bit cs base (real mode segment)
+ * upper 16bit APM 32bit cs base (real mode segment)
+ * %edx lower 16bit APM ds limit (real mode segment)
+ * upper 16bit [Reserved]
+ * %esi lower 16bit APM cs limit (APM 1.1 or later)
+ * upper 16bit APM ds limit (APM 1.1 or later)
+ * %edi bit0 = 1 16bit protected mode interface supported
+ * bit1 = 1 32bit protected mode interface supported
+ * bit2 = 1 "CPU idle" call slows processor clock speed
+ * bit3 = 1 APM BIOS Power Management disabled
+ * bit4 = 1 APM BIOS Power Management disengaged
+ */
+
+ .text
+ENTRY(apm_init)
+ cli /* disable interrupt */
+ push %ebp /* save original base pointer */
+ /* ebp is used as a register variable */
+ /*
+ * save old data segments: We assume that %ds == %es && %ds == %ss
+ */
+ push %fs
+ movw %ds, %ax
+ movw %ax, %fs
+ movw $(APM_INIT_DS_SEL), %ax /* initializer data segment */
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movl %esp, old_esp /* save original stack pointer */
+ movl $0x10000, %esp /* setup temporary stack */
+ /* (note that it isn't 0x00000000) */
+
+ sidt EXT(Idtr_prot) /* save current IDT */
+ call EXT(prot_to_real) /* return to real mode */
+
+ /*
+ * APM installation check
+ */
+ movb $(APM_BIOS), %ah
+ movb $(APM_INSTCHECK), %al
+ data32
+ movl $(PMDV_APMBIOS), %ebx
+ sti
+ int $(SYSTEM_BIOS) /* call system BIOS */
+ cli
+
+ jnc 1f /* if found, goto 1f */
+
+ data32
+ call EXT(real_to_prot) /* come back again to protected mode */
+ movl $(APMINI_CANTFIND), apm_version
+ /* can't find APM BIOS */
+ jmp finish
+
+1:
+ movl %eax, %edx /* actually, movw %ax, %dx */
+ /* save the value of %ax */
+ data32
+ call EXT(real_to_prot) /* come back again to protected mode */
+ cmpb $0x50, %bh /* %bh == 'P'? */
+ jnz 1f
+ cmpb $0x4d, %bl /* %bl == 'M'? */
+ jz 2f
+
+1:
+ movl $(APMINI_CANTFIND), apm_version
+ /* can't find APM BIOS */
+ jmp finish
+
+2:
+ testl $(APM_32BIT_SUPPORT), %ecx
+ /* supports 32bit connection? */
+ jnz 1f
+
+ movl $(APMINI_NOT32BIT), apm_version
+ /* don't support 32bit connection */
+ jmp finish
+1:
+ movl %edx, apm_version
+ andl $0x0000ffff, %ecx
+ movl %ecx, apm_flags
+
+ /*
+ * APM Protected Mode 32-bit Interface Connect
+ */
+ call EXT(prot_to_real) /* return to real mode */
+
+ movb $(APM_BIOS), %ah
+ movb $(APM_PROT32CONNECT), %al
+ data32
+ movl $(PMDV_APMBIOS), %ebx
+ sti
+ int $(SYSTEM_BIOS)
+ cli
+ jnc 1f /* if successed, go to 1f */
+ data32
+ call EXT(real_to_prot)
+ movl $(APMINI_CONNECTERR), apm_version
+ /* connection error */
+ jmp finish
+1:
+ /* save PM 32bit code segment into %bp */
+ movl %eax, %ebp /* actually, movw %ax, %bp */
+ data32
+ call EXT(real_to_prot)
+ movl $0x0000ffff, %eax
+ andl %eax, %ebp /* 32bit cs base */
+ andl %eax, %ecx /* 16bit cs base */
+ andl %eax, %edx /* ds base */
+ andl %eax, %esi /* cs length (APM 1.1 or later) */
+ andl %eax, %edi /* ds length (APM 1.1 or later) */
+ /* %ebx is code offset */
+ /* pack 32bit cs and 16bit cs into %ecx */
+ shll $16, %ebp
+ orl %ebp, %ecx
+ /* pack cs length and ds length into %esi */
+ shll $16, %edi
+ orl %edi, %esi
+finish:
+ cli
+ lidt EXT(Idtr_prot) /* restore old IDTR */
+ movl old_esp, %esp /* restore old stack pointer */
+ movl apm_version, %ebp /* stored to %eax later */
+ movl apm_flags, %edi
+#if 0
+ movw $(BOOTSTRAP_DS_SEL), %ax
+ /* restore old data segments */
+#else
+ movw %fs, %ax
+#endif
+ movw %ax, %ss
+ movw %ax, %es
+ movw %ax, %ds
+ movl %ebp, %eax
+ pop %fs
+ popl %ebp /* restore old base pointer */
+ lret /* restore old code segment */
+
+ .data
+
+ .globl EXT(ouraddr)
+LEXT(ouraddr)
+ .long APM_OURADDR
+
+old_esp:
+ .long 0
+apm_version:
+ .long 0
+apm_flags:
+ .long 0
+old_ds:
+ .word 0
+old_es:
+ .word 0
+old_ss:
+ .word 0
diff --git a/sys/i386/apm/apm_init/apm_init.inc b/sys/i386/apm/apm_init/apm_init.inc
new file mode 100644
index 0000000..d241334
--- /dev/null
+++ b/sys/i386/apm/apm_init/apm_init.inc
@@ -0,0 +1,59 @@
+/* This file is automatically generated by bin2asm */
+/* Original file is 'apm_init' */
+
+ .byte 0xfa, 0x55, 0x0f, 0xa0, 0x66, 0x8c, 0xd8, 0x66
+ .byte 0x8e, 0xe0, 0x66, 0xb8, 0xf0, 0x00, 0x66, 0x8e
+ .byte 0xd8, 0x66, 0x8e, 0xc0, 0x66, 0x8e, 0xd0, 0x89
+ .byte 0x25, 0x84, 0x01, 0x00, 0x00, 0xbc, 0x00, 0x00
+ .byte 0x01, 0x00, 0x0f, 0x01, 0x0d, 0xa0, 0x01, 0x00
+ .byte 0x00, 0xe8, 0x12, 0x01, 0x00, 0x00, 0xb4, 0x53
+ .byte 0xb0, 0x00, 0x66, 0xbb, 0x00, 0x00, 0x00, 0x00
+ .byte 0xfb, 0xcd, 0x15, 0xfa, 0x73, 0x15, 0x66, 0xe8
+ .byte 0xcc, 0x00, 0x00, 0x00, 0xc7, 0x05, 0x88, 0x01
+ .byte 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x8c
+ .byte 0x00, 0x00, 0x00, 0x89, 0xc2, 0x66, 0xe8, 0xb5
+ .byte 0x00, 0x00, 0x00, 0x80, 0xff, 0x50, 0x75, 0x05
+ .byte 0x80, 0xfb, 0x4d, 0x74, 0x0c, 0xc7, 0x05, 0x88
+ .byte 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xeb
+ .byte 0x6e, 0xf7, 0xc1, 0x02, 0x00, 0x00, 0x00, 0x75
+ .byte 0x0c, 0xc7, 0x05, 0x88, 0x01, 0x00, 0x00, 0xfe
+ .byte 0xff, 0xff, 0xff, 0xeb, 0x5a, 0x89, 0x15, 0x88
+ .byte 0x01, 0x00, 0x00, 0x81, 0xe1, 0xff, 0xff, 0x00
+ .byte 0x00, 0x89, 0x0d, 0x8c, 0x01, 0x00, 0x00, 0xe8
+ .byte 0xa4, 0x00, 0x00, 0x00, 0xb4, 0x53, 0xb0, 0x03
+ .byte 0x66, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xcd
+ .byte 0x15, 0xfa, 0x73, 0x12, 0x66, 0xe8, 0x5e, 0x00
+ .byte 0x00, 0x00, 0xc7, 0x05, 0x88, 0x01, 0x00, 0x00
+ .byte 0xfd, 0xff, 0xff, 0xff, 0xeb, 0x21, 0x89, 0xc5
+ .byte 0x66, 0xe8, 0x4a, 0x00, 0x00, 0x00, 0xb8, 0xff
+ .byte 0xff, 0x00, 0x00, 0x21, 0xc5, 0x21, 0xc1, 0x21
+ .byte 0xc2, 0x21, 0xc6, 0x21, 0xc7, 0xc1, 0xe5, 0x10
+ .byte 0x09, 0xe9, 0xc1, 0xe7, 0x10, 0x09, 0xfe, 0xfa
+ .byte 0x0f, 0x01, 0x1d, 0xa0, 0x01, 0x00, 0x00, 0x8b
+ .byte 0x25, 0x84, 0x01, 0x00, 0x00, 0x8b, 0x2d, 0x88
+ .byte 0x01, 0x00, 0x00, 0x8b, 0x3d, 0x8c, 0x01, 0x00
+ .byte 0x00, 0x66, 0x8c, 0xe0, 0x66, 0x8e, 0xd0, 0x66
+ .byte 0x8e, 0xc0, 0x66, 0x8e, 0xd8, 0x89, 0xe8, 0x0f
+ .byte 0xa1, 0x5d, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0xfa, 0x0f, 0x20, 0xc0, 0x66, 0x83, 0xc8, 0x01
+ .byte 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x23, 0x01, 0x00
+ .byte 0x00, 0xe8, 0x00, 0xb8, 0xf0, 0x00, 0x00, 0x00
+ .byte 0x66, 0x8e, 0xd8, 0x66, 0x8e, 0xd0, 0x66, 0x8e
+ .byte 0xc0, 0x0f, 0x01, 0x1d, 0xa0, 0x01, 0x00, 0x00
+ .byte 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0xa1, 0x80, 0x01, 0x00, 0x00, 0xc1, 0xf8, 0x04
+ .byte 0x66, 0x50, 0x66, 0xb8, 0x62, 0x01, 0x66, 0x50
+ .byte 0xea, 0x57, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x0f
+ .byte 0x20, 0xc0, 0x66, 0x83, 0xe0, 0xfe, 0x0f, 0x22
+ .byte 0xc0, 0xcb, 0x66, 0x8c, 0xc8, 0x66, 0x8e, 0xd8
+ .byte 0x66, 0x8e, 0xd0, 0x66, 0x8e, 0xc0, 0x67, 0x66
+ .byte 0x0f, 0x01, 0x1d, 0xa6, 0x01, 0x00, 0x00, 0x66
+ .byte 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+/* Total size = 0x01b0 */
diff --git a/sys/i386/apm/apm_init/bin2asm.c b/sys/i386/apm/apm_init/bin2asm.c
new file mode 100644
index 0000000..b826e68
--- /dev/null
+++ b/sys/i386/apm/apm_init/bin2asm.c
@@ -0,0 +1,64 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include <stdio.h>
+
+#define NCOLS 8
+
+int main(int argc, char *argv[])
+{
+ int c, col;
+ FILE *infile, *outfile;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
+ exit(1);
+ }
+
+ if ((infile = fopen(argv[1], "rb")) == NULL) {
+ fprintf(stderr, "Can't open %s.\n", argv[1]);
+ exit(1);
+ }
+
+ if ((outfile = fopen(argv[2], "wb")) == NULL) {
+ fprintf(stderr, "Can't open %s.\n", argv[2]);
+ exit(1);
+ }
+
+ col = 0;
+
+ fprintf(outfile, "/* This file is automatically generated by bin2asm */\n");
+ fprintf(outfile, "/* Original file is '%s' */\n\n", argv[1]);
+
+ while ((c = fgetc(infile)) != EOF) {
+ if (col % NCOLS == 0) {
+ fprintf(outfile, "\t.byte\t");
+ }
+ fprintf(outfile, "0x%02x", c);
+ if (col % NCOLS == NCOLS - 1) {
+ fprintf(outfile, "\n");
+ }
+ else {
+ fprintf(outfile, ", ");
+ }
+ col++;
+ }
+
+ fprintf(outfile, "\n/* Total size = 0x%04x */\n", col);
+
+ fclose(infile);
+ fclose(outfile);
+ return 0;
+}
diff --git a/sys/i386/apm/apm_init/real_prot.S b/sys/i386/apm/apm_init/real_prot.S
new file mode 100644
index 0000000..d61a394
--- /dev/null
+++ b/sys/i386/apm/apm_init/real_prot.S
@@ -0,0 +1,185 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:13 rpd
+ * $Id: asm.S,v 1.2 1993/10/16 19:11:27 rgrimes Exp $
+ */
+
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * Modified for APM BIOS initializer by HOSOKAWA Tatsumi
+ *
+ * See also locore.s. It supports these functions works correctly.
+ */
+
+ .file "real_prot.S"
+
+#include "real_prot.h"
+#include "apm_segments.h"
+
+CR0_PE_ON = 0x1
+CR0_PE_OFF = 0xfffffffe
+
+.globl _ouraddr
+ .text
+
+/*
+ *
+ * real_to_prot()
+ * transfer from real mode to protected mode.
+ */
+
+ENTRY(real_to_prot)
+ /* guarantee that interrupt is disabled when in prot mode */
+ cli
+
+ /*
+ * deleted for APM initializer by HOSOKAWA Tatsumi
+ * <hosoakwa@mt.cs.keio.ac.jp>
+ */
+#if 0
+ /* load the gdtr */
+ addr32
+ data32
+ lgdt EXT(Gdtr)
+#endif
+
+ /* set the PE bit of CR0 */
+ mov %cr0, %eax
+
+ data32
+ or $CR0_PE_ON, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intrasegment jump to flush the processor pipeline and
+ * reload CS register
+ */
+ data32
+ ljmp $(APM_INIT_CS_SEL), $xprot
+
+xprot:
+ /*
+ * we are in USE32 mode now
+ * set up the protected mode segment registers : DS, SS, ES
+ */
+ mov $(APM_INIT_DS_SEL), %eax
+ movw %ax, %ds
+ movw %ax, %ss
+ movw %ax, %es
+
+ /* load idtr so we can debug */
+ lidt EXT(Idtr_prot)
+
+ ret
+
+/*
+ *
+ * prot_to_real()
+ * transfer from protected mode to real mode
+ *
+ */
+
+ENTRY(prot_to_real)
+
+ /* set up a dummy stack frame for the second seg change. */
+ movl _ouraddr, %eax
+ sarl $4, %eax
+ pushw %ax
+ movw $xreal, %ax /* gas botches pushw $xreal - extra bytes 0, 0*/
+ pushw %ax /* decode to add %al, (%eax) (%al usually 0) */
+
+ /* Change to use16 mode. */
+ ljmp $(APM_INIT_CS16_SEL), $x16
+
+x16:
+ /* clear the PE bit of CR0 */
+ mov %cr0, %eax
+ data32
+ and $CR0_PE_OFF, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intersegment jmp to flush the processor pipeline
+ * using the fake stack frame set up earlier
+ * and reload CS register
+ */
+ lret
+
+xreal:
+ /*
+ * we are in real mode now
+ * set up the real mode segment registers : DS, SS, ES
+ */
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %ss
+ movw %ax, %es
+
+ /* load idtr so we can debug */
+ addr32
+ data32
+ lidt EXT(Idtr_real)
+
+ data32
+ ret
diff --git a/sys/i386/apm/apm_init/real_prot.h b/sys/i386/apm/apm_init/real_prot.h
new file mode 100644
index 0000000..bc02200
--- /dev/null
+++ b/sys/i386/apm/apm_init/real_prot.h
@@ -0,0 +1,56 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.7 92/02/29 15:33:41 rpd
+ * $Id: asm.h,v 1.3 1993/10/16 19:11:29 rgrimes Exp $
+ */
+
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * Modified to APM BIOS initializer by HOSOKAWA, Tatsumi
+ */
+
+#define ALIGN 4
+#define EXT(x) _ ## x
+#define LEXT(x) _ ## x ## :
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+#define ENTRY(x) .globl EXT(x); .align ALIGN; LEXT(x)
diff --git a/sys/i386/apm/apm_init/rmaouthdr b/sys/i386/apm/apm_init/rmaouthdr
new file mode 100644
index 0000000..47838b0
--- /dev/null
+++ b/sys/i386/apm/apm_init/rmaouthdr
@@ -0,0 +1,6 @@
+#!/bin/csh -f
+#
+# from: Mach, Revision 2.2 92/04/04 11:36:01 rpd
+# $Id: rmaouthdr,v 1.3 1993/10/16 19:11:37 rgrimes Exp $
+#
+dd if=$1 of=$2 ibs=32 skip=1 obs=1024b
diff --git a/sys/i386/apm/apm_init/table.c b/sys/i386/apm/apm_init/table.c
new file mode 100644
index 0000000..eaf2fc6
--- /dev/null
+++ b/sys/i386/apm/apm_init/table.c
@@ -0,0 +1,24 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include <apm_bios.h>
+
+struct pseudo_desc {
+ unsigned short limit;
+ unsigned long base __attribute__ ((packed));
+};
+
+struct pseudo_desc Idtr_prot = { 0, 0 }; /* filled on run time */
+struct pseudo_desc Idtr_real = { 0x400 - 1, 0x0 };
diff --git a/sys/i386/apm/apm_setup.h b/sys/i386/apm/apm_setup.h
new file mode 100644
index 0000000..0009e56
--- /dev/null
+++ b/sys/i386/apm/apm_setup.h
@@ -0,0 +1,23 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, distributed, and sold,
+ * in both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+extern u_long apm_version;
+extern u_long apm_cs_entry;
+extern u_short apm_cs32_base;
+extern u_short apm_cs16_base;
+extern u_short apm_ds_base;
+extern u_short apm_cs_limit;
+extern u_short apm_ds_limit;
+extern u_short apm_flags;
diff --git a/sys/i386/apm/apm_setup.s b/sys/i386/apm/apm_setup.s
new file mode 100644
index 0000000..df1e9c9
--- /dev/null
+++ b/sys/i386/apm/apm_setup.s
@@ -0,0 +1,126 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, distributed, and sold,
+ * in both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#ifdef APM
+
+#define ASM
+
+#include <machine/asmacros.h>
+#include "assym.s"
+#include <machine/apm_bios.h>
+
+ .file "apm_setup.s"
+
+ .text
+
+ /* void call_apm(union real_regs *); */
+_call_apm:
+ .globl _call_apm
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ pushl %ecx
+
+ movl 8(%ebp), %eax
+ movl %eax, struct_regs
+ movw 2(%eax), %bx
+ movw 4(%eax), %cx
+ movw 6(%eax), %dx
+ movw 8(%eax), %si
+ movw 10(%eax), %di
+ movw 0(%eax), %ax
+
+ lcall _apm_addr /* intersegment call */
+
+ setc cf_result
+ movb %ah, _apm_errno
+ push %eax
+ movl struct_regs, %eax
+ movw %bx, 2(%eax)
+ movw %cx, 4(%eax)
+ movw %dx, 6(%eax)
+ movw %si, 8(%eax)
+ movw %di, 10(%eax)
+ movb cf_result, %bl
+ xorb %bh, %bh
+ movw %bx, 12(%eax)
+ popl %ebx
+ movl %ebx, 0(%eax)
+
+ popl %ecx
+ popl %ebx
+ popl %edi
+ popl %esi
+ leave
+ ret
+
+ .data
+struct_regs:
+ .long 0
+
+cf_result:
+ .byte 0
+
+_apm_errno:
+ .globl _apm_errno
+ .byte 0
+
+ .data
+_apm_init_image:
+ .globl _apm_init_image
+
+1:
+#include "apm_init/apm_init.inc"
+2:
+
+_apm_init_image_size:
+ .globl _apm_init_image_size
+ .long 2b - 1b
+
+_apm_version:
+ .globl _apm_version
+ .long 0
+
+_apm_cs_entry:
+ .globl _apm_cs_entry
+ .long 0
+
+_apm_cs16_base:
+ .globl _apm_cs16_base
+ .word 0
+
+_apm_cs32_base:
+ .globl _apm_cs32_base
+ .word 0
+
+_apm_ds_base:
+ .globl _apm_ds_base
+ .word 0
+
+_apm_cs_limit:
+ .globl _apm_cs_limit
+ .word 0
+
+_apm_ds_limit:
+ .globl _apm_ds_limit
+ .word 0
+
+_apm_flags:
+ .globl _apm_flags
+ .word 0
+
+#endif /* APM */
diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c
new file mode 100644
index 0000000..3660844
--- /dev/null
+++ b/sys/i386/bios/apm.c
@@ -0,0 +1,823 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (c) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include "apm.h"
+
+#if NAPM > 0
+
+#include <sys/param.h>
+#include "conf.h"
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#include <sys/proc.h>
+#include <sys/vnode.h>
+#include "i386/isa/isa.h"
+#include "i386/isa/isa_device.h"
+#include <machine/apm_bios.h>
+#include <machine/segments.h>
+#include <vm/vm.h>
+#include <sys/syslog.h>
+#include "apm_setup.h"
+
+/* static data */
+static int apm_initialized = 0, active = 0, halt_cpu = 1;
+static u_int minorversion, majorversion;
+static u_int cs32_base, cs16_base, ds_base;
+static u_int cs_limit, ds_limit;
+static u_int cs_entry;
+static u_int intversion;
+static int idle_cpu, disabled, disengaged;
+
+/* Map version number to integer (keeps ordering of version numbers) */
+#define INTVERSION(major, minor) ((major)*100 + (minor))
+
+static timeout_t apm_timeout;
+
+/* setup APM GDT discriptors */
+static void
+setup_apm_gdt(u_int code32_base, u_int code16_base, u_int data_base, u_int code_limit, u_int data_limit)
+{
+ /* setup 32bit code segment */
+ gdt_segs[GAPMCODE32_SEL].ssd_base = code32_base;
+ gdt_segs[GAPMCODE32_SEL].ssd_limit = code_limit;
+
+ /* setup 16bit code segment */
+ gdt_segs[GAPMCODE16_SEL].ssd_base = code16_base;
+ gdt_segs[GAPMCODE16_SEL].ssd_limit = code_limit;
+
+ /* setup data segment */
+ gdt_segs[GAPMDATA_SEL ].ssd_base = data_base;
+ gdt_segs[GAPMDATA_SEL ].ssd_limit = data_limit;
+
+ /* reflect these changes on physical GDT */
+ ssdtosd(gdt_segs + GAPMCODE32_SEL, gdt + GAPMCODE32_SEL);
+ ssdtosd(gdt_segs + GAPMCODE16_SEL, gdt + GAPMCODE16_SEL);
+ ssdtosd(gdt_segs + GAPMDATA_SEL , gdt + GAPMDATA_SEL );
+}
+
+/* 48bit far pointer */
+struct addr48 {
+ u_long offset;
+ u_short segment;
+} apm_addr;
+
+
+/* register structure for BIOS call */
+union real_regs {
+ struct xregs {
+ u_short ax;
+ u_short bx __attribute__ ((packed));
+ u_short cx __attribute__ ((packed));
+ u_short dx __attribute__ ((packed));
+ u_short si __attribute__ ((packed));
+ u_short di __attribute__ ((packed));
+ u_short cf __attribute__ ((packed)); /* carry */
+ } x;
+ struct hlregs {
+ u_char al;
+ u_char ah __attribute__ ((packed));
+ u_char bl __attribute__ ((packed));
+ u_char bh __attribute__ ((packed));
+ u_char cl __attribute__ ((packed));
+ u_char ch __attribute__ ((packed));
+ u_char dl __attribute__ ((packed));
+ u_char dh __attribute__ ((packed));
+ u_short si __attribute__ ((packed));
+ u_short di __attribute__ ((packed));
+ u_short cf __attribute__ ((packed)); /* carry */
+ } hl;
+};
+
+
+/* call APM BIOS */
+extern void call_apm(union real_regs* regs);
+
+extern u_char apm_errno;
+
+/* enable/disable power management */
+static int
+apm_enable_disable_pm(int enable)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_ENABLEDISABLEPM;
+ if (intversion >= INTVERSION(1, 1)) {
+ regs.x.bx = PMDV_ALLDEV;
+ }
+ else {
+ regs.x.bx = 0xffff; /* APM version 1.0 only */
+ }
+ regs.x.cx = enable;
+ call_apm(&regs);
+ return regs.x.cf;
+}
+
+/* engage/disengage power management (APM 1.1 or later) */
+static int
+apm_engage_disengage_pm(int engage)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_ENGAGEDISENGAGEPM;
+ regs.x.bx = PMDV_ALLDEV;
+ regs.x.cx = engage;
+ call_apm(&regs);
+ return regs.x.cf;
+}
+
+/* get PM event */
+static u_int
+apm_getevent(void)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_GETPMEVENT;
+ call_apm(&regs);
+ if (regs.x.cf) {
+#if 0
+ printf("No event: errcode = %d\n", apm_errno);
+#endif
+ return PMEV_NOEVENT;
+ }
+ return (u_int)regs.x.bx;
+}
+
+/*
+ * In many cases, the first event that occured after resume, needs
+ * special treatment. This binary flag make this process possible.
+ * Initial value of this variable is 1, because the bootstrap
+ * condition is equivalent to resumed condition for the power
+ * manager.
+ */
+static int resumed_event = 1;
+
+/* suspend entire system */
+static int
+apm_suspend_system(void)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_SETPWSTATE;
+ regs.x.bx = PMDV_ALLDEV;
+ regs.x.cx = PMST_SUSPEND;
+ call_apm(&regs);
+ if (regs.x.cf) {
+ printf("Entire system suspend failure: errcode = %d\n", apm_errno);
+ return 1;
+ }
+ resumed_event = 1;
+
+ return 0;
+}
+
+/* APM Battery low handler */
+static void
+apm_battery_low(void)
+{
+ /* Currently, this routine has not been implemented. Sorry... */
+}
+
+
+/* APM driver calls some functions automatically when the system wakes up */
+static void
+apm_execute_hook(apm_hook_func_t list)
+{
+ apm_hook_func_t p;
+
+ for (p = list; p != NULL; p = p->next) {
+ if ((*(p->func))()) {
+ printf("Warning: APM hook of %s failed", p->name);
+ }
+ }
+}
+
+
+/* APM hook manager */
+static apm_hook_func_t
+apm_hook_init(apm_hook_func_t *list, int (*func)(void), char *name, int order)
+{
+ int pl;
+ apm_hook_func_t p, prev, new_node;
+
+ pl = splhigh();
+ new_node = malloc(sizeof(*new_node), M_DEVBUF, M_NOWAIT);
+ if (new_node == NULL) {
+ panic("Can't allocate device buffer for apm_resume_hook.");
+ }
+ new_node->func = func;
+ new_node->name = name;
+#if 0
+ new_node->next = *list;
+ *list = new_node;
+#else
+ prev = NULL;
+ for (p = *list; p != NULL; prev = p, p = p->next) {
+ if (p->order > order) {
+ break;
+ }
+ }
+
+ if (prev == NULL) {
+ new_node->next = *list;
+ *list = new_node;
+ }
+ else {
+ new_node->next = prev->next;
+ prev->next = new_node;
+ }
+#endif
+ splx(pl);
+ return new_node;
+}
+
+void
+apm_hook_delete(apm_hook_func_t *list, apm_hook_func_t delete_node)
+{
+ int pl;
+ apm_hook_func_t p, prev;
+
+ pl = splhigh();
+ prev = NULL;
+ for (p = *list; p != NULL; prev = p, p = p->next) {
+ if (p == delete_node) {
+ goto deleteit;
+ }
+ }
+ panic("Tried to delete unregistered apm_resume_hook.");
+ goto nosuchnode;
+deleteit:
+ if (prev != NULL) {
+ prev->next = p->next;
+ }
+ else {
+ *list = p->next;
+ }
+ free(delete_node, M_DEVBUF);
+nosuchnode:
+ splx(pl);
+}
+
+static struct timeval suspend_time;
+
+/* default APM hook functions */
+static int
+apm_default_resume(void)
+{
+ u_int second, minute, hour;
+ struct timeval resume_time;
+
+ inittodr(0); /* adjust time to RTC */
+ microtime(&resume_time);
+ second = resume_time.tv_sec - suspend_time.tv_sec;
+ hour = second / 3600;
+ second %= 3600;
+ minute = second / 60;
+ second %= 60;
+ log(LOG_NOTICE, "resumed from suspended mode (slept %02d:%02d:%02d)\n", hour, minute, second);
+ return 0;
+}
+
+static int
+apm_default_suspend(void)
+{
+ int pl;
+#if 0
+ pl = splhigh();
+ sync(curproc, NULL, NULL);
+ splx(pl);
+#endif
+ microtime(&suspend_time);
+ return 0;
+}
+
+/* list structure for hook */
+static apm_hook_func_t apm_resume_hook = NULL;
+static apm_hook_func_t apm_suspend_hook = NULL;
+
+/* execute resume hook */
+static void
+apm_execute_resume_hook(void)
+{
+ apm_execute_hook(apm_resume_hook);
+}
+
+/* add a node on resume hook */
+apm_hook_func_t
+apm_resume_hook_init(int (*func)(void), char *name, int order)
+{
+ return apm_hook_init(&apm_resume_hook, func, name, order);
+}
+
+/* delete a node from resume hook */
+void
+apm_resume_hook_delete(apm_hook_func_t delete_node)
+{
+ apm_hook_delete(&apm_resume_hook, delete_node);
+}
+
+/* execute suspend hook */
+static void
+apm_execute_suspend_hook(void)
+{
+ apm_execute_hook(apm_suspend_hook);
+}
+
+/* add a node on resume hook */
+apm_hook_func_t
+apm_suspend_hook_init(int (*func)(void), char *name, int order)
+{
+ return apm_hook_init(&apm_suspend_hook, func, name, order);
+}
+
+/* delete a node from resume hook */
+void
+apm_suspend_hook_delete(apm_hook_func_t delete_node)
+{
+ apm_hook_delete(&apm_suspend_hook, delete_node);
+}
+
+/* get APM information */
+static int
+apm_get_info(apm_info_t aip)
+{
+ union real_regs regs;
+
+ regs.hl.ah = APM_BIOS;
+ regs.hl.al = APM_GETPWSTATUS;
+ regs.x.bx = PMDV_ALLDEV;
+ call_apm(&regs);
+ if (regs.x.cf) {
+ printf("Get APM info failure: errcode = %d\n", apm_errno);
+ return 1;
+ }
+ aip->ai_major = (u_int)majorversion;
+ aip->ai_minor = (u_int)minorversion;
+ aip->ai_acline = (u_int)regs.hl.bh;
+ aip->ai_batt_stat = (u_int)regs.hl.bl;
+ aip->ai_batt_life = (u_int)regs.hl.cl;
+ return 0;
+}
+
+
+/* Define equivalent event sets */
+
+static int equiv_event_num = 0;
+static struct apm_eqv_event equiv_events[APM_MAX_EQUIV_EVENTS];
+
+static int
+apm_def_eqv(apm_eqv_event_t aee)
+{
+ if (equiv_event_num == APM_MAX_EQUIV_EVENTS) {
+ return 1;
+ }
+ memcpy(&equiv_events[equiv_event_num], aee, sizeof(struct apm_eqv_event));
+ equiv_event_num++;
+ return 0;
+}
+
+static void
+apm_flush_eqv(void)
+{
+ equiv_event_num = 0;
+}
+
+static void apm_processevent(void);
+
+/*
+ * Public interface to the suspend/resume:
+ *
+ * Execute suspend and resume hook before and after sleep, respectively.
+ */
+
+void
+apm_suspend_resume(void)
+{
+ int pl;
+#if 0
+ printf("Called apm_suspend_resume();\n");
+#endif
+ if (apm_initialized) {
+ apm_execute_suspend_hook();
+ apm_suspend_system();
+ apm_execute_resume_hook();
+ apm_processevent();
+ }
+}
+
+/* inform APM BIOS that CPU is idle */
+void
+apm_cpu_idle(void)
+{
+ if (idle_cpu) {
+ if (active) {
+ asm("movw $0x5305, %ax; lcall _apm_addr");
+ }
+ }
+ /*
+ * Some APM implementation halts CPU in BIOS, whenever
+ * "CPU-idle" function are invoked, but swtch() of
+ * FreeBSD halts CPU, therefore, CPU is halted twice
+ * in the sched loop. It makes the interrupt latency
+ * terribly long and be able to cause a serious problem
+ * in interrupt processing. We prevent it by removing
+ * "hlt" operation from swtch() and managed it under
+ * APM driver.
+ */
+ if (!active || halt_cpu) {
+ asm("sti ; hlt"); /* wait for interrupt */
+ }
+}
+
+/* inform APM BIOS that CPU is busy */
+void
+apm_cpu_busy(void)
+{
+ if (idle_cpu && active) {
+ asm("movw $0x5306, %ax; lcall _apm_addr");
+ }
+}
+
+
+/*
+ * APM timeout routine:
+ *
+ * This routine is automatically called by timer two times within one
+ * seconed.
+ */
+
+static void
+apm_timeout(void *arg1)
+{
+#if 0
+ printf("Called apm_timeout\n");
+#endif
+ apm_processevent();
+ timeout(apm_timeout, NULL, hz / 2); /* 2 Hz */
+ /* APM driver must polls APM event a time per second */
+}
+
+/* enable APM BIOS */
+static void
+apm_event_enable(void)
+{
+#if 0
+ printf("called apm_event_enable()\n");
+#endif
+ if (apm_initialized) {
+ active = 1;
+ timeout(apm_timeout, NULL, 2 * hz);
+ }
+}
+
+/* disable APM BIOS */
+static void
+apm_event_disable(void)
+{
+#if 0
+ printf("called apm_event_disable()\n");
+#endif
+ if (apm_initialized) {
+ untimeout(apm_timeout, NULL);
+ active = 0;
+ }
+}
+
+/* halt CPU in scheduling loop */
+static void apm_halt_cpu(void)
+{
+ if (apm_initialized) {
+ halt_cpu = 1;
+ }
+}
+
+/* don't halt CPU in scheduling loop */
+static void apm_not_halt_cpu(void)
+{
+ if (apm_initialized) {
+ halt_cpu = 0;
+ }
+}
+
+/* device driver definitions */
+int apmprobe (struct isa_device *);
+int apmattach(struct isa_device *);
+
+struct isa_driver apmdriver = { apmprobe, apmattach, "apm" };
+
+
+/*
+ * probe APM (dummy):
+ *
+ * APM probing routine is placed on locore.s and apm_init.S because
+ * this process forces the CPU to turn to real mode or V86 mode.
+ * Current version uses real mode, but on future version, we want
+ * to use V86 mode in APM initialization.
+ */
+int
+apmprobe(struct isa_device *dvp)
+{
+ switch (apm_version) {
+ case APMINI_CANTFIND:
+ /* silent */
+ return 0;
+ case APMINI_NOT32BIT:
+ printf("apm%d: 32bit connection is not supported.\n", dvp->id_unit);
+ return 0;
+ case APMINI_CONNECTERR:
+ printf("apm%d: 32-bit connection error.\n", dvp->id_unit);
+ return 0;
+ }
+ return -1;
+}
+
+static const char *
+is_enabled(int enabled)
+{
+ if (enabled) {
+ return "enabled";
+ }
+ return "disabled";
+}
+
+static const char *
+apm_error(void)
+{
+ static char buffer[64];
+
+ switch (apm_errno) {
+ case 0:
+ return "APM OK.";
+ default:
+ sprintf(buffer, "Unknown Error 0x%x", (u_int)apm_errno);
+ return buffer;
+ }
+}
+
+
+
+/* Process APM event */
+static void
+apm_processevent(void)
+{
+ int i, apm_event;
+
+getevent:
+ while (1) {
+ if ((apm_event = apm_getevent()) == PMEV_NOEVENT) {
+ break;
+ }
+#if 0
+#if 1
+#define OPMEV_DEBUGMESSAGE(symbol) case symbol: break;
+#else
+#define OPMEV_DEBUGMESSAGE(symbol) case symbol: printf("Original APM Event: " #symbol "\n"); break
+#endif
+ switch (apm_event) {
+ OPMEV_DEBUGMESSAGE(PMEV_NOEVENT);
+ OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
+ OPMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
+ OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
+ OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
+ OPMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
+ OPMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
+ OPMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
+ OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
+ default:
+ printf("Unknown Original APM Event 0x%x\n", apm_event);
+ break;
+ }
+#endif
+ for (i = 0; i < equiv_event_num; i++) {
+ if (equiv_events[i].aee_event == apm_event) {
+ u_int tmp = PMEV_DEFAULT;
+ if (resumed_event) {
+ tmp = equiv_events[i].aee_resume;
+ }
+ else {
+ tmp = equiv_events[i].aee_equiv;
+ }
+ if (tmp != PMEV_DEFAULT) {
+ apm_event = tmp;
+ break;
+ }
+ }
+ }
+#if 1
+#if 1
+#define PMEV_DEBUGMESSAGE(symbol) case symbol: break;
+#else
+#define PMEV_DEBUGMESSAGE(symbol) case symbol: printf("APM Event: " #symbol "\n"); break
+#endif
+ switch (apm_event) {
+ PMEV_DEBUGMESSAGE(PMEV_NOEVENT);
+ PMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
+ PMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
+ PMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
+ PMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
+ PMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
+ PMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
+ PMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
+ PMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
+ PMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
+ PMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
+ default:
+ printf("Unknown APM Event 0x%x\n", apm_event);
+ break;
+ }
+#endif
+ switch (apm_event) {
+ case PMEV_NOEVENT:
+ case PMEV_STANDBYREQ:
+ case PMEV_POWERSTATECHANGE:
+ case PMEV_CRITSUSPEND:
+ case PMEV_USERSTANDBYREQ:
+ case PMEV_USERSUSPENDREQ:
+ break;
+ case PMEV_BATTERYLOW:
+ apm_battery_low();
+ break;
+ case PMEV_SUSPENDREQ:
+ apm_suspend_resume();
+ break;
+ case PMEV_NORMRESUME:
+ case PMEV_CRITRESUME:
+ case PMEV_UPDATETIME:
+ case PMEV_STANDBYRESUME:
+ inittodr(0); /* adjust time to RTC */
+ break;
+ }
+ }
+ resumed_event = 0;
+}
+
+
+/*
+ * Attach APM:
+ *
+ * Initialize APM driver (APM BIOS itself has been initialized in locore.s)
+ */
+
+int
+apmattach(struct isa_device *dvp)
+{
+
+ /* setup APM parameters */
+ minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0);
+ majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8);
+ intversion = INTVERSION(majorversion, minorversion);
+ cs32_base = (apm_cs32_base << 4) + KERNBASE;
+ cs16_base = (apm_cs16_base << 4) + KERNBASE;
+ ds_base = (apm_ds_base << 4) + KERNBASE;
+ cs_limit = apm_cs_limit;
+ ds_limit = apm_ds_limit;
+ cs_entry = apm_cs_entry;
+ idle_cpu = ((apm_flags & APM_CPUIDLE_SLOW) != 0);
+ disabled = ((apm_flags & APM_DISABLED) != 0);
+ disengaged = ((apm_flags & APM_DISENGAGED) != 0);
+
+ /* print bootstrap messages */
+ printf(" found APM BIOS version %d.%d\n", dvp->id_unit, majorversion, minorversion);
+ printf("apm%d: Code32 0x%08x, Code16 0x%08x, Data 0x%08x\n", dvp->id_unit, cs32_base, cs16_base, ds_base);
+ printf("apm%d: Code entry 0x%08x, Idling CPU %s, Management %s\n", dvp->id_unit, cs_entry, is_enabled(idle_cpu), is_enabled(!disabled));
+
+ /*
+ * APM 1.0 does not have:
+ *
+ * 1. segment limit parameters
+ *
+ * 2. engage/disengage operations
+ */
+ if (intversion >= INTVERSION(1, 1)) {
+ printf("apm%d: Engaged control %s\n", dvp->id_unit, is_enabled(!disengaged));
+ }
+ else {
+ cs_limit = 0xffff;
+ ds_limit = 0xffff;
+ }
+
+ /* setup GDT */
+ setup_apm_gdt(cs32_base, cs16_base, ds_base, cs_limit, ds_limit);
+
+ /* setup entry point 48bit pointer */
+ apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL);
+ apm_addr.offset = cs_entry;
+
+ /* enable power management */
+ if (disabled) {
+ if (apm_enable_disable_pm(1)) {
+ printf("Warning: APM enable function failed! [%s]\n", apm_error());
+ }
+ }
+
+ /* engage power managment (APM 1.1 or later) */
+ if (intversion >= INTVERSION(1, 1) && disengaged) {
+ if (apm_engage_disengage_pm(1)) {
+ printf("Warning: APM engage function failed [%s]\n", apm_error());
+ }
+ }
+
+ apm_suspend_hook_init(apm_default_suspend, "default suspend", APM_MAX_ORDER);
+ apm_resume_hook_init (apm_default_resume , "default resume" , APM_MIN_ORDER);
+ apm_initialized = 1;
+
+ return 0;
+}
+
+int
+apmopen(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ if (!apm_initialized) {
+ return ENXIO;
+ }
+ switch (minor(dev)) {
+ case 0: /* apm0 */
+ break;
+ defaults:
+ return (ENXIO);
+ }
+ return 0;
+}
+
+int
+apmclose(dev_t dev, int flag, int fmt, struct proc *p)
+{
+ return 0;
+}
+
+int
+apmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
+{
+ int error = 0;
+ int pl;
+
+#if 0
+ printf("APM ioctl: minor = %d, cmd = 0x%x\n", minor(dev), cmd);
+#endif
+
+ pl = splhigh();
+ if (minor(dev) != 0) {
+ return ENXIO;
+ }
+ if (!apm_initialized) {
+ return ENXIO;
+ }
+ switch (cmd) {
+ case APMIO_SUSPEND:
+ apm_suspend_resume();
+ break;
+ case APMIO_GETINFO:
+ if (apm_get_info((apm_info_t)addr)) {
+ error = ENXIO;
+ }
+ break;
+ case APMIO_DEFEQV:
+ if (apm_def_eqv((apm_eqv_event_t)addr)) {
+ error = ENOSPC;
+ }
+ break;
+ case APMIO_FLUSHEQV:
+ apm_flush_eqv();
+ break;
+ case APMIO_ENABLE:
+ apm_event_enable();
+ break;
+ case APMIO_DISABLE:
+ apm_event_disable();
+ break;
+ case APMIO_HALTCPU:
+ apm_halt_cpu();
+ break;
+ case APMIO_NOTHALTCPU:
+ apm_not_halt_cpu();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(pl);
+ return error;
+}
+
+#endif /* NAPM > 0 */
diff --git a/sys/i386/bios/apm_init/Makefile b/sys/i386/bios/apm_init/Makefile
new file mode 100644
index 0000000..22d6d60
--- /dev/null
+++ b/sys/i386/bios/apm_init/Makefile
@@ -0,0 +1,50 @@
+#
+# LP (Laptop Package)
+#
+# (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+#
+# This software may be used, modified, copied, and distributed in
+# both source and binary form provided that the above copyright and
+# these terms are retained. Under no circumstances is the author
+# responsible for the proper functioning of this software, nor does
+# the author assume any responsibility for damages incurred with its
+# use.
+#
+# Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+#
+
+OBJS = apm_init.o real_prot.o table.o
+CFLAGS = -DKERNEL -DINITIALIZER
+OPTFLAGS = -O2
+I386INCDIR = ${.CURDIR}/../../include
+INC= -I$(I386INCDIR)
+
+all: apm_init.inc
+
+.SUFFIXES: .c .S .o
+
+.c.o:
+ $(CC) $(CFLAGS) $(OPTFLAGS) $(INC) -c $<
+
+.S.o:
+ $(CC) $(CFLAGS) $(INC) -c $<
+
+apm_init.inc: apm_init bin2asm
+ ./bin2asm apm_init apm_init.inc
+
+apm_init: $(OBJS)
+ $(LD) -Bstatic -N -T 0 -o apm_init $(OBJS)
+ cp apm_init apm_init.sym
+ @strip apm_init
+ @sh ${.CURDIR}/rmaouthdr apm_init apm_init.tmp
+ @mv -f apm_init.tmp apm_init
+
+bin2asm: bin2asm.c
+ $(CC) -o bin2asm ${.CURDIR}/bin2asm.c
+
+allclean: clean
+ @rm -f apm_init.inc
+clean:
+ @rm -f *.o apm_init apm_init.sym bin2asm
+
+.include <bsd.prog.mk>
diff --git a/sys/i386/bios/apm_init/apm_init.S b/sys/i386/bios/apm_init/apm_init.S
new file mode 100644
index 0000000..6c22571
--- /dev/null
+++ b/sys/i386/bios/apm_init/apm_init.S
@@ -0,0 +1,207 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * If you want to know the specification of APM BIOS, see the following
+ * documentations,
+ *
+ * [1] Intel Corporation and Microsoft Corporation, "Advanced Power
+ * Management, The Next Generation, Version 1.0", Feb.,1992.
+ *
+ * [2] Intel Corporation and Microsoft Corporation, "Advanced Power
+ * Management (APM) BIOS Interface Specification Revision 1.1",
+ * Sep.,1993, Intel Order Number: 241704-001, Microsoft Part
+ * Number: 781-110-X01
+ *
+ * or contact
+ *
+ * APM Support Desk (Intel Corporation, US)
+ * TEL: (800)628-8686
+ * FAX: (916)356-6100.
+ */
+
+ .file "apm_init.S"
+
+#define ASM
+
+#include "real_prot.h"
+#include "apm_bios.h"
+#include "apm_segments.h"
+
+/*
+ * APM BIOS initializer
+ *
+ * Return value:
+ * %eax 0xfffffff Can't find APM BIOS
+ * 0xffffffe Don't support 32bit connection
+ * 0xffffffd Connection error
+ * otherwise APM version (16bit BCD format)
+ * %ebx APM cs entry offset (32bit)
+ * %ecx lower 16bit APM 16bit cs base (real mode segment)
+ * upper 16bit APM 32bit cs base (real mode segment)
+ * %edx lower 16bit APM ds limit (real mode segment)
+ * upper 16bit [Reserved]
+ * %esi lower 16bit APM cs limit (APM 1.1 or later)
+ * upper 16bit APM ds limit (APM 1.1 or later)
+ * %edi bit0 = 1 16bit protected mode interface supported
+ * bit1 = 1 32bit protected mode interface supported
+ * bit2 = 1 "CPU idle" call slows processor clock speed
+ * bit3 = 1 APM BIOS Power Management disabled
+ * bit4 = 1 APM BIOS Power Management disengaged
+ */
+
+ .text
+ENTRY(apm_init)
+ cli /* disable interrupt */
+ push %ebp /* save original base pointer */
+ /* ebp is used as a register variable */
+ /*
+ * save old data segments: We assume that %ds == %es && %ds == %ss
+ */
+ push %fs
+ movw %ds, %ax
+ movw %ax, %fs
+ movw $(APM_INIT_DS_SEL), %ax /* initializer data segment */
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %ss
+ movl %esp, old_esp /* save original stack pointer */
+ movl $0x10000, %esp /* setup temporary stack */
+ /* (note that it isn't 0x00000000) */
+
+ sidt EXT(Idtr_prot) /* save current IDT */
+ call EXT(prot_to_real) /* return to real mode */
+
+ /*
+ * APM installation check
+ */
+ movb $(APM_BIOS), %ah
+ movb $(APM_INSTCHECK), %al
+ data32
+ movl $(PMDV_APMBIOS), %ebx
+ sti
+ int $(SYSTEM_BIOS) /* call system BIOS */
+ cli
+
+ jnc 1f /* if found, goto 1f */
+
+ data32
+ call EXT(real_to_prot) /* come back again to protected mode */
+ movl $(APMINI_CANTFIND), apm_version
+ /* can't find APM BIOS */
+ jmp finish
+
+1:
+ movl %eax, %edx /* actually, movw %ax, %dx */
+ /* save the value of %ax */
+ data32
+ call EXT(real_to_prot) /* come back again to protected mode */
+ cmpb $0x50, %bh /* %bh == 'P'? */
+ jnz 1f
+ cmpb $0x4d, %bl /* %bl == 'M'? */
+ jz 2f
+
+1:
+ movl $(APMINI_CANTFIND), apm_version
+ /* can't find APM BIOS */
+ jmp finish
+
+2:
+ testl $(APM_32BIT_SUPPORT), %ecx
+ /* supports 32bit connection? */
+ jnz 1f
+
+ movl $(APMINI_NOT32BIT), apm_version
+ /* don't support 32bit connection */
+ jmp finish
+1:
+ movl %edx, apm_version
+ andl $0x0000ffff, %ecx
+ movl %ecx, apm_flags
+
+ /*
+ * APM Protected Mode 32-bit Interface Connect
+ */
+ call EXT(prot_to_real) /* return to real mode */
+
+ movb $(APM_BIOS), %ah
+ movb $(APM_PROT32CONNECT), %al
+ data32
+ movl $(PMDV_APMBIOS), %ebx
+ sti
+ int $(SYSTEM_BIOS)
+ cli
+ jnc 1f /* if successed, go to 1f */
+ data32
+ call EXT(real_to_prot)
+ movl $(APMINI_CONNECTERR), apm_version
+ /* connection error */
+ jmp finish
+1:
+ /* save PM 32bit code segment into %bp */
+ movl %eax, %ebp /* actually, movw %ax, %bp */
+ data32
+ call EXT(real_to_prot)
+ movl $0x0000ffff, %eax
+ andl %eax, %ebp /* 32bit cs base */
+ andl %eax, %ecx /* 16bit cs base */
+ andl %eax, %edx /* ds base */
+ andl %eax, %esi /* cs length (APM 1.1 or later) */
+ andl %eax, %edi /* ds length (APM 1.1 or later) */
+ /* %ebx is code offset */
+ /* pack 32bit cs and 16bit cs into %ecx */
+ shll $16, %ebp
+ orl %ebp, %ecx
+ /* pack cs length and ds length into %esi */
+ shll $16, %edi
+ orl %edi, %esi
+finish:
+ cli
+ lidt EXT(Idtr_prot) /* restore old IDTR */
+ movl old_esp, %esp /* restore old stack pointer */
+ movl apm_version, %ebp /* stored to %eax later */
+ movl apm_flags, %edi
+#if 0
+ movw $(BOOTSTRAP_DS_SEL), %ax
+ /* restore old data segments */
+#else
+ movw %fs, %ax
+#endif
+ movw %ax, %ss
+ movw %ax, %es
+ movw %ax, %ds
+ movl %ebp, %eax
+ pop %fs
+ popl %ebp /* restore old base pointer */
+ lret /* restore old code segment */
+
+ .data
+
+ .globl EXT(ouraddr)
+LEXT(ouraddr)
+ .long APM_OURADDR
+
+old_esp:
+ .long 0
+apm_version:
+ .long 0
+apm_flags:
+ .long 0
+old_ds:
+ .word 0
+old_es:
+ .word 0
+old_ss:
+ .word 0
diff --git a/sys/i386/bios/apm_init/apm_init.inc b/sys/i386/bios/apm_init/apm_init.inc
new file mode 100644
index 0000000..d241334
--- /dev/null
+++ b/sys/i386/bios/apm_init/apm_init.inc
@@ -0,0 +1,59 @@
+/* This file is automatically generated by bin2asm */
+/* Original file is 'apm_init' */
+
+ .byte 0xfa, 0x55, 0x0f, 0xa0, 0x66, 0x8c, 0xd8, 0x66
+ .byte 0x8e, 0xe0, 0x66, 0xb8, 0xf0, 0x00, 0x66, 0x8e
+ .byte 0xd8, 0x66, 0x8e, 0xc0, 0x66, 0x8e, 0xd0, 0x89
+ .byte 0x25, 0x84, 0x01, 0x00, 0x00, 0xbc, 0x00, 0x00
+ .byte 0x01, 0x00, 0x0f, 0x01, 0x0d, 0xa0, 0x01, 0x00
+ .byte 0x00, 0xe8, 0x12, 0x01, 0x00, 0x00, 0xb4, 0x53
+ .byte 0xb0, 0x00, 0x66, 0xbb, 0x00, 0x00, 0x00, 0x00
+ .byte 0xfb, 0xcd, 0x15, 0xfa, 0x73, 0x15, 0x66, 0xe8
+ .byte 0xcc, 0x00, 0x00, 0x00, 0xc7, 0x05, 0x88, 0x01
+ .byte 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe9, 0x8c
+ .byte 0x00, 0x00, 0x00, 0x89, 0xc2, 0x66, 0xe8, 0xb5
+ .byte 0x00, 0x00, 0x00, 0x80, 0xff, 0x50, 0x75, 0x05
+ .byte 0x80, 0xfb, 0x4d, 0x74, 0x0c, 0xc7, 0x05, 0x88
+ .byte 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xeb
+ .byte 0x6e, 0xf7, 0xc1, 0x02, 0x00, 0x00, 0x00, 0x75
+ .byte 0x0c, 0xc7, 0x05, 0x88, 0x01, 0x00, 0x00, 0xfe
+ .byte 0xff, 0xff, 0xff, 0xeb, 0x5a, 0x89, 0x15, 0x88
+ .byte 0x01, 0x00, 0x00, 0x81, 0xe1, 0xff, 0xff, 0x00
+ .byte 0x00, 0x89, 0x0d, 0x8c, 0x01, 0x00, 0x00, 0xe8
+ .byte 0xa4, 0x00, 0x00, 0x00, 0xb4, 0x53, 0xb0, 0x03
+ .byte 0x66, 0xbb, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xcd
+ .byte 0x15, 0xfa, 0x73, 0x12, 0x66, 0xe8, 0x5e, 0x00
+ .byte 0x00, 0x00, 0xc7, 0x05, 0x88, 0x01, 0x00, 0x00
+ .byte 0xfd, 0xff, 0xff, 0xff, 0xeb, 0x21, 0x89, 0xc5
+ .byte 0x66, 0xe8, 0x4a, 0x00, 0x00, 0x00, 0xb8, 0xff
+ .byte 0xff, 0x00, 0x00, 0x21, 0xc5, 0x21, 0xc1, 0x21
+ .byte 0xc2, 0x21, 0xc6, 0x21, 0xc7, 0xc1, 0xe5, 0x10
+ .byte 0x09, 0xe9, 0xc1, 0xe7, 0x10, 0x09, 0xfe, 0xfa
+ .byte 0x0f, 0x01, 0x1d, 0xa0, 0x01, 0x00, 0x00, 0x8b
+ .byte 0x25, 0x84, 0x01, 0x00, 0x00, 0x8b, 0x2d, 0x88
+ .byte 0x01, 0x00, 0x00, 0x8b, 0x3d, 0x8c, 0x01, 0x00
+ .byte 0x00, 0x66, 0x8c, 0xe0, 0x66, 0x8e, 0xd0, 0x66
+ .byte 0x8e, 0xc0, 0x66, 0x8e, 0xd8, 0x89, 0xe8, 0x0f
+ .byte 0xa1, 0x5d, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0xfa, 0x0f, 0x20, 0xc0, 0x66, 0x83, 0xc8, 0x01
+ .byte 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x23, 0x01, 0x00
+ .byte 0x00, 0xe8, 0x00, 0xb8, 0xf0, 0x00, 0x00, 0x00
+ .byte 0x66, 0x8e, 0xd8, 0x66, 0x8e, 0xd0, 0x66, 0x8e
+ .byte 0xc0, 0x0f, 0x01, 0x1d, 0xa0, 0x01, 0x00, 0x00
+ .byte 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0xa1, 0x80, 0x01, 0x00, 0x00, 0xc1, 0xf8, 0x04
+ .byte 0x66, 0x50, 0x66, 0xb8, 0x62, 0x01, 0x66, 0x50
+ .byte 0xea, 0x57, 0x01, 0x00, 0x00, 0xf8, 0x00, 0x0f
+ .byte 0x20, 0xc0, 0x66, 0x83, 0xe0, 0xfe, 0x0f, 0x22
+ .byte 0xc0, 0xcb, 0x66, 0x8c, 0xc8, 0x66, 0x8e, 0xd8
+ .byte 0x66, 0x8e, 0xd0, 0x66, 0x8e, 0xc0, 0x67, 0x66
+ .byte 0x0f, 0x01, 0x1d, 0xa6, 0x01, 0x00, 0x00, 0x66
+ .byte 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03
+ .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+/* Total size = 0x01b0 */
diff --git a/sys/i386/bios/apm_init/bin2asm.c b/sys/i386/bios/apm_init/bin2asm.c
new file mode 100644
index 0000000..b826e68
--- /dev/null
+++ b/sys/i386/bios/apm_init/bin2asm.c
@@ -0,0 +1,64 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include <stdio.h>
+
+#define NCOLS 8
+
+int main(int argc, char *argv[])
+{
+ int c, col;
+ FILE *infile, *outfile;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s infile outfile\n", argv[0]);
+ exit(1);
+ }
+
+ if ((infile = fopen(argv[1], "rb")) == NULL) {
+ fprintf(stderr, "Can't open %s.\n", argv[1]);
+ exit(1);
+ }
+
+ if ((outfile = fopen(argv[2], "wb")) == NULL) {
+ fprintf(stderr, "Can't open %s.\n", argv[2]);
+ exit(1);
+ }
+
+ col = 0;
+
+ fprintf(outfile, "/* This file is automatically generated by bin2asm */\n");
+ fprintf(outfile, "/* Original file is '%s' */\n\n", argv[1]);
+
+ while ((c = fgetc(infile)) != EOF) {
+ if (col % NCOLS == 0) {
+ fprintf(outfile, "\t.byte\t");
+ }
+ fprintf(outfile, "0x%02x", c);
+ if (col % NCOLS == NCOLS - 1) {
+ fprintf(outfile, "\n");
+ }
+ else {
+ fprintf(outfile, ", ");
+ }
+ col++;
+ }
+
+ fprintf(outfile, "\n/* Total size = 0x%04x */\n", col);
+
+ fclose(infile);
+ fclose(outfile);
+ return 0;
+}
diff --git a/sys/i386/bios/apm_init/real_prot.S b/sys/i386/bios/apm_init/real_prot.S
new file mode 100644
index 0000000..d61a394
--- /dev/null
+++ b/sys/i386/bios/apm_init/real_prot.S
@@ -0,0 +1,185 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992, 1991 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.2 92/04/04 11:34:13 rpd
+ * $Id: asm.S,v 1.2 1993/10/16 19:11:27 rgrimes Exp $
+ */
+
+
+/*
+ Copyright 1988, 1989, 1990, 1991, 1992
+ by Intel Corporation, Santa Clara, California.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appears in all
+copies and that both the copyright notice and this permission notice
+appear in supporting documentation, and that the name of Intel
+not be used in advertising or publicity pertaining to distribution
+of the software without specific, written prior permission.
+
+INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
+IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
+NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * Modified for APM BIOS initializer by HOSOKAWA Tatsumi
+ *
+ * See also locore.s. It supports these functions works correctly.
+ */
+
+ .file "real_prot.S"
+
+#include "real_prot.h"
+#include "apm_segments.h"
+
+CR0_PE_ON = 0x1
+CR0_PE_OFF = 0xfffffffe
+
+.globl _ouraddr
+ .text
+
+/*
+ *
+ * real_to_prot()
+ * transfer from real mode to protected mode.
+ */
+
+ENTRY(real_to_prot)
+ /* guarantee that interrupt is disabled when in prot mode */
+ cli
+
+ /*
+ * deleted for APM initializer by HOSOKAWA Tatsumi
+ * <hosoakwa@mt.cs.keio.ac.jp>
+ */
+#if 0
+ /* load the gdtr */
+ addr32
+ data32
+ lgdt EXT(Gdtr)
+#endif
+
+ /* set the PE bit of CR0 */
+ mov %cr0, %eax
+
+ data32
+ or $CR0_PE_ON, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intrasegment jump to flush the processor pipeline and
+ * reload CS register
+ */
+ data32
+ ljmp $(APM_INIT_CS_SEL), $xprot
+
+xprot:
+ /*
+ * we are in USE32 mode now
+ * set up the protected mode segment registers : DS, SS, ES
+ */
+ mov $(APM_INIT_DS_SEL), %eax
+ movw %ax, %ds
+ movw %ax, %ss
+ movw %ax, %es
+
+ /* load idtr so we can debug */
+ lidt EXT(Idtr_prot)
+
+ ret
+
+/*
+ *
+ * prot_to_real()
+ * transfer from protected mode to real mode
+ *
+ */
+
+ENTRY(prot_to_real)
+
+ /* set up a dummy stack frame for the second seg change. */
+ movl _ouraddr, %eax
+ sarl $4, %eax
+ pushw %ax
+ movw $xreal, %ax /* gas botches pushw $xreal - extra bytes 0, 0*/
+ pushw %ax /* decode to add %al, (%eax) (%al usually 0) */
+
+ /* Change to use16 mode. */
+ ljmp $(APM_INIT_CS16_SEL), $x16
+
+x16:
+ /* clear the PE bit of CR0 */
+ mov %cr0, %eax
+ data32
+ and $CR0_PE_OFF, %eax
+ mov %eax, %cr0
+
+ /*
+ * make intersegment jmp to flush the processor pipeline
+ * using the fake stack frame set up earlier
+ * and reload CS register
+ */
+ lret
+
+xreal:
+ /*
+ * we are in real mode now
+ * set up the real mode segment registers : DS, SS, ES
+ */
+ movw %cs, %ax
+ movw %ax, %ds
+ movw %ax, %ss
+ movw %ax, %es
+
+ /* load idtr so we can debug */
+ addr32
+ data32
+ lidt EXT(Idtr_real)
+
+ data32
+ ret
diff --git a/sys/i386/bios/apm_init/real_prot.h b/sys/i386/bios/apm_init/real_prot.h
new file mode 100644
index 0000000..bc02200
--- /dev/null
+++ b/sys/i386/bios/apm_init/real_prot.h
@@ -0,0 +1,56 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ *
+ * from: Mach, Revision 2.7 92/02/29 15:33:41 rpd
+ * $Id: asm.h,v 1.3 1993/10/16 19:11:29 rgrimes Exp $
+ */
+
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+/*
+ * Modified to APM BIOS initializer by HOSOKAWA, Tatsumi
+ */
+
+#define ALIGN 4
+#define EXT(x) _ ## x
+#define LEXT(x) _ ## x ## :
+
+#define addr32 .byte 0x67
+#define data32 .byte 0x66
+
+#define ENTRY(x) .globl EXT(x); .align ALIGN; LEXT(x)
diff --git a/sys/i386/bios/apm_init/rmaouthdr b/sys/i386/bios/apm_init/rmaouthdr
new file mode 100644
index 0000000..47838b0
--- /dev/null
+++ b/sys/i386/bios/apm_init/rmaouthdr
@@ -0,0 +1,6 @@
+#!/bin/csh -f
+#
+# from: Mach, Revision 2.2 92/04/04 11:36:01 rpd
+# $Id: rmaouthdr,v 1.3 1993/10/16 19:11:37 rgrimes Exp $
+#
+dd if=$1 of=$2 ibs=32 skip=1 obs=1024b
diff --git a/sys/i386/bios/apm_init/table.c b/sys/i386/bios/apm_init/table.c
new file mode 100644
index 0000000..eaf2fc6
--- /dev/null
+++ b/sys/i386/bios/apm_init/table.c
@@ -0,0 +1,24 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, and distributed, in
+ * both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#include <apm_bios.h>
+
+struct pseudo_desc {
+ unsigned short limit;
+ unsigned long base __attribute__ ((packed));
+};
+
+struct pseudo_desc Idtr_prot = { 0, 0 }; /* filled on run time */
+struct pseudo_desc Idtr_real = { 0x400 - 1, 0x0 };
diff --git a/sys/i386/bios/apm_setup.h b/sys/i386/bios/apm_setup.h
new file mode 100644
index 0000000..0009e56
--- /dev/null
+++ b/sys/i386/bios/apm_setup.h
@@ -0,0 +1,23 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, distributed, and sold,
+ * in both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+extern u_long apm_version;
+extern u_long apm_cs_entry;
+extern u_short apm_cs32_base;
+extern u_short apm_cs16_base;
+extern u_short apm_ds_base;
+extern u_short apm_cs_limit;
+extern u_short apm_ds_limit;
+extern u_short apm_flags;
diff --git a/sys/i386/bios/apm_setup.s b/sys/i386/bios/apm_setup.s
new file mode 100644
index 0000000..df1e9c9
--- /dev/null
+++ b/sys/i386/bios/apm_setup.s
@@ -0,0 +1,126 @@
+/*
+ * LP (Laptop Package)
+ *
+ * Copyright (C) 1994 by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ *
+ * This software may be used, modified, copied, distributed, and sold,
+ * in both source and binary form provided that the above copyright and
+ * these terms are retained. Under no circumstances is the author
+ * responsible for the proper functioning of this software, nor does
+ * the author assume any responsibility for damages incurred with its
+ * use.
+ *
+ * Sep., 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD)
+ */
+
+#ifdef APM
+
+#define ASM
+
+#include <machine/asmacros.h>
+#include "assym.s"
+#include <machine/apm_bios.h>
+
+ .file "apm_setup.s"
+
+ .text
+
+ /* void call_apm(union real_regs *); */
+_call_apm:
+ .globl _call_apm
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+ pushl %edi
+ pushl %ebx
+ pushl %ecx
+
+ movl 8(%ebp), %eax
+ movl %eax, struct_regs
+ movw 2(%eax), %bx
+ movw 4(%eax), %cx
+ movw 6(%eax), %dx
+ movw 8(%eax), %si
+ movw 10(%eax), %di
+ movw 0(%eax), %ax
+
+ lcall _apm_addr /* intersegment call */
+
+ setc cf_result
+ movb %ah, _apm_errno
+ push %eax
+ movl struct_regs, %eax
+ movw %bx, 2(%eax)
+ movw %cx, 4(%eax)
+ movw %dx, 6(%eax)
+ movw %si, 8(%eax)
+ movw %di, 10(%eax)
+ movb cf_result, %bl
+ xorb %bh, %bh
+ movw %bx, 12(%eax)
+ popl %ebx
+ movl %ebx, 0(%eax)
+
+ popl %ecx
+ popl %ebx
+ popl %edi
+ popl %esi
+ leave
+ ret
+
+ .data
+struct_regs:
+ .long 0
+
+cf_result:
+ .byte 0
+
+_apm_errno:
+ .globl _apm_errno
+ .byte 0
+
+ .data
+_apm_init_image:
+ .globl _apm_init_image
+
+1:
+#include "apm_init/apm_init.inc"
+2:
+
+_apm_init_image_size:
+ .globl _apm_init_image_size
+ .long 2b - 1b
+
+_apm_version:
+ .globl _apm_version
+ .long 0
+
+_apm_cs_entry:
+ .globl _apm_cs_entry
+ .long 0
+
+_apm_cs16_base:
+ .globl _apm_cs16_base
+ .word 0
+
+_apm_cs32_base:
+ .globl _apm_cs32_base
+ .word 0
+
+_apm_ds_base:
+ .globl _apm_ds_base
+ .word 0
+
+_apm_cs_limit:
+ .globl _apm_cs_limit
+ .word 0
+
+_apm_ds_limit:
+ .globl _apm_ds_limit
+ .word 0
+
+_apm_flags:
+ .globl _apm_flags
+ .word 0
+
+#endif /* APM */
diff --git a/sys/i386/conf/Makefile.i386 b/sys/i386/conf/Makefile.i386
index 097d688..b4f6efc 100644
--- a/sys/i386/conf/Makefile.i386
+++ b/sys/i386/conf/Makefile.i386
@@ -1,6 +1,6 @@
# Copyright 1990 W. Jolitz
# from: @(#)Makefile.i386 7.1 5/10/91
-# $Id: Makefile.i386,v 1.38 1994/09/23 07:01:59 phk Exp $
+# $Id: Makefile.i386,v 1.39 1994/09/29 14:02:40 csgr Exp $
#
# Makefile for FreeBSD
#
@@ -66,7 +66,7 @@ DRIVER_C= ${CC} -c ${CFLAGS} ${PROF} $<
DRIVER_C_C= ${CC} -c ${CFLAGS} ${PROF} ${PARAM} $<
SFILES= ${I386}/i386/exception.s ${I386}/i386/microtime.s \
- ${I386}/i386/support.s ${I386}/i386/swtch.s
+ ${I386}/i386/support.s ${I386}/i386/swtch.s ${I386}/apm/apm_setup.s
SYSTEM_CFILES= ioconf.c param.c vnode_if.c
SYSTEM_SFILES= ${I386}/i386/locore.s
SYSTEM_OBJS=locore.o vnode_if.o ${OBJS} ioconf.o param.o
diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386
index 5ccdaab..c08c577 100644
--- a/sys/i386/conf/files.i386
+++ b/sys/i386/conf/files.i386
@@ -1,8 +1,10 @@
# This file tells config what files go into building a kernel,
# files marked standard are always included.
#
-# $Id: files.i386,v 1.49 1994/09/26 16:15:06 jkh Exp $
+# $Id: files.i386,v 1.50 1994/10/01 02:36:24 swallace Exp $
#
+i386/apm/apm.c optional apm device-driver
+i386/apm/apm_setup.s optional apm
i386/i386/autoconf.c standard device-driver
i386/i386/conf.c standard
i386/i386/cons.c standard
diff --git a/sys/i386/i386/conf.c b/sys/i386/i386/conf.c
index 121e4b7..181c976 100644
--- a/sys/i386/i386/conf.c
+++ b/sys/i386/i386/conf.c
@@ -41,7 +41,7 @@
* SUCH DAMAGE.
*
* from: @(#)conf.c 5.8 (Berkeley) 5/12/91
- * $Id: conf.c,v 1.34 1994/09/28 22:44:35 wollman Exp $
+ * $Id: conf.c,v 1.35 1994/09/29 08:59:33 sos Exp $
*/
#include <sys/param.h>
@@ -533,6 +533,17 @@ d_open_t lkmcopen;
d_close_t lkmcclose;
d_ioctl_t lkmcioctl;
+#include "apm.h"
+#if NAPM > 0
+d_open_t apmopen;
+d_close_t apmclose;
+d_ioctl_t apmioctl;
+#else
+#define apmopen (d_open_t *)enxio
+#define apmclose (d_close_t *)enxio
+#define apmioctl (d_ioctl_t *)enxio
+#endif
+
#define noopen (d_open_t *)enodev
#define noclose (d_close_t *)enodev
#define noread (d_rdwr_t *)enodev
@@ -671,8 +682,11 @@ struct cdevsw cdevsw[] =
{ lkmopen, lkmclose, lkmread, lkmwrite, /*38*/
lkmioctl, lkmstop, lkmreset, NULL,
lkmselect, lkmmmap, NULL },
- /* character device 39 is reserved for local use */
- { (d_open_t *)enxio, (d_close_t *)enxio, (d_rdwr_t *)enxio, /*39*/
+ { apmopen, apmclose, noread, nowrite, /*39*/
+ apmioctl, nostop, nullreset, NULL, /* laptop APM */
+ seltrue, nommap, NULL },
+ /* character device 40 is reserved for local use */
+ { (d_open_t *)enxio, (d_close_t *)enxio, (d_rdwr_t *)enxio, /*40*/
(d_rdwr_t *)enxio, (d_ioctl_t *)enxio, (d_stop_t *)enxio,
(d_reset_t *)enxio, NULL, (d_select_t *)enxio,
(d_mmap_t *)enxio, NULL }
diff --git a/sys/i386/i386/locore.s b/sys/i386/i386/locore.s
index 72973aa..bc7b854 100644
--- a/sys/i386/i386/locore.s
+++ b/sys/i386/i386/locore.s
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)locore.s 7.3 (Berkeley) 5/13/91
- * $Id: locore.s,v 1.28 1994/09/15 07:26:31 sos Exp $
+ * $Id: locore.s,v 1.29 1994/09/26 16:56:22 pst Exp $
*/
/*
@@ -54,6 +54,11 @@
#include <machine/cputypes.h> /* x86 cpu type definitions */
#include <sys/syscall.h> /* system call numbers */
#include <machine/asmacros.h> /* miscellaneous asm macros */
+#ifdef APM
+#define ASM
+#include <machine/apm_bios.h>
+#include <machine/apm_segments.h>
+#endif
/*
* XXX
@@ -130,7 +135,15 @@ _proc0paddr: .long 0 /* address of proc 0 address space */
.globl _bdb_exists /* flag to indicate BDE debugger is available */
_bdb_exists: .long 0
#endif
-
+#ifdef APM
+ .globl _apm_current_gdt_pdesc /* current GDT pseudo desc. */
+_apm_current_gdt_pdesc:
+ .byte 0, 0, 0
+
+ .globl _bootstrap_gdt
+_bootstrap_gdt:
+ .space SIZEOF_GDT * BOOTSTRAP_GDT_NUM
+#endif /* APM */
.globl tmpstk
.space 0x1000
tmpstk:
@@ -195,6 +208,89 @@ NON_GPROF_ENTRY(btext)
rep
movsb
#endif
+#ifdef APM
+ /*
+ * Setup APM BIOS:
+ *
+ * APM BIOS initialization should be done from real mode or V86 mode.
+ *
+ * (by HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>)
+ */
+
+ /*
+ * Copy APM initializer under 1MB boundary:
+ *
+ * APM initializer program must switch the CPU to real mode.
+ * But FreeBSD kernel runs above 1MB boundary. So we must
+ * copy the initializer code to conventional memory.
+ */
+ movl _apm_init_image_size-KERNBASE, %ecx /* size */
+ lea _apm_init_image-KERNBASE, %esi /* source */
+ movl $ APM_OURADDR, %edi /* destination */
+ cld
+ rep
+ movsb
+
+ /* get GDT base */
+ sgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* copy GDT to _bootstrap_gdt */
+ xorl %ecx, %ecx
+ movw _apm_current_gdt_pdesc-KERNBASE, %cx
+ movl _apm_current_gdt_pdesc-KERNBASE+2, %esi
+ lea _bootstrap_gdt-KERNBASE, %edi
+ cld
+ rep
+ movsb
+
+ /* setup GDT pseudo descriptor */
+ movw $(SIZEOF_GDT*BOOTSTRAP_GDT_NUM), %ax
+ movw %ax, _apm_current_gdt_pdesc-KERNBASE
+ leal _bootstrap_gdt-KERNBASE, %eax
+ movl %eax, _apm_current_gdt_pdesc-KERNBASE+2
+
+ /* load new GDTR */
+ lgdt _apm_current_gdt_pdesc-KERNBASE
+
+ /* setup GDT for APM initializer */
+ lea _bootstrap_gdt-KERNBASE, %ecx
+ movl $(APM_OURADDR), %eax /* use %ax for 15..0 */
+ movl %eax, %ebx
+ shrl $16, %ebx /* use %bl for 23..16 */
+ /* use %bh for 31..24 */
+#define APM_SETUP_GDT(index, attrib) \
+ movl $(index), %si ; \
+ lea 0(%ecx,%esi,8), %edx ; \
+ movw $0xffff, (%edx) ; \
+ movw %ax, 2(%edx) ; \
+ movb %bl, 4(%edx) ; \
+ movw $(attrib), 5(%edx) ; \
+ movb %bh, 7(%edx)
+
+ APM_SETUP_GDT(APM_INIT_CS_INDEX , CS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_DS_INDEX , DS32_ATTRIB)
+ APM_SETUP_GDT(APM_INIT_CS16_INDEX, CS16_ATTRIB)
+
+ /*
+ * Call the initializer:
+ *
+ * direct intersegment call to conventional memory code
+ */
+ .byte 0x9a /* actually, lcall $APM_INIT_CS_SEL, $0 */
+ .long 0
+ .word APM_INIT_CS_SEL
+
+ movw %ax, _apm_version-KERNBASE
+ movl %ebx, _apm_cs_entry-KERNBASE
+ movw %cx, _apm_cs32_base-KERNBASE
+ shrl $16, %ecx
+ movw %cx, _apm_cs16_base-KERNBASE
+ movw %dx, _apm_ds_base-KERNBASE
+ movw %si, _apm_cs_limit-KERNBASE
+ shrl $16, %esi
+ movw %si, _apm_ds_limit-KERNBASE
+ movw %di, _apm_flags-KERNBASE
+#endif /* APM */
/* Find out our CPU type. */
diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c
index 46df0ca..3242846 100644
--- a/sys/i386/i386/machdep.c
+++ b/sys/i386/i386/machdep.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)machdep.c 7.4 (Berkeley) 6/3/91
- * $Id: machdep.c,v 1.65 1994/09/16 05:46:54 phk Exp $
+ * $Id: machdep.c,v 1.66 1994/09/24 12:22:47 davidg Exp $
*/
#include "npx.h"
@@ -1012,7 +1012,7 @@ struct soft_segment_descriptor gdt_segs[] = {
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
/* User LDT Descriptor per process */
-{ (int) ldt, /* segment base address */
+{ (int) ldt, /* segment base address */
(512 * sizeof(union descriptor)-1), /* length */
SDT_SYSLDT, /* segment type */
0, /* segment descriptor priority level */
@@ -1020,6 +1020,60 @@ struct soft_segment_descriptor gdt_segs[] = {
0, 0,
0, /* unused - default 32 vs 16 bit size */
0 /* limit granularity (byte/page units)*/ },
+#ifdef APM
+ /* APM BIOS 32-bit interface (32bit Code) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMERA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+ /* APM BIOS 32-bit interface (16bit Code) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMERA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 0, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+ /* APM BIOS 32-bit interface (Data) */
+{ 0, /* segment base address (overwritten by APM) */
+ 0xffff, /* length */
+ SDT_MEMRWA, /* segment type */
+ 0, /* segment descriptor priority level */
+ 1, /* segment descriptor present */
+ 0, 0,
+ 1, /* default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+#else /* APM */
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+{ 0, /* segment base address */
+ 0, /* length */
+ 0, /* segment type */
+ 0, /* segment descriptor priority level */
+ 0, /* segment descriptor present */
+ 0, 0,
+ 0, /* unused - default 32 vs 16 bit size */
+ 0 /* limit granularity (byte/page units)*/ },
+#endif /* APMBIOS */
};
struct soft_segment_descriptor ldt_segs[] = {
@@ -1103,6 +1157,22 @@ extern idtvec_t
int _gsel_tss;
+/* added sdtossd() by HOSOKAWA Tatsumi <hosokawa@mt.cs.keio.ac.jp> */
+int
+sdtossd(sd, ssd)
+ struct segment_descriptor *sd;
+ struct soft_segment_descriptor *ssd;
+{
+ ssd->ssd_base = (sd->sd_hibase << 24) | sd->sd_lobase;
+ ssd->ssd_limit = (sd->sd_hilimit << 16) | sd->sd_lolimit;
+ ssd->ssd_type = sd->sd_type;
+ ssd->ssd_dpl = sd->sd_dpl;
+ ssd->ssd_p = sd->sd_p;
+ ssd->ssd_def32 = sd->sd_def32;
+ ssd->ssd_gran = sd->sd_gran;
+ return 0;
+}
+
void
init386(first)
int first;
diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s
index 7031c64..ad83a9a 100644
--- a/sys/i386/i386/swtch.s
+++ b/sys/i386/i386/swtch.s
@@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: swtch.s,v 1.12 1994/09/01 05:12:18 davidg Exp $
+ * $Id: swtch.s,v 1.13 1994/09/02 05:58:51 davidg Exp $
*/
#include "npx.h" /* for NNPX */
@@ -204,8 +204,13 @@ idle_loop:
jne sw1a
cmpl $0,_whichqs
jne nortqr
+#ifdef APM
+ call _apm_cpu_idle
+ call _apm_cpu_busy
+#else
sti
hlt /* wait for interrupt */
+#endif
jmp idle_loop
badsw:
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 49b4ffd..fcaa6e9 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.33 1994/09/08 11:48:52 bde Exp $
+ * $Id: trap.c,v 1.34 1994/09/11 11:26:18 davidg Exp $
*/
/*
@@ -459,10 +459,12 @@ trap_fatal(frame)
struct trapframe *frame;
{
int code, type, eva;
+ struct soft_segment_descriptor softseg;
code = frame->tf_err;
type = frame->tf_trapno;
eva = rcr2();
+ sdtossd(gdt + IDXSEL(frame->tf_cs & 0xffff), &softseg);
if (type <= MAX_TRAP_MSG)
printf("\n\nFatal trap %d: %s while in %s mode\n",
@@ -475,7 +477,11 @@ trap_fatal(frame)
code & PGEX_W ? "write" : "read",
code & PGEX_P ? "protection violation" : "page not present");
}
- printf("instruction pointer = 0x%x\n", frame->tf_eip);
+ printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip);
+ printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n",
+ softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
+ printf(" = DPL %d, pres %d, def32 %d, gran %d\n",
+ softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran);
printf("processor eflags = ");
if (frame->tf_eflags & PSL_T)
printf("trace/trap, ");
diff --git a/sys/i386/include/console.h b/sys/i386/include/console.h
index 209baa4..ad441e1 100644
--- a/sys/i386/include/console.h
+++ b/sys/i386/include/console.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: console.h,v 1.10 1994/09/15 07:26:04 sos Exp $
+ * $Id: console.h,v 1.11 1994/09/29 08:31:39 sos Exp $
*/
#ifndef _CONSOLE_H_
@@ -218,6 +218,7 @@ typedef struct ssaver ssaver_t;
#define META 0x7f /* meta key */
#define RBT 0x80 /* boot machine */
#define DBG 0x81 /* call debugger */
+#define SUSP 0x82 /* suspend power (APM BIOS) */
#define F(x) ((x)+F_FN-1)
#define S(x) ((x)+F_SCR-1)
diff --git a/sys/i386/include/segments.h b/sys/i386/include/segments.h
index 023a0cf..0e996e6 100644
--- a/sys/i386/include/segments.h
+++ b/sys/i386/include/segments.h
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)segments.h 7.1 (Berkeley) 5/9/91
- * $Id: segments.h,v 1.3 1993/11/07 17:43:08 wollman Exp $
+ * $Id: segments.h,v 1.4 1994/01/31 10:27:13 davidg Exp $
*/
#ifndef _MACHINE_SEGMENTS_H_
@@ -211,7 +211,11 @@ struct region_descriptor {
#define GPANIC_SEL 5 /* Task state to consider panic from */
#define GPROC0_SEL 6 /* Task state process slot zero and up */
#define GUSERLDT_SEL 7 /* User LDT */
-#define NGDT GUSERLDT_SEL+1
+#define GAPMCODE32_SEL 8 /* APM BIOS 32-bit interface (32bit Code) */
+#define GAPMCODE16_SEL 9 /* APM BIOS 32-bit interface (16bit Code) */
+#define GAPMDATA_SEL 10 /* APM BIOS 32-bit interface (Data) */
+
+#define NGDT (GAPMDATA_SEL+1)
/*
* Entries in the Local Descriptor Table (LDT)
diff --git a/sys/i386/isa/icu.h b/sys/i386/isa/icu.h
index 5cecf65..a68269b 100644
--- a/sys/i386/isa/icu.h
+++ b/sys/i386/isa/icu.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)icu.h 5.6 (Berkeley) 5/9/91
- * $Id: icu.h,v 1.5 1994/09/18 23:08:56 bde Exp $
+ * $Id: icu.h,v 1.6 1994/09/18 23:18:32 bde Exp $
*/
/*
@@ -52,9 +52,10 @@
*/
extern unsigned imen; /* interrupt mask enable */
-#define INTREN(s) (imen &= ~(s), SET_ICUS())
-#define INTRDIS(s) (imen |= (s), SET_ICUS())
-#define INTRMASK(msk,s) (msk |= (s))
+#define INTREN(s) (imen &= ~(s), SET_ICUS())
+#define INTRDIS(s) (imen |= (s), SET_ICUS())
+#define INTRMASK(msk,s) (msk |= (s))
+#define INTRUNMASK(msk,s) (msk &= ~(s))
#if 0
#define SET_ICUS() (outb(IO_ICU1 + 1, imen), outb(IU_ICU2 + 1, imen >> 8))
#else
diff --git a/sys/i386/isa/if_ze.c b/sys/i386/isa/if_ze.c
index 207ed70..3a16263 100644
--- a/sys/i386/isa/if_ze.c
+++ b/sys/i386/isa/if_ze.c
@@ -36,6 +36,11 @@
* of this software, nor does the author assume any responsibility
* for damages incurred with its use.
*/
+/*
+ * I doubled delay loops in this file because it is not enough for some
+ * laptop machines' PCIC (especially, on my Chaplet ILFA 350 ^^;).
+ * HOSOKAWA, Tatsumi <hosokawa@mt.cs.keio.ac.jp>
+ */
#include "ze.h"
#if NZE > 0
@@ -77,6 +82,9 @@
#include "i386/isa/icu.h"
#include "i386/isa/if_zereg.h"
+#ifdef APM
+#include "i386/include/apm_bios.h"
+#endif /* APM */
/*****************************************************************************
@@ -368,7 +376,7 @@ pcic_power_on (int slot)
{
pcic_putb (slot, PCIC_POWER,
pcic_getb (slot, PCIC_POWER) | PCIC_DISRST | PCIC_PCPWRE);
- DELAY (50000);
+ DELAY (100000);
pcic_putb (slot, PCIC_POWER,
pcic_getb (slot, PCIC_POWER) | PCIC_OUTENA);
}
@@ -379,7 +387,7 @@ pcic_reset (int slot)
/* assert RESET (by clearing a bit!), wait a bit, and de-assert it */
pcic_putb (slot, PCIC_INT_GEN,
pcic_getb (slot, PCIC_INT_GEN) & ~PCIC_CARDRESET);
- DELAY (50000);
+ DELAY (100000);
pcic_putb (slot, PCIC_INT_GEN,
pcic_getb (slot, PCIC_INT_GEN) | PCIC_CARDRESET);
}
@@ -424,6 +432,8 @@ struct ze_softc {
u_char rec_page_start; /* first page of RX ring-buffer */
u_char rec_page_stop; /* last page of RX ring-buffer */
u_char next_packet; /* pointer to next unread RX packet */
+ u_char last_alive; /* information for reconfiguration */
+ u_char last_up; /* information for reconfiguration */
} ze_softc[NZE];
int ze_attach(), ze_ioctl(), ze_probe();
@@ -502,7 +512,7 @@ ze_check_cis (unsigned char *scratch)
*/
static int
-ze_find_adapter (unsigned char *scratch)
+ze_find_adapter (unsigned char *scratch, int reconfig)
{
int slot;
@@ -523,7 +533,9 @@ ze_find_adapter (unsigned char *scratch)
continue;
}
if ((pcic_getb (slot, PCIC_STATUS) & PCIC_CD) != PCIC_CD) {
- printf ("ze: slot %d: no card in slot\n", slot);
+ if (!reconfig) {
+ printf ("ze: slot %d: no card in slot\n", slot);
+ }
/* no card in slot */
continue;
}
@@ -539,11 +551,16 @@ ze_find_adapter (unsigned char *scratch)
if ((ze_check_cis (scratch)) > 0) {
/* found it */
- printf ("ze: found card in slot %d\n", slot);
+ if (!reconfig) {
+ printf ("ze: found card in slot %d\n", slot);
+ }
return slot;
}
- else
- printf ("ze: pcmcia slot %d: %s\n", slot, card_info);
+ else {
+ if (!reconfig) {
+ printf ("ze: pcmcia slot %d: %s\n", slot, card_info);
+ }
+ }
pcic_unmap_memory (slot, 0);
}
return -1;
@@ -577,7 +594,7 @@ ze_probe(isa_dev)
u_char iptr, memwidth, sum, tmp;
int slot;
- if ((slot = ze_find_adapter (isa_dev->id_maddr)) < 0)
+ if ((slot = ze_find_adapter (isa_dev->id_maddr, isa_dev->id_reconfig)) < 0)
return NULL;
/*
@@ -627,7 +644,7 @@ ze_probe(isa_dev)
pcic_map_memory (slot, 0, kvtop (isa_dev->id_maddr), 0x20000, 8L,
ATTRIBUTE, 1);
POKE(isa_dev->id_maddr, 0x80); /* reset the card (how long?) */
- DELAY (10000);
+ DELAY (40000);
/*
* Set the configuration index. According to [1], the adapter won't
* respond to any i/o signals until we do this; it uses the
@@ -706,9 +723,9 @@ ze_probe(isa_dev)
/* reset card to force it into a known state */
tmp = inb (isa_dev->id_iobase + ZE_RESET);
- DELAY(5000);
+ DELAY(20000);
outb (isa_dev->id_iobase + ZE_RESET, tmp);
- DELAY(5000);
+ DELAY(20000);
/*
* query MAM bit in misc register for 10base2
@@ -735,12 +752,38 @@ ze_probe(isa_dev)
sc->arpcom.ac_enaddr[i] = enet_addr[i];
isa_dev->id_msize = memsize;
+
+
+ /* information for reconfiguration */
+ sc->last_alive = 0;
+ sc->last_up = 0;
return 32;
}
+
+#ifdef APM
+#define ZEDEVS 4
+static apm_hook_func_t ze_hook;
+struct isa_device* ze_devs[ZEDEVS] = {NULL};
+
+static int
+ze_resume(void)
+{
+ int i;
+
+ for (i = 0; i < ZEDEVS; i++) {
+ if (ze_devs[i] != NULL) {
+ reconfig_isadev(ze_devs[i], &net_imask);
+ }
+ }
+
+ return 0;
+}
+#endif /* APM */
/*
* Install interface into kernel networking data structures
*/
+
int
ze_attach(isa_dev)
struct isa_device *isa_dev;
@@ -749,6 +792,26 @@ ze_attach(isa_dev)
struct ifnet *ifp = &sc->arpcom.ac_if;
struct ifaddr *ifa;
struct sockaddr_dl *sdl;
+
+ /* PCMCIA card can be offlined. Reconfiguration is required */
+ if (isa_dev->id_reconfig) {
+ if (!isa_dev->id_alive && sc->last_alive) {
+ sc->last_up = (ifp->if_flags & IFF_UP);
+ ifp->if_flags &= ~(IFF_UP);
+ sc->last_alive = 0;
+ }
+ if (isa_dev->id_alive && !sc->last_alive) {
+ if (sc->last_up) {
+ ifp->if_flags |= IFF_UP;
+ }
+ sc->last_alive = 1;
+ }
+ ze_reset(isa_dev->id_unit);
+ return 1;
+ }
+ else {
+ sc->last_alive = 1;
+ }
/*
* Set interface to stopped condition (reset)
@@ -822,6 +885,11 @@ ze_attach(isa_dev)
#if NBPFILTER > 0
bpfattach(&sc->bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
#endif
+
+#ifdef APM
+ ze_devs[isa_dev->id_unit] = isa_dev;
+ ze_hook = apm_resume_hook_init(ze_resume, "IBM PCMCIA Ethernet", APM_MID_ORDER);
+#endif /* APM */
return 1;
}
@@ -1660,6 +1728,17 @@ ze_ioctl(ifp, command, data)
case SIOCSIFFLAGS:
/*
+ * When the card is offlined, `up' operation can't be permitted
+ */
+ if (!sc->last_alive) {
+ int tmp;
+ tmp = (ifp->if_flags & IFF_UP);
+ if (!sc->last_up && (ifp->if_flags & IFF_UP)) {
+ ifp->if_flags &= ~(IFF_UP);
+ }
+ sc->last_up = tmp;
+ }
+ /*
* If interface is marked down and it is running, then stop it
*/
if (((ifp->if_flags & IFF_UP) == 0) &&
diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c
index 2cd9d23..2f93fcc 100644
--- a/sys/i386/isa/isa.c
+++ b/sys/i386/isa/isa.c
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.c 7.2 (Berkeley) 5/13/91
- * $Id: isa.c,v 1.25 1994/09/20 05:07:11 bde Exp $
+ * $Id: isa.c,v 1.26 1994/09/30 05:35:55 swallace Exp $
*/
/*
@@ -317,13 +317,35 @@ isa_configure() {
/*
* Configure an ISA device.
*/
+
+
+static void config_isadev_c();
+
static void
config_isadev(isdp, mp)
+ struct isa_device *isdp;
+ u_int *mp;
+{
+ config_isadev_c(isdp, mp, 0);
+}
+
+void
+reconfig_isadev(isdp, mp)
+ struct isa_device *isdp;
+ u_int *mp;
+{
+ config_isadev_c(isdp, mp, 1);
+}
+
+static void
+config_isadev_c(isdp, mp, reconfig)
struct isa_device *isdp;
u_int *mp;
+ int reconfig;
{
u_int checkbits;
int id_alive;
+ int last_alive;
struct isa_driver *dp = isdp->id_driver;
checkbits = 0;
@@ -339,12 +361,18 @@ config_isadev(isdp, mp)
#ifndef ALLOW_CONFLICT_MEMADDR
checkbits |= CC_MEMADDR;
#endif
- if (haveseen_isadev(isdp, checkbits))
+ if (!reconfig && haveseen_isadev(isdp, checkbits))
return;
- if (isdp->id_maddr) {
+ if (!reconfig && isdp->id_maddr) {
isdp->id_maddr -= 0xa0000; /* XXX should be a define */
isdp->id_maddr += atdevbase;
}
+ if (reconfig) {
+ last_alive = isdp->id_alive;
+ }
+ else {
+ last_alive = 0;
+ }
id_alive = (*dp->probe)(isdp);
if (id_alive) {
/*
@@ -354,50 +382,52 @@ config_isadev(isdp, mp)
* 16 it will not report I/O addresses.
* Rod Grimes 04/26/94
*/
- printf("%s%d", dp->name, isdp->id_unit);
- if (id_alive != -1) {
- printf(" at 0x%x", isdp->id_iobase);
- if ((isdp->id_iobase + id_alive - 1) !=
- isdp->id_iobase) {
- printf("-0x%x",
- isdp->id_iobase + id_alive - 1);
+ if (!isdp->id_reconfig) {
+ printf("%s%d", dp->name, isdp->id_unit);
+ if (id_alive != -1) {
+ printf(" at 0x%x", isdp->id_iobase);
+ if ((isdp->id_iobase + id_alive - 1) !=
+ isdp->id_iobase) {
+ printf("-0x%x",
+ isdp->id_iobase + id_alive - 1);
+ }
}
- }
- if (isdp->id_irq)
- printf(" irq %d", ffs(isdp->id_irq) - 1);
- if (isdp->id_drq != -1)
- printf(" drq %d", isdp->id_drq);
- if (isdp->id_maddr)
- printf(" maddr 0x%lx", kvtop(isdp->id_maddr));
- if (isdp->id_msize)
- printf(" msize %d", isdp->id_msize);
- if (isdp->id_flags)
- printf(" flags 0x%x", isdp->id_flags);
- if (isdp->id_iobase) {
- if (isdp->id_iobase < 0x100) {
- printf(" on motherboard\n");
- } else {
- if (isdp->id_iobase >= 0x1000) {
- printf (" on eisa\n");
+ if (isdp->id_irq)
+ printf(" irq %d", ffs(isdp->id_irq) - 1);
+ if (isdp->id_drq != -1)
+ printf(" drq %d", isdp->id_drq);
+ if (isdp->id_maddr)
+ printf(" maddr 0x%lx", kvtop(isdp->id_maddr));
+ if (isdp->id_msize)
+ printf(" msize %d", isdp->id_msize);
+ if (isdp->id_flags)
+ printf(" flags 0x%x", isdp->id_flags);
+ if (isdp->id_iobase) {
+ if (isdp->id_iobase < 0x100) {
+ printf(" on motherboard\n");
} else {
- printf (" on isa\n");
+ if (isdp->id_iobase >= 0x1000) {
+ printf (" on eisa\n");
+ } else {
+ printf (" on isa\n");
+ }
}
}
- }
- /*
- * Check for conflicts again. The driver may have changed
- * *dvp. We should weaken the early check since the
- * driver may have been able to change *dvp to avoid
- * conflicts if given a chance. We already skip the early
- * check for IRQs and force a check for IRQs in the next
- * group of checks.
- */
+ /*
+ * Check for conflicts again. The driver may have
+ * changed *dvp. We should weaken the early check
+ * since the driver may have been able to change
+ * *dvp to avoid conflicts if given a chance. We
+ * already skip the early check for IRQs and force
+ * a check for IRQs in the next group of checks.
+ */
#ifndef ALLOW_CONFLICT_IRQ
- checkbits |= CC_IRQ;
+ checkbits |= CC_IRQ;
#endif
- if (haveseen_isadev(isdp, checkbits))
- return;
- isdp->id_alive = id_alive;
+ if (haveseen_isadev(isdp, checkbits))
+ return;
+ isdp->id_alive = id_alive;
+ }
(*dp->attach)(isdp);
if (isdp->id_irq) {
if (mp)
@@ -408,11 +438,28 @@ config_isadev(isdp, mp)
INTREN(isdp->id_irq);
}
} else {
- printf("%s%d not found", dp->name, isdp->id_unit);
- if (isdp->id_iobase) {
- printf(" at 0x%x", isdp->id_iobase);
+ if (isdp->id_reconfig) {
+ (*dp->attach)(isdp); /* reconfiguration attach */
+ }
+ if (!last_alive) {
+ if (!isdp->id_reconfig) {
+ printf("%s%d not found", dp->name, isdp->id_unit);
+ if (isdp->id_iobase) {
+ printf(" at 0x%x", isdp->id_iobase);
+ }
+ printf("\n");
+ }
+ }
+ else {
+ /* This code has not been tested.... */
+ if (isdp->id_irq) {
+ INTRDIS(isdp->id_irq);
+ unregister_intr(ffs(isdp->id_irq) - 1,
+ isdp->id_intr);
+ if (mp)
+ INTRUNMASK(*mp, isdp->id_irq);
+ }
}
- printf("\n");
}
}
diff --git a/sys/i386/isa/isa.h b/sys/i386/isa/isa.h
index e2a26e7..7f6b02a 100644
--- a/sys/i386/isa/isa.h
+++ b/sys/i386/isa/isa.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa.h 5.7 (Berkeley) 5/9/91
- * $Id: isa.h,v 1.4 1994/01/05 15:03:28 rgrimes Exp $
+ * $Id: isa.h,v 1.5 1994/04/21 14:20:54 sos Exp $
*/
#ifndef _I386_ISA_ISA_H_
@@ -62,6 +62,7 @@ unsigned char rtcin __P((int));
/* CPU Board */
#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */
#define IO_ICU1 0x020 /* 8259A Interrupt Controller #1 */
+#define IO_PMP1 0x026 /* 82347 Power Management Peripheral */
#define IO_TIMER1 0x040 /* 8253 Timer #1 */
#define IO_TIMER2 0x048 /* 8253 Timer #2 */
#define IO_KBD 0x060 /* 8042 Keyboard */
@@ -78,7 +79,9 @@ unsigned char rtcin __P((int));
#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */
- /* 0x178 - 0x1EF Open */
+#define IO_PMP2 0x178 /* 82347 Power Management Peripheral */
+
+ /* 0x17A - 0x1EF Open */
#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */
#define IO_GAME 0x200 /* Game Controller */
@@ -146,6 +149,7 @@ unsigned char rtcin __P((int));
#define IO_TMRSIZE 16 /* 8253 programmable timers */
#define IO_NPXSIZE 16 /* 80387/80487 NPX registers */
#define IO_VGASIZE 16 /* VGA controllers */
+#define IO_PMPSIZE 2 /* 82347 power management peripheral */
#endif /* IO_ISASIZES */
diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h
index 31d6c5d..5da5123 100644
--- a/sys/i386/isa/isa_device.h
+++ b/sys/i386/isa/isa_device.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91
- * $Id: isa_device.h,v 1.9 1994/09/02 22:13:34 ats Exp $
+ * $Id: isa_device.h,v 1.10 1994/09/03 16:03:09 csgr Exp $
*/
#ifndef _I386_ISA_ISA_DEVICE_H_
@@ -73,6 +73,7 @@ struct isa_device {
int id_alive; /* device is present */
#define RI_FAST 1 /* fast interrupt handler */
u_int id_ri_flags; /* flags for register_intr() */
+ int id_reconfig; /* hot eject device support (such as PCMCIA) */
};
/*
diff --git a/sys/i386/isa/kbdtables.h b/sys/i386/isa/kbdtables.h
index 7e8318f..a48b6a6 100644
--- a/sys/i386/isa/kbdtables.h
+++ b/sys/i386/isa/kbdtables.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * $Id: kbdtables.h,v 1.14 1994/09/29 08:29:17 sos Exp $
*/
#define SET8 0x80 /* eight bit for emacs SET8-key */
@@ -799,7 +799,7 @@ keymap_t key_map = { 0x69, /* US iso8859 keymap */
/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00,
/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00,
/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00,
-/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 0x00, 0x00,
+/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00,
/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00,
/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00,
/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00,
diff --git a/sys/i386/isa/syscons.c b/sys/i386/isa/syscons.c
index 0479f76..230c945 100644
--- a/sys/i386/isa/syscons.c
+++ b/sys/i386/isa/syscons.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.59 1994/09/29 08:29:21 sos Exp $
+ * $Id: syscons.c,v 1.60 1994/09/29 15:49:09 ache Exp $
*/
#include "sc.h"
@@ -64,6 +64,9 @@
#include <i386/isa/timerreg.h>
#include <i386/isa/kbdtables.h>
#include <i386/i386/cons.h>
+#ifdef APM
+#include <machine/apm_bios.h>
+#endif
#if !defined(NCONS)
#define NCONS 12
@@ -288,6 +291,16 @@ struct isa_driver scdriver = {
pcprobe, pcattach, "sc",
};
+#ifdef APM
+static int
+pc_resume(void)
+{
+ /* when the system wakes up, modifier keys must be re-initialized */
+ shfts = ctls = alts = agrs = metas = 0;
+ return 0;
+}
+#endif /* APM */
+
int
pcprobe(struct isa_device *dev)
{
@@ -391,6 +404,9 @@ pcattach(struct isa_device *dev)
#endif
cursor_pos(1);
update_leds(console[0].status);
+#ifdef APM
+ apm_resume_hook_init(pc_resume, "Syscons console", APM_MID_ORDER);
+#endif
return 0;
}
@@ -2081,7 +2097,11 @@ scinit(void)
scp->ysize = ROW;
scp->bell_pitch = BELL_PITCH;
scp->bell_duration = BELL_DURATION;
+#ifndef LAPTOP
scp->status = NLKED;
+#else
+ scp->status = 0;
+#endif
scp->pid = 0;
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
@@ -2429,6 +2449,12 @@ next_code:
case RBT:
shutdown_nice();
break;
+ case SUSP:
+#ifdef APM
+ apm_suspend_resume();
+#endif /* APM */
+ break;
+
case DBG:
#ifdef DDB /* try to switch to console 0 */
if (cur_console->smode.mode == VT_AUTO &&
diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c
index 4569cc5..c8b92ce 100644
--- a/sys/i386/isa/wd.c
+++ b/sys/i386/isa/wd.c
@@ -37,7 +37,7 @@ static int wdtest = 0;
* SUCH DAMAGE.
*
* from: @(#)wd.c 7.2 (Berkeley) 5/9/91
- * $Id: wd.c,v 1.45 1994/08/30 14:26:13 ache Exp $
+ * $Id: wd.c,v 1.46 1994/09/10 03:19:49 davidg Exp $
*/
/* TODO:
@@ -80,6 +80,9 @@ static int wdtest = 0;
#include <i386/isa/isa.h>
#include <i386/isa/isa_device.h>
#include <i386/isa/wdreg.h>
+#ifdef APM
+#include <machine/apm_bios.h>
+#endif
#include <sys/syslog.h>
#include <vm/vm.h>
@@ -161,6 +164,9 @@ static struct buf wdutab[NWD]; /* head of queue per drive */
static struct buf rwdbuf[NWD]; /* buffers for raw IO */
#endif
static long wdxfer[NWD]; /* count of transfers */
+#ifdef APM
+static int wdsuspend_regist = 0;
+#endif /* APM */
static void bad144intern(struct disk *);
@@ -181,6 +187,9 @@ static void wdsleep(int ctrlr, char *wmesg);
static timeout_t wdtimeout;
static int wdunwedge(struct disk *du);
static int wdwait(struct disk *du, u_char bits_wanted, int timeout);
+#ifdef APM
+static int wdsuspend(void);
+#endif /* APM */
struct isa_driver wdcdriver = {
wdprobe, wdattach, "wdc",
@@ -337,6 +346,11 @@ wdattach(struct isa_device *dvp)
* doesn't work now because the ambient ipl is too high.
*/
wdtab[dvp->id_unit].b_active = 2;
+#ifdef APM
+ if (!wdsuspend_regist) {
+ apm_suspend_hook_init(wdsuspend, "IDE HDD", APM_MID_ORDER);
+ }
+#endif /* APM */
return (1);
}
@@ -1833,4 +1847,13 @@ void bad144intern(struct disk *du) {
}
}
+#ifdef APM
+static int wdsuspend(void)
+{
+ /* Currently, this routine has not be implemented. Sorry... */
+
+ return 0;
+}
+#endif /* APM */
+
#endif /* NWDC > 0 */
diff --git a/sys/isa/kbdtables.h b/sys/isa/kbdtables.h
index 7e8318f..a48b6a6 100644
--- a/sys/isa/kbdtables.h
+++ b/sys/isa/kbdtables.h
@@ -25,7 +25,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id$
+ * $Id: kbdtables.h,v 1.14 1994/09/29 08:29:17 sos Exp $
*/
#define SET8 0x80 /* eight bit for emacs SET8-key */
@@ -799,7 +799,7 @@ keymap_t key_map = { 0x69, /* US iso8859 keymap */
/* sc=36 */ RSH, RSH, RSH, RSH, RSH, RSH, RSH, RSH, 0xFF, 0x00,
/* sc=37 */ '*', '*', 0x0A, 0x0A, '*', '*', 0x0A, 0x0A, 0x33, 0x00,
/* sc=38 */ LALT, LALT, LALT, LALT, LALT, LALT, LALT, LALT, 0xFF, 0x00,
-/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 0x00, 0x00,
+/* sc=39 */ ' ', ' ', ' ', ' ', ' ', ' ', SUSP, ' ', 0x02, 0x00,
/* sc=3a */ CLK, CLK, CLK, CLK, CLK, CLK, CLK, CLK, 0xFF, 0x00,
/* sc=3b */ F( 1), F(13), F(25), F(37), S( 1), S(11), S( 1), S(11), 0xFF, 0x00,
/* sc=3c */ F( 2), F(14), F(26), F(38), S( 2), S(12), S( 2), S(12), 0xFF, 0x00,
diff --git a/sys/isa/syscons.c b/sys/isa/syscons.c
index 0479f76..230c945 100644
--- a/sys/isa/syscons.c
+++ b/sys/isa/syscons.c
@@ -35,7 +35,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: syscons.c,v 1.59 1994/09/29 08:29:21 sos Exp $
+ * $Id: syscons.c,v 1.60 1994/09/29 15:49:09 ache Exp $
*/
#include "sc.h"
@@ -64,6 +64,9 @@
#include <i386/isa/timerreg.h>
#include <i386/isa/kbdtables.h>
#include <i386/i386/cons.h>
+#ifdef APM
+#include <machine/apm_bios.h>
+#endif
#if !defined(NCONS)
#define NCONS 12
@@ -288,6 +291,16 @@ struct isa_driver scdriver = {
pcprobe, pcattach, "sc",
};
+#ifdef APM
+static int
+pc_resume(void)
+{
+ /* when the system wakes up, modifier keys must be re-initialized */
+ shfts = ctls = alts = agrs = metas = 0;
+ return 0;
+}
+#endif /* APM */
+
int
pcprobe(struct isa_device *dev)
{
@@ -391,6 +404,9 @@ pcattach(struct isa_device *dev)
#endif
cursor_pos(1);
update_leds(console[0].status);
+#ifdef APM
+ apm_resume_hook_init(pc_resume, "Syscons console", APM_MID_ORDER);
+#endif
return 0;
}
@@ -2081,7 +2097,11 @@ scinit(void)
scp->ysize = ROW;
scp->bell_pitch = BELL_PITCH;
scp->bell_duration = BELL_DURATION;
+#ifndef LAPTOP
scp->status = NLKED;
+#else
+ scp->status = 0;
+#endif
scp->pid = 0;
scp->proc = NULL;
scp->smode.mode = VT_AUTO;
@@ -2429,6 +2449,12 @@ next_code:
case RBT:
shutdown_nice();
break;
+ case SUSP:
+#ifdef APM
+ apm_suspend_resume();
+#endif /* APM */
+ break;
+
case DBG:
#ifdef DDB /* try to switch to console 0 */
if (cur_console->smode.mode == VT_AUTO &&
diff --git a/sys/kern/subr_trap.c b/sys/kern/subr_trap.c
index 49b4ffd..fcaa6e9 100644
--- a/sys/kern/subr_trap.c
+++ b/sys/kern/subr_trap.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* from: @(#)trap.c 7.4 (Berkeley) 5/13/91
- * $Id: trap.c,v 1.33 1994/09/08 11:48:52 bde Exp $
+ * $Id: trap.c,v 1.34 1994/09/11 11:26:18 davidg Exp $
*/
/*
@@ -459,10 +459,12 @@ trap_fatal(frame)
struct trapframe *frame;
{
int code, type, eva;
+ struct soft_segment_descriptor softseg;
code = frame->tf_err;
type = frame->tf_trapno;
eva = rcr2();
+ sdtossd(gdt + IDXSEL(frame->tf_cs & 0xffff), &softseg);
if (type <= MAX_TRAP_MSG)
printf("\n\nFatal trap %d: %s while in %s mode\n",
@@ -475,7 +477,11 @@ trap_fatal(frame)
code & PGEX_W ? "write" : "read",
code & PGEX_P ? "protection violation" : "page not present");
}
- printf("instruction pointer = 0x%x\n", frame->tf_eip);
+ printf("instruction pointer = 0x%x:0x%x\n", frame->tf_cs & 0xffff, frame->tf_eip);
+ printf("code segment = base 0x%x, limit 0x%x, type 0x%x\n",
+ softseg.ssd_base, softseg.ssd_limit, softseg.ssd_type);
+ printf(" = DPL %d, pres %d, def32 %d, gran %d\n",
+ softseg.ssd_dpl, softseg.ssd_p, softseg.ssd_def32, softseg.ssd_gran);
printf("processor eflags = ");
if (frame->tf_eflags & PSL_T)
printf("trace/trap, ");
OpenPOWER on IntegriCloud