summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/pm/ntdrv
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/pm/ntdrv')
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm288
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/_pm.asm281
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/cpuinfo.c65
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/int86.c252
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/irq.c143
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/mem.c519
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/oshdr.h46
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/pm.c934
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdio.c331
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdlib.c140
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/vflat.c45
-rw-r--r--board/MAI/bios_emulator/scitech/src/pm/ntdrv/ztimer.c124
12 files changed, 3168 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm
new file mode 100644
index 0000000000..11824a0afc
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_irq.asm
@@ -0,0 +1,288 @@
+;****************************************************************************
+;*
+;* SciTech OS Portability Manager Library
+;*
+;* ========================================================================
+;*
+;* The contents of this file are subject to the SciTech MGL Public
+;* License Version 1.0 (the "License"); you may not use this file
+;* except in compliance with the License. You may obtain a copy of
+;* the License at http://www.scitechsoft.com/mgl-license.txt
+;*
+;* Software distributed under the License is distributed on an
+;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+;* implied. See the License for the specific language governing
+;* rights and limitations under the License.
+;*
+;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+;*
+;* The Initial Developer of the Original Code is SciTech Software, Inc.
+;* All Rights Reserved.
+;*
+;* ========================================================================
+;*
+;* Language: 80386 Assembler, TASM 4.0 or NASM
+;* Environment: 32-bit Windows NT device driver
+;*
+;* Description: Low level assembly support for the PM library specific to
+;* Windows NT device drivers.
+;*
+;****************************************************************************
+
+ IDEAL
+
+include "scitech.mac" ; Memory model macros
+
+header _irq ; Set up memory model
+
+begdataseg _irq
+
+ cextern _PM_rtcHandler,CPTR
+ cextern _PM_prevRTC,FCPTR
+
+RtcInside dw 0 ; Are we still handling current interrupt
+sidtBuf df 0 ; Buffer for sidt instruction
+
+enddataseg _irq
+
+begcodeseg _irq ; Start of code segment
+
+cpublic _PM_irqCodeStart
+
+; Macro to delay briefly to ensure that enough time has elapsed between
+; successive I/O accesses so that the device being accessed can respond
+; to both accesses even on a very fast PC.
+
+ifdef USE_NASM
+%macro DELAY 0
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+%endmacro
+%macro IODELAYN 1
+%rep %1
+ DELAY
+%endrep
+%endmacro
+else
+macro DELAY
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+endm
+macro IODELAYN N
+ rept N
+ DELAY
+ endm
+endm
+endif
+
+;----------------------------------------------------------------------------
+; PM_rtcISR - Real time clock interrupt subroutine dispatcher
+;----------------------------------------------------------------------------
+; Hardware interrupt handler for the timer interrupt, to dispatch control
+; to high level C based subroutines. We save the state of all registers
+; in this routine, and switch to a local stack. Interrupts are *off*
+; when we call the user code.
+;
+; NOTE: This routine switches to a local stack before calling any C code,
+; and hence is _not_ re-entrant. Make sure your C code executes as
+; quickly as possible, since a timer overrun will simply hang the
+; system.
+;----------------------------------------------------------------------------
+cprocfar _PM_rtcISR
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; If we enable interrupts and call into any C based interrupt handling code,
+; we need to setup a bunch of important information for the NT kernel. The
+; code below takes care of this housekeeping for us (see Undocumented NT for
+; details). If we don't do this housekeeping and interrupts are enabled,
+; the kernel will become very unstable and crash within 10 seconds or so.
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+ pushad
+ pushfd
+ push fs
+
+ mov ebx,00000030h
+ mov fs,bx
+ sub esp,50h
+ mov ebp,esp
+
+; Setup the exception frame to NULL
+
+ mov ebx,[DWORD cs:0FFDFF000h]
+ mov [DWORD ds:0FFDFF000h], 0FFFFFFFFh
+ mov [DWORD ebp],ebx
+
+; Save away the existing KSS ebp
+
+ mov esi,[DWORD cs:0FFDFF124h]
+ mov ebx,[DWORD esi+00000128h]
+ mov [DWORD ebp+4h],ebx
+ mov [DWORD esi+00000128h],ebp
+
+; Save away the kernel time and the thread mode (kernel/user)
+
+ mov edi,[DWORD esi+00000137h]
+ mov [DWORD ebp+8h],edi
+
+; Set the thread mode (kernel/user) based on the code selector
+
+ mov ebx,[DWORD ebp+7Ch]
+ and ebx,01
+ mov [BYTE esi+00000137h],bl
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; End of special interrupt Prolog code
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+; Clear priority interrupt controller and re-enable interrupts so we
+; dont lock things up for long.
+
+ mov al,20h
+ out 0A0h,al
+ out 020h,al
+
+; Clear real-time clock timeout
+
+ in al,70h ; Read CMOS index register
+ push eax ; and save for later
+ IODELAYN 3
+ mov al,0Ch
+ out 70h,al
+ IODELAYN 5
+ in al,71h
+
+; Call the C interrupt handler function
+
+ cmp [BYTE RtcInside],1 ; Check for mutual exclusion
+ je @@Exit
+ mov [BYTE RtcInside],1
+ sti ; Enable interrupts
+ cld ; Clear direction flag for C code
+ call [CPTR _PM_rtcHandler]
+ cli ; Disable interrupts on exit!
+ mov [BYTE RtcInside],0
+
+@@Exit: pop eax
+ out 70h,al ; Restore CMOS index register
+
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+; Start of special epilog code to restore stuff on exit from handler
+;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+; Restore the KSS ebp
+
+ mov esi,[DWORD cs:0FFDFF124h]
+ mov ebx,[DWORD ebp+4]
+ mov [DWORD esi+00000128h],ebx
+
+; Restore the exception frame
+
+ mov ebx,[DWORD ebp]
+ mov [DWORD fs:00000000],ebx
+
+; Restore the thread mode
+
+ mov ebx,[DWORD ebp+8h]
+ mov esi,[DWORD fs:00000124h]
+ mov [BYTE esi+00000137h],bl
+ add esp, 50h
+ pop fs
+ popfd
+ popad
+
+; Return from interrupt
+
+ iret
+
+cprocend
+
+cpublic _PM_irqCodeEnd
+
+;----------------------------------------------------------------------------
+; void _PM_getISR(int irq,PMFARPTR *handler);
+;----------------------------------------------------------------------------
+; Function to return the specific IRQ handler direct from the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_getISR
+
+ ARG idtEntry:UINT, handler:DPTR
+
+ enter_c 0
+ mov ecx,[handler] ; Get address of handler to fill in
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ movzx edx,[WORD eax+6] ; Get high order 16-bits
+ shl edx,16 ; Move into top 16-bits of address
+ mov dx,[WORD eax] ; Get low order 16-bits
+ mov [DWORD ecx],edx ; Store linear address of handler
+ mov dx,[WORD eax+2] ; Get selector value
+ mov [WORD ecx+4],dx ; Store selector value
+ leave_c
+ ret
+
+cprocend _PM_getISR
+
+;----------------------------------------------------------------------------
+; void _PM_setISR(int irq,void *handler);
+;----------------------------------------------------------------------------
+; Function to set the specific IRQ handler direct in the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_setISR
+
+ ARG irq:UINT, handler:CPTR
+
+ enter_c 0
+ mov ecx,[handler] ; Get address of new handler
+ mov dx,cs ; Get selector for new handler
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ cli
+ mov [WORD eax+2],dx ; Store code segment selector
+ mov [WORD eax],cx ; Store low order bits of handler
+ shr ecx,16
+ mov [WORD eax+6],cx ; Store high order bits of handler
+ sti
+ leave_c
+ ret
+
+cprocend _PM_setISR
+
+;----------------------------------------------------------------------------
+; void _PM_restoreISR(int irq,PMFARPTR *handler);
+;----------------------------------------------------------------------------
+; Function to set the specific IRQ handler direct in the IDT.
+;----------------------------------------------------------------------------
+cprocstart _PM_restoreISR
+
+ ARG irq:UINT, handler:CPTR
+
+ enter_c 0
+ mov ecx,[handler]
+ mov dx,[WORD ecx+4] ; Get selector for old handler
+ mov ecx,[DWORD ecx] ; Get address of old handler
+ sidt [sidtBuf] ; Get IDTR register into sidtBuf
+ mov eax,[DWORD sidtBuf+2] ; Get address of IDT into EAX
+ mov ebx,[idtEntry]
+ lea eax,[eax+ebx*8] ; Get entry in the IDT
+ cli
+ mov [WORD eax+2],dx ; Store code segment selector
+ mov [WORD eax],cx ; Store low order bits of handler
+ shr ecx,16
+ mov [WORD eax+6],cx ; Store high order bits of handler
+ sti
+ leave_c
+ ret
+
+cprocend _PM_restoreISR
+
+endcodeseg _irq
+
+ END ; End of module
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_pm.asm b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_pm.asm
new file mode 100644
index 0000000000..6cb276d25e
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/_pm.asm
@@ -0,0 +1,281 @@
+;****************************************************************************
+;*
+;* SciTech OS Portability Manager Library
+;*
+;* ========================================================================
+;*
+;* The contents of this file are subject to the SciTech MGL Public
+;* License Version 1.0 (the "License"); you may not use this file
+;* except in compliance with the License. You may obtain a copy of
+;* the License at http://www.scitechsoft.com/mgl-license.txt
+;*
+;* Software distributed under the License is distributed on an
+;* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+;* implied. See the License for the specific language governing
+;* rights and limitations under the License.
+;*
+;* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+;*
+;* The Initial Developer of the Original Code is SciTech Software, Inc.
+;* All Rights Reserved.
+;*
+;* ========================================================================
+;*
+;* Language: 80386 Assembler, TASM 4.0 or NASM
+;* Environment: 32-bit Windows NT device driver
+;*
+;* Description: Low level assembly support for the PM library specific to
+;* Windows NT device drivers.
+;*
+;****************************************************************************
+
+ IDEAL
+
+include "scitech.mac" ; Memory model macros
+
+header _pm ; Set up memory model
+
+P586
+
+begdataseg
+
+; Watcom C++ externals required to link when compiling floating point
+; C code. They are not actually used in the code because we compile with
+; inline floating point instructions, however the compiler still generates
+; the references in the object modules.
+
+__8087 dd 0
+ PUBLIC __8087
+__imthread:
+__fltused:
+_fltused_ dd 0
+ PUBLIC __imthread
+ PUBLIC _fltused_
+ PUBLIC __fltused
+
+enddataseg
+
+begcodeseg _pm ; Start of code segment
+
+;----------------------------------------------------------------------------
+; void PM_segread(PMSREGS *sregs)
+;----------------------------------------------------------------------------
+; Read the current value of all segment registers
+;----------------------------------------------------------------------------
+cprocstart PM_segread
+
+ ARG sregs:DPTR
+
+ enter_c
+
+ mov ax,es
+ _les _si,[sregs]
+ mov [_ES _si],ax
+ mov [_ES _si+2],cs
+ mov [_ES _si+4],ss
+ mov [_ES _si+6],ds
+ mov [_ES _si+8],fs
+ mov [_ES _si+10],gs
+
+ leave_c
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; int PM_int386x(int intno, PMREGS *in, PMREGS *out,PMSREGS *sregs)
+;----------------------------------------------------------------------------
+; Issues a software interrupt in protected mode. This routine has been
+; written to allow user programs to load CS and DS with different values
+; other than the default.
+;----------------------------------------------------------------------------
+cprocstart PM_int386x
+
+; Not used for NT device drivers
+
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; void PM_setBankA(int bank)
+;----------------------------------------------------------------------------
+cprocstart PM_setBankA
+
+; Not used for NT device drivers
+
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; void PM_setBankAB(int bank)
+;----------------------------------------------------------------------------
+cprocstart PM_setBankAB
+
+; Not used for NT device drivers
+
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; void PM_setCRTStart(int x,int y,int waitVRT)
+;----------------------------------------------------------------------------
+cprocstart PM_setCRTStart
+
+; Not used for NT device drivers
+
+ ret
+
+cprocend
+
+; Macro to delay briefly to ensure that enough time has elapsed between
+; successive I/O accesses so that the device being accessed can respond
+; to both accesses even on a very fast PC.
+
+ifdef USE_NASM
+%macro DELAY 0
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+%endmacro
+%macro IODELAYN 1
+%rep %1
+ DELAY
+%endrep
+%endmacro
+else
+macro DELAY
+ jmp short $+2
+ jmp short $+2
+ jmp short $+2
+endm
+macro IODELAYN N
+ rept N
+ DELAY
+ endm
+endm
+endif
+
+;----------------------------------------------------------------------------
+; uchar _PM_readCMOS(int index)
+;----------------------------------------------------------------------------
+; Read the value of a specific CMOS register. We do this with both
+; normal interrupts and NMI disabled.
+;----------------------------------------------------------------------------
+cprocstart _PM_readCMOS
+
+ ARG index:UINT
+
+ push _bp
+ mov _bp,_sp
+ pushfd
+ mov al,[BYTE index]
+ or al,80h ; Add disable NMI flag
+ cli
+ out 70h,al
+ IODELAYN 5
+ in al,71h
+ mov ah,al
+ xor al,al
+ IODELAYN 5
+ out 70h,al ; Re-enable NMI
+ mov al,ah ; Return value in AL
+ popfd
+ pop _bp
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; void _PM_writeCMOS(int index,uchar value)
+;----------------------------------------------------------------------------
+; Read the value of a specific CMOS register. We do this with both
+; normal interrupts and NMI disabled.
+;----------------------------------------------------------------------------
+cprocstart _PM_writeCMOS
+
+ ARG index:UINT, value:UCHAR
+
+ push _bp
+ mov _bp,_sp
+ pushfd
+ mov al,[BYTE index]
+ or al,80h ; Add disable NMI flag
+ cli
+ out 70h,al
+ IODELAYN 5
+ mov al,[value]
+ out 71h,al
+ xor al,al
+ IODELAYN 5
+ out 70h,al ; Re-enable NMI
+ popfd
+ pop _bp
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; double _ftol(double f)
+;----------------------------------------------------------------------------
+; Calls to __ftol are generated by the Borland C++ compiler for code
+; that needs to convert a floating point type to an integral type.
+;
+; Input: floating point number on the top of the '87.
+;
+; Output: a (signed or unsigned) long in EAX
+; All other registers preserved.
+;-----------------------------------------------------------------------
+cprocstart _ftol
+
+ LOCAL temp1:WORD, temp2:QWORD = LocalSize
+
+ push ebp
+ mov ebp,esp
+ sub esp,LocalSize
+
+ fstcw [temp1] ; save the control word
+ fwait
+ mov al,[BYTE temp1+1]
+ or [BYTE temp1+1],0Ch ; set rounding control to chop
+ fldcw [temp1]
+ fistp [temp2] ; convert to 64-bit integer
+ mov [BYTE temp1+1],al
+ fldcw [temp1] ; restore the control word
+ mov eax,[DWORD temp2] ; return LS 32 bits
+ mov edx,[DWORD temp2+4] ; MS 32 bits
+
+ mov esp,ebp
+ pop ebp
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; _PM_getPDB - Return the Page Table Directory Base address
+;----------------------------------------------------------------------------
+cprocstart _PM_getPDB
+
+ mov eax,cr3
+ and eax,0FFFFF000h
+ ret
+
+cprocend
+
+;----------------------------------------------------------------------------
+; Flush the Translation Lookaside buffer
+;----------------------------------------------------------------------------
+cprocstart PM_flushTLB
+
+ wbinvd ; Flush the CPU cache
+ mov eax,cr3
+ mov cr3,eax ; Flush the TLB
+ ret
+
+cprocend
+
+endcodeseg _pm
+
+ END ; End of module
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/cpuinfo.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/cpuinfo.c
new file mode 100644
index 0000000000..e72a856019
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/cpuinfo.c
@@ -0,0 +1,65 @@
+/****************************************************************************
+*
+* Ultra Long Period Timer
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows VxD
+*
+* Description: VxD specific code for the CPU detection module.
+*
+****************************************************************************/
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Do nothing for VxD's
+****************************************************************************/
+#define SetMaxThreadPriority() 0
+
+/****************************************************************************
+REMARKS:
+Do nothing for VxD's
+****************************************************************************/
+#define RestoreThreadPriority(i) (void)(i)
+
+/****************************************************************************
+REMARKS:
+Initialise the counter and return the frequency of the counter.
+****************************************************************************/
+static void GetCounterFrequency(
+ CPU_largeInteger *freq)
+{
+ KeQueryPerformanceCounter((LARGE_INTEGER*)freq);
+}
+
+/****************************************************************************
+REMARKS:
+Read the counter and return the counter value.
+****************************************************************************/
+#define GetCounter(t) \
+{ \
+ LARGE_INTEGER lt = KeQueryPerformanceCounter(NULL); \
+ (t)->low = lt.LowPart; \
+ (t)->high = lt.HighPart; \
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/int86.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/int86.c
new file mode 100644
index 0000000000..f93d9c22e7
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/int86.c
@@ -0,0 +1,252 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT device drivers.
+*
+* Description: Implementation for the real mode software interrupt
+* handling functions.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "drvlib/os/os.h"
+#include "sdd/sddhelp.h"
+#include "mtrr.h"
+#include "oshdr.h"
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+We do have limited BIOS access under Windows NT device drivers.
+****************************************************************************/
+ibool PMAPI PM_haveBIOSAccess(void)
+{
+ // Return false unless we have full buffer passing!
+ return false;
+}
+
+/****************************************************************************
+PARAMETERS:
+len - Place to store the length of the buffer
+rseg - Place to store the real mode segment of the buffer
+roff - Place to store the real mode offset of the buffer
+
+REMARKS:
+This function returns the address and length of the global VESA transfer
+buffer that is used for communicating with the VESA BIOS functions from
+Win16 and Win32 programs under Windows.
+****************************************************************************/
+void * PMAPI PM_getVESABuf(
+ uint *len,
+ uint *rseg,
+ uint *roff)
+{
+ // No buffers supported under Windows NT (Windows XP has them however if
+ // we ever decide to support this!)
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Issue a protected mode software interrupt.
+****************************************************************************/
+int PMAPI PM_int386(
+ int intno,
+ PMREGS *in,
+ PMREGS *out)
+{
+ PMSREGS sregs;
+ PM_segread(&sregs);
+ return PM_int386x(intno,in,out,&sregs);
+}
+
+/****************************************************************************
+REMARKS:
+Map a real mode pointer to a protected mode pointer.
+****************************************************************************/
+void * PMAPI PM_mapRealPointer(
+ uint r_seg,
+ uint r_off)
+{
+ // Not used for Windows NT drivers!
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Allocate a block of real mode memory
+****************************************************************************/
+void * PMAPI PM_allocRealSeg(
+ uint size,
+ uint *r_seg,
+ uint *r_off)
+{
+ // Not supported in NT drivers
+ (void)size;
+ (void)r_seg;
+ (void)r_off;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Free a block of real mode memory.
+****************************************************************************/
+void PMAPI PM_freeRealSeg(
+ void *mem)
+{
+ // Not supported in NT drivers
+ (void)mem;
+}
+
+/****************************************************************************
+REMARKS:
+Issue a real mode interrupt (parameters in DPMI compatible structure)
+****************************************************************************/
+void PMAPI DPMI_int86(
+ int intno,
+ DPMI_regs *regs)
+{
+ // Not used in NT drivers
+}
+
+/****************************************************************************
+REMARKS:
+Call a V86 real mode function with the specified register values
+loaded before the call. The call returns with a far ret.
+****************************************************************************/
+void PMAPI PM_callRealMode(
+ uint seg,
+ uint off,
+ RMREGS *regs,
+ RMSREGS *sregs)
+{
+ // TODO!!
+#if 0
+ CLIENT_STRUCT saveRegs;
+
+ /* Bail if we do not have BIOS access (ie: the VxD was dynamically
+ * loaded, and not statically loaded.
+ */
+ if (!_PM_haveBIOS)
+ return;
+
+ TRACE("SDDHELP: Entering PM_callRealMode()\n");
+ Begin_Nest_V86_Exec();
+ LoadV86Registers(&saveRegs,regs,sregs);
+ Simulate_Far_Call(seg, off);
+ Resume_Exec();
+ ReadV86Registers(&saveRegs,regs,sregs);
+ End_Nest_Exec();
+ TRACE("SDDHELP: Exiting PM_callRealMode()\n");
+#endif
+}
+
+/****************************************************************************
+REMARKS:
+Issue a V86 real mode interrupt with the specified register values
+loaded before the interrupt.
+****************************************************************************/
+int PMAPI PM_int86(
+ int intno,
+ RMREGS *in,
+ RMREGS *out)
+{
+ // TODO!!
+#if 0
+ RMSREGS sregs = {0};
+ CLIENT_STRUCT saveRegs;
+ ushort oldDisable;
+
+ /* Disable pass-up to our VxD handler so we directly call BIOS */
+ TRACE("SDDHELP: Entering PM_int86()\n");
+ if (disableTSRFlag) {
+ oldDisable = *disableTSRFlag;
+ *disableTSRFlag = 0;
+ }
+ Begin_Nest_V86_Exec();
+ LoadV86Registers(&saveRegs,in,&sregs);
+ Exec_Int(intno);
+ ReadV86Registers(&saveRegs,out,&sregs);
+ End_Nest_Exec();
+
+ /* Re-enable pass-up to our VxD handler if previously enabled */
+ if (disableTSRFlag)
+ *disableTSRFlag = oldDisable;
+
+ TRACE("SDDHELP: Exiting PM_int86()\n");
+#else
+ *out = *in;
+#endif
+ return out->x.ax;
+}
+
+/****************************************************************************
+REMARKS:
+Issue a V86 real mode interrupt with the specified register values
+loaded before the interrupt.
+****************************************************************************/
+int PMAPI PM_int86x(
+ int intno,
+ RMREGS *in,
+ RMREGS *out,
+ RMSREGS *sregs)
+{
+ // TODO!!
+#if 0
+ CLIENT_STRUCT saveRegs;
+ ushort oldDisable;
+
+ /* Bail if we do not have BIOS access (ie: the VxD was dynamically
+ * loaded, and not statically loaded.
+ */
+ if (!_PM_haveBIOS) {
+ *out = *in;
+ return out->x.ax;
+ }
+
+ /* Disable pass-up to our VxD handler so we directly call BIOS */
+ TRACE("SDDHELP: Entering PM_int86x()\n");
+ if (disableTSRFlag) {
+ oldDisable = *disableTSRFlag;
+ *disableTSRFlag = 0;
+ }
+ Begin_Nest_V86_Exec();
+ LoadV86Registers(&saveRegs,in,sregs);
+ Exec_Int(intno);
+ ReadV86Registers(&saveRegs,out,sregs);
+ End_Nest_Exec();
+
+ /* Re-enable pass-up to our VxD handler if previously enabled */
+ if (disableTSRFlag)
+ *disableTSRFlag = oldDisable;
+
+ TRACE("SDDHELP: Exiting PM_int86x()\n");
+#else
+ *out = *in;
+#endif
+ return out->x.ax;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/irq.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/irq.c
new file mode 100644
index 0000000000..bc6b4274df
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/irq.c
@@ -0,0 +1,143 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT device drivers.
+*
+* Description: Implementation for the NT driver IRQ management functions
+* for the PM library.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "pmint.h"
+#include "drvlib/os/os.h"
+#include "sdd/sddhelp.h"
+#include "mtrr.h"
+#include "oshdr.h"
+
+/*--------------------------- Global variables ----------------------------*/
+
+static int globalDataStart;
+static uchar _PM_oldCMOSRegA;
+static uchar _PM_oldCMOSRegB;
+static uchar _PM_oldRTCPIC2;
+static ulong RTC_idtEntry;
+PM_intHandler _PM_rtcHandler = NULL;
+PMFARPTR _VARAPI _PM_prevRTC = PMNULL;
+
+/*----------------------------- Implementation ----------------------------*/
+
+/* Functions to read and write CMOS registers */
+
+uchar _ASMAPI _PM_readCMOS(int index);
+void _ASMAPI _PM_writeCMOS(int index,uchar value);
+void _ASMAPI _PM_rtcISR(void);
+void _ASMAPI _PM_getISR(int irq,PMFARPTR *handler);
+void _ASMAPI _PM_setISR(int irq,void *handler);
+void _ASMAPI _PM_restoreISR(int irq,PMFARPTR *handler);
+void _ASMAPI _PM_irqCodeStart(void);
+void _ASMAPI _PM_irqCodeEnd(void);
+
+/****************************************************************************
+REMARKS:
+Set the real time clock frequency (for stereo modes).
+****************************************************************************/
+void PMAPI PM_setRealTimeClockFrequency(
+ int frequency)
+{
+ static short convert[] = {
+ 8192,
+ 4096,
+ 2048,
+ 1024,
+ 512,
+ 256,
+ 128,
+ 64,
+ 32,
+ 16,
+ 8,
+ 4,
+ 2,
+ -1,
+ };
+ int i;
+
+ /* First clear any pending RTC timeout if not cleared */
+ _PM_readCMOS(0x0C);
+ if (frequency == 0) {
+ /* Disable RTC timout */
+ _PM_writeCMOS(0x0A,(uchar)_PM_oldCMOSRegA);
+ _PM_writeCMOS(0x0B,(uchar)(_PM_oldCMOSRegB & 0x0F));
+ }
+ else {
+ /* Convert frequency value to RTC clock indexes */
+ for (i = 0; convert[i] != -1; i++) {
+ if (convert[i] == frequency)
+ break;
+ }
+
+ /* Set RTC timout value and enable timeout */
+ _PM_writeCMOS(0x0A,(uchar)(0x20 | (i+3)));
+ _PM_writeCMOS(0x0B,(uchar)((_PM_oldCMOSRegB & 0x0F) | 0x40));
+ }
+}
+
+ibool PMAPI PM_setRealTimeClockHandler(PM_intHandler th,int frequency)
+{
+ static ibool locked = false;
+
+ /* Save the old CMOS real time clock values */
+ _PM_oldCMOSRegA = _PM_readCMOS(0x0A);
+ _PM_oldCMOSRegB = _PM_readCMOS(0x0B);
+
+ /* Install the interrupt handler */
+ RTC_idtEntry = 0x38;
+ _PM_getISR(RTC_idtEntry, &_PM_prevRTC);
+ _PM_rtcHandler = th;
+ _PM_setISR(RTC_idtEntry, _PM_rtcISR);
+
+ /* Program the real time clock default frequency */
+ PM_setRealTimeClockFrequency(frequency);
+
+ /* Unmask IRQ8 in the PIC2 */
+ _PM_oldRTCPIC2 = PM_inpb(0xA1);
+ PM_outpb(0xA1,(uchar)(_PM_oldRTCPIC2 & 0xFE));
+ return true;
+}
+
+void PMAPI PM_restoreRealTimeClockHandler(void)
+{
+ if (_PM_rtcHandler) {
+ /* Restore CMOS registers and mask RTC clock */
+ _PM_writeCMOS(0x0A,_PM_oldCMOSRegA);
+ _PM_writeCMOS(0x0B,_PM_oldCMOSRegB);
+ PM_outpb(0xA1,(uchar)((PM_inpb(0xA1) & 0xFE) | (_PM_oldRTCPIC2 & ~0xFE)));
+
+ /* Restore the interrupt vector */
+ _PM_restoreISR(RTC_idtEntry, &_PM_prevRTC);
+ _PM_rtcHandler = NULL;
+ }
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/mem.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/mem.c
new file mode 100644
index 0000000000..b30d2be860
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/mem.c
@@ -0,0 +1,519 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT device drivers.
+*
+* Description: Implementation for the NT driver memory management functions
+* for the PM library.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "drvlib/os/os.h"
+#include "sdd/sddhelp.h"
+#include "mtrr.h"
+#include "oshdr.h"
+
+/*--------------------------- Global variables ----------------------------*/
+
+#define MAX_MEMORY_SHARED 100
+#define MAX_MEMORY_MAPPINGS 100
+#define MAX_MEMORY_LOCKED 100
+
+typedef struct {
+ void *linear;
+ ulong length;
+ PMDL pMdl;
+ } memshared;
+
+typedef struct {
+ void *linear;
+ void *mmIoMapped;
+ ulong length;
+ PMDL pMdl;
+ } memlocked;
+
+typedef struct {
+ ulong physical;
+ ulong linear;
+ ulong length;
+ ibool isCached;
+ } mmapping;
+
+static int numMappings = 0;
+static memshared shared[MAX_MEMORY_MAPPINGS] = {0};
+static mmapping maps[MAX_MEMORY_MAPPINGS];
+static memlocked locked[MAX_MEMORY_LOCKED];
+
+/*----------------------------- Implementation ----------------------------*/
+
+ulong PMAPI _PM_getPDB(void);
+
+// Page table entry flags
+
+#define PAGE_FLAGS_PRESENT 0x00000001
+#define PAGE_FLAGS_WRITEABLE 0x00000002
+#define PAGE_FLAGS_USER 0x00000004
+#define PAGE_FLAGS_WRITE_THROUGH 0x00000008
+#define PAGE_FLAGS_CACHE_DISABLE 0x00000010
+#define PAGE_FLAGS_ACCESSED 0x00000020
+#define PAGE_FLAGS_DIRTY 0x00000040
+#define PAGE_FLAGS_4MB 0x00000080
+
+/****************************************************************************
+PARAMETERS:
+base - Physical base address of the memory to maps in
+limit - Limit of physical memory to region to maps in
+
+RETURNS:
+Linear address of the newly mapped memory.
+
+REMARKS:
+Maps a physical memory range to a linear memory range.
+****************************************************************************/
+static ulong _PM_mapPhysicalToLinear(
+ ulong base,
+ ulong limit,
+ ibool isCached)
+{
+ ulong length = limit+1;
+ PHYSICAL_ADDRESS paIoBase = {0};
+
+ // NT loves large Ints
+ paIoBase = RtlConvertUlongToLargeInteger( base );
+
+ // Map IO space into Kernel
+ if (isCached)
+ return (ULONG)MmMapIoSpace(paIoBase, length, MmCached );
+ else
+ return (ULONG)MmMapIoSpace(paIoBase, length, MmNonCached );
+}
+
+/****************************************************************************
+REMARKS:
+Adjust the page table caching bits directly. Requires ring 0 access and
+only works with DOS4GW and compatible extenders (CauseWay also works since
+it has direct support for the ring 0 instructions we need from ring 3). Will
+not work in a DOS box, but we call into the ring 0 helper VxD so we should
+never get here in a DOS box anyway (assuming the VxD is present). If we
+do get here and we are in windows, this code will be skipped.
+****************************************************************************/
+static void _PM_adjustPageTables(
+ ulong linear,
+ ulong limit,
+ ibool isGlobal,
+ ibool isCached)
+{
+ int startPDB,endPDB,iPDB,startPage,endPage,start,end,iPage;
+ ulong pageTable,*pPDB,*pPageTable;
+ ulong mask = 0xFFFFFFFF;
+ ulong bits = 0x00000000;
+
+ /* Enable user level access for page table entry */
+ if (isGlobal) {
+ mask &= ~PAGE_FLAGS_USER;
+ bits |= PAGE_FLAGS_USER;
+ }
+
+ /* Disable PCD bit if page table entry should be uncached */
+ if (!isCached) {
+ mask &= ~(PAGE_FLAGS_CACHE_DISABLE | PAGE_FLAGS_WRITE_THROUGH);
+ bits |= (PAGE_FLAGS_CACHE_DISABLE | PAGE_FLAGS_WRITE_THROUGH);
+ }
+
+ pPDB = (ulong*)_PM_mapPhysicalToLinear(_PM_getPDB(),0xFFF,true);
+ if (pPDB) {
+ startPDB = (linear >> 22) & 0x3FF;
+ startPage = (linear >> 12) & 0x3FF;
+ endPDB = ((linear+limit) >> 22) & 0x3FF;
+ endPage = ((linear+limit) >> 12) & 0x3FF;
+ for (iPDB = startPDB; iPDB <= endPDB; iPDB++) {
+ // Set the bits in the page directory entry - required as per
+ // Pentium 4 manual. This also takes care of the 4MB page entries
+ pPDB[iPDB] = (pPDB[iPDB] & mask) | bits;
+ if (!(pPDB[iPDB] & PAGE_FLAGS_4MB)) {
+ // If we are dealing with 4KB pages then we need to iterate
+ // through each of the page table entries
+ pageTable = pPDB[iPDB] & ~0xFFF;
+ pPageTable = (ulong*)_PM_mapPhysicalToLinear(pageTable,0xFFF,true);
+ start = (iPDB == startPDB) ? startPage : 0;
+ end = (iPDB == endPDB) ? endPage : 0x3FF;
+ for (iPage = start; iPage <= end; iPage++) {
+ pPageTable[iPage] = (pPageTable[iPage] & mask) | bits;
+ }
+ MmUnmapIoSpace(pPageTable,0xFFF);
+ }
+ }
+ MmUnmapIoSpace(pPDB,0xFFF);
+ PM_flushTLB();
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Allocate a block of shared memory. For NT we allocate shared memory
+as locked, global memory that is accessible from any memory context
+(including interrupt time context), which allows us to load our important
+data structure and code such that we can access it directly from a ring
+0 interrupt context.
+****************************************************************************/
+void * PMAPI PM_mallocShared(
+ long size)
+{
+ int i;
+
+ // First find a free slot in our shared memory table
+ for (i = 0; i < MAX_MEMORY_SHARED; i++) {
+ if (shared[i].linear == 0)
+ break;
+ }
+ if (i == MAX_MEMORY_SHARED)
+ return NULL;
+
+ // Allocate the paged pool
+ shared[i].linear = ExAllocatePool(PagedPool, size);
+
+ // Create a list to manage this allocation
+ shared[i].pMdl = IoAllocateMdl(shared[i].linear,size,FALSE,FALSE,(PIRP) NULL);
+
+ // Lock this allocation in memory
+ MmProbeAndLockPages(shared[i].pMdl,KernelMode,IoModifyAccess);
+
+ // Modify bits to grant user access
+ _PM_adjustPageTables((ulong)shared[i].linear, size, true, true);
+ return (void*)shared[i].linear;
+}
+
+/****************************************************************************
+REMARKS:
+Free a block of shared memory
+****************************************************************************/
+void PMAPI PM_freeShared(
+ void *p)
+{
+ int i;
+
+ // Find a shared memory block in our table and free it
+ for (i = 0; i < MAX_MEMORY_SHARED; i++) {
+ if (shared[i].linear == p) {
+ // Unlock what we locked
+ MmUnlockPages(shared[i].pMdl);
+
+ // Free our MDL
+ IoFreeMdl(shared[i].pMdl);
+
+ // Free our mem
+ ExFreePool(shared[i].linear);
+
+ // Flag that is entry is available
+ shared[i].linear = 0;
+ break;
+ }
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Map a physical address to a linear address in the callers process.
+****************************************************************************/
+void * PMAPI PM_mapPhysicalAddr(
+ ulong base,
+ ulong limit,
+ ibool isCached)
+{
+ ulong linear,length = limit+1;
+ int i;
+
+ // Search table of existing mappings to see if we have already mapped
+ // a region of memory that will serve this purpose.
+ for (i = 0; i < numMappings; i++) {
+ if (maps[i].physical == base && maps[i].length == length && maps[i].isCached == isCached) {
+ _PM_adjustPageTables((ulong)maps[i].linear, maps[i].length, true, isCached);
+ return (void*)maps[i].linear;
+ }
+ }
+ if (numMappings == MAX_MEMORY_MAPPINGS)
+ return NULL;
+
+ // We did not find any previously mapped memory region, so maps it in.
+ if ((linear = _PM_mapPhysicalToLinear(base,limit,isCached)) == 0xFFFFFFFF)
+ return NULL;
+ maps[numMappings].physical = base;
+ maps[numMappings].length = length;
+ maps[numMappings].linear = linear;
+ maps[numMappings].isCached = isCached;
+ numMappings++;
+
+ // Grant user access to this I/O space
+ _PM_adjustPageTables((ulong)linear, length, true, isCached);
+ return (void*)linear;
+}
+
+/****************************************************************************
+REMARKS:
+Free a physical address mapping allocated by PM_mapPhysicalAddr.
+****************************************************************************/
+void PMAPI PM_freePhysicalAddr(
+ void *ptr,
+ ulong limit)
+{
+ // We don't free the memory mappings in here because we cache all
+ // the memory mappings we create in the system for later use.
+}
+
+/****************************************************************************
+REMARKS:
+Called when the device driver unloads to free all the page table mappings!
+****************************************************************************/
+void PMAPI _PM_freeMemoryMappings(void)
+{
+ int i;
+
+ for (i = 0; i < numMappings; i++)
+ MmUnmapIoSpace((void *)maps[i].linear,maps[i].length);
+}
+
+/****************************************************************************
+REMARKS:
+Find the physical address of a linear memory address in current process.
+****************************************************************************/
+ulong PMAPI PM_getPhysicalAddr(
+ void *p)
+{
+ PHYSICAL_ADDRESS paOurAddress;
+
+ paOurAddress = MmGetPhysicalAddress(p);
+ return paOurAddress.LowPart;
+}
+
+/****************************************************************************
+REMARKS:
+Find the physical address of a linear memory address in current process.
+****************************************************************************/
+ibool PMAPI PM_getPhysicalAddrRange(
+ void *p,
+ ulong length,
+ ulong *physAddress)
+{
+ int i;
+ ulong linear = (ulong)p & ~0xFFF;
+
+ for (i = (length + 0xFFF) >> 12; i > 0; i--) {
+ if ((*physAddress++ = PM_getPhysicalAddr((void*)linear)) == 0xFFFFFFFF)
+ return false;
+ linear += 4096;
+ }
+ return true;
+}
+
+/****************************************************************************
+REMARKS:
+Allocates a block of locked physical memory.
+****************************************************************************/
+void * PMAPI PM_allocLockedMem(
+ uint size,
+ ulong *physAddr,
+ ibool contiguous,
+ ibool below16M)
+{
+ int i;
+ PHYSICAL_ADDRESS paOurAddress;
+
+ // First find a free slot in our shared memory table
+ for (i = 0; i < MAX_MEMORY_LOCKED; i++) {
+ if (locked[i].linear == 0)
+ break;
+ }
+ if (i == MAX_MEMORY_LOCKED)
+ return NULL;
+
+ // HighestAcceptableAddress - Specifies the highest valid physical address
+ // the driver can use. For example, if a device can only reference physical
+ // memory in the lower 16MB, this value would be set to 0x00000000FFFFFF.
+ paOurAddress.HighPart = 0;
+ if (below16M)
+ paOurAddress.LowPart = 0x00FFFFFF;
+ else
+ paOurAddress.LowPart = 0xFFFFFFFF;
+
+ if (contiguous) {
+ // Allocate from the non-paged pool (unfortunately 4MB pages)
+ locked[i].linear = MmAllocateContiguousMemory(size, paOurAddress);
+ if (!locked[i].linear)
+ return NULL;
+
+ // Flag no MDL
+ locked[i].pMdl = NULL;
+
+ // Map the physical address for the memory so we can manage
+ // the page tables in 4KB chunks mapped into user space.
+
+ // TODO: Map this with the physical address to the linear addresss
+ locked[i].mmIoMapped = locked[i].linear;
+
+ // Modify bits to grant user access, flag not cached
+ _PM_adjustPageTables((ulong)locked[i].mmIoMapped, size, true, false);
+ return (void*)locked[i].mmIoMapped;
+ }
+ else {
+ // Allocate from the paged pool
+ locked[i].linear = ExAllocatePool(PagedPool, size);
+ if (!locked[i].linear)
+ return NULL;
+
+ // Create a list to manage this allocation
+ locked[i].pMdl = IoAllocateMdl(locked[i].linear,size,FALSE,FALSE,(PIRP) NULL);
+
+ // Lock this allocation in memory
+ MmProbeAndLockPages(locked[i].pMdl,KernelMode,IoModifyAccess);
+
+ // Modify bits to grant user access, flag not cached
+ _PM_adjustPageTables((ulong)locked[i].linear, size, true, false);
+ return (void*)locked[i].linear;
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Frees a block of locked physical memory.
+****************************************************************************/
+void PMAPI PM_freeLockedMem(
+ void *p,
+ uint size,
+ ibool contiguous)
+{
+ int i;
+
+ /* Find a locked memory block in our table and free it */
+ for (i = 0; i < MAX_MEMORY_LOCKED; i++) {
+ if (locked[i].linear == p) {
+ // An Mdl indicates that we used the paged pool, and locked it,
+ // so now we have to unlock, free the MDL, and free paged
+ if (locked[i].pMdl) {
+ // Unlock what we locked and free the Mdl
+ MmUnlockPages(locked[i].pMdl);
+ IoFreeMdl(locked[i].pMdl);
+ ExFreePool(locked[i].linear);
+ }
+ else {
+ // TODO: Free the mmIoMap mapping for the memory!
+
+ // Free non-paged pool
+ MmFreeContiguousMemory(locked[i].linear);
+ }
+
+ // Flag that is entry is available
+ locked[i].linear = 0;
+ break;
+ }
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Allocates a page aligned and page sized block of memory
+****************************************************************************/
+void * PMAPI PM_allocPage(
+ ibool locked)
+{
+ // Allocate the memory from the non-paged pool if we want the memory
+ // to be locked.
+ return ExAllocatePool(
+ locked ? NonPagedPoolCacheAligned : PagedPoolCacheAligned,
+ PAGE_SIZE);
+}
+
+/****************************************************************************
+REMARKS:
+Free a page aligned and page sized block of memory
+****************************************************************************/
+void PMAPI PM_freePage(
+ void *p)
+{
+ if (p) ExFreePool(p);
+}
+
+/****************************************************************************
+REMARKS:
+Lock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_lockDataPages(
+ void *p,
+ uint len,
+ PM_lockHandle *lh)
+{
+ MDL *pMdl;
+
+ // Create a list to manage this allocation
+ if ((pMdl = IoAllocateMdl(p,len,FALSE,FALSE,(PIRP)NULL)) == NULL)
+ return false;
+
+ // Lock this allocation in memory
+ MmProbeAndLockPages(pMdl,KernelMode,IoModifyAccess);
+ *((PMDL*)(&lh->h)) = pMdl;
+ return true;
+}
+
+/****************************************************************************
+REMARKS:
+Unlock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_unlockDataPages(
+ void *p,
+ uint len,
+ PM_lockHandle *lh)
+{
+ if (p && lh) {
+ // Unlock what we locked
+ MDL *pMdl = *((PMDL*)(&lh->h));
+ MmUnlockPages(pMdl);
+ IoFreeMdl(pMdl);
+ }
+ return true;
+}
+
+/****************************************************************************
+REMARKS:
+Lock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_lockCodePages(
+ void (*p)(),
+ uint len,
+ PM_lockHandle *lh)
+{
+ return PM_lockDataPages((void*)p,len,lh);
+}
+
+/****************************************************************************
+REMARKS:
+Unlock linear memory so it won't be paged.
+****************************************************************************/
+int PMAPI PM_unlockCodePages(
+ void (*p)(),
+ uint len,
+ PM_lockHandle *lh)
+{
+ return PM_unlockDataPages((void*)p,len,lh);
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/oshdr.h b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/oshdr.h
new file mode 100644
index 0000000000..3f747bb9ce
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/oshdr.h
@@ -0,0 +1,46 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT drivers
+*
+* Description: Include file to include all OS specific header files.
+*
+****************************************************************************/
+
+#ifndef __NTDRV_OSHDR_H
+#define __NTDRV_OSHDR_H
+
+/*--------------------------- Macros and Typedefs -------------------------*/
+
+/*---------------------------- Global variables ---------------------------*/
+
+/*--------------------------- Function Prototypes -------------------------*/
+
+/* Internal unicode string handling functions */
+
+UNICODE_STRING * _PM_CStringToUnicodeString(const char *cstr);
+void _PM_FreeUnicodeString(UNICODE_STRING *uniStr);
+
+#endif // __NTDRV_OSHDR_H
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/pm.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/pm.c
new file mode 100644
index 0000000000..d4bbe228b7
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/pm.c
@@ -0,0 +1,934 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT device drivers.
+*
+* Description: Implementation for the OS Portability Manager Library, which
+* contains functions to implement OS specific services in a
+* generic, cross platform API. Porting the OS Portability
+* Manager library is the first step to porting any SciTech
+* products to a new platform.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "drvlib/os/os.h"
+#include "sdd/sddhelp.h"
+#include "mtrr.h"
+#include "oshdr.h"
+
+/*--------------------------- Global variables ----------------------------*/
+
+char _PM_cntPath[PM_MAX_PATH] = "";
+char _PM_nucleusPath[PM_MAX_PATH] = "";
+static void (PMAPIP fatalErrorCleanup)(void) = NULL;
+
+static char *szNTWindowsKey = "\\REGISTRY\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion";
+static char *szNTSystemRoot = "SystemRoot";
+static char *szMachineNameKey = "\\REGISTRY\\Machine\\System\\CurrentControlSet\\control\\ComputerName\\ComputerName";
+static char *szMachineNameKeyNT = "\\REGISTRY\\Machine\\System\\CurrentControlSet\\control\\ComputerName\\ActiveComputerName";
+static char *szMachineName = "ComputerName";
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Initialise the PM library.
+****************************************************************************/
+void PMAPI PM_init(void)
+{
+ /* Initialiase the MTRR module */
+ MTRR_init();
+}
+
+/****************************************************************************
+REMARKS:
+Return the operating system type identifier.
+****************************************************************************/
+long PMAPI PM_getOSType(void)
+{
+ return _OS_WINNTDRV;
+}
+
+/****************************************************************************
+REMARKS:
+Return the runtime type identifier.
+****************************************************************************/
+int PMAPI PM_getModeType(void)
+{
+ return PM_386;
+}
+
+/****************************************************************************
+REMARKS:
+Add a file directory separator to the end of the filename.
+****************************************************************************/
+void PMAPI PM_backslash(char *s)
+{
+ uint pos = strlen(s);
+ if (s[pos-1] != '\\') {
+ s[pos] = '\\';
+ s[pos+1] = '\0';
+ }
+}
+
+/****************************************************************************
+REMARKS:
+Add a user defined PM_fatalError cleanup function.
+****************************************************************************/
+void PMAPI PM_setFatalErrorCleanup(
+ void (PMAPIP cleanup)(void))
+{
+ fatalErrorCleanup = cleanup;
+}
+
+/****************************************************************************
+REMARKS:
+Handle fatal errors internally in the driver.
+****************************************************************************/
+void PMAPI PM_fatalError(
+ const char *msg)
+{
+ ULONG BugCheckCode = 0;
+ ULONG MoreBugCheckData[4] = {0};
+ char *p;
+ ULONG len;
+
+ if (fatalErrorCleanup)
+ fatalErrorCleanup();
+
+#ifdef DBG // Send output to debugger, just return so as not to force a reboot
+#pragma message("INFO: building for debug, PM_fatalError() re-routed")
+ DBGMSG2("SDDHELP> PM_fatalError(): ERROR: %s\n", msg);
+ return ;
+#endif
+ // KeBugCheckEx brings down the system in a controlled
+ // manner when the caller discovers an unrecoverable
+ // inconsistency that would corrupt the system if
+ // the caller continued to run.
+ //
+ // hack - dump the first 20 chars in hex using the variables
+ // provided - Each ULONG is equal to four characters...
+ for(len = 0; len < 20; len++)
+ if (msg[len] == (char)0)
+ break;
+
+ // This looks bad but it's quick and reliable...
+ p = (char *)&BugCheckCode;
+ if(len > 0) p[3] = msg[0];
+ if(len > 1) p[2] = msg[1];
+ if(len > 2) p[1] = msg[2];
+ if(len > 3) p[0] = msg[3];
+
+ p = (char *)&MoreBugCheckData[0];
+ if(len > 4) p[3] = msg[4];
+ if(len > 5) p[2] = msg[5];
+ if(len > 6) p[1] = msg[6];
+ if(len > 7) p[0] = msg[7];
+
+ p = (char *)&MoreBugCheckData[1];
+ if(len > 8) p[3] = msg[8];
+ if(len > 9) p[2] = msg[9];
+ if(len > 10) p[1] = msg[10];
+ if(len > 11) p[0] = msg[11];
+
+ p = (char *)&MoreBugCheckData[2];
+ if(len > 12) p[3] = msg[12];
+ if(len > 13) p[2] = msg[13];
+ if(len > 14) p[1] = msg[14];
+ if(len > 15) p[0] = msg[15];
+
+ p = (char *)&MoreBugCheckData[3];
+ if(len > 16) p[3] = msg[16];
+ if(len > 17) p[2] = msg[17];
+ if(len > 18) p[1] = msg[18];
+ if(len > 19) p[0] = msg[19];
+
+ // Halt the system!
+ KeBugCheckEx(BugCheckCode, MoreBugCheckData[0], MoreBugCheckData[1], MoreBugCheckData[2], MoreBugCheckData[3]);
+}
+
+/****************************************************************************
+REMARKS:
+Return the current operating system path or working directory.
+****************************************************************************/
+char * PMAPI PM_getCurrentPath(
+ char *path,
+ int maxLen)
+{
+ strncpy(path,_PM_cntPath,maxLen);
+ path[maxLen-1] = 0;
+ return path;
+}
+
+/****************************************************************************
+PARAMETERS:
+szKey - Key to query (can contain version number formatting)
+szValue - Value to get information for
+value - Place to store the registry key data read
+size - Size of the string buffer to read into
+
+RETURNS:
+true if the key was found, false if not.
+****************************************************************************/
+static ibool REG_queryString(
+ char *szKey,
+ const char *szValue,
+ char *value,
+ DWORD size)
+{
+ ibool status;
+ NTSTATUS rval;
+ ULONG length;
+ HANDLE Handle;
+ OBJECT_ATTRIBUTES keyAttributes;
+ UNICODE_STRING *uniKey = NULL;
+ UNICODE_STRING *uniValue = NULL;
+ PKEY_VALUE_FULL_INFORMATION fullInfo = NULL;
+ STRING stringdata;
+ UNICODE_STRING unidata;
+
+ // Convert strings to UniCode
+ status = false;
+ if ((uniKey = _PM_CStringToUnicodeString(szKey)) == NULL)
+ goto Exit;
+ if ((uniValue = _PM_CStringToUnicodeString(szValue)) == NULL)
+ goto Exit;
+
+ // Open the key
+ InitializeObjectAttributes( &keyAttributes,
+ uniKey,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+ rval = ZwOpenKey( &Handle,
+ KEY_ALL_ACCESS,
+ &keyAttributes );
+ if (!NT_SUCCESS(rval))
+ goto Exit;
+
+ // Query the value
+ length = sizeof (KEY_VALUE_FULL_INFORMATION)
+ + size * sizeof(WCHAR);
+ if ((fullInfo = ExAllocatePool (PagedPool, length)) == NULL)
+ goto Exit;
+ RtlZeroMemory(fullInfo, length);
+ rval = ZwQueryValueKey (Handle,
+ uniValue,
+ KeyValueFullInformation,
+ fullInfo,
+ length,
+ &length);
+ if (NT_SUCCESS (rval)) {
+ // Create the UniCode string so we can convert it
+ unidata.Buffer = (PWCHAR)(((PCHAR)fullInfo) + fullInfo->DataOffset);
+ unidata.Length = (USHORT)fullInfo->DataLength;
+ unidata.MaximumLength = (USHORT)fullInfo->DataLength + sizeof(WCHAR);
+
+ // Convert unicode univalue to ansi string.
+ rval = RtlUnicodeStringToAnsiString(&stringdata, &unidata, TRUE);
+ if (NT_SUCCESS(rval)) {
+ strcpy(value,stringdata.Buffer);
+ status = true;
+ }
+ }
+
+Exit:
+ if (fullInfo) ExFreePool(fullInfo);
+ if (uniKey) _PM_FreeUnicodeString(uniKey);
+ if (uniValue) _PM_FreeUnicodeString(uniValue);
+ return status;
+}
+
+/****************************************************************************
+REMARKS:
+Return the drive letter for the boot drive.
+****************************************************************************/
+char PMAPI PM_getBootDrive(void)
+{
+ char path[256];
+ if (REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
+ return 'c';
+ return path[0];
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the VBE/AF driver files.
+****************************************************************************/
+const char * PMAPI PM_getVBEAFPath(void)
+{
+ return "c:\\";
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the Nucleus driver files.
+****************************************************************************/
+const char * PMAPI PM_getNucleusPath(void)
+{
+ static char path[256];
+
+ if (strlen(_PM_nucleusPath) > 0) {
+ strcpy(path,_PM_nucleusPath);
+ PM_backslash(path);
+ return path;
+ }
+ if (!REG_queryString(szNTWindowsKey,szNTSystemRoot,path,sizeof(path)))
+ strcpy(path,"c:\\winnt");
+ PM_backslash(path);
+ strcat(path,"system32\\nucleus");
+ return path;
+}
+
+/****************************************************************************
+REMARKS:
+Return the path to the Nucleus configuration files.
+****************************************************************************/
+const char * PMAPI PM_getNucleusConfigPath(void)
+{
+ static char path[256];
+ strcpy(path,PM_getNucleusPath());
+ PM_backslash(path);
+ strcat(path,"config");
+ return path;
+}
+
+/****************************************************************************
+REMARKS:
+Return a unique identifier for the machine if possible.
+****************************************************************************/
+const char * PMAPI PM_getUniqueID(void)
+{
+ return PM_getMachineName();
+}
+
+/****************************************************************************
+REMARKS:
+Get the name of the machine on the network.
+****************************************************************************/
+const char * PMAPI PM_getMachineName(void)
+{
+ static char name[256];
+
+ if (REG_queryString(szMachineNameKey,szMachineName,name,sizeof(name)))
+ return name;
+ if (REG_queryString(szMachineNameKeyNT,szMachineName,name,sizeof(name)))
+ return name;
+ return "Unknown";
+}
+
+/****************************************************************************
+REMARKS:
+Check if a key has been pressed.
+****************************************************************************/
+int PMAPI PM_kbhit(void)
+{
+ // Not used in NT drivers
+ return true;
+}
+
+/****************************************************************************
+REMARKS:
+Wait for and return the next keypress.
+****************************************************************************/
+int PMAPI PM_getch(void)
+{
+ // Not used in NT drivers
+ return 0xD;
+}
+
+/****************************************************************************
+REMARKS:
+Open a console for output to the screen, creating the main event handling
+window if necessary.
+****************************************************************************/
+PM_HWND PMAPI PM_openConsole(
+ PM_HWND hwndUser,
+ int device,
+ int xRes,
+ int yRes,
+ int bpp,
+ ibool fullScreen)
+{
+ // Not used in NT drivers
+ (void)hwndUser;
+ (void)device;
+ (void)xRes;
+ (void)yRes;
+ (void)bpp;
+ (void)fullScreen;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Find the size of the console state buffer.
+****************************************************************************/
+int PMAPI PM_getConsoleStateSize(void)
+{
+ // Not used in NT drivers
+ return 1;
+}
+
+/****************************************************************************
+REMARKS:
+Save the state of the console.
+****************************************************************************/
+void PMAPI PM_saveConsoleState(
+ void *stateBuf,
+ PM_HWND hwndConsole)
+{
+ // Not used in NT drivers
+ (void)stateBuf;
+ (void)hwndConsole;
+}
+
+/****************************************************************************
+REMARKS:
+Set the suspend application callback for the fullscreen console.
+****************************************************************************/
+void PMAPI PM_setSuspendAppCallback(
+ PM_saveState_cb saveState)
+{
+ // Not used in NT drivers
+ (void)saveState;
+}
+
+/****************************************************************************
+REMARKS:
+Restore the console state.
+****************************************************************************/
+void PMAPI PM_restoreConsoleState(
+ const void *stateBuf,
+ PM_HWND hwndConsole)
+{
+ // Not used in NT drivers
+ (void)stateBuf;
+ (void)hwndConsole;
+}
+
+/****************************************************************************
+REMARKS:
+Close the fullscreen console.
+****************************************************************************/
+void PMAPI PM_closeConsole(
+ PM_HWND hwndConsole)
+{
+ // Not used in NT drivers
+ (void)hwndConsole;
+}
+
+/****************************************************************************
+REMARKS:
+Set the location of the OS console cursor.
+****************************************************************************/
+void PMAPI PM_setOSCursorLocation(
+ int x,
+ int y)
+{
+ /* Nothing to do for Windows */
+ (void)x;
+ (void)y;
+}
+
+/****************************************************************************
+REMARKS:
+Set the width of the OS console.
+****************************************************************************/
+void PMAPI PM_setOSScreenWidth(
+ int width,
+ int height)
+{
+ /* Nothing to do for Windows */
+ (void)width;
+ (void)height;
+}
+
+/****************************************************************************
+REMARKS:
+Maps a shared memory block into process address space. Does nothing since
+the memory blocks are already globally mapped into all processes.
+****************************************************************************/
+void * PMAPI PM_mapToProcess(
+ void *base,
+ ulong limit)
+{
+ // Not used anymore
+ (void)base;
+ (void)limit;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+Execute the POST on the secondary BIOS for a controller.
+****************************************************************************/
+ibool PMAPI PM_doBIOSPOST(
+ ushort axVal,
+ ulong BIOSPhysAddr,
+ void *mappedBIOS,
+ ulong BIOSLen)
+{
+ // This may not be possible in NT and should be done by the OS anyway
+ (void)axVal;
+ (void)BIOSPhysAddr;
+ (void)mappedBIOS;
+ (void)BIOSLen;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Return a pointer to the real mode BIOS data area.
+****************************************************************************/
+void * PMAPI PM_getBIOSPointer(void)
+{
+ // Note that on NT this probably does not do what we expect!
+ return PM_mapPhysicalAddr(0x400, 0x1000, true);
+}
+
+/****************************************************************************
+REMARKS:
+Return a pointer to 0xA0000 physical VGA graphics framebuffer.
+****************************************************************************/
+void * PMAPI PM_getA0000Pointer(void)
+{
+ return PM_mapPhysicalAddr(0xA0000,0xFFFF,false);
+}
+
+/****************************************************************************
+REMARKS:
+Sleep for the specified number of milliseconds.
+****************************************************************************/
+void PMAPI PM_sleep(
+ ulong milliseconds)
+{
+ // We never use this in NT drivers
+ (void)milliseconds;
+}
+
+/****************************************************************************
+REMARKS:
+Return the base I/O port for the specified COM port.
+****************************************************************************/
+int PMAPI PM_getCOMPort(int port)
+{
+ // TODO: Re-code this to determine real values using the Plug and Play
+ // manager for the OS.
+ switch (port) {
+ case 0: return 0x3F8;
+ case 1: return 0x2F8;
+ case 2: return 0x3E8;
+ case 3: return 0x2E8;
+ }
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Return the base I/O port for the specified LPT port.
+****************************************************************************/
+int PMAPI PM_getLPTPort(int port)
+{
+ // TODO: Re-code this to determine real values using the Plug and Play
+ // manager for the OS.
+ switch (port) {
+ case 0: return 0x3BC;
+ case 1: return 0x378;
+ case 2: return 0x278;
+ }
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+Returns available memory. Not possible under Windows.
+****************************************************************************/
+void PMAPI PM_availableMemory(
+ ulong *physical,
+ ulong *total)
+{
+ *physical = *total = 0;
+}
+
+/****************************************************************************
+REMARKS:
+OS specific shared libraries not supported inside a VxD
+****************************************************************************/
+PM_MODULE PMAPI PM_loadLibrary(
+ const char *szDLLName)
+{
+ // Not used in NT drivers
+ (void)szDLLName;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+OS specific shared libraries not supported inside a VxD
+****************************************************************************/
+void * PMAPI PM_getProcAddress(
+ PM_MODULE hModule,
+ const char *szProcName)
+{
+ // Not used in NT drivers
+ (void)hModule;
+ (void)szProcName;
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+OS specific shared libraries not supported inside a VxD
+****************************************************************************/
+void PMAPI PM_freeLibrary(
+ PM_MODULE hModule)
+{
+ // Not used in NT drivers
+ (void)hModule;
+}
+
+/****************************************************************************
+REMARKS:
+Function to find the first file matching a search criteria in a directory.
+****************************************************************************/
+void *PMAPI PM_findFirstFile(
+ const char *filename,
+ PM_findData *findData)
+{
+ // TODO: This function should start a directory enumeration search
+ // given the filename (with wildcards). The data should be
+ // converted and returned in the findData standard form.
+ (void)filename;
+ (void)findData;
+ return PM_FILE_INVALID;
+}
+
+/****************************************************************************
+REMARKS:
+Function to find the next file matching a search criteria in a directory.
+****************************************************************************/
+ibool PMAPI PM_findNextFile(
+ void *handle,
+ PM_findData *findData)
+{
+ // TODO: This function should find the next file in directory enumeration
+ // search given the search criteria defined in the call to
+ // PM_findFirstFile. The data should be converted and returned
+ // in the findData standard form.
+ (void)handle;
+ (void)findData;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to close the find process
+****************************************************************************/
+void PMAPI PM_findClose(
+ void *handle)
+{
+ // TODO: This function should close the find process. This may do
+ // nothing for some OS'es.
+ (void)handle;
+}
+
+/****************************************************************************
+REMARKS:
+Function to determine if a drive is a valid drive or not. Under Unix this
+function will return false for anything except a value of 3 (considered
+the root drive, and equivalent to C: for non-Unix systems). The drive
+numbering is:
+
+ 1 - Drive A:
+ 2 - Drive B:
+ 3 - Drive C:
+ etc
+
+****************************************************************************/
+ibool PMAPI PM_driveValid(
+ char drive)
+{
+ // Not supported in NT drivers
+ (void)drive;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the current working directory for the specififed drive.
+Under Unix this will always return the current working directory regardless
+of what the value of 'drive' is.
+****************************************************************************/
+void PMAPI PM_getdcwd(
+ int drive,
+ char *dir,
+ int len)
+{
+ // Not supported in NT drivers
+ (void)drive;
+ (void)dir;
+ (void)len;
+}
+
+/****************************************************************************
+PARAMETERS:
+base - The starting physical base address of the region
+size - The size in bytes of the region
+type - Type to place into the MTRR register
+
+RETURNS:
+Error code describing the result.
+
+REMARKS:
+Function to enable write combining for the specified region of memory.
+****************************************************************************/
+int PMAPI PM_enableWriteCombine(
+ ulong base,
+ ulong size,
+ uint type)
+{
+ return MTRR_enableWriteCombine(base,size,type);
+}
+
+/****************************************************************************
+REMARKS:
+Function to change the file attributes for a specific file.
+****************************************************************************/
+void PMAPI PM_setFileAttr(
+ const char *filename,
+ uint attrib)
+{
+ NTSTATUS status;
+ ACCESS_MASK DesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG ShareAccess = FILE_SHARE_READ;
+ ULONG CreateDisposition = FILE_OPEN;
+ HANDLE FileHandle = NULL;
+ UNICODE_STRING *uniFile = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileBasic;
+ char kernelFilename[PM_MAX_PATH+5];
+ ULONG FileAttributes = 0;
+
+ // Convert file attribute flags
+ if (attrib & PM_FILE_READONLY)
+ FileAttributes |= FILE_ATTRIBUTE_READONLY;
+ if (attrib & PM_FILE_ARCHIVE)
+ FileAttributes |= FILE_ATTRIBUTE_ARCHIVE;
+ if (attrib & PM_FILE_HIDDEN)
+ FileAttributes |= FILE_ATTRIBUTE_HIDDEN;
+ if (attrib & PM_FILE_SYSTEM)
+ FileAttributes |= FILE_ATTRIBUTE_SYSTEM;
+
+ // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
+ strcpy(kernelFilename, "\\??\\");
+ strcat(kernelFilename, filename);
+
+ // Convert filename string to ansi string
+ if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
+ goto Exit;
+
+ // Must open a file to query it's attributes
+ InitializeObjectAttributes (&ObjectAttributes,
+ uniFile,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+ status = ZwCreateFile( &FileHandle,
+ DesiredAccess | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, //AllocationSize OPTIONAL,
+ FILE_ATTRIBUTE_NORMAL,
+ ShareAccess,
+ CreateDisposition,
+ FILE_RANDOM_ACCESS, //CreateOptions,
+ NULL, //EaBuffer OPTIONAL,
+ 0 //EaLength (required if EaBuffer)
+ );
+ if (!NT_SUCCESS (status))
+ goto Exit;
+
+ // Query timestamps
+ status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation
+ );
+ if (!NT_SUCCESS (status))
+ goto Exit;
+
+ // Change the four bits we change
+ FileBasic.FileAttributes &= ~(FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_ARCHIVE
+ | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM);
+ FileBasic.FileAttributes |= FileAttributes;
+
+ // Set timestamps
+ ZwSetInformationFile( FileHandle,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation
+ );
+
+Exit:
+ if (FileHandle) ZwClose(FileHandle);
+ if (uniFile) _PM_FreeUnicodeString(uniFile);
+ return;
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the file attributes for a specific file.
+****************************************************************************/
+uint PMAPI PM_getFileAttr(
+ const char *filename)
+{
+ NTSTATUS status;
+ ACCESS_MASK DesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG ShareAccess = FILE_SHARE_READ;
+ ULONG CreateDisposition = FILE_OPEN;
+ HANDLE FileHandle = NULL;
+ UNICODE_STRING *uniFile = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_BASIC_INFORMATION FileBasic;
+ char kernelFilename[PM_MAX_PATH+5];
+ ULONG FileAttributes = 0;
+ uint retval = 0;
+
+ // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
+ strcpy(kernelFilename, "\\??\\");
+ strcat(kernelFilename, filename);
+
+ // Convert filename string to ansi string
+ if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
+ goto Exit;
+
+ // Must open a file to query it's attributes
+ InitializeObjectAttributes (&ObjectAttributes,
+ uniFile,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL );
+ status = ZwCreateFile( &FileHandle,
+ DesiredAccess | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, //AllocationSize OPTIONAL,
+ FILE_ATTRIBUTE_NORMAL,
+ ShareAccess,
+ CreateDisposition,
+ FILE_RANDOM_ACCESS, //CreateOptions,
+ NULL, //EaBuffer OPTIONAL,
+ 0 //EaLength (required if EaBuffer)
+ );
+ if (!NT_SUCCESS (status))
+ goto Exit;
+
+ // Query timestamps
+ status = ZwQueryInformationFile(FileHandle,
+ &IoStatusBlock,
+ &FileBasic,
+ sizeof(FILE_BASIC_INFORMATION),
+ FileBasicInformation
+ );
+ if (!NT_SUCCESS (status))
+ goto Exit;
+
+ // Translate the file attributes
+ if (FileBasic.FileAttributes & FILE_ATTRIBUTE_READONLY)
+ retval |= PM_FILE_READONLY;
+ if (FileBasic.FileAttributes & FILE_ATTRIBUTE_ARCHIVE)
+ retval |= PM_FILE_ARCHIVE;
+ if (FileBasic.FileAttributes & FILE_ATTRIBUTE_HIDDEN)
+ retval |= PM_FILE_HIDDEN;
+ if (FileBasic.FileAttributes & FILE_ATTRIBUTE_SYSTEM)
+ retval |= PM_FILE_SYSTEM;
+
+Exit:
+ if (FileHandle) ZwClose(FileHandle);
+ if (uniFile) _PM_FreeUnicodeString(uniFile);
+ return retval;
+}
+
+/****************************************************************************
+REMARKS:
+Function to create a directory.
+****************************************************************************/
+ibool PMAPI PM_mkdir(
+ const char *filename)
+{
+ // Not supported in NT drivers
+ (void)filename;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to remove a directory.
+****************************************************************************/
+ibool PMAPI PM_rmdir(
+ const char *filename)
+{
+ // Not supported in NT drivers
+ (void)filename;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to get the file time and date for a specific file.
+****************************************************************************/
+ibool PMAPI PM_getFileTime(
+ const char *filename,
+ ibool gmTime,
+ PM_time *time)
+{
+ // Not supported in NT drivers
+ (void)filename;
+ (void)gmTime;
+ (void)time;
+ return false;
+}
+
+/****************************************************************************
+REMARKS:
+Function to set the file time and date for a specific file.
+****************************************************************************/
+ibool PMAPI PM_setFileTime(
+ const char *filename,
+ ibool gmTime,
+ PM_time *time)
+{
+ // Not supported in NT drivers
+ (void)filename;
+ (void)gmTime;
+ (void)time;
+ return false;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdio.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdio.c
new file mode 100644
index 0000000000..856215206f
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdio.c
@@ -0,0 +1,331 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT driver
+*
+* Description: C library compatible I/O functions for use within a Windows
+* NT driver.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "oshdr.h"
+
+/*------------------------ Main Code Implementation -----------------------*/
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fopen function.
+****************************************************************************/
+FILE * fopen(
+ const char *filename,
+ const char *mode)
+{
+ ACCESS_MASK DesiredAccess; // for ZwCreateFile...
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ ULONG ShareAccess;
+ ULONG CreateDisposition;
+ NTSTATUS status;
+ HANDLE FileHandle;
+ UNICODE_STRING *uniFile = NULL;
+ PWCHAR bufFile = NULL;
+ IO_STATUS_BLOCK IoStatusBlock;
+ FILE_STANDARD_INFORMATION FileInformation;
+ FILE_POSITION_INFORMATION FilePosition;
+ char kernelFilename[PM_MAX_PATH+5];
+ FILE *f;
+
+ // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
+ strcpy(kernelFilename, "\\??\\");
+ strcat(kernelFilename, filename);
+ if ((f = PM_malloc(sizeof(FILE))) == NULL)
+ goto Error;
+ f->offset = 0;
+ f->text = (mode[1] == 't' || mode[2] == 't');
+ f->writemode = (mode[0] == 'w') || (mode[0] == 'a');
+ if (mode[0] == 'r') {
+ // omode = OPEN_ACCESS_READONLY | OPEN_SHARE_COMPATIBLE;
+ // action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_FAIL;
+ DesiredAccess = GENERIC_READ;
+ ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ CreateDisposition = FILE_OPEN;
+ }
+ else if (mode[0] == 'w') {
+ // omode = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_COMPATIBLE;
+ // action = ACTION_IFEXISTS_TRUNCATE | ACTION_IFNOTEXISTS_CREATE;
+ DesiredAccess = GENERIC_WRITE;
+ ShareAccess = FILE_SHARE_READ | FILE_SHARE_WRITE;
+ CreateDisposition = FILE_SUPERSEDE;
+ }
+ else {
+ // omode = OPEN_ACCESS_READWRITE | OPEN_SHARE_COMPATIBLE;
+ // action = ACTION_IFEXISTS_OPEN | ACTION_IFNOTEXISTS_CREATE;
+ DesiredAccess = GENERIC_READ | GENERIC_WRITE;
+ ShareAccess = FILE_SHARE_READ;
+ CreateDisposition = FILE_OPEN_IF;
+ }
+
+ // Convert filename string to ansi string and then to UniCode string
+ if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
+ return NULL;
+
+ // Create the file
+ InitializeObjectAttributes (&ObjectAttributes,
+ uniFile,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL);
+ status = ZwCreateFile( &FileHandle,
+ DesiredAccess | SYNCHRONIZE,
+ &ObjectAttributes,
+ &IoStatusBlock,
+ NULL, // AllocationSize OPTIONAL,
+ FILE_ATTRIBUTE_NORMAL,
+ ShareAccess,
+ CreateDisposition,
+ FILE_RANDOM_ACCESS, // CreateOptions,
+ NULL, // EaBuffer OPTIONAL,
+ 0 // EaLength (required if EaBuffer)
+ );
+ if (!NT_SUCCESS (status))
+ goto Error;
+ f->handle = (int)FileHandle;
+
+ // Determine size of the file
+ status = ZwQueryInformationFile( FileHandle,
+ &IoStatusBlock,
+ &FileInformation,
+ sizeof(FILE_STANDARD_INFORMATION),
+ FileStandardInformation
+ );
+ if (!NT_SUCCESS (status))
+ goto Error;
+ f->filesize = FileInformation.EndOfFile.LowPart;
+
+ // Move to the end of the file if we are appending
+ if (mode[0] == 'a') {
+ FilePosition.CurrentByteOffset.HighPart = 0;
+ FilePosition.CurrentByteOffset.LowPart = f->filesize;
+ status = ZwSetInformationFile( FileHandle,
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation
+ );
+ if (!NT_SUCCESS (status))
+ goto Error;
+ }
+ return f;
+
+Error:
+ if (f) PM_free(f);
+ if (uniFile) _PM_FreeUnicodeString(uniFile);
+ return NULL;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fread function.
+****************************************************************************/
+size_t fread(
+ void *ptr,
+ size_t size,
+ size_t n,
+ FILE *f)
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+
+ // Read any extra bytes from the file
+ ByteOffset.HighPart = 0;
+ ByteOffset.LowPart = f->offset;
+ status = ZwReadFile( (HANDLE)f->handle,
+ NULL, //IN HANDLE Event OPTIONAL,
+ NULL, // IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ NULL, // IN PVOID ApcContext OPTIONAL,
+ &IoStatusBlock,
+ ptr, // OUT PVOID Buffer,
+ size * n, //IN ULONG Length,
+ &ByteOffset, //OPTIONAL,
+ NULL //IN PULONG Key OPTIONAL
+ );
+ if (!NT_SUCCESS (status))
+ return 0;
+ f->offset += IoStatusBlock.Information;
+ return IoStatusBlock.Information / size;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fwrite function.
+****************************************************************************/
+size_t fwrite(
+ const void *ptr,
+ size_t size,
+ size_t n,
+ FILE *f)
+{
+ NTSTATUS status;
+ IO_STATUS_BLOCK IoStatusBlock;
+ LARGE_INTEGER ByteOffset;
+
+ if (!f->writemode)
+ return 0;
+ ByteOffset.HighPart = 0;
+ ByteOffset.LowPart = f->offset;
+ status = ZwWriteFile( (HANDLE)f->handle,
+ NULL, //IN HANDLE Event OPTIONAL,
+ NULL, // IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ NULL, // IN PVOID ApcContext OPTIONAL,
+ &IoStatusBlock,
+ (void*)ptr, // OUT PVOID Buffer,
+ size * n, //IN ULONG Length,
+ &ByteOffset, //OPTIONAL,
+ NULL //IN PULONG Key OPTIONAL
+ );
+ if (!NT_SUCCESS (status))
+ return 0;
+ f->offset += IoStatusBlock.Information;
+ if (f->offset > f->filesize)
+ f->filesize = f->offset;
+ return IoStatusBlock.Information / size;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fflush function.
+****************************************************************************/
+int fflush(
+ FILE *f)
+{
+ // Nothing to do here as we are not doing buffered I/O
+ (void)f;
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fseek function.
+****************************************************************************/
+int fseek(
+ FILE *f,
+ long int offset,
+ int whence)
+{
+ NTSTATUS status;
+ FILE_POSITION_INFORMATION FilePosition;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ if (whence == 0)
+ f->offset = offset;
+ else if (whence == 1)
+ f->offset += offset;
+ else if (whence == 2)
+ f->offset = f->filesize + offset;
+ FilePosition.CurrentByteOffset.HighPart = 0;
+ FilePosition.CurrentByteOffset.LowPart = f->offset;
+ status = ZwSetInformationFile( (HANDLE)f->handle,
+ &IoStatusBlock,
+ &FilePosition,
+ sizeof(FILE_POSITION_INFORMATION),
+ FilePositionInformation
+ );
+ if (!NT_SUCCESS (status))
+ return -1;
+ return 0;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C ftell function.
+****************************************************************************/
+long ftell(
+ FILE *f)
+{
+ return f->offset;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C feof function.
+****************************************************************************/
+int feof(
+ FILE *f)
+{
+ return (f->offset == f->filesize);
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fgets function.
+****************************************************************************/
+char *fgets(
+ char *s,
+ int n,
+ FILE *f)
+{
+ int len;
+ char *cs;
+
+ // Read the entire buffer into memory (our functions are unbuffered!)
+ if ((len = fread(s,1,n,f)) == 0)
+ return NULL;
+
+ // Search for '\n' or end of string
+ if (n > len)
+ n = len;
+ cs = s;
+ while (--n > 0) {
+ if (*cs == '\n')
+ break;
+ cs++;
+ }
+ *cs = '\0';
+ return s;
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fputs function.
+****************************************************************************/
+int fputs(
+ const char *s,
+ FILE *f)
+{
+ return fwrite(s,1,strlen(s),f);
+}
+
+/****************************************************************************
+REMARKS:
+NT driver implementation of the ANSI C fclose function.
+****************************************************************************/
+int fclose(
+ FILE *f)
+{
+ ZwClose((HANDLE)f->handle);
+ PM_free(f);
+ return 0;
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdlib.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdlib.c
new file mode 100644
index 0000000000..d7705130b7
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/stdlib.c
@@ -0,0 +1,140 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows NT driver
+*
+* Description: C library compatible stdlib.h functions for use within a
+* Windows NT driver.
+*
+****************************************************************************/
+
+#include "pmapi.h"
+#include "oshdr.h"
+
+/*------------------------ Main Code Implementation -----------------------*/
+
+/****************************************************************************
+REMARKS:
+PM_malloc override function for Nucleus drivers loaded in NT drivers's.
+****************************************************************************/
+void * malloc(
+ size_t size)
+{
+ return PM_mallocShared(size);
+}
+
+/****************************************************************************
+REMARKS:
+calloc library function for Nucleus drivers loaded in NT drivers's.
+****************************************************************************/
+void * calloc(
+ size_t nelem,
+ size_t size)
+{
+ void *p = PM_mallocShared(nelem * size);
+ if (p)
+ memset(p,0,nelem * size);
+ return p;
+}
+
+/****************************************************************************
+REMARKS:
+PM_realloc override function for Nucleus drivers loaded in VxD's.
+****************************************************************************/
+void * realloc(
+ void *ptr,
+ size_t size)
+{
+ void *p = PM_mallocShared(size);
+ if (p) {
+ memcpy(p,ptr,size);
+ PM_freeShared(ptr);
+ }
+ return p;
+}
+
+/****************************************************************************
+REMARKS:
+PM_free override function for Nucleus drivers loaded in VxD's.
+****************************************************************************/
+void free(
+ void *p)
+{
+ PM_freeShared(p);
+}
+
+/****************************************************************************
+PARAMETERS:
+cstr - C style ANSI string to convert
+
+RETURNS:
+Pointer to the UniCode string structure or NULL on failure to allocate memory
+
+REMARKS:
+Converts a C style string to a UniCode string structure that can be passed
+directly to NT kernel functions.
+****************************************************************************/
+UNICODE_STRING *_PM_CStringToUnicodeString(
+ const char *cstr)
+{
+ int length;
+ ANSI_STRING ansiStr;
+ UNICODE_STRING *uniStr;
+
+ // Allocate memory for the string structure
+ if ((uniStr = ExAllocatePool(NonPagedPool, sizeof(UNICODE_STRING))) == NULL)
+ return NULL;
+
+ // Allocate memory for the wide string itself
+ length = (strlen(cstr) * sizeof(WCHAR)) + sizeof(WCHAR);
+ if ((uniStr->Buffer = ExAllocatePool(NonPagedPool, length)) == NULL) {
+ ExFreePool(uniStr);
+ return NULL;
+ }
+ RtlZeroMemory(uniStr->Buffer, length);
+ uniStr->Length = 0;
+ uniStr->MaximumLength = (USHORT)length;
+
+ // Convert filename string to ansi string and then to UniCode string
+ RtlInitAnsiString(&ansiStr, cstr);
+ RtlAnsiStringToUnicodeString(uniStr, &ansiStr, FALSE);
+ return uniStr;
+}
+
+/****************************************************************************
+PARAMETERS:
+uniStr - UniCode string structure to free
+
+REMARKS:
+Frees a string allocated by the above _PM_CStringToUnicodeString function.
+****************************************************************************/
+void _PM_FreeUnicodeString(
+ UNICODE_STRING *uniStr)
+{
+ if (uniStr) {
+ ExFreePool(uniStr->Buffer);
+ ExFreePool(uniStr);
+ }
+}
+
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/vflat.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/vflat.c
new file mode 100644
index 0000000000..901ce1cf03
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/vflat.c
@@ -0,0 +1,45 @@
+/****************************************************************************
+*
+* SciTech OS Portability Manager Library
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: Any
+*
+* Description: Dummy module; no virtual framebuffer for this OS
+*
+****************************************************************************/
+
+#include "pmapi.h"
+
+ibool PMAPI VF_available(void)
+{
+ return false;
+}
+
+void * PMAPI VF_init(ulong baseAddr,int bankSize,int codeLen,void *bankFunc)
+{
+ return NULL;
+}
+
+void PMAPI VF_exit(void)
+{
+}
diff --git a/board/MAI/bios_emulator/scitech/src/pm/ntdrv/ztimer.c b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/ztimer.c
new file mode 100644
index 0000000000..ef27294107
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/pm/ntdrv/ztimer.c
@@ -0,0 +1,124 @@
+/****************************************************************************
+*
+* Ultra Long Period Timer
+*
+* ========================================================================
+*
+* The contents of this file are subject to the SciTech MGL Public
+* License Version 1.0 (the "License"); you may not use this file
+* except in compliance with the License. You may obtain a copy of
+* the License at http://www.scitechsoft.com/mgl-license.txt
+*
+* Software distributed under the License is distributed on an
+* "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+* implied. See the License for the specific language governing
+* rights and limitations under the License.
+*
+* The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
+*
+* The Initial Developer of the Original Code is SciTech Software, Inc.
+* All Rights Reserved.
+*
+* ========================================================================
+*
+* Language: ANSI C
+* Environment: 32-bit Windows VxD
+*
+* Description: OS specific implementation for the Zen Timer functions.
+*
+****************************************************************************/
+
+/*---------------------------- Global variables ---------------------------*/
+
+static CPU_largeInteger countFreq;
+static ulong start,finish;
+
+/*----------------------------- Implementation ----------------------------*/
+
+/****************************************************************************
+REMARKS:
+Initialise the Zen Timer module internals.
+****************************************************************************/
+static void __ZTimerInit(void)
+{
+ KeQueryPerformanceCounter((LARGE_INTEGER*)&countFreq);
+}
+
+/****************************************************************************
+REMARKS:
+Call the assembler Zen Timer functions to do the timing.
+****************************************************************************/
+static void __LZTimerOn(
+ LZTimerObject *tm)
+{
+ LARGE_INTEGER lt = KeQueryPerformanceCounter(NULL);
+ tm->start.low = lt.LowPart;
+ tm->start.high = lt.HighPart;
+}
+
+/****************************************************************************
+REMARKS:
+Call the assembler Zen Timer functions to do the timing.
+****************************************************************************/
+static ulong __LZTimerLap(
+ LZTimerObject *tm)
+{
+ LARGE_INTEGER tmLap = KeQueryPerformanceCounter(NULL);
+ CPU_largeInteger tmCount;
+
+ _CPU_diffTime64(&tm->start,(CPU_largeInteger*)&tmLap,&tmCount);
+ return _CPU_calcMicroSec(&tmCount,countFreq.low);
+}
+
+/****************************************************************************
+REMARKS:
+Call the assembler Zen Timer functions to do the timing.
+****************************************************************************/
+static void __LZTimerOff(
+ LZTimerObject *tm)
+{
+ LARGE_INTEGER lt = KeQueryPerformanceCounter(NULL);
+ tm->end.low = lt.LowPart;
+ tm->end.high = lt.HighPart;
+}
+
+/****************************************************************************
+REMARKS:
+Call the assembler Zen Timer functions to do the timing.
+****************************************************************************/
+static ulong __LZTimerCount(
+ LZTimerObject *tm)
+{
+ CPU_largeInteger tmCount;
+
+ _CPU_diffTime64(&tm->start,&tm->end,&tmCount);
+ return _CPU_calcMicroSec(&tmCount,countFreq.low);
+}
+
+/****************************************************************************
+REMARKS:
+Define the resolution of the long period timer as microseconds per timer tick.
+****************************************************************************/
+#define ULZTIMER_RESOLUTION 1
+
+/****************************************************************************
+REMARKS:
+Read the Long Period timer value from the BIOS timer tick.
+****************************************************************************/
+static ulong __ULZReadTime(void)
+{
+ LARGE_INTEGER count;
+ KeQuerySystemTime(&count);
+ return (ulong)(*((_int64*)&count) / 10);
+}
+
+/****************************************************************************
+REMARKS:
+Compute the elapsed time from the BIOS timer tick. Note that we check to see
+whether a midnight boundary has passed, and if so adjust the finish time to
+account for this. We cannot detect if more that one midnight boundary has
+passed, so if this happens we will be generating erronous results.
+****************************************************************************/
+ulong __ULZElapsedTime(ulong start,ulong finish)
+{ return finish - start; }
+
OpenPOWER on IntegriCloud