mirror of
https://github.com/acpica/acpica/
synced 2025-01-15 22:09:17 +03:00
f2527faa0e
date 2003.04.24.18.05.00; author rmoore1; state Exp;
916 lines
20 KiB
NASM
916 lines
20 KiB
NASM
NAME BU_ASM
|
|
TITLE BU_ASM.ASM -- ASM support for DOS BU_LIB
|
|
|
|
;****************************************************************************
|
|
;* Copyright (C) Intel Corporation 1994-1999
|
|
;*
|
|
;* All rights reserved. No part of this program or publication
|
|
;* may be reproduced, transmitted, transcribed, stored in a
|
|
;* retrieval system, or translated into any language or computer
|
|
;* language, in any form or by any means, electronic, mechanical,
|
|
;* magnetic, optical, chemical, manual, or otherwise, without
|
|
;* the prior written permission of Intel Corporation.
|
|
;****************************************************************************
|
|
;
|
|
; To assemble with MASM61 -- ml /c a16utils.asm
|
|
;
|
|
;****************************************************************************
|
|
|
|
.286
|
|
.MODEL large, c
|
|
|
|
IFDEF MODEL_S
|
|
.MODEL small, c
|
|
ENDIF
|
|
|
|
IFDEF MODEL_M
|
|
.MODEL medium, c
|
|
ENDIF
|
|
|
|
IFDEF MODEL_L
|
|
.MODEL large, c
|
|
ENDIF
|
|
|
|
IFDEF MODEL_C
|
|
.MODEL compact, c
|
|
ENDIF
|
|
|
|
IFDEF MODEL_H
|
|
.MODEL huge, c
|
|
ENDIF
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
GOREAL MACRO
|
|
LOCAL here
|
|
|
|
mov eax, cr0
|
|
and eax, 0fffffffeh
|
|
mov cr0, eax
|
|
jmp here
|
|
here:
|
|
ENDM
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
GOPROT MACRO
|
|
LOCAL here
|
|
|
|
xor eax, eax
|
|
xor edx, edx
|
|
|
|
mov ax, ds
|
|
shl eax, 4
|
|
lea edx, _gdt
|
|
add eax, edx
|
|
|
|
mov [_gdt_ptr+2], ax
|
|
shr eax, 16
|
|
mov [_gdt_ptr+4], ax
|
|
|
|
lgdt FWORD PTR _gdt_ptr
|
|
mov eax, cr0
|
|
or eax, 1
|
|
mov cr0, eax
|
|
jmp here
|
|
here:
|
|
ENDM
|
|
;--------------------------------------------------------------------
|
|
|
|
.STACK
|
|
.DATA
|
|
|
|
PUBLIC _dAPAwake, _dAPDone, _dAPFuncPtr, _wProcNumber, _bSPValid
|
|
PUBLIC _wCSegDS, _wCSegES, _wCSegSS, _wCSegSP, _wASegDS, _wASegES
|
|
PUBLIC _dAPHltJmp
|
|
|
|
|
|
|
|
emsfilename DB 'EMMXXXX0',0
|
|
|
|
_dAPAwake DD 0
|
|
_dAPDone DD 0
|
|
_dAPFuncPtr DD 0
|
|
_wProcNumber DW 0
|
|
_bSPValid DB 0
|
|
|
|
_wASegDS DW 0
|
|
_wASegES DW 0
|
|
_wCSegDS DW 0
|
|
_wCSegES DW 0
|
|
_wCSegSS DW 0
|
|
_wCSegSP DW 0
|
|
|
|
_block DW 0
|
|
_gdt_ptr DW 23
|
|
DD 0
|
|
_gdt DD 0 ; NULL descriptor
|
|
DD 0 ; NULL descriptor
|
|
|
|
; 64K real mode style data segment
|
|
DD 0ffffh ; base 0, limit 0xffff
|
|
DD 00009200h ; data, CPL=0, 16-bit, 1 byte granularity, r/w
|
|
|
|
; 4G flat data segment
|
|
DD 0ffffh ; base 0, limit 0xfffff
|
|
DD 008f9200h ; data, CPL=0, 16-bit, 4K granularity, r/w
|
|
_old_es DW 0
|
|
_old_ds DW 0
|
|
_old_fs DW 0
|
|
_old_gs DW 0
|
|
_dAPHltJmp DD 0 ; jump to halt location
|
|
|
|
.CODE
|
|
EXTERNDEF pascal cprint:proc
|
|
|
|
PUBLIC ems_present
|
|
ems_present PROC C
|
|
mov ah,3dh ; open file
|
|
xor al,al ; read only operation
|
|
mov dx,offset emsfilename ; look for EMMXXXX0
|
|
int 21h
|
|
jc emserror1 ; if carry flag set, then no EMM driver
|
|
|
|
mov di,ax ; save file handle
|
|
mov bx,ax ; set up handle
|
|
mov ax,4400h ; get device (channel) info
|
|
int 21h
|
|
|
|
mov ah,3eh ; close file
|
|
mov bx,di ; close the file handle up
|
|
int 21h
|
|
jc emserror1 ; if carry flag set, then no driver is present
|
|
|
|
test dx,10000000b ; if bit 7 not set, then the channel is a file
|
|
jz emserror1 ; otherwise the channel is a device driver
|
|
|
|
mov ax,1 ; 1 = EMS present
|
|
ret
|
|
|
|
emserror1:
|
|
xor ax,ax ; 0 = EMS not present
|
|
ret
|
|
ems_present ENDP
|
|
|
|
PUBLIC vm86
|
|
vm86 PROC C
|
|
smsw ax
|
|
and ax, 1
|
|
ret
|
|
vm86 ENDP
|
|
|
|
|
|
PUBLIC _set_rows
|
|
_set_rows PROC C rows:WORD
|
|
cmp rows, 25
|
|
je set_25
|
|
cmp rows, 50
|
|
je set_50
|
|
cmp rows, 132
|
|
je set_132
|
|
jmp invalid_input
|
|
set_25:
|
|
mov ah, 00
|
|
mov al, 03
|
|
int 10h
|
|
mov ax, rows
|
|
jmp end_set_rows
|
|
set_50:
|
|
mov ah, 00
|
|
mov al, 03
|
|
int 10h
|
|
xor bx, bx
|
|
mov ah, 11h
|
|
mov al, 12h
|
|
int 10h
|
|
mov ax, rows
|
|
jmp end_set_rows
|
|
set_132:
|
|
mov ah, 00
|
|
mov al, 14h
|
|
int 10h
|
|
xor bx, bx
|
|
mov ah, 11h
|
|
mov al, 12h
|
|
int 10h
|
|
mov ax, rows
|
|
jmp end_set_rows
|
|
invalid_input:
|
|
xor ax, ax
|
|
jmp end_set_rows
|
|
end_set_rows:
|
|
ret
|
|
_set_rows ENDP
|
|
|
|
|
|
PUBLIC _cpuid_asm
|
|
_cpuid_asm PROC C hv:DWORD, regs:PTR DWORD
|
|
|
|
check_8086:
|
|
.8086
|
|
pushf
|
|
pop ax
|
|
mov cx, ax
|
|
and ax, 0fffh
|
|
push ax
|
|
popf
|
|
pushf
|
|
pop ax
|
|
and ax, 0f000h
|
|
cmp ax, 0f000h
|
|
mov ax, 10h
|
|
je end_cpuid
|
|
|
|
check_80286:
|
|
.286
|
|
or cx, 0f000h
|
|
push cx
|
|
popf
|
|
pushf
|
|
pop ax
|
|
and ax, 0f000h
|
|
mov ax, 20h
|
|
jz end_cpuid
|
|
|
|
check_80386:
|
|
.386
|
|
mov bx, sp
|
|
and sp, not 3
|
|
pushfd
|
|
pop eax
|
|
mov ecx, eax
|
|
xor eax, 40000h
|
|
push eax
|
|
popfd
|
|
pushfd
|
|
pop eax
|
|
cmp ecx, eax
|
|
jne check_80486
|
|
mov ax, 30h
|
|
mov sp, bx
|
|
jmp end_cpuid
|
|
|
|
check_80486:
|
|
.486
|
|
pushfd
|
|
pop ecx
|
|
mov ecx, eax
|
|
xor eax, 200000h
|
|
push eax
|
|
popfd
|
|
pushfd
|
|
pop eax
|
|
xor eax, ecx
|
|
mov ax, 40h
|
|
je end_cpuid
|
|
|
|
check_cpuid:
|
|
.586
|
|
mov eax, hv
|
|
cpuid
|
|
push ebx
|
|
IF @DataSize ; segment is far
|
|
les bx, regs
|
|
mov dword ptr es:[bx], eax
|
|
pop eax
|
|
mov dword ptr es:[bx + 4], eax
|
|
mov dword ptr es:[bx + 8], ecx
|
|
mov dword ptr es:[bx + 12], edx
|
|
ELSE ; segment is near
|
|
mov bx, regs
|
|
mov dword ptr [bx], eax
|
|
pop eax
|
|
mov dword ptr [bx + 4], eax
|
|
mov dword ptr [bx + 8], ecx
|
|
mov dword ptr [bx + 12], edx
|
|
ENDIF
|
|
mov ax, 5
|
|
end_cpuid:
|
|
ret
|
|
_cpuid_asm ENDP
|
|
|
|
.386p
|
|
;--------------------------------------------------------------------
|
|
; Pentium Pro MSRs - from Pentium Pro Developer's Manual
|
|
; January 1996 - Appendix C
|
|
;
|
|
; MTRRs: 200h - 20Fh, 250h, 258h - 259h, 268h - 26Fh, 2FFh
|
|
;--------------------------------------------------------------------
|
|
PUBLIC _read_msr
|
|
_read_msr PROC C dmsr:DWORD, pqmsr:PTR DWORD
|
|
pushad
|
|
mov ecx, dmsr
|
|
dw 320fh ; RDMSR
|
|
les bx, pqmsr
|
|
mov DWORD ptr es:[bx], eax
|
|
mov DWORD ptr es:[bx + 4], edx
|
|
popad
|
|
ret
|
|
_read_msr ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC _write_msr
|
|
_write_msr PROC C dmsr:DWORD, pqmsr:PTR DWORD
|
|
pushad
|
|
les bx, pqmsr
|
|
mov eax, DWORD ptr es:[bx]
|
|
mov edx, DWORD ptr es:[bx + 4]
|
|
mov ecx, dmsr
|
|
dw 300fh ; WRMSR
|
|
popad
|
|
ret
|
|
_write_msr ENDP
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Procedure: dReadCR0 - Reads CR0 CPU Register
|
|
;
|
|
; Output: dx:ax and eax - Contents of CR0
|
|
;
|
|
; Registers: All registers preserved except EAX and EDX
|
|
;----------------------------------------------------------------------------
|
|
PUBLIC dReadCR0
|
|
dReadCR0 PROC C
|
|
mov eax, cr0
|
|
mov edx, eax
|
|
shr edx, 16 ; upper 16 bits in dx
|
|
ret
|
|
dReadCR0 ENDP
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Procedure: dReadCR2 - Reads CR2 CPU Register
|
|
;
|
|
; Output: dx:ax and eax - Contents of CR2
|
|
;
|
|
; Registers: All registers preserved except EAX and EDX
|
|
;----------------------------------------------------------------------------
|
|
PUBLIC dReadCR2
|
|
dReadCR2 PROC C
|
|
mov eax, cr2
|
|
mov edx, eax
|
|
shr edx, 16 ; upper 16 bits in dx
|
|
ret
|
|
dReadCR2 ENDP
|
|
|
|
;----------------------------------------------------------------------------
|
|
; Procedure: dReadCR3 - Reads CR3 CPU Register
|
|
;
|
|
; Output: dx:ax and eax - Contents of CR3
|
|
;
|
|
; Registers: All registers preserved except EAX and EDX
|
|
;----------------------------------------------------------------------------
|
|
PUBLIC dReadCR3
|
|
dReadCR3 PROC C
|
|
mov eax, cr3
|
|
mov edx, eax
|
|
shr edx, 16 ; upper 16 bits in dx
|
|
ret
|
|
dReadCR3 ENDP
|
|
|
|
|
|
.586
|
|
;----------------------------------------------------------------------------
|
|
; Procedure: dGetProcUpdateRev_asm - Reads PPP Update Revision via an MSR
|
|
;
|
|
; Output: dx:ax and eax - PPP Update Revision
|
|
;
|
|
; Registers: All registers preserved except EAX, ECX, and EDX
|
|
;----------------------------------------------------------------------------
|
|
PUBLIC _dGetProcUpdateRev_asm
|
|
_dGetProcUpdateRev_asm PROC C
|
|
mov ecx, 08Bh ; model specific register to write
|
|
xor eax, eax
|
|
xor edx, edx
|
|
dw 300Fh ; WRMSR ==> load 0 to MSR at 8Bh
|
|
mov eax, 1
|
|
cpuid
|
|
mov ecx, 08Bh ; model specific register to read
|
|
dw 320Fh ; RDMSR ==> EDX = (read) MSR 8Bh
|
|
mov eax, edx ; return EAX
|
|
shr edx, 16 ; return DX:AX
|
|
ret
|
|
_dGetProcUpdateRev_asm ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC iInterruptFlagState
|
|
iInterruptFlagState PROC
|
|
pushf
|
|
pop ax
|
|
and ax, 200h
|
|
shr ax, 9
|
|
ret
|
|
iInterruptFlagState ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
.586P
|
|
PUBLIC vRealFsGs
|
|
vRealFsGs PROC C
|
|
|
|
; TBD: verify this on an AMD K6-2 266 MHz
|
|
; Assert A20M# via system control port A (This is a
|
|
; system dependent feature).
|
|
in al, 92h
|
|
and al, 0fdh
|
|
out 92h, al ; re-assert A20M#
|
|
|
|
GOPROT
|
|
|
|
mov ax, 8
|
|
mov gs, ax
|
|
|
|
GOREAL
|
|
|
|
mov ax, [_old_fs] ; restore original
|
|
mov fs, ax
|
|
mov ax, [_old_gs] ; restore original
|
|
mov gs, ax
|
|
sti
|
|
ret
|
|
vRealFsGs ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
PUBLIC vFlatFsGs
|
|
vFlatFsGs PROC C
|
|
cli
|
|
mov ax, fs
|
|
mov [_old_fs], ax ; save original fs
|
|
mov ax, gs
|
|
mov [_old_gs], ax ; save original gs
|
|
|
|
; Deassert A20M# via system control port A (This is a
|
|
; system dependent feature)
|
|
in al, 92h
|
|
or al, 2
|
|
out 92h, al ; de-assert A20M#
|
|
|
|
GOPROT
|
|
|
|
mov ax, 10h
|
|
mov fs, ax
|
|
mov gs, ax
|
|
|
|
GOREAL
|
|
|
|
ret
|
|
vFlatFsGs ENDP
|
|
|
|
|
|
PUBLIC vRealEsDs
|
|
vRealEsDs PROC C
|
|
|
|
; TBD: verify this on an AMD K6-2 266 MHz
|
|
; Assert A20M# via system control port A (This is a
|
|
; system dependent feature).
|
|
in al, 92h
|
|
and al, 0fdh
|
|
out 92h, al ; re-assert A20M#
|
|
|
|
GOPROT
|
|
|
|
mov ax, 8
|
|
mov gs, ax
|
|
|
|
GOREAL
|
|
|
|
mov ax, [_old_es] ; restore original
|
|
mov es, ax
|
|
mov ax, [_old_gs] ; restore original
|
|
mov gs, ax
|
|
sti
|
|
ret
|
|
vRealEsDs ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
PUBLIC vFlatEsDs
|
|
vFlatEsDs PROC C
|
|
cli
|
|
mov ax, es
|
|
mov [_old_es], ax ; save original
|
|
mov ax, gs
|
|
mov [_old_gs], ax ; save original
|
|
|
|
; Deassert A20M# via system control port A (This is a
|
|
; system dependent feature)
|
|
in al, 92h
|
|
or al, 2
|
|
out 92h, al ; de-assert A20M#
|
|
|
|
GOPROT
|
|
|
|
mov ax, 10h
|
|
mov es, ax
|
|
mov gs, ax
|
|
|
|
GOREAL
|
|
|
|
ret
|
|
vFlatEsDs ENDP
|
|
|
|
PUBLIC print
|
|
print PROC PASCAL Seq:DWORD
|
|
|
|
|
|
pushad
|
|
mov eax, Seq
|
|
push eax
|
|
call cprint
|
|
popad
|
|
|
|
ret
|
|
print ENDP
|
|
|
|
PUBLIC DoMove
|
|
DoMove PROC
|
|
|
|
push edx
|
|
; GOPROT
|
|
pop edx
|
|
|
|
mov ecx, edx
|
|
shr ecx, 2 ; byte count / 4 = dword count
|
|
cmp ecx, 0
|
|
je DoBytes
|
|
|
|
NextDword:
|
|
xor eax, eax
|
|
lock or eax, gs:[esi]
|
|
; mov eax, gs:[esi]
|
|
|
|
mov gs:[edi], eax
|
|
|
|
add esi, 4
|
|
add edi, 4
|
|
loop NextDword
|
|
|
|
DoBytes:
|
|
mov ecx, edx
|
|
and ecx, 3
|
|
cmp ecx, 0
|
|
je Exit ; no extra bytes to move
|
|
|
|
NextByte:
|
|
mov al, byte ptr gs:[esi]
|
|
mov byte ptr gs:[edi], al
|
|
inc esi
|
|
inc edi
|
|
loop NextByte
|
|
|
|
Exit:
|
|
; GOREAL
|
|
ret
|
|
|
|
DoMove ENDP
|
|
.586
|
|
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC _WriteApic
|
|
_WriteApic PROC C
|
|
call vFlatFsGs
|
|
xor ecx, ecx
|
|
xor edx, edx
|
|
|
|
mov cx, [esp+6] ; high word of apic address
|
|
shl ecx, 16
|
|
mov cx, [esp+4] ; low word of apic address
|
|
|
|
mov dx, [esp+10] ; high word of apic command
|
|
shl edx, 16
|
|
mov dx, [esp+8] ; low word of apic command
|
|
|
|
mov gs:[ecx], edx
|
|
|
|
call vRealFsGs
|
|
ret
|
|
_WriteApic ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC _ReadApic
|
|
_ReadApic PROC C
|
|
call vFlatFsGs
|
|
xor ecx, ecx
|
|
|
|
mov cx, [esp+6] ; low word of apic address
|
|
shl ecx, 16
|
|
mov cx, [esp+4] ; high word of apic address
|
|
|
|
mov eax, gs:[ecx]
|
|
|
|
push eax ; save eax
|
|
call vRealFsGs
|
|
pop eax ; restore eax
|
|
|
|
mov edx, eax
|
|
shr edx, 16
|
|
ret
|
|
_ReadApic ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
; Since the AP shares the BSP's stack, coordination is needed to avoid
|
|
; simultaneous usage by both processors, which would cause corruption.
|
|
;
|
|
; While the AP is executing here, the BSP is executing the code
|
|
; which follows the call to vAPStartupAll() or vAPStartupOne()
|
|
; in bu_apic.c:vExecuteOnAPs(). After disabling interrupts,
|
|
; the BSP stores the sp value in _wCSegSP, sets _bSPValid to 1,
|
|
; and spins while _dAPDone != _dAPAwake. (Both are initially zero;
|
|
; the code below increments _dAPAwake before spinning on _bSPValid.)
|
|
;
|
|
; XXX - There is a race condition here: if the BSP makes it all
|
|
; XXX - the way to its spin loop on _dAPDone != _dAPAwake before
|
|
; XXX - the AP increments _dAPAwake, the BSP will exit the spin
|
|
; XXX - loop without actually having waited for the AP to finish.
|
|
|
|
PUBLIC _vSetupAP
|
|
_vSetupAP PROC C
|
|
cli
|
|
mov ax, @data
|
|
mov ds, ax
|
|
mov esp, 0
|
|
lock inc dword ptr [_dAPAwake]
|
|
spin1:
|
|
mov al, [_bSPValid]
|
|
cmp al, 1
|
|
jne spin1
|
|
; XXX - The following line is supposed to provide some validity checking,
|
|
; XXX - but it does not entirely succeed. It is possible for > 1 AP to
|
|
; XXX - see _bSPValid == 1, and exit the spin1 loop just above, before
|
|
; XXX - the first one out has had time to decrement _bSPValid; this race
|
|
; XXX - defeats the purpose of decrementing it. The decrement is likely
|
|
; XXX - not needed anyway due to the exclusion provided by the spin2 loop
|
|
; XXX - below.
|
|
lock dec byte ptr[_bSPValid]
|
|
|
|
mov ax, [_wCSegSS]
|
|
mov ss, ax
|
|
mov sp, [_wCSegSP]
|
|
|
|
; critical section - determining unique cpu signatures
|
|
|
|
spin2:
|
|
mov eax, 1
|
|
; XXX - Should the following line have a 'lock' prefix?
|
|
xchg word ptr [_block], ax
|
|
test ax, ax
|
|
jne spin2
|
|
|
|
mov ax, ds ; Save ASM DS and ES in global vars
|
|
mov [_wASegDS], ax
|
|
mov ax, es
|
|
mov [_wASegES], ax
|
|
|
|
mov ax, [_wCSegES]
|
|
mov es, ax
|
|
mov ax, [_wCSegDS] ; Restore C DS and ES from global vars
|
|
mov ds, ax
|
|
|
|
; Update Current Processor Number. Mutual exclusion from other AP's is
|
|
; guaranteed by the spin2 loop above.
|
|
; Note that the "processor number" determined here represents the order
|
|
; in which the processors happened to get through the spin2 lock, and
|
|
; has nothing to do with APIC numbers. A system having > 1 AP will not
|
|
; necessarily number the AP's consistently from one run to the next.
|
|
mov eax, [_dAPDone]
|
|
inc eax
|
|
mov [_wProcNumber], ax
|
|
|
|
call [_dAPFuncPtr] ; _dAPFuncPtr needs to point to a void function
|
|
|
|
mov ax, [_wASegDS] ; Restore ASM DS and ES from global vars
|
|
mov ds, ax
|
|
mov ax, [_wASegES]
|
|
mov es, ax
|
|
|
|
lock inc dword ptr [_dAPDone]
|
|
lock inc byte ptr [_bSPValid]
|
|
|
|
xor eax, eax
|
|
; A simple 'mov' would serve as well as the following 'xchg'.
|
|
xchg word ptr [_block], ax
|
|
wbinvd
|
|
mov si, offset _dAPHltJmp
|
|
jmp dword ptr [si] ; Jump to HLT, JMP $-1 in F000 segment
|
|
hlt ; Should never get here
|
|
_vSetupAP ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC bIn8
|
|
bIn8 PROC C wPort:WORD
|
|
xor ax, ax
|
|
mov dx, wPort
|
|
in al, dx
|
|
ret
|
|
bIn8 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC wIn16
|
|
wIn16 PROC C wPort:WORD
|
|
mov dx, wPort
|
|
in ax, dx
|
|
ret
|
|
wIn16 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC dIn32
|
|
dIn32 PROC C wPort:WORD
|
|
mov dx, wPort
|
|
in eax, dx
|
|
mov edx, eax
|
|
shr edx, 16
|
|
ret
|
|
dIn32 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC vOut8
|
|
vOut8 PROC C wPort:WORD, bValue:BYTE
|
|
mov dx, wPort
|
|
mov al, bValue
|
|
out dx, al
|
|
ret
|
|
vOut8 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC vOut16
|
|
vOut16 PROC C wPort:WORD, wValue:WORD
|
|
mov dx, wPort
|
|
mov ax, wValue
|
|
out dx, ax
|
|
ret
|
|
vOut16 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
PUBLIC vOut32
|
|
vOut32 PROC C wPort:WORD, dValue:DWORD
|
|
mov dx, wPort
|
|
mov eax, dValue
|
|
out dx, eax
|
|
ret
|
|
vOut32 ENDP
|
|
|
|
;--------------------------------------------------------------------
|
|
|
|
; int FlatMove (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
|
|
PUBLIC FlatMoveX
|
|
FlatMoveX PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
|
|
call vm86 ; check if VM86 mode
|
|
cmp ax, 0
|
|
jne NotRealMode ; skip memory move if not in real mode
|
|
|
|
call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
|
|
; base 0:0 and de-assert A20M#
|
|
|
|
movzx ecx, sSize
|
|
cmp ecx, 0
|
|
je SKipMemoryMove ; skip memory move if 0==sSize
|
|
|
|
mov eax, dDest
|
|
cmp eax, 400h
|
|
jbe SkipMemoryMove ; skip memory move if destination is 40:0
|
|
; BIOS Data Area or less (IVT)
|
|
|
|
mov ebx, dSrc
|
|
NextByte:
|
|
mov dl, gs:[ebx][ecx - 1]
|
|
mov gs:[eax][ecx - 1], dl
|
|
loop NextByte
|
|
|
|
call vRealFsGs
|
|
xor ax, ax
|
|
NotRealMode:
|
|
ret
|
|
|
|
SkipMemoryMove:
|
|
mov ax, 1 ; return error code
|
|
ret
|
|
FlatMoveX ENDP
|
|
|
|
|
|
; int FlatMove32 (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
|
|
PUBLIC FlatMove32
|
|
FlatMove32 PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
|
|
|
|
call vm86 ; check if VM86 mode
|
|
cmp ax, 0
|
|
jne NotRealMode ; skip memory move if not in real mode
|
|
|
|
call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
|
|
; base 0:0 and de-assert A20M#
|
|
movzx edx, sSize
|
|
mov esi, dSrc
|
|
mov edi, dDest
|
|
|
|
push edx
|
|
call print
|
|
push esi
|
|
call print
|
|
push edi
|
|
call print
|
|
|
|
cmp edx, 0
|
|
je SkipMemoryMove ; skip memory move if 0==sSize
|
|
|
|
cmp edi, 400h
|
|
jbe SkipMemoryMove ; skip memory move if destination is 40:0
|
|
; BIOS Data Area or less (IVT)
|
|
call DoMove ; edx=Count, esi=src, edi=dst
|
|
|
|
movzx ecx, sSize
|
|
shr ecx, 2
|
|
mov edi, dDest
|
|
PrintLoop:
|
|
mov eax, gs:[edi]
|
|
push eax
|
|
call print
|
|
add edi, 4
|
|
loop PrintLoop
|
|
|
|
call vRealFsGs
|
|
xor ax, ax
|
|
|
|
NotRealMode:
|
|
ret
|
|
|
|
SkipMemoryMove:
|
|
call print
|
|
call vRealEsDs
|
|
mov ax, 1 ; return error code
|
|
ret
|
|
|
|
FlatMove32 ENDP
|
|
|
|
|
|
; int FlatMove32 (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
|
|
PUBLIC FlatMove32x
|
|
FlatMove32x PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
|
|
call vm86 ; check if VM86 mode
|
|
cmp ax, 0
|
|
jne NotRealMode ; skip memory move if not in real mode
|
|
|
|
call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
|
|
; base 0:0 and de-assert A20M#
|
|
movzx ecx, sSize
|
|
cmp ecx, 0
|
|
je SKipMemoryMove ; skip memory move if 0==sSize
|
|
|
|
mov eax, dDest
|
|
cmp eax, 400h
|
|
jbe SkipMemoryMove ; skip memory move if destination is 40:0
|
|
; BIOS Data Area or less (IVT)
|
|
|
|
mov ebx, dSrc
|
|
mov esi, 0
|
|
|
|
push ecx
|
|
call print
|
|
push ebx
|
|
call print
|
|
push eax
|
|
call print
|
|
|
|
shr ecx, 2 ; byte count / 4 = dword count
|
|
cmp ecx, 0
|
|
je DoBytes
|
|
|
|
NextDword:
|
|
mov edx, dword ptr gs:[ebx][esi]
|
|
mov dword ptr gs:[eax][esi], edx
|
|
push edx
|
|
call print
|
|
add esi, 4
|
|
loop NextDword
|
|
|
|
DoBytes:
|
|
movzx ecx, sSize
|
|
and ecx, 3
|
|
cmp ecx, 0
|
|
je Exit ; no extra bytes to move
|
|
|
|
NextByte:
|
|
mov dl, gs:[ebx][esi]
|
|
mov gs:[eax][esi], dl
|
|
inc esi
|
|
loop NextByte
|
|
|
|
Exit:
|
|
call vRealFsGs
|
|
xor ax, ax
|
|
|
|
NotRealMode:
|
|
ret
|
|
|
|
SkipMemoryMove:
|
|
mov ax, 1 ; return error code
|
|
ret
|
|
FlatMove32x ENDP
|
|
END
|