home *** CD-ROM | disk | FTP | other *** search
- ;****************************************************************
- ;*
- ;* PEEPER.ASM - Assembly subroutines to move memory from a 4G linear
- ;* address into a buffer in the current data segment
- ;*
- ;* Assembled using Microsoft Macro Assembler 5.1
- ;*
- ;****************************************************************
-
- ;* Need to use 80386 protected mode instructions
- .386P
-
-
- KBC_IBF_BIT EQU 02H
- KBC_WOP_CMD EQU 0D1H
- KBC_ROP_CMD EQU 0D0H
- A20_OFF_DATA EQU 0DDH
- A20_ON_DATA EQU 0DFH
- KBC_NOP_CMD EQU 0FFH
-
- KBC_DATA_PORT EQU 060H
- KBC_CMD_PORT EQU 064H
-
- GA20_FAIL_ERR_CODE EQU 0FFFFH
-
- _TEXT segment use16 public 'CODE'
- assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
-
-
- ;****************************************************************
- ;* get_high_mem(dest,len,source) - copy memory from source to dest (len bytes)
- ;* Entry - dest - buffer in current DS
- ;* len - size of buffer in bytes
- ;* source - 32-bit linear address of source memory
- ;* Exit - gs: set to zero
- ;* WARNING: Forces GateA20 low when done
- ;****************************************************************
- public _get_high_mem
- ghm_dest equ word ptr [bp+4]
- ghm_len equ word ptr [bp+6]
- ghm_source equ dword ptr [bp+8]
- _get_high_mem proc near
- push bp
- mov bp, sp
- push di
-
- mov al, 080h ; allow normal A20
- call gate_A20
-
- xor ax, ax
- mov gs, ax ; zero out gs
- mov ax, ds
- mov es, ax ; es := ds
- mov di, ghm_dest
- mov cx, ghm_len
- mov ebx, ghm_source
- jcxz ghm_bottom
- ghm_top:
- mov al, byte ptr gs:[ebx]
- inc ebx
- stosb
- loop ghm_top
- ghm_bottom:
- xor al, al ; cripple A20 for DOS
- call gate_A20
-
- pop di
- pop bp
- ret
-
- _get_high_mem endp
-
- ;****************************************************************
- ;* gate_A20(how) - set gateA20 to the desired state
- ;* Entry - AL==80h => A20 on
- ;* AL==00h => A20 off
- ;* Exit - GateA20 in desired state
- ;* WARNING: Assumes preferred states of output port bits
- ;****************************************************************
-
- ;
- ; gate_A20 - set gateA20 to the desired state
- ; Entry - AL==80h => A20 on (no 1M wrap)
- ; AL==00h => A20 off (1M wrap)
- ;
- gate_A20 proc near
- test al,080H ; al&80 = 0 ?
- jnz short ga20_on
- ; al is zero, turn a20 off
- mov ah,A20_OFF_DATA ; kbc off gate a20
- call empty_KBC ; clear to use
- jnz short ga20_err ; didn't clear
- jmp short ga20_KBC_ctl ; cleared, go fix KBC A20
- ga20_on:
- mov ah,A20_ON_DATA ; kbc on gate a20 if needed
- ga20_KBC_ctl:
- mov al,KBC_WOP_CMD ; Write Output Port
- out KBC_CMD_PORT,al ; command it
- call empty_KBC
- jnz short ga20_err
- mov al,ah
- out KBC_DATA_PORT,al
- call empty_KBC ; wait till it clears
- jnz short ga20_err ; didn't clear
- mov al,KBC_NOP_CMD ; flush it through
- out KBC_CMD_PORT,al ; command it
- call empty_KBC
- jnz short ga20_err
- ; we're here, it worked!!
- ga20_ok:
- xor ax,ax
- jmp short ga20_out
- ga20_err:
- mov ax,GA20_FAIL_ERR_CODE
- ga20_out:
- ret
- gate_A20 endp
-
- ;
- ; empty_KBC - Empty keyboard controller input buffer
- ; Entry - none
- ; Exit - bashes AL
- ;
- empty_KBC proc near
- push cx ; save reg
- xor cx,cx ; set for max timeout
- empty_KBC_loop:
- in al,KBC_CMD_PORT ; get KBC status
- test al,KBC_IBF_BIT ; check IBF bit
- loopnz empty_KBC_loop ; try till timeout
- pop cx ; restore reg
- ret ; that's all folks
- empty_KBC endp
-
-
-
-
- _TEXT ends
- end
-
-
-