6666
6767;--- assembly time parameters
6868
69- VERSIONSTR equ < '3.39 ' >
70- DRIVER_VER equ 300h + 39
69+ VERSIONSTR equ < '3.40 ' >
70+ DRIVER_VER equ 300h + 40
7171INTERFACE_VER equ 300h
7272
7373ifndef NUMHANDLES
7474NUMHANDLES equ 48 ;std 48, default number of handles
7575endif
7676MAXHANDLES equ 128 ;std 128, max number of handles
7777ALLOWDISABLEA20 equ 1 ;std 1, 1=allow to disable A20
78- BLOCKSIZE equ 2000h ;std 2000h, block size moved to/from ext. memory
79- USEUNREAL equ 1 ;std 1, 1=use "unreal" mode for EMB copy
78+ BLOCKSIZE equ 2000h ;std 2000h, block size moved to/from ext. memory (max 16-bits!)
79+ ifndef USEUNREAL
80+ USEUNREAL equ 2 ;std 2, 0=use pmode; 1=set/reset "unreal" mode; 2=set unreal if GPF occurs
81+ endif
82+ DISABLEIRQS equ USEUNREAL ne 2 ;0=don't disable interrupts during block move
8083PREF66LGDT equ 0 ;std 0, 1=use 66h prefix for LGDT
8184?LOG equ 0 ;std 0, 1=enable /LOG option
8285?TESTMEM equ 0 ;std 0, 1=enable /TESTMEM:ON|OFF option
8386ifndef ?ALTSTR AT
8487?ALTSTR AT equ 0 ;std 0, 1=use alternate strategie for (re)alloc emb
8588endif
89+ ifndef ?NMIOPT
90+ ?NMIOPT equ 0 ;std 0, 1=support /NMI cmdline option
91+ endif
8692?MERGE0HDL equ 1 ;std 0, 1=try to merge even if handle to free has size 0
8793?ALLOCDX0 equ 1 ;std 1, 1=return DX=0 if alloc fails
8894;--- change for v3.39: std now 1
@@ -160,6 +166,30 @@ ifdef _DEBUG
160166endif
161167 endm
162168
169+ @NMI_OFF macro savereg
170+ if ?NMIOPT
171+ ifnb <savereg>
172+ push savereg
173+ endif
174+ call nmi_off
175+ ifnb <savereg>
176+ pop savereg
177+ endif
178+ endif
179+ endm
180+
181+ @NMI_ON macro savereg
182+ if ?NMIOPT
183+ ifnb <savereg>
184+ push savereg
185+ endif
186+ call nmi_on
187+ ifnb <savereg>
188+ pop savereg
189+ endif
190+ endif
191+ endm
192+
163193@display macro value
164194 echo value
165195 endm
@@ -313,6 +343,9 @@ szX DB '/X', 00H
313343szMETHOD DB '/METHOD:' , 00H
314344szMAX DB '/MAX=' , 00H
315345szMaximum DB 'Maximum XMS: %luK' , 0aH , 00H
346+ if ?NMIOPT
347+ szNMI DB '/NMI' , 00H
348+ endif
316349szHMAMIN DB '/HMAMIN=' , 00H
317350szMinimum DB 'Minimum HMA that has to be requested: %uK' , 0aH , 00H
318351szHMAMAX DB 'HimemX: HMAMIN must be <= 63, corrected' , 0aH , 00H
@@ -384,6 +417,9 @@ if ?TESTMEM
384417 db " /TESTMEM:ON|OFF Performs or skips an extended memory test (def: OFF)" , 10
385418endif
386419 db " /VERBOSE Gives extra information" , 10
420+ if ?NMIOPT
421+ db " /NMI Make HimemX NMI aware" , 10
422+ endif
387423 db " /NOABOVE16 Do not use INT 15h function E801h to detect >64M" , 10
388424 db " /X Do not use INT 15h function E820h to detect >64M" , 10
389425 db " /X2MAX32 Limit XMS 2.0 free/avail. memory report to 32M-1K" , 10
@@ -560,16 +596,31 @@ exit_set_reset_carry:
560596
561597do_move:
562598 pushf
599+ @NMI_OFF ax
563600 call test_a20
564601 jz isdisabled
565602 call cs : [ old_int15 ]
603+ @NMI_ON ax
566604 call enable_a20 ; preserves flags
567605 jmp exit_set_reset_carry
568606isdisabled:
569607 call cs : [ old_int15 ]
608+ @NMI_ON ax
570609 call disable_a20 ; preserves flags
571610 jmp exit_set_reset_carry
572611
612+ if ?NMIOPT
613+ nmi_off::
614+ mov al , 80h
615+ jmp @F
616+ nmi_on::
617+ mov al , 0
618+ @@:
619+ out 70h , al
620+ in al , 71h
621+ ret
622+ endif
623+
573624int15_handler endp
574625
575626;******************************************************************************
@@ -584,7 +635,6 @@ int2f_handler proc
584635 db 0EAh
585636old_int2f dd 0 ; old INT 2fh vector
586637
587-
588638@@maybe_my2f:
589639 cmp al , 00h ; is it "Installation Check"?
590640 je @@get_driver_installed
@@ -1298,8 +1348,15 @@ endif
12981348@@move_ok_to_start:
12991349 SMSW AX ; don't use priviledged "mov eax,cr0"!
13001350 test al , 1 ; are we already in PM?
1351+ if DISABLEIRQS eq 0
1352+ jnz copy_pm
1353+ call rmcopy ; no need to loop in this case
1354+ jmp @@xms_exit_copy
1355+ copy_pm:
1356+ else
13011357 mov bx , offset rmcopy ; no, switch to pm yourself
13021358 jz @F
1359+ endif
13031360 push ss ; set ES for int 15h, ah=87h call
13041361 pop es
13051362 mov bx , offset pmcopy ; yes, use INT 15h, ah=87h
@@ -1367,21 +1424,26 @@ endif
13671424; EDI = dst linear adress
13681425; ECX = length (hiword cleared)
13691426
1370- ; 2 strategies are implemented. The first does the move in protected-mode,
1371- ; the latter activates "unreal" mode and does the move there.
1372- ; After the last transfer "unreal" mode is exited. Interrupts occuring
1373- ; during the "interrupt window" will run in "unreal" mode as well, but
1374- ; this shouldn't hurt.
1427+ ; 3 strategies are implemented:
1428+ ; 1) the block copy is done in protected-mode
1429+ ; 2) the block copy is done in "unreal" mode, which is explicitely
1430+ ; enabled and disabled. After the last transfer "unreal" mode is exited.
1431+ ; Interrupts occuring during the "interrupt window" will run in "unreal"
1432+ ; mode as well, but this shouldn't hurt.
1433+ ; 3) An interrupt handler for INT 0Dh is set temporarily, then the copy op
1434+ ; starts, assuming "unreal" mode is active. If assumtion is wrong, an
1435+ ; exception will occur, and the interrupt handler will enable "unreal".
13751436
13761437rmcopy:
13771438
1378- ife USEUNREAL
1439+ if USEUNREAL eq 0
13791440
1441+ @NMI_OFF
13801442 pushf
13811443 cli ; no interrupts when doing protected mode
1382- if PREF66LGDT
1444+ if PREF66LGDT
13831445 db 66h ; load full 32bit base
1384- endif
1446+ endif
13851447 lgdt fword ptr cs : [ gdt32 ] ; load GDTR (use CS prefix here)
13861448 mov eax , cr0
13871449 inc ax ; set PE bit
@@ -1392,10 +1454,11 @@ endif
13921454 mov ds , dx
13931455 mov es , dx
13941456
1395- shr ecx , 2 ; get number of DWORDS to move
1396- rep movs @dword [ edi ],[ esi ]
1457+ ; shr ecx,2 ; get number of DWORDS to move
1458+ shr cx , 2 ; hiword(ecx) is 0
1459+ rep movsd [ edi ],[ esi ]
13971460 adc cx , cx
1398- rep movs @word [ edi ],[ esi ] ; move a trailing WORD
1461+ rep movsw [ edi ],[ esi ] ; move a trailing WORD
13991462
14001463 db 67h ; don't remove - some 80386s were buggy
14011464 nop ; don't remove - some 80386s were buggy
@@ -1410,20 +1473,20 @@ endif
14101473 clc
14111474 ret
14121475
1413- else
1476+ elseif USEUNREAL eq 1
14141477
1415- if 0
14161478 pushf
14171479 cli ; no interrupts during the block move
14181480 pushf
14191481 call set_ureal ; every time since the mode might have been
14201482 xor dx , dx ; exited by an interrupt routine.
14211483 mov ds , dx
14221484 mov es , dx
1423- shr ecx , 2 ; get number of DWORDS to move
1424- rep movs @dword [ edi ],[ esi ]
1485+ ; shr ecx,2 ; get number of DWORDS to move
1486+ shr cx , 2 ; hiword(ecx) is 0
1487+ rep movsd [ edi ],[ esi ]
14251488 adc cx , cx
1426- rep movs @word [ edi ],[ esi ] ; move a trailing WORD
1489+ rep movsw [ edi ],[ esi ] ; move a trailing WORD
14271490 db 67h ; don't remove - some 80386s were buggy
14281491 nop ; don't remove - some 80386s were buggy
14291492 popf
@@ -1437,9 +1500,10 @@ else
14371500set_ureal:
14381501 mov dx , data32sel
14391502reset_ureal:
1440- if PREF66LGDT
1503+ @NMI_OFF
1504+ if PREF66LGDT
14411505 db 66h ; load full 32bit base
1442- endif
1506+ endif
14431507 lgdt fword ptr cs : [ gdt32 ] ; load GDTR (use CS prefix here)
14441508 mov eax , cr0
14451509 inc ax ; set PE bit
@@ -1452,33 +1516,79 @@ endif
14521516 mov ds , dx
14531517 mov es , dx
14541518 mov cr0 , eax
1519+ @NMI_ON
14551520 ret
1521+
1522+ else ; USEUNREAL eq 2
1523+
1524+ mov ax , cs
1525+ shl eax , 16
1526+ if DISABLEIRQS eq 0 ;checks if interrupts may be ON
1527+ mov dx , offset myint0d_2 ; NO check for IRQ 5 in INT 0Dh
1528+ pushf
1529+ pop ax
1530+ test ah , 2 ; IF set?
1531+ jz ifdone ; no check if interrupts disabled
1532+ mov al , 0Bh
1533+ out 20h , al
1534+ jmp @F
1535+ @@:
1536+ in al , 20h ; get ISS
1537+ test al , 20h ; IRQ 5 in service?
1538+ jnz ifdone
1539+ mov dx , offset myint0d ; check for IRQ 5 in INT 0Dh
1540+ ifdone:
1541+ mov ax , dx
14561542 else
1457- ;--- set int 0dh, then just start to copy.
1458- ;--- if int 0dh is called, an exception occured, since IRQs are disabled.
1459- ;--- then set unreal mode inside int 0dh code.
1543+ mov ax , offset myint0d
1544+ endif
1545+
1546+ ;--- set int 0dh, then start copying.
1547+ ;--- if int 0dh is triggered, check PIC to see if it's an IRQ;
1548+ ;--- if no, it's an exception and unreal mode is activated.
1549+
14601550 xor dx , dx
1461- mov ax , cs
14621551 mov ds , dx
14631552 mov es , dx
1553+ if DISABLEIRQS
14641554 pushf
1465- shl eax , 16
1466- mov ax , offset myint0d
1467- shr ecx , 2 ; get number of DWORDS to move
14681555 cli
1556+ endif
1557+ shr ecx , 2 ; get number of DWORDS to move
14691558 xchg eax , ds : [ 13 * 4 ]
1470- rep movs @dword [ edi ],[ esi ]
1559+ rep movsd [ edi ],[ esi ]
14711560 adc cx , cx
1472- rep movs @word [ edi ],[ esi ] ; move a trailing WORD
1561+ rep movsw [ edi ],[ esi ] ; move a trailing WORD
14731562 db 67h ; don't remove - some 80386s were buggy
14741563 nop ; don't remove - some 80386s were buggy
14751564 mov ds : [ 13 * 4 ], eax ; restore int 0dh
1565+ if DISABLEIRQS
14761566 popf
1567+ endif
14771568 ret
14781569myint0d:
1570+ if DISABLEIRQS eq 0
1571+ push ax
1572+ ;--- if IRQs aren't disabled, check if an IRQ 5 is "in service";
1573+ ;--- if no, assume it's an exception;
1574+ ;--- this is the MS Himem way of doing things; however,
1575+ ;--- XMS block moves inside an IRQ 5 handler may not work then!
1576+ mov al , 0Bh
1577+ out 20h , al
1578+ jmp @F
1579+ @@:
1580+ in al , 20h
1581+ test al , 20h ;IRQ 5 in service?
1582+ pop ax
1583+ jz myint0d_2
1584+ push eax ;assume eax holds old int 0Dh vector
1585+ retf
1586+ myint0d_2:
1587+ endif
1588+ push eax
14791589 push ds
14801590 push es
1481- push eax
1591+ @NMI_OFF
14821592 lgdt fword ptr cs : [ gdt32 ] ; load GDTR (use CS prefix here)
14831593 mov eax , cr0
14841594 inc ax ; set PE bit
@@ -1490,15 +1600,14 @@ myint0d:
14901600 mov ds , dx
14911601 mov es , dx
14921602 mov cr0 , eax
1493- pop eax
1603+ @NMI_ON
14941604 pop es
14951605 pop ds
1606+ pop eax
14961607 iret
1497- endif
14981608
14991609endif
15001610
1501-
15021611;------------------------------------------------------------------------
15031612; cpu is in v86-mode, use int15, ah=87 to copy things around
15041613
@@ -3161,6 +3270,17 @@ no_numhandles:
31613270 mov _x_option , 1
31623271@@:
31633272
3273+ if ?NMIOPT
3274+ ;--- option /NMI
3275+ push offset szNMI
3276+ call _FindCommand
3277+ or ax , ax
3278+ jne @F
3279+ mov byte ptr [ nmi_off ], 0C3h
3280+ mov byte ptr [ nmi_on ], 0C3h
3281+ @@:
3282+ endif
3283+
31643284;--- option /METHOD
31653285 push offset szMETHOD
31663286 call _FindCommand
@@ -3431,7 +3551,6 @@ e820_done:
34313551 ret
34323552geti15mem endp
34333553
3434-
34353554;--- driver init. this proc should be last
34363555;--- since it initializes the handle table
34373556;--- ds:di = request_ptr
0 commit comments