2 TITLE BU_ASM.ASM -- ASM support for DOS BU_LIB
4 ;****************************************************************************
5 ;* Copyright (C) Intel Corporation 1994-1999
7 ;* All rights reserved. No part of this program or publication
8 ;* may be reproduced, transmitted, transcribed, stored in a
9 ;* retrieval system, or translated into any language or computer
10 ;* language, in any form or by any means, electronic, mechanical,
11 ;* magnetic, optical, chemical, manual, or otherwise, without
12 ;* the prior written permission of Intel Corporation.
13 ;****************************************************************************
15 ; To assemble with MASM61 -- ml /c a16utils.asm
17 ;****************************************************************************
42 ;--------------------------------------------------------------------
54 ;--------------------------------------------------------------------
71 lgdt FWORD PTR _gdt_ptr
78 ;--------------------------------------------------------------------
83 PUBLIC _dAPAwake, _dAPDone, _dAPFuncPtr, _wProcNumber, _bSPValid
84 PUBLIC _wCSegDS, _wCSegES, _wCSegSS, _wCSegSP, _wASegDS, _wASegES
89 emsfilename DB 'EMMXXXX0',0
107 _gdt DD 0 ; NULL descriptor
108 DD 0 ; NULL descriptor
110 ; 64K real mode style data segment
111 DD 0ffffh ; base 0, limit 0xffff
112 DD 00009200h ; data, CPL=0, 16-bit, 1 byte granularity, r/w
114 ; 4G flat data segment
115 DD 0ffffh ; base 0, limit 0xfffff
116 DD 008f9200h ; data, CPL=0, 16-bit, 4K granularity, r/w
121 _dAPHltJmp DD 0 ; jump to halt location
124 EXTERNDEF pascal cprint:proc
128 mov ah,3dh ; open file
129 xor al,al ; read only operation
130 mov dx,offset emsfilename ; look for EMMXXXX0
132 jc emserror1 ; if carry flag set, then no EMM driver
134 mov di,ax ; save file handle
135 mov bx,ax ; set up handle
136 mov ax,4400h ; get device (channel) info
139 mov ah,3eh ; close file
140 mov bx,di ; close the file handle up
142 jc emserror1 ; if carry flag set, then no driver is present
144 test dx,10000000b ; if bit 7 not set, then the channel is a file
145 jz emserror1 ; otherwise the channel is a device driver
147 mov ax,1 ; 1 = EMS present
151 xor ax,ax ; 0 = EMS not present
164 _set_rows PROC C rows:WORD
207 _cpuid_asm PROC C hv:DWORD, regs:PTR DWORD
272 IF @DataSize ; segment is far
274 mov dword ptr es:[bx], eax
276 mov dword ptr es:[bx + 4], eax
277 mov dword ptr es:[bx + 8], ecx
278 mov dword ptr es:[bx + 12], edx
279 ELSE ; segment is near
281 mov dword ptr [bx], eax
283 mov dword ptr [bx + 4], eax
284 mov dword ptr [bx + 8], ecx
285 mov dword ptr [bx + 12], edx
293 ;--------------------------------------------------------------------
294 ; Pentium Pro MSRs - from Pentium Pro Developer's Manual
295 ; January 1996 - Appendix C
297 ; MTRRs: 200h - 20Fh, 250h, 258h - 259h, 268h - 26Fh, 2FFh
298 ;--------------------------------------------------------------------
300 _read_msr PROC C dmsr:DWORD, pqmsr:PTR DWORD
305 mov DWORD ptr es:[bx], eax
306 mov DWORD ptr es:[bx + 4], edx
311 ;--------------------------------------------------------------------
314 _write_msr PROC C dmsr:DWORD, pqmsr:PTR DWORD
317 mov eax, DWORD ptr es:[bx]
318 mov edx, DWORD ptr es:[bx + 4]
325 ;----------------------------------------------------------------------------
326 ; Procedure: dReadCR0 - Reads CR0 CPU Register
328 ; Output: dx:ax and eax - Contents of CR0
330 ; Registers: All registers preserved except EAX and EDX
331 ;----------------------------------------------------------------------------
336 shr edx, 16 ; upper 16 bits in dx
340 ;----------------------------------------------------------------------------
341 ; Procedure: dReadCR2 - Reads CR2 CPU Register
343 ; Output: dx:ax and eax - Contents of CR2
345 ; Registers: All registers preserved except EAX and EDX
346 ;----------------------------------------------------------------------------
351 shr edx, 16 ; upper 16 bits in dx
355 ;----------------------------------------------------------------------------
356 ; Procedure: dReadCR3 - Reads CR3 CPU Register
358 ; Output: dx:ax and eax - Contents of CR3
360 ; Registers: All registers preserved except EAX and EDX
361 ;----------------------------------------------------------------------------
366 shr edx, 16 ; upper 16 bits in dx
372 ;----------------------------------------------------------------------------
373 ; Procedure: dGetProcUpdateRev_asm - Reads PPP Update Revision via an MSR
375 ; Output: dx:ax and eax - PPP Update Revision
377 ; Registers: All registers preserved except EAX, ECX, and EDX
378 ;----------------------------------------------------------------------------
379 PUBLIC _dGetProcUpdateRev_asm
380 _dGetProcUpdateRev_asm PROC C
381 mov ecx, 08Bh ; model specific register to write
384 dw 300Fh ; WRMSR ==> load 0 to MSR at 8Bh
387 mov ecx, 08Bh ; model specific register to read
388 dw 320Fh ; RDMSR ==> EDX = (read) MSR 8Bh
389 mov eax, edx ; return EAX
390 shr edx, 16 ; return DX:AX
392 _dGetProcUpdateRev_asm ENDP
394 ;--------------------------------------------------------------------
396 PUBLIC iInterruptFlagState
397 iInterruptFlagState PROC
403 iInterruptFlagState ENDP
405 ;--------------------------------------------------------------------
411 ; TBD: verify this on an AMD K6-2 266 MHz
412 ; Assert A20M# via system control port A (This is a
413 ; system dependent feature).
416 out 92h, al ; re-assert A20M#
425 mov ax, [_old_fs] ; restore original
427 mov ax, [_old_gs] ; restore original
433 ;--------------------------------------------------------------------
438 mov [_old_fs], ax ; save original fs
440 mov [_old_gs], ax ; save original gs
442 ; Deassert A20M# via system control port A (This is a
443 ; system dependent feature)
446 out 92h, al ; de-assert A20M#
463 ; TBD: verify this on an AMD K6-2 266 MHz
464 ; Assert A20M# via system control port A (This is a
465 ; system dependent feature).
468 out 92h, al ; re-assert A20M#
477 mov ax, [_old_es] ; restore original
479 mov ax, [_old_gs] ; restore original
485 ;--------------------------------------------------------------------
490 mov [_old_es], ax ; save original
492 mov [_old_gs], ax ; save original
494 ; Deassert A20M# via system control port A (This is a
495 ; system dependent feature)
498 out 92h, al ; de-assert A20M#
512 print PROC PASCAL Seq:DWORD
532 shr ecx, 2 ; byte count / 4 = dword count
538 lock or eax, gs:[esi]
551 je Exit ; no extra bytes to move
554 mov al, byte ptr gs:[esi]
555 mov byte ptr gs:[edi], al
568 ;--------------------------------------------------------------------
576 mov cx, [esp+6] ; high word of apic address
578 mov cx, [esp+4] ; low word of apic address
580 mov dx, [esp+10] ; high word of apic command
582 mov dx, [esp+8] ; low word of apic command
590 ;--------------------------------------------------------------------
597 mov cx, [esp+6] ; low word of apic address
599 mov cx, [esp+4] ; high word of apic address
605 pop eax ; restore eax
612 ;--------------------------------------------------------------------
613 ; Since the AP shares the BSP's stack, coordination is needed to avoid
614 ; simultaneous usage by both processors, which would cause corruption.
616 ; While the AP is executing here, the BSP is executing the code
617 ; which follows the call to vAPStartupAll() or vAPStartupOne()
618 ; in bu_apic.c:vExecuteOnAPs(). After disabling interrupts,
619 ; the BSP stores the sp value in _wCSegSP, sets _bSPValid to 1,
620 ; and spins while _dAPDone != _dAPAwake. (Both are initially zero;
621 ; the code below increments _dAPAwake before spinning on _bSPValid.)
623 ; XXX - There is a race condition here: if the BSP makes it all
624 ; XXX - the way to its spin loop on _dAPDone != _dAPAwake before
625 ; XXX - the AP increments _dAPAwake, the BSP will exit the spin
626 ; XXX - loop without actually having waited for the AP to finish.
634 lock inc dword ptr [_dAPAwake]
639 ; XXX - The following line is supposed to provide some validity checking,
640 ; XXX - but it does not entirely succeed. It is possible for > 1 AP to
641 ; XXX - see _bSPValid == 1, and exit the spin1 loop just above, before
642 ; XXX - the first one out has had time to decrement _bSPValid; this race
643 ; XXX - defeats the purpose of decrementing it. The decrement is likely
644 ; XXX - not needed anyway due to the exclusion provided by the spin2 loop
646 lock dec byte ptr[_bSPValid]
652 ; critical section - determining unique cpu signatures
656 ; XXX - Should the following line have a 'lock' prefix?
657 xchg word ptr [_block], ax
661 mov ax, ds ; Save ASM DS and ES in global vars
668 mov ax, [_wCSegDS] ; Restore C DS and ES from global vars
671 ; Update Current Processor Number. Mutual exclusion from other AP's is
672 ; guaranteed by the spin2 loop above.
673 ; Note that the "processor number" determined here represents the order
674 ; in which the processors happened to get through the spin2 lock, and
675 ; has nothing to do with APIC numbers. A system having > 1 AP will not
676 ; necessarily number the AP's consistently from one run to the next.
679 mov [_wProcNumber], ax
681 call [_dAPFuncPtr] ; _dAPFuncPtr needs to point to a void function
683 mov ax, [_wASegDS] ; Restore ASM DS and ES from global vars
688 lock inc dword ptr [_dAPDone]
689 lock inc byte ptr [_bSPValid]
692 ; A simple 'mov' would serve as well as the following 'xchg'.
693 xchg word ptr [_block], ax
695 mov si, offset _dAPHltJmp
696 jmp dword ptr [si] ; Jump to HLT, JMP $-1 in F000 segment
697 hlt ; Should never get here
700 ;--------------------------------------------------------------------
703 bIn8 PROC C wPort:WORD
710 ;--------------------------------------------------------------------
713 wIn16 PROC C wPort:WORD
719 ;--------------------------------------------------------------------
722 dIn32 PROC C wPort:WORD
730 ;--------------------------------------------------------------------
733 vOut8 PROC C wPort:WORD, bValue:BYTE
740 ;--------------------------------------------------------------------
743 vOut16 PROC C wPort:WORD, wValue:WORD
750 ;--------------------------------------------------------------------
753 vOut32 PROC C wPort:WORD, dValue:DWORD
760 ;--------------------------------------------------------------------
762 ; int FlatMove (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
764 FlatMoveX PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
765 call vm86 ; check if VM86 mode
767 jne NotRealMode ; skip memory move if not in real mode
769 call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
770 ; base 0:0 and de-assert A20M#
774 je SKipMemoryMove ; skip memory move if 0==sSize
778 jbe SkipMemoryMove ; skip memory move if destination is 40:0
779 ; BIOS Data Area or less (IVT)
783 mov dl, gs:[ebx][ecx - 1]
784 mov gs:[eax][ecx - 1], dl
793 mov ax, 1 ; return error code
798 ; int FlatMove32 (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
800 FlatMove32 PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
802 call vm86 ; check if VM86 mode
804 jne NotRealMode ; skip memory move if not in real mode
806 call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
807 ; base 0:0 and de-assert A20M#
820 je SkipMemoryMove ; skip memory move if 0==sSize
823 jbe SkipMemoryMove ; skip memory move if destination is 40:0
824 ; BIOS Data Area or less (IVT)
825 call DoMove ; edx=Count, esi=src, edi=dst
846 mov ax, 1 ; return error code
852 ; int FlatMove32 (DWORD dPhysicalDestination, DWORD dPhysicalSource, size_t sSize)
854 FlatMove32x PROC C dDest:DWORD, dSrc:DWORD, sSize:WORD
855 call vm86 ; check if VM86 mode
857 jne NotRealMode ; skip memory move if not in real mode
859 call vFlatFsGs ; set up FS and GS as 4GB limit selectors with
860 ; base 0:0 and de-assert A20M#
863 je SKipMemoryMove ; skip memory move if 0==sSize
867 jbe SkipMemoryMove ; skip memory move if destination is 40:0
868 ; BIOS Data Area or less (IVT)
880 shr ecx, 2 ; byte count / 4 = dword count
885 mov edx, dword ptr gs:[ebx][esi]
886 mov dword ptr gs:[eax][esi], edx
896 je Exit ; no extra bytes to move
899 mov dl, gs:[ebx][esi]
900 mov gs:[eax][esi], dl
912 mov ax, 1 ; return error code