-
Notifications
You must be signed in to change notification settings - Fork 4
/
himem.asm
2802 lines (2213 loc) · 81.1 KB
/
himem.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;*****************************************************************************
;* *
;* HIMEM.ASM - Chip Anderson *
;* *
;* Extended Memory Specification Driver - *
;* Copyright 1988, Microsoft Corporation *
;* *
;* The HMA was originally envisioned by Ralph Lipe. *
;* Original XMS spec designed by Aaron Reynolds, Chip Anderson, and *
;* Tony Gosling. Additional spec suggestions by Phil Barrett and David *
;* Weise of Microsoft, Ed McNierney of Lotus and Bob Smith of Qualitas. *
;* *
;* MoveExtMemory function written by Tony Gosling. *
;* *
;* AT&T 6300 support added by Bill Hall, Olivetti ATC, Cupertino, CA *
;* HP Vectra support added by Ralph Peterson, Hewlett Packard Corp. *
;* *
;*****************************************************************************
XMSVersion equ 0200h
HimemVersion equ 0203h
; Version -
;
; 1.00 - Written 4/17/88
; 1.01 - Added Global/Temporary Enable of A20 4/18/88
; 1.02 - Don't use DOS to change interrupts 4/19/88
; - Return 1 for success in Disable cases 4/19/88
; - Prevent disables if A20 enabled at start 4/19/88
; - Added INT 2F handler check 4/19/88
; - Used smarter hooking routine 4/19/88
; 1.03 - Optimized some code 4/20/88
; - Temporarily Disable properly 4/20/88
; - Disable INT's while changing vars 4/20/88
; 1.04 - Check to see if A20 works during init 4/23/88
; - Fixed PS/2 support 4/23/88
; 1.05 - Added QueryExtMemory and AllocExtMemory 4/25/88
; 1.06 - Never remove the INT 15h hook once it is in 4/27/88
; - Changed ExtMemory calls to provide "full" MM 4/27/88
; - Force A20 line off on PS2's at init time 4/27/88
; 1.07 - Added Multiple A20 Handler support 5/01/88
; - Added popff macro 5/01/88
; - REP MOVSW words not bytes 5/04/88
; 1.08 - Made popff relocateable 5/04/88
; - Added support for the AT&T 6300 Plus 5/05/88
; - Added support for the HP Vectra 5/06/88
; 1.09 - Added CEMM recognition code 5/16/88
; - Don't automatically trash BX in HMMControl 5/17/88
; 1.10 - Change PS/2 ID routine to use Watchdog timer 6/02/88
; - Changed CEMM recognition string to just VDISK 6/07/88
; - Fixed 2 instance bug 6/14/88
; 1.11 - Changed INT 2F multiplex number to 43h 6/23/88
; - Fixed HP Vectra support for older Vectras 6/23/88
; - Fixed Block Move register trashing bug 6/25/88
; 2.00 - Updated to XMS v2.00 7/10/88
; - Reworked initialization code 7/12/88
; - Reworked reentrancy issues 7/13/88
; - Finialized A20 handling 7/14/88
; - Added parameter support 7/14/88
; 2.01 - Official version with Vecta and 6300 support 7/15/88
; 2.02 - Removed INT 1 from MoveExtMemory 7/19/88
; - Fixed minor problems in QueryExtMemory 7/19/88
; 2.03 - Added 386 Big Mode MoveBlock 8/04/88
; - Added Compaq "Built-In" Memory support 8/05/88
; - Fixed 64K-free Installation bug 8/05/88
; - Change PS/2 detection code yet again 8/08/88
; - Fixed "A20 On" Message bug (ugh) 8/09/88
; - Fixed A20 Init testing code 8/09/88
; - Cleaned up for publication 8/09/88
name Himem
title 'HIMEM.SYS - Microsoft XMS Device Driver'
;*--------------------------------------------------------------------------*
;* EQUATES *
;*--------------------------------------------------------------------------*
DEFHANDLES equ 32 ; Default # of EMB handles
MAXHANDLES equ 128 ; Max # of EMB handles
cXMSFunctions equ 12h ; = # of last function+1!
FREEFLAG equ 00000001b ; EMB Flags
USEDFLAG equ 00000010b
UNUSEDFLAG equ 00000100b
; XMS Error Codes.
ERR_NOTIMPLEMENTED equ 080h
ERR_VDISKFOUND equ 081h
ERR_A20 equ 082h
ERR_GENERAL equ 08Eh
ERR_UNRECOVERABLE equ 08Fh
ERR_HMANOTEXIST equ 090h
ERR_HMAINUSE equ 091h
ERR_HMAMINSIZE equ 092h
ERR_HMANOTALLOCED equ 093h
ERR_OUTOMEMORY equ 0A0h
ERR_OUTOHANDLES equ 0A1h
ERR_INVALIDHANDLE equ 0A2h
ERR_SHINVALID equ 0A3h
ERR_SOINVALID equ 0A4h
ERR_DHINVALID equ 0A5h
ERR_DOINVALID equ 0A6h
ERR_LENINVALID equ 0A7h
ERR_OVERLAP equ 0A8h
ERR_PARITY equ 0A9h
ERR_EMBUNLOCKED equ 0AAh
ERR_EMBLOCKED equ 0ABh
ERR_LOCKOVERFLOW equ 0ACh
ERR_LOCKFAIL equ 0ADh
ERR_UMBSIZETOOBIG equ 0B0h
ERR_NOUMBS equ 0B1h
ERR_INVALIDUMB equ 0B2h
.386p
; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is
; necessary to use the special OS-MERGE hardware to activate lines
; A20 to A23. However, these lines can be disabled only by resetting
; the processor. The address to which to return after reset are placed
; at 40:A2, noted here as RealLoc1.
BiosSeg SEGMENT USE16 AT 40h ; Used to locate 6300 PLUS reset address
org 00A2h
RealLoc1 dd 0
BiosSeg ends
; Macro to avoid the 286 POPF bug. Performs a harmless IRET to simulate a
; popf. Some 286s allow interrupts to sneak in during a real popf.
popff macro
push cs
call pPPFIRet ; Defined as the offset of any IRET
endm
;*--------------------------------------------------------------------------*
;* SEGMENT DEFINITION *
;*--------------------------------------------------------------------------*
CODE SEGMENT PARA PUBLIC USE16 'CODE'
assume cs:code,ds:code,es:code
org 0
; The Driver Header definition.
Header dd -1 ; Link to next driver, -1 = end of list
dw 1010000000000000b
; Device attributes, Non-IBM bit set
dw Strategy ; "Stategy" entry point
dw Interrupt ; "Interrupt" entry point
db 'XMSXXXX0' ; Device name
;****************************************************************************
;* *
;* Data Structures and Global Variables - *
;* *
;****************************************************************************
; The driver Request Header structure definition.
ReqHdr struc
ReqLen db ?
Unit db ?
Command db ?
Status dw ?
Reserved db 8 dup (?)
Units db ?
Address dd ?
pCmdLine dd ?
ReqHdr ends
; An EMB Handle structure definition.
Handle struc ; Handle Table Entry
Flags db ? ; Unused/InUse/Free
cLock db ? ; Lock count
Base dw ? ; 32-bit base address in K
Len dw ? ; 32-bit length in K
Handle ends
; Extended Memory Move Block structure definition.
MoveExtendedStruc struc
bCount dd ? ; Length of block to move
SourceHandle dw ? ; Handle for souce
SourceOffset dd ? ; Offset into source
DestHandle dw ? ; Handle for destination
DestOffset dd ? ; Offset into destination
MoveExtendedStruc ends
; The Global variables.
pPPFIRet dw PPFIRet ; The offset of an IRET for the POPFF macro
pReqHdr dd ? ; Pointer to MSDOS Request Header structure
pInt15Vector dw 15h*4,0 ; Pointer to the INT 15 Vector
PrevInt15 dd 0 ; Original INT 15 Vector
PrevInt2F dd 0 ; Original INT 2F Vector
fHMAInUse db 0 ; High Memory Control Flag, != 0 -> In Use
fCanChangeA20 db 0 ; A20 Enabled at start?
fHMAMayExist db 0 ; True if the HMA could exist at init time
fHMAExists db 0 ; True if the HMA exists
fVDISK db 0 ; True if a VDISK device was found
EnableCount dw 0 ; A20 Enable/Disable counter
fGlobalEnable dw 0 ; Global A20 Enable/Disable flag
KiddValley dw 0 ; The address of the handle table
KiddValleyTop dw 0 ; Points to the end of the handle table
MinHMASize dw 0 ; /HMAMIN= parameter value
cHandles dw DEFHANDLES ; # of handles to allocate
cImplementedFuncs db cXMSFunctions-3 ; Omit the UMB functions
; and ReallocEMB
A20Handler dw 0 ; Offset of the A20 Handler
BIMBase dw 0 ; Base address and Lenght of remaining Compaq
BIMLength dw 0 ; Built-In Memory (set at Init time)
MemCorr dw 0 ; KB of memory at FA0000 on AT&T 6300 Plus.
; This is used to correct INT 15h,
; Function 88h return value.
OldStackSeg dw 0 ; Stack segment save area for 6300 Plus.
; Needed during processor reset.
;*--------------------------------------------------------------------------*
;* *
;* Strategy - *
;* *
;* Called by MS-DOS when ever the driver is accessed. *
;* *
;* ARGS: ES:BX = Address of Request Header *
;* RETS: Nothing *
;* REGS: Preserved *
;* *
;*--------------------------------------------------------------------------*
Strategy proc far
; Save the address of the request header.
mov word ptr cs:[pReqHdr],bx
mov word ptr cs:[pReqHdr][2],es
ret
Strategy endp
;*--------------------------------------------------------------------------*
;* *
;* Interrupt - *
;* *
;* Called by MS-DOS immediately after Strategy routine *
;* *
;* ARGS: None *
;* RETS: Return code in Request Header's Status field *
;* REGS: Preserved *
;* *
;*--------------------------------------------------------------------------*
Interrupt proc far
; Save the registers including flags.
push ax ; We cannot use pusha\popa because
push bx ; we could be on an 8086 at this point
push cx
push dx
push ds
push es
push di
push si
push bp
pushf
; Set DS=CS for access to global variables.
push cs
pop ds
les di,[pReqHdr] ; ES:DI = Request Header
mov bl,es:[di.Command] ; Get Function code in BL
or bl,bl ; Only Function 00h (Init) is legal
jz short IInit
cmp bl,16 ; Test for "legal" DOS functions
jle short IOtherFunc
IBogusFunc: mov ax,8003h ; Return "Unknown Command"
jmp short IExit
IOtherFunc: xor ax,ax ; Return zero for unsupported functions
jmp short IExit
; Initialize the driver.
IInit: call InitDriver
les di,[pReqHdr] ; Restore ES:DI = Request Header
IExit: or ax,0100h ; Turn on the "Done" bit
mov es:[di.Status],ax ; Store return code
; Restore the registers.
popff
pop bp
pop si
pop di
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
ret
Interrupt endp
;*--------------------------------------------------------------------------*
;* *
;* Int2FHandler - *
;* *
;* Hooks Function 43h, Subfunction 10h to return the *
;* address of the High Memory Manager Control function. *
;* Also returns 80h if Function 43h, Subfunction 0h is requested. *
;* *
;* ARGS: AH = Function, AL = Subfunction *
;* RETS: ES:BX = Address of XMMControl function (if AX=4310h) *
;* AL = 80h (if AX=4300) *
;* REGS: Preserved except for ES:BX (if AX=4310h) *
;* Preserved except for AL (if AX=4300h) *
;* *
;*--------------------------------------------------------------------------*
Int2FHandler proc far
sti ; Flush any queued interrupts
cmp ah,43h ; Function 43h?
jne short I2FNextInt
or al,al ; Subfunction 0?
jne short I2FNextSub ; No, continue
; Indicate that an XMS driver is installed.
mov al,80h ; Return 80h in AL
PPFIRet: iret ; Label sets up the POPFF macro
I2FNextSub: cmp al,10h ; Subfunction 10?
jne short I2FNextInt ; No, goto next handler
; Return the address of the XMS Control function in ES:BX.
push cs
pop es
mov bx,offset XMMControl
iret
; Continue down the Int 2F chain.
I2FNextInt: cli ; Disable interrupts again
jmp cs:[PrevInt2F]
Int2FHandler endp
;*--------------------------------------------------------------------------*
;* *
;* ControlJumpTable - *
;* *
;* Contains the address for each of the XMS Functions. *
;* *
;*--------------------------------------------------------------------------*
ControlJumpTable label word
dw Version ; Function 00h
dw RequestHMA ; Function 01h
dw ReleaseHMA ; Function 02h
dw GlobalEnableA20 ; Function 03h
dw GlobalDisableA20 ; Function 04h
dw LocalEnableA20 ; Function 05h
dw LocalDisableA20 ; Function 06h
dw IsA20On ; Function 07h
dw QueryExtMemory ; Function 08h
dw AllocExtMemory ; Function 09h
dw FreeExtMemory ; Function 0Ah
dw MoveBlock ; Function 0Bh
dw LockExtMemory ; Function 0Ch
dw UnlockExtMemory ; Function 0Dh
dw GetExtMemoryInfo ; Function 0Eh
; We don't implement Realloc in this version.
; dw ReallocExtMemory ; Function 0Fh
; We don't implement the UMB functions.
; dw RequestUMB ; Function 14
; dw ReleaseUMB ; Function 15
;*--------------------------------------------------------------------------*
;* *
;* XMMControl - *
;* *
;* Main Entry point for the Extended Memory Manager *
;* *
;* ARGS: AH = Function, AL = Optional parm *
;* RETS: AX = Function Success Code, BL = Optional Error Code *
;* REGS: AX, BX, DX and ES may not be preserved depending on function *
;* *
;* INTERNALLY REENTRANT *
;* *
;*--------------------------------------------------------------------------*
XMMControl proc far
jmp short XCControlEntry ; For "hookability"
nop ; NOTE: The jump must be a
nop ; short jump to indicate
nop ; the end of any hook chain.
; The nop's allow a far jump
; to be patched in.
XCControlEntry:
; Preserve the following registers.
push cx
push si
push di
push ds
push es
pushf
; Save DS in ES.
push ds
pop es ; NOTE: ES cannot be used for parms!
; Set DS equal to CS.
push cs
pop ds
; Preserve the current function number.
push ax
; Is this a call to "Get XMS Version"?
or ah,ah
jz short XCCallFunc ; Yes, don't hook INT 15h yet
; Is this a valid function number?
cmp ah,[cImplementedFuncs]
jb short XCCheckHook
pop ax ; No, Un-preserve AX and return an error
xor ax,ax
mov bl,ERR_NOTIMPLEMENTED
jmp short XCExit
; Is INT 15h already hooked?
XCCheckHook:pushf
cli ; This is a critical section
cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
jne short XCCheckVD
; Try to claim all remaining extended memory.
call HookInt15
; Was a VDISK device found?
XCCheckVD: popff ; End of critical section
cmp [fVDISK],0
je short XCCallFunc
pop ax ; Yes, Un-preserve AX and return an error
xor ax,ax
mov bl,ERR_VDISKFOUND
xor dx,dx
jmp short XCExit
; Call the appropriate API function.
XCCallFunc: pop ax ; Restore AX
mov al,ah
xor ah,ah
shl ax,1
mov di,ax ; NOTE: DI cannot be used for parms!
call word ptr [ControlJumpTable+di]
; Restore the preserved registers.
XCExit: popff ; NOTE: Flags must be restored immediately
pop es ; after the call to the API functions.
pop ds
pop di
pop si
pop cx
ret
XMMControl endp
;*--------------------------------------------------------------------------*
;* *
;* Get XMS Version Number - FUNCTION 00h *
;* *
;* Returns the XMS version number *
;* *
;* ARGS: None *
;* RETS: AX = XMS Version Number *
;* BX = Internal Driver Version Number *
;* DX = 1 if HMA exists, 0 if it doesn't *
;* REGS: AX, BX and DX are clobbered *
;* *
;* INTERNALLY REENTRANT *
;* *
;*--------------------------------------------------------------------------*
Version proc near
mov ax,XMSVersion
mov bx,HimemVersion
xor dh,dh
; Is Int 15h hooked?
cmp word ptr [PrevInt15][2],0 ; Is the segment non-zero?
jne short VHooked
mov dl,[fHMAMayExist] ; No, return the status at
ret ; init time.
VHooked: mov dl,[fHMAExists] ; Yes, return the real status
ret
Version endp
;*--------------------------------------------------------------------------*
;* *
;* HookInt15 - *
;* *
;* Insert the INT 15 hook *
;* *
;* ARGS: None *
;* RETS: None *
;* REGS: AX, BX, CS, DI, SI, and Flags are clobbered *
;* *
;* EXTERNALLY NON-REENTRANT *
;* Interrupts must be disabled before calling this function. *
;* *
;*--------------------------------------------------------------------------*
HookInt15 proc near
push es
; Has a VDISK device been installed?
call IsVDISKIn
cmp [fVDISK],0
je short HINoVD ; No, continue
pop es ; Yes, return without hooking
ret
HINoVD: mov ah,88h ; Is 64K of Extended memory around?
int 15h
sub ax,[MemCorr] ; 6300 Plus may have memory at FA0000h
cmp ax,64
jb short HIInitMemory ; Less than 64K free? Then no HMA.
mov [fHMAExists],1
HIInitMemory:
; Init the first handle to be one huge free block.
mov bx,[KiddValley]
mov [bx.Flags],FREEFLAG
mov [bx.Len],ax
mov [bx.Base],1024
cmp [fHMAExists],0
je short HICont
add [bx.Base],64
; See if any Compaq "Built In Memory" exists.
HICont: mov ax,[BIMBase]
or ax,ax
jz short HIHookEmHorns
mov cx,[BIMLength]
; Fill out the next handle entry.
add bx,size Handle
mov [bx.Flags],FREEFLAG
mov [bx.Len],cx
mov [bx.Base],ax
; Save the current INT 15 vector.
HIHookEmHorns:
les si,dword ptr pInt15Vector
; Exchange the old vector with the new one.
mov ax,offset Int15Handler
xchg ax,es:[si][0]
mov word ptr [PrevInt15][0],ax
mov ax,cs
xchg ax,es:[si][2]
mov word ptr [PrevInt15][2],ax
pop es
ret
HookInt15 endp
;*--------------------------------------------------------------------------*
;* *
;* IsVDISKIn - *
;* *
;* Looks for drivers which use the IBM VDISK method of allocating *
;* Extended Memory. XMS is incompatible with the VDISK method. *
;* *
;* ARGS: None *
;* RETS: None. Sets "fVDISK" accordingly *
;* REGS: AX, CX, SI, DI and Flags are clobbered *
;* *
;* INTERNALLY REENTRANT *
;* *
;*--------------------------------------------------------------------------*
pVDISK label dword
dw 00013h
dw 0FFFFh
szVDISK db 'VDISK'
IsVDISKIn proc near
; Look for "VDISK" starting at the 4th byte of extended memory.
call LocalEnableA20 ; Turn on A20
push ds
push es
; Set up the comparison.
lds si,cs:pVDISK
push cs
pop es
mov di,offset szVDISK
mov cx,5
cld
rep cmpsb ; Do the comparison
pop es ; Restore ES and DS
pop ds
jz short IVIFoundIt
mov [fVDISK],0 ; No VDISK device found
jmp short IVIExit
; "VDISK" was found.
IVIFoundIt: mov [fVDISK],1
IVIExit: call LocalDisableA20
ret ; Turn off A20
IsVDISKIn endp
;*--------------------------------------------------------------------------*
;* *
;* Int15Handler - *
;* *
;* Hooks Function 88h to return zero as the amount of extended *
;* memory available in the system. *
;* *
;* Hooks Function 87h and preserves the state of A20 across the *
;* block move. *
;* *
;* ARGS: AH = Function, AL = Subfunction *
;* RETS: AX = 0 (if AH == 88h) *
;* REGS: AX is clobbered *
;* *
;*--------------------------------------------------------------------------*
I15RegSave dw ?
Int15Handler proc far
; Is this a request for the amount of free extended memory?
cmp ah,88h
jne short I15HCont ; No, continue
xor ax,ax ; Yes, return zero
iret
; Is it a Block Move?
I15HCont: cmp ah,87h
jne short I15HNext ; No, continue
; Int 15h Block Move:
cli ; Make sure interrupts are off
; Store the A20 line's state.
pusha ; Preserve the registers
call IsA20On
mov cs:[I15RegSave],ax
popa ; Restore the registers
; Call the previous Int 15h handler.
pushf ; Simualate an interrupt
call cs:[PrevInt15]
pusha ; Preserve previous handler's return
; Was A20 on before?
cmp cs:[I15RegSave],0
je short I15HExit ; No, continue
mov ax,1
call cs:[A20Handler] ; Yes, turn A20 back on
I15HExit: popa ; Restore the previous handler's return
iret
; Continue down the Int 15h chain.
I15HNext: jmp cs:[PrevInt15]
Int15Handler endp
;*--------------------------------------------------------------------------*
;* *
;* RequestHMA - FUNCTION 01h *
;* *
;* Give caller control of the High Memory Area if it is available. *
;* *
;* ARGS: DX = HMA space requested in bytes *
;* RETS: AX = 1 if the HMA was reserved, 0 otherwise. BL = Error Code *
;* REGS: AX, BX and Flags clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
RequestHMA proc near
cli ; This is a non-reentrant function.
; Flags are restored after the return.
mov bl,ERR_HMAINUSE
cmp [fHMAInUse],1 ; Is the HMA already allocated?
je short RHRetErr
mov bl,ERR_HMANOTEXIST
cmp [fHMAExists],0 ; Is the HMA available?
je short RHRetErr
mov bl,ERR_HMAMINSIZE
cmp dx,[MinHMASize] ; Is this guy allowed in?
jb short RHRetErr
mov ax,1
mov [fHMAInUse],al ; Reserve the High Memory Area
xor bl,bl ; Clear the error code
ret
RHRetErr: xor ax,ax ; Return failure with error code in BL
ret
RequestHMA endp
;*--------------------------------------------------------------------------*
;* *
;* ReleaseHMA - FUNCTION 02h *
;* *
;* Caller is releasing control of the High Memory area *
;* *
;* ARGS: None *
;* RETS: AX = 1 if control is released, 0 otherwise. BL = Error Code *
;* REGS: AX, BX and Flags clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
ReleaseHMA proc near
cli ; This is a non-reentrant function
; Is the HMA currently in use?
mov al,[fHMAInUse]
or al,al
jz short RLHRetErr ; No, return error
; Release the HMA and return success.
mov [fHMAInUse],0
mov ax,1
xor bl,bl
ret
RLHRetErr: xor ax,ax
mov bl,ERR_HMANOTALLOCED
ret
ReleaseHMA endp
;*--------------------------------------------------------------------------*
;* *
;* GlobalEnableA20 - FUNCTION 03h *
;* *
;* Globally enable the A20 line *
;* *
;* ARGS: None *
;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
;* REGS: AX, BX and Flags clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
GlobalEnableA20 proc near
cli ; This is a non-reentrant function
; Is A20 already globally enabled?
cmp [fGlobalEnable],1
je short GEARet
; Attempt to enable the A20 line.
call LocalEnableA20
or ax,ax
jz short GEAA20Err
; Mark A20 as globally enabled.
mov [fGlobalEnable],1
; Return success.
GEARet: mov ax,1
xor bl,bl
ret
; Some A20 error occured.
GEAA20Err: mov bl,ERR_A20
xor ax,ax
ret
GlobalEnableA20 endp
;*--------------------------------------------------------------------------*
;* *
;* GlobalDisableA20 - FUNCTION 04h *
;* *
;* Globally disable the A20 line *
;* *
;* ARGS: None *
;* RETS: AX = 1 if the A20 line is disabled, 0 otherwise. BL = Error *
;* REGS: AX, BX and Flags are clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
GlobalDisableA20 proc near
cli ; This is a non-reentrant function
; Is A20 already globally disabled?
cmp [fGlobalEnable],0
je short GDARet
; Attempt to disable the A20 line.
call LocalDisableA20
or ax,ax
jz short GDAA20Err
; Mark A20 as globally disabled.
mov [fGlobalEnable],0
; Return success.
GDARet: mov ax,1
xor bl,bl
ret
; Some A20 error occured.
GDAA20Err: mov bl,ERR_A20
xor ax,ax
ret
GlobalDisableA20 endp
;*--------------------------------------------------------------------------*
;* *
;* LocalEnableA20 - FUNCTION 05h *
;* *
;* Locally enable the A20 line *
;* *
;* ARGS: None *
;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise. BL = Error *
;* REGS: AX, BX and Flags clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
LocalEnableA20 proc near
cli ; This is a non-reentrant function
cmp [fCanChangeA20],1 ; Can we change A20?
jne short LEARet ; No, don't touch A20
; Only actually enable A20 if the count is zero.
cmp [EnableCount],0
jne short LEAIncIt
; Attempt to enable the A20 line.
mov ax,1
call [A20Handler] ; Call machine-specific A20 handler
or ax,ax
jz short LEAA20Err
LEAIncIt: inc [EnableCount]
; Return success.
LEARet: mov ax,1
xor bl,bl
ret
; Some A20 error occurred.
LEAA20Err: mov bl,ERR_A20
xor ax,ax
ret
LocalEnableA20 endp
;*--------------------------------------------------------------------------*
;* *
;* LocalDisableA20 - FUNCTION 06h *
;* *
;* Locally disable the A20 line *
;* *
;* ARGS: None *
;* RETS: AX = 1 if the A20 line is disabled, 0 otherwise. BL = Error *
;* REGS: AX, BX and Flags are clobbered *
;* *
;* INTERNALLY NON-REENTRANT *
;* *
;*--------------------------------------------------------------------------*
LocalDisableA20 proc near
cli ; This is a non-reentrant function
cmp [fCanChangeA20],0 ; Can we change A20?
je short LDARet ; No, don't touch A20
; Make sure the count's not zero.
cmp [EnableCount],0
je short LDAA20Err
; Only actually disable if the count is one.
cmp [EnableCount],1
jne short LDADecIt
xor ax,ax
call [A20Handler] ; Call machine-specific A20 handler
or ax,ax
jz short LDAA20Err
LDADecIt: dec [EnableCount]
; Return success.
LDARet: mov ax,1
xor bl,bl
ret
; Some A20 error occurred.
LDAA20Err: mov bl,ERR_A20
xor ax,ax
ret
LocalDisableA20 endp
;*--------------------------------------------------------------------------*
;* *
;* IsA20On - FUNCTION 07h *
;* *
;* Returns the state of the A20 line *
;* *
;* ARGS: None *
;* RETS: AX = 1 if the A20 line is enabled, 0 otherwise *
;* REGS: AX, CX, DI, SI and Flags clobbered *
;* *
;* INTERNALLY REENTRANT *
;* *
;*--------------------------------------------------------------------------*
LowMemory label dword ; Set equal to 0000:0080
dw 00080h
dw 00000h
HighMemory label dword
dw 00090h ; Set equal to FFFF:0090
dw 0FFFFh
IsA20On proc near
push ds
push es
lds si,cs:LowMemory ; Compare the four words at 0000:0080