Index: /trunk/src/VBox/Devices/PC/BIOS/apm.c
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS/apm.c	(revision 42790)
+++ /trunk/src/VBox/Devices/PC/BIOS/apm.c	(revision 42791)
@@ -165,4 +165,14 @@
         // @todo: change connection state
         break;
+    case APM_PM_CONN:
+        // @todo: validate device ID
+        // @todo: validate current connection state
+        // @todo: change connection state
+        AX = APM_BIOS_SEG;              /* 16-bit PM code segment (RM segment base). */
+        BX = (uint16_t)apm_pm16_entry;  /* 16-bit PM entry point offset. */
+        CX = APM_BIOS_SEG;              /* 16-bit data segment. */
+        SI = APM_BIOS_SEG_LEN;          /* 16-bit PM code segment length. */
+        DI = APM_BIOS_SEG_LEN;          /* Data segment length. */
+        break;
     case APM_32_CONN:
         // @todo: validate device ID
Index: /trunk/src/VBox/Devices/PC/BIOS/apm_pm.asm
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS/apm_pm.asm	(revision 42790)
+++ /trunk/src/VBox/Devices/PC/BIOS/apm_pm.asm	(revision 42791)
@@ -124,8 +124,14 @@
 
 
+;; 16-bit protected mode APM entry point
+
+;; According to the APM spec, only CS (16-bit code selector) is defined.
+;; The data selector can be derived from it.
 
 apm_pm16_entry:
-		stc
-		retf			; return to 16-bit caller
+
+		mov	ah, 2		; mark as originating in 16-bit PM
+		
+					; fall through
 
 apm_pm16_entry_from_32:
@@ -144,6 +150,6 @@
 		pop	ds		; restore registers
 
-.386
-		retfd			; return to 32-bit code
+		retf			; return to caller - 16-bit return
+					; even to 32-bit thunk!
 
 _TEXT		ends
@@ -161,24 +167,28 @@
 ;; selector and the data selector can be derived from it.
 
+;; WARNING: To simplify matters, we use 16-bit far return to go from 32-bit
+;; code to 16-bit and back. As a consequence, the 32-bit APM code must lie
+;; below 64K boundary in the 32-bit APM code segment.
+
 apm_pm32_entry:
 
-;		cli
-;		hlt
-
 		push	ebp		; ebp is not used by APM
 
-		push	cs		; return address for 16-bit code
-		push	apm_pm32_back
+		mov	bp, cs		; return address for 16-bit code
+		push	bp
+		mov	ebp, apm_pm32_back
+		push	bp		; Note: 16:16 address!
 
 		push	cs
 		pop	ebp
 		add	ebp, 8		; calculate 16-bit code selector
-		push	ebp		; push 16-bit code selector
-
-		xor	ebp, ebp	; manually pad 16-bit offset
-		push	bp		; to a 32-bit value
-		push	apm_pm16_entry_from_32
+		push	bp		; push 16-bit code selector
+
+		mov	ebp, apm_pm16_entry_from_32
+		push	bp		; push 16-bit offset
 
 		mov	ah, 3		; mark as originating in 32-bit PM
+
+		db	66h		; force a 16-bit return
 		retf			; off to 16-bit code...
 
Index: /trunk/src/VBox/Devices/PC/BIOS/notes.txt
===================================================================
--- /trunk/src/VBox/Devices/PC/BIOS/notes.txt	(revision 42790)
+++ /trunk/src/VBox/Devices/PC/BIOS/notes.txt	(revision 42791)
@@ -45,4 +45,8 @@
 
 - PC DOS 6.x/7.x QCONFIG is a rare user of INT 16h fn 0Ah (read keyboard ID).
+
+- DOS POWER.EXE uses the real mode APM interface, OS/2 APM.SYS uses the 16-bit
+  protected mode APM interface, and Windows 9x uses the 32-bit protected mode
+  APM interface.
 
 - Windows 98 is one of the few APM 1.2 users; Windows 95 uses APM 1.1, while
