3 ;******************************************************************************
5 ; (C) Copyright MICROSOFT Corp. 1986
7 ; Title: MEMM - MICROSOFT Expanded Memory Manager 386
17 ;******************************************************************************
21 ; DATE REVISION DESCRIPTION
22 ; -------- -------- -------------------------------------------------------
23 ; 06/13/86 Original Separated out OEMPROC from OEMDEP.INC
25 ;******************************************************************************
28 .lfcond
; list false conditionals
43 public ROM_BIOS_Machine_ID
44 public OEM_Init_Diag_Page
77 ;******************************************************************************
78 ; E X T E R N A L R E F E R E N C E S
79 ;******************************************************************************
88 extrn set_src_selector
:near
89 extrn set_dest_selector
:near
90 extrn SetPageEntry
:near
98 ;******************************************************************************
99 ; L O C A L C O N S T A N T S
100 ;******************************************************************************
103 MASTER_IMR equ 21h
; mask port for master 8259
106 ; PPI port bit definitions
110 PPO_MASK_IOCHECK equ
04h ; disable system board parity check
111 PPO_MASK_PCHECK equ
08h ; disable IO parity check
113 RTC_CMD equ 70h
; Real Time Clock cmd port
114 DISABLE_NMI equ 80h
; mask bit for NMI
115 ENABLE_NMI equ
00h ; this command to RTC_CMD enables NMI
117 ;****** REMOVE BEFORE DISTRIBUTION begin
118 ; Compaq specific 386 related addresses
120 X_HI_MEM_SEG equ
0f000h ;segment for the following words
121 X_MT_386 equ
0fffeh ; Machine type
122 X_RT_386 equ
0ffe8h ; Rom type
123 X_HI_PTR equ
0ffe0h ; pointer to four words (offsets below)
124 X_MEM_BOARD equ
0 ; 32-bit memory board status word
125 X_HISYS equ
0 ; low byte = # of free 4k system pages
126 X_AVAIL_MEM equ
4 ; available hi memory in 16 byte chunks
127 X_LAST_HI equ
6 ; last used byte in hi memory (grows down)
129 ; Addresses and values used to write the "ROM"
131 OEM_MEM_HI equ 80c0h
; Upper 16 bits of high mem physical adr
132 LOCK_ADR_LO equ
0000h ; 0:15 of 32-bit location
133 LOCK_ADR_HI equ OEM_MEM_HI
; 16-31 of 32-bit location
134 LOCK_ROM equ
0fcfch ; value to write to lock rom
135 UNLOCK_ROM equ
0fefeh ; value to write to unlock rom
139 DIAGSEG
segment use16 at 0
140 DiagLoc dw ?
; 32 bit memory board diagnostic byte
149 NMI_Old db 8 dup (0) ; save area for old NMI handler
151 NMI_New
label byte ; descriptor for new NMI handler
152 IDT_ENTRY VDMC_GSEL
,<offset _TEXT
:Parity_Handler
>,D_386INT0
155 ifndef NOHIMEM
; if high memory in this model
156 ;Next two entries MUST stay together!
157 hbase_addr_l dw 0000h ; 24 bit address of beginning of hi memory
158 hbase_addr_h db 00h ; pool of EMM pages.
160 hi_size dw 0 ; size of hi memory in kbytes
161 hi_alloc dw 0 ; actual hi memory allocated (due to potential waste)
162 hisys_alloc dw 0 ; amount of hi system memory allocated in 4k bytes
164 DiagAddr db 0 ; set this when writting to diag byte location
165 DiagByte db LOW LOCK_ROM
; most recent diag byte written by user
166 buffer dw 0 ; buffer for 1 word move blocks
170 int_mask db ?
; save for restoring masked interrupts
173 ROM_BIOS_Machine_ID db 0fch ; hard coded right now to AT model byte.
174 ; should be changed to be initialised at
179 ;****** REMOVE BEFORE DISTRIBUTION end
183 ASSUME
CS:_TEXT
, DS:DGROUP
185 ;******************************************************************************
187 ; MaskIntAll Save current interrupt mask state and mask all interrupts
189 ; entry: DS pts to DGROUP
191 ; exit: All interrupts disabled
197 ;******************************************************************************
201 mov al,0ffh ;;; all OFF
206 ;******************************************************************************
208 ; RestIntMask Restore interrupt mask saved in MaskIntAll
210 ; entry: DS pts to DGROUP
212 ; exit: Interrupts restored to state previous to MaskIntAll
218 ;******************************************************************************
219 RestIntMask proc
near
220 mov al,[int_mask
] ; restore interrupt mask
225 ;******************************************************************************
226 ; OEM_Trap_Init - turn on I/O bit map trapping for I/O port watching
228 ; ENTRY: DS -> DGROUP - real,virtual, or protected mode
230 ; Trap_Tab already has address of OEM_Handler for ??? ports
232 ; Description: This routine is used to initialize any data structures,
233 ; including the IOBitMap(via PortTrap call) used for trapping I/O ports
234 ; when going into virtual mode. The routine(s) used to handle the
235 ; trap(s) should already be installed in the IOTrap_tab table.
236 ; See RRTrap.asm for an example.
238 ; EXIT: IO_BitMap Updated to trap ports used for ???
242 ;------------------------------------------------------------------------------
243 assume
cs:_TEXT
, ds:DGROUP
, es:TSS
244 OEM_Trap_Init proc
near
246 ; Initialize data structures
249 ; Set IOBM traps to look for client's disabling of the A20 line
252 ; mov bh, 80h ; set every 1k
253 ; mov ax, ??? ; AX = port num to trap
254 ; call PortTrap ; set traps on ??? port
257 ; mov [???],ax ; Initialize trap data structure
265 ifndef NOHIMEM
; only for high memory
267 ;******************************************************************************
269 ; HwMemUnlock - unlocks high system RAM - makes tables writeable
273 ; EXIT: If NOHIMEM, does nothing, else:
274 ; FS points to DIAG segment
275 ; high system RAM writeable
277 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
278 HwMemUnlock proc
near
280 POP_FS
; set FS to diag segment
283 mov word ptr [DiagLoc
],UNLOCK_ROM
289 ;******************************************************************************
291 ; HwMemLock - update client's hi system RAM write locks state
293 ; ENTRY: CS = _TEXT(Protected mode)
294 ; DGROUP:[DiagByte] = last byte written to diag byte by user.
296 ; EXIT: high system RAM write protect ON or OFF depenending on
297 ; write protect bit in CS:[DiagByte].
298 ; Bit 1 = 0 => write protect ON
299 ; Bit 1 = 1 => write protect OFF
301 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
308 test [DiagByte
],02h ;Q: client's ROM write protected?
311 POP_FS
; set FS to diag segment
314 jz HTL_wp
; Y: then write protect ON
315 FSOVER
; N: then write protect OFF
316 mov word ptr [DiagLoc
],UNLOCK_ROM
320 mov word ptr [DiagLoc
],LOCK_ROM
325 endif
;end of "high" memory routines(ifndef NOHIMEM)
327 ;******************************************************************************
329 ; Map_Lin_OEM Map OEM high memory from physical to linear address
331 ; description: This maps an attempt to access the "high" memory to the
332 ; area starting at 16Meg, which the page tables map to the
333 ; proper physical address.
335 ; entry: EAX = physical address to map to linear address
337 ; exit: If address has been mapped in AX, CF = 1, else CF = 0.
343 ;******************************************************************************
345 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
346 Map_Lin_OEM proc
near
349 dw OEM_MEM_HI
;Q: Addr in diags byte region ?
351 jne Mp_Lin_Exit
; N: return, CF = 0(no mapping done)
352 OP32
; Y: set EAX to proper seg address for diags
354 dw (OEM_MEM_HI
- 0100h); move to 0100h segment
356 ; set write to diag byte flag
361 mov [DiagAddr
],1 ; set flag for diag addr
371 ;******************************************************************************
373 ; UMap_Lin_OEM Map OEM high memory from linear to physical address
375 ; description: This maps an attempt to access the "high" memory in the
376 ; linear address area starting at 16Meg, to the proper physical
379 ; entry: EAX = linear address to map to physical address
381 ; exit: EAX = physical address
387 ;******************************************************************************
389 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
390 UMap_Lin_OEM proc
near
391 OP32
; Y: set EAX to physical address for diags
393 dw (OEM_MEM_HI
- 0100h) ; move to OEM_MEM_HI segment
397 ;******************************************************************************
399 ; MB_Map_Src Do special move block processing before source mapping
402 ; This routine is called just before MoveBlock does mapping of
403 ; the source. In conjunction with the Map_Lin_OEM routine, and
404 ; the MB_Start routine, it can perform special processing on the
407 ; entry: ES:DI pts to source work descr in GDT
409 ; exit: any flag setting or perturbation of descriptor is done
415 ;******************************************************************************
416 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
421 ;******************************************************************************
423 ; MB_Map_Dest Do special move block processing before destination mapping
426 ; This routine is called just before MoveBlock does mapping of
427 ; the destination. In conjunction with the Map_Lin_OEM routine,
428 ; and the MB_Start routine, it can perform special processing on
431 ; entry: ES:DI pts to destination work descr in GDT
433 ; exit: any flag setting or perturbation of descriptor is done
439 ;******************************************************************************
440 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
441 MB_Map_Dest proc
near
445 pop ds ; DS = DGROUP alias selector
447 mov [DiagAddr
],0 ; reset diag addr flag before write
453 ;******************************************************************************
455 ; MB_Start Do any special move block processing
458 ; This routine is called just before MoveBlock does the move.
459 ; It allows for any special processing of data moved
461 ; entry: DS is source selector
462 ; ES is destination selector
463 ; SI is source offset
464 ; DI is destination offset
472 ;******************************************************************************
473 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
477 ; check for write to diag byte location
481 pop es ; ES = DGROUP alias
483 cmp es:[DiagAddr
],0 ;Q: does target -> diag byte ?
484 je MB_nodiag
; N: then don't worry
485 mov al,[si] ; Y: get current diag byte
486 mov es:[DiagByte
],al ; and save it where we can access it
493 ;*************************************************************************
494 ; Set_Par_Vect - Set parity handling routine to routine below
497 ; This routine sets up a parity handling routine in case of
498 ; a parity error during a MOVEBLOCK.
500 ; ENTRY: protected mode
502 ; EXIT: vector restored
504 ; USES: AX, CX, ES, DS, DI, SI
506 ; note: entry is from protected mode -> DS,ES are same as during
508 ;*************************************************************************
509 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
510 Set_Par_Vect proc
near
512 mov es,ax ; ES pts to DGROUP
514 mov ds,ax ; DS points to IDT
516 mov si,0010h ; DS:[SI] points to NMI descr address in IDT
517 mov di,offset DGROUP
:NMI_Old
; ES:[DI] pts to store area
520 rep movsw ; store 2 dwords - save current NMI descriptor
525 mov di,0010h ; ES:[DI] points to NMI descr address in IDT
526 mov si,offset DGROUP
:NMI_New
; DS:[SI] pts to new NMI descr
529 rep movsw ; set up new NMI descriptor in IDT
533 ;*************************************************************************
534 ; Rest_Par_Vect - restore parity handling routine to original
537 ; This routine restores the parity handling vector to the
538 ; contents before Set_Par_Vect was called. It is called after
539 ; a MOVEBLOCK has been completed.
543 ; EXIT: vector restored
545 ; USES: AX, CX, ES, DI, SI
547 ; note: entry is from protected mode -> DS,ES are same as during
549 ;*************************************************************************
550 assume
cs:_TEXT
, ds:DGROUP
, es:NOTHING
551 Rest_Par_Vect proc
near
553 call HwMemUnlock
; in case IDT is in high mem
555 mov ax,IDTD_GSEL
; selector for IDT
556 mov es,ax ; ES points to IDT
558 mov di,0010h ; ES:[DI] points to NMI descr address in IDT
559 mov si,offset DGROUP
:NMI_Old
; DS:[SI] pts to store area
562 rep movsw ; restore previous NMI descriptor
570 ;*************************************************************************
571 ; Parity_Handler - routine to handle parity errors which occur during
574 ; This routine writes to the parity error location to
575 ; clear the parity error on the memory board, then it clears
576 ; the parity error on the system board.
578 ; note: entry is from protected mode -> DS,ES are same as during
580 ;*************************************************************************
581 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
582 Parity_Handler proc
far
585 dec si ;;; DS:SI pts to address causing parity error
586 mov ax,[si] ;;; retrieve value and write it back
587 mov [si],ax ;;; to reset parity on memory board.
588 in al,PPI
;;; Get parity error flags, reset then set
589 jmp $+2 ;;; parity checking to reset parity on
590 jmp $+2 ;;; system board
591 or al,PPO_MASK_IOCHECK
;;; disable IOCHECK
592 or al,PPO_MASK_PCHECK
;;; disable PCHECK
593 out PPO
,al ;;; disable them
599 call HwMemlock
;;; LOCK high sys mem
602 and al, NOT PPO_MASK_IOCHECK
;;; enable IOCHECK
603 and al, NOT PPO_MASK_PCHECK
;;; enable PCHECK
604 out PPO
,al ;;; enable them
605 ;;; system board parity now reset
609 mov ds,ax ;;; set DS to data seg
611 mov [MB_Stat
],1 ;;; set parity error
612 add sp,12 ;;; remove NMI stuff from stack
613 jmp MB_Exit
;;; and exit move block
617 ;*************************************************************************
618 ; DisableNMI - This is called by the NMI handler to disable the
619 ; NMI interrupt(stop gracefully) as part of the
620 ; graceful handling of the NMI interrupt.
624 ; note: entry is from 386 protected mode
625 ;*************************************************************************
626 assume
cs:_TEXT
, ds:NOTHING
, es:NOTHING
639 ;******************************************************************************
641 ; VerifyMachine Check ID, etc. to make sure machine is 386 valid for
642 ; running the LIM/386 product.
645 ; This routine should check ROM signature bytes and any other
646 ; hardware features that guarantee the appropriateness of running this
647 ; software on the machine.
649 ; entry: DS pts to DGROUP
650 ; CF = 1 if from INIT procedure, CF = 0 if from AllocMem procedure
651 ; REAL or VIRTUAL MODE
653 ; exit: If not correct machine, CF = 1, else CF = 0.
659 ;******************************************************************************
661 assume
cs:LAST
, ds:NOTHING
, es:NOTHING
662 VerifyMachine proc
near
666 mov bx,X_HI_MEM_SEG
; segment of hi memory control words
668 mov ax,es:X_MT_386
; get machine type
669 cmp al,0FCh ; q: is this an AT class machine?
670 mov ax,es:X_RT_386
; get ROM type
673 jne inc_prcf
; n: invalid
675 jc Cor_Prc
; that's all the checking for INIT
676 cmp ax,'30' ; q: is this a 386? (really '03')
686 VerifyMachine endp
; End of procedure
689 ifndef NOHIMEM
; if high memory in this model
690 ;******************************************************************************
692 ; Hi_Mem_Size - returns pointer and size of high mem allocated to EMM
696 ; exit: if ZF = 1, no high memory allocated to EMM, else
697 ; EAX = 24 bit pointer to EMM allocated high memory
698 ; CX = kbytes of high memory allocated
700 ; used: EAX, CX(returned values)
704 ;******************************************************************************
706 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
707 Hi_Mem_Size proc
near
708 mov cx,[hi_size
] ; CX = kbytes of high mem
709 shr cx,4 ;Q: any hi memory pages ? CX = pg cnt
710 jz Hi_Mem_SXit
; N: Exit with ZF = 1
711 db 66h
; Y: get high memory pointers
712 mov ax,[hbase_addr_l
] ; get pointer to high memory pool
714 and ax,0FFFFh ; AND EAX,00FFFFFFh
715 dw 00FFh ; clear highest nibble
721 ;******************************************************************************
723 ; hbuf_chk Hi memory pool check.
724 ; Check available hi memory pool space
728 ; exit: If hi memory pool space is available then
729 ; AX = size of memory available and CF = 0
730 ; else AX = 0 and CF = 1
732 ; used: AX(returned value)
736 ;******************************************************************************
738 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
742 mov bx,X_HI_MEM_SEG
; segment of hi memory control words
744 mov bx,es:X_HI_PTR
; pointer to hi memory control words
745 mov ax,es:[bx+X_MEM_BOARD
] ; 32-bit memory board status
746 inc ax ; q: memory board status word == -1?
748 jz hbuf_xit
; y: not installed
749 mov ax,es:[bx+X_AVAIL_MEM
] ; get available memory in 16 byte pieces
750 mov bx,es:[bx+X_LAST_HI
] ; get last used address
751 and bx,0ffh ; align to 4k byte boundary (2**8)*16
752 sub ax,bx ; ax = available 16 byte pieces
753 shr ax,10 ; ax = available 16k byte pieces
754 shl ax,4 ; ax = available 1k byte pieces
757 pop bx ; ax = availble memory unless CF = 1
763 ;******************************************************************************
765 ; HiAlloc - allocate hi memory - update hi memory control words
767 ; entry: REAL or VIRTUAL MODE
769 ; DGROUP:[hi_size] size in kbytes to allocate
771 ; exit: update available hi memory and last used address.
772 ; Set [hbase_addr_l] and [hbase_addr_h] to starting address.
773 ; If error occurs in writing control words, CF = 1, else CF = 0.
779 ;******************************************************************************
780 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
790 mov ax,[hi_size
] ; get amount of hi memory to allocate
791 or ax,ax ; q: allocate any?
792 jz Hi_xit
; n: quit(CF = 0)
795 shl ax,cl ; back to 16 byte pieces
797 mov bx,X_HI_MEM_SEG
; high memory segment
799 mov bx,es:X_HI_PTR
; pointer to high memory control words
800 mov cx,0ffh ; determine waste by aligning to 4k
801 and cx,es:[bx+X_LAST_HI
] ; cx = extra needed to align
802 add ax,cx ; ax = total to allocate
803 mov [hi_alloc
],ax ; save it in case we need to put it back
804 xor bx,bx ; bx = no hi system memory to alloc
805 call HImod
; go allocate it
806 ; ax = start of this hi memory
807 jc Hi_xit
; error occurred during move block(CF=1)
809 mul cx ; make it 24 bits
810 add dl,0f0h ; last 1M segment
811 mov [hbase_addr_h
],dl ; save starting address of hi mem
812 mov [hbase_addr_l
],ax
815 Hi_xit: ; CF = 1 if error, else CF = 0
826 ;******************************************************************************
828 ; HiSysAlloc - allocate hi system memory - update hi memory control words
830 ; entry: REAL or VIRTUAL MODE
832 ; ax = # of 4k byte pieces to allocate
834 ; exit: If enough hi system memory available
835 ; update available hi system memory.
836 ; ax = # of 4k byte pieces used before this allocation.
839 ; ax = amount of hi system memory available
841 ; If error occurs in writing control words,
849 ;******************************************************************************
850 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
855 push ax ; save amount asked for
856 mov bx,X_HI_MEM_SEG
; high memory segment
858 mov bx,es:X_HI_PTR
; pointer to high memory control words
859 mov ax,es:[bx+X_HISYS
] ; ax = amount of hi system mem available
860 and ax,00ffh ; after we get rid of high byte
861 pop bx ; bx = amount requested
862 ; ax = amount currently available
863 cmp ax,bx ; Q: available >= requested?
864 jb Hisys_xit
; N: quit - carry set => not enough mem
865 add [hisys_alloc
],bx ; Y: save it in case we must deallocate
866 push ax ; save amount available before
867 xor ax,ax ; ax = no hi user mem to alloc
868 call HImod
; go allocate high sys mem
869 pop bx ; bx = amount available before
870 jc Hisys_err
; MOD ERROR -> set error flag
871 mov ax,10h
; 16 pages in high sys mem pool
872 sub ax,bx ; ax = amount used before this request
873 jmp Hisys_xit
; no error in move block
885 ;******************************************************************************
887 ; Himod - allocate/deallocate hi memory - update hi memory control words
889 ; entry: REAL or VIRTUAL MODE
891 ; ax = size in 16 bytes of hi USER mem to alloc (a negative #
893 ; bx = size in 4k bytes of hi SYSTEM mem to alloc (ditto above)
895 ; exit: update available hi memory and last used address.
896 ; ax = New last used address for high user memory
897 ; CY = set if block move error occurred
903 ;******************************************************************************
904 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
912 call UnLockROM
;Q: ROM space writeable?
913 jz unlock_ok
; Y: continue
914 jmp Himod_err
; N: exit
916 push bx ; save hi system memory allocation
917 mov bx,X_HI_MEM_SEG
; high memory segment
919 mov bx,es:X_HI_PTR
; pointer to high memory control words
920 sub es:[bx+X_AVAIL_MEM
],ax ; update hi memory available
921 sub es:[bx+X_LAST_HI
],ax ; and last used address
922 pop ax ; get hi system memory amount
923 sub es:[bx+X_HISYS
],ax ; update hi system memory available
924 mov ax,es:[bx+X_LAST_HI
] ; start of this hi memory
926 call LockROM
;Q: ROM write protected now ?
927 clc ; clear error flag
928 jz Himod_xit
; Y: exit with no error
944 ;******************************************************************************
946 ; LockROM - write protects high system RAM
948 ; entry: REAL or VIRTUAL MODE
951 ; exit: Z = no error - high system RAM write protected
958 ;******************************************************************************
959 assume
cs:LAST
, ds:DGROUP
, es:NOTHING
966 mov word ptr [buffer
],LOCK_ROM
; word to write to unlock
967 jmp UL_write
; go write it...
972 ;******************************************************************************
974 ; UnLockROM - turns off write protect on high system RAM
976 ; entry: REAL or VIRTUAL MODE
979 ; exit: Z = no error - high system RAM writeable
986 ;******************************************************************************
987 assume
cs:LAST
, ds:DGROUP
, es:DGROUP
994 mov word ptr [buffer
],UNLOCK_ROM
; word to write to unlock
997 mov ax,seg DGROUP
; set source addr to buffer
998 mov es,ax ; set ES to DGROUP
1000 mul cx ; make 24 bits
1001 add ax,offset DGROUP
:buffer
1003 mov cx,1 ; 1 word to transfer
1004 call set_src_selector
; set source segment selector to buffer
1005 mov ax,LOCK_ADR_LO
; DX:AX = 32-bit addr of ROM LOCK
1007 mov cx,1 ; 1 word long
1008 call set_dest_selector
; destination is unlock address
1011 mov es,ax ; es to last segmetn
1012 mov si,offset DGROUP
:gdt_mb
; ES:SI -> global descriptor table
1013 mov ah,MOVE_BLK
; int 15 block move function code
1014 int XBIOS
; unlock rom
1015 or ah,ah ; Q: error?
1023 UnLockROM endp
; end of procedure
1025 endif
; end of code for not NOHIMEM
1028 ;******************************************************************************
1030 ; OEM_Init_Diag_Page: Initialise the 5th page table to point to the
1031 ; diagnostic segment.
1035 ; place 32 bit memory board diagnostic byte address into page table
1036 ; xxxx0000h - xxxxFFFFh physical
1037 ; -> 01000000h - 0100FFFFh linear => 64k => 16 entries in page tables
1038 ; => 1st 64k in 5th page table
1040 ; entry: DS pts to DGROUP
1041 ; ES:0 Page table seg.
1045 ; used: ax,di,dx,bx,cx,flags
1049 ;******************************************************************************
1051 OEM_Init_Diag_Page proc
near
1052 assume
cs:LAST
, ds:dgroup
, es:NOTHING
1055 mov di,4*P_SIZE
; ES:DI -> 1st 64k of 5th page table
1057 xor ax,ax ; start with physical addr = xxxx0000h
1059 mov bl,P_AVAIL
; make pages available to all
1060 mov cx,10h
; set 64k worth of entries
1063 ; ES:[DI] pts to next page table entry
1064 add ax,1000h
; next physical page
1065 adc dx,0h
; address in DX,AX
1066 loop IT_set_entry
;Q: done with page table entries ?
1071 OEM_Init_Diag_Page endp
1073 LAST ends
; End of segment
1075 ifndef NOHIMEM
; if high memory in this model
1078 assume
cs:R_CODE
, ds:DGROUP
, es:DGROUP
1080 ;******************************************************************************
1081 ; InitLock - Init state of Table lock
1083 ; NOTE: this is a FAR routine.
1089 ; DGROUP:[DiagByte] = updated to current LOCK state
1093 ;******************************************************************************
1096 mov [DiagByte
],LOW LOCK_ROM
; default is locked
1099 mov es,ax ; ES -> ROM
1100 mov bx,X_MT_386
; ES:BX -> machine type byte
1101 mov ax,ES:[bx] ; AX = ROM contents
1102 xor ES:[bx],0FFFFh ; flip all bits in ROM
1103 xor ax,0FFFFh ; AX = "flipped" value
1104 cmp ax,ES:[bx] ;Q: flipped value in ROM ?
1105 jne gv_locked
; N: "ROM" is locked
1106 mov [DiagByte
],LOW UNLOCK_ROM
;Y: ROM is UNLOCKED
1108 xor ES:[bx],0FFFFh ; restore ROM contents (if changed)
1117 endif
; end of code for not NOHIMEM