Laptop Advanced Power Management support by HOSOKAWA Tatsumi.

Submitted by:	HOSOKAWA Tatsumi
This commit is contained in:
David Greenman 1994-10-01 02:56:21 +00:00
parent 7f4295e337
commit 22414e535a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=3258
58 changed files with 4181 additions and 161 deletions

View File

@ -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)

View File

@ -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:

View File

@ -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. */

View File

@ -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. */

View File

@ -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;

View File

@ -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:

View File

@ -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, ");

View File

@ -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)

View File

@ -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

View File

@ -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");
}
}

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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
View 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(&regs);
return regs.x.cf;
}
/* engage/disengage power management (APM 1.1 or later) */
static int
apm_engage_disengage_pm(int engage)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_ENGAGEDISENGAGEPM;
regs.x.bx = PMDV_ALLDEV;
regs.x.cx = engage;
call_apm(&regs);
return regs.x.cf;
}
/* get PM event */
static u_int
apm_getevent(void)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_GETPMEVENT;
call_apm(&regs);
if (regs.x.cf) {
#if 0
printf("No event: errcode = %d\n", apm_errno);
#endif
return PMEV_NOEVENT;
}
return (u_int)regs.x.bx;
}
/*
* In many cases, the first event that occured after resume, needs
* special treatment. This binary flag make this process possible.
* Initial value of this variable is 1, because the bootstrap
* condition is equivalent to resumed condition for the power
* manager.
*/
static int resumed_event = 1;
/* suspend entire system */
static int
apm_suspend_system(void)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_SETPWSTATE;
regs.x.bx = PMDV_ALLDEV;
regs.x.cx = PMST_SUSPEND;
call_apm(&regs);
if (regs.x.cf) {
printf("Entire system suspend failure: errcode = %d\n", apm_errno);
return 1;
}
resumed_event = 1;
return 0;
}
/* APM Battery low handler */
static void
apm_battery_low(void)
{
/* Currently, this routine has not been implemented. Sorry... */
}
/* APM driver calls some functions automatically when the system wakes up */
static void
apm_execute_hook(apm_hook_func_t list)
{
apm_hook_func_t p;
for (p = list; p != NULL; p = p->next) {
if ((*(p->func))()) {
printf("Warning: APM hook of %s failed", p->name);
}
}
}
/* APM hook manager */
static apm_hook_func_t
apm_hook_init(apm_hook_func_t *list, int (*func)(void), char *name, int order)
{
int pl;
apm_hook_func_t p, prev, new_node;
pl = splhigh();
new_node = malloc(sizeof(*new_node), M_DEVBUF, M_NOWAIT);
if (new_node == NULL) {
panic("Can't allocate device buffer for apm_resume_hook.");
}
new_node->func = func;
new_node->name = name;
#if 0
new_node->next = *list;
*list = new_node;
#else
prev = NULL;
for (p = *list; p != NULL; prev = p, p = p->next) {
if (p->order > order) {
break;
}
}
if (prev == NULL) {
new_node->next = *list;
*list = new_node;
}
else {
new_node->next = prev->next;
prev->next = new_node;
}
#endif
splx(pl);
return new_node;
}
void
apm_hook_delete(apm_hook_func_t *list, apm_hook_func_t delete_node)
{
int pl;
apm_hook_func_t p, prev;
pl = splhigh();
prev = NULL;
for (p = *list; p != NULL; prev = p, p = p->next) {
if (p == delete_node) {
goto deleteit;
}
}
panic("Tried to delete unregistered apm_resume_hook.");
goto nosuchnode;
deleteit:
if (prev != NULL) {
prev->next = p->next;
}
else {
*list = p->next;
}
free(delete_node, M_DEVBUF);
nosuchnode:
splx(pl);
}
static struct timeval suspend_time;
/* default APM hook functions */
static int
apm_default_resume(void)
{
u_int second, minute, hour;
struct timeval resume_time;
inittodr(0); /* adjust time to RTC */
microtime(&resume_time);
second = resume_time.tv_sec - suspend_time.tv_sec;
hour = second / 3600;
second %= 3600;
minute = second / 60;
second %= 60;
log(LOG_NOTICE, "resumed from suspended mode (slept %02d:%02d:%02d)\n", hour, minute, second);
return 0;
}
static int
apm_default_suspend(void)
{
int pl;
#if 0
pl = splhigh();
sync(curproc, NULL, NULL);
splx(pl);
#endif
microtime(&suspend_time);
return 0;
}
/* list structure for hook */
static apm_hook_func_t apm_resume_hook = NULL;
static apm_hook_func_t apm_suspend_hook = NULL;
/* execute resume hook */
static void
apm_execute_resume_hook(void)
{
apm_execute_hook(apm_resume_hook);
}
/* add a node on resume hook */
apm_hook_func_t
apm_resume_hook_init(int (*func)(void), char *name, int order)
{
return apm_hook_init(&apm_resume_hook, func, name, order);
}
/* delete a node from resume hook */
void
apm_resume_hook_delete(apm_hook_func_t delete_node)
{
apm_hook_delete(&apm_resume_hook, delete_node);
}
/* execute suspend hook */
static void
apm_execute_suspend_hook(void)
{
apm_execute_hook(apm_suspend_hook);
}
/* add a node on resume hook */
apm_hook_func_t
apm_suspend_hook_init(int (*func)(void), char *name, int order)
{
return apm_hook_init(&apm_suspend_hook, func, name, order);
}
/* delete a node from resume hook */
void
apm_suspend_hook_delete(apm_hook_func_t delete_node)
{
apm_hook_delete(&apm_suspend_hook, delete_node);
}
/* get APM information */
static int
apm_get_info(apm_info_t aip)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_GETPWSTATUS;
regs.x.bx = PMDV_ALLDEV;
call_apm(&regs);
if (regs.x.cf) {
printf("Get APM info failure: errcode = %d\n", apm_errno);
return 1;
}
aip->ai_major = (u_int)majorversion;
aip->ai_minor = (u_int)minorversion;
aip->ai_acline = (u_int)regs.hl.bh;
aip->ai_batt_stat = (u_int)regs.hl.bl;
aip->ai_batt_life = (u_int)regs.hl.cl;
return 0;
}
/* Define equivalent event sets */
static int equiv_event_num = 0;
static struct apm_eqv_event equiv_events[APM_MAX_EQUIV_EVENTS];
static int
apm_def_eqv(apm_eqv_event_t aee)
{
if (equiv_event_num == APM_MAX_EQUIV_EVENTS) {
return 1;
}
memcpy(&equiv_events[equiv_event_num], aee, sizeof(struct apm_eqv_event));
equiv_event_num++;
return 0;
}
static void
apm_flush_eqv(void)
{
equiv_event_num = 0;
}
static void apm_processevent(void);
/*
* Public interface to the suspend/resume:
*
* Execute suspend and resume hook before and after sleep, respectively.
*/
void
apm_suspend_resume(void)
{
int pl;
#if 0
printf("Called apm_suspend_resume();\n");
#endif
if (apm_initialized) {
apm_execute_suspend_hook();
apm_suspend_system();
apm_execute_resume_hook();
apm_processevent();
}
}
/* inform APM BIOS that CPU is idle */
void
apm_cpu_idle(void)
{
if (idle_cpu) {
if (active) {
asm("movw $0x5305, %ax; lcall _apm_addr");
}
}
/*
* Some APM implementation halts CPU in BIOS, whenever
* "CPU-idle" function are invoked, but swtch() of
* FreeBSD halts CPU, therefore, CPU is halted twice
* in the sched loop. It makes the interrupt latency
* terribly long and be able to cause a serious problem
* in interrupt processing. We prevent it by removing
* "hlt" operation from swtch() and managed it under
* APM driver.
*/
if (!active || halt_cpu) {
asm("sti ; hlt"); /* wait for interrupt */
}
}
/* inform APM BIOS that CPU is busy */
void
apm_cpu_busy(void)
{
if (idle_cpu && active) {
asm("movw $0x5306, %ax; lcall _apm_addr");
}
}
/*
* APM timeout routine:
*
* This routine is automatically called by timer two times within one
* seconed.
*/
static void
apm_timeout(void *arg1)
{
#if 0
printf("Called apm_timeout\n");
#endif
apm_processevent();
timeout(apm_timeout, NULL, hz / 2); /* 2 Hz */
/* APM driver must polls APM event a time per second */
}
/* enable APM BIOS */
static void
apm_event_enable(void)
{
#if 0
printf("called apm_event_enable()\n");
#endif
if (apm_initialized) {
active = 1;
timeout(apm_timeout, NULL, 2 * hz);
}
}
/* disable APM BIOS */
static void
apm_event_disable(void)
{
#if 0
printf("called apm_event_disable()\n");
#endif
if (apm_initialized) {
untimeout(apm_timeout, NULL);
active = 0;
}
}
/* halt CPU in scheduling loop */
static void apm_halt_cpu(void)
{
if (apm_initialized) {
halt_cpu = 1;
}
}
/* don't halt CPU in scheduling loop */
static void apm_not_halt_cpu(void)
{
if (apm_initialized) {
halt_cpu = 0;
}
}
/* device driver definitions */
int apmprobe (struct isa_device *);
int apmattach(struct isa_device *);
struct isa_driver apmdriver = { apmprobe, apmattach, "apm" };
/*
* probe APM (dummy):
*
* APM probing routine is placed on locore.s and apm_init.S because
* this process forces the CPU to turn to real mode or V86 mode.
* Current version uses real mode, but on future version, we want
* to use V86 mode in APM initialization.
*/
int
apmprobe(struct isa_device *dvp)
{
switch (apm_version) {
case APMINI_CANTFIND:
/* silent */
return 0;
case APMINI_NOT32BIT:
printf("apm%d: 32bit connection is not supported.\n", dvp->id_unit);
return 0;
case APMINI_CONNECTERR:
printf("apm%d: 32-bit connection error.\n", dvp->id_unit);
return 0;
}
return -1;
}
static const char *
is_enabled(int enabled)
{
if (enabled) {
return "enabled";
}
return "disabled";
}
static const char *
apm_error(void)
{
static char buffer[64];
switch (apm_errno) {
case 0:
return "APM OK.";
default:
sprintf(buffer, "Unknown Error 0x%x", (u_int)apm_errno);
return buffer;
}
}
/* Process APM event */
static void
apm_processevent(void)
{
int i, apm_event;
getevent:
while (1) {
if ((apm_event = apm_getevent()) == PMEV_NOEVENT) {
break;
}
#if 0
#if 1
#define OPMEV_DEBUGMESSAGE(symbol) case symbol: break;
#else
#define OPMEV_DEBUGMESSAGE(symbol) case symbol: printf("Original APM Event: " #symbol "\n"); break
#endif
switch (apm_event) {
OPMEV_DEBUGMESSAGE(PMEV_NOEVENT);
OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
OPMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
OPMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
OPMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
OPMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
OPMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
default:
printf("Unknown Original APM Event 0x%x\n", apm_event);
break;
}
#endif
for (i = 0; i < equiv_event_num; i++) {
if (equiv_events[i].aee_event == apm_event) {
u_int tmp = PMEV_DEFAULT;
if (resumed_event) {
tmp = equiv_events[i].aee_resume;
}
else {
tmp = equiv_events[i].aee_equiv;
}
if (tmp != PMEV_DEFAULT) {
apm_event = tmp;
break;
}
}
}
#if 1
#if 1
#define PMEV_DEBUGMESSAGE(symbol) case symbol: break;
#else
#define PMEV_DEBUGMESSAGE(symbol) case symbol: printf("APM Event: " #symbol "\n"); break
#endif
switch (apm_event) {
PMEV_DEBUGMESSAGE(PMEV_NOEVENT);
PMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
PMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
PMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
PMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
PMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
PMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
PMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
PMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
PMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
PMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
default:
printf("Unknown APM Event 0x%x\n", apm_event);
break;
}
#endif
switch (apm_event) {
case PMEV_NOEVENT:
case PMEV_STANDBYREQ:
case PMEV_POWERSTATECHANGE:
case PMEV_CRITSUSPEND:
case PMEV_USERSTANDBYREQ:
case PMEV_USERSUSPENDREQ:
break;
case PMEV_BATTERYLOW:
apm_battery_low();
break;
case PMEV_SUSPENDREQ:
apm_suspend_resume();
break;
case PMEV_NORMRESUME:
case PMEV_CRITRESUME:
case PMEV_UPDATETIME:
case PMEV_STANDBYRESUME:
inittodr(0); /* adjust time to RTC */
break;
}
}
resumed_event = 0;
}
/*
* Attach APM:
*
* Initialize APM driver (APM BIOS itself has been initialized in locore.s)
*/
int
apmattach(struct isa_device *dvp)
{
/* setup APM parameters */
minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0);
majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8);
intversion = INTVERSION(majorversion, minorversion);
cs32_base = (apm_cs32_base << 4) + KERNBASE;
cs16_base = (apm_cs16_base << 4) + KERNBASE;
ds_base = (apm_ds_base << 4) + KERNBASE;
cs_limit = apm_cs_limit;
ds_limit = apm_ds_limit;
cs_entry = apm_cs_entry;
idle_cpu = ((apm_flags & APM_CPUIDLE_SLOW) != 0);
disabled = ((apm_flags & APM_DISABLED) != 0);
disengaged = ((apm_flags & APM_DISENGAGED) != 0);
/* print bootstrap messages */
printf(" found APM BIOS version %d.%d\n", dvp->id_unit, majorversion, minorversion);
printf("apm%d: Code32 0x%08x, Code16 0x%08x, Data 0x%08x\n", dvp->id_unit, cs32_base, cs16_base, ds_base);
printf("apm%d: Code entry 0x%08x, Idling CPU %s, Management %s\n", dvp->id_unit, cs_entry, is_enabled(idle_cpu), is_enabled(!disabled));
/*
* APM 1.0 does not have:
*
* 1. segment limit parameters
*
* 2. engage/disengage operations
*/
if (intversion >= INTVERSION(1, 1)) {
printf("apm%d: Engaged control %s\n", dvp->id_unit, is_enabled(!disengaged));
}
else {
cs_limit = 0xffff;
ds_limit = 0xffff;
}
/* setup GDT */
setup_apm_gdt(cs32_base, cs16_base, ds_base, cs_limit, ds_limit);
/* setup entry point 48bit pointer */
apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL);
apm_addr.offset = cs_entry;
/* enable power management */
if (disabled) {
if (apm_enable_disable_pm(1)) {
printf("Warning: APM enable function failed! [%s]\n", apm_error());
}
}
/* engage power managment (APM 1.1 or later) */
if (intversion >= INTVERSION(1, 1) && disengaged) {
if (apm_engage_disengage_pm(1)) {
printf("Warning: APM engage function failed [%s]\n", apm_error());
}
}
apm_suspend_hook_init(apm_default_suspend, "default suspend", APM_MAX_ORDER);
apm_resume_hook_init (apm_default_resume , "default resume" , APM_MIN_ORDER);
apm_initialized = 1;
return 0;
}
int
apmopen(dev_t dev, int flag, int fmt, struct proc *p)
{
if (!apm_initialized) {
return ENXIO;
}
switch (minor(dev)) {
case 0: /* apm0 */
break;
defaults:
return (ENXIO);
}
return 0;
}
int
apmclose(dev_t dev, int flag, int fmt, struct proc *p)
{
return 0;
}
int
apmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
{
int error = 0;
int pl;
#if 0
printf("APM ioctl: minor = %d, cmd = 0x%x\n", minor(dev), cmd);
#endif
pl = splhigh();
if (minor(dev) != 0) {
return ENXIO;
}
if (!apm_initialized) {
return ENXIO;
}
switch (cmd) {
case APMIO_SUSPEND:
apm_suspend_resume();
break;
case APMIO_GETINFO:
if (apm_get_info((apm_info_t)addr)) {
error = ENXIO;
}
break;
case APMIO_DEFEQV:
if (apm_def_eqv((apm_eqv_event_t)addr)) {
error = ENOSPC;
}
break;
case APMIO_FLUSHEQV:
apm_flush_eqv();
break;
case APMIO_ENABLE:
apm_event_enable();
break;
case APMIO_DISABLE:
apm_event_disable();
break;
case APMIO_HALTCPU:
apm_halt_cpu();
break;
case APMIO_NOTHALTCPU:
apm_not_halt_cpu();
break;
default:
error = EINVAL;
break;
}
splx(pl);
return error;
}
#endif /* NAPM > 0 */

