; ; bigreal.asm ; ; Programmer: David Lindauer ; Date: August 16,1995 ; email address: gclind01@ulkyvx.louisville.edu ; ; ; Enable big real mode on FS,GS ; ; .MODEL SMALL .386P MEMSIZE = 400000h ; Set this to MB you want to test MEMBASE = 100000h ;--------------------------------------------------------------------- ; Various symbols used to make things more readable. ; ;--------------------------------------------------------------------- NUMGDT = 2 ; Number of entries in GDT. GDTSIZE = NUMGDT*8 ; ; Selectors, RPL = 0, in GDT ; DS386 EQU 8h ; 386 data segment selector ;--------------------------------------------------------------------- ; Define ordering of segments. ; ;--------------------------------------------------------------------- DGROUP GROUP seg8086 SEG8086 SEGMENT dword USE16 public 'CODE' SEG8086 ends ;--------------------------------------------------------------------- ; Define a 1K entry stack. ; ;--------------------------------------------------------------------- .STACK 256 ;--------------------------------------------------------------------- ; IDT and GDT are first so they will be DWORD aligned ; ;--------------------------------------------------------------------- SEG8086 SEGMENT ; ; The constructed GDT ; tgdt dw 0,0,0,0 db 0ffh,0ffh,0,0,0,92h,0cfh,0 ; ; The value to load with the lgdt reg ; pGDT dw GDTSIZE-1 ; Protected mode GDT register gdtadr dd offset tGDT ; Move this out of ROM!!!!! ; msg db "Failure attempting to init a20 line",10,13,'$' goodmsg db "Test ok",10,13,'$' badmsg db "Test failed",10,13,'$' SEG8086 ends seg8086 SEGMENT assume cs:dgroup bigreal proc cld cli ; Interrupts clear throughout sub ebx,ebx mov bx,cs ; Set ES=DS=CS=DGROUP mov ds,bx mov es,bx ; ; Fixup the GDT with our current location in memory. ; shl ebx,4 add [gdtadr],ebx ; GDT and IDT regs must have a physical value ; Load the GDT descriptor lgdt [fword ptr pGDT] ; ; Switch to protected mode. ; mov ebx,CR0 ; Set protected mode inc bx mov CR0,ebx ; ; Load fs & gs with big segs ; push DS386 pop fs push DS386 pop gs ; ; Switch back to real mode ; dec bx mov CR0,ebx ret bigreal endp ; ; Routine to wait till KB controller not busy ; kb_busy proc xor cx,cx ; Loop 65536 times kb_bs2: in al,64h ; Get status jmp $+2 jmp $+2 test al,2 ; See if busy jz kb_busy_done ; Not busy any more loop kb_bs2 stc ret kb_busy_done: clc ret kb_busy endp ; ; Routine to wait till KB data buffer empty ; kb_writewait proc xor cx,cx ; Loop 65536 times kb_rd2: in al,64h ; Get port status test al,2 ; jz short kb_writewait_done ; Quit if buffer empty loop kb_rd2 ; Wait a while stc ; Error ret kb_writewait_done: clc ret kb_writewait endp ; ; Routine to wait till KB data buffer fll ; kb_readwait proc xor cx,cx ; Loop 65536 times kb_rdrd2: in al,64h ; Get port status test al,1 ; jnz short kb_readwait_done ; Quit if buffer empty loop kb_rdrd2 ; Wait a while stc ; Error ret kb_readwait_done: mov cx,32 ; Wait for controller to set data delay: jmp $+2 jmp $+2 loop delay ; clc ret kb_readwait endp ; ; Routine to turn on A20 line ; seta20 proc cli ; Don't want a keypress now! call kb_busy ; Wait while busy jc short error ; mov al,0d0h ; Command to get port status out 64h,al ; call kb_busy ; Wait while busy jc short error call kb_readwait ; Wait for it to put the char there jc short error in al,60h ; Get the data or al,2 ; Set the A20 bit xchg al,ah ; Data to ah call kb_busy ; Wait while busy jc short error mov al,0d1h ; Command to put port status out 64h,al ; call kb_busy ; Wait while busy jc short error call kb_writewait ; Wait for buffer to empty jc short error mov al,ah ; Write the data out 60h,al ; clc ; No erros error: sti ; Keys allowed now ret seta20 endp ; ; Fill extended memory with a pattern ; fillmegs proc mov edi,MEMBASE mov ecx,MEMSIZE / 4 mov eax,0ffff0000h fmlp: mov fs:[edi],eax add edi,4 inc eax loop fmlp ; mov dword ptr fs:[edi-16],0 ; put this line in to observe a failure ret fillmegs endp ; ; See if pattern overwrote itself ; testmegs proc mov edi,MEMBASE mov ecx,MEMSIZE/4 mov eax,0ffff0000h cmlp: cmp fs:[edi],eax jnz short badcmp add edi,4 inc eax loop cmlp mov dx,offset goodmsg jmp short pmsg badcmp: mov dx,offset badmsg pmsg: mov ah,9 int 21h ret testmegs endp ; start: call seta20 jc short bada20 call bigreal ; Switch FS & GS to large seg sizes call fillmegs call testmegs done: mov ah,04ch ; Back to DOS; big limits on everything. int 21h bada20: mov dx,offset msg mov ah,9 int 21h jmp done SEG8086 ends end start