summaryrefslogtreecommitdiff
path: root/v4.0/src/MEMM/MEMM/OEMPROC.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v4.0/src/MEMM/MEMM/OEMPROC.ASM')
-rw-r--r--v4.0/src/MEMM/MEMM/OEMPROC.ASM1120
1 files changed, 1120 insertions, 0 deletions
diff --git a/v4.0/src/MEMM/MEMM/OEMPROC.ASM b/v4.0/src/MEMM/MEMM/OEMPROC.ASM
new file mode 100644
index 0000000..b5e4931
--- /dev/null
+++ b/v4.0/src/MEMM/MEMM/OEMPROC.ASM
@@ -0,0 +1,1120 @@
1
2
3;******************************************************************************
4;
5; (C) Copyright MICROSOFT Corp. 1986
6;
7; Title: MEMM - MICROSOFT Expanded Memory Manager 386
8;
9; Module: OEMPROC.ASM
10;
11; Version: 0.05
12;
13; Date: June 13, 1986
14;
15; Author:
16;
17;******************************************************************************
18;
19; Change log:
20;
21; DATE REVISION DESCRIPTION
22; -------- -------- -------------------------------------------------------
23; 06/13/86 Original Separated out OEMPROC from OEMDEP.INC
24;
25;******************************************************************************
26;
27.386p
28.lfcond ; list false conditionals
29
30public VerifyMachine
31public MaskIntAll
32public RestIntMask
33public OEM_Trap_Init
34public Map_Lin_OEM
35public UMap_Lin_OEM
36public MB_Map_Src
37public MB_Map_Dest
38public MB_Start
39public Rest_Par_Vect
40public Set_Par_Vect
41
42public DisableNMI
43public ROM_BIOS_Machine_ID
44public OEM_Init_Diag_Page
45
46
47ifndef NOHIMEM
48
49public hi_size
50public hi_alloc
51public hisys_alloc
52
53public HwMemLock
54public HwMemUnlock
55
56public Hi_Mem_Size
57public hbuf_chk
58public HiAlloc
59public HiSysAlloc
60public HImod
61
62public InitLock
63public LockROM
64public UnLockROM
65
66
67endif
68
69 include page.inc
70 include vdmseg.inc
71 include VDMsel.inc
72 include desc.inc
73 include Instr386.inc
74 include romxbios.equ
75
76
77;******************************************************************************
78; E X T E R N A L R E F E R E N C E S
79;******************************************************************************
80;
81_DATA segment
82 extrn gdt_mb:word
83 extrn MB_Stat:word
84_DATA ends
85
86
87LAST segment
88 extrn set_src_selector:near
89 extrn set_dest_selector:near
90 extrn SetPageEntry:near
91LAST ends
92
93_TEXT segment
94 extrn MB_Exit:near
95_TEXT ends
96
97 page
98;******************************************************************************
99; L O C A L C O N S T A N T S
100;******************************************************************************
101;
102
103MASTER_IMR equ 21h ; mask port for master 8259
104
105;
106; PPI port bit definitions
107;
108PPI equ 61h
109PPO equ 61h
110PPO_MASK_IOCHECK equ 04h ; disable system board parity check
111PPO_MASK_PCHECK equ 08h ; disable IO parity check
112
113RTC_CMD equ 70h ; Real Time Clock cmd port
114DISABLE_NMI equ 80h ; mask bit for NMI
115ENABLE_NMI equ 00h ; this command to RTC_CMD enables NMI
116
117;****** REMOVE BEFORE DISTRIBUTION begin
118; Compaq specific 386 related addresses
119;
120X_HI_MEM_SEG equ 0f000h ;segment for the following words
121X_MT_386 equ 0fffeh ; Machine type
122X_RT_386 equ 0ffe8h ; Rom type
123X_HI_PTR equ 0ffe0h ; pointer to four words (offsets below)
124X_MEM_BOARD equ 0 ; 32-bit memory board status word
125X_HISYS equ 0 ; low byte = # of free 4k system pages
126X_AVAIL_MEM equ 4 ; available hi memory in 16 byte chunks
127X_LAST_HI equ 6 ; last used byte in hi memory (grows down)
128;
129; Addresses and values used to write the "ROM"
130;
131OEM_MEM_HI equ 80c0h ; Upper 16 bits of high mem physical adr
132LOCK_ADR_LO equ 0000h ; 0:15 of 32-bit location
133LOCK_ADR_HI equ OEM_MEM_HI ; 16-31 of 32-bit location
134LOCK_ROM equ 0fcfch ; value to write to lock rom
135UNLOCK_ROM equ 0fefeh ; value to write to unlock rom
136
137
138
139DIAGSEG segment use16 at 0
140DiagLoc dw ? ; 32 bit memory board diagnostic byte
141DIAGSEG ends
142
143
144;
145; data definitions
146;
147_DATA segment
148
149NMI_Old db 8 dup (0) ; save area for old NMI handler
150
151NMI_New label byte ; descriptor for new NMI handler
152IDT_ENTRY VDMC_GSEL,<offset _TEXT:Parity_Handler>,D_386INT0
153
154;
155ifndef NOHIMEM ; if high memory in this model
156;Next two entries MUST stay together!
157hbase_addr_l dw 0000h ; 24 bit address of beginning of hi memory
158hbase_addr_h db 00h ; pool of EMM pages.
159;
160hi_size dw 0 ; size of hi memory in kbytes
161hi_alloc dw 0 ; actual hi memory allocated (due to potential waste)
162hisys_alloc dw 0 ; amount of hi system memory allocated in 4k bytes
163;
164DiagAddr db 0 ; set this when writting to diag byte location
165DiagByte db LOW LOCK_ROM ; most recent diag byte written by user
166buffer dw 0 ; buffer for 1 word move blocks
167endif
168
169
170int_mask db ? ; save for restoring masked interrupts
171
172;
173ROM_BIOS_Machine_ID db 0fch ; hard coded right now to AT model byte.
174 ; should be changed to be initialised at
175 ; init time ...isp
176
177
178_DATA ends
179;****** REMOVE BEFORE DISTRIBUTION end
180
181
182_TEXT segment
183 ASSUME CS:_TEXT, DS:DGROUP
184
185;******************************************************************************
186;
187; MaskIntAll Save current interrupt mask state and mask all interrupts
188;
189; entry: DS pts to DGROUP
190;
191; exit: All interrupts disabled
192;
193; used: AX
194;
195; stack:
196;
197;******************************************************************************
198MaskIntAll proc near
199 in al,MASTER_IMR
200 mov [int_mask], al
201 mov al,0ffh ;;; all OFF
202 out MASTER_IMR,al
203 ret
204MaskIntAll endp
205
206;******************************************************************************
207;
208; RestIntMask Restore interrupt mask saved in MaskIntAll
209;
210; entry: DS pts to DGROUP
211;
212; exit: Interrupts restored to state previous to MaskIntAll
213;
214; used: AX
215;
216; stack:
217;
218;******************************************************************************
219RestIntMask proc near
220 mov al,[int_mask] ; restore interrupt mask
221 out MASTER_IMR,al
222 ret
223RestIntMask endp
224
225;******************************************************************************
226; OEM_Trap_Init - turn on I/O bit map trapping for I/O port watching
227;
228; ENTRY: DS -> DGROUP - real,virtual, or protected mode
229; ES -> TSS segment
230; Trap_Tab already has address of OEM_Handler for ??? ports
231;
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.
237;
238; EXIT: IO_BitMap Updated to trap ports used for ???
239;
240; USED: AX,Flags
241; STACK:
242;------------------------------------------------------------------------------
243 assume cs:_TEXT, ds:DGROUP, es:TSS
244OEM_Trap_Init proc near
245;
246; Initialize data structures
247;
248;
249; Set IOBM traps to look for client's disabling of the A20 line
250;
251; push bx
252; mov bh, 80h ; set every 1k
253; mov ax, ??? ; AX = port num to trap
254; call PortTrap ; set traps on ??? port
255;
256; mov ax,0FFFFh
257; mov [???],ax ; Initialize trap data structure
258; pop bx
259
260 ret
261;
262OEM_Trap_Init endp
263;
264
265ifndef NOHIMEM ; only for high memory
266
267;******************************************************************************
268;
269; HwMemUnlock - unlocks high system RAM - makes tables writeable
270;
271; ENTRY: None
272;
273; EXIT: If NOHIMEM, does nothing, else:
274; FS points to DIAG segment
275; high system RAM writeable
276;
277 assume cs:_TEXT, ds:NOTHING, es:NOTHING
278HwMemUnlock proc near
279 push OEM0_GSEL
280 POP_FS ; set FS to diag segment
281 ASSUME DS:DIAGSEG
282 FSOVER
283 mov word ptr [DiagLoc],UNLOCK_ROM
284 ret
285HwMemUnlock endp
286
287
288
289;******************************************************************************
290;
291; HwMemLock - update client's hi system RAM write locks state
292;
293; ENTRY: CS = _TEXT(Protected mode)
294; DGROUP:[DiagByte] = last byte written to diag byte by user.
295;
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
300;
301 assume cs:_TEXT, ds:NOTHING, es:NOTHING
302HwMemLock proc near
303
304 push VDMD_GSEL
305 POP_FS ; FS = DGROUP
306 assume ds:DGROUP
307 FSOVER
308 test [DiagByte],02h ;Q: client's ROM write protected?
309
310 push OEM0_GSEL
311 POP_FS ; set FS to diag segment
312 ASSUME DS:DIAGSEG
313
314 jz HTL_wp ; Y: then write protect ON
315 FSOVER ; N: then write protect OFF
316 mov word ptr [DiagLoc],UNLOCK_ROM
317 jmp short HTL_exit
318HTL_wp:
319 FSOVER
320 mov word ptr [DiagLoc],LOCK_ROM
321HTL_exit:
322 ret
323HwMemLock endp
324
325endif ;end of "high" memory routines(ifndef NOHIMEM)
326
327;******************************************************************************
328;
329; Map_Lin_OEM Map OEM high memory from physical to linear address
330;
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.
334;
335; entry: EAX = physical address to map to linear address
336;
337; exit: If address has been mapped in AX, CF = 1, else CF = 0.
338;
339; used: AX
340;
341; stack:
342;
343;******************************************************************************
344;
345 assume cs:_TEXT, ds:NOTHING, es:NOTHING
346Map_Lin_OEM proc near
347 OP32
348 cmp ax,0000h
349 dw OEM_MEM_HI ;Q: Addr in diags byte region ?
350 clc
351 jne Mp_Lin_Exit ; N: return, CF = 0(no mapping done)
352 OP32 ; Y: set EAX to proper seg address for diags
353 sub ax,0000h
354 dw (OEM_MEM_HI - 0100h); move to 0100h segment
355ifndef NOHIMEM
356; set write to diag byte flag
357 push ds ; save DS
358 push VDMD_GSEL
359 pop ds ; DS = DGROUP
360 ASSUME DS:DGROUP
361 mov [DiagAddr],1 ; set flag for diag addr
362 pop ds ; reset DS
363endif
364 stc
365Mp_Lin_Exit:
366 ret
367Map_Lin_OEM endp
368
369
370
371;******************************************************************************
372;
373; UMap_Lin_OEM Map OEM high memory from linear to physical address
374;
375; description: This maps an attempt to access the "high" memory in the
376; linear address area starting at 16Meg, to the proper physical
377; address.
378;
379; entry: EAX = linear address to map to physical address
380;
381; exit: EAX = physical address
382;
383; used: EAX
384;
385; stack:
386;
387;******************************************************************************
388;
389 assume cs:_TEXT, ds:NOTHING, es:NOTHING
390UMap_Lin_OEM proc near
391 OP32 ; Y: set EAX to physical address for diags
392 add ax,0000h
393 dw (OEM_MEM_HI - 0100h) ; move to OEM_MEM_HI segment
394 ret
395UMap_Lin_OEM endp
396
397;******************************************************************************
398;
399; MB_Map_Src Do special move block processing before source mapping
400;
401; description:
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
405; data moved.
406;
407; entry: ES:DI pts to source work descr in GDT
408;
409; exit: any flag setting or perturbation of descriptor is done
410;
411; used: none
412;
413; stack:
414;
415;******************************************************************************
416 assume cs:_TEXT, ds:NOTHING, es:NOTHING
417MB_Map_Src proc near
418 ret
419MB_Map_Src endp
420
421;******************************************************************************
422;
423; MB_Map_Dest Do special move block processing before destination mapping
424;
425; description:
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
429; the data moved.
430;
431; entry: ES:DI pts to destination work descr in GDT
432;
433; exit: any flag setting or perturbation of descriptor is done
434;
435; used: AX
436;
437; stack:
438;
439;******************************************************************************
440 assume cs:_TEXT, ds:NOTHING, es:NOTHING
441MB_Map_Dest proc near
442ifndef NOHIMEM
443 push ds
444 push VDMD_GSEL
445 pop ds ; DS = DGROUP alias selector
446 ASSUME DS:DGROUP
447 mov [DiagAddr],0 ; reset diag addr flag before write
448 pop ds ; reset DS
449endif
450 ret
451MB_Map_Dest endp
452
453;******************************************************************************
454;
455; MB_Start Do any special move block processing
456;
457; description:
458; This routine is called just before MoveBlock does the move.
459; It allows for any special processing of data moved
460;
461; entry: DS is source selector
462; ES is destination selector
463; SI is source offset
464; DI is destination offset
465;
466; exit: nothing
467;
468; used: AX
469;
470; stack:
471;
472;******************************************************************************
473 assume cs:_TEXT, ds:NOTHING, es:NOTHING
474MB_Start proc near
475ifndef NOHIMEM
476;
477; check for write to diag byte location
478;
479 push es
480 push VDMD_GSEL
481 pop es ; ES = DGROUP alias
482 ASSUME ES:DGROUP
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
487MB_nodiag:
488 pop es ; restore es
489endif
490 ret
491MB_Start endp
492
493;*************************************************************************
494; Set_Par_Vect - Set parity handling routine to routine below
495;
496; Description:
497; This routine sets up a parity handling routine in case of
498; a parity error during a MOVEBLOCK.
499;
500; ENTRY: protected mode
501;
502; EXIT: vector restored
503;
504; USES: AX, CX, ES, DS, DI, SI
505;
506; note: entry is from protected mode -> DS,ES are same as during
507; move block.
508;*************************************************************************
509 assume cs:_TEXT, ds:NOTHING, es:NOTHING
510Set_Par_Vect proc near
511 mov ax,VDMD_GSEL
512 mov es,ax ; ES pts to DGROUP
513 mov ax,IDTD_GSEL ;
514 mov ds,ax ; DS points to IDT
515
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
518 mov cx,2
519 db 66h
520 rep movsw ; store 2 dwords - save current NMI descriptor
521 push ds
522 push es
523 pop ds ; DS = DGROUP
524 pop es ; ES = IDT
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
527 mov cx,2
528 db 66h
529 rep movsw ; set up new NMI descriptor in IDT
530 ret
531Set_Par_Vect endp
532
533;*************************************************************************
534; Rest_Par_Vect - restore parity handling routine to original
535;
536; Description:
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.
540;
541; ENTRY: DS = DGROUP
542;
543; EXIT: vector restored
544;
545; USES: AX, CX, ES, DI, SI
546;
547; note: entry is from protected mode -> DS,ES are same as during
548; move block.
549;*************************************************************************
550 assume cs:_TEXT, ds:DGROUP, es:NOTHING
551Rest_Par_Vect proc near
552ifndef NOHIMEM
553 call HwMemUnlock ; in case IDT is in high mem
554endif
555 mov ax,IDTD_GSEL ; selector for IDT
556 mov es,ax ; ES points to IDT
557
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
560 mov cx,2
561 db 66h
562 rep movsw ; restore previous NMI descriptor
563ifndef NOHIMEM
564 call HwMemLock
565endif
566 ret
567Rest_Par_Vect endp
568
569
570;*************************************************************************
571; Parity_Handler - routine to handle parity errors which occur during
572; move_block.
573; Description:
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.
577;
578; note: entry is from protected mode -> DS,ES are same as during
579; move block.
580;*************************************************************************
581 assume cs:_TEXT, ds:NOTHING, es:NOTHING
582Parity_Handler proc far
583;
584 dec si
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
594 jmp $+2
595 jmp $+2
596 jmp $+2
597
598ifndef NOHIMEM
599 call HwMemlock ;;; LOCK high sys mem
600endif
601
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
606
607;
608 mov ax,VDMD_GSEL ;;;
609 mov ds,ax ;;; set DS to data seg
610 assume ds:DGROUP
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
614
615Parity_Handler endp
616
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.
621;
622; Description:
623;
624; note: entry is from 386 protected mode
625;*************************************************************************
626 assume cs:_TEXT, ds:NOTHING, es:NOTHING
627DisableNMI proc near
628 push ax
629 mov al,DISABLE_NMI
630 out RTC_CMD,al
631 pop ax
632 ret
633DisableNMI endp
634
635_TEXT ends
636
637LAST segment
638
639;******************************************************************************
640;
641; VerifyMachine Check ID, etc. to make sure machine is 386 valid for
642; running the LIM/386 product.
643;
644; description:
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.
648;
649; entry: DS pts to DGROUP
650; CF = 1 if from INIT procedure, CF = 0 if from AllocMem procedure
651; REAL or VIRTUAL MODE
652;
653; exit: If not correct machine, CF = 1, else CF = 0.
654;
655; used: AX
656;
657; stack:
658;
659;******************************************************************************
660;
661 assume cs:LAST, ds:NOTHING, es:NOTHING
662VerifyMachine proc near
663 pushf
664 push es ; save es
665 push bx ; save bx
666 mov bx,X_HI_MEM_SEG ; segment of hi memory control words
667 mov es,bx ; into es
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
671 pop bx ; restore bx
672 pop es ; restore es
673 jne inc_prcf ; n: invalid
674 popf
675 jc Cor_Prc ; that's all the checking for INIT
676 cmp ax,'30' ; q: is this a 386? (really '03')
677 jne inc_prc
678Cor_Prc:
679 clc
680 ret
681inc_prcf:
682 popf
683inc_prc:
684 stc
685 ret
686VerifyMachine endp ; End of procedure
687
688
689ifndef NOHIMEM ; if high memory in this model
690;******************************************************************************
691;
692; Hi_Mem_Size - returns pointer and size of high mem allocated to EMM
693;
694; entry:
695;
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
699;
700; used: EAX, CX(returned values)
701;
702; stack:
703;
704;******************************************************************************
705;
706 assume cs:LAST, ds:DGROUP, es:NOTHING
707Hi_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
713 db 66h
714 and ax,0FFFFh ; AND EAX,00FFFFFFh
715 dw 00FFh ; clear highest nibble
716Hi_Mem_SXit:
717 ret
718Hi_Mem_Size endp
719
720 page
721;******************************************************************************
722;
723; hbuf_chk Hi memory pool check.
724; Check available hi memory pool space
725;
726; entry:
727;
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
731;
732; used: AX(returned value)
733;
734; stack:
735;
736;******************************************************************************
737;
738 assume cs:LAST, ds:DGROUP, es:NOTHING
739hbuf_chk proc near
740 push es ; save es
741 push bx
742 mov bx,X_HI_MEM_SEG ; segment of hi memory control words
743 mov es,bx
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?
747 stc
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
755 clc
756hbuf_xit:
757 pop bx ; ax = availble memory unless CF = 1
758 pop es
759 ret
760hbuf_chk endp
761;
762 page
763;******************************************************************************
764;
765; HiAlloc - allocate hi memory - update hi memory control words
766;
767; entry: REAL or VIRTUAL MODE
768; DS pts to DGROUP
769; DGROUP:[hi_size] size in kbytes to allocate
770;
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.
774;
775; used: none
776;
777; stack:
778;
779;******************************************************************************
780 assume cs:LAST, ds:DGROUP, es:NOTHING
781HiAlloc proc near
782;
783 push ax
784 push bx
785 push cx
786 push dx
787 push si
788 push es
789;
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)
793
794 mov cl,6
795 shl ax,cl ; back to 16 byte pieces
796;
797 mov bx,X_HI_MEM_SEG ; high memory segment
798 mov es,bx
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)
808 mov cx,16
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
813 clc
814;
815Hi_xit: ; CF = 1 if error, else CF = 0
816 pop es
817 pop si
818 pop dx
819 pop cx
820 pop bx
821 pop ax
822 ret
823HiAlloc endp
824;
825 page
826;******************************************************************************
827;
828; HiSysAlloc - allocate hi system memory - update hi memory control words
829;
830; entry: REAL or VIRTUAL MODE
831; DS pts to DGROUP
832; ax = # of 4k byte pieces to allocate
833;
834; exit: If enough hi system memory available
835; update available hi system memory.
836; ax = # of 4k byte pieces used before this allocation.
837; CY cleared
838; else
839; ax = amount of hi system memory available
840; CY set
841; If error occurs in writing control words,
842; CY set
843; ax = -1
844;
845; used: see above
846;
847; stack:
848;
849;******************************************************************************
850 assume cs:LAST, ds:DGROUP, es:NOTHING
851HiSysAlloc proc near
852 push bx
853 push es
854;
855 push ax ; save amount asked for
856 mov bx,X_HI_MEM_SEG ; high memory segment
857 mov es,bx
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
874;
875Hisys_err:
876 mov ax,-1
877 stc ; to be sure
878Hisys_xit:
879 pop es
880 pop bx
881 ret
882HiSysAlloc endp
883;
884 page
885;******************************************************************************
886;
887; Himod - allocate/deallocate hi memory - update hi memory control words
888;
889; entry: REAL or VIRTUAL MODE
890; DS pts to DGROUP
891; ax = size in 16 bytes of hi USER mem to alloc (a negative #
892; will deallocate)
893; bx = size in 4k bytes of hi SYSTEM mem to alloc (ditto above)
894;
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
898;
899; used: none
900;
901; stack:
902;
903;******************************************************************************
904 assume cs:LAST, ds:DGROUP, es:NOTHING
905HImod proc near
906 push bx
907 push cx
908 push dx
909 push si
910 push es
911;
912 call UnLockROM ;Q: ROM space writeable?
913 jz unlock_ok ; Y: continue
914 jmp Himod_err ; N: exit
915unlock_ok:
916 push bx ; save hi system memory allocation
917 mov bx,X_HI_MEM_SEG ; high memory segment
918 mov es,bx
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
925;
926 call LockROM ;Q: ROM write protected now ?
927 clc ; clear error flag
928 jz Himod_xit ; Y: exit with no error
929; ; N: report error
930Himod_err:
931 stc ; indicate error
932HImod_xit:
933 pop es
934 pop si
935 pop dx
936 pop cx
937 pop bx
938;
939 ret
940
941
942HImod endp
943 page
944;******************************************************************************
945;
946; LockROM - write protects high system RAM
947;
948; entry: REAL or VIRTUAL MODE
949; DS pts to DGROUP
950;
951; exit: Z = no error - high system RAM write protected
952; NZ = ERROR.
953;
954; used: none
955;
956; stack:
957;
958;******************************************************************************
959 assume cs:LAST, ds:DGROUP, es:NOTHING
960LockROM proc near
961 push ax ; save ax
962 push cx
963 push dx
964 push es
965;
966 mov word ptr [buffer],LOCK_ROM ; word to write to unlock
967 jmp UL_write ; go write it...
968;
969LockROM endp
970
971 page
972;******************************************************************************
973;
974; UnLockROM - turns off write protect on high system RAM
975;
976; entry: REAL or VIRTUAL MODE
977; DS pts to DGROUP
978;
979; exit: Z = no error - high system RAM writeable
980; NZ = ERROR.
981;
982; used: none
983;
984; stack:
985;
986;******************************************************************************
987 assume cs:LAST, ds:DGROUP, es:DGROUP
988UnLockROM proc near
989 push ax ; save ax
990 push cx
991 push dx
992 push es
993;
994 mov word ptr [buffer],UNLOCK_ROM ; word to write to unlock
995;
996UL_write:
997 mov ax,seg DGROUP ; set source addr to buffer
998 mov es,ax ; set ES to DGROUP
999 mov cx,16
1000 mul cx ; make 24 bits
1001 add ax,offset DGROUP:buffer
1002 adc dl,0
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
1006 mov dx,LOCK_ADR_HI
1007 mov cx,1 ; 1 word long
1008 call set_dest_selector ; destination is unlock address
1009
1010 mov ax,seg LAST
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?
1016 ; Y: return NZ
1017 ; N: return Z
1018 pop es
1019 pop dx
1020 pop cx
1021 pop ax
1022 ret
1023UnLockROM endp ; end of procedure
1024
1025endif ; end of code for not NOHIMEM
1026
1027
1028;******************************************************************************
1029;
1030; OEM_Init_Diag_Page: Initialise the 5th page table to point to the
1031; diagnostic segment.
1032;
1033; description:
1034;
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
1039;
1040; entry: DS pts to DGROUP
1041; ES:0 Page table seg.
1042;
1043; exit: nothing
1044;
1045; used: ax,di,dx,bx,cx,flags
1046;
1047; stack:
1048;
1049;******************************************************************************
1050;
1051OEM_Init_Diag_Page proc near
1052 assume cs:LAST, ds:dgroup, es:NOTHING
1053;
1054;
1055 mov di,4*P_SIZE ; ES:DI -> 1st 64k of 5th page table
1056 mov dx,OEM_MEM_HI
1057 xor ax,ax ; start with physical addr = xxxx0000h
1058 mov bh,0
1059 mov bl,P_AVAIL ; make pages available to all
1060 mov cx,10h ; set 64k worth of entries
1061IT_set_entry:
1062 call SetPageEntry
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 ?
1067 ; N: loop again
1068 ; Y: all done
1069 ret
1070;
1071OEM_Init_Diag_Page endp
1072
1073LAST ends ; End of segment
1074
1075ifndef NOHIMEM ; if high memory in this model
1076
1077R_CODE SEGMENT
1078 assume cs:R_CODE, ds:DGROUP, es:DGROUP
1079
1080;******************************************************************************
1081; InitLock - Init state of Table lock
1082;
1083; NOTE: this is a FAR routine.
1084;
1085; ENTRY: REAL MODE
1086; DS = DGROUP
1087;
1088; EXIT: REAL MODE
1089; DGROUP:[DiagByte] = updated to current LOCK state
1090;
1091; USED: AX,BX
1092;
1093;******************************************************************************
1094InitLOCK proc far
1095
1096 mov [DiagByte],LOW LOCK_ROM ; default is locked
1097 push es
1098 mov ax,X_HI_MEM_SEG
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
1107gv_locked:
1108 xor ES:[bx],0FFFFh ; restore ROM contents (if changed)
1109;
1110 pop es
1111 ret
1112
1113InitLOCK endp
1114
1115R_CODE ENDS
1116
1117endif ; end of code for not NOHIMEM
1118
1119 end ; of module
1120