View 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>

View 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

View 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 */

View 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;
}

View 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

View 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)

View 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

View 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
View 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
View 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
View 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(&regs);
return regs.x.cf;
}
/* engage/disengage power management (APM 1.1 or later) */
static int
apm_engage_disengage_pm(int engage)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_ENGAGEDISENGAGEPM;
regs.x.bx = PMDV_ALLDEV;
regs.x.cx = engage;
call_apm(&regs);
return regs.x.cf;
}
/* get PM event */
static u_int
apm_getevent(void)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_GETPMEVENT;
call_apm(&regs);
if (regs.x.cf) {
#if 0
printf("No event: errcode = %d\n", apm_errno);
#endif
return PMEV_NOEVENT;
}
return (u_int)regs.x.bx;
}
/*
* In many cases, the first event that occured after resume, needs
* special treatment. This binary flag make this process possible.
* Initial value of this variable is 1, because the bootstrap
* condition is equivalent to resumed condition for the power
* manager.
*/
static int resumed_event = 1;
/* suspend entire system */
static int
apm_suspend_system(void)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_SETPWSTATE;
regs.x.bx = PMDV_ALLDEV;
regs.x.cx = PMST_SUSPEND;
call_apm(&regs);
if (regs.x.cf) {
printf("Entire system suspend failure: errcode = %d\n", apm_errno);
return 1;
}
resumed_event = 1;
return 0;
}
/* APM Battery low handler */
static void
apm_battery_low(void)
{
/* Currently, this routine has not been implemented. Sorry... */
}
/* APM driver calls some functions automatically when the system wakes up */
static void
apm_execute_hook(apm_hook_func_t list)
{
apm_hook_func_t p;
for (p = list; p != NULL; p = p->next) {
if ((*(p->func))()) {
printf("Warning: APM hook of %s failed", p->name);
}
}
}
/* APM hook manager */
static apm_hook_func_t
apm_hook_init(apm_hook_func_t *list, int (*func)(void), char *name, int order)
{
int pl;
apm_hook_func_t p, prev, new_node;
pl = splhigh();
new_node = malloc(sizeof(*new_node), M_DEVBUF, M_NOWAIT);
if (new_node == NULL) {
panic("Can't allocate device buffer for apm_resume_hook.");
}
new_node->func = func;
new_node->name = name;
#if 0
new_node->next = *list;
*list = new_node;
#else
prev = NULL;
for (p = *list; p != NULL; prev = p, p = p->next) {
if (p->order > order) {
break;
}
}
if (prev == NULL) {
new_node->next = *list;
*list = new_node;
}
else {
new_node->next = prev->next;
prev->next = new_node;
}
#endif
splx(pl);
return new_node;
}
void
apm_hook_delete(apm_hook_func_t *list, apm_hook_func_t delete_node)
{
int pl;
apm_hook_func_t p, prev;
pl = splhigh();
prev = NULL;
for (p = *list; p != NULL; prev = p, p = p->next) {
if (p == delete_node) {
goto deleteit;
}
}
panic("Tried to delete unregistered apm_resume_hook.");
goto nosuchnode;
deleteit:
if (prev != NULL) {
prev->next = p->next;
}
else {
*list = p->next;
}
free(delete_node, M_DEVBUF);
nosuchnode:
splx(pl);
}
static struct timeval suspend_time;
/* default APM hook functions */
static int
apm_default_resume(void)
{
u_int second, minute, hour;
struct timeval resume_time;
inittodr(0); /* adjust time to RTC */
microtime(&resume_time);
second = resume_time.tv_sec - suspend_time.tv_sec;
hour = second / 3600;
second %= 3600;
minute = second / 60;
second %= 60;
log(LOG_NOTICE, "resumed from suspended mode (slept %02d:%02d:%02d)\n", hour, minute, second);
return 0;
}
static int
apm_default_suspend(void)
{
int pl;
#if 0
pl = splhigh();
sync(curproc, NULL, NULL);
splx(pl);
#endif
microtime(&suspend_time);
return 0;
}
/* list structure for hook */
static apm_hook_func_t apm_resume_hook = NULL;
static apm_hook_func_t apm_suspend_hook = NULL;
/* execute resume hook */
static void
apm_execute_resume_hook(void)
{
apm_execute_hook(apm_resume_hook);
}
/* add a node on resume hook */
apm_hook_func_t
apm_resume_hook_init(int (*func)(void), char *name, int order)
{
return apm_hook_init(&apm_resume_hook, func, name, order);
}
/* delete a node from resume hook */
void
apm_resume_hook_delete(apm_hook_func_t delete_node)
{
apm_hook_delete(&apm_resume_hook, delete_node);
}
/* execute suspend hook */
static void
apm_execute_suspend_hook(void)
{
apm_execute_hook(apm_suspend_hook);
}
/* add a node on resume hook */
apm_hook_func_t
apm_suspend_hook_init(int (*func)(void), char *name, int order)
{
return apm_hook_init(&apm_suspend_hook, func, name, order);
}
/* delete a node from resume hook */
void
apm_suspend_hook_delete(apm_hook_func_t delete_node)
{
apm_hook_delete(&apm_suspend_hook, delete_node);
}
/* get APM information */
static int
apm_get_info(apm_info_t aip)
{
union real_regs regs;
regs.hl.ah = APM_BIOS;
regs.hl.al = APM_GETPWSTATUS;
regs.x.bx = PMDV_ALLDEV;
call_apm(&regs);
if (regs.x.cf) {
printf("Get APM info failure: errcode = %d\n", apm_errno);
return 1;
}
aip->ai_major = (u_int)majorversion;
aip->ai_minor = (u_int)minorversion;
aip->ai_acline = (u_int)regs.hl.bh;
aip->ai_batt_stat = (u_int)regs.hl.bl;
aip->ai_batt_life = (u_int)regs.hl.cl;
return 0;
}
/* Define equivalent event sets */
static int equiv_event_num = 0;
static struct apm_eqv_event equiv_events[APM_MAX_EQUIV_EVENTS];
static int
apm_def_eqv(apm_eqv_event_t aee)
{
if (equiv_event_num == APM_MAX_EQUIV_EVENTS) {
return 1;
}
memcpy(&equiv_events[equiv_event_num], aee, sizeof(struct apm_eqv_event));
equiv_event_num++;
return 0;
}
static void
apm_flush_eqv(void)
{
equiv_event_num = 0;
}
static void apm_processevent(void);
/*
* Public interface to the suspend/resume:
*
* Execute suspend and resume hook before and after sleep, respectively.
*/
void
apm_suspend_resume(void)
{
int pl;
#if 0
printf("Called apm_suspend_resume();\n");
#endif
if (apm_initialized) {
apm_execute_suspend_hook();
apm_suspend_system();
apm_execute_resume_hook();
apm_processevent();
}
}
/* inform APM BIOS that CPU is idle */
void
apm_cpu_idle(void)
{
if (idle_cpu) {
if (active) {
asm("movw $0x5305, %ax; lcall _apm_addr");
}
}
/*
* Some APM implementation halts CPU in BIOS, whenever
* "CPU-idle" function are invoked, but swtch() of
* FreeBSD halts CPU, therefore, CPU is halted twice
* in the sched loop. It makes the interrupt latency
* terribly long and be able to cause a serious problem
* in interrupt processing. We prevent it by removing
* "hlt" operation from swtch() and managed it under
* APM driver.
*/
if (!active || halt_cpu) {
asm("sti ; hlt"); /* wait for interrupt */
}
}
/* inform APM BIOS that CPU is busy */
void
apm_cpu_busy(void)
{
if (idle_cpu && active) {
asm("movw $0x5306, %ax; lcall _apm_addr");
}
}
/*
* APM timeout routine:
*
* This routine is automatically called by timer two times within one
* seconed.
*/
static void
apm_timeout(void *arg1)
{
#if 0
printf("Called apm_timeout\n");
#endif
apm_processevent();
timeout(apm_timeout, NULL, hz / 2); /* 2 Hz */
/* APM driver must polls APM event a time per second */
}
/* enable APM BIOS */
static void
apm_event_enable(void)
{
#if 0
printf("called apm_event_enable()\n");
#endif
if (apm_initialized) {
active = 1;
timeout(apm_timeout, NULL, 2 * hz);
}
}
/* disable APM BIOS */
static void
apm_event_disable(void)
{
#if 0
printf("called apm_event_disable()\n");
#endif
if (apm_initialized) {
untimeout(apm_timeout, NULL);
active = 0;
}
}
/* halt CPU in scheduling loop */
static void apm_halt_cpu(void)
{
if (apm_initialized) {
halt_cpu = 1;
}
}
/* don't halt CPU in scheduling loop */
static void apm_not_halt_cpu(void)
{
if (apm_initialized) {
halt_cpu = 0;
}
}
/* device driver definitions */
int apmprobe (struct isa_device *);
int apmattach(struct isa_device *);
struct isa_driver apmdriver = { apmprobe, apmattach, "apm" };
/*
* probe APM (dummy):
*
* APM probing routine is placed on locore.s and apm_init.S because
* this process forces the CPU to turn to real mode or V86 mode.
* Current version uses real mode, but on future version, we want
* to use V86 mode in APM initialization.
*/
int
apmprobe(struct isa_device *dvp)
{
switch (apm_version) {
case APMINI_CANTFIND:
/* silent */
return 0;
case APMINI_NOT32BIT:
printf("apm%d: 32bit connection is not supported.\n", dvp->id_unit);
return 0;
case APMINI_CONNECTERR:
printf("apm%d: 32-bit connection error.\n", dvp->id_unit);
return 0;
}
return -1;
}
static const char *
is_enabled(int enabled)
{
if (enabled) {
return "enabled";
}
return "disabled";
}
static const char *
apm_error(void)
{
static char buffer[64];
switch (apm_errno) {
case 0:
return "APM OK.";
default:
sprintf(buffer, "Unknown Error 0x%x", (u_int)apm_errno);
return buffer;
}
}
/* Process APM event */
static void
apm_processevent(void)
{
int i, apm_event;
getevent:
while (1) {
if ((apm_event = apm_getevent()) == PMEV_NOEVENT) {
break;
}
#if 0
#if 1
#define OPMEV_DEBUGMESSAGE(symbol) case symbol: break;
#else
#define OPMEV_DEBUGMESSAGE(symbol) case symbol: printf("Original APM Event: " #symbol "\n"); break
#endif
switch (apm_event) {
OPMEV_DEBUGMESSAGE(PMEV_NOEVENT);
OPMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
OPMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
OPMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
OPMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
OPMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
OPMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
OPMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
OPMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
OPMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
OPMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
default:
printf("Unknown Original APM Event 0x%x\n", apm_event);
break;
}
#endif
for (i = 0; i < equiv_event_num; i++) {
if (equiv_events[i].aee_event == apm_event) {
u_int tmp = PMEV_DEFAULT;
if (resumed_event) {
tmp = equiv_events[i].aee_resume;
}
else {
tmp = equiv_events[i].aee_equiv;
}
if (tmp != PMEV_DEFAULT) {
apm_event = tmp;
break;
}
}
}
#if 1
#if 1
#define PMEV_DEBUGMESSAGE(symbol) case symbol: break;
#else
#define PMEV_DEBUGMESSAGE(symbol) case symbol: printf("APM Event: " #symbol "\n"); break
#endif
switch (apm_event) {
PMEV_DEBUGMESSAGE(PMEV_NOEVENT);
PMEV_DEBUGMESSAGE(PMEV_STANDBYREQ);
PMEV_DEBUGMESSAGE(PMEV_SUSPENDREQ);
PMEV_DEBUGMESSAGE(PMEV_NORMRESUME);
PMEV_DEBUGMESSAGE(PMEV_CRITRESUME);
PMEV_DEBUGMESSAGE(PMEV_BATTERYLOW);
PMEV_DEBUGMESSAGE(PMEV_POWERSTATECHANGE);
PMEV_DEBUGMESSAGE(PMEV_UPDATETIME);
PMEV_DEBUGMESSAGE(PMEV_CRITSUSPEND);
PMEV_DEBUGMESSAGE(PMEV_USERSUSPENDREQ);
PMEV_DEBUGMESSAGE(PMEV_STANDBYRESUME);
default:
printf("Unknown APM Event 0x%x\n", apm_event);
break;
}
#endif
switch (apm_event) {
case PMEV_NOEVENT:
case PMEV_STANDBYREQ:
case PMEV_POWERSTATECHANGE:
case PMEV_CRITSUSPEND:
case PMEV_USERSTANDBYREQ:
case PMEV_USERSUSPENDREQ:
break;
case PMEV_BATTERYLOW:
apm_battery_low();
break;
case PMEV_SUSPENDREQ:
apm_suspend_resume();
break;
case PMEV_NORMRESUME:
case PMEV_CRITRESUME:
case PMEV_UPDATETIME:
case PMEV_STANDBYRESUME:
inittodr(0); /* adjust time to RTC */
break;
}
}
resumed_event = 0;
}
/*
* Attach APM:
*
* Initialize APM driver (APM BIOS itself has been initialized in locore.s)
*/
int
apmattach(struct isa_device *dvp)
{
/* setup APM parameters */
minorversion = ((apm_version & 0x00f0) >> 4) * 10 + ((apm_version & 0x000f) >> 0);
majorversion = ((apm_version & 0xf000) >> 12) * 10 + ((apm_version & 0x0f00) >> 8);
intversion = INTVERSION(majorversion, minorversion);
cs32_base = (apm_cs32_base << 4) + KERNBASE;
cs16_base = (apm_cs16_base << 4) + KERNBASE;
ds_base = (apm_ds_base << 4) + KERNBASE;
cs_limit = apm_cs_limit;
ds_limit = apm_ds_limit;
cs_entry = apm_cs_entry;
idle_cpu = ((apm_flags & APM_CPUIDLE_SLOW) != 0);
disabled = ((apm_flags & APM_DISABLED) != 0);
disengaged = ((apm_flags & APM_DISENGAGED) != 0);
/* print bootstrap messages */
printf(" found APM BIOS version %d.%d\n", dvp->id_unit, majorversion, minorversion);
printf("apm%d: Code32 0x%08x, Code16 0x%08x, Data 0x%08x\n", dvp->id_unit, cs32_base, cs16_base, ds_base);
printf("apm%d: Code entry 0x%08x, Idling CPU %s, Management %s\n", dvp->id_unit, cs_entry, is_enabled(idle_cpu), is_enabled(!disabled));
/*
* APM 1.0 does not have:
*
* 1. segment limit parameters
*
* 2. engage/disengage operations
*/
if (intversion >= INTVERSION(1, 1)) {
printf("apm%d: Engaged control %s\n", dvp->id_unit, is_enabled(!disengaged));
}
else {
cs_limit = 0xffff;
ds_limit = 0xffff;
}
/* setup GDT */
setup_apm_gdt(cs32_base, cs16_base, ds_base, cs_limit, ds_limit);
/* setup entry point 48bit pointer */
apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL);
apm_addr.offset = cs_entry;
/* enable power management */
if (disabled) {
if (apm_enable_disable_pm(1)) {
printf("Warning: APM enable function failed! [%s]\n", apm_error());
}
}
/* engage power managment (APM 1.1 or later) */
if (intversion >= INTVERSION(1, 1) && disengaged) {
if (apm_engage_disengage_pm(1)) {
printf("Warning: APM engage function failed [%s]\n", apm_error());
}
}
apm_suspend_hook_init(apm_default_suspend, "default suspend", APM_MAX_ORDER);
apm_resume_hook_init (apm_default_resume , "default resume" , APM_MIN_ORDER);
apm_initialized = 1;
return 0;
}
int
apmopen(dev_t dev, int flag, int fmt, struct proc *p)
{
if (!apm_initialized) {
return ENXIO;
}
switch (minor(dev)) {
case 0: /* apm0 */
break;
defaults:
return (ENXIO);
}
return 0;
}
int
apmclose(dev_t dev, int flag, int fmt, struct proc *p)
{
return 0;
}
int
apmioctl(dev_t dev, int cmd, caddr_t addr, int flag, struct proc *p)
{
int error = 0;
int pl;
#if 0
printf("APM ioctl: minor = %d, cmd = 0x%x\n", minor(dev), cmd);
#endif
pl = splhigh();
if (minor(dev) != 0) {
return ENXIO;
}
if (!apm_initialized) {
return ENXIO;
}
switch (cmd) {
case APMIO_SUSPEND:
apm_suspend_resume();
break;
case APMIO_GETINFO:
if (apm_get_info((apm_info_t)addr)) {
error = ENXIO;
}
break;
case APMIO_DEFEQV:
if (apm_def_eqv((apm_eqv_event_t)addr)) {
error = ENOSPC;
}
break;
case APMIO_FLUSHEQV:
apm_flush_eqv();
break;
case APMIO_ENABLE:
apm_event_enable();
break;
case APMIO_DISABLE:
apm_event_disable();
break;
case APMIO_HALTCPU:
apm_halt_cpu();
break;
case APMIO_NOTHALTCPU:
apm_not_halt_cpu();
break;
default:
error = EINVAL;
break;
}
splx(pl);
return error;
}
#endif /* NAPM > 0 */

View 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>

View 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

View 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 */

View 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;
}

View 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

View 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)

View 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

View 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
View 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
View 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 */

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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. */

View File

@ -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;

View File

@ -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:

View File

@ -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, ");

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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
*/

View File

@ -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");
}
}

View File

@ -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 */

View File

@ -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) */
};
/*

View File

@ -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,

View File

@ -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 &&

View File

@ -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 */

View File

@ -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,

View File

@ -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 &&

View File

@ -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, ");