mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-15 06:42:51 +01:00
Laptop Advanced Power Management support by HOSOKAWA Tatsumi.
Submitted by: HOSOKAWA Tatsumi
This commit is contained in:
parent
7f4295e337
commit
22414e535a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3258
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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, ");
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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_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");
|
||||
} else {
|
||||
printf (" on isa\n");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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");
|
||||
} 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.
|
||||
*/
|
||||
#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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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 &&
|
||||
|
823
sys/i386/apm/apm.c
Normal file
823
sys/i386/apm/apm.c
Normal file
@ -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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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 */
|
50
sys/i386/apm/apm_init/Makefile
Normal file
50
sys/i386/apm/apm_init/Makefile
Normal file
@ -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>
|
207
sys/i386/apm/apm_init/apm_init.S
Normal file
207
sys/i386/apm/apm_init/apm_init.S
Normal file
@ -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
|
59
sys/i386/apm/apm_init/apm_init.inc
Normal file
59
sys/i386/apm/apm_init/apm_init.inc
Normal file
@ -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 */
|
64
sys/i386/apm/apm_init/bin2asm.c
Normal file
64
sys/i386/apm/apm_init/bin2asm.c
Normal file
@ -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;
|
||||
}
|
185
sys/i386/apm/apm_init/real_prot.S
Normal file
185
sys/i386/apm/apm_init/real_prot.S
Normal file
@ -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
|
56
sys/i386/apm/apm_init/real_prot.h
Normal file
56
sys/i386/apm/apm_init/real_prot.h
Normal file
@ -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)
|
6
sys/i386/apm/apm_init/rmaouthdr
Normal file
6
sys/i386/apm/apm_init/rmaouthdr
Normal file
@ -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
|
24
sys/i386/apm/apm_init/table.c
Normal file
24
sys/i386/apm/apm_init/table.c
Normal file
@ -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 };
|
23
sys/i386/apm/apm_setup.h
Normal file
23
sys/i386/apm/apm_setup.h
Normal file
@ -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;
|
126
sys/i386/apm/apm_setup.s
Normal file
126
sys/i386/apm/apm_setup.s
Normal file
@ -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 */
|
823
sys/i386/bios/apm.c
Normal file
823
sys/i386/bios/apm.c
Normal file
@ -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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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(®s);
|
||||
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 */
|
50
sys/i386/bios/apm_init/Makefile
Normal file
50
sys/i386/bios/apm_init/Makefile
Normal file
@ -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>
|
207
sys/i386/bios/apm_init/apm_init.S
Normal file
207
sys/i386/bios/apm_init/apm_init.S
Normal file
@ -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
|
59
sys/i386/bios/apm_init/apm_init.inc
Normal file
59
sys/i386/bios/apm_init/apm_init.inc
Normal file
@ -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 */
|
64
sys/i386/bios/apm_init/bin2asm.c
Normal file
64
sys/i386/bios/apm_init/bin2asm.c
Normal file
@ -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;
|
||||
}
|
185
sys/i386/bios/apm_init/real_prot.S
Normal file
185
sys/i386/bios/apm_init/real_prot.S
Normal file
@ -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
|
56
sys/i386/bios/apm_init/real_prot.h
Normal file
56
sys/i386/bios/apm_init/real_prot.h
Normal file
@ -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)
|
6
sys/i386/bios/apm_init/rmaouthdr
Normal file
6
sys/i386/bios/apm_init/rmaouthdr
Normal file
@ -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
|
24
sys/i386/bios/apm_init/table.c
Normal file
24
sys/i386/bios/apm_init/table.c
Normal file
@ -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 };
|
23
sys/i386/bios/apm_setup.h
Normal file
23
sys/i386/bios/apm_setup.h
Normal file
@ -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;
|
126
sys/i386/bios/apm_setup.s
Normal file
126
sys/i386/bios/apm_setup.s
Normal file
@ -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 */
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }
|
||||
|
@ -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. */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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, ");
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
@ -1659,6 +1727,17 @@ ze_ioctl(ifp, command, data)
|
||||
break;
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -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_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");
|
||||
} else {
|
||||
printf (" on isa\n");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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");
|
||||
} 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.
|
||||
*/
|
||||
#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");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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) */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
@ -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 &&
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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 &&
|
||||
|
@ -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, ");
|
||||
|
Loading…
Reference in New Issue
Block a user