From 2d04cacc5322951f187bb17e017c12920ac8ebe2 Mon Sep 17 00:00:00 2001 From: Mark Zbikowski Date: Thu, 25 Apr 2024 21:24:10 +0100 Subject: MZ is back! --- v4.0/src/DEV/XMA2EMS/DIAGS.ASM | 1909 ++++++++++++++++++++ v4.0/src/DEV/XMA2EMS/EMSINIT.INC | 886 ++++++++++ v4.0/src/DEV/XMA2EMS/EMS_US.MSG | 110 ++ v4.0/src/DEV/XMA2EMS/GENIOCTL.INC | 167 ++ v4.0/src/DEV/XMA2EMS/I13HOOK.INC | 449 +++++ v4.0/src/DEV/XMA2EMS/LIM40.INC | 1792 +++++++++++++++++++ v4.0/src/DEV/XMA2EMS/LIM40B.INC | 3468 +++++++++++++++++++++++++++++++++++++ v4.0/src/DEV/XMA2EMS/MAKEFILE | 24 + v4.0/src/DEV/XMA2EMS/PARMPARS.INC | 530 ++++++ v4.0/src/DEV/XMA2EMS/PS2_5060.INC | 735 ++++++++ v4.0/src/DEV/XMA2EMS/ROMSCAN.INC | 420 +++++ v4.0/src/DEV/XMA2EMS/XMA1DIAG.INC | 1870 ++++++++++++++++++++ v4.0/src/DEV/XMA2EMS/XMA2EMS.ASM | 2591 +++++++++++++++++++++++++++ v4.0/src/DEV/XMA2EMS/XMA2EMS.LC | 11 + v4.0/src/DEV/XMA2EMS/XMA2EMS.SKL | 39 + v4.0/src/DEV/XMA2EMS/XMA2EMSP.INC | 243 +++ 16 files changed, 15244 insertions(+) create mode 100644 v4.0/src/DEV/XMA2EMS/DIAGS.ASM create mode 100644 v4.0/src/DEV/XMA2EMS/EMSINIT.INC create mode 100644 v4.0/src/DEV/XMA2EMS/EMS_US.MSG create mode 100644 v4.0/src/DEV/XMA2EMS/GENIOCTL.INC create mode 100644 v4.0/src/DEV/XMA2EMS/I13HOOK.INC create mode 100644 v4.0/src/DEV/XMA2EMS/LIM40.INC create mode 100644 v4.0/src/DEV/XMA2EMS/LIM40B.INC create mode 100644 v4.0/src/DEV/XMA2EMS/MAKEFILE create mode 100644 v4.0/src/DEV/XMA2EMS/PARMPARS.INC create mode 100644 v4.0/src/DEV/XMA2EMS/PS2_5060.INC create mode 100644 v4.0/src/DEV/XMA2EMS/ROMSCAN.INC create mode 100644 v4.0/src/DEV/XMA2EMS/XMA1DIAG.INC create mode 100644 v4.0/src/DEV/XMA2EMS/XMA2EMS.ASM create mode 100644 v4.0/src/DEV/XMA2EMS/XMA2EMS.LC create mode 100644 v4.0/src/DEV/XMA2EMS/XMA2EMS.SKL create mode 100644 v4.0/src/DEV/XMA2EMS/XMA2EMSP.INC (limited to 'v4.0/src/DEV/XMA2EMS') diff --git a/v4.0/src/DEV/XMA2EMS/DIAGS.ASM b/v4.0/src/DEV/XMA2EMS/DIAGS.ASM new file mode 100644 index 0000000..6c52a1c --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/DIAGS.ASM @@ -0,0 +1,1909 @@ +;-----------------------------------------------------------------------; +; DATA THAT IS UNIQUE TO THE DIAGNOSTICS PORTION OF ; +; THE DEVICE DRIVER. THIS AREA WILL NOT REMAIN PRESENT ; +; AFTER INITIALIZATION. ; +;-----------------------------------------------------------------------; +INCLUDE EMS_US.MSG + +MEM_INST DB '1' +ADDR_MODEL_BYTE DD 0F000FFFEH ;ADDRESS IN BIOS OF MODEL BYTE +MODEL DB ? ;SAVE AREA FOR MODEL +TEST_ID DB ? ;SAVE AREA FOR CURRENT TEST ID +CTRLPARM DW ? ;SAVE AREA FOR CONTROL PARM +PAGE_UNDER_TEST DW 0 ;SAVE AREA FOR PAGE UNDER TEST +CUR_SAVE DW ? ;SAVE AREA FOR NEXT AVAILABLE LINE + ;FOR MESSAGES +ACTIVE_PAGE DB ? ;ACTIVE DISPLAY PAGE +TESTABLE_SEGMENTS DW ? + + +PAGE +;-----------------------------------------------------------------------; +; EQUATES THAT ARE UNIQUE TO THE DIAGNOSTICS PORTION OF ; +; THE DEVICE DRIVER. ; +;-----------------------------------------------------------------------; +BASE_REG EQU 31A0H +DMACAPT EQU 31A8H ;I/O ADDRESS OF DMA CAPTURE REG +BLK_ON EQU 11110111B ;MASK FOR ENABLING A BLOCK +BLK_OFF EQU 00001000B ;MASK FOR INHIBITING A BLOCK +VIRT_MODE EQU 00000010B ;MASK FOR VIRTUAL MODE +REAL_MODE EQU 11111101B ;MASK FOR REAL MODE +MAX_TASK_ID EQU 15 ;MAXIMIM TASK ID +ENABLE EQU 01H ;INDICATES THAT BLOCK SHOULD BE ENABLED +TABLEN EQU 1000H ;NUMBER OF ENTRIES IN XLAT TABLE +DMAREQ1 EQU 0009H ;I/O ADDRESS OF DMA CTRL 1 REQ REG +DMAREQ2 EQU 00D2H ;I/O ADDRESS OF DMA CTRL 2 REQ REG +DMAMODE1 EQU 000BH ;I/O ADDRESS OF DMA CTRL 1 MODE REG +DMAMODE2 EQU 00D6H ;I/O ADDRESS OF DMA CTRL 2 MODE REG +PC1 EQU 0FFH ;RESERVED BYTE FOR PC1 +PC_XT EQU 0FEH ;RESERVED BYTE FOR XT +XT_AQUARIUS EQU 0FBH ;RESERVED BYTE FOR XT-AQUARIUS +AT_NMI_REG EQU 70H ;AT NMI REG +AT_NMI_OFF EQU 80H ;AT NMI OFF MASK +AT_NMI_ON EQU 00H ;AT NMI ON MASK +AT_CHCHK_EN_REG EQU 61H ;AT CH CHK ENABLE REG +AT_CHCHK_REG EQU 61H ;AT CH CHK REG +AT_CHCHK_EN EQU 0F7H ;AT CH CHK ENABLE MASK +AT_CHCHK_DIS EQU 08H ;AT CH CHK DISABLE MASK +AT_CHCHK EQU 40H ;AT CH CHK MASK +XT_NMI_REG EQU 0A0H ;XT NMI REG +XT_NMI_OFF EQU 00H ;XT NMI OFF MASK +XT_NMI_ON EQU 80H ;XT NMI ON MASK +XT_CHCHK_EN_REG EQU 61H ;XT CH CHK ENABLE REG +XT_CHCHK_REG EQU 62H ;XT CH CHK REG +XT_CHCHK_EN EQU 0DFH ;XT CH CHK ENABLE MASK +XT_CHCHK_DIS EQU 20H ;XT CH CHK DISABLE MASK +XT_CHCHK EQU 40H ;XT CH CHK MASK +ONE_MEG EQU 16 ;CONSTANT FOR ONE MEG MEMORY CARD +TWO_MEG EQU 32 ;CONSTANT FOR TWO MEG MEMORY CARD +CR EQU 0DH ;CARRIAGE RETURN +LF EQU 0AH ;LINE FEED +PRES_TEST EQU 01 ;PRESENCE TEST ID +REG_TEST EQU 02 ;REG TEST ID +AUTO_INC EQU 03 ;AUTO INC TEST ID +XLAT_TABLE_TEST EQU 04 ;TT TEST ID +LOMEM_TEST EQU 05 ;ABOVE 640K TEST ID +DMA_CAPTURE EQU 06 ;DMA CAPTURE TEST ID +PAGE_TEST EQU 07 ;PAGE TEST ID +MEM_TEST EQU 10 ;MEMORY TEST ID + + +;------------------------------------------------------------------------; +; Diagnostics...on exit if ZF=0 then error ; +;------------------------------------------------------------------------; +DIAGS PROC + + MOV CS:TEST_ID,00H ;CLEAR TEST ID BYTE + MOV CS:CTRLPARM,0100H ;SAVE CONTROL PARM + CALL GETMOD ;FIND OUT WHICH PC THIS IS + CALL CUR_POS ;GET CURSOR READY FOR MESSAGES + CALL REGTST ;TEST XMA REGISTERS + JNE FOUND_ERROR ;JUMP IF ERROR + CALL INCTST + JNE FOUND_ERROR + CALL XLATST + JNE FOUND_ERROR + CALL LOMEMTST ;TEST FOR BELOW 640K + JNE FOUND_ERROR ;JUMP IF ERROR + CALL MEMARRAY ;TEST MEMORY ABOVE 640K + JNE FOUND_ERROR ;JUMP IF ERROR + CALL PAGETST + JNE FOUND_ERROR + CALL CAPTST ;TEST DMA CAPTURE + JNE FOUND_ERROR ;JUMP IF ERROR +FOUND_ERROR: + RET +DIAGS ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; PRESENCE TEST +; +; DESCRIPTION : This routine will determine if the XMA is in the system. +; It will also determine the amount of memory installed +; on the card in 1Meg increments (up to 4Meg). +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : PRESTST +; +; ENTRY : The assumption is that at least 1MB of memory is installed. +; CONDITIONS If the 2nd, 3rd or 4th MB of memory is installed then the +; TOTAL_XMA_PAGES, TOTAL_PAGES, FREE_PAGES and +; MEM_INST words are Revised accordingly. +; +; +; +; EXIT : (zero flag) = 0 indicates that the XMA is not installed. +; if (zero flag) <> 0 then +; TOTAL_XMA_PAGES, TOTAL_PAGES, FREE_PAGES and +; MEM_INST words are Revised accordingly. +; +; AX,BX,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +PRESTST PROC +; + MOV AL,PRES_TEST + MOV CS:TEST_ID,AL + +;SAVE CONTENTS OF MODE REG + MOV DX,MODE_REG + IN AL,DX + PUSH AX + +; TRANSLATE TABLE ADDRESS AND DATA REGISTERS +; + MOV AX,0AA55H ;DATA PATTERN (IN REAL MODE) + ;BE CERTAIN MODE REG GETS + ;REAL MODE + MOV DX,MODE_REG ;I/O TO MODE REG + OUT DX,AL ;WRITE PATTERN + MOV DX,TTPOINTER + 1 ;I/O TO TT POINTER (ODD ADDR) + XCHG AL,AH ;CHRG BUS WITH INVERSE PATTERN + OUT DX,AL ;WRITE IT + MOV DX,MODE_REG + IN AL,DX ;READ BACK MODE REG + XOR AL,AH + AND AL,0FH ;MASK OFF UNUSED BITS + ;ZERO FLAG = 0 IF ERROR +END_PRES: + POP AX + PUSHF ;SAVE FLAGS + MOV DX,MODE_REG + OUT DX,AL ;RESTORE MODE REG TO INITIAL STATE + POPF ;RESTORE FLAGS + RET ;BACK TO CALLER +; +PRESTST ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; SAVES CURSOR POSITION +; +; DESCRIPTION : This routine simply saves the cursor location +; in CS:CUR_SAVE. This cursor position +; should be used by the KB_OK routine to insure proper +; format of the screen. +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : CUR_POS +; +; ENTRY : +; CONDITIONS +; +; +; EXIT : new cursor position is saved in CS:CUR_SAVE +; +; All registers are preserved +; +;------------------------------------------------------------------------- +; +CUR_POS PROC +; + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS ;SAVE REGISTERS +; + PUSH CS + POP DS ;GET DS TO THIS CODE SEGMENT + ;MOVE CURSOR TO NEXT AVAILABLE LINE +;IF DOS +; MOV AH,9 ;DOS PRINT STRING +; MOV DX,OFFSET NEXT_LINE + 1 ;OFFSET OF NEXT LINE MSG +; INT 21H ;DISPLAY MESSAGE +;ELSE +; MOV BX,OFFSET NEXT_LINE ;GET OFFSET OF NEXT LINE MSG +; MOV AH,0 ;TELL DCP TO DISPLAY +; INT 82H ;DISPLAY MESSAGE +;ENDIF + ; rsh001 fix scroll problem + ; and remove IF DOS crap + ;READ CURRENT VIDEO PAGE ; rsh001 + MOV AH,15 ;READ CURRENT Video Page + INT 10H ;VIDEO CALL + MOV ACTIVE_PAGE,BH ;SAVE ACTIVE PAGE + + ;READ CURRENT CURSOR POSITION + MOV AH,3 ;READ CURRENT CURSOR POS + INT 10H ;VIDEO CALL + MOV CUR_SAVE,DX ;SAVE CURSOR POSITION + + ;RESTORE ALL REGISTERS + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX ;RESTORE ALL REGISTERS + + RET ;RETURN TO CALLER + +CUR_POS ENDP + + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; TEST FOR PRESENCE OF MORE THAN 1 MEGABYTE OF MEMORY +; +; DESCRIPTION : This routine will determine if the 2nd, 3rd or 4th MB is +; installed. Since there are no switches or other indicators +; to be tested, this test will make a "best guess" as to +; the presence of this memory. This test will roll a 0 +; and a 1 through the 1st word of the next Meg and if +; at least 1 bit is consistently good then it is assumed +; that the optional memory is installed. If successful +; then try next Meg. +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : TRY4MEG +; +; ENTRY : none +; CONDITIONS +; +; EXIT : +; +; AX,BX,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +TRY4MEG PROC + +;MEMORY TEST MUST RUN IN PAGE MODE +;BEFORE CARD IS PUT INTO PAGE MODE...MUST SET UP XLAT TABLE TO PASSOVER +;RESERVED MEMORY SPACES (IE.,BIOS, DISPLAY, DISTRIBUTED ROS, ETC) +; + CALL VIRT2REAL + + MOV DX,IDREG ;I/O TO ID REGISTER + MOV AL,0 ;ID = 0 + OUT DX,AL ;SWITCH TO ID = 0 +; + ;DISABLE NMI AND ENABLE I/O CHANNEL CHECK + MOV AL,CS:MODEL ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE TR2M1 ;IF NO THEN TRY FOR PC_XT + CMP AL,PC_XT ;IS IT AN XT? + JE TR2M1 ;IF NO THEN TRY FOR AQUARIUS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE TR2M1 ;IF NO THEN USE AT NMI REGS + ;USE PC-AT NMI REGISTER + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + ;USE PC1, XT, AQUARIUS REGISTERS +TR2M1: + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED +; + ;MAP FIRST 64K OF 2ND MEG INTO PC SPACE BEGINNING AT 512K +;***jnw MOV CX,3 ;LOOK FOR PRESENCE OF NEXT 3 MB IN 1MB STEPS + MOV CX,99*1024/16 ;***jnw ;LOOK FOR PRESENCE OF NEXT n MB IN 1MB STEPS + MOV AX,CS:PAGE_FRAME_STA ;SEGMENT AT PAGE FRAME +;***jnw MOV DX,256 ;BEGINNING AT 2ND MEG OF XMA + MOV DX,256+3 ;***jnw ;AT end of 16k + MOV BH,0 ;ASSIGNED TO TASK ID 0 + MOV BL,01H ;ENABLE THIS MEMORY +TR2M1A: + PUSH AX + PUSH BX + PUSH CX + PUSH DX +;***jnw MOV CX,16 ;16 * 4K = 64K BLOCK + MOV CX,1 ;***jnw ;1 * 4K = 4K BLOCK + CALL SETXLAT ;SET TRANSLATE TABLE +; + MOV AX,CS:PAGE_FRAME_STA + MOV DS,AX ;SET SEGMENT AND + MOV SI,0 ;OFFSET TO TEST + MOV BX,0000000000000001B ;ROLL 1 THROUGH WORD + MOV DX,1111111111111110B ;ROLL 0 THROUGH WORD + MOV CX,16 ;16 BITS TO TEST +TR2M2: + MOV [SI],BX ;WRITE ROLLING 1 PATTERN + LOCK MOV [SI+2],DX ;CHARGE BUS INVERSE PATTERN + LOCK MOV AX,[SI] ;READ BACK INITIAL PATTERN + AND AX,BX ;ISOLATE BIT UNDER TEST +;***jnw JZ TR2M3 ;IF ZERO TRY ANOTHER BIT + JZ quit ;IF ZERO quit ***jnw + MOV [SI],DX ;WRITE ROLLING 0 PATTERN + LOCK MOV [SI+2],BX ;CHARGE BUS INVERSE PATTERN + LOCK MOV AX,[SI] ;READ BACK INITIAL PATTERN + AND AX,BX ;ISOLATE BIT UNDER TEST + AND AX,BX ;ISOLATE BIT UNDER TEST +;***jnw JZ TR2M4 ;IF ZERO THEN FOUND GOOD BIT + Jnz quit ;IF nonzero then quit ***jnw +TR2M3: + ROL BX,1 ;ROLL 1 TO NEXT POSITION + ROL DX,1 ;ROLL 0 TO NEXT POSITION + LOOP TR2M2 ;REPEAT FOR 16 BITS + jmp tr2m4 ;all 16 bits passed test ***jnw +quit: ;***jnw +;AT THIS POINT THERE ARE NO GOOD BITS SO END SEARCH FOR NEXT MB + POP DX ;RECOVER THESES REGISTERS + POP CX + POP BX + POP AX + JMP TR2M5 ;EXIT +;AT THIS POINT WE KNOW THERE IS MEMORY IN THIS MEG THAT WAS JUST TESTED +TR2M4: +;***jnw ADD CS:MEM_INST,1 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:TOTAL_XMA_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:TOTAL_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:FREE_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG + ADD CS:TOTAL_XMA_PAGES,1 ;Add 16k ***jnw + ADD CS:TOTAL_PAGES,1 ;Add 16k ***jnw + ADD CS:FREE_PAGES,1 ;Add 16k ***jnw + POP DX ;RECOVER THESE REGISTERS + POP CX + POP BX + POP AX +;***jnw ADD DX,256 ;TRY NEXT MB + ADD DX,4 ;TRY NEXT 16k ***jnw + LOOP TR2M1A ;REPEAT LOOP +TR2M5: +;BEFORE NMI IS ENABLED, CLEAR PARITY CHECK LATCH ON XMA + MOV SI,0 + MOV AX,[SI] ;READ 1ST WORD OF THIS SEG + MOV [SI],AX ;WRITE BACK SAME WORD + ;THE WRITE WILL CLEAR PCHK LTCH +;PUT THE XMA CARD BACK INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG +;CLEAR I/O CHANNEL CHECK LATCHES AND ENABLE NMI + MOV AL,CS:MODEL ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE TR2M6 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE TR2M6 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE TR2M6 ;USE XT REGISTERS +;IF NONE OF THE ABOVE THEN... +;USE AT NMI REGISTER + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +;USE XT/AQUARIUS NMI REGISTER +TR2M6: + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +; + RET ;RETURN TO CALLER + +TRY4MEG ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; REGISTER TESTS +; +; DESCRIPTION : This routine will test the following subset +; of XMA registers: +; 31A0...8 bits +; 31A1...4 bits +; 31A6...4 bits +; 31A7...4 bits (BIT 1 IS HELD LOW TO DISABLE +; THE VIRTUAL MODE) +; +; The test is performed by writing and reading +; AA, 55, FF, 00 from each of the above locations. +; +; NOTE: Regs 31A6 and 31A7 should always return 0 in +; the high nibble. +; +; The remainding registers will be tested in +; subsequent routines. +; +; +; FUNCTION/ : To ensure integrity of XMA registers that will be used +; PURPOSE in subsequent routines. +; +; ENTRY POINT : REGTST +; +; ENTRY : none +; CONDITIONS +; +; EXIT : XMA registers are set to zero +; +; (zero flag) = 0 indicates an error +; (DX) failing register +; (AL) expected data XOR'ed with actual data +; +;------------------------------------------------------------------------- +; +REGTST PROC +; + MOV AL,REG_TEST + MOV CS:TEST_ID,AL + +;SAVE CONTENTS OF MODE REG + MOV DX,MODE_REG + IN AL,DX + PUSH AX + +; TRANSLATE TABLE ADDRESS AND DATA REGISTERS +; + MOV BX,0AA55H ;SET UP INITIAL DATA PATTERN + MOV AX,BX + MOV CX,BX + +R1: + MOV DX,BASE_REG ;FIRST REGISTER PAIR TO WRITE + + OUT DX,AX ;WRITE PATTERN TO REGS + ADD DX,6 ;POINT TO NEXT REG PAIR + XCHG AL,AH ;SETUP INVERSE PATTERN + AND AH,11111101B ;MASK OFF BIT 1 + OUT DX,AX ;BECAUSE AH -> 21B7 +R2: + SUB DX,6 ;POINT TO FIRST REGISTER PAIR + IN AX,DX ;READ REGISTER (21B1 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE OF 21B1 + JNE R_ERROR ;MISMATCH - GO TO ERROR ROUTINE + XCHG BH,BL ;NEXT PATTERN TO TEST + AND BX,0F0FH ;REGS RETURN 0 IN HI NIBBLE + ADD DX,6 ;POINT TO NEXT REGISTER PAIR + IN AX,DX ;READ IT (21B7 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0DFFH ;MASK OFF BIT 1 IN REG 21B7 + JNE R_ERROR ;MISMATCH - GO TO ERROR ROUTINE +; + CMP CH,CL ;LAST PASS ? + JE R_EXIT ;YES - THEN EXIT REG TEST +; + CMP CX,055AAH ;END OF AA55,55AA PATTERNS? + JNE R3 ; + MOV CX,000FFH ;SET UP NEXT VALUE TO WRITE + JMP R4 +R3: + CMP CX,00FFH ;END OF FF00,00FF PATTERNS? + JNE R4 ; + MOV CX,0 ;YES, THEN SET UP FOR LAST PASS +R4: + XCHG CL,CH ;SET UP INVERSE PATTERN + MOV AX,CX ;SAVE IT + MOV BX,CX ;SAVE IT +R5: + JMP R1 ;CONTINUE TILL ZERO PATTERN + +R_ERROR: +R_EXIT: + POP AX + MOV DX,MODE_REG + OUT DX,AL ;restore mode reg + RET +; +REGTST ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; MEMORY ARRAY TEST +; +; DESCRIPTION : This routine test all 1Meg (or 2Meg) of XMA memory +; through a 64K window in PC space beginning at PF:0 +; (where PF is the Page Frame Segment) +; This module looks at TOTAL_XMA_PAGES +; to determine the memory size to be tested. +; +; (i) write the Translate Table for the 1st 64K block +; of XMA memory to be mapped into PF:0 in PC space +; (ii) test PF:0 to PF:FFFF +; (iii) if good...write Translate Table to map next 64K block +; into PF:0 +; (iv) repeat 'till all XMA memory is tested +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : MEMARRAY +; +; ENTRY : +; CONDITIONS +; +; EXIT : All SMAS memory is set to zero. +; +; (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if AX = 0 and ZF = 0 then parity error +; DS:SI point to failing location +; CS:PAGE_UNDER_TEST point failing 64k block +; +; AX,BX,CX,DX,DS,ES,SI,DI ARE DESTROYED +; +;------------------------------------------------------------------------- + +MEMARRAY PROC + + MOV AL,MEM_TEST + MOV CS:TEST_ID,AL + +;MEMORY TEST MUST RUN IN PAGE MODE + + CALL VIRT2REAL + +;INDICATE 0 KB OK + MOV DX,(640-64)/4 ;CODE FOR 640 KB OK + CALL KB_OK +;SETUP FOR TEST OF SMAS MEMORY ARRAY + MOV AX,CS:PAGE_FRAME_STA ;PAGE MEMORY FROM THIS SEGMENT + MOV ES,AX ;SET UP DEST SEG + MOV DS,AX ;SET UP SOURCE SEG + MOV BL,01H ;ENABLE THIS BLOCK OF MEMORY + MOV BH,0 ;USING ID 0 + MOV DX,(640)/4 ;STARTING BLK IN SMAS ARRAY + ;DETERMINE HOW MUCH MEMORY TO TEST + MOV CX,CS:TOTAL_XMA_PAGES ;GET NUMBER OF 16K PAGES + SHR CX,1 ;CONVERT TO NUMBER + SHR CX,1 ; OF 64K SEGMENTS + SUB CX,640/64 ;SUBTRACT OFF 1ST 640K MEMORY +;BEGIN TEST +MA1: + MOV CS:PAGE_UNDER_TEST,DX ;INDICATE WHICH 64K BLOCK + PUSH AX ;IS UNDER TEST + PUSH BX + PUSH CX + PUSH DX ;SAVE ALL REGISTERS +; + MOV CX,16 ;TEST 64K AT ONE TIME + ;16 x 4K = 64K + CALL SETXLAT ;SET UP XLAT TABLE + CALL STGTST ;TEST 64K OF STORAGE + JNZ MA2 ;WAS THERE AN ERROR + POP DX + POP CX + POP BX + POP AX ;RESTORE REGISTERS +; + PUSHF ;SAVE FLAGS FOR ADDITION + + CALL KB_OK ;INDICATE HOW MUCH + ;MEMORY HAS BEEN TESTED + + + ADD DX,16 ;POINT TO NEXT 64K BLOCK + POPF ;RESTORE FLAGS + LOOP MA1 ;LOOP FOR NEXT 64K + JMP MA3 ;EXIT WHEN COMPLETE +MA2: + POP DX + POP CX + POP BX ;BX IS POPPED TWICE + POP BX ;TO RESTORE STACK WHILE + ;MAINTAINING AX +MA3: + PUSH AX + PUSH DX + PUSHF ;SAVE THESE REGS...THEY CONTAIN + ;USEFULL ERROR INFO +;PUT THE SMAS CARD INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG + POPF + POP DX + POP AX ;RESTORE THESE REGS + RET +; +MEMARRAY ENDP + + + + +PAGE +;--------------------------------------------------------------------- +;--------------------------------------------------------------------- +; LO MEMORY TEST +; +; DESCRIPTION : This routine tests the first 256K or 512K +; of XMA memory depending on the starting +; position of the starting address jumper on +; the card. The memory that is used to +; fill conventional memory space is not tested +; it is tested during POST and may now contain +; parts of COMMAND.COM. +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : LOMEMTST +; +; ENTRY : +; CONDITIONS +; +; EXIT : All tested memory is set to zero +; +; (zero flag) = 0 if storage error +; (AX) = expected data XOR'ed with actual data +; if (AX)=0 and ZF=0 then parity error +; DS:SI point to failing location +; CS:PAGE_UNDER_TEST point to failing 64K block +; +; AX,BX,CX,DX,DI,SI,ES,DS ARE DESTROYED +; +;----------------------------------------------------------------------- +LOMEMTST PROC + + MOV AL,LOMEM_TEST + MOV CS:TEST_ID,AL + +;MEMORY TEST MUST RUN IN PAGE MODE + CALL VIRT2REAL + +;INDICATE 0 KB OK AT START OF TEST + MOV DX,0FFF0H ;code for initial 0 kb + CALL KB_OK + +;DETERMINE HOW MUCH MEMORY TO TEST + MOV AX,CS:START_FILL ;get starting fill segment + XCHG AH,AL + MOV CL,4 + SHR AX,CL ;convert to 64k block number + MOV CS:TESTABLE_SEGMENTS,AX ;save...this is number of 64k blocks + ;that can be tested without + ;destroying DOS +;SET UP FOR TEST OF XMA MEMORY + MOV AX,CS:PAGE_FRAME_STA ;test through page frame + MOV DS,AX ;set up ds + MOV ES,AX ;and es + MOV BL,01H ;enable this block of memory + MOV BH,0 ;using id=0 + XOR DX,DX ;start at block 0 in xma + MOV CX,640/64 ;loop counter is # 64k blocks in + ;conventional memory +LM1: + MOV CS:PAGE_UNDER_TEST,DX ;save page under test + PUSH AX + PUSH BX + PUSH CX + PUSH DX ;save these registers + + MOV CX,16 ;test 64k at one time + ;16 * 4k = 64k + CALL SETXLAT ;set translate table + CMP CS:TESTABLE_SEGMENTS,0 ;if this segment under test is used for + ;fill then read only + JG LM2 ;else do storage test + CALL READ_ONLY + JMP LM3 +LM2: + CALL STGTST +LM3: + JNZ LM4 ;jump if there was an error + POP DX + POP CX + POP BX + POP AX ;recover registers + + PUSHF ;save flags for addition + CALL KB_OK + ;indicate kb ok + ADD DX,16 ;next 64k block + DEC CS:TESTABLE_SEGMENTS ;dec testable pages + POPF ;recover flags + LOOP LM1 ;repeat for next 64k block + JMP LM5 ;exit when complete +LM4: + POP DX ;recover these registers + POP CX + POP BX ;bx is popped twice to restore + POP BX ;satck while maintaining ax +LM5: + PUSH AX ;save these ... they contain + PUSH DX ;useful error information + PUSHF +;PUT CARD BACK TO REAL MODE + MOV DX,MODE_REG ;read mode reg + IN AL,DX + AND AL,REAL_MODE ;turn off virtual bit + OUT DX,AL ;write it to mode reg + POPF + POP DX + POP AX ;restore these registers + RET + + +READ_ONLY PROC ;INTERNAL PROC TO READ MEMORY WITHOUT DESTROYING CONTENTS + XOR SI,SI ;start of segment + XOR CX,CX ;test 64k + + LODSW ;just read each byte + XOR AX,AX ;and set zf=1 for return + RET ;back to caller +READ_ONLY ENDP + +LOMEMTST ENDP + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; PAGE TEST +; +; DESCRIPTION : This routine tests that the TASK ID register is +; actually paging in unique segments of memory. +; The test is performed through the page frame segment. +; The test assumes that the memory test has already +; completed successfully. The page test procedes as +; follows: +; (i) 6-64K blocks of XMA memory are mapped into a +; 64K segment of PC space (the page frame) +; These XMA blocks are from 640k to 1024k of XMA memory. +; (ii) Each of these blocks is assigned to a unique +; task ID ranging from 0 to 5. +; (iii) For each task ID, the page frame is filled with +; a pattern that is the same as the task ID. +; (iv) The page frame is then read for each task ID +; and compared with the expected data. +; +; FUNCTION/ : +; PURPOSE +; +; ENTRY POINT : PAGETST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : (zero flag) = 0 indicates an error +; (AL) expected data XOR'ed with actual data +; +; AX,BX,CX,DX,ES,DS,SI,DI ARE DESTROYED +;------------------------------------------------------------------------- +; +PAGETST PROC +; + MOV AL,PAGE_TEST + MOV CS:TEST_ID,AL +;MEMORY TEST MUST RUN IN PAGE MODE + CALL VIRT2REAL +;INITIALIZE TRANSLATE TABLE FOR THIS TEST + MOV AX,CS:PAGE_FRAME_STA ;SEMENT OF PAGE FRAME + MOV BL,01H ;ENABLE CODE + MOV BH,0 ;START WITH TASK ID = 0 + MOV DX,640/4 ;START WITH XMA BLOCK 160 + MOV CX,6 ;LOOP COUNT...6 TASK ID's + ;EACH TASK ID IS ASSIGNED 64K + ;FROM 640K TO 1024K +PT1: + PUSH AX + PUSH BX + PUSH CX + PUSH DX ;SAVE ALL REGISTERS +; + MOV CX,16 ;16-4K BLOCKS IN 64K + CALL SETXLAT ;SET TRANSLATE TABLE + POP DX + POP CX + POP BX + POP AX ;RECOVER ALL + INC BH ;POINT TO NEXT TASK ID + ADD DX,16 ;NEXT 64K IN XMA MEMORY + LOOP PT1 ;REPEAT FOR ALL TASK ID's +;FILL MEMORY WITH A UNIQUE PATTERN FOR EACH TASK ID + MOV CX,6 ;6 TASK ID's + MOV DX,IDREG ;READY FOR I/O TO TASK ID REG + MOV AL,0 ;START WITH ID = 0 +PT2: + PUSH AX ;SAVE ID NUMBER + PUSH CX ;SAVE ID COUNT + OUT DX,AL ;SWITCH TASK ID + MOV BX,CS:PAGE_FRAME_STA + MOV ES,BX ;SEGMENT TO 1ST 64K 0F ID + SUB DI,DI ;POINT TO 1ST LOCATION + XOR CX,CX ;WRITE ALL 64K LOCATIONS +PT2X: + STOSB + LOOP PT2X + POP CX ;RECOVER ID COUNT + POP AX ;RECOVER CURRENT ID + INC AL + LOOP PT2 ;REPEAT FOR ALL TASK ID's +;NOW CHECK THAT THERE ARE 16 UNIQUE PATTERNS IN MEMORY + MOV CX,6 ;USE 6 TASK ID's + MOV AH,0 ;START WITH ID = 0 +PT3: + MOV AL,AH ;GET TASK ID IN AL + PUSH AX + PUSH CX ;SAVE ID COUNT + OUT DX,AL ;SWITCH TASK ID + MOV BX,CS:PAGE_FRAME_STA + MOV DS,BX + MOV ES,BX ;SEGMENT AT 1ST 64K + SUB DI,DI ;POINT TO 1ST LOCATION + SUB SI,SI ;POINT TO 1ST LOCATION + XOR CX,CX ;READ ALL 64K LOCATIONS +PT3X: + LODSB + XOR AL,AH ;DATA AS EXPECTED ? + JNE PT4X ;NO - THEN EXIT + STOSB ;AL SHOULD CONTAIN 0...WRITE IT + LOOP PT3X + + POP CX ;RECOVER ID COUNT + POP AX + INC AH ;NEXT TASK ID + LOOP PT3 ;REPEAT FOR ALL TASK ID's + XOR AL,AL ;IF WE GOT THIS FAR THEN + ;NO ERRORS...SET ZF TO + ;INDICATE SUCCESS +PT4: + PUSH AX + PUSH DX + PUSHF ;SAVE THESE REGS...THEY CONTAIN + ;USEFULL ERROR INFO +;PUT THE SMAS CARD INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG +;MAKE SURE WE EXIT WHILE IN TASK ID=0 + MOV DX,IDREG + XOR AL,AL + OUT DX,AL + + POPF + POP DX + POP AX ;RESTORE THESE REGS + RET ;RETURN TO CALLER +PT4X: + POP CX ;ALTERNATE RETURN PATH + POP AX + JMP PT4 ;TO ADJUST STACK +; +PAGETST ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; DMA CAPTURE TEST +; +; DESCRIPTION : This routine is a test of the DMA capture logic. +; The test is as follows: +; (i) A bit is rolled through the second entry in the +; DMA cature register file. (The first entry is used +; for refresh on a PC-XT). +; (ii) A bit and address test is performed on the +; remainder of the register file(s). +; (iii) A test is made for the capture of both REQUEST and +; MODE registers of the DMA controller. +; (iv) DMA channel 0 is tested only on the PC-AT +; +; +; FUNCTION/ : To verify the functionality of the DMA capture logic. +; PURPOSE +; +; ENTRY POINT : CAPTST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : Each entry in the DMA capture register file is set to 0. +; +; (zero flag) = 0 indicates an error +; '31A8'X points to failing DMA capture reg +; (AL) expected data XOR'ed with actual data +; +; AX,BX,CX,DX,SI,DI ARE DESTROYED +;------------------------------------------------------------------------- +; +; +CAPTST PROC +; + MOV AL,DMA_CAPTURE + MOV CS:TEST_ID,AL +; +;ROLL A BIT THROUGH THE SECOND ENTRY IN THE DMA CAPTURE REGISTER FILE +; + MOV BL,01H ;SET UP INITIAL PATTERN + MOV BH,01H ;SET UP DMA CHANNEL 1 + MOV DI,DMACAPT ;SAVE FOR I/O TO DMA CAPTURE REG + MOV SI,DMAREQ1 ;SAVE FOR I/O TO DMA CTRL 1 REQ REG + MOV CX,4 ;ROLL 4 BIT POSITIONS +C1: + MOV DX,IDREG ;I/O TO ID REG + MOV AL,BL ;PATTERN TO WRITE + OUT DX,AX ;SETUP ID REG WITH DATA PATTERN + MOV DX,SI ;DMA CTRL 1 + MOV AL,BH ;CHANNEL 1 + OUT DX,AL ;SETUP DMA CH 1...CAPT ID IN 2nd ENTRY + MOV DX,DI ;DMA CAPTURE REG + OUT DX,AL ;POINT TO 2nd ENTRY + IN AL,DX ;READ IT + XOR AL,BL ;DATA READ AS EXPECTED ? + JNE CAPT_ERROR ;NO - THEN ERROR + SHL BL,1 ;SHIFT BIT TO NEXT POSITION + LOOP C1 ;REPEAT +; + MOV DI,DMAREQ2 ;SETUP FOR I/O TO DMA CTRL 2 REQ REG + MOV AL,05H ;DATA PATTERN TO CAPTURE + CALL CAPT_FILL ;FILL CAPTURE REGS WITH VALUE +; + MOV AH,05H ;SETUP INITIAL PATTERN + MOV BX,0F0AH ;OTHER PATTERNS TO USE +C2: + CALL CAPT_RMW + JNZ CAPT_ERROR ;ERROR - THEN EXIT + CMP AH,BL ;ZERO PATTERN ? + JE CAPT_EXIT ;EXIT IF YES + MOV AH,BL ;SET UP + MOV BL,BH ; NEXT + MOV BH,0 ; PATTERN + JMP C2 ;REPEAT + +;NOW REPEAT TEST FOR CATPURE OF DMA MODE REGISTERS + MOV SI,DMAMODE1 ;SETUP FOR I/O TO DMA CTRL 1 MODE REG + MOV DI,DMAMODE2 ;SETUP FOR I/O TO DMA CTRL 2 MODE REG + MOV AL,05H ;DATA PATTERN TO CAPTURE + CALL CAPT_FILL ;FILL CAPTURE REGS WITH VALUE +; + MOV AH,05H ;SETUP INITIAL PATTERN + MOV BX,0F0AH ;OTHER PATTERNS TO USE +C3: + CALL CAPT_RMW + JNZ CAPT_ERROR ;ERROR - THEN EXIT + CMP AH,BL ;ZERO PATTERN ? + JE CAPT_EXIT ;EXIT IF YES + MOV AH,BL ;SET UP + MOV BL,BH ; NEXT + MOV BH,0 ; PATTERN + JMP C3 ;REPEAT +CAPT_ERROR: +CAPT_EXIT: + RET + +CAPTST ENDP + + + +PAGE + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; FILL DMA CAPTURE REG +; +; DESCRIPTION : This routine will fill the entire DMA capture register +; file with the pattern that is passed in AL +; +; FUNCTION/ : See Description. +; PURPOSE +; +; ENTRY POINT : CAPT_FILL +; +; ENTRY : AL contains the value to be captured into +; CONDITIONS the register file. +; SI contains the address of DMA controller 1 +; DI contains the address of DMA controller 2 +; +; EXIT : Each entry in the DMA capture register file is set to +; the value specified in AL. +;------------------------------------------------------------------------- +; +CAPT_FILL PROC NEAR +; + MOV DX,IDREG + OUT DX,AL ;LOAD ID REG WITH PAT TO BE CAPTURED + MOV DX,DI ;GET ADDRESS OF CTRL 2 + MOV CX,3 ;REP FOR CHANNELS 7,6,5 +CF1: + MOV AL,CL ;CL CONTAINS WHICH DMA CHANNEL + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL + LOOP CF1 ;REPEAT +; + MOV DX,SI ;GET ADDRESS OF CTRL 1 + MOV CX,3 ;REP FOR CHANNELS 3,2,1 +CF2: + MOV AL,CL ;CL CONTAINS WHICH DMA CHANNEL + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL + LOOP CF2 ;REPEAT + ;DO CHANNEL 0 IF NOT MODEL PC1, XT, AQUARIUS + CMP CS:MODEL,PC1 ;IS THIS A PC1 ? + JE CF3 ;YES - THEN EXIT ELSE TRY PC_XT + CMP CS:MODEL,PC_XT ;IS THIS AN XT ? + JE CF3 ;YES - THEN EXIT ELSE TRY AQUARIUS + CMP CS:MODEL,XT_AQUARIUS ;IS THIS AN AQUARIUS? + JE CF3 ;YES - THEN EXIT ELSE FILL CH 0 CAPT + MOV AL,0 ;INDICATE CHANNEL 0 + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL +CF3: + RET ;RETURN TO CALLER +; +CAPT_FILL ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; READ-MODIFY-WRITE DMA CAPTURE REG +; +; DESCRIPTION : This routine will read the a DMA capture register +; and if the correct value is found will cause a capture +; of a new value. The next DMA capture reg is read and +; the process repeated. +; +; FUNCTION/ : See Description. +; PURPOSE +; +; ENTRY POINT : CAPT_RMW +; +; ENTRY : AH contains the value to be compared +; CONDITIONS BL contains the new value to be written +; SI contains the address of DMA controller 1 +; DI contains the address of DMA controller 2 +; +; EXIT : Each entry in the DMA capture register file is set to +; the value specified in BL. +; +; AL,CX,DX,ARE DESTROYED +;------------------------------------------------------------------------- +; +CAPT_RMW PROC NEAR +; + MOV CX,3 ;REP FOR CHANNELS 7,6,5 +RMW1: + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV AL,CL ;GET LOW BYTE OF COUNT + ADD AL,4 ;ADD 4 TO POINT TO DMA CAPTURE + CALL RMW + JNZ RMW4 ;EXIT IF ERROR + LOOP RMW1 ;REPEAT FOR CHANNEL 6,5 +; + MOV CX,3 ;REP FOR CHANNELS 3,2,1 + PUSH DI ;SAVE DMA CTRL 2 + MOV DI,SI ;GET DMA CTRL 1 INTO DI FOR PROC RMW +RMW2: + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV AL,CL ;GET LOW BYTE OF COUNT + CALL RMW + JNZ RMW3 ;EXIT IF ERROR + LOOP RMW2 ;REPEAT FOR DMA CHANNELS 2,1 + ;DO CHANNEL 0 IF NOT MODEL PC1, XT, AQUARIUS + CMP CS:MODEL,PC1 ;IS THIS A PC1 ? + JE RMW3 ;YES - THEN EXIT ELSE TEST FOR PC_XT + CMP CS:MODEL,PC_XT ;IS THIS AN XT ? + JE RMW3 ;YES - THEN EXIT ELSE TEST FOR AQUARIUS + CMP CS:MODEL,XT_AQUARIUS ;IS THIS AN AQUARIUS? + JE RMW3 ;YES - THEN EXIT ELSE TEST CH 0 + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV CL,0 ;INDICATE CHANNEL 0 + MOV AL,CL ;ALSO INTO AL + CALL RMW +RMW3: + POP DI ;RESTORE DI (ADDR OF DMA CTRL 2) +RMW4: + RET ;RETURN TO CALLER +; +CAPT_RMW ENDP +; +RMW PROC +; + OUT DX,AL ;SETUP TO READ FROM DMA CAPTURE REG + IN AL,DX ;READ IT + XOR AL,AH ;DATA AS EXPECTED ? + JNE RMW5 ;NO THEN EXIT + ;DATA WAS GOOD---NOW GET NEXT PATTERN INTO THIS CAPTURE REG + MOV DX,IDREG ;ADDRESS OF ID REG + MOV AL,BL ;NEW PATTERN TO WRITE + OUT DX,AL ;WRITE IT TO ID REG + MOV DX,DI ;ADDRESS OF DMA CTRL 2 + MOV AL,CL ;DMA CHANNEL TO SET UP + OUT DX,AL ;SET UP DMA---THIS CAUSES CAPTURE OF ID +RMW5: + RET ;RETURN TO CALLER +; +RMW ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; INHIBIT A BLOCK OF MEMORY +; +; DESCRIPTION : This routine will set a block of SMAS memory with +; the code to enable or inhibit it. The user simply +; specifies the starting segment and length of the block in +; PC 'real' address space that is to be enabled/inhibited. +; The appropriate entries in the Translate Table are +; written so that this specified block in 'real' address +; is enabled or protected in all 16 possible TASK ID's. +; +; +; FUNCTION/ : To enable or inhibit SMAS memory in specified areas of +; PURPOSE PC 'real'address space (ie.,diplay buffer, BIOS, +; distributed ROS...) +; +; ENTRY POINT : INHIBLK +; +; ENTRY : (AX) starting segment in PC address space to be +; CONDITIONS protected/enabled. Must be on 4K boundary else +; this routine will round UP to next 4K block. +; +; (CX) number of 4K blocks to be protected +; +; (BL) 01 = ENABLE +; 00 = INHIBIT +; +; EXIT : specified entries in Translate Table are enabled or +; inhibited for all posible task ID's. +; +; AX,BH,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +INHIBLK PROC +; + ;ADJUST SI FOR TRANSLATE TABLE ENTRY + XCHG AL,AH ;ROTATE RIGHT BY 8 + XOR AH,AH ;CLEAR AH + ;AX IS NOW ADJUSTED FOR ENTRY INTO + ;XLAT TABLE FOR TASK ID=0 + PUSH AX ;SAVE IT + PUSH CX ;SAVE COUNT OF 4K BLOCKS +; + MOV SI,TTDATA ;ADDRESS OF TT DATA REG + MOV DI,AIDATA ;ADDRESS OF TT DATA WITH AUTO INC + XOR BH,BH ;BH IS TASK ID +INH1: + MOV DX,TTPOINTER ;ADDRESS OF TT POINTER + POP CX ;RESTORE COUNT + POP AX ;RESTORE TT ENTRY + PUSH AX ;SAVE BOTH + PUSH CX ; OF THEM + MOV AH,BH ;APPEND TASK ID TO TT POINTER + OUT DX,AX ;SET TT POINTER TO STARTING ENTRY +INH2: + MOV DX,SI ;TT DATA REG + IN AX,DX ;READ CURRENT ENTRY + MOV DX,DI ;ADDRESS OF TT DATA WITH AUTO INC + ;DETERMINE IF ENABLE OR INHIBIT BLOCK + CMP BL,ENABLE ;WANT TO ENABLE THIS BLOCK ? + JNE INH3 ;NO - THEN DISABLE IT + AND AH,BLK_ON ;MASK OFF INHIBIT BIT + JMP INH4 +INH3: + OR AH,BLK_OFF ;MASK ON INHIBIT BIT +INH4: + OUT DX,AX ;WRITE IT THEN INC TO NEXT TT ENTRY + LOOP INH2 ;REPEAT FOR EACH BLOCK OF 4K + INC BH ;NEXT TASK ID + CMP BH,MAX_TASK_ID ;COMPLETED FOR ALL TASK ID's ? + JBE INH1 ;NO - THEN LOOP TILL DONE +INHIBLK_EXIT: + POP CX + POP AX + RET +; +INHIBLK ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; STORAGE TEST +; +; DESCRIPTION : This routine performs a bit and address test on a +; 64K block of storage. +; +; (i) 55AA is written to each location. +; (ii) 55AA is read back +; (iii) if good, write AA55 and point to next location +; (iv) repeat step (iii) for all 64K locations +; (v) repeat steps (ii) to (iv) for AA55, FF00, 0101, 0000 +; (vi) check parity bits +; +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : STGTST +; +; ENTRY : (ES) storage segment to be tested +; CONDITIONS (DS) storage segment to be tested +; +; EXIT : (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if ax = 0 and zf = 0 then parity error +; DS:SI point to failing location +; +; AX,BX,CX,DX,DI,SI ARE DESTROYED +; +;------------------------------------------------------------------------- +; +STGTST PROC +; + CMP CS:WARM_START,'Y' ;is this a warm start? + JNE STG1A ;if no then do mem test + CALL CLEAR_MEM ;if yes then just clear memory + XOR AX,AX ;set zero flag + JMP STG6 ;exit + + + ;DISABLE NMI AND ENABLE I/O CHANNEL CHECK +STG1A: + MOV AL,CS:MODEL ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG1 ;IF NO THEN TRY FOR PC_XT + CMP AL,PC_XT ;IS IT AN XT? + JE STG1 ;IF NO THEN TRY FOR AQUARIUS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG1 ;IF NO THEN USE AT NMI REGS + ;USE PC-AT NMI REGISTER + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + ;USE PC1, XT, AQUARIUS REGISTERS +STG1: + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + + + + ;ROLL A BIT THROUGH THE FIRST WORD + SUB DI,DI ;FIRST LOCATION + MOV CX,16 ;ROLL 16 BITS + MOV AX,0001H ;FIRST PATTERN TO WRITE + MOV BX,AX ;SAVE IT +STG2: + MOV [DI],AX ;WRITE PATTERN + MOV [DI+2],0FFFFH ;CHARGE BUS + MOV AX,[DI] ;READ PATTERN + XOR AX,BX ;IS IT CORRECT ? + JNE STG_EXIT ;IF NO - THEN EXIT + SHL BX,1 ;SHIFT BIT + MOV AX,BX ;GET IT INTO AX + LOOP STG2 ;REPEAT +; + CLD ;FILL FORWARD + SUB DI,DI ;POINT TO FIRST LOCATION + MOV CX,8000H ;32K WORDS + MOV AX,55AAH ;INITIAL PATTERN TO WRITE + REP STOSW ;FILL ENTIRE SEGMENT +; + MOV BX,55AAH ;PATTERN TO LOOK FOR + MOV DX,0AA55H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; + MOV BX,0AA55H ;PATTERN TO LOOK FOR + MOV DX,0101H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; + MOV BX,0101H ;PATTERN TO LOOK FOR + MOV DX,0000H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; +; MOV BX,0000H ;PATTERN TO LOOK FOR +; MOV DX,0000H ;NEXT PATTERN TO WRITE +; CALL STG_CNT +; JNZ STG_EXIT ;EXIT IF ERROR +; + ;IF TEST REACHES THIS POINT THEN MEMORY IS GOOD + ;NEED TO CHECK PARITY BITS...IF PARITY ERROR EXISTS THEN + ;CAN ASSUME BAD PARITY BIT OR BAD PARITY GENERATOR +; + MOV AL,CS:MODEL ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG3 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE STG3 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG3 ;USE XT REGISTERS + ;IF NONE OF THE ABOVE THEN... + ;USE AT NMI REGISTER + MOV DX,AT_CHCHK_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + AND AL,AT_CHCHK ;IS CH CHK BIT ON ? + JZ STG4 ;IF NO - THEN EXIT + MOV AX,0 ;ELSE - CLEAR AX TO INDICATE + ;PARITY ERROR + JMP STG4 ;EXIT + ;USE XT/AQUARIUS NMI REGISTER +STG3: + MOV DX,XT_CHCHK_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + AND AL,XT_CHCHK ;IS CH CHK BIT ON ? + JZ STG4 ;IF NO - THEN EXIT + MOV AX,0 ;ELSE - CLEAR AX TO INDICATE + ;PARITY ERROR +STG4: +STG_EXIT: + PUSH AX ;SAVE THESE REGS + PUSH DX ;THEY CONTAIN + PUSH SI + PUSHF ;USEFUL ERROR INFORMATION + ;BEFORE NMI IS ENABLED, CLEAR PARITY CHECK LATCH ON XMA + MOV SI,0 + MOV AX,[SI] ;READ 1ST WORD OF THIS SEG + MOV [SI],AX ;WRITE BACK SAME WORD + ;THE WRITE WILL CLEAR PCHK LTCH + ;CLEAR I/O CHANNEL CHECK LATCHES AND ENABLE NMI + MOV AL,CS:MODEL ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG5 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE STG5 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG5 ;USE XT REGISTERS + ;IF NONE OF THE ABOVE THEN... + ;USE AT NMI REGISTER + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT + ;USE XT/AQUARIUS NMI REGISTER +STG5: + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +; + POPF + POP SI + POP DX + POP AX ;RESTORE REGS +STG6: + RET ;RETURN TO CALLER + + + +CLEAR_MEM PROC ;INTERNAL PROC TO CLEAR MEMORY + XOR DI,DI ;start of segment + XOR CX,CX ;clear entire segment + XOR AX,AX ;write zeroes + + STOSB ;just write + RET ;back to caller +CLEAR_MEM ENDP + + +STGTST ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; STORAGE TEST SUBROUTINE +; +; DESCRIPTION : This routine performs a bit and address test on a +; 64K block of storage. +; +; (i) a word is read and compared against the value in (BX) +; (ii) if good the value in (DX) is written into that location +; (iii) point to next location and repeat steps (i) to (ii) +; +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : STG_CNT +; +; ENTRY : (ES) storage segment to be tested +; CONDITIONS (DS) storage segment to be tested +; (BX) value to be compared +; (DX) new value to be written +; +; EXIT : (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if ax = 0 and zf = 0 then parity error +; DS:SI point to failing location +;------------------------------------------------------------------------- +; +STG_CNT PROC +; + MOV CX,8000H ;32K WORDS + SUB DI,DI ;FIRST LOCATION + MOV SI,DI ;FIRST LOCATION +SC1: + LODSW ;READ OLD WORD FROM STORAGE + XOR AX,BX ;DATA AS EXPECTED ? + JNE SC2 ;IF NO - THEN EXIT + MOV AX,DX ;GET NEW PATTERN + STOSW ;WRITE IT + LOOP SC1 ;REPEAT +SC2: + RET + +STG_CNT ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; PRINT MEMORY GOOD +; +; DESCRIPTION : This routine will print to the screen how much memory +; has been tested. +; +; The format will be: xxxx KB TESTED +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : KB_OK +; +; ENTRY : (DX) = 1/4 OF GOOD MEMORY + 64K IN KB +; CONDITIONS ex: if (DX) = 16 then +; (16 * 4) + 64 = 128KB is OK +; +; NOTE: if (DX) = FFF0 then 0 KB is OK +; +; +; EXIT : Message is displayed +; +; All registers are preserved +; +;------------------------------------------------------------------------- +; +KB_OK PROC +; + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS ;SAVE REGISTERS +; + PUSH CS + POP DS ;GET DS TO THIS CODE SEGMENT + ;CONVERT DX TO KILO BYTES + SHL DX,1 + SHL DX,1 ;MULTIPLY BY 4 + ADD DX,64 ;ADJUST BY 64 +; + MOV AX,DX ;GET NUMBER INTO AX + MOV BX,10 ;READY FOR DECIMAL CONVERT + MOV CX,4 ;OF 4 DIGITS +K1: + XOR DX,DX ;CLEAR HI WORD OF DIVIDEND + ;AX IS LOW WORD OF DIVIDEND + DIV BX ;DIVIDE BY 10 + OR DL,30H ;MAKE MODULO INTO ASCII + PUSH DX ;SAVE IT + LOOP K1 ;REPEAT FOR ALL DIGITS +; + XOR SI,SI ;CLEAR SI + MOV CX,4 +K2: + POP AX ;ASCII DIGIT GOES INTO AL + MOV BX,OFFSET MEM_OK + MOV CS:[BX+SI],AL ;BUILD ASCII MESSAGE + INC SI + LOOP K2 + ;MOVE THE CURSOR AND PRINT MESSAGE + MOV DX,CUR_SAVE + MOV BH,ACTIVE_PAGE + MOV AH,2 ;SET CURSOR +IF DOS + INT 10H ;BIOS VIDEO CALL SET CURSOR + MOV AH,9 ;DOS PRINT STRING + MOV DX,OFFSET SIZE_MSG1 + 1 ;OFFSET OF MEM_OK MSG + INT 21H ;DISPLAY MESSAGE +ELSE + INT 85H ;SET CURSOR POSITION + + MOV BX,OFFSET SIZE_MSG1 ;GET OFFSET OF MEM_OK MSG + MOV AX,0905H ;MAGENTA MESSAGE + INT 82H ;DISPLAY MESSAGE +ENDIF + + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX ;RESTORE ALL REGISTERS + + RET ;RETURN TO CALLER + +KB_OK ENDP + + +PAGE +;-------------------------------------------------------------------- +;-------------------------------------------------------------------- +; GET MODEL BYTE +; +GETMOD PROC +;GET COPY OF MODEL BYTE INTO THIS SEGMENT +; + PUSH DS ;SAVE DS + LDS SI,ADDR_MODEL_BYTE + MOV AL,[SI] ;GET IT INTO AL + MOV CS:MODEL,AL ;SAVE IT IN THIS SEGMENT + POP DS ;RESTORE DS + RET +; +GETMOD ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; SET TRANSLATE TABLE +; +; DESCRIPTION : This routine will write the Translate Table so that +; a specified block of PC 'real' address will be mapped +; to a specified block of SMAS physycal memory. Note that +; this routine will map only into CONTIGUOUS blocks of +; SMAS memory. PC memory is referenced by segments +; (must be on 4K boundaries) while SMAS memory is referenced +; by block number (each block is 4K). +; +; EXAMPLE: segment 4000 can be mapped to block 5 +; segment 4100 can be mapped to block 6 +; +; FUNCTION/ : To map PC 'real' addresses into SMAS physical memory. +; PURPOSE +; +; +; ENTRY POINT : SETXLAT +; +; ENTRY : (AX) starting segment in PC address space to be +; CONDITIONS mapped. Must be on 4K boundary else +; this routine will round UP to next 4K block. +; +; (CX) number of 4K blocks translated. +; +; (BH) task ID for this memory allocation +; +; (BL) 01 = ENABLE +; 00 = INHIBIT +; +; (DX) starting block number in SMAS memory +; +; +; EXIT : specified entries in Translate Table are enabled or +; inhibited for all posible task ID's. +; +; +; AX,CX,DX ARE DESTROYED +; +;------------------------------------------------------------------------- +; +SETXLAT PROC +; + ;ADJUST AX FOR TRANSLATE TABLE ENTRY + XCHG AL,AH ;ROTATE RIGHT BY 8 + MOV AH,BH ;TASK ID INTO BH + ;AX IS NOW ADJUSTED FOR ENTRY INTO + ;XLAT TABLE FOR TASK ID=(BH) + PUSH DX ;SAVE STARTING SMAS BLOCK NUMBER +; + MOV DX,TTPOINTER ;ADDRESS OF TT POINTER + OUT DX,AX ;SET TT POINTER TO STARTING ENTRY + POP AX ;GET STARTING BLOCK NUMBER INTO AX +; + MOV DX,AIDATA ;TT DATA REG WITH AUTO INC + ;DETERMINE IF ENABLE OR INHIBIT BLOCK + CMP BL,ENABLE ;WANT TO ENABLE THIS BLOCK ? + JE SETX1 ;YES - THEN SKIP THE DISABLE STEP + OR AH,BLK_OFF ;MASK ON INHIBIT BIT +SETX1: + OUT DX,AX ;WRITE IT THEN INC TO NEXT TT ENTRY + INC AX ;NEXT BLOCK OF SMAS MEMORY + LOOP SETX1 ;REPEAT FOR EACH BLOCK OF 4K +SETXLAT_EXIT: + RET +; +SETXLAT ENDP + + PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; AUTO-INCREMENT TEST +; +; DESCRIPTION : This routine will test the auto-increment of +; the Translate Table pointer. The test will procede +; in the following manner: +; (i) A basic check of the TT pointer reg is performed +; (ii) The TT pointer is initialized to '00'H +; (iii) The auto increment data reg is written +; (iv) The TT pointer is read and checked for increment +; (v) Repeat until TT pointer wraps from 'FFF'H to '000'H +; (vi) Repeat test for auto-increment for read of data reg +; +; FUNCTION/ : To ensure that the Translate Table pointer can auto +; PURPOSE increment when 31A5 is written or read. +; +; ENTRY POINT : INCTST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : +; (zero flag) = 0 indicates an error +; (DX) failing register (ie.,TT pointer reg) +; (AX) expected data XOR'ed with actual data +;------------------------------------------------------------------------- +; +; +INCTST PROC +; + MOV AL,AUTO_INC + MOV CS:TEST_ID,AL +; +;PERFORM SIMPLE TEST OF TTPOINTER REG +; + MOV BX,0AA55H ;SET UP PATTERN TO WRITE + MOV AX,BX + MOV DX,TTPOINTER ;I/O TO TTPOINTER REG + MOV SI,TTDATA ;SAVE FOR I/O TO TTDATA + OUT DX,AX ;WRITE THE REGISTER + XCHG DX,SI ;I/O TO TTDATA REG + XCHG AH,AL ;INVERSE PATTERN + OUT DX,AX ;CHARGE BUS WITH OPPOSITE PATTERN + XCHG DX,SI ;I/O TO TTPOINTER REG + IN AX,DX ;READ TTPOINTER REG + XOR AX,BX ;READ AS EXPECTED + AND AX,0FFFH ;MASK OFF HI NIBBLE (INVALID) + JNE INC_ERROR ;NO - THEN EXIT +; +;CONTINUE WITH AUTO-INC TEST +; + MOV DI,2 ;2 PASSES...1 WRITE , 1 READ +AI1: + MOV SI,AIDATA ;SAVE FOR I/O TO TTDATA WITH AUTO-INC +AI2: + MOV CX,1000H ;TTPOINTER RANGE 0 -> FFF + MOV BX,0001H ;INITIAL COMPARE VALUE + MOV AX,0 ;SET TTPONTER TO ZERO + OUT DX,AX ;TTPOINTER IS INITIALIZED TO ZERO +AI2X: + XCHG DX,SI ;I/O TO TTDATA WITH AUTO-INC +; +;DETERMINE IF WRITE OR READ TEST +; + CMP DI,2 ;DOING A AUTO-INC WRITE TEST ? + JNE AI3 ;NO - THEN MUST BE AUTO-INC READ TEST + OUT DX,AX ;WRITE TO AUTO-INC DATA REG + JMP AI4 ;CONTINUE WITH TEST +AI3: + IN AX,DX ;READ FROM AUTO-INC DATA REG +AI4: + XCHG DX,SI ;I/O TO TTPOINTER REG + IN AX,DX ;READ TTPOINTER (31A1 -> AH) + XOR AX,BX ;DATA AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE (INVALID) + JNE INC_ERROR ;NO - GO TO ERROR + INC BX ;NEXT VALUE TO LOOK FOR + LOOP AI2X ;CONTINUE TIL ALL VALUES ARE TESTED +; + DEC DI + CMP DI,0 ;COMPLETE WITH WRITE AND READ TEST ? + JE INC_EXIT ;YES - THEN EXIT + JMP AI1 ;NO - THEN CONTINUE WITH READ TEST +; +INC_ERROR: +INC_EXIT: RET +; +INCTST ENDP + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; TRANSLATE TABLE TEST +; +; DESCRIPTION : This routine performs a write/read storage test +; on the Translate Table. The test is as follows: +; (i) A bit is rolled through the first word of the TT +; (ii) A bit and address test is performed on the +; remainder of the TT. +; +; FUNCTION/ : To verify the integrity of the Translate Table. +; PURPOSE +; +; ENTRY POINT : XLATST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : Entire Translate Table is left with FFF (passover code) +; +; (zero flag) = 0 indicates an error +; (DX) failing register (TT data register) +; (AX) expected data XOR'ed with actual data +; (31A0) address in TT of failure +;------------------------------------------------------------------------- +; +XLATST PROC +; + MOV AL,XLAT_TABLE_TEST + MOV CS:TEST_ID,AL +; +;ROLL A BIT THROUGH THE FIRST BYTE +; + MOV BX,0001H ;SET UP INITIAL PATTERN + MOV SI,TTDATA ;SAVE FOR I/O TO DATA REG + MOV DX,TTPOINTER ;I/O TO TTPOINTER REG + MOV CX,12 ;ROLL 12 BIT POSITIONS + XOR AX,AX ;CLEAR AX (WRITE TO 1st TT LOCATION) + OUT DX,AX ;SET TT POINTER + XCHG DX,SI ;READY FOR I/O TO TTDATA REG +X1: + MOV AX,BX ;GET BIT PATTERN + OUT DX,AX ;WRITE BIT PATTERN TO TT + XCHG DX,SI ;READY FOR I/O TO TTPOINTER REG + XOR AX,AX ;CLEAR AX + OUT DX,AX ;CHARGE BUS WITH 0000 PATTERN + XCHG DX,SI ;READY FOR I/O TO TTDATA REG + IN AX,DX ;READ TT (31A1 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE (INVALID) + JNE XLA_ERROR ;NO - THEN EXIT + SHL BX,1 ;SHIFT BIT TO NEXT POSITION + LOOP X1 +; +;CONTINUE REMAINDER OF TRANSLATE TABLE +; + MOV DX,AIDATA +; + XCHG DX,SI ;READY FOR I/O TO TTPOINTER + XOR AX,AX ;CLEAR AX + OUT DX,AX ;TTPOINTER AT 1st LOCATION +; + XCHG DX,SI ;READY FOR I/O TO TT DATA W/AUTO-INC + MOV AX,0AA55H ;INITIAL DATA PATTERN + MOV CX,TABLEN ;NUMBER OF TT ENTRIES +X2: + OUT DX,AX ;SETUP INVERSE PATTERN + LOOP X2 ;FILL ENTIRE XLATE TABLE +; + MOV SI,TTDATA ;ADDRESS OF TTDATA WITHOUT INC. + MOV BX,AX ;SAVE VALUE FOR COMPARE + MOV DI,055AAH ;NEXT PATTERN TO WRITE +X3: + MOV CX,TABLEN ;NUMBER OF TT ENTRIES +X4: + XCHG DX,SI ;GET IT INTO DX...SI GETS AUTO-INC + IN AX,DX ;READ TABLE ENTRY (HI BYTE -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF HI NIBBLE (INVALID) + JNE XLA_ERROR ;NO - THE EXIT + XCHG DX,SI ;GET TTDATA WITH AUTO-INC + MOV AX,DI ;RECOVER NEXT PATTERN TO WRITE + OUT DX,AX ;WRITE IT THEN INCREMENT + LOOP X4 ;REPEAT TILL TABLE FILLED + + +; + CMP DI,0FFFFH ;LAST PASS ? + JE XLA_EXIT ;YES - THEN EXIT REG TEST +; + XCHG BX,DI ;BX GETS NEXT PATTERN TO TEST +; + CMP BX,055AAH ;LAST PASS FOR AA55,55AA PATTERN? + JNE X5 ;NO + MOV DI,0FF00H ;YES- PREPARE TO WRITE NEW PATTERN + JMP X3 ;DO IT +X5: + CMP BX,0FF00H ;READY TO READ 0FF00 PATTERN + JNE X6 ;NO + MOV DI,00FFH ;YES- PREPARE TO WRITE NEW PATTERN + JMP X3 ;DO IT +X6: + MOV DI,0FFFFH ;PREPARE TO SET ALL OF TT INACTIVE + JMP X3 ;DO IT +; +XLA_ERROR: +XLA_EXIT: RET +; +XLATST ENDP diff --git a/v4.0/src/DEV/XMA2EMS/EMSINIT.INC b/v4.0/src/DEV/XMA2EMS/EMSINIT.INC new file mode 100644 index 0000000..4c2213e --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/EMSINIT.INC @@ -0,0 +1,886 @@ + +;------------------------------------------------------------------------; +; Initialization... ; +;------------------------------------------------------------------------; + +RESR_EXT_PGS DW 0 ;Ext mem reserved here after EMS taken ;an002; dms; + +MACH_MODEL_PTR DD 0F000FFFEh ;Byte in upper BIOS that indicates @RH1 +MODEL_BYTE DB (?) ; which system you are on. @RH1 +PC1 EQU 0FFh ;Values returned for: PC 1 @RH1 +PC_XT EQU 0FEh ; PC XT @RH1 +XT_AQUARIUS EQU 0FBH ; PC Aquarius @RH1 +PC_AT EQU 0FCh ; PC AT type - AT, PS/2 models @RH1 + ; 50 and 60, etc. +PS2MODEL80 EQU 0F8h ; 386 processor - PS/2 model 80 @RH1 + +INT15_SEC_MOD EQU ES:BYTE PTR [BX+3] ;Secondary model byte @RH2 +SEC_MOD_TB EQU 4 ; PS/2 Model 50 @RH2 +SEC_MOD_RR EQU 5 ; PS/2 Model 60 @RH2 + +START_BACMEM_SEG DW 0 ;Starting and ending segment addrs +END_BACMEM_SEG DW 0 ; of memory backed by the XMA card + +INIT_ERR DW ? ;Initialization error flag @RH4 +NO_ERROR EQU 0 ; @RH4 +ERROR EQU 1 ; @RH4 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Device driver IOCTL call declares ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +EMULATOR_DD_NAME DB '386XMAEM',0 ;Device driver names for the Emulator +XMAAVIRT_DD_NAME DB 'INDXMAII',0 ; and WSP's XMA/A init code +DD_FILE_HANDLE DW ? ;File handle from opening either DD + +REQ_PACKET_STRUC STRUC ;Generic IOCTL parameter packet +PACKET_LEN DW 4 ;Packet length (in bytes) +PACKET_FCN DW 0 ;DD defined function number +PACKET_WORD DW 0 ;Data area +REQ_PACKET_STRUC ENDS + +REQ_PACKET REQ_PACKET_STRUC <> ; + + +INIT PROC + + PUSH CS + POP DS ;Get this segment into CS + + MOV DX,SS ;save stack segment + MOV CX,SP ;save stack pointer + CLI ;ints off during swap + MOV AX,CS ;move cs to ss + MOV SS,AX ;through ax + MOV SP,OFFSET TOP_OF_STACK ;sp to end of code + STI ;ints back on + PUSH DX ;save old ss on new stack + PUSH CX ;save old sp on new stack + + + MOV DX,OFFSET WELCOME_MSG ;Print title and copy-right + MOV AH,9 ; + INT 21H + + push ax ;save affected regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push si ; ;an000; dms; + push di ; ;an000; dms; + push ds ; ;an000; dms; + + CALL GET_PARMS ;Get the user parameters + + pop ds ;restore affected regs ;an000; dms; + pop di ; ;an000; dms; + pop si ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + JE PARMS_OK + PUSH CS + POP DS + MOV DX,OFFSET PARM_ERR_MSG ;Print message indicating + MOV AH,9 ; parameter error using + INT 21H ; DOS function call + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver + MOV AH,9 ; has not been installed + INT 21H ; + JMP GENERAL_FAILURE ;indicate general failure +PARMS_OK: + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Does the system use the XMA Emulator? ³ + ;³ (PS/2 model 80 with 80386 processor) ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + PUSH DS ; @RH1 + LDS SI,MACH_MODEL_PTR ; DS:SI points to model descriptor @RH1 + MOV AL,DS:BYTE PTR [SI] ; byte (F000:FEEE) @RH1 + MOV MODEL_BYTE,AL ; @RH1 + POP DS ; @RH1 + + CMP MODEL_BYTE,PS2MODEL80 ;If the model byte is for a @RH7 + JE FIND_EMULATOR ; PS/2 model 80 @RH7 + JMP NOT_PS2MODEL80 ; then attempt to open the 80386 @RH7 +FIND_EMULATOR: ; XMA Emulator device driver @RH7 + MOV AX,3D00h ; (INDXMAEM.SYS) @RH7 + LEA DX,EMULATOR_DD_NAME ; @RH7 + INT 21h ;No carry means open successful @RH7 + JNC EMUL_INSTALLED ; and the DD is present @RH7 + PUSH CS ;Else open failed @RH7 + POP DS ;Print message indicating @RH7 + MOV DX,OFFSET NO_EMUL_MSG ; emulator not present @RH7 + MOV AH,9 ;dos prt string @RH7 + INT 21H ;write message @RH7 + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver @RH7 + MOV AH,9 ; has not been installed @RH7 + INT 21H ; @RH7 + JMP GENERAL_FAILURE ;indicate general failure @RH7 +EMUL_INSTALLED: ;Emulator is present @RH7 + MOV DD_FILE_HANDLE,AX ;Do IOCTL to find # of XMA blocks @RH7 + MOV BX,AX ;Emulator DD handle in BX @RH7 + MOV AX,440Ch ;Handle generic IOCTL fcn code @RH7 + XOR CH,CH ;CH = 0 means "unknown" @RH7 + MOV CL,60h ;CL = 40h means set device info @RH7 + PUSH CS ; = 60h means get device info @RH7 + POP DS ; @RH7 + LEA DX,REQ_PACKET ;DS:DX -> generic IOCTL packet @RH7 + INT 21h ;Issue the generic IOCTL @RH7 + JNC EMUL_VER_GOOD ;No carry means the right @RH7 + PUSH CS ; version of the Emulator was @RH7 + POP DS ; installed (can handle IOCTL) @RH7 + MOV DX,OFFSET WRONG_EMUL_MSG ;Otherwise print message @RH7 + MOV AH,9 ; indicating incorrect version @RH7 + INT 21H ; of the Emulator detected @RH7 + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver @RH7 + MOV AH,9 ; has not been installed @RH7 + INT 21H ; @RH7 + JMP GENERAL_FAILURE ;indicate general failure @RH7 +EMUL_VER_GOOD: + MOV AX,REQ_PACKET.PACKET_WORD ;Get the last available XMA block@RH7 + INC AX ; number from the emulator...add 1 @RH7 + XOR DX,DX ; to calc total XMA blocks and @RH7 + DIV BLOCKS_PER_PAGE ; convert it to EMS pages @RH7 + MOV TOTAL_SYS_PAGES,AX ;Set the number of total 16K pages @RH7 + MOV TOTAL_EMS_PAGES,AX ; (before and after mem backing) @RH7 + MOV FREE_PAGES,AX ; and the pages free for useage @RH7 + MOV START_BACMEM_SEG,0 ;Mark from 0-640K as taken to @RH7 + MOV END_BACMEM_SEG,0A000h ; back conventional memory and @RH7 + CALL BACK_CONV_MEM ; adjust TOTAL_EMS_PAGES @RH7 + MOV AX,3E00h ;Close the XMA Emulator device @RH7 + MOV BX,DD_FILE_HANDLE ; driver @RH7 + MOV MEMCARD_MODE,EMUL_VIRT ;Set flag for hardware used @RH7 + INT 21h ; @RH7 + JMP INT_67_INSTALL ;Install int 67 vector, end init @RH7 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +NOT_PS2MODEL80: ;³ Does the system use the XMA\A or XMO card? ³ + ;³ (PS/2 models 50 and 60) ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP MODEL_BYTE,PC_AT ;If the model byte is for an 'AT' @RH2 + JE MODEL_AT ; type (80286 processor), check @RH2 + JMP FAMILY_1_MACH ; the secondary model byte to @RH2 +MODEL_AT: ; see if it's a model that uses @RH2 + MOV AH,0C0h ; the XMA/A or XMO card @RH2 + INT 15h ; @RH2 + CMP INT15_SEC_MOD,SEC_MOD_TB; @RH2 + JNE NOT_PS2MODEL50 ; @RH2 + MOV NUM_OF_SLOTS,4 ; PS2/50 has 4 adapter slots @RH2 + JMP PS2_5060 ; Init for XMA/A and XMO @RH2 +NOT_PS2MODEL50: ; @RH2 + CMP INT15_SEC_MOD,SEC_MOD_RR;If 'AT' but not PS/2 50 or 60, @RH2 + JE IS_PS2MODEL60 ; then family 1 (uses XMA 1 card) @RH2 + JMP FAMILY_1_MACH ; @RH2 +IS_PS2MODEL60: + MOV NUM_OF_SLOTS,8 ;PS2/60 has 8 adapter slots @RH2 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +PS2_5060: ;³ Machine is a PS/2 Model 50 (TB) or 60 (RR). ³ + ;³ Check for the Workstation Program's XMA/A ³ + ;³ virtual mode device driver (INDXMAA.SYS). If ³ + ;³ present, use only that card in virtual mode. ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,3D00h ;Attempt to open WSP's XMA/A @RH6 + LEA DX,XMAAVIRT_DD_NAME ; virtual mode device driver @RH6 + INT 21h ;Carry means open failed and the @RH6 + JC PS2_5060_REAL ; DD is not present. Use XMA/A @RH6 + ; in real mode and XMO card. @RH6 +INDXMAA_INSTALLED: ;Else driver found. XMA/A virtual @RH6 + MOV DD_FILE_HANDLE,AX ;Do IOCTL to find # of XMA/A blks @RH6 + MOV BX,AX ;INDXMAA.SYS DD handle in BX @RH6 + MOV AX,440Ch ;Handle generic IOCTL fcn code @RH6 + XOR CH,CH ;CH = 0 means "unknown" @RH6 + MOV CL,60h ;CL = 40h means set device info @RH6 + PUSH CS ; = 60h means get device info @RH6 + POP DS ; @RH6 + LEA DX,REQ_PACKET ;DS:DX -> generic IOCTL packet @RH6 + INT 21h ;Issue the generic IOCTL @RH6 + JNC XMAA_VER_GOOD ;No carry means the right @RH6 + PUSH CS ; version of the XMAA DD was @RH6 + POP DS ; installed (can handle IOCTL) @RH6 + MOV DX,OFFSET WRONG_XMAA_MSG ;Otherwise print message @RH6 + MOV AH,9 ; indicating incorrect version @RH6 + INT 21H ; of the XMAA DD detected @RH6 + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver @RH6 + MOV AH,9 ; has not been installed @RH6 + INT 21H ; @RH6 + JMP GENERAL_FAILURE ;indicate general failure @RH6 +XMAA_VER_GOOD: + MOV AX,REQ_PACKET.PACKET_WORD ;Get the last available XMA/A blk@RH6 + INC AX ; number from the XMA/A DD...add 1 @RH6 + XOR DX,DX ; to calc total XMA/A blocks and @RH6 + DIV BLOCKS_PER_PAGE ; convert it to EMS pages @RH6 + MOV TOTAL_SYS_PAGES,AX ;Set the number of total 16K pages @RH6 + MOV TOTAL_EMS_PAGES,AX ; (before and after mem backing) @RH6 + MOV FREE_PAGES,AX ; and the pages free for useage @RH6 + MOV START_BACMEM_SEG,0 ;Mark from 0-640K as taken to @RH6 + MOV END_BACMEM_SEG,0A000h ; back conventional memory and @RH6 + CALL BACK_CONV_MEM ; adjust TOTAL_EMS_PAGES @RH6 + MOV AX,3E00h ;Close the XMA/A virtual mode @RH6 + MOV BX,DD_FILE_HANDLE ; device driver @RH6 + INT 21h ; @RH6 + MOV MEMCARD_MODE,XMAA_VIRT ;Set hardware flag to XMAA virtual @RH6 + JMP INT_67_INSTALL ;Install int 67 vector,end init @RH6 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +PS2_5060_REAL: ;³ PS/2 Model 50 or 60 without XMA/A virtual DD. ³ + ;³ Use XMA/A card in real mode (Bank ID reg ³ + ;³ not used) or XMO card. ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CALL INIT_MOD_50_60 ;Init for XMA/A and XMO @RH2 + CMP INIT_ERR,ERROR ;If no error then install the @RH2 + JE PS2_5060_ERROR ; int 67 vector, print msgs @RH2 + JMP INT_67_INSTALL ; @RH2 +PS2_5060_ERROR: + ;Else error in intialization @RH2 + PUSH CS ; + POP DS ; + MOV AH,9 ; Barf out 1st part of msg @RH2 + INT 21H ; set by subproc (DX = ptr) @RH2 + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver @RH2 + MOV AH,9 ; has not been installed @RH2 + INT 21H ; @RH2 + JMP GENERAL_FAILURE ;indicate general failure @RH2 + + +FAMILY_1_MACH: ;Family 1 machine (pre-PS/2) + mov rom_scan_type,family1 ; set flag for rom scan code - gga + MOV START_BACMEM_SEG,04000h ;Memory is backed from 256K to + MOV END_BACMEM_SEG,0A000h ; 640K on XMA 1 card + CALL PRESTST ;Insure XMA 1 card is present + JE XMA1_FOUND ;Zero flag = 1 means XMA 1 found + PUSH CS ;Else error..get this segment + POP DS ;into ds + MOV DX,OFFSET NOT_FOUND_MSG ;Print message for cannot + MOV AH,9 ; find adapter + INT 21H ;write message + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver + MOV AH,9 ; has not been installed + INT 21H ; + JMP GENERAL_FAILURE ;indicate general failure +XMA1_FOUND: + MOV MEMCARD_MODE,XMA1_VIRT ;Indicate an XMA 1 card present @RH2 + CALL TRY4MEG ;determine the size of the XMA memory card + + PUSH CS + POP DS + MOV DX,OFFSET DGS_START_MSG ;start of diagnostics message + MOV AH,9 ;dos prt string + INT 21H ;starting diagnostics message + CALL CUR_POS ;save cursor position for KB OK msg + + MOV DX,MODE_REG ;determine if this is a warm start + IN AL,DX ;read mode reg + AND AL,WARM_MASK ;isolate warm start bit + JZ DO_XMA1DIAG ;If off perform full XMA 1 diags + MOV CS:WARM_START,'Y' ;Else warm start..limited diags +DO_XMA1DIAG: + CALL XMA1DIAGS ;Perform XMA 1 diagnostics + JE XMA1_OK ;Zero flag set means all OK + PUSH CS ;Else error..get this segment + POP DS ;into ds + MOV DX,OFFSET XMA1_ERR_MSG ;'XMA001 Adapter error' + MOV AH,9 ;dos prt string + INT 21H ;write message + MOV DX,OFFSET NOT_INSTL_MSG ;Print that the EMS driver + MOV AH,9 ; has not been installed + INT 21H ; + JMP GENERAL_FAILURE ;indicate general failure +XMA1_OK: + PUSH CS ;get this segment + POP DS ;into ds + MOV DX,OFFSET DGS_END_MSG ;start of message + MOV AH,9 ;dos prt string + INT 21H ;write message + +;Set XMA in virtual mode to look like it was in real mode + CALL VIRT2REAL +;Mark pages used on XMA card to back conventional memory + CALL BACK_CONV_MEM + + +;Set up interrupt 67 vector +INT_67_INSTALL: +;------------------------ +; added by GGA +;------------------------ +;------------------------------------------------------------------- + call romscan ; just for grins + jc ROM_Scan_Fail ; error - prompt user to hit any key ;an000; dms; + jmp Skip_Pars ; continue load of XMA2EMS ;an000; dms; + +ROM_Scan_Fail: + + PUSH CS ;set up addressibility ;an000; dms; + POP DS ; ;an000; dms; + MOV DX,OFFSET Prompt_Msg ;Press any key to continue... ;an000; dms; + MOV AH,9 ;dos prt string ;an000; dms; + INT 21H ; + + mov ah,07h ;keyboard input without ECHO ;an000; dms; + int 21h ;wait until input ;an000; dms; + jmp General_Failure ; +;------------------------------------------------------------------- +skip_pars: +;------------------------ +; end of adds by GGA +;------------------------ + + CALL INIT_PAL ;Initialize the Page Allocation @RH8 + ; linked List RH8 + CALL STEAL_INT67 ; + + + + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Initialize the entries in the Page Allocation List ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV CX,TOTAL_SYS_PAGES + + +;write variables into message string + PUSH CS ;get this segment + POP ES ;into es + MOV DI,OFFSET CONV_PAGES ;ascii string for numb fill pgs + MOV AX,END_BACMEM_SEG ;upper limit of fill + SUB AX,START_BACMEM_SEG ;minus lower start of fill + MOV CL,10 + SHR AX,CL ;convert to number 16k blocks + CALL CNVDECAT + + MOV DI,OFFSET RES_PAGES ;ascii string for pinta reserved pages + MOV AX,STARTING_BLOCK ;number of 4k pages res for pinta + SHR AX,1 + SHR AX,1 ;convert to 16k pages + CALL CNVDECAT + + MOV DI,OFFSET EMS_PAGES ;ascii string available ems pages + MOV AX,FREE_PAGES ;free pages + CALL CNVDECAT + + MOV DI,OFFSET PF_START ;ascii string page frame + MOV AX,PAGE_FRAME_STA ;page frame + CALL CNVHEXAT + +;gga MOV DX,OFFSET PAGE_FRAME_MSG ;start of message +;gga MOV AH,9 ;dos prt string +;gga INT 21H ;status msg1 + + CMP STARTING_BLOCK,0 +; $IF A + JNA $$IF117 + MOV DX,OFFSET RESERVE_MSG ;start of message + MOV AH,9 ;dos prt string + INT 21H ;status msg2 +; $ENDIF +$$IF117: + +;gga MOV DX,OFFSET AVAIL_MSG ;start of message +;gga MOV AH,9 ;dos prt string +;gga INT 21H ;status msg3 + +;indicate that the card has been tested + MOV DX,MODE_REG + IN AL,DX ;read mode reg + OR AL,WARM_MASK ;turn on warm start bit + OUT DX,AL ;write it back + + call Calc_INT15_Space ;calculate remaining INT 15h space ;an000; dms; + call Steal_INT15 ;hook INT 15h ;an000; dms; + call Steal_Int13 ;hook INT 13h ;an004; dms; + + JMP COMMON_EXIT_PATH + + +GENERAL_FAILURE: + + LDS BX,CS:RH_PTRA ;ELSE ... + MOV AX,STAT_GENFAIL ;INDICATE A GENERAL FAILURE + MOV RH.RHC_STA,AX ;WRITE IT TO RH STATUS +;------------------------ +; adds by GGA +;------------------------ + xor ax,ax ; zero segment and offset + mov rh.rh0_endo,ax ; offset of ending addr + push cs + pop ax + mov rh.rh0_ends,ax ; segment of ending addr + + mov rh.rh0_err,0ffh ; error flag for DOS + + mov rh.rh0_nun,al ; = 0 causes installation failure + + jmp skip_size +;------------------------ +COMMON_EXIT_PATH: +;move cursor to next line so other messages are clear + PUSH CS ;get cs + POP DS ;into ds + MOV DX,OFFSET NEXT_LINE + 1 ;get offset of string + MOV AH,9 ;dos print string + INT 21H + + LDS BX,CS:RH_PTRA ;ADDRESSABILITY INTO RH + MOV AX,OFFSET RESIDENT + STACK_SIZE + 100H + MOV RH.RH0_ENDO,AX ;OFFSET OF ENDING ADDR + PUSH CS + POP AX + MOV RH.RH0_ENDS,AX ;OFFSET OF ENDING ADDR + +skip_size: ; gga + + POP CX ;recover old ss + POP DX ;recover old sp + CLI ;ints off during swap + MOV SP,CX ;restore old sp + MOV SS,DX ;restore old ss + STI ;ints back on + + + RET +INIT ENDP + +;-----------------------------------------------------------------------; +; STEAL_INT67 changes the INT 67H vector to point to this ; +; Memory Manager to field subsequent calls. ; +;-----------------------------------------------------------------------; +STEAL_INT67 PROC + PUSH DS + XOR AX,AX + MOV DS,AX ;set DS = 0 + ASSUME DS:INT_VEC + CLI ;disable interrupts + LES DI,DS:EMS_VEC ;get addressing into vector + MOV DS:EMS_VECO,OFFSET EMS_INT67 ;offset of new INT routine + MOV DS:EMS_VECS,CS ;segment of new INT routine + STI ;enable interrupts again + POP DS ;restore DS + RET +STEAL_INT67 ENDP + +;-----------------------------------------------------------------------; +; VIRT2REAL puts the XMA into 'virtual' mode with the translate ; +; table written such that memory is mapped just as it was ; +; in 'real' mode. (Either 256-640k or 512-640k reamains fixed ; +; for all ID's) ; +; ; +; all registers are preserved ; +; ; +;-----------------------------------------------------------------------; +VIRT2REAL PROC + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS ;save these registers + + PUSH CS ;get this segment + POP DS ;into ds +;inhibit all of XMA memory before going into virtual mode + XOR AX,AX ;start at segment 0 + XOR BL,BL ;inhibit + MOV CX,1024/4 ;all 4k blocks in pc space + CALL INHIBLK +;now map virtual mode to look like real mode + MOV AX,START_BACMEM_SEG ;starting 'fill' segment + MOV DX,AX ;get it into dx + XCHG DH,DL ;and shr 8 to convert it to 4k block # + XOR BH,BH ;start at task ID=0 + MOV BL,1 ;enable + MOV CX,16 ;do for all 16 task ID's +; $DO +$$DO119: + PUSH AX ;save these + PUSH CX ;because they are + PUSH DX ;destroyed by call + MOV CX,160 ;640K = 160*4K blocks + SUB CX,DX ;minus starting 4K block + ;is # 4K blocks to map for this ID + CALL SETXLAT ;write trans table accordingly + POP DX ;recover these registers + POP CX + POP AX + INC BH ;next ID +; $ENDDO LOOP + LOOP $$DO119 + + MOV DX,MODE_REG + IN AL,DX ;read mode reg + OR AL,VIRT_MODE ;turn on virtual bit + OUT DX,AL ;write it back + + POP DS ;restore these registers + POP DX + POP CX + POP BX + POP AX + RET +VIRT2REAL ENDP + + +include romscan.inc ; code to do romscan for hole location/verification +INCLUDE PARMPARS.INC ;Routines to parse the parameters + ; on the CONFIG.SYS line + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subprocedure: BACK_CONV_MEM ³ +;³ ³ +;³ Purpose: Called when a portion of the XMA card is used to back ³ +;³ conventional memory. This is the case on an XMA 1 ³ +;³ card (256K - 640K disabled on planar) and on the ³ +;³ XMA/A card when WSP's XMA/A initialization device ³ +;³ driver has disabled the planar. ³ +;³ This procedure will mark the Page Allocation List for ³ +;³ these entries with an ASCII value (for debugging) that ³ +;³ is above the range of eligible pointer values. ³ +;³ At the time this proc is called the PAL has not been ³ +;³ initialized. Initialization will skip these entries. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +BACK_CONV_MEM PROC + MOV AX,END_BACMEM_SEG ;upper segment of backed memory + SUB AX,START_BACMEM_SEG ;subtract seg of backed memory start + MOV CL,10 ;conver # of segments to # of 16 K + SHR AX,CL ; pages used for fill (div by 1024) + SUB TOTAL_EMS_PAGES,AX ;subtract from total EMS pages + ; (but not from TOTAL_SYStem_PAGES) + SUB FREE_PAGES,AX ;subtract from free EMS pages + MOV CX,AX ;Put # of backing pages into CX + PUSH CX ; and save it on stack + + MOV AX,START_BACMEM_SEG ;Convert the segment value for the + MOV CL,10 ; start of backed memory to its + SHR AX,CL ; corresponding page number + MOV DX,TYPE PAGE_ALLOC_LIST ; then convert to the correct @RH8 + MUL DX ; entry in the page alloc list @RH8 + MOV SI,AX ; store PAL offset into SI + POP CX ;recover loop counter for # backed +;mark these pages used in page list but do not assign a handle +BACK_MEM_PAL: + MOV PAGE_LIST_ENTRY,BACMEM_ALLOC ;Mark the PAL with ascii @RH8 + ADD SI,TYPE PAGE_ALLOC_LIST ;Next entry in PAL @RH8 + LOOP BACK_MEM_PAL + ;Remove code here that used to reserve pages for + ; WSP by reading a value on the CONFIG.SYS line. + ; Instead, WSP will make an IOCTL call for the + ; number of pages it needs. +BACK_CONV_MEM ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subprocedure: INIT_PAL ³ +;³ ³ +;³ Purpose: This subprocedure will link the Page Allocation List. ³ +;³ The head pointer to the list of available pages ³ +;³ (PAL_FREE_PTR) is initialized to the top EMS page, ³ +;³ and all available pages are linked from top to bottom. ³ +;³ All free pages will initially be contiguous, except on ³ +;³ an XMA 1 system. With XMA 1, 256-640K on the card is ³ +;³ used to back conventional memory. The free list will ³ +;³ skip around these pages (pages 16 to 40). ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INIT_PAL PROC + push cs ;set up addressibility ;an000; dms; + pop ds ; ;an000; dms; + + cmp Total_EMS_Pages,0 ;any pages? ;an000; dms; + je Init_Pal_End ;no - exit ;an000; dms; + + mov ax,Total_Sys_Pages ;top of EMS pages = ;an000; dms; + add ax,Resr_Ext_Pgs ; total EMS pages + ;an000; dms; + dec ax ; rsv ext. pages - 1 ;an000; dms; + + + mov si,ax ;ptr to free page ;an000; dms; + shl si,1 ;make an index ;an000; dms; + mov Page_List_Entry,Pal_Null ;set last entry to null ;ac007; dms; + shr si,1 ;convert to ptr value ;an007; dms; + mov di,si ;place in di ;an007; dms; + + dec ax ;next page ;an000; dms; + mov cx,Total_EMS_Pages ;loop for all entries ;an000; dms; + dec cx ; but the last ;an000; dms; + +INIT_PAL_LP: + + cmp cx,0 ;at end? ;an000; dms; + je Init_Pal_Loop_Exit ;yes - exit ;an000; dms; + + mov si,ax ;ptr to next page ;ac007; dms; + shl si,1 ;make an index ;ac007; dms; + cmp Page_Alloc_List[si],BacMem_Alloc ;backfilled memory? ;ac007; dms; + jne Init_Pal_Entry ;no - set up ptr's ;an000; dms; + dec ax ;yes - next ptr value ;an000; dms; + jmp Init_Pal_LP ;keep on looping ;an000; dms; +INIT_PAL_ENTRY: + mov Page_List_Entry,di ;set up ptr value ;ac007; dms; + mov di,si ;next ptr value ;ac007; dms; + shr di,1 ;make a ptr value ;an007; dms; +INIT_PAL_BOT: + dec ax ;get next ptr value ;an000; dms; + dec cx ;dec loop counter ;an000; dms; + jmp INIT_PAL_LP ;continue looping ;an000; dms; + +Init_Pal_Loop_Exit: + mov Pal_Free_Ptr,di ;init free ptr ;an007; dms; + +INIT_PAL_END: + ret ;return to caller ;an000; dms; +INIT_PAL ENDP + +;-----------------------------------------------------------------------; +; This routine will convert a number in (AX) to a ; +; 4 byte ascii string equivalent to a 4 digit decimal ; +; number and write it at the address pointed to ; +; by ES:DI. Leading zeroes are suppressed. ; +; ; +; On entry: (AX) = number to be converted ; +; ES:DI= address where string is to be written ; +; ; +; On exit: all registers are preserved ; +; ; +;-----------------------------------------------------------------------; + +CNVDECAT PROC + + PUSH AX + PUSH CX + PUSH DX + PUSH DI ;save these registers + + MOV CX,4 ;loop counter 4 digits +; $DO +$$DO152: + XOR DX,DX ;clear hi word of dividend + ;ax is low word of dividend + DIV CS:TEN ;divide by 10 + OR DL,30H ;make modulo into ascii digit + PUSH DX ;put it on stack +; $ENDDO LOOP ;repeat for all 4 digits + LOOP $$DO152 + + MOV CX,4 ;recover 4 digits from stack +; $DO +$$DO154: + POP AX ;recover next most sign digit + CMP AL,'0' ;is it a '0' +; $IF NE + JE $$IF155 + PUSH AX ;back on stack for next loop + JMP LEAD_DIGIT ;if not then we found leading non zero +; $ENDIF +$$IF155: +; $ENDDO LOOP ;else continiue til non zero found + LOOP $$DO154 +LEAD_DIGIT: +; $IF NCXZ ;only if cx is non zero + JCXZ $$IF158 +; $DO +$$DO159: + POP AX ;recover next digit + MOV ES:BYTE PTR [DI],AL ;write it to string + INC DI ;point to next byte +; $ENDDO LOOP ;repeat for all digits + LOOP $$DO159 +; $ENDIF +$$IF158: + + POP DI ;recover these registers + POP DX + POP CX + POP AX + + RET ;return to caller +CNVDECAT ENDP + + + +;-----------------------------------------------------------------------; +; This routine will convert a number in (AX) to a ; +; 4 byte ascii string equivalent to a 4 digit hexadecimal ; +; number and write it at the address pointed to ; +; by ES:DI. Leading zeroes are suppressed. ; +; ; +; On entry: (AX) = number to be converted ; +; ES:DI= address where string is to be written ; +; ; +; On exit: all registers are preserved ; +; ; +;-----------------------------------------------------------------------; + +DEC2ASCII DB '0123456789ABCDEF' + + +CNVHEXAT PROC + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DI ;save these registers + PUSH DS + + PUSH CS + POP DS + + MOV BX,OFFSET DEC2ASCII + MOV CX,4 ;loop counter 4 digits +; $DO +$$DO162: + XOR DX,DX ;clear hi word of dividend + ;ax is low word of dividend + DIV SIXTEEN ;divide by 10 + + PUSH AX ;save quotient + MOV AX,DX ;get modulo into ax + XLAT DEC2ASCII ;convert al to ascii + MOV DX,AX ;get it into dx + POP AX ;recover quotient + PUSH DX ;put ascii modulo on stack +; $ENDDO LOOP ;repeat for all 4 digits + LOOP $$DO162 + + MOV CX,4 ;recover 4 digits from stack +; $DO +$$DO164: +;gga POP AX ;recover next most sign digit +;gga CMP AL,'0' ;is it a '0' +; $IF NE +;gga JE $$IF165 +;gga PUSH AX ;back on stack for next loop +;gga JMP CNVH1 ;if not then we found leading non zero +; $ENDIF +$$IF165: +; $ENDDO LOOP ;else continiue til non zero found +;gga LOOP $$DO164 +CNVH1: +; $IF NCXZ ;only if cx is non zero + JCXZ $$IF168 +; $DO +$$DO169: + POP AX ;recover next digit + MOV ES:BYTE PTR [DI],AL ;write it to string + INC DI ;point to next byte +; $ENDDO LOOP ;repeat for all digits + LOOP $$DO169 +; $ENDIF +$$IF168: + + POP DS + POP DI ;recover these registers + POP DX + POP CX + POP BX + POP AX + + RET ;return to caller +CNVHEXAT ENDP + +;-----------------------------------------------------------------------; +; STEAL_INT15 changes the INT 15H vector to point to this EMS' ; +; so that subsequent calls to INT15H may determine the actual ; +; size of EM after EMS' allocation of it ; +;-----------------------------------------------------------------------; +STEAL_INT15 PROC + PUSH DS + push ax + + CMP MODEL_BYTE,PS2MODEL80 ;If a PS2/80 treat as XMA memory ;an000; dms; + je Steal_INT15_Exit ;do not hook INT15h ;an000; dms; + + CMP MODEL_BYTE,PC_AT ;If the model byte is for an 'AT' @RH2 + jne Steal_INT15_Hook ; type (80286 processor), check @RH2 + + MOV AH,0C0h ; the XMA/A or XMO card @RH2 + INT 15h ; @RH2 + CMP INT15_SEC_MOD,SEC_MOD_TB; @RH2 + JE Steal_INT15_Hook ; @RH2 + + CMP INT15_SEC_MOD,SEC_MOD_RR;If 'AT' but not PS/2 50 or 60, @RH2 + JE Steal_INT15_Hook ; then family 1 (uses XMA 1 card) @RH2 + JMP Steal_INT15_Exit ; @RH2 + +Steal_INT15_Hook: + + XOR AX,AX + MOV DS,AX ;set DS = 0 + ASSUME DS:INT_VEC15 + CLI ;disable interrupts + LES DI,DS:EM_VEC ;get original vector's content + MOV CS:INTV15O,DI ;save original vector + MOV CS:INTV15S,ES + MOV DS:EM_VECO,OFFSET XMA_INT15 ;offset of new INT routine + MOV DS:EM_VECS,CS ;segment of new INT routine + STI ;enable interrupts again + +Steal_INT15_Exit: + + pop ax + POP DS ;restore DS + RET +STEAL_INT15 ENDP + + +;-----------------------------------------------------------------------; +; Calc_INT15_Space calculates the remaining extended memory for ; +; the system. This value will be used by all subsequent calls ; +; to function 88h, INT 15h. ; +;-----------------------------------------------------------------------; +Calc_INT15_Space proc near ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an002; dms; + push dx ; ;an000; dms; + + mov ah,EM_Size_Get ;get extended mem ;an000; dms; + int 15h ; ;an000; dms; + + mov cl,4 ;divide by 16 ;an002; dms; + shr ax,cl ; to get page count ;an002; dms; + + sub ax,cs:Total_Sys_Pages ;new extended mem size ;an002; dms; + xor dx,dx ;get K count ;an002; dms; + mov bx,cs:Sixteen ; ;an002; dms; + mul bx ; ;an002; dms; + mov word ptr cs:EM_Ksize,ax ;save new size ;an000; dms; + + pop dx ;restore regs ;an000; dms; + pop cx ; ;an002; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret + +Calc_INT15_Space endp ;an000; dms; + + +;-----------------------------------------------------------------------; +; STEAL_INT13 changes the INT 13H vector to point to this EMS' ; +; so that subsequent calls to INT13H may properly handle DMA ; +; to EMS pages. ; +;-----------------------------------------------------------------------; +Steal_Int13 PROC ;an004; dms; + PUSH DS ;an004; dms; + push ax ;an004; dms; + + CMP MODEL_BYTE,PS2MODEL80 ;If not a PS2/80 don't hook INT 13h ;an004; dms; + jne Steal_INT15_Exit ; ;an004; dms; + + XOR AX,AX + MOV DS,AX ;set DS = 0 + ASSUME DS:INT_VEC13 + CLI ;disable interrupts + LES DI,DS:DK_VEC ;get original vector's content + MOV CS:INTV13O,DI ;save original vector + MOV CS:INTV13S,ES + MOV DS:DK_VECO,OFFSET I13_Handler ;offset of new INT routine + MOV DS:DK_VECS,CS ;segment of new INT routine + STI ;enable interrupts again + +Steal_INT13_Exit: + + pop ax + POP DS ;restore DS + RET +STEAL_INT13 ENDP diff --git a/v4.0/src/DEV/XMA2EMS/EMS_US.MSG b/v4.0/src/DEV/XMA2EMS/EMS_US.MSG new file mode 100644 index 0000000..72100b8 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/EMS_US.MSG @@ -0,0 +1,110 @@ +LF EQU 0AH ;ASCII line feed +CR EQU 0DH ;ASCII carriage return + +CRLF DB CR,LF ; gga used to skip a blank line + db '$' + +WELCOME_MSG DB 'XMA2EMS: Expanded Memory Manager' + DB CR,LF + DB '(c)Copyright 1988 Microsoft Corporation All rights reserved' + DB CR,LF + DB '$' + +DGS_START_MSG DB CR,LF + DB 'Performing XMA diagnostics: ' + DB '$' + +DGS_END_MSG DB CR,LF + DB 'Diagnostics completed ' + DB CR,LF,LF + DB '$' + +PAGE_FRAME_MSG DB 'Page Frame starts at........................ ' +PF_START DB 'XXXX' + DB ':0' + DB CR,LF + DB 'Pages mapped to conventional memory......... ' +CONV_PAGES DB '0 ' + DB CR,LF + DB '$' +RESERVE_MSG DB 'Pages reserved for 3270 PC Control Program.. ' +RES_PAGES DB '0 ' + DB CR,LF + DB '$' +AVAIL_MSG DB 'Pages available for expanded memory......... ' +EMS_PAGES DB '0 ' + DB CR,LF + DB '$' + +XMA1_ERR_MSG DB CR,LF + DB 'Adapter error ' + DB CR,LF + DB '$' + +NOT_FOUND_MSG DB CR,LF + DB 'Cannot find adapter ' + DB CR,LF + DB '$' + +PARM_ERR_MSG DB CR,LF + DB 'Parameter syntax or value error ' + DB CR,LF + DB '$' + +NO_EMUL_MSG DB CR,LF + DB 'Cannot find XMA Emulator device driver ' + DB CR,LF + DB '$' + +WRONG_EMUL_MSG DB CR,LF + DB 'Incorrect version of XMAEM.SYS ' + DB CR,LF + DB '$' + +WRONG_XMAA_MSG DB CR,LF + DB 'Incorrect version of INDXMAA.SYS ' + DB CR,LF + DB '$' + +REQ_EMS_ERR_MSG DB CR,LF + DB 'Too many EMS pages requested in /X parameter ' + DB CR,LF + DB '$' + +NOT_INSTL_MSG DB 'Expanded Memory Manager has NOT been installed' + DB CR,LF + DB '$' + +CONFLICT_MSG DB 'Specified page address conflicts with installed adapter at address ' +CONFL_ADDRESS DB '0 ' + DB CR,LF + DB '$' + +HOLE_MSG DB 'Possible 16KB page available at address ' +HOLE_ADDRESS DB '0 ' + DB CR,LF + DB '$' + +FRAME_MSG DB CR,LF + DB 'Possible 64KB frame available at address ' +FRAME_ADDRESS DB '0 ' + DB CR,LF + DB '$' + +NO_PAGES_MSG DB 'No page addresses specified' + DB CR,LF + DB '$' + + +SIZE_MSG1 DB SIZE1_END - 2 -$ +MEM_OK DB 4 DUP (?) + DB ' KB OK$' +SIZE1_END EQU $ + +NEXT_LINE DB NXT_LN_END - 2 -$ + DB ' ',CR,LF,'$' +NXT_LN_END EQU $ + +Prompt_Msg db 'Press any key to continue . . .',CR,LF + db '$' + diff --git a/v4.0/src/DEV/XMA2EMS/GENIOCTL.INC b/v4.0/src/DEV/XMA2EMS/GENIOCTL.INC new file mode 100644 index 0000000..1580fce --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/GENIOCTL.INC @@ -0,0 +1,167 @@ + +GENERIC_IOCTL_P PROC +;ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸ +;³ This routine handles the Generic IOCTL call. The EMS device driver ³ +;³ provides an interface through the Generic IOCTL call to allocate pages ³ +;³ for the Workstation Program. Since WSP needs memory off the 'bottom' of ³ +;³ the XMA card in order to bank switch memory, an IOCTL call is needed to ³ +;³ mark these pages as allocated in the Page Allocation Table. ³ +;³ ³ +;³ The pages for EMS are taken from the linked Page Allocation List. ³ +;³ The PAL is initialized from top down, meaning pages that correspond to ³ +;³ the highest physical addresses on the card are at the beginning of the ³ +;³ free list. Therefore, WSP needs to get the pages from the end of the ³ +;³ free list. ³ +;³ ³ +;³ Programs may load before WSP and allocate and deallocate pages. ³ +;³ This will work fine for WSP, since these pages will come from the 'top' ³ +;³ using the standard function 43 allocate call. It will even work if ³ +;³ an application allocates these bottom pages and then deallocates to ³ +;³ the EMS pool, since the deallocated pages are returned to the top of ³ +;³ the free list and linked in reverse order. The allocates and deallocates ³ +;³ must, however, occur in a stack (LIFO) order or problems will arise. ³ +;³ For example, suppose the system has 30 EMS pages. Handle A allocs ³ +;³ 20 pages that come from the 'top' of the memory card. Handle B then ³ +;³ allocs the bottom 10. Handle A goes counter to LIFO order and deallocs ³ +;³ its 20. WSP then issues this generic IOCTL call asking for 20 pages. ³ +;³ The pages are available, but they are not from the bottom physical ³ +;³ blocks on the card. For this we return error code '91'x (see below). ³ +;³ ³ +;³ The call from WSP's loader will be function 0. No other functions are ³ +;³ supported at this time. If an error is encountered, the return code ³ +;³ is set in the request packet, but not the device driver header. The ³ +;³ header error is set by previous versions of the EMS driver that didn't ³ +;³ handle the IOCTL. ³ +;³ ³ +;ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´ +;³ On entry: ES:BX -> Device driver request header ³ +;³ ³ +;³ The IOCTL code will set standard EMS return codes in the packet's function ³ +;³ field on exit. These include: ³ +;³ '00'x - Good - Requested pages reserved for WSP ³ +;³ '80'x - Software malfunction in EMS software ³ +;³ '84'x - Function code passed is not defined ³ +;³ '87'x - Insufficient total pages to satisfy request ³ +;³ '88'x - Insufficient free pages to satisfy request ³ +;³ '89'x - 0 pages requested ³ +;³ '90'x - Parameter list has an invalid length (Not an EMS return code) ³ +;³ '91'x - Allocated pages do not correspond to ³ +;³ the 'bottom' blocks of XMA memory (Not an EMS return code) ³ +;³ ³ +;ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; + +GIP EQU ES:[DI] ;Pointer to the Generic IOCTL packet @RH6 + +GEN_IOCTL_PARM STRUC ; @RH6 +GIO_PLEN DW ? ; Length of the parameter list @RH6 +GIO_FCNRC DW ? ; Function code on call, ret code on ret +GIO_WSPP DW ? ; Number of pages to reserve for WSP @RH6 +GEN_IOCTL_PARM ENDS ; + +GENERIC_IOCTL: ; @RH6 + PUSH ES ;Save pointer to the request header + PUSH BX + LES DI,RH.RH19_RQPK ;Point ES:DI to the Generic IOCTL @RH6 + ; request packet @RH6 + PUSH CS ;Set addressability to our data @RH6 + POP DS ; @RH6 + XOR AH,AH ;Init upper half of user's ret code @RH6 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ First insure the parameter list is long enough ³ + ;³ to input the number of pages needed by WSP ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP GIP.GIO_PLEN,4 ;If the length is 4 bytes then OK @RH6 + JE GIO_FCN_CHK ;Else give invalid len ret code @RH6 + MOV AL,90h ; and error exit @RH6 + JMP GIP_EXIT ; @RH6 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Check for function code 0 (only one available) ³ +GIO_FCN_CHK: ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP GIP.GIO_FCNRC,0 ; @RH6 + JE GIO_REQNOT0_CHK ; @RH6 + MOV AL,EMS_CODE84 ; @RH6 + JMP GIP_EXIT ; @RH6 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Parm list is OK. Attempt to reserve WSP pages. ³ +GIO_REQNOT0_CHK: ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV BX,GIP.GIO_WSPP ;BX = requested WSP pages @RH6 + CMP BX,0 ;Check that request was not 0 @RH6 + JNE GIO_NOT0 ; @RH6 + MOV AL,EMS_CODE89 ; @RH6 + JMP GIP_EXIT ; @RH6 + +GIO_NOT0: ; @RH6 + CMP BX,TOTAL_EMS_PAGES ;Check for enough total pages @RH6 + JNA GIO_OKTOTAL ; @RH6 + MOV AL,EMS_CODE87 ; @RH6 + JMP GIP_EXIT ; @RH6 + + ;Note: section is not reentrant. It is possible RH8 + ; that between the time FREE_PAGES is loaded and RH8 + ; then changed, an EMS allocate or deallocate RH8 + ; could occur and hose this up. However, since RH8 + ; WSP is loading at this point, it is unlikely. RH8 +GIO_OKTOTAL: + CLI ;Don't allow other alloc or deall @RH8 + CMP BX,FREE_PAGES ;Check for enough free pages @RH6 + JNA GIO_REMOVE_FREE ; If not enough pages free then @RH6 + MOV AX,FREE_PAGES ; return number of free in parm @RH6 + STI ; list and set ret code @RH8 + MOV GIP.GIO_WSPP,AX ; @RH6 + MOV AL,EMS_CODE88 ; @RH6 + JMP GIP_EXIT ; @RH6 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Remove WSP pages from the end of the free list ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +GIO_REMOVE_FREE: + SUB FREE_PAGES,BX + MOV CX,FREE_PAGES + MOV SI,PAL_FREE_PTR + STI + SHL SI,1 + + CMP CX,0 ;WSP LEAVE NOTHING FREE? + JNE GIO_GET_LAST_FREE ;YES SET FREE PTR TO NULL + MOV PAL_FREE_PTR,PAL_NULL + JMP SHORT GIO_MARK_WSP + + +GIO_GET_LAST_FREE: + DEC CX + CMP CX,0 + JE GIO_GOT_LAST_FREE +GIO_LAST_FREE_LOOP: + MOV SI,PAGE_LIST_ENTRY ;BASED OFF SI + SHL SI,1 + LOOP GIO_LAST_FREE_LOOP + + +GIO_GOT_LAST_FREE: + MOV AX,PAGE_LIST_ENTRY ;STORE OFFSET FOR 1ST WSP + MOV PAGE_LIST_ENTRY,PAL_NULL ;THEN MAKE IT END OF FREE LIST + MOV SI,AX ;RESTORE 1ST WSP (TOP) + SHL SI,1 + +GIO_MARK_WSP: + MOV CX,BX ;LOOPR FOR WSP PAGES +GIO_WSP_LOOP: + MOV AX,PAGE_LIST_ENTRY ;STORE INDEX OF NEXT + MOV PAGE_LIST_ENTRY,WSP_ALLOC ;MARK AS WSP + MOV SI,AX ;RESTOER INEX OF NEXT + SHL SI,1 + LOOP GIO_WSP_LOOP + + XOR AX,AX ;Set good return code + +GIP_EXIT: ;GGA + + MOV GIP.GIO_FCNRC,AX ;Store ret code in user's req packet + POP BX ;Restore for ptr to request header @RH6 + POP ES ; @RH6 + MOV RH.RHC_STA,STAT_DONE ; Store done status and good return@RH6 + ; code into request header @RH6 + RET +GENERIC_IOCTL_P ENDP + + \ No newline at end of file diff --git a/v4.0/src/DEV/XMA2EMS/I13HOOK.INC b/v4.0/src/DEV/XMA2EMS/I13HOOK.INC new file mode 100644 index 0000000..2f981c2 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/I13HOOK.INC @@ -0,0 +1,449 @@ + +include MSBDS.INC ;include BDS struc ;an000; dms; + + + + +;========================================================================= +; I13_Handler - This routine is the main driver of the +; INT 13h hook. +;========================================================================= + +I13_Handler proc far ; ;an000; dms; + + jmp I13_Handler_Start + + +I13_Max_Head db ? ;max head count on drive ;an000; dms; +I13_SPT db ? ;max sectors/track count ;an000; dms; +I13_BPS dw ? ;max number bytes/sector ;an000; dms; +I13_Bytes_Per_Para dw 10h ;number of bytes per paragraph ;an000; dms; +I13_Bytes_Per_EMS_Page dw 4000h ;bytes per EMS page ;an000; dms; +I13_Paras_Per_Sector dw ? ;paras per sector ;an000; dms; +I13_DD_Per_Sector dw ? ;double words per sector ;an000; dms; +I13_Operation db ? ;INT 13h function ;an000; dms; +I13_Sector_Count db ? ;sector count ;an000; dms; +I13_Track_Number dw ? ;track number ;an000; dms; +I13_Sector_Number db ? ;sector number ;an000; dms; +I13_Head_Number db ? ;head number ;an000; dms; +I13_Drive_Number db ? ;drive number ;an000; dms; +I13_Sectors_To_Trf db 1 ;current sectors to trf ;an000; dms; +I13_Curr_Trf_Cnt db ? ;total transfer count in secs ;an000; dms; +I13_Trf_Off dw ? ;current address for trf ;an000; dms; +I13_Trf_Seg dw ? ;an000; dms; +I13_512_Byte_Buffer db 512 dup(0) ;buffer for sector ;an000; dms; + +I13_Handler_Start: + + sti ;ints on ;an000; dms; + cmp ah,02h ;read operation? ;an000; dms; + je I13_Handler_Get_Parms ;yes - get drive parms ;an000; dms; + + cmp ah,03h ;write operation? ;an000; dms; + je I13_Handler_Get_Parms ;yes - get drive parms ;an000; dms; + + jmp cs:IntV13 ;neither - go to old INT 13h ;an000; dms; + +I13_Handler_Get_Parms: + + call I13_Get_Dev_Parms ;get device parms for this drive;an000; dms; + jnc I13_Handler_Range_Ck ;we have device data ;an000; dms; + jmp cs:IntV13 ;go to old INT 13h vector ;an000; dms; + +I13_Handler_Range_Ck: + + call I13_Target_Source_Range_Ck ;crosses the 640k boundary? ;an000; dms; + jc I13_Handler_Request_Break ;break up the request ;an000; dms; + jmp cs:IntV13 ;go to old INT 13h vector ;an000; dms; + +I13_Handler_Request_Break: + + call I13_Request_Break_Up ;break up I13 request ;an000; dms; + + ret 2 ;return to caller ;an000; dms; + ;clear the flags from the stack + ; and pass back ours +I13_Handler endp ; ;an000; dms; + + + +;========================================================================= +; I13_Target_Source_Range_Ck - This routine determines if the +; target or source resides in an EMS +; page. +; +; Inputs : ES:BX - Source/target address +; +; Outputs : CY - if address resides in an EMS page +; NC - address not in an EMS page +;========================================================================= + + +I13_Target_Source_Range_Ck proc near ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + + mov ax,cs ;get cs addressibility ;an000; dms; + mov ds,ax ; ;an000; dms; + mov si,offset cs:Map_Table ;point to the map table ;an000; dms; + + mov cx,cs:Map_Count ;get the number of phys. pages ;an000; dms; + +I13_Target_Source_Loop: + + cmp cx,0 ;at end? ;an000; dms; + je I13_Target_Source_Not_EMS_Page ;yes - source/target not in pg ;an000; dms; + + mov ax,ds:[si].Phys_Page_Segment ;get the segment value ;an000; dms; + mov bx,es ; ;an000; dms; + cmp bx,ax ;source/target > EMS page? ;an000; dms; + jb I13_Target_Source_Not_EMS_Page ;no - we are OK for old INT 13 ;an000; dms; + ;must be >= EMS page + + add ax,400h ;get end address of EMS page ;an000; dms; + cmp bx,ax ;source/target < end of EMS pg? ;an000; dms; + jb I13_Target_Source_In_EMS_Page ;yes - we are in a page ;an000; dms; + + add si,type Mappable_Phys_Page_Struct ;adjust pointer to next page ;an000; dms; + dec cx ;dec counter ;an000; dms; + + jmp I13_Target_Source_Loop ;continue loop ;an000; dms; + +I13_Target_Source_Not_EMS_Page: + + clc ;flag not in EMS page ;an000; dms; + jmp I13_Target_Source_Exit ;exit routine ;an000; dms; + +I13_Target_Source_In_EMS_Page: + + stc ;flag in an EMS page ;an000; dms; + +I13_Target_Source_Exit: + + pop ds ;restore regs ;an000; dms; + pop si ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ; ;an000; dms; + +I13_Target_Source_Range_Ck endp ; ;an000; dms; + + +;========================================================================= +; I13_Request_Break_Up - Break up the INT 13h request onto 16k +; boundaries. +; +; Inputs : AH - 02 (Read) +; 03 (Write) +; AL - Sector count +; CH - Track number +; CL - Sector number +; DH - Head number +; DL - Drive number +; ES:BX - Buffer address +; +; Outputs : Data transferred +;========================================================================= + + +I13_Request_Break_Up proc near ; ;an000; dms; + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + + mov cs:I13_Trf_Seg,es ;save segment ;an000; dms; + mov cs:I13_Trf_Off,bx ;save offset ;an000; dms; + mov cs:I13_Curr_Trf_Cnt,0 ;init transfer count ;an000; dms; + mov cs:I13_Operation,ah ;save operation ;an000; dms; + mov cs:I13_Sector_Count,al ;save sector count ;an000; dms; + + + mov byte ptr cs:I13_Track_Number,ch ;save starting track number ;an000; dms; + mov ch,cl ;xchg bytes ;an000; dms; + shr ch,1 ;shift 6 bits ;an000; dms; + shr ch,1 ; ;an000; dms; + shr ch,1 ; ;an000; dms; + shr ch,1 ; ;an000; dms; + shr ch,1 ; ;an000; dms; + shr ch,1 ; ;an000; dms; + + mov byte ptr cs:I13_Track_Number[+1],ch ;high byte for cylinder ;an000; dms; + and cl,00111111b ;get bits 0-5 for sector number ;an000; dms; + + mov cs:I13_Sector_Number,cl ;save starting sector number ;an000; dms; + mov cs:I13_Head_Number,dh ;save starting head number ;an000; dms; + mov cs:I13_Drive_Number,dl ;save drive number ;an000; dms; + + mov cl,cs:I13_Sector_Count ;while sectors ;an000; dms; + + cmp cs:I13_Operation,02h ;read? ;an000; dms; + jne I13_Request_Write ;must be a write ;an000; dms; + +I13_Request_Read: + + cmp cl,0 ;at end? ;an000; dms; + je I13_Request_Success ;exit we are done ;an000; dms; + + lea bx,cs:I13_512_Byte_Buffer ;point to 512 byte buffer ;an000; dms; + mov ax,cs ;pass cs to es ;an000; dms; + mov es,ax ; ;an000; dms; + + call I13_Invoke ;do the INT 13h to our buffer ;an000; dms; + jc I13_Request_Failed ;signal failure ;an000; dms; + mov ax,cs ;point to our buffer to the ;an000; dms; + mov ds,ax ; transfer ;an000; dms; + mov si,offset cs:I13_512_Byte_Buffer; ;an000; dms; + + mov es,cs:I13_Trf_Seg ;restore seg to target ;an000; dms; + mov di,cs:I13_Trf_Off ;restore off to target ;an000; dms; + + push cx ;save cx across move ;an000; dms; + cld ;do a forward move ;an000; dms; + mov cx,cs:I13_DD_Per_Sector ; for 128 dd's ;an000; dms; + db 66h ;op code for dd word move ;an000; dms; + rep movsw ;do the move - wow that was fast;an000; dms; + pop cx ;restore it ;an000; dms; + + call I13_Adjust ;adjust our pointers ;an000; dms; + + dec cl ;decrease sector counter ;an000; dms; + jmp I13_Request_Read ;continue loop ;an000; dms; + +I13_Request_Write: + + cmp cl,0 ;at end? ;an000; dms; + je I13_Request_Success ;exit we are done ;an000; dms; + + mov ax,cs ;point to 512 byte buffer ;an000; dms; + mov es,ax ; ;an000; dms; + mov di,offset cs:I13_512_Byte_Buffer; ;an000; dms; + + mov ds,cs:I13_Trf_Seg ;get source segment ;an000; dms; + mov si,cs:I13_Trf_Off ;get source offset ;an000; dms; + + push cx ;save cx across move ;an000; dms; + cld ;do a forward move ;an000; dms; + mov cx,cs:I13_DD_Per_Sector ; for 128 dd's ;an000; dms; + db 66h ;op code for dd word move ;an000; dms; + rep movsw ;do the move - wow that was fast;an000; dms; + pop cx ;restore it ;an000; dms; + + lea bx,cs:I13_512_Byte_Buffer ;point to 512 byte buffer ;an000; dms; + mov ax,cs ;pass cs to es ;an000; dms; + mov es,ax ; ;an000; dms; + + call I13_Invoke ;do the INT 13h to our buffer ;an000; dms; + jc I13_Request_Failed ;signal failure ;an000; dms; + call I13_Adjust ;adjust our pointers ;an000; dms; + + dec cl ;decrease sector counter ;an000; dms; + jmp I13_Request_Write ;continue loop ;an000; dms; + +I13_Request_Failed: + + jmp I13_Request_Exit ;exit on error ;an000; dms; + + +I13_Request_Success: + + xor ax,ax ;clear status byte ;an000; dms; + +I13_Request_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + + ret ; ;an000; dms; + +I13_Request_Break_Up endp ; ;an000; dms; + + + +;========================================================================= +; I13_Adjust - This routine adjusts the needed fields for +; the next iteration of INT 13h. +; +; Inputs : I13_Sectors_To_Trf - Sectors just read/written +; I13_Sector_Number - Starting sector number for trf +; I13_Head_Number - Starting head number for trf +; I13_Track_Number - Starting track number for trf +; +; Outputs : I13_Sector_Number - New starting sector for trf +; I13_Head_Number - New starting head for trf +; I13_Track_Number - New starting track for trf +;========================================================================= + + +I13_Adjust proc near ;adjust values ;an000; dms; + + push ax ;save regs ;an000; dms; + + inc cs:I13_Sector_Number ;next sector ;an000; dms; + mov al,cs:I13_Sector_Number ; ;an000; dms; + cmp al,cs:I13_SPT ;> sectors on track? ;an000; dms; + jna I13_Adjust_Exit ;no ;an000; dms; + mov cs:I13_Sector_Number,1 ;yes - start at next ;an000; dms; + inc cs:I13_Head_Number ;next head ;an000; dms; + mov al,cs:I13_Head_Number ; ;an000; dms; + cmp al,cs:I13_Max_Head ;> head count ;an000; dms; + jb I13_Adjust_Exit ;no ;an000; dms; + mov cs:I13_Head_Number,0 ;yes - head 0 ;an000; dms; + inc cs:I13_Track_Number ;next track ;an000; dms; + +I13_Adjust_Exit: + + mov ax,cs:I13_Paras_Per_Sector ;get bytes per sector ;an000; dms; + add cs:I13_Trf_Seg,ax ;adjust segment ;an000; dms; + + pop ax ;restore regs ;an000; dms; + + ret ; ;an000; dms; + +I13_Adjust endp ; ;an000; dms; + + +;========================================================================= +; I13_Invoke - This routine sets up the regs for the INT 13h +; and invokes it for the sector we need. +; +; Inputs : I13_Operation - read/write +; I13_Track_Number - cylinder to read/write +; I13_Sector_Number - starting sector for read/write +; I13_Head_Number - starting head +; I13_Drive_Number - starting drive +; +; Outputs : NC - good read/write +; CY - bad read/write +;========================================================================= + +I13_Invoke proc near ;invoke INT 13h ;an000; dms; + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + + mov ah,cs:I13_Operation ;get function call ;an000; dms; + mov al,cs:I13_Sectors_To_Trf ;get sectors to transfer ;an000; dms; + + mov ch,byte ptr cs:I13_Track_Number ;get track number ;an000; dms; + mov cl,byte ptr cs:I13_Track_Number[+1] ;get high 2 bits ;an000; dms; + shl cl,1 ;put bit is positions 6&7 ;an000; dms; + shl cl,1 ; ;an000; dms; + shl cl,1 ; ;an000; dms; + shl cl,1 ; ;an000; dms; + shl cl,1 ; ;an000; dms; + shl cl,1 ; ;an000; dms; + or cl,cs:I13_Sector_Number ;place the sector number in cl ;an000; dms; + + mov dh,cs:I13_Head_Number ;get head number ;an000; dms; + mov dl,cs:I13_Drive_Number ;get drive number ;an000; dms; + pushf + call cs:IntV13 ;go to old vector ;an000; dms; + inc cs:I13_Curr_Trf_Cnt ;increment counter ;an000; dms; + + pop dx ;restore regs ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + ret ; ;an000; dms; + +I13_Invoke endp ; ;an000; dms; + + +;========================================================================= +; I13_Get_Dev_Parms - This routine obtains the device parameters for +; the drive being accessed for the INT 13h. +; +; Inputs : DL - drive number +; +; Outputs : I13_Max_Head - max head count on drive +; I13_SPT - max sectors/track count for drive +; CY - error +; NC - no error +;========================================================================= + + + +I13_Get_Dev_Parms proc near ;get sectors/track & head cnt. ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push ds ; ;an000; dms; + + mov ax,0803h ;get the BDS table ;an000; dms; + int 2fh ; ;an000; dms; + +I13_Get_Dev_Next_Entry: + + cmp ds:[di].Drivenum,dl ;do we have our drive? ;an000; dms; + je I13_Get_Dev_Save_Parms ;yes get data ;an000; dms; + cmp word ptr ds:[di].Link[+0],-1 ;last entry in list? ;an000; dms; + je I13_Get_Dev_Parms_Error_Exit ;yes - did not find drive ;an000; dms; + mov ax,word ptr ds:[di].Link[+0] ;get offset of next entry ;an000; dms; + mov bx,word ptr ds:[di].Link[+2] ;get segment of next entry ;an000; dms; + mov ds,bx ;stuff into ds:di ;an000; dms; + mov di,ax ; ;an000; dms; + jmp I13_Get_Dev_Next_Entry ;continue ;an000; dms; + +I13_Get_Dev_Save_Parms: + + mov ax,ds:[di].BytePerSec ;get byte count per sector ;an000; dms; + mov cs:I13_BPS,ax ; ;an000; dms; + + xor dx,dx ;clear high word ;an000; dms; + div cs:I13_Bytes_Per_Para ;get number of paras in sector ;an000; dms; + mov cs:I13_Paras_Per_Sector,ax ;save it ;an000; dms; + shl ax,1 ;get DD's per sector ;an000; dms; + shl ax,1 ; ;an000; dms; + mov cs:I13_DD_Per_Sector,ax ; ;an000; dms; + + mov ax,ds:[di].SecLim ;get sectors per track ;an000; dms; + mov cs:I13_SPT,al ; ;an000; dms; + + mov ax,ds:[di].HdLim ;get max head count ;an000; dms; + mov cs:I13_Max_Head,al ; ;an000; dms; + + clc ;flag data found ;an000; dms; + + jmp I13_Get_Dev_Parms_Exit ; ;an000; dms; + + +I13_Get_Dev_Parms_Error_Exit: + + stc ;flag no data found ;an000; dms; + +I13_Get_Dev_Parms_Exit: + + pop ds ;restore regs ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ; ;an000; dms; + +I13_Get_Dev_Parms endp ; ;an000; dms; + + diff --git a/v4.0/src/DEV/XMA2EMS/LIM40.INC b/v4.0/src/DEV/XMA2EMS/LIM40.INC new file mode 100644 index 0000000..8cd006c --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/LIM40.INC @@ -0,0 +1,1792 @@ + page +;------------------------------------------------------------------- +; +; Equates that are specific to LIM 4.0 functions go here +; +;------------------------------------------------------------------- + +null equ 0 ; null value, used everywhere +max_phys_pages equ 255 ; largest allowable phys page + +sf_pm_get equ 0 ; 4f00 - get partial map +sf_pm_set equ 1 ; 4f01 - set partial map +sf_pm_size equ 2 ; 4f02 - get partial map size + +mu_ppn equ 0 ; 5000 - map/unmap multiple +mu_seg equ 1 ; 5001 - map/unmap multiple +mu_max_fcn equ 1 ; 50 - map/unmap multiple + +Hn_Attr_Max_Fcn equ 2 ; 52xx - max subfunction ;an000; dms; + +sf_hn_get equ 0 ; 5300 - get handle name +sf_hn_set equ 1 ; 5301 - set handle name +hn_max_fcn equ 1 ; 53 - handle name sub-functions 00, 01 + +sf_hd_get equ 0 ; 5400 - get handle dir +sf_hd_search equ 1 ; 5401 - search for named handle +sf_hd_total equ 2 ; 5402 - get total number of handles +hd_max_fcn equ 2 ; 54 - get handle directory s-f's 00, 01, 02 + +Add_Get_Array equ 0 ; 5800 - Get Mappable Physical Address Array +Add_Get_Size equ 1 ; 5801 - Get Mappable Physical Address Array Entries + +hi_info equ 0 ; 5900 - hardware info +hi_raw equ 1 ; 5901 - # raw pages + +am_get equ 0 ; 5b00 - get alternate map register set +am_set equ 1 ; 5b01 - set alternate map register set +am_size equ 2 ; 5b02 - get alternate map save array size +am_alloc equ 3 ; 5b03 - allocate alternate map register set +am_dealloc equ 4 ; 5b04 - deallocate alternate map register set +am_dma_alloc equ 5 ; 5b05 - allocate DMA register set +am_dma_enable equ 6 ; 5b06 - enable DMA register set +am_dma_disable equ 7 ; 5b07 - disable DMA register set +am_dma_dealloc equ 8 ; 5b08 - deallocate DMA register set + +os_enable equ 0 ; 5d00 - enable OS/E function +os_disable equ 1 ; 5d01 - disable OS/E function +os_access equ 2 ; 5d02 - "return" access key function + +map_pages_fcn equ 44h ; function code used to map pages +get_free_pages equ 42h ; function code used to get free page count + +read_clock equ 2ch ; function code to read clock +dos_int equ 21h ; interrupt 21 +xor_mask equ 0ffffh ; mask used to confuse the random numbers a little + +ppm_struct STRUC ; define the structure +phys_page_offset dw ? ; offsets into PPM entry +ppm_handle_offset dw ? +ppm_log_page_offset dw ? +ppm_struct ENDS + + page +;------------------------------------------------------------------- +; +; 4F - get/set partial page map +; +; INPUT: +; AL = 00, get partial page map pm_get +; 01, set partial page map pm_set +; 02, get partial page map size pm_size +; +; OUTPUT: +; See individual function headers +; +;------------------------------------------------------------------- +partial_map proc + +; use AL value to select sub-function + + cmp al,sf_pm_get ; al = 00, get partial page map + je pm_get + + cmp al,sf_pm_set ; al = 01, set partial page map + je pm_set + + cmp al,sf_pm_size ; al = 02, get partial page map size + jne pm_invalid_sfcn + jmp pm_size + + +; invalid sub-function, report the error + +pm_invalid_sfcn: + mov ah,ems_code8F ; invalid sub-function code + ret + + page +;------------------------------------------------------------------- +; +; 4F00 - get partial page map +; +; INPUT: +; DS:SI -> partial page map +; +; dw ? ; segment count (number +; ; of following entries) +; dw ? ; segment address to save +; : ; (repeats count times) +; : +; +; ES:DI -> user array for mapping info +; size determined by function 4F02 +; +; +; OUTPUT: +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 84H, Invalid function +; 8FH, Invalid sub-function +; A3H, Contents of control structure are invalid +; +; ES:DI -> saved partial state array +; format for this is un-disclosed to the user +; but will be: +; +; ppm_count dw ? ; number of saved entries +; ppm_phys_page dw ? ; physical page +; ppm_handle dw ? ; handle +; ppm_log_page dw ? ; logical page +; : ; repeats for each requested page +; : +; +; +;------------------------------------------------------------------- +pm_get: + + push bx ; save some regs + push cx + push dx + push di + push si + push ds + + mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to mapping control structure + + +;------------------------------------------------------------------- + +; get count from caller's control structure + + mov cx,ds:[si] ; the first word of the control + ; structure holds the # of entries + + cmp cx,0 ; 0 pages requested? ;an000; dms; + je PM_Get_Error_A3 ; yes - flag an error ;an000; dms; + + cmp cx,cs:Map_Count ; do some sanity checking + jbe pm_phys_ok ; requested number is ok, do the copies + +; They asked for more than we can possibly have. Sounds like trouble. + +PM_Get_Error_A3: + + mov ah,ems_codea3 ; bad stuff in the control structure + jmp pm_exit00 ; return the error code + +pm_phys_ok: + mov cx,DS:word ptr [si] ; get count from control structure + mov ES:word ptr [di],cx ; save count in save area + add di,2 ; increment save area pointer + +;------------------------------------------------------------------- +; +; everything is OK so far, copy the entries requested +; +;------------------------------------------------------------------- + +ppm_copies: + + add si,2 ; point to next segment number + mov ax,DS:word ptr [si] ; get segment value from control structure + + push si ; save user's si + push ds ; save user's ds + push cx ; save counter for outer loop + +; ready to do the lookup and copy operation + + push cs ; make DS:SI point to internal data area + pop ds + lea si,map_table + + mov cx,map_count ; number of mappable segments + +ppm_inner_copy_loop: + cmp ax,ds:word ptr [si+phys_page_segment] ; is this entry the requested? + jne ppm_not_yet ; no, try again + + mov cx,ppm_size ; number of bytes to copy + cld ; make sure direction flag is right + add si,2 ; point to phys_page_number + + rep movsb ; copy the entry + + sub si,2 ; reset si + + jmp ppm_entry_done ; done with this copy, go on + +ppm_not_yet: + add si,type mappable_phys_page_struct ; point to next entry + loop ppm_inner_copy_loop ; try some more + + pop cx ; restore counter for outer loop + pop ds ; restore user's ds + pop si ; restore user's si + mov ah,EMS_Code8B ; we have an invalid segment specified ;an000; dms; + jmp PM_Exit00 ; exit the program + +ppm_entry_done: + +; restore pointer to control structure + + pop cx ; restore counter for outer loop + pop ds ; restore user's ds + pop si ; restore user's si + + + loop ppm_copies ; keep going until proper number of + ; entries have been copied + + xor ah,ah ; good return code +;------------------------------------------------------------------- +pm_exit00: + pop ds ; restore these registers + pop si + pop di + pop dx + pop cx + pop bx + + ret ; return to caller + + + + page +;------------------------------------------------------------------- +; +; 4F01 - set partial page map +; +; INPUT: +; DS:SI -> source array +; Format: +; +; ppm_count dw ? ; number of saved entries +; ppm_phys_page dw ? ; physical page +; ppm_handle dw ? ; handle +; ppm_log_page dw ? ; logical page +; : ; repeats ppm_count times +; : +; +; +; OUTPUT: +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 84H, Invalid function +; 8FH, Invalid sub-function +; A3H, Contents of source array invalid +; +;------------------------------------------------------------------- +pm_set: + + push bx ; save some regs + push cx + push dx + push di + push si + push ds + + mov cx,DS:word ptr [si] ; get number of entries in save area + + cmp cx,0 ; is the count zero? + je pm_set_error_A3 ; yes - error ;an000; dms; + + cmp cx,cs:Map_Count ; greater than phys pages avail? ;an000; dms; + jbe count_ok ; no - data not corrupted ;an000; dms; + +pm_set_error_A3: + + mov ah,EMS_CODEA3 ; control structure error + jmp pm_exit01 ; exit + +count_ok: + add si,2 ; point to first entry in save area + +pm01_loop: + + mov ax,DS:word ptr [si+phys_page_offset] ; set up regs for map_l_to_p + mov ah,map_pages_fcn + mov dx,DS:word ptr [si+ppm_handle_offset] + mov bx,DS:word ptr [si+ppm_log_page_offset] + + cmp dx,0ffffh ; is there a real entry? + je no_map ; no, skip the call to map_l_to_p + + call map_l_to_p ; make the mapping call + +no_map: + add si,type ppm_struct ; point to next entry + + loop pm01_loop ; + + xor ah,ah ; good return code +pm_exit01: + + pop ds ; restore these registers + pop si + pop di + pop dx + pop cx + pop bx + + ret ; return to caller + + + page +;------------------------------------------------------------------- +; +; 4F02 - get partial page map size +; +; INPUT: +; AX = 4f02h +; +; BX = number of pages in partial page map +; +; OUTPUT: +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 84H, Invalid function +; 8FH, Invalid sub-function +; +; AL = size of partial page map save array +; number of bytes that will be needed +; to save the requested number of pages +; +;------------------------------------------------------------------- +pm_size: + + push dx ; save dx + + cmp bx,0 ; 0 pages requested? ;an000; dms; + je PM_Size_Error_8B ; yes flag an error ;an000; dms; + + cmp bx,cs:Map_Count ; page count > phys pages? ;an000; dms; + jbe PM_Size_Return ; no - continue ;an000; dms; + +PM_Size_Error_8B: + + mov ah,EMS_Code8B ; signal page count exceeded ;an000; dms; + jmp PM_Exit02 ; exit routine ;an000; dms; + +PM_Size_Return: + + mov dx,bx ; number of pages times ... + mov ax,ppm_size ; * size of an entry ... + mul dx ; = number of bytes in save array + add ax,2 ; increase by 2 to include count word + + xor ah,ah ; good return code + +pm_exit02: + pop dx ; restore dx + + ret ; return to caller + +partial_map endp + + + page +;------------------------------------------------------------------- +; +; 50 - map/unmap multiple handle pages +; +; INPUT: +; AH = 00 physical page numbers +; 01 segment numbers +; +;------------------------------------------------------------------- +map_mult proc + + cmp al,mu_ppn ; is this a map request? + je mu_ppn_fcn ; yes, go do it + + cmp al,mu_seg ; no, is this an unmap request? + je mu_seg_fcn ; yes, go do it + + xor al,al ; clear al, why not? + mov ah,ems_code8f ; no, return invalid sub-function code + ret ; return to caller + +;------------------------------------------------------------------- +; +; 5000 - map/unmap multiple handle pages using physical page numbers +; +; INPUT: +; AX = 5000h +; +; DX = handle +; +; CX = num entries in control structure +; +; DS:SI -> points to control structure +; Format: +; +; log_pg_num dw ? ; logical page number +; phys_pg_num dw ? ; physical page number +; : ; repeats CX times +; : +; +; OUTPUT: +; +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 83H, Invalid handle +; 84H, Invalid function +; 8AH, Invalid logical page +; 8BH, Invalid physical page +; 8FH, Invalid sub-function +; +;------------------------------------------------------------------- + +mu_ppn_fcn: + + push bx ; save regs ;an000; dms; + push cx ; save count + push dx ; ;an000; dms; + push si ; save pointer + + xor ah,ah ; good return code + cmp cx,0 ; is count 0? + je mu_ppn_exit + +mu_ppn_loop: + mov bx,ds:word ptr[si+0] ; get logical page number + mov ax,ds:word ptr[si+2] ; get physical page number + mov ah,map_pages_fcn ; fcn code for mapping + + push cx + call map_l_to_p ; call the mapping routine + pop cx + + cmp ah,0 ; was return code OK + jne mu_ppn_error + + add si,4 ; point to next entry + + loop mu_ppn_loop ; do it again + + xor ah,ah ; good return code + jmp mu_ppn_exit + +mu_ppn_error: +mu_ppn_exit: + pop si ; restore pointer + pop dx ; ;an000; dms; + pop cx ; restore count + pop bx ; restore regs ;an000; dms; + + ret ; return to caller + + +;------------------------------------------------------------------- +; +; 5001 - map/unmap multiple handle pages using segment addresses +; +; INPUT: +; AX = 5001h +; +; DX = handle +; +; CX = num entries in control structure +; +; DS:SI -> points to control structure +; Format: +; +; log_pg_num dw ? ; logical page number +; seg_address dw ? ; physical segment address +; : ; repeats CX times +; : +; +; OUTPUT: +; +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 83H, Invalid handle +; 84H, Invalid function +; 8AH, Invalid logical page +; 8BH, Invalid physical page +; 8FH, Invalid sub-function +; +;------------------------------------------------------------------- + +mu_seg_fcn: + + push bx ; save regs ;an000; dms; + push cx ; save count + push dx ; ;an000; dms; + push si ; save pointer + + xor ah,ah ; good return code + cmp cx,0 ; is count 0? + je mu_seg_exit + +mu_seg_loop: + mov bx,ds:word ptr[si+0] ; get logical page number + + push dx ; save handle + mov dx,ds:word ptr[si+2] ; get physical page number + call Get_Phys_Seg_Page ; convert to logical page circle + mov ax,dx ; must be in AX + pop dx ; restore handle + + mov ah,map_pages_fcn ; fcn code for mapping + + push cx + call map_l_to_p ; call the mapping routine + pop cx + + cmp ah,0 ; was return code OK + jne mu_seg_error + + add si,4 ; point to next entry + + loop mu_seg_loop ; do it again + + xor ah,ah ; good return code + jmp mu_seg_exit + +mu_seg_error: +mu_seg_exit: + pop si ; restore pointer + pop dx ; ;an000; dms; + pop cx ; restore count + pop bx ; restore regs ;an000; dms; + + ret ; return to caller + +map_mult endp + +;------------------------------------------------------------------- +include lim40b.inc +;------------------------------------------------------------------- + + page +;------------------------------------------------------------------- +; +; 52 - get/set handle attributes +; +; The LIM 4.0 spec strongly advises EMS implementers to avoid this +; call. Our current implementation of this function is not to provide +; support. Possibly in future releases it will be supported, if +; the proper hardware becomes available. +; +; DMS 4/29/88 +; +;------------------------------------------------------------------- +handle_attrib proc + + + cmp al,Hn_Attr_Max_Fcn ;maximum subfunction number ;an000; dms; + jbe Handle_Attrib_Cont ;continue routine ;an000; dms; + mov ah,EMS_Code8F ;we have an invalid subfunction ;an000; dms; + jmp Handle_Attrib_Exit ; exit the routine ;an000; dms; + +Handle_Attrib_Cont: + + mov ah,EMS_Code91 ;this function is not supported ;an000; dms; + +Handle_Attrib_Exit: + + RET ; return to caller + +handle_attrib endp + + page +;------------------------------------------------------------------- +; +; 53 - get/set handle name +; +; Virtual Mode Note: The Handle Name functions (53 and 54) will @RH6 +; be handled differently when running on a system in virtual mode. @RH6 +; This is to accommadate the Workstation Program's bank switching. @RH6 +; In this case, handle names and ID's will only be returned for @RH6 +; handles allocated in the same PC bank, or for handles in bank 0. @RH6 +; Bank 0 is for device drivers, system extensions, or applications @RH6 +; that install resident before WSP loads. @RH6 +; When interfacing with handles in bank 0, one must be aware of @RH6 +; the problem of two PC applications running simultaneously that @RH6 +; get the handle ID of the resident program and map its pages. @RH6 +; Data corruption will occur if both map and write to the same page @RH6 +; at the same time. @RH6 +; While these new LIM 4.0 functions will return info only for @RH6 +; bank 0 and the current bank, the existing LIM 3.2 functions will @RH6 +; continue to return total system values. For example, function 4B @RH6 +; will return the number of active handles in all banks. @RH6 +; +; INPUT: +; AL = sub-function code +; 00 = get handle name hn_get +; 01 = set handle name hn_set +; +; DX = handle +; +; ES:DI -> Get caller's name buffer (8 char's) +; DS:SI -> Set caller's name buffer (8 char's) +; +; +; OUTPUT: +; AH = 00, No error +; 80H, Software error +; 81H, Hardware error +; 83H, Handle not found +; 84H, Invalid function +; 8FH, Invalid sub-function +; +; AL = 0 +; +; +; gga 8/21/87 +; +;------------------------------------------------------------------- + + Null_Handle_Name db 8 dup(0) ;null handle value ;an000; dms; + +handle_name proc + + push bx ; save some regs + push cx + push dx + push di + push si + push ds + + PUSH CS ;Set addressability to our tables @RH8 + POP DS ;Must restore DS for Set name @RH8 + + cmp al,hn_max_fcn ; al = 00 or 01, anything else = error + jbe hn_val_sf + +; invalid sub-function, report the error + + mov ah,ems_code8F ; invalid sub-function code + jmp hn_exit ; exit + +; check the handle for valid range + +hn_val_sf: + + cmp dx,num_handles-1 ; handle within range ? + jnae hn_range_ok ; yes, get down to business + + mov ah,ems_code83 ; handle not found + jmp hn_exit ; exit + +;------------------------ +; handle is within valid range, now see if it is valid handle (i.e. in use) + +hn_range_ok: + + push ax ; save fcn code + push dx ; save handle + + MOV AX,DX ;DX = handle id + MOV DX,TYPE H_LOOKUP_STRUC ;DI = entry's offset into + MUL DX ; the handle lookup table + MOV DI,AX ; + POP DX ; restore handle + POP AX ; restore fcn code + + CMP HANDLE_LOOKUP_TABLE.H_PAGES[DI],REUSABLE_HANDLE + JNE HN_IN_USE ;Is this handle valid (in use)? + ; No...error + mov ah,ems_code83 ; handle not found + jmp hn_exit ; return the error code + +HN_IN_USE: ;Check bank ID if in virutal mode + + mov bx,ax ;save ax ;an000; dms; + TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6 + JZ HN_VALID ; (i.e. bank swapping), then read @RH6 + MOV DX,IDREG ; the current bank ID. @RH6 + IN AL,DX ; @RH6 + CMP HANDLE_LOOKUP_TABLE.H_BANK[DI],AL ;If handle's bank ID @RH6 + JE HN_VALID ; is 0 (resident) or @RH6 + CMP HANDLE_LOOKUP_TABLE.H_BANK[DI],0 ; = requesters bank @RH6 + JE HN_VALID ; then OK @RH6 + ;Else invalid requester bank @RH6 + MOV AH,EMS_CODE83 ;Indicate handle not found @RH6 + JMP HN_EXIT + +;------------------------ +; find out if get or set operation + +hn_valid: + mov ax,bx ;restore ax ;an000; dms; + cmp al,sf_hn_get ; al = 00 means GET + je hn_get + + cmp al,sf_hn_set ; = 01 means SET + je hn_set + +; invalid sub-function, report the error + + mov ah,ems_code8F ; invalid sub-function code + jmp hn_exit ; exit + + + + page +;------------------------------------------------------------------- +; +; 5300 - GET sub-function +; ES:DI -> User's area where name is stored +;------------------------------------------------------------------- +hn_get: + ;Here DI = offset into h lookup + LEA SI,HANDLE_LOOKUP_TABLE ;Set the source SI to the handle's + ADD SI,DI ; name field in the handle lookup + ADD SI,H_NAME ; lookup table + + MOV DI,cs:[bp].IE_Saved_DI_Reg ;Restore the user's dest where + ; the handle name will be stored + + MOV CX,8 ; want to copy 8 characters + CLD ; make sure direction flag is right + REP MOVSB ; copy the string + + XOR AH,AH ; set good return code + JMP HN_EXIT ; exit + + + page +;------------------------------------------------------------------- +; +; 5301 - SET sub-function +; DS:SI -> User's area where name comes from +; +;------------------------------------------------------------------- + +hn_set: + + POP DS ;Restore the user's source where @RH6 + PUSH DS ; the handle name will come from + + +;------------------------ + push si ;save regs ;an000; dms; + push di ; ;an000; dms; + push cx ; ;an000; dms; + push es ; ;an000; dms; + + push cs ;swap segs for compare ;an000; dms; + pop es ; ;an000; dms; + + mov di,offset cs:Null_Handle_Name ;point to null handle name ;an000; dms; + mov cx,8 ;8 bytes to compare ;an000; dms; + cld + cli ;ints off ;an000; dms; + rep cmpsb ;null string entered? ;an000; dms; + sti ;ints on ;an000; dms; + + pop es ;restore regs ;an000; dms; + pop cx ; ;an000; dms; + pop di ; ;an000; dms; + pop si ; ;an000; dms; + je HN_Set_Null_Entered ;continue - don't look for match ;an000; dms; + + push dx + call hd_named_handle ; find out if name is in use + pop dx + + cmp ah,0 ; is return code good + je name_in_use + +HN_Set_Null_Entered: + +;------------------------ + ;Here DI = offset into h lookup + ADD DI,OFFSET HANDLE_LOOKUP_TABLE ;Set the dest. DI to the @RH6 + ADD DI,OFFSET H_NAME ; handle's name field in @RH6 + ; the handle lookup table @RH6 + + PUSH ES ;Make ES:DI -> destination in + PUSH CS ; the handle lookup table where + POP ES ; the name will be stored + + mov cx,8 ; want to copy 8 characters + cld ; clear DF to auto-increment + rep movsb ; copy the string + +; all done with the SET function, set good return code and exit + + pop es ; restore user's ES + xor ax,ax ; set good return code + jmp hn_exit + + +;------------------------ +name_in_use: + mov ah,ems_codea1 ; name is use error + + +hn_exit: + pop ds ; restore these registers + pop si + pop di + pop dx + pop cx + pop bx + + ret + +handle_name endp + + + + page +;------------------------------------------------------------------- +; +; 54 - get handle directory +; +; SUB-FCNS: +; AL = 00, get handle directory hd_directory +; 01, search for named handle hd_named_handle +; 02, get total handles hd_total_handles +; +;------------------------------------------------------------------- +handle_dir proc + + cmp al,sf_hd_get ; 00 get handle dir + je hd_directory + + cmp al,sf_hd_search ; 01 search for named handle + je hd_named_handle + + cmp al,sf_hd_total ; 02 get total number of handles + jne hd_invalid_sfcn ; must be an invalid function code + + jmp hd_total_handles ; go display total handles + + +; invalid sub-function, report the error + +hd_invalid_sfcn: + mov ah,ems_code8F ; invalid sub-function code + +; invalid sub-function, fall through to exit + +hd_exit: + + ret + + +;------------------------------------------------------------------- +; 5400 - get handle directory +; +; +; INPUT: +; AL = 00, get handle directory +; +; ES:DI -> caller's buffer for handle directory +; +; OUTPUT: +; AH = 00H, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; +; AL = number of entries in handle directory +; +; ES:DI -> handle directory +; +; dw ? ; handle number +; db 8 dup(?) ; handle name +; : +; : ; repeats AL times +; +;------------------------------------------------------------------- +hd_directory: + + push bx ; save some regs + push cx + push dx + push di + push si + push ds + + TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6 + JZ HD_LOOP_INIT ; (i.e. bank swapping), then read @RH6 + MOV DX,IDREG ; the current bank ID and save it. @RH6 + IN AL,DX ; @RH6 + MOV cs:BANKID,AL + + +; initialize some things for the loop +HD_LOOP_INIT: + mov di,cs:[bp].IE_Saved_DI_Reg ;restore users DI ;an000; dms; + xor al,al ; al = num entries + xor dx,dx ; dx = handle index + mov cx,NUM_HANDLES ; loop enough for all handles + cld ; make sure direction flag cleared + + push cs ; get cs + pop ds ; into ds + XOR SI,SI ; SI = offset into handle lookup @RH6 + ; table +hd_loop: + CMP HANDLE_LOOKUP_TABLE.h_pages[SI],REUSABLE_HANDLE + ; If handle not active, then @RH6 + je hd_next_hndl ; loop and look again +;------------------------- +; Active handle...if in virtual mode check bank ID @RH6 +;------------------------- + + TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6 + JZ HD_ACTIVE ; (i.e. bank swapping), then check @RH6 + MOV BL,cs:BANKID ; handle's bank id @RH6 + CMP HANDLE_LOOKUP_TABLE.H_BANK[SI],BL ;If handle's bank ID @RH6 + JE HD_Active ; is 0 (resident) or @RH6 + CMP HANDLE_LOOKUP_TABLE.H_BANK[SI],0 ; = requesters bank @RH6 + JE HD_Active ; then OK @RH6 + jmp HD_Next_Hndl ;Else skip to next one @RH6 + +;------------------------ +; found an active handle, copy info to directory +;------------------------ +hd_active: + mov es:word ptr[di],dx ; put handle number in directory + add di,2 ; move directory table pointer along, + ; must point to area for handle name now + + push cx ; save counter for outer loop + push si ; save si for outer loop + + mov cx,8 ; need to copy 8 chars + add si,offset Handle_LookUp_Table ;point to entry ;an000; dms; + add si,h_name ; make DS:SI -> handle name in lookup table + +rep movsb ; copy the string + + pop si ; restore si for outer loop + pop cx ; restore counter for outer loop + inc al ; increment entry count + +;------------------------ +; done with the copy +;------------------------ + +hd_next_hndl: + inc dx ; update handle index + add si,type h_lookup_struc ; point to next entry in lookup table + loop hd_loop ; look for more + + xor ah,ah ; good return code + +; all done, fall through to exit + +hd_exit00: + + pop ds ;restore these registers + pop si + pop di + pop dx + pop cx + pop bx + + ret + + + + page +;------------------------------------------------------------------- +; +; 5401 - Search for named handle sub-function +; +; +; INPUT: +; AL = 01, search for named handle +; +; DS:SI = Pointer to handle name to search for +; +; +; OUTPUT sub-fcn 01: Search for named handle +; +; AH = 00H, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; A0H, no matching handle found +; A1H, duplicate handle found +; +; DX = value of named handle +; +;------------------------------------------------------------------- + +hd_named_handle: + + push bx ; save some regs + push cx + push di + push si + push ds + push es ;an000; dms; + + TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6 + JZ HD1_LOOP_INIT ; (i.e. bank swapping), then read @RH6 + MOV DX,IDREG ; the current bank ID and save it. @RH6 + IN AL,DX ; @RH6 + MOV cs:BANKID,AL + + +; initialize some things for the loop +HD1_LOOP_INIT: + xor ah,ah ; good return code + xor dx,dx ; dx = handle index + mov cx,NUM_HANDLES ; loop enough for all handles + cld ; make sure direction flag cleared + + push cs ; get cs + pop es ; into es + XOR DI,DI ; DI = offset into handle lookup @RH6 + ; table @RH6 +hd1_loop: + CMP ES:HANDLE_LOOKUP_TABLE.h_pages[DI],REUSABLE_HANDLE + ; If handle not active, then @RH6 + je hd1_next_hndl ; loop and look again +;------------------------- +; Active handle...if in virtual mode check bank ID @RH6 +;------------------------- + + TEST MEMCARD_MODE,WSP_VIRT ;If using a card in virtual mode @RH6 + JZ HD1_ACTIVE ; (i.e. bank swapping), then check @RH6 + MOV BL,cs:BANKID ; handle's bank id @RH6 + CMP ES:HANDLE_LOOKUP_TABLE.H_BANK[DI],BL ;If handle's bank ID @RH6 + JE HD1_Active ; is 0 (resident) or @RH6 + CMP ES:HANDLE_LOOKUP_TABLE.H_BANK[DI],0 ; = requesters bank @RH6 + JE HD1_Active ; then OK @RH6 + jmp HD1_Next_Hndl ;Else skip to next one @RH6 +;------------------------ +; found an active handle, check the name +;------------------------ + +HD1_ACTIVE: + push cx ; save counter for outer loop + push si ; save si for outer loop + push di ; save di for outer loop + + mov cx,8 ; need to compare 8 chars + add di,offset Handle_LookUp_Table ;point to entry ;an000; dms; + add di,offset H_Name ; must point to area for handle name now;an000; dms; + +rep cmpsb ; compare the strings + + pop di ; restore di for outer loop + pop si ; restore si for outer loop + pop cx ; restore counter for outer loop + je hd_exit01 ; found a match, exit + +;------------------------ +; done with the check +;------------------------ + +hd1_next_hndl: + inc dx ; update handle index + add di,type h_lookup_struc ; point to next entry in lookup table + loop hd1_loop ; look for more + + + +; all done, if we fall through loop without finding a match, +; must report the error + + mov ah,ems_codea0 ; no matching handle + xor dx,dx ; invalid handle + +hd_exit01: + + + pop es ;restore these registers ;an000; dms; + pop ds + pop si + pop di + pop cx + pop bx + + ret + + + + page +;------------------------------------------------------------------- +; +; 5402 - Get total handles sub-function +; +; INPUT: +; AL = 02, get total handles +; +; +; OUTPUT: +; AH = 00H, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; +; BX = total number of handles (includes OS handle, 0) +; +;------------------------------------------------------------------- + +hd_total_handles: + + mov bx,NUM_HANDLES ; return number of handles + xor ah,ah ; good return code + +; all done, fall through to exit + +hd_exit02: + + ret ; return to caller + +handle_dir endp + + page +;------------------------------------------------------------------- +; +; 58 - Get mappable physical address array +; +; +; INPUT: +; AX = 5800h +; +; ES:DI -> mappable physical array address +; +; OUTPUT: +; AH = 00, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; +; CX = number of entries returned in the table below +; +; ES:DI -> DW ? ; phys_page_segment +; DW ? ; phys_page_number +; : +; : ; repeats CX times +; +;------------------------------------------------------------------- +address_array proc + + cmp al,Add_Get_Array ; subfunction 00 Get Mappable Physical ;an000; dms; + ; Address Array + je Address_Get_Physical_Address + + cmp al,Add_Get_Size ; subfunction 01 Get Mappable Physical ;an000; dms; + ; Address Array Entries + je Address_Get_Size_Entries + + mov ah,EMS_Code8F ; none of the above - invalid sub parm ;an000; dms; + + ret + + +Address_Get_Physical_Address: + + push si ; save some regs + push di ; save di ;an000; dms; + push ds ; save DS + + +; set up some things for the loop + + mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to handle area + + mov cx,map_count ; number of entries in table + + push cs ; make DS:SI -> array + pop ds + + lea si,map_table + + cld ; make sure direction flag is right + +copy_address_array: + + mov ax,DS:[si+phys_page_segment] + mov ES:[di],ax + add di,2 ; increment destination pointer + mov ax,DS:[si+phys_page_number] + mov ES:[di],ax + + add si,type mappable_phys_page_struct ; increment pointer + add di,2 ; increment destination pointer + + loop copy_address_array + + mov cx,map_count ; number of entries + xor ah,ah ; good return code + + pop ds ; restore DS + pop di ; restore di + pop si ; restore SI + + RET ; return to caller + +Address_Get_Size_Entries: + + mov cx,cs:Map_Count ; return the number of pages allocated ;an000; dms; + xor ax,ax ; clear error flag ;an000; dms; + ret ; return to caller ;an000; dms; + + +address_array endp + + + + page +;------------------------------------------------------------------- +; +; 59 - Get extended momory hardware information +; +;------------------------------------------------------------------- +hardware_info proc + + cmp ose_functions,ose_enabled ; first, check for fcns enabled + je hi_enabled ; + + + mov ah,EMS_CODEA4 ; access denied + jmp hi_exit ; exit + +hi_enabled: + cmp al,hi_info ; 5900 - hardware info fcn + je hi_info_fcn + + cmp al,hi_raw ; 5901 - unallocated raw page count + je hi_raw_fcn + + mov ah,EMS_CODE8F ; invalid sub-function + +hi_exit: + RET ; return to caller + + + page +;------------------------------------------------------------------- +; +; hi_info_fcn +; +;------------------------------------------------------------------- + +hi_info_fcn: + + mov di,cs:[bp].IE_Saved_DI_Reg ; get di register + + mov es:word ptr[di+0],1024 ; raw page size = 16KB + mov es:word ptr[di+2],0 ; number of alternate register sets + mov es:word ptr[di+4],type H_SAVE_STRUC ; size of save array + mov es:word ptr[di+6],0 ; number of DMA register sets + mov es:word ptr[di+8],1 ; 1 = no special DMA register sets + + xor ah,ah ; good return code + ret ; return to caller + + page +;------------------------------------------------------------------- +; +; hi_raw_fcn +; +;------------------------------------------------------------------- + +hi_raw_fcn: + + mov ah,get_free_pages ; function code to get free pages + + call q_pages ; pass this one through, since our + ; raw pages = 16 KB + ; this fcn returns exacly the same + ; regs as are needed here + + ret ; return to caller + +hardware_info endp + + page +;------------------------------------------------------------------- +; +; 5B - alternate map register set +; +;------------------------------------------------------------------- + + AM_ES_Save dw 0 ;ES save variable ;an000; dms; + AM_DI_Save dw 0 ;DI save variable ;an000; dms; + AM_Set_Flag db 0 ;set called flag ;an000; dms; + +alternate_map proc + + cmp ose_functions,ose_enabled ; first, check for fcns enabled + je am_enabled ; + + + mov ah,EMS_CODEA4 ; access denied + jmp am_exit ; exit + +am_enabled: + cmp al,am_get ; 5b00 - get alternate map register set + je _am_get + + cmp al,am_set ; 5b01 - set alternate map register set + je _am_set + + cmp al,am_size ; 5b02 - get alternate map save array size + je _am_size + + cmp al,am_alloc ; 5b03 - allocate alternate map register set + je _am_alloc + + cmp al,am_dealloc ; 5b04 - deallocate alternate map register set + je _am_dealloc + + cmp al,am_dma_alloc ; 5b05 - allocate DMA register set + je _am_dma_alloc + + cmp al,am_dma_enable ; 5b06 - enable DMA register set + je _am_dma_enable + + cmp al,am_dma_disable ; 5b07 - disable DMA register set + je _am_dma_disable + + cmp al,am_dma_dealloc ; 5b08 - deallocate DMA register set + je _am_dma_dealloc + + mov ah,EMS_CODE8F ; invalid sub-function + +am_exit: + ret ; return to caller + + + page +;------------------------------------------------------------------- +; +; _am_get +; +;------------------------------------------------------------------- +_am_get: + + cmp cs:AM_Set_Flag,0 ;flag set? ;an000; dms; + jne AM_Get_Continue ;yes ;an000; dms; + xor di,di ;signal set has not ;an000; dms; + mov es,di ; been performed ;an000; dms; + xor ah,ah ;signal good exit ;an000; dms; + jmp AM_Get_Exit ;exit routine ;an000; dms; + +AM_Get_Continue: + + mov di,cs:AM_DI_Save + mov es,cs:AM_ES_Save + mov cs:[bp].IE_Saved_DI_Reg,di;set instance table entry ;an000; dms; + + call GET_SUBFCN ; copy the save area info to user's buffer + + xor bl,bl ; bl = 0 for our implementation + ; this indicates to user that ES:DI + ; buffer has been filled in with save + ; area info +AM_Get_Exit: + + ret + + page +;------------------------------------------------------------------- +; +; _am_set +; +;------------------------------------------------------------------- +_am_set: + + push si + push ds + + cmp bl,null ; bl must be 0 for us + jne _am_set_error ; set error code and exit + + mov di,cs:[bp].IE_Saved_DI_Reg ; restore caller's DI, pointer to mapping control structure + + mov cs:AM_ES_Save,es ; save es value ;an000; dms; + mov cs:AM_DI_Save,di ; save di value ;an000; dms; + mov cs:AM_Set_Flag,01 ; flag indicates set performed ;an000; dms; + mov si,di ; restore_pgfrm_map expects DS:SI to point to save area + push es + pop ds + + call RESTORE_PGFRM_MAP + + xor ah,ah ; good return code + + jmp _am_set_exit + +_am_set_error: + mov ah,EMS_CODE9C ; fast regs not supported and BL != 0 + +_am_set_exit: + + pop ds + pop si + + ret + + page +;------------------------------------------------------------------- +; +; _am_size +; +;------------------------------------------------------------------- +_am_size: + + mov dx,type h_save_struc ; get size requirements for save area + + xor ah,ah ; good return code + + ret + + page +;------------------------------------------------------------------- +; +; _am_alloc +; +;------------------------------------------------------------------- +_am_alloc: + + + xor bl,bl ; We don't support this function + ; in hardware, so return 0. + ; This indicates we will do software + ; emulation of these register sets. + + xor ah,ah ; good return code + + ret + + page +;------------------------------------------------------------------- +; +; _am_dealloc - 5b04 +; +;------------------------------------------------------------------- +_am_dealloc: + + xor ah,ah ; assume good return code + + cmp bl,0 ; is this a deallocate for 0? + je _am_dealloc_exit ; yes, goo return code + + mov ah,EMS_CODE9C ; error code for dealloc of unsupported + ; register set + +_am_dealloc_exit: + + ret + + page +;------------------------------------------------------------------- +; +; _am_dma_alloc +; +;------------------------------------------------------------------- +_am_dma_alloc: + + xor ah,ah ; good return code + xor bl,bl ; no DMA sets available + + ret + + page +;------------------------------------------------------------------- +; +; _am_dma_enable +; +;------------------------------------------------------------------- +_am_dma_enable: + + mov ah,EMS_CODE9E ; dedicated DMA not supported + + ret + + page +;------------------------------------------------------------------- +; +; _am_dma_disable +; +;------------------------------------------------------------------- +_am_dma_disable: + + mov ah,EMS_CODE9E ; dedicated DMA not supported + + ret + + page +;------------------------------------------------------------------- +; +; _am_dma_dealloc +; +;------------------------------------------------------------------- +_am_dma_dealloc: + + xor ah,ah ; assume good return code + + cmp bl,null ; is the DMA channel 0? + je _am_dma_de_exit + + mov ah,EMS_CODE9C ; DMA register sets are not + ; supported and bl != 0 + +_am_dma_de_exit: + ret + + +alternate_map endp + + page +;------------------------------------------------------------------- +; +; 5D - enable/disable OS/E functions set functions +; +;------------------------------------------------------------------- +enable_os proc + + cmp al,os_enable ; fcn code for enable + je os_enable_fcn + + cmp al,os_disable ; fcn code for disable + je os_disable_fcn + + cmp al,os_access ; fcn code for access key return + je os_access_fcn + + mov ah,EMS_CODE8F ;invalid sub-function code error + + ret ; return to caller + + page +;------------------------------------------------------------------- +; +; 5d00 - enable OS/E function set +; +; INPUT: +; +; BX,CX = Access key +; +; OUTPUT: +; +; AH = 00h, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; A4H, access denied, incorrect access key supplied +; +;------------------------------------------------------------------- +os_enable_fcn: + +; find out if this is the first time + + cmp word ptr access_code[0],0 ; access_code = 0, means enabled + jne ose_check_code ; not 0, must check access code + + cmp word ptr access_code[2],0 ; access_code = 0, means enabled + jne ose_check_code ; not 0, must check access code + + call get_code ; get access code to return + + xor ah,ah ; good return code + jmp ose_exit + +; not the first time, must check access code + +ose_check_code: + + cmp word ptr access_code[0],bx ; does it match? + jne ose_bad ; no, return access denied error + + cmp word ptr access_code[2],cx ; get second word of access code + jne ose_bad ; no, return access denied error + +; access code was OK, enable functions and return no error condition + + mov word ptr ose_functions,ose_enabled ; reset enabled flag + + xor ah,ah ; good return code + jmp ose_exit ; all done, exit + +ose_bad: + mov ah,EMS_CODEA4 ; return access denied error code + +ose_exit: + ret ; return to caller + + + page +;------------------------------------------------------------------- +; +; 5d01 - disable OS/E function set +; +; INPUT: +; +; BX,CX = Access key +; +; OUTPUT: +; +; AH = 00h, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; A4H, access denied, incorrect access key supplied +; +;------------------------------------------------------------------- +os_disable_fcn: + +; find out if this is the first time + + cmp word ptr access_code[0],0 ; access_code = 0, means enabled + jne osd_check_code ; not 0, must check access code + + cmp word ptr access_code[2],0 ; access_code = 0, means enabled + jne osd_check_code ; not 0, must check access code + +; yes, first time, must set access code and disable fcns + + call get_code ; get access code to return + + mov word ptr ose_functions,ose_disabled ; disable fcns + + xor ah,ah ; good return code + jmp osd_exit + +; not the first time, must check access code + +osd_check_code: + + cmp word ptr access_code[0],bx ; does it match? + jne osd_bad ; no, return access denied error + + cmp word ptr access_code[2],cx ; get second word of access code + jne osd_bad ; no, return access denied error + +; access code was OK, enable functions and return no error condition + + mov word ptr ose_functions,ose_disabled ; disable functions + + xor ah,ah ; good return code + jmp osd_exit ; all done, exit + +osd_bad: + mov ah,EMS_CODEA4 ; return access denied error code + +osd_exit: + ret ; return to caller + + page +;------------------------------------------------------------------- +; +; 5d02 - return OS/E function set access code +; +; INPUT: +; +; BX,CX = Access key +; +; OUTPUT: +; +; AH = 00h, no error +; 80H, software error +; 81H, hardware error +; 84H, invalid function +; 8FH, invalid subfunction +; A4H, access denied, incorrect access key supplied +; +;------------------------------------------------------------------- +os_access_fcn: + +; check access code + + + cmp word ptr access_code[0],bx ; does it match? + jne osa_bad ; no, return access denied error + + cmp word ptr access_code[2],cx ; get second word of access code + jne osa_bad ; no, return access denied error + +; clear access code and return "no error" return code (AH = 00) + + xor ax,ax ; clear ax + mov word ptr access_code[0],ax ; clear access code + mov word ptr access_code[2],ax ; clear access code + + jmp osa_exit + +osa_bad: + mov ah,ems_codeA4 ; access denied error code + +osa_exit: + ret ; return to caller + + + + + page +;------------------------------------------------------------------- +; +; get_code - returns random access code in cx,dx and stores it in +; system variable access_code. Access_code is a double-word +; which is used to save the bx,cx combination making up the +; "password" for OS/E functions. +; +;------------------------------------------------------------------- + +get_code: + + push dx ; save dx + +; get a "random" number for first word of access code + +redo1: + call get_rand ; returns "random" num in dx + xor dx,xor_mask ; confuse it a little + + cmp dx,0 ; make sure we didn't end up w/0 + je redo1 + + mov word ptr access_code[0],dx ; save it away + mov bx,dx + +; get another one for second word of access code + +redo2: + call get_rand + add dx,dx ; confuse it a little + xor dx,xor_mask + + cmp dx,0 ; make sure we didn't end up w/0 + je redo2 + + mov word ptr access_code[2],dx ; save it away + mov cx,dx ; put second word in cx + + pop dx ; restore + + ret ; return to caller + + +;------------------------------------------------------------------- +; +; get_rand - returns a "random" number in dx +; +;------------------------------------------------------------------- +get_rand: + + push ax ; save some regs + push cx + +redo: + mov ah,read_clock ; function code to read clock + int dos_int ; read the time + ; keep DX since it changes the most + + cmp dx,0 ; did we end up with 0? + je redo ; yes, redo it ... never want 0 + + pop cx ; restore some regs + pop ax + + ret ; return to caller + +enable_os endp + diff --git a/v4.0/src/DEV/XMA2EMS/LIM40B.INC b/v4.0/src/DEV/XMA2EMS/LIM40B.INC new file mode 100644 index 0000000..1e7683f --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/LIM40B.INC @@ -0,0 +1,3468 @@ + + page +;========================================================================= +; This module contains all the EQU's, STRUC's, data, and routines necessary +; for LIMDMS.INC. +; This module is to be INCLUDE'd as part of LIMDMS.INC. +; +;========================================================================= + +;========================================================================= +;========== Begin EQUate Definitions ===================================== +;========================================================================= + +AAJ_Option_Max equ 1h ;max option value ;an000; dms; +AAJ_Segment equ 1h ;segment request value ;an000; dms; +AAJ_No_Pages_To_Map equ 0h ;0 page map request ;an000; dms; + +MAC_Stack_Status_Request equ 02h ;stack size request ;an000; dms; + +ER_Conv_Memory equ 00h ;conv. memory request ;an000; dms; +ER_EMS_Memory equ 01h ;EMS memory request ;an000; dms; +EMS_Page_Size_In_Bytes equ (16*1024)-1 ;page size in bytes ;an000; dms; +ER_Max_Type equ 01h ;max type possible ;an000; dms; +ER_Max_Function equ 01h ;max function possible ;an000; dms; +ER_Move equ 00h ;move data ;an000; dms; +ER_Exchange equ 01h ;exchange data ;an000; dms; +ER_EMS_Page_FE equ 0FEh ;phys. page FEh ;an000; dms; +ER_EMS_Page_FF equ 0FFh ;phys. page FFh ;an000; dms; +ER_Dest_EMS_Memory equ 01h ;bit 0 set ;an000; dms; +ER_Source_EMS_Memory equ 02h ;bit 1 set ;an000; dms; +ER_Up equ 00h ;signal forward move ;an000; dms; +ER_Down equ 0ffh ;signal reverse move +ER_10H equ 10h ;equ for 10h ;an000; dms; + +AR_Sub_Max equ 01h ;5ah max. sub functions ;an000; dms; + +;========================================================================= +;========== End EQUate Definitions ======================================= +;========================================================================= + + page +;========================================================================= +;========== Begin STRUC Definitions ====================================== +;========================================================================= + +Log_Phys_Map_Struc struc ;page structure ;an000; dms; + + Log_Page_Number dw ? ;logical page number ;an000; dms; + Phys_Page_Number_Seg dw ? ;physical page or seg ;an000; dms; + ; determined by AL +Log_Phys_Map_Struc ends + + +Map_And_Jump_Struc struc ;carries jump info. ;an000; dms; + + Target_Address dd ? ;jump address ;an000; dms; + Log_Phys_Map_Len db ? ;entry count in ;an000; dms; + ; Log_Phys_Map_Struct + Log_Phys_Map_Ptr dd ? ;Log_Phys_Map_Struct ptr;an000; dms; + +Map_And_Jump_Struc ends ;an000; dms; + + +Map_And_Call_Struc struc ;carries jump info. ;an000; dms; + + MAC_Target_Address dd ? ;jump address ;an000; dms; + MAC_New_Page_Map_Len db ? ;entry count in ;an000; dms; + ; Log_Phys_Map_Struct + ; for new map scheme + MAC_New_Page_Map_Ptr dd ? ;Log_Phys_Map_Struc ptr ;an000; dms; + ; for new map scheme + MAC_Old_Page_Map_Len db ? ;entry count in ;an000; dms; + ; Log_Phys_Map_Struc + ; for old map scheme + MAC_Old_Page_Map_Ptr dd ? ;Log_Phys_Map_Struc ptr ;an000; dms; + ; for old map scheme + MAC_Reserved dw 4 DUP (?) ;Used to restore map ;an000; dms; + ; context + +Map_And_Call_Struc ends ;an000; dms; + + +Move_Source_Dest_Struc struc ;structure for move ;an000; dms; + + Region_Length_Low_Word dw ? ; + Region_Length_High_Word dw ? ;length of region ;an000; dms; + + Source_Memory_Type db ? ;conv/EMS ;an000; dms; + Source_Handle dw ? ;handle if EMS, else 0 ;an000; dms; + Source_Initial_Offset dw ? ;offset of source region;an000; dms; + Source_Initial_Seg_Page dw ? ;logical page if EMS ;an000; dms; + ; seg if conv. + Dest_Memory_Type db ? ;conv/EMS ;an000; dms; + Dest_Handle dw ? ;handle if EMS, else 0 ;an000; dms; + Dest_Initial_Offset dw ? ;offset of source region;an000; dms; + Dest_Initial_Seg_Page dw ? ;logical page if EMS ;an000; dms; + ; seg if conv. +Move_Source_Dest_Struc ends ;end structure ;an000; dms; + +Realloc_Struc Struc ;BP addressible struc ;an000; dms; + + Realloc_Reserved db size Instance_Entry_Struc dup (?) ;an000; dms; + Realloc_Alloc_Byte db ? ;reserved ;an000; dms; + Realloc_Reg_DI dw ? ;reserved ;an000; dms; + Realloc_Handle dw ? ;handle ;an000; dms; + + Realloc_Page_Count dw ? ;new page count ;an000; dms; + Realloc_Page_Alloc dw ? ;pages to be allocated ;an000; dms; + Realloc_Page_Dealloc dw ? ;pages to be deallocated ;an000; dms; + + Realloc_Handle_Xref_Index dw ? ;index to end of handle table ;an000; dms; + Realloc_LookUp_Index dw ? ;index to applicable handle ;an000; dms; + Realloc_Mult dw ? ;multiplier ;an000; dms; + +Realloc_Struc Ends ;end structure ;an000; dms; + +AAJ_Struc Struc ;BP addressible struc ;an000; dms; + + AAJ_Reserved db size Instance_Entry_Struc dup (?) ;an000; dms; + AAJ_Xref_Pages dw ? ;save logical page count ;an000; dms; + AAJ_Handle dw ? ;saved handle ;an000; dms; + AAJ_Option db ? ;saved selector state ;an000; dms; + AAJ_LookUp_Index dw ? ;save index ;an000; dms; + AAJ_Mult dw ? ;multiplier ;an000; dms; + +AAJ_Struc Ends ;end structure ;an000; dms; + +MAC_Struc Struc ;BP addressible struc ;an000; dms; + + MAC_Reserved_Area db size Instance_Entry_Struc dup (?) ;an000; dms; + MAC_LookUp_Index dw ? ;save index ;an000; dms; + MAC_Xref_Pages dw ? ;save logical page count ;an000; dms; + MAC_Option db ? ;saved selector state ;an000; dms; + + EMS_Reg_ES dw ? ;ES reg ;an000; dms; + EMS_Reg_DS dw ? ;DS reg ;an000; dms; + EMS_Reg_FL dw ? ;FL reg ;an000; dms; + EMS_Reg_SI dw ? ;SI reg ;an000; dms; + EMS_Reg_DI dw ? ;DI reg ;an000; dms; + EMS_Reg_DX dw ? ;DX reg ;an000; dms; + EMS_Reg_CX dw ? ;CX reg ;an000; dms; + EMS_Reg_BX dw ? ;BX reg ;an000; dms; + + MAC_M_C_Data db size Map_And_Call_Struc dup (?) ;an000; dms; + MAC_M_C_Log db size Log_Phys_Map_Struc*Map_Count_Def dup (?) ;an000; dms; + MAC_Map_Table db size Mappable_Phys_Page_Struct*Map_Count_Def dup (?) ;an000; dms; + MAC_Mult dw ? ;multiplier ;an000; dms; + +MAC_Struc Ends ;end structure ;an000; dms; + + +ER_Struc Struc ;BP addressible struc ;an000; dms; + + ER_Reserved db size Instance_Entry_Struc dup (?) ;an000; dms; + ER_Direction_Flag db ER_Up ;default to forward move;an000; dms; + + ER_Sub_Function db ? ;save subfunction byte ;an000; dms; + + ER_Src_Abs_Beg_Low dw ? ;abs add of src EMS page;an000; dms; + ER_Src_Abs_Beg_High dw ? ; beginning of trf area;an000; dms; + ER_Src_Abs_End_Low dw ? ;abs add of src EMS page;an000; dms; + ER_Src_Abs_End_High dw ? ; end of trf area ;an000; dms; + + ER_Dst_Abs_Beg_Low dw ? ;abs add of src EMS page;an000; dms; + ER_Dst_Abs_Beg_High dw ? ; beginning of trf area;an000; dms; + ER_Dst_Abs_End_Low dw ? ;abs add of src EMS page;an000; dms; + ER_Dst_Abs_End_High dw ? ; end of trf area ;an000; dms; + + ER_Current_Move_Count dw ? ;bytes moved this time ;an000; dms; + + ER_Move_Xchg_Buffer1 db 10h dup (?) ;buffer for move/xchg ;an000; dms; + ER_Move_Xchg_Buffer2 db 10h dup (?) ;buffer for move/xchg ;an000; dms; + + ER_Move_Count_Low dw ? ;low word of count ;an000; dms; + ER_Move_Count_High dw ? ;high word of count ;an000; dms; + + ER_Source_Phys_Page dw ? ;page number of source ;an000; dms; + ER_Dest_Phys_Page dw ? ;page number of dest ;an000; dms; + + ER_Source_Page dw ? ;active source page ;an000; dms; + ER_Dest_Page dw ? ;active dest page ;an000; dms; + + ER_Source_Handle dw ? ;active handle ;an000; dms; + ER_Dest_Handle dw ? ;active handle ;an000; dms; + ; 10h byte moves + + ER_Save_Context_Buffer dw 2*Type Mappable_Phys_Page_Struct dup (0) ;room for 2 pgs;an000; dms; + + ER_Dest_Seg dw ? ;seg value of dest ;an000; dms; + ER_Source_Seg dw ? ;seg value of source ;an000; dms; + + ER_Dest_Off dw ? ;off value of dest ;an000; dms; + ER_Source_Off dw ? ;off value of source ;an000; dms; + + ER_Mem_Type dw ? ;memory type ;an000; dms; + + +ER_Struc Ends ;end structure ;an000; dms; + +;========================================================================= +;========== End STRUC Definitions ======================================== +;========================================================================= + + page +;========================================================================= +;========== Begin Macro Definitions ====================================== +;========================================================================= + + +;========================================================================= +; MAC_Expand_Stack_And_Copy : This routine will place data in the +; instance table by copying the data pointed +; at by ES:DI. +; +; Inputs : AX - Size of stack adjustment +; ES:DI - Pointer to data to be copied to stack +; +; Outputs : BP - data place in instance table +; +;========================================================================= + +MAC_Expand_Stack_And_Copy proc + + mov cx,ax ;get adjustment factor ;an000; dms; + shr cx,1 ;convert to word move ;an000; dms; + mov ax,es ;get data source seg ;an000; dms; + mov ds,ax ;place in ds ;an000; dms; + mov si,di ;get data source off ;an000; dms; + + mov ax,cs ;get dest. seg ;an000; dms; + mov es,ax ;place in es ;an000; dms; + mov di,bx ;get dest. off ;an000; dms; + + cli ;ints off ;an000; dms; + rep movsw ;move data to stack ;an000; dms; + sti ;ints on ;an000; dms; + + ret ;end routine ;an000; dms; + +MAC_Expand_Stack_And_Copy endp + + page +;========================================================================= +; MAC_Shrink_Stack_And_Copy : This routine move data from the instance +; table and place it at ES:DI. +; +; Inputs : AX - Size of stack adjustment +; ES:DI - Pointer to where data is to be copied +; +; Outputs : BP - data removed from instance table +; +;========================================================================= + +MAC_Shrink_Stack_And_Copy proc + + mov cx,ax ;get adjustment factor ;an000; dms; + mov ax,cs ;get data source seg ;an000; dms; + mov ds,ax ;place in ds ;an000; dms; + mov si,bx ;get data source off ;an000; dms; + mov ax,cx ;save count across move ;an000; dms; + shr cx,1 ;convert to word move ;an000; dms; + + cli ;ints off ;an000; dms; + rep movsw ;move data from stack ;an000; dms; + sti ;ints on ;an000; dms; + + ret ;end routine ;an000; dms; + +MAC_Shrink_Stack_And_Copy endp + + +;========================================================================= +;========== End Macro Definitions ======================================== +;========================================================================= + + page +;========================================================================= +;========== Begin Generic PROC Definitions =============================== +;========================================================================= + +;========================================================================= +; Map_Pages : This routine will map the pages being +; requested in the struc pointed to by +; DS:SI. +; +; Inputs : ES:DI - Pointer to data in Log_Phys_Map_Struc format +; CX - Count of data iterations in ES:DI +; DX - handle +; BX - page count for handle +; AL - option +; +; Outputs : Revised map +; AH - 0 = no error +; > 0 = error +;========================================================================= + +Map_Pages proc ; ;an000; dms; + + push si ;save reg ;an000; dms; + + mov si,ax ;save option ;an000; dms; + cmp cx,AAJ_No_Pages_To_Map ;no pages? ;an000; dms; + je Map_Error_Exit ;yes - exit loop ;an000; dms; + +Map_Loop_Continue: + + cmp [di].Log_Page_Number,bx ;logical page out of ;an000; dms; + ; range? + jbe Map_Get_Segment ;no - in range ;an000; dms; + mov ah,EMS_Code8A ;yes - out of range ;an000; dms; + jmp Map_Error_Exit ;exit routine ;an000; dms; + +Map_Get_Segment: + + cmp si,AAJ_Segment ;segment request? ;an000; dms; + mov ax,[di].Phys_Page_Number_Seg ;get physical page ;an000; dms; + jne Map_Page_Request ;no - page request ;an000; dms; + push dx ;save handle + mov dx,[di].Phys_Page_Number_Seg ;get segment ;an000; dms; + call Get_Phys_Seg_Page ;get the associated ;an000; dms; + ; page for the segment + mov ax,dx ;place page in ax ;an000; dms; + pop dx ;restore handle + jnc Map_Page_Request ;no error - continue ;an000; dms; + mov ah,EMS_Code8B ;phys page not found ;an000; dms; + jmp Map_Error_Exit ;exit routine ;an000; dms; + +Map_Page_Request: + + push bx ;save bx across call ;an000; dms; + mov bx,[di].Log_Page_Number ;logical page to map ;an000; dms; + call Map_L_To_P ;map the page ;an000; dms; + pop bx ;restore bx ;an000; dms; + or ah,ah ;error? ;an000; dms; + jnz Map_Error_Exit ;pass error on & exit ;an000; dms; + add di,Type Log_Phys_Map_Struc ;adjust pointer ;an000; dms; + loop Map_Loop_Continue ;continue loop ;an000; dms; + xor ax,ax ;signal good finish ;an000; dms; + +Map_Error_Exit: + + pop si ;restore reg ;an000; dms; + + ret ;return to caller ;an000; dms; + +Map_Pages endp ;end proc ;an000; dms; + + + page +;========================================================================= +; Get_Phys_Seg_Page : This routine will obtain the physical page +; number for a given segment. +; +; Inputs : DX - Segment value +; Outputs : DX - Physical page number +; CY - Error +; NC - No error +;========================================================================= + +Get_Phys_Seg_Page proc ;begin routine ;an000; dms; + + push ax ;save regs ;an000; dms; + push cx ; ;an000; dms; + push di ; ;an000; dms; + + cli ;ints off ;an000; dms; + mov di,offset Map_Table ;point to table map ;an000; dms; + mov cx,Map_Count ;number of table entries;an000; dms; + sti ;ints on ;an000; dms; + +GPSP_Loop: + + cli ;ints off ;an000; dms; + cmp dx,cs:[di].Phys_Page_Segment ;segment match? ;an000; dms; + je GPSP_Got_Segment ;yes ;an000; dms; + add di,Type Mappable_Phys_Page_Struct ;adjust pointer ;an000; dms; + loop GPSP_Loop ;continue search ;an000; dms; + +GPSP_Got_Segment: + + sti ;ints on ;an000; dms; + cmp cx,0 ;data found? ;an000; dms; + je GPSP_Not_Found ;exit with error ;an000; dms; + mov dx,cs:[di].Phys_Page_Number ;exit with page number ;an000; dms; + clc ;clear cy ;an000; dms; + jmp GPSP_Found ;exit ;an000; dms; + +GPSP_Not_Found: + + stc ;signal error ;an000; dms; + +GPSP_Found: ;exit ;an000; dms; + + pop di ;restore regs ;an000; dms; + pop cx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +Get_Phys_Seg_Page endp ;end proc ;an000; dms; + + +;========================================================================= +;========== End Generic PROC Definitions ================================= +;========================================================================= + + + + page + +;------------------------------------------------------------------- +; Reallocate Pages - Function 18 +; +; Entry - AX = 51?? +; BX = count of new allocation pages +; DX = handle +; +; Exit - AH = status +; BX = new page count +; if error - original page count +;------------------------------------------------------------------- +reallocate proc + + push cx ;save affected regs ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + + push ds ;save segments ;an000; dms; + push es ; ;an000; dms; + + mov ax,cs ;get code segment ;an000; dms; + mov ds,ax ;put int ds and ;an000; dms; + mov es,ax ; es ;an000; dms; + + + mov cs:[bp].Realloc_Page_Count,bx ;new page count ;an000; dms; + mov cs:[bp].Realloc_Handle,dx ;handle ;an000; dms; + + + + mov ax,cs:[bp].Realloc_Handle ;get handle for search ;an000; dms; + mov cs:[bp].Realloc_Mult,Type H_LookUp_Struc;handle lookup table ;an000; dms; + mul cs:[bp].Realloc_Mult ;obtain index position ;an000; dms; + mov cs:[bp].Realloc_LookUp_Index,ax ;index to handle ;an000; dms; + mov di,ax ;place index in si ;an000; dms; + mov dx,cs:[bp].Realloc_Handle ;get handle number ;an000; dms; + + + cmp dx,Num_Handles-1 ;dx > handle count? ;an000; dms; + jbe Realloc_Handle_Search ;handle within range ;an000; dms; + mov ah,EMS_Code83 ;EMS handle non-existent;an000; dms; + jmp Realloc_Error_Exit ;exit program ;an000; dms; + +Realloc_Handle_Search: + + cmp Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;handle allocated ;an000; dms; + jne Realloc_Status_Of_Handle ;handle good ;an000; dms; + mov ah,EMS_Code83 ;EMS handle not alloc ;an000; dms; + jmp Realloc_Error_Exit ;exit program ;an000; dms; + +Realloc_Status_Of_Handle: + + + mov ax,Handle_LookUp_Table.H_Pages[di] ;get current page count ;an000; dms; + sub ax,cs:[bp].Realloc_Page_Count ;more or less pages? ;an000; dms; + jc Realloc_More_Pages ;more pages to alloc ;an000; dms; + +Realloc_Less_Pages: + + mov bx,ax ;pages to deallocate ;an000; dms; + mov cs:[bp].Realloc_Page_Dealloc,ax ;save dealloc value ;an000; dms; + + mov si,Handle_LookUp_Table.H_Pal_Ptr[di] ;get start of links ;an000; dms; + mov cx,Handle_LookUp_Table.H_Pages[di] ;current pages allocated;an000; dms; + sub cx,bx ;pages to remain alloc ;an000; dms; + + +Realloc_Dealloc_Loop1: + + cmp cx,0 ;pages? ;an000; dms; + je Realloc_Dealloc_Loop1_Exit ;no - exit ;an000; dms; + shl si,1 + mov si,Page_Alloc_List[si] ;get next pointer ;an000; dms; + dec cx ;dec loop count ;an000; dms; + jmp Realloc_Dealloc_Loop1 ;continue ;an000; dms; + +Realloc_Dealloc_Loop1_Exit: + +;***** Adjust pointers ***** + + mov cx,cs:[bp].Realloc_Page_Dealloc ;get dealloc count ;an000; dms; + mov ax,cs:PAL_Free_Ptr ;get the free ptr ;an001; dms; + cmp cx,0 ;0 pages to dealloc? ;an001; dms; + je Realloc_Dealloc_Loop2_Exit1 ;yes - bypass dealloc ;an001; dms; + mov cs:PAL_Free_Ptr,si ;no - set new free ptr ;an001; dms; + dec cx ;don't loop past last pg;an001; dms; + +Realloc_Dealloc_Loop2: + + cmp cx,0 ;end of deallocate? ;an000; dms; + je Realloc_Dealloc_Loop2_Exit ;yes - exit ;an000; dms; + shl si,1 ;get index entry ;an001; dms; + mov si,Page_Alloc_List[si] ;get next ptr ;an001; dms; + dec cx ;decrement counter ;an000; dms; + jmp Realloc_Dealloc_Loop2 + +Realloc_Dealloc_Loop2_Exit: + + shl si,1 ;get index entry ;an001; dms; + mov Page_Alloc_List[si],ax ;pt. last page to orig. ;an001; dms; + ; free ptr. + +Realloc_Dealloc_Loop2_Exit1: + + mov ax,cs:[bp].Realloc_Page_Count ;new page count ;an000; dms; + mov Handle_LookUp_Table.H_Pages[di],ax ; ;an000; dms; + + mov ax,cs:[bp].Realloc_Page_Dealloc ;adj. value ;an000; dms; + add cs:Free_Pages,ax ;free up page ;an000; dms; + + mov bx,cs:[bp].Realloc_Page_Count ;pass back page request ;an000; dms; + xor ah,ah ;clear error ;an000; dms; + jmp Realloc_Exit ;exit ;an000; dms; + +Realloc_More_Pages: + + mov cx,cs:[bp].Realloc_Page_Count ;get page request count ;an000; dms; + mov di,cs:[bp].Realloc_LookUp_Index ;get LookUp Table ptr ;an000; dms; + mov ax,Handle_LookUp_Table.H_Pages[di] ;get current page count ;an000; dms; + sub cx,ax ;get additional pages ;an000; dms; + mov cs:[bp].Realloc_Page_Alloc,cx ;new pages to alloc ;an000; dms; + cmp cx,Free_Pages ;> pages remaining? ;an000; dms; + jbe Realloc_Pages ;reallocate pages ;an000; dms; + mov ah,EMS_Code87 ;Too few pages avail ;an000; dms; + jmp Realloc_Error_Exit ;exit prog ;an000; dms; + +Realloc_Pages: + + mov cx,Handle_LookUp_Table.H_Pages[di] ;current pages allocated;an000; dms; + cmp cx,0 ;any pages? ;an000; dms; + jne Realloc_More_Pages_Cont ;yes ;an000; dms; + cmp cs:[bp].Realloc_Page_Alloc,0 ;any pages requested? ;an000; dms; + je Realloc_Alloc_Loop1_Exit ;continue ;an000; dms; + + mov cx,cs:[bp].Realloc_Page_Alloc ;get new page count ;an001; dms; + cli ;ints off ;an001; dms; + call EMS_Page_Contig_Chk ;contig pages avail? ;an001; dms; + jnc Realloc_New_Pages + mov ah,EMS_Code87 ;Too few pages avail ;an000; dms; + sti ;ints on ;an001; dms; + jmp Realloc_Error_Exit ;exit prog ;an000; dms; + +Realloc_New_Pages: + + call EMS_Link_Set ;set up page list ;an001; dms; + + mov Handle_LookUp_Table.H_Pal_Ptr[di],si ;set table to pointer ;an000; dms; + mov Handle_LookUp_Table.H_Pages[di],cx ;new page count ;an000; dms; + mov bx,cs:[bp].Realloc_Page_Count ;return new page count ;an001; dms; + sub cs:Free_Pages,bx ;new free count ;an000; dms; + sti ;ints on ;an001; dms; + xor ax,ax ;clear error flag ;an001; dms; + + jmp Realloc_Exit ;exit routine ;an001; dms; + + +Realloc_More_Pages_Cont: + + dec cx + mov si,Handle_LookUp_Table.H_Pal_Ptr[di] ;get start of links ;an000; dms; + +Realloc_Alloc_Loop1: + cmp cx,0 ;at end ;an000; dms; + je Realloc_Alloc_Loop1_Exit ;yes ;an000; dms; + shl si,1 ;word entry ;an000; dms; + mov si,Page_Alloc_List[si] ;get next pointer ;an000; dms; + dec cx ;decrement loop count ;an000; dms; + jmp Realloc_Alloc_Loop1 ;continue ;an000; dms; + +Realloc_Alloc_Loop1_Exit: + + mov cx,cs:[bp].Realloc_Page_Alloc ;new pages to alloc ;an000; dms; + cmp cx,0 ;pages requested? ;an001; dms; + je Realloc_Alloc_Exit ;no - exit routine ;an001; dms; + + mov bx,si ;save si ;an001; dms; + cli ;ints off ;an001; dms; + call EMS_Page_Contig_Chk ;contig pages? ;an001; dms; + jnc Realloc_Next_Pages ;yes ;an001; dms; + mov ah,EMS_Code87 ;Too few pages avail ;an000; dms; + sti ;ints on ;an001; dms; + jmp Realloc_Error_Exit ;exit prog ;an000; dms; + +Realloc_Next_Pages: + +;;;; mov ax,si ;ptr to new list ;an001; dms; +;;;; inc ax ;contig to new links? ;an001; dms; +;;;; cmp ax,bx ; ;an001; dms; +;;;; je Realloc_Next_Pages1 ;yes continue ;an001; dms; +;;;; mov ah,EMS_Code87 ;Too few pages avail ;an000; dms; +;;;; sti ;ints on ;an001; dms; +;;;; jmp Realloc_Error_Exit ;exit prog ;an000; dms; + +Realloc_Next_Pages1: + + call EMS_Link_Set ;set up page list ;an001; dms; + mov ax,si ;ptr to new list ;an001; dms; + mov si,bx ;end of old list ;an001; dms; + shl si,1 ;index entry ;an001; dms; + mov Page_Alloc_List[si],ax ;pick up new links ;an001; dms; + +Realloc_Alloc_Exit: + + mov bx,cs:[bp].Realloc_Page_Alloc ;additional pages ;an001; dms; + sub cs:Free_Pages,bx ;new free count ;an000; dms; + mov bx,cs:[bp].Realloc_Page_Count ;pass back page request ;an000; dms; + mov Handle_LookUp_Table.H_Pages[di],bx ;new page count ;an000; dms; + sti ;ints on ;an001; dms; + xor ah,ah ;clear ah ;an000; dms; + jmp Realloc_Exit ;exit ;an000; dms; + + +Realloc_Error_Exit: + + cli ;ints off ;an000; dms; + mov si,cs:[bp].Realloc_LookUp_Index ;get handle index ;an000; dms; + mov bx,Handle_LookUp_Table.H_Pages[si] ;get orig. count ;an000; dms; + mov Handle_LookUp_Table.H_Pages[si],bx ;new page count ;an000; dms; + sti ;ints on ;an000; dms; + +Realloc_Exit: + + pop es ;restore segments ;an000; dms; + pop ds ; ;an000; dms; + + pop si ;restore regs ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +reallocate endp + + + + page +;========================================================================= +;=============== Function 55h Logic - Alter Page Map & Jump ============= +;========================================================================= +;========================================================================= +; Alter_And_Jump - This routine alters the page map and jumps +; to the specified address. +; +; Inputs : AH - 55h (Alter page map & jump) +; AL - Physical page number/segment selector +; 0 = Physical page numbers specified +; 1 = Segment addresses specified in lieu of +; physical page numbers +; DX - handle number +; DS:SI - Pointer to map and jump structure +; (see Map_And_Jump_Struct above) +; +; Outputs : Revised map +; AH - Non-zero if error +; +;========================================================================= +Alter_And_Jump proc ;modify map ;an000; dms; + + push bx ;save regs for jump ;an000; dms; + push cx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + + pushf ;save flags ;an000; dms; + push ds ;save segments ;an000; dms; + push es ; ;an000; dms; + + mov bx,cs ;get code segment ;an000; dms; + mov es,bx ; es ;an000; dms; + + mov cs:[bp].AAJ_Handle,dx ;save handle ;an000; dms; + mov cs:[bp].AAJ_Option,al ;save selector option ;an000; dms; + + + + cmp dx,Num_Handles-1 ;dx > handle count ;an000; dms; + jbe AAJ_Check_Reusable ;continue test ;an000; dms; + mov ah,EMS_Code83 ;EMS handle bad ;an000; dms; + jmp AAJ_Error_Exit ;exit routine ;an000; dms; + +AAJ_Check_Reusable: + + mov ax,dx ;get handle ;an000; dms; + mov cs:[bp].AAJ_Mult,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul cs:[bp].AAJ_Mult ;obtain index position ;an000; dms; + mov cs:[bp].AAJ_LookUp_Index,ax ;index to handle ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + + cli ;ints off ;an000; dms; + mov ax,Handle_LookUp_Table.H_Pages[di] ;get logical page count ;an000; dms; + mov cs:[bp].AAJ_Xref_Pages,ax ;save logical page count;an000; dms; + sti ;ints on ;an000; dms; + cmp Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;handle allocated ;an000; dms; + jne AAJ_Good_Handle ;handle good ;an000; dms; + mov ah,EMS_Code83 ;EMS handle bad ;an000; dms; + jmp AAJ_Error_Exit ;exit routine ;an000; dms; + +AAJ_Good_Handle: + + cmp cs:[bp].AAJ_Option,AAJ_Option_Max ;option in range? ;an000; dms; + jbe AAJ_Good_Option ;option good ;an000; dms; + mov ah,EMS_Code8F ;bad option ;an000; dms; + jmp AAJ_Error_Exit ;exit routine ;an000; dms; + +AAJ_Good_Option: + + les di,[si].Log_Phys_Map_Ptr ;point to map data ;an000; dms; + xor cx,cx ;clear loop counter ;an000; dms; + mov cl,[si].Log_Phys_Map_Len ;get loop count ;an000; dms; + mov dx,cs:[bp].AAJ_Handle ;get handle for call ;an000; dms; + mov bx,cs:[bp].AAJ_Xref_Pages ;logical page count ;an000; dms; + xor ah,ah ;clear high word ;an000; dms; + mov al,cs:[bp].AAJ_Option ;option selected ;an000; dms; + call Map_Pages ;map the pages requested;an000; dms; + or ah,ah ;error? ;an000; dms; + jnz AAJ_Error_Exit ;exit with error cond. ;an000; dms; + +AAJ_Loop_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + popf ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + mov cs:[bp].IE_Alloc_Byte,Unallocated ;deallocate instance ;an000; dms; + + jmp dword ptr [si].Target_Address ;jump to address & run ;an000; dms; + +AAJ_Error_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + popf ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + + ret ;return to caller ;an000; dms; + +Alter_And_Jump endp ;end proc ;an000; dms; + + + + page +;========================================================================= +;=============== Function 56h Logic - Alter Page Map & Call ============= +;========================================================================= + + + +;========================================================================= +; Alter_And_Call - This routine alters the page map and calls +; the specified address. The mapping context +; is saved on entry to the routine and restored +; on exit from the routine. +; +; Inputs : AH - 56h (Alter page map & call) +; AL - Physical page number/segment selector +; 0 = Physical page numbers specified +; 1 = Segment addresses specified in lieu of +; physical page numbers +; 2 = Give minimum required stack size +; DX - handle number +; DS:SI - Pointer to map and jump structure +; (see Map_And_Call_Struc above) +; +; Outputs : Revised map +; AH - Non-zero if error +; BX - Function 2 = size in bytes needed for stack +; +;========================================================================= + + +Alter_And_Call proc ;modify map & call ;an000; dms; + + cmp al,MAC_Stack_Status_Request ;stack report? ;an000; dms; + je MAC_Calc_Stack_Status ;yes ;an000; dms; + jb MAC_Alter_And_Call ;no - new mapping ;an000; dms; + mov ah,EMS_Code8F ;error occurred ;an000; dms; + jmp MAC_Stack_Exit ;exit routine ;an000; dms; + +MAC_Calc_Stack_Status: + + mov bx,8h ;room for call address ;an000; dms; + ; and return address + xor ax,ax ;signal no error ;an000; dms; + jmp MAC_Stack_Exit ;exit routine ;an000; dms; + +MAC_Alter_And_Call: + + cli ;ints off ;an000; dms; + mov cs:[bp].EMS_Reg_BX,bx ; ;an000; dms; + mov bx,ax ;save ax across flags ;an000; dms; + lahf ;move flags to ah ;an000; dms; + mov cs:[bp].EMS_Reg_FL,ax ;save flags ;an000; dms; + mov ax,bx ;restore ax ;an000; dms; + mov cs:[bp].EMS_Reg_CX,cx ; ;an000; dms; + mov cs:[bp].EMS_Reg_DX,dx ; ;an000; dms; + mov cs:[bp].EMS_Reg_DI,di ; ;an000; dms; + mov cs:[bp].EMS_Reg_SI,si ; ;an000; dms; + mov cs:[bp].EMS_Reg_DS,ds ; ;an000; dms; + mov cs:[bp].EMS_Reg_ES,es ; ;an000; dms; + + mov cs:[bp].MAC_Option,al ;save option ;an000; dms; + sti ;ints on ;an000; dms; + cmp dx,Num_Handles-1 ;dx > handle count ;an000; dms; + jbe MAC_Check_Reusable ;continue test ;an000; dms; + mov ah,EMS_Code83 ;EMS handle bad ;an000; dms; + jmp MAC_Error_Exit ;exit routine ;an000; dms; + +MAC_Check_Reusable: + + mov ax,dx ;get handle ;an000; dms; + mov cs:[bp].MAC_Mult,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul cs:[bp].MAC_Mult ;obtain index position ;an000; dms; + mov cs:[bp].MAC_LookUp_Index,ax ;index to handle ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + + cli ;ints off ;an000; dms; + mov ax,Handle_LookUp_Table.H_Pages[di] ;get logical page count ;an000; dms; + mov cs:[bp].MAC_Xref_Pages,ax ;save logical page count;an000; dms; + cmp Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;handle allocated ;an000; dms; + sti ;ints on ;an000; dms; + jne MAC_Verify_New_Count ;handle good ;an000; dms; + mov ah,EMS_Code83 ;EMS handle bad ;an000; dms; + jmp MAC_Error_Exit ;exit routine ;an000; dms; + +MAC_Verify_New_Count: + + cli ;ints off ;an000; dms; + mov ax,Map_Count ;get phys. page count ;an000; dms; + sti ;ints on ;an000; dms; + cmp [si].MAC_New_Page_Map_Len,al ;> physical pages ;an000; dms; + jbe MAC_Verify_Old_Count ;no - continue ;an000; dms; + mov ah,EMS_Code8B ;out of range ;an000; dms; + jmp MAC_Error_Exit ;exit routine ;an000; dms; + +MAC_Verify_Old_Count: + + cli ;ints off ;an000; dms; + mov ax,Map_Count ;get phys. page count ;an000; dms; + sti ;ints on ;an000; dms; + cmp [si].MAC_Old_Page_Map_Len,al ;> physical pages ;an000; dms; + jbe MAC_Do_Alter_and_Call ;no - continue ;an000; dms; + mov ah,EMS_Code8B ;yes - error ;an000; dms; + jmp MAC_Error_Exit ;exit routine ;an000; dms; + +MAC_Do_Alter_And_Call: + + jmp MAC_Build_Stack_And_Map ;build stack and map ;an000; dms; + ; new pages +MAC_Return_Routine: + + jmp MAC_Strip_Stack_And_Map ;restore data strucs ;an000; dms; + ; and map old pages + +MAC_Exit: +MAC_Error_Exit: + + cli ;ints off ;an000; dms; + mov bx,ax ;save ax ;an000; dms; + mov ax,cs:[bp].EMS_Reg_FL ;obtain entry flag stat ;an000; dms; + sahf ;put in flags reg ;an000; dms; + mov ax,bx ;restore ax ;an000; dms; + mov bx,cs:[bp].EMS_Reg_BX ; ;an000; dms; + mov cx,cs:[bp].EMS_Reg_CX ; ;an000; dms; + mov dx,cs:[bp].EMS_Reg_DX ; ;an000; dms; + mov di,cs:[bp].EMS_Reg_DI ; ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ; ;an000; dms; + mov ds,cs:[bp].EMS_Reg_DS ; ;an000; dms; + mov es,cs:[bp].EMS_Reg_ES ; ;an000; dms; + sti ;ints on ;an000; dms; + +MAC_Stack_Exit: + + ret ;return to caller ;an000; dms; + + +;========================================================================= +; MAC_Build_Stack_And_Map : This routine will build the required +; stack structure for a re-entrant +; routine and map the new pages. +; +; Inputs : DS:SI - Pointer to data in Map_And_Call_Struc format +; +; Outputs : BP - Instance table to reflect data copyied to it +; New mapped pages +; AH - 0 = no error +; >0 = error (determined by Map_Pages) +; +; Instance Table carries this data: Old Map Data +; New Map Data +; Map & Call Data +; Context +;========================================================================= + +MAC_Build_Stack_And_Map: + + mov cs:[bp].EMS_Reg_DS,ds ;save DS ;an000; dms; + mov cs:[bp].EMS_Reg_SI,si ;save SI ;an000; dms; + + mov ax,word ptr [si].MAC_Old_Page_Map_Ptr[+2];get the segment ;an000; dms; + mov es,ax ; of the old map ;an000; dms; + mov di,word ptr [si].MAC_Old_Page_Map_Ptr[+0];get its offset ;an000; dms; + + mov al,[si].MAC_Old_Page_Map_Len ;get length of data ;an000; dms; + cbw ;convert to word ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,Type Log_Phys_Map_Struc ;struc size + mul bx ;get total byte count ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Log ;offset in struc ;an000; dms; + sti ;ints on ;an000; dms; + add bx,bp ;actual offset ;an000; dms; + call MAC_Expand_Stack_And_Copy ;set up stack for ;an000; dms; + ; copy of data and + ; copy the data + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov ax,word ptr [si].MAC_New_Page_Map_Ptr[+2];get the segment ;an000; dms; + mov es,ax ; of the old map ;an000; dms; + mov di,word ptr [si].MAC_New_Page_Map_Ptr[+0];get its offset ;an000; dms; + + mov al,[si].MAC_New_Page_Map_Len ;get length of data ;an000; dms; + cbw ;conver to word ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,Type Log_Phys_Map_Struc ;struc size + mul bx ;get total byte count ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Log ;Ptr in struc ;an000; dms; + add bx,size MAC_M_C_Log/2 ;next entry ;an000; dms; + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Expand_Stack_And_Copy ;set up stack for ;an000; dms; + ; copy of data and + ; copy the data + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov ax,ds ;move seg of data to ;an000; dms; + mov es,ax ; es ;an000; dms; + mov di,si ;move off of data ;an000; dms; + mov ax,Type Map_And_Call_Struc ;get size of structure ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Data + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Expand_Stack_And_Copy ;set up stack for ;an000; dms; + ; copy of data and + ; copy the data + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov ax,cs ;get seg of context ;an000; dms; + mov es,ax ; in es ;an000; dms; + cli ;ints off ;an000; dms; + mov di,offset cs:Map_Table ;get offset of context ;an000; dms; + mov ax,Map_Count ;get context entry count;an000; dms; + sti ;ints on ;an000; dms; + xor dx,dx ;clear dx ;an000; dms; + mov bx,Type Mappable_Phys_Page_Struct ;get struc size ;an000; dms; + mul bx ;get size in bytes ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset cs:MAC_Map_Table + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Expand_Stack_And_Copy ;set up stack for ;an000; dms; + ; copy of data and + ; copy the data + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + push cs ;save return segment ;an000; dms; + mov ax,offset MAC_Return_Routine ;save return offset ;an000; dms; + push ax ; ;an000; dms; + + mov ax,word ptr [si].MAC_Target_Address[+2] ;get seg of call far ;an000; dms; + mov bx,word ptr [si].MAC_Target_Address[+0] ;get offset of call far ;an000; dms; + push ax ;put on stack ;an000; dms; + push bx ; ;an000; dms; + + les di,[si].MAC_New_Page_Map_Ptr ;set up for call ;an000; dms; + xor cx,cx ;clear cx ;an000; dms; + mov cl,[si].MAC_New_Page_Map_Len ;get array size ;an000; dms; + mov dx,cs:[bp].EMS_Reg_DX ;get handle for call ;an000; dms; + mov bx,cs:[bp].MAC_Xref_Pages ;get handle page count ;an000; dms; + xor ah,ah ;clear high word ;an000; dms; + mov al,cs:[bp].MAC_Option ;get option ;an000; dms; + + call Map_Pages ;map the new pages ;an000; dms; + or ah,ah ;error? ;an000; dms; + jnz MAC_Error_Strip_Stack ;take data off stack ;an000; dms; + + cli ;ints off ;an000; dms; + mov ax,cs:[bp].EMS_Reg_FL ;obtain entry flag stat ;an000; dms; + sahf ;put in flags reg ;an000; dms; + mov bx,cs:[bp].EMS_Reg_BX ; ;an000; dms; + mov cx,cs:[bp].EMS_Reg_CX ; ;an000; dms; + mov dx,cs:[bp].EMS_Reg_DX ; ;an000; dms; + mov di,cs:[bp].EMS_Reg_DI ; ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ; ;an000; dms; + mov ds,cs:[bp].EMS_Reg_DS ; ;an000; dms; + mov es,cs:[bp].EMS_Reg_ES ; ;an000; dms; + sti ;ints on ;an000; dms; + +Retf_Fake_Out Proc Far ;this proc is to ;an000; dms; + ; simulate a RETF + ; instruction + ret ;performs a far return ;an000; dms; + +Retf_Fake_Out Endp ;end of retf fake out ;an000; dms; + + +MAC_Error_Strip_Stack: + + add sp,8h ;adjust for return add. ;an000; dms; + ; and target add. on + ; error + jmp MAC_Error_Exit ;exit routine ;an000; dms; + + +;========================================================================= +; MAC_Strip_Stack_And_Map : This routine will strip the stack of all +; the data placed on by MAC_Build_Stack_And_Map. +; +; Inputs : CS:BP - Pointer to data on the instance table +; +; Outputs : All data area restored +; Pages remapped to original +; AH - 0 = no error +; >0 = error (determined by Map_Pages) +; +; Instance Table carries this data: Old Map Data +; New Map Data +; Map & Call Data +; Context +;========================================================================= + +MAC_Strip_Stack_And_Map: ;an000; dms; + + mov ax,cs ;seg of context ;an000; dms; + mov es,ax ;place in es ;an000; dms; + cli ;ints off ;an000; dms; + mov di,offset cs:Map_Table ;get off of context ;an000; dms; + mov ax,Map_Count ;get entries in context ;an000; dms; + sti ;ints on ;an000; dms; + xor dx,dx ;clear dx ;an000; dms; + mov bx,Type Mappable_Phys_Page_Struct ;struc size ;an000; dms; + mul bx ;get byte count ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_Map_Table + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Shrink_Stack_And_Copy ;restore context ;an000; dms; + + mov si,cs:[bp].EMS_Reg_SI ;restore pointer ;an000; dms; + mov ds,cs:[bp].EMS_Reg_DS ; to data struc ;an000; dms; + + mov ax,ds ;transfer seg of struc ;an000; dms; + mov es,ax ; to dest. segment ;an000; dms; + mov di,si ;di=dest. offset ;an000; dms; + mov ax,Type Map_And_Call_Struc ;get size to move ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Data + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Shrink_Stack_And_Copy ;restore Map & Call buf ;an000; dms; + + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov ax,word ptr [si].MAC_New_Page_Map_Ptr[+2];get the segment ;an000; dms; + mov es,ax ; of the old map ;an000; dms; + mov di,word ptr [si].MAC_New_Page_Map_Ptr[+0];get its offset ;an000; dms; + + mov al,[si].MAC_New_Page_Map_Len ;get length of data ;an000; dms; + cbw ;convert to word ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,Type Log_Phys_Map_Struc ;struc size ;an000; dms; + mul bx ;get total byte count ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Log + sti ;ints on ;an000; dms; + add bx,size MAC_M_C_Log/2 + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Shrink_Stack_And_Copy ;restore new page data ;an000; dms; + + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov ax,word ptr [si].MAC_Old_Page_Map_Ptr[+2];get the segment ;an000; dms; + mov es,ax ; of the old map ;an000; dms; + mov di,word ptr [si].MAC_Old_Page_Map_Ptr[+0];get its offset ;an000; dms; + + mov al,[si].MAC_Old_Page_Map_Len ;get length of data ;an000; dms; + cbw ;convert to word ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,Type Log_Phys_Map_Struc ;struc size ;an000; dms; + mul bx ;get total byte count ;an000; dms; + cli ;ints off ;an000; dms; + mov bx,offset MAC_M_C_Log + sti ;ints on ;an000; dms; + add bx,bp ;offset BP relative ;an000; dms; + call MAC_Shrink_Stack_And_Copy ;set up stack for ;an000; dms; + + mov ds,cs:[bp].EMS_Reg_DS ;restore ds ;an000; dms; + mov si,cs:[bp].EMS_Reg_SI ;restore si ;an000; dms; + + mov dx,cs:[bp].EMS_Reg_DX ;get DX reg + + les di,[si].MAC_Old_Page_Map_Ptr ;set up for call ;an000; dms; + xor cx,cx ;clear cx ;an000; dms; + mov cl,[si].MAC_Old_Page_Map_Len ;get array size ;an000; dms; + mov bx,cs:[bp].MAC_Xref_Pages ;get handle page count ;an000; dms; + xor ah,ah ;clear high byte ;an000; dms; + mov al,cs:[bp].MAC_Option ;get option ;an000; dms; + + call Map_Pages ;map the new pages ;an000; dms; + + jmp MAC_Exit ;exit the program ;an000; dms; + + +Alter_And_Call endp ;end proc ;an000; dms; + + + page +;========================================================================= +;=============== Function 57h Logic - Move/Exchange Memory Region ======= +;========================================================================= + +;========================================================================= +; Exchng_Region - This routine moves/exchanges memory regions +; specified by the user. The following types of +; moves/exchanges are possible: +; +; Source Destination +; ------------------- ---------------------- +; Conventional Memory Expanded Memory +; Expanded Memory Conventional Memory +; Expanded Memory Expanded Memory +; +; Inputs : AH - 57h (Move/Exchange Memory Region) +; AL - Type of transfer +; 0 = Move memory +; 1 = Exchange memory +; DS:SI - Pointer to Move_Source_Dest Structure +; +; Outputs : Revised map +; AH - Non-zero if error +;========================================================================= + + +Exchng_Region proc + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + mov cs:[bp].ER_Sub_Function,al ;save subfunction ;an000; dms; + cmp al,ER_Max_Function ;valid function? ;an000; dms; + jbe ER_Valid_Sub_Function ;yes - continue ;an000; dms; + mov ah,EMS_Code8F ;no - error ;an000; dms; + jmp ER_Error_Exit ;exit routine ;an000; dms; + +ER_Valid_Sub_Function: + + call ER_Type_Check ;Proper types & ;an000; dms; + or ah,ah ; type combinations? ;an000; dms; + jnz ER_Error_Exit ;no - exit routine ;an000; dms; + + call ER_Handle_Check ;valid handles? ;an000; dms; + or ah,ah ; ;an000; dms; + jnz ER_Error_Exit ;no - exit routine ;an000; dms; + + call ER_Length_Check ;Region fits in page ;an000; dms; + or ah,ah ; and <= 1Mb? ;an000; dms; + jnz ER_Error_Exit ;no - exit routine ;an000; dms; + + call ER_Wrap_Check ;> 1Mb wrap on move? ;an000; dms; + or ah,ah ; ;an000; dms; + jnz ER_Error_Exit ;yes - exit routine ;an000; dms; + + call ER_Overlap_Check ;conv. memory overlaps ;an000; dms; + or ah,ah ; EMS page frame? ;an000; dms; + jnz ER_Error_Exit ;yes - exit routine ;an000; dms; + + call ER_Log_Page_Test ;offset valid for log. ;an000; dms; + or ah,ah ; page? ;an000; dms; + jnz ER_Error_Exit ;no - exit routine ;an000; dms; + + cmp cs:[bp].ER_Sub_Function,ER_Move ;move? ;an000; dms; + je ER_Move_Call ;yes - perform move ;an000; dms; + call ER_EMS_Overlap_Check ;EMS pages overlap? ;an000; dms; + or ah,ah ; + jz ER_Exchange_No_Overlap ;no - exit with error ;an000; dms; + mov ah,EMS_Code97 ;signal error ;an000; dms; + jmp ER_Error_Exit ;exit with error code ;an000; dms; + +ER_Exchange_No_Overlap: + + call ER_Exchange_Data ;no - perform exchange ;an000; dms; + jmp ER_Exit ;exit the routine ;an000; dms; + +ER_Move_Call: + + call ER_EMS_Overlap_Check ;see if we had a move ;an000; dms; + ; overlap + push ax ;save result across call;an000; dms; + call ER_Move_Data ;perform the move ;an000; dms; + pop ax ;restore result ;an000; dms; + + ER_Exit: + ER_Error_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +Exchng_Region endp + + +;========================================================================= +; ER_Handle_Check : This routine checks to see if the EMS handles +; specified are valid. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 83h +;========================================================================= + +ER_Handle_Check proc ;check requested handles;an000; dms; + + push dx ;save regs ;an000; dms; + push di ; ;an000; dms; + + cmp [si].Source_Memory_Type,ER_Conv_Memory ;Conv memory for source?;an000; dms; + je ER_Handle_Check_Dest ;yes - ck dest. handle ;an000; dms; + + push dx ;save dx ;an000; dms; + xor dx,dx ;clear it ;an000; dms; + mov ax,[si].Source_Handle ;get handle requested ;an000; dms; + mov dx,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul dx ;obtain index position ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + pop dx ;restore dx ;an000; dms; + + cmp Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;handle allocated ;an000; dms; + je ER_Handle_Check_Error_Exit ;handle not allocated ;an000; dms; + +ER_Handle_Check_Dest: + + cmp [si].Dest_Memory_Type,ER_Conv_Memory ;Conv memory for dest? ;an000; dms; + je ER_Handle_Check_Good_Exit ;yes - exit routine ;an000; dms; + + push dx ;save dx ;an000; dms; + xor dx,dx ;clear it ;an000; dms; + mov ax,[si].Dest_Handle ;get handle requested ;an000; dms; + mov dx,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul dx ;obtain index position ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + pop dx ;restore dx ;an000; dms; + + cmp Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;handle allocated ;an000; dms; + je ER_Handle_Check_Error_Exit ;handle not allocated ;an000; dms; + +ER_Handle_Check_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + jmp ER_Handle_Check_Exit ;exit program ;an000; dms; + +ER_Handle_Check_Error_Exit: + + mov ah,EMS_Code83 ;signal error ;an000; dms; + +ER_Handle_Check_Exit: + + pop di ;restore regs ;an000; dms; + pop dx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Handle_Check endp ;end proc ;an000; dms; + + + +;========================================================================= +; ER_Length_Check : This routine checks to see if the region length +; specified exceeds the page count of either the +; source or destination EMS handle pages allocated. +; It also checks to determine if the region length +; exceeds 1 Mb. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 93h +; 96h +; 8Ah +;========================================================================= + +ER_Length_Check proc ;check region length ;an000; dms; + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + + mov cx,[si].Region_Length_High_Word ;get size of the region ;an000; dms; + mov bx,[si].Region_Length_Low_Word ; in CX:BX ;an000; dms; + cmp cx,ER_10H ;> 1Mb ;an000; dms; + ja ER_Length_Check_Error96 ;exit with error ;an000; dms; + cmp cx,ER_10H ;high word = 10h? ;an000; dms; + jne ER_Length_Check_Cont ;no - continue ;an000; dms; + cmp bx,0 ;low word other than 0? ;an000; dms; + je ER_Length_Check_Cont ;no - good value ;an000; dms; + +ER_Length_Check_Error96: + + mov ah,EMS_Code96 ;signal error ;an000; dms; + jmp ER_Length_Check_Exit ;exit routine + +ER_Length_Check_Cont: + + cmp [si].Source_Memory_Type,ER_Conv_Memory ;Conv memory for source?;an000; dms; + je ER_Length_Check_Dest ;yes - ck dest. length ;an000; dms; + + push dx ;save dx ;an000; dms; + xor dx,dx ;clear it ;an000; dms; + mov ax,[si].Source_Handle ;get handle requested ;an000; dms; + mov dx,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul dx ;obtain index position ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + pop dx ;restore dx ;an000; dms; + + mov ax,Handle_LookUp_Table.H_Pages[di] ;get logical page count ;an000; dms; + ; for source handle + sub ax,[si].Source_Initial_Seg_Page ;pages in EMS to fill ;an000; dms; + push ax ;save ax ;an000; dms; + dec ax ;make it 0 based ;an000; dms; + pop ax ;restore ax ;an000; dms; + js ER_Length_Check_Error8A_Exit ;page out of range ;an000; dms; + + xor dx,dx ;clear it ;an000; dms; + mov dx,EMS_Page_Size_In_Bytes+1 ;page size in bytes ;an000; dms; + mul dx ;get total bytes to trf ;an000; dms; + sub ax,[si].Source_Initial_Offset ;get byte count in 1st ;an000; dms; + sbb dx,0 + + mov bx,ax ;prepare for DWORD comp ;an000; dms; + mov ax,dx ; ;an000; dms; + + mov cx,[si].Region_Length_High_Word ;get size of the region ;an000; dms; + mov dx,[si].Region_Length_Low_Word ; in CX:BX ;an000; dms; + + call ER_Dword_Compare ;region > target? ;an000; dms; + jc ER_Length_Check_Error93_Exit ;CY = region > target ;an000; dms; + + +ER_Length_Check_Dest: + + cmp [si].Dest_Memory_Type,ER_Conv_Memory ;Conv memory for dest? ;an000; dms; + je ER_Length_Check_Good_Exit ;yes - exit routine ;an000; dms; + + push dx ;save dx ;an000; dms; + xor dx,dx ;clear it ;an000; dms; + mov ax,[si].Dest_Handle ;get handle requested ;an000; dms; + mov dx,Type H_LookUp_Struc ;handle lookup table ;an000; dms; + mul dx ;obtain index position ;an000; dms; + mov di,ax ;place index in di ;an000; dms; + pop dx ;restore dx ;an000; dms; + + mov ax,Handle_LookUp_Table.H_Pages[di] ;get logical page count ;an000; dms; + + sub ax,[si].Dest_Initial_Seg_Page ;pages in EMS to fill ;an000; dms; + push ax ;save ax ;an000; dms; + dec ax ;make it 0 based ;an000; dms; + pop ax ;restore ax ;an000; dms; + js ER_Length_Check_Error8A_Exit ;page out of range ;an000; dms; + + xor dx,dx ;clear high word ;an000; dms; + mov dx,EMS_Page_Size_In_Bytes+1 ;page size in bytes ;an000; dms; + mul dx ;get total bytes to trf ;an000; dms; + sub ax,[si].Dest_Initial_Offset ;get byte count in 1st ;an000; dms; + sbb dx,0 + + mov bx,ax ;prepare for DWORD comp ;an000; dms; + mov ax,dx ; ;an000; dms; + + mov cx,[si].Region_Length_High_Word ;get size of the region ;an000; dms; + mov dx,[si].Region_Length_Low_Word ; in CX:BX ;an000; dms; + + call ER_Dword_Compare ;region > target? ;an000; dms; + jc ER_Length_Check_Error93_Exit ;CY = region > target ;an000; dms; + + +ER_Length_Check_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + jmp ER_Length_Check_Exit ;exit routine ;an000; dms; + +ER_Length_Check_Error93_Exit: + + mov ah,EMS_Code93 ;signal error ;an000; dms; + jmp ER_Length_Check_Exit ;exit routine ;an000; dms; + +ER_Length_Check_Error8A_Exit: + + mov ah,EMS_Code8A ;signal error ;an000; dms; + +ER_Length_Check_Exit: ;main exit ;an000; dms; + + pop di ;restore regs ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Length_Check endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Type_Check : This routine checks the source/destination type +; specified to determine if they are within the +; proper range. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 98h +;========================================================================= + +ER_Type_Check proc ;check type ;an000; dms; + + cmp [si].Source_Memory_Type,ER_Max_Type ;type within range? ;an000; dms; + ja ER_Type_Check_Error_Exit ;no - error exit ;an000; dms; + + cmp [si].Dest_Memory_Type,ER_Max_Type ;type within range? ;an000; dms; + ja ER_Type_Check_Error_Exit ;no - error exit ;an000; dms; + + +ER_Type_Check_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + jmp ER_Type_Check_Exit ;exit routine ;an000; dms; + +ER_Type_Check_Error_Exit: + + mov ah,EMS_Code98 ;signal error ;an000; dms; + +ER_Type_Check_Exit: + + ret ;return to caller ;an000; dms; + +ER_Type_Check endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Wrap_Check : This routine checks to determine if there will be +; a wrap of conventional memory beyond 1Mb. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: A2h +;========================================================================= + +ER_Wrap_Check proc ;cks. conv. mem. wrap ;an000; dms; + + push dx ;save regs ;an000; dms; + push bx ; ;an000; dms; + + cmp [si].Source_Memory_Type,ER_Conv_Memory ;conv. memory? ;an000; dms; + jne ER_Wrap_Check_Dest ;no -check dest. ;an000; dms; + + mov ax,[si].Source_Initial_Seg_Page ;get segment ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;adjust segment to ;an000; dms; + ; absolute address + mul bx ; ;an000; dms; + add ax,[si].Source_Initial_Offset ;add in offset ;an000; dms; + adc dx,0 ;pick up carry if any ;an000; dms; + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; trf size + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + ; trf size + cmp dx,ER_10H ;> 1Mb? ;an000; dms; + jae ER_Wrap_Check_Error_Exit ;yes - signal error ;an000; dms; + jmp ER_Wrap_Check_Good_Exit ;no - signal no error ;an000; dms; + +ER_Wrap_Check_Dest: + + cmp [si].Dest_Memory_Type,ER_Conv_Memory ;conv. memory? ;an000; dms; + jne ER_Wrap_Check_Good_Exit ;no - exit routine ;an000; dms; + + mov ax,[si].Dest_Initial_Seg_Page ;get segment ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;adjust segment to ;an000; dms; + ; absolute address + mul bx ; ;an000; dms; + add ax,[si].Dest_Initial_Offset ;add in offset ;an000; dms; + adc dx,0 ;pick up carry if any ;an000; dms; + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; trf size + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + ; trf size + cmp dx,ER_10H ;> 1Mb? ;an000; dms; + jae ER_Wrap_Check_Error_Exit ;yes - signal error ;an000; dms; + +ER_Wrap_Check_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + jmp ER_Wrap_Check_Exit ;exit routine ;an000; dms; + +ER_Wrap_Check_Error_Exit: + + mov ah,EMS_CodeA2 ;signal error ;an000; dms; + +ER_Wrap_Check_Exit: + + pop bx ;restore regs ;an000; dms; + pop dx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Wrap_Check endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Overlap_Check : This routine checks to determine if the conventional +; memory region and expanded memory region overlap. +; Specifically, does the conventional memory region +; overlap the physical page addresses used for +; expanded memory? +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 94h +; +; Algorithm : +; +; If Beg.Src.Add. < Beg.Dst.Add +; If (End.Src.Add - Beg.Dst.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; Else +; If (End.Dst.Add - Beg.Src.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; EndIf +;========================================================================= + +ER_Overlap_Check proc ;check for overlap ;an000; dms; + + push dx ;save regs ;an000; dms; + call ER_Save_Context ;save context ;an000; dms; + + cmp [si].Source_Memory_Type,ER_Conv_Memory ;conventional memory? ;an000; dms; + je ER_Overlap_Check_Source ;yes - check overlap ;an000; dms; + ;no - see if dest is + ; conv. memory + + cmp [si].Dest_Memory_Type,ER_Conv_Memory ;conventional memory? ;an000; dms; + jne ER_Overlap_Jump_Good ;no - exit routine ;an000; dms; + +ER_Overlap_Check_Dest: + + mov di,offset cs:ER_Save_Context_Buffer ;get addressibility to ;an000; dms; + ; the page frame save + ;buffer + add di,bp ;offset BP relative ;an000; dms; + cli ;ints off ;an000; dms; + cmp Map_Count,2 ;>= 2 page frames ;an000; dms; + sti ;ints on ;an000; dms; + jb ER_Overlap_Check_Dest_1_Frame ;no - use 1st. frame ;an000; dms; + add di,Type Mappable_Phys_Page_Struct ;yes - adjust ptr to ;an000; dms; + ; next frame for dest. +ER_Overlap_Check_Dest_1_Frame: + + ;**** calc abs address of the bottom of EMS transfer area + + mov ax,cs:[di].Phys_Page_Segment ;get seg value ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;para size ;an000; dms; + mul bx ;make abs address ;an000; dms; + mov cs:[bp].ER_Src_Abs_Beg_Low,ax ;save abs. address of ;an000; dms; + mov cs:[bp].ER_Src_Abs_Beg_High,dx ; phys page beg. ;an000; dms; + + ;**** calc abs address of the top of EMS transfer area + + add ax,EMS_Page_Size_In_Bytes ;make abs address ;an000; dms; + adc dx,0 ; ;an000; dms; + mov cs:[bp].ER_Src_Abs_End_Low,ax ;save abs. address ;an000; dms; + mov cs:[bp].ER_Src_Abs_End_High,dx ; of phys page end ;an000; dms; + + ;**** calc abs address of the bottom of CONV transfer area + + mov ax,[si].Dest_Initial_Seg_Page ;get segment ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;para size ;an000; dms; + mul bx ;make abs address ;an000; dms; + add ax,[si].Dest_Initial_Offset ;get offset ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + mov cs:[bp].ER_Dst_Abs_Beg_Low,ax ;save initial seg start ;an000; dms; + mov cs:[bp].ER_Dst_Abs_Beg_High,dx ;save initial off start ;an000; dms; + + ;**** calc abs address of the top of CONV transfer area + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; trf size + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + mov cs:[bp].ER_Dst_Abs_End_Low,ax ;save initial seg start ;an000; dms; + mov cs:[bp].ER_Dst_Abs_End_High,dx ;save initial off start ;an000; dms; + + call ER_General_Overlap_Test ;test for overlap ;an000; dms; + + jc ER_Overlap_Error_Exit ;exit with error ;an000; dms; + +ER_Overlap_Jump_Good: + + jmp ER_Overlap_Good_Exit ;exit good ;an000; dms; + +ER_Overlap_Check_Source: + + mov di,offset cs:ER_Save_Context_Buffer ;get addressibility to ;an000; dms; + ; the page frame save + ;buffer + add di,bp ;offset BP relative ;an000; dms; + + ;**** calc abs address of the bottom of EMS transfer area + + mov ax,cs:[di].Phys_Page_Segment ;get seg value ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;para size ;an000; dms; + mul bx ;make abs address ;an000; dms; + mov cs:[bp].ER_Src_Abs_Beg_Low,ax ;save abs. address of ;an000; dms; + mov cs:[bp].ER_Src_Abs_Beg_High,dx ; phys page beg. ;an000; dms; + + ;**** calc abs address of the top of EMS transfer area + + mov ax,cs:[di].Phys_Page_Segment ;get seg value ;an000; dms; + mov dx,EMS_Page_Size_In_Bytes ;get end of phys page ;an000; dms; + mov bx,ER_10H ;para size ;an000; dms; + mul bx ;make abs address ;an000; dms; + mov cs:[bp].ER_Src_Abs_End_Low,ax ;save abs. address ;an000; dms; + mov cs:[bp].ER_Src_Abs_End_High,dx ; of phys page end ;an000; dms; + + ;**** calc abs address of the bottom of CONV transfer area + + mov ax,[si].Source_Initial_Seg_Page ;get segment ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,ER_10H ;para size ;an000; dms; + mul bx ;make abs address ;an000; dms; + add ax,[si].Source_Initial_Offset ;get offset ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + mov cs:[bp].ER_Dst_Abs_Beg_Low,ax ;save initial seg start ;an000; dms; + mov cs:[bp].ER_Dst_Abs_Beg_High,dx ;save initial off start ;an000; dms; + + ;**** calc abs address of the top of CONV transfer area + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; trf size + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + mov cs:[bp].ER_Dst_Abs_End_Low,ax ;save initial seg start ;an000; dms; + mov cs:[bp].ER_Dst_Abs_End_High,dx ;save initial off start ;an000; dms; + + call ER_General_Overlap_Test ;test for overlap ;an000; dms; + + jnc ER_Overlap_Good_Exit ;exit good ;an000; dms; + jmp ER_Overlap_Error_Exit ;exit bad + +ER_Overlap_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + jmp ER_Overlap_Exit ;exit ;an000; dms; + +ER_Overlap_Error_Exit: + + mov ah,EMS_Code94 ;signal error ;an000; dms; + +ER_Overlap_Exit: + + call ER_Restore_Context ;restore context ;an000; dms; + + pop dx ;restore regs ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Overlap_Check endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_EMS_Overlap_Check : This routine determines if the source and target +; EMS regions overlap when both the source and target +; reside in EMS. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 92h +; +; Algorithm : +; +; If Beg.Src.Add. < Beg.Dst.Add +; If (End.Src.Add - Beg.Dst.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; Else +; If (End.Dst.Add - Beg.Src.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; EndIf +;========================================================================= + +ER_EMS_Overlap_Check proc ;check for overlap ;an000; dms; + + push bx ;save regs ;an000; dms; + push dx ; ;an000; dms; + + cmp [si].Source_Memory_Type,ER_EMS_Memory ;Source EMS? ;an000; dms; + jne ER_EMS_Overlap_Exit ;no - exit routine ;an000; dms; + + cmp [si].Dest_Memory_Type,ER_EMS_Memory ;Dest. EMS? ;an000; dms; + jne ER_EMS_Overlap_Exit ;no - exit routine ;an000; dms; + + mov bx,[si].Source_Handle ;get source handle ;an000; dms; + cmp bx,[si].Dest_Handle ;source = dest? ;an000; dms; + jne ER_EMS_Overlap_Good_Exit ;no - exit routine ;an000; dms; + +ER_EMS_Overlap_Calc_N_Ck: + + ;**** calc absolute beginning address of source page + + mov ax,[si].Source_Initial_Seg_Page ;get start page ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,EMS_Page_Size_In_Bytes ;get page size ;an000; dms; + mul bx ;convert page to abs ;an000; dms; + ; address + add ax,[si].Source_Initial_Offset ;add in offset value ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + + mov cs:[bp].ER_Src_Abs_Beg_Low,ax ;save low word of add + mov cs:[bp].ER_Src_Abs_Beg_High,dx ;save high word of add ;an000; dms; + + ;**** calc absolute ending address of source page + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; length + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + ; length + mov cs:[bp].ER_Src_Abs_End_Low,ax ;save low word of end ;an000; dms; + mov cs:[bp].ER_Src_Abs_End_High,dx ;save high word of end ;an000; dms; + + ;**** calc absolute beginning address of dest. page + + mov ax,[si].Dest_Initial_Seg_Page ;get start page ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov bx,EMS_Page_Size_In_Bytes ;get page size ;an000; dms; + mul bx ;convert page to abs ;an000; dms; + ; address + add ax,[si].Dest_Initial_Offset ;add in offset value ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + + mov cs:[bp].ER_Dst_Abs_Beg_Low,ax ;save low word of add + mov cs:[bp].ER_Dst_Abs_Beg_High,dx ;save high word of add ;an000; dms; + + ;**** calc absolute ending address of dest. page + + add ax,[si].Region_Length_Low_Word ;add in low word of ;an000; dms; + ; length + adc dx,[si].Region_Length_High_Word ;add in high word of ;an000; dms; + ; length + mov cs:[bp].ER_Dst_Abs_End_Low,ax ;save low word of end ;an000; dms; + mov cs:[bp].ER_Dst_Abs_End_High,dx ;save high word of end ;an000; dms; + + ;**** Actual test for overlap - corresponds to algorithm above + + call ER_General_Overlap_Test ;test for overlap ;an000; dms; + jnc ER_EMS_Overlap_Good_Exit ;no error ;an000; dms; + +ER_EMS_Overlap_Error_Exit: + + mov ah,EMS_Code92 ;signal error ;an000; dms; + jmp ER_EMS_Overlap_Exit ;exit ;an000; dms; + +ER_EMS_Overlap_Good_Exit: + + xor ah,ah ;no error ;an000; dms; + +ER_EMS_Overlap_Exit: + + pop dx ;restore regs ;an000; dms; + pop bx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_EMS_Overlap_Check endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_General_Overlap_Test:This routine determines if the source and target +; EMS regions overlap when both the source and target +; reside in EMS. +; +; Inputs : ER_Src_Abs_Beg_Low - Low word of beginning trf area of source +; ER_Src_Abs_Beg_High - High word of beginning trf area of source +; +; ER_Src_Abs_End_Low - Low word of ending trf area of source +; ER_Src_Abs_End_High - High word of ending trf area of source +; +; : ER_Dst_Abs_Beg_Low - Low word of beginning trf area of dest. +; ER_Dst_Abs_Beg_High - High word of beginning trf area of dest. +; +; ER_Dst_Abs_End_Low - Low word of ending trf area of dest. +; ER_Dst_Abs_End_High - High word of ending trf area of dest. +; +; Outputs : NC - no overlap +; CY - overlap +; +; Algorithm : +; +; If Beg.Src.Add. < Beg.Dst.Add +; If (End.Src.Add - Beg.Dst.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; Else +; If (End.Dst.Add - Beg.Src.Add) > 0 +; signal OVERLAP +; Else +; signal NO-OVERLAP +; EndIf +; EndIf +;========================================================================= + +ER_General_Overlap_Test proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + + mov ax,cs:[bp].ER_Src_Abs_Beg_High ;get source beg. add. ;an000; dms; + mov bx,cs:[bp].ER_Src_Abs_Beg_Low ; ;an000; dms; + mov cx,cs:[bp].ER_Dst_Abs_Beg_High ;get dest. beg. add. ;an000; dms; + mov dx,cs:[bp].ER_Dst_Abs_Beg_Low ; ;an000; dms; + call ER_Dword_Compare ; +; $if c ;< dest. beg. add.? ;an000; dms; + JNC ER_IF1 + mov ax,cs:[bp].ER_Src_Abs_End_Low ;get end address ;an000; dms; + mov dx,cs:[bp].ER_Src_Abs_End_High ; ;an000; dms; + sub ax,cs:[bp].ER_Dst_Abs_Beg_Low ;End.Src.Add-Beg.Dst.Add;an000; dms; + sbb dx,cs:[bp].ER_Dst_Abs_Beg_High ; ;an000; dms; +; $if ns ;yes - overlap ;an000; dms; + JS ER_IF2 + stc ;signal error ;an000; dms; + mov cs:[bp].ER_Direction_Flag,ER_Down ;signal reverse move ;an000; dms; +; $else ;no - not sure yet ;an000; dms; + JMP SHORT ER_EN2 +ER_IF2: + clc ;signal no overlap ;an000; dms; + mov cs:[bp].ER_Direction_Flag,ER_Up ;forward move ;an000; dms; +; $endif ; ;an000; dms; +ER_EN2: +; $else ;not sure if src < dst ;an000; dms; + JMP SHORT ER_EN1 +ER_IF1: + mov ax,cs:[bp].ER_Dst_Abs_End_Low ;get end address ;an000; dms; + mov dx,cs:[bp].ER_Dst_Abs_End_High ; ;an000; dms; + sub ax,cs:[bp].ER_Src_Abs_Beg_Low ;End.Dst.Add-Beg.Src.Add;an000; dms; + sbb dx,cs:[bp].ER_Src_Abs_Beg_High ; ;an000; dms; +; $if ns ;yes - overlap ;an000; dms; + JS ER_IF6 + stc ;signal error ;an000; dms; + mov cs:[bp].ER_Direction_Flag,ER_Up ;forward move ;an000; dms; +; $else ;no - not sure yet ;an000; dms; + JMP SHORT ER_EN6 +ER_IF6: + clc ;signal no overlap ;an000; dms; + mov cs:[bp].ER_Direction_Flag,ER_Up ;forward move ;an000; dms; +; $endif ; ;an000; dms; +ER_EN6: +; $endif ; ;an000; dms; +ER_EN1: + + pop dx ;restore regs ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_General_Overlap_Test endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Dword_Compare : This routine determines whether or not a dword +; value is greater than another dword value. +; +; Inputs : AX - Source high word +; BX - Source low word +; CX - Destination high word +; DX - Destination low word +; +; Outputs : NC - source >= destination +; CY - source < destination +;========================================================================= + +ER_Dword_Compare proc ; ;an000; dms; + + cmp ax,cx ;src high < dest high? ;an000; dms; +; $if b ;yes ;an000; dms; + JNB ER_IF10 + stc ;signal less than ;an000; dms; +; $else ;no ;an000; dms; + JMP SHORT ER_EN10 +ER_IF10: + cmp ax,cx ;src high > dest high? ;an000; dms; +; $if a ;yes ;an000; dms; + JNA ER_IF12 + clc ;signal greater than ;an000; dms; +; $else ;no ;an000; dms; + JMP SHORT ER_EN12 +ER_IF12: + cmp bx,dx ;src low < dest low? ;an000; dms; +; $if b ;yes ;an000; dms; + JNB ER_IF14 + stc ;signal less than ;an000; dms; +; $else ;no ;an000; dms; + JMP SHORT ER_EN14 +ER_IF14: + cmp bx,dx ;src low > dest low? ;an000; dms; +; $if a ;yes ;an000; dms; + JNA ER_IF16 + clc ;signal greater than ;an000; dms; +; $else ;no ;an000; dms; + JMP SHORT ER_EN16 +ER_IF16: + clc ; ;an000; dms; +; $endif ; ;an000; dms; +ER_EN16: +; $endif ; ;an000; dms; +ER_EN14: +; $endif ; ;an000; dms; +ER_EN12: +; $endif ; ;an000; dms; +ER_EN10: + + ret ; ;an000; dms; + +ER_Dword_Compare endp ; ;an000; dms; + + + +;========================================================================= +; ER_Segment_Adjust : This routine adjusts the segment:offset to a value +; with an offset less than 16. +; +; Inputs : AX:DX - Segment:Offset to be adjusted +; +; Outputs : AX:DX - New Segment:Offset value +;========================================================================= + +ER_Segment_Adjust proc ;adjust segment value ;an000; dms; + + push bx ;save bx ;an000; dms; + push cx ; ;an000; dms; + + mov bx,ax ;save segment value ;an000; dms; + mov ax,dx ;get offset ;an000; dms; + xor dx,dx ;clear high word ;an000; dms; + mov cx,ER_10h ;divide by 10h ;an000; dms; + div cx ;get seg adjustment ;an000; dms; + ; factor + add ax,bx ;adjust segment up ;an000; dms; + ; dx contains new off. ;an000; dms; + pop cx ;restore regs ;an000; dms; + pop bx ;restore bx ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Segment_Adjust endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Log_Page_Test : This routine checks the offset specified for +; the logical page to determine if the offset is +; within the valid ranges for the page size. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +; Possible error codes: 95h +;========================================================================= + +ER_Log_Page_Test proc ; ;an000; dms; + + mov ax,EMS_Page_Size_In_Bytes ;get page size ;an000; dms; + + cmp [si].Source_Memory_Type,ER_EMS_Memory ;EMS memory specified? ;an000; dms; + jne ER_Log_Dest_Test ;no - check dest. ;an000; dms; + + cmp ax,[si].Source_Initial_Offset ;> EMS page size ;an000; dms; + jae ER_Log_Good_Exit ;good exit ;an000; dms; + jmp ER_Log_Error_Exit ;error - bad exit ;an000; dms; + +ER_Log_Dest_Test: + + cmp [si].Dest_Memory_Type,ER_EMS_Memory ;EMS memory specified? ;an000; dms; + jne ER_Log_Good_Exit ;good exit ;an000; dms; + + cmp ax,[si].Dest_Initial_Offset ;> EMS page size ;an000; dms; + jae ER_Log_Good_Exit ;good exit ;an000; dms; + +ER_Log_Error_Exit: + + mov ah,EMS_Code95 ;signal error ;an000; dms; + jmp ER_Log_Exit ;exit routine ;an000; dms; + +ER_Log_Good_Exit: + + xor ah,ah ;signal no error ;an000; dms; + +ER_Log_Exit: + + ret ;return to caller ;an000; dms; + +ER_Log_Page_Test endp ;end proc ;an000; dms; + +;========================================================================= +; ER_Save_Context : This routine saves the context for page frames +; needed for the move/exchange. +; +; Inputs : none +; +; Outputs : ER_Save_Context_Buffer - save context for the needed page frames +;========================================================================= + +ER_Save_Context proc ;save contexts ;an000; dms; + + push ax ;save regs ;an000; dms; + push cx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + mov ax,cs ;make ds/es = cs ;an000; dms; + mov ds,ax ; ;an000; dms; + mov es,ax ; ;an000; dms; + + mov si,offset cs:Map_Table ;ptr to page frame table;an000; dms; + mov di,offset cs:ER_Save_Context_Buffer ;get dest. offset + add di,bp ;offset BP relative ;an000; dms; + + mov cx,2 ;default frame save ;an000; dms; + cli ;ints off ;an000; dms; + cmp Map_Count,2 ;2 page frames? ;an000; dms; + jae ER_Save_Context_Loop ;< = 2 - continue ;an000; dms; + mov cx,Map_Count ;max frame count to save;an000; dms; + +ER_Save_Context_Loop: + + sti ;ints on ;an000; dms; + push cx ;save cx ;an000; dms; + mov cx,Type Mappable_Phys_Page_Struct ;get byte count to trf ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;perform save ;an000; dms; + sti ;ints on ;an000; dms; + pop cx ;restore cx ;an000; dms; + loop ER_Save_Context_Loop ;continue ;an000; dms; + +ER_Save_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop cx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Save_Context endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Restore_Context : This routine restores the context for page frames +; saved. These pages were used for the +; move/exchange requested. +; +; Inputs : ER_Save_Context_Buffer - contains saved context +; +; Outputs : restored context for the saved page frames +;========================================================================= + +ER_Restore_Context proc ;restore contexts ;an000; dms; + + push ax ;save regs ;an000; dms; + push cx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + mov ax,cs ;make ds/es = cs ;an000; dms; + mov ds,ax ; ;an000; dms; + mov es,ax ; ;an000; dms; + + mov di,offset cs:Map_Table ;ptr to page frame table;an000; dms; + mov si,offset cs:ER_Save_Context_Buffer ;get dest. offset + add si,bp ;offset BP relative ;an000; dms; + + mov cx,2 ;default frame restore ;an000; dms; + cli ;ints off ;an000; dms; + cmp Map_Count,2 ;2 page frames? ;an000; dms; + jae ER_Restore_Context_Loop ;< = 2 - continue ;an000; dms; + mov cx,Map_Count ;max frame count to rest;an000; dms; + +ER_Restore_Context_Loop: + + sti ;ints on ;an000; dms; + mov al,byte ptr ds:[si].Phys_Page_Number ;get physical page num. ;an000; dms; + mov bx,word ptr ds:[si].PPM_Log_Page ;get logical page num. ;an000; dms; + mov dx,word ptr ds:[si].PPM_Handle ;get handle number ;an000; dms; + call Map_L_To_P ;map in orig. page ;an000; dms; + + push cx ;save cx ;an000; dms; + mov cx,Type Mappable_Phys_Page_Struct ;get byte count to trf ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;perform save ;an000; dms; + sti ;ints on ;an000; dms; + pop cx ;restore cx ;an000; dms; + loop ER_Restore_Context_Loop ;continue ;an000; dms; + +ER_Restore_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop cx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Restore_Context endp ;end proc ;an000; dms; + + + +;========================================================================= +; ER_Det_Src_Dest_Seg : This routine determines the applicable segment, +; offset, and page to be used for the move/exchange. +; This routine sets the pages/addresses to the end +; of the area to be moved/exchanged, if the move +; is to be a reverse move. If the move is to be +; a forward move, the pages/addresses are set to +; the beginning of the area to be moved/exchanged. +; In this way an overlapping move can be +; performed without overlaying data it is to move. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : ER_Source_Seg - Segment value of source +; ER_Dest_Seg - Segment value of destination +; +; ER_Source_Off - Offset value of source +; ER_Dest_Off - Offset value of destination +; +; ER_Source_Page - Source EMS page +; ER_Dest_Page - Destination EMS page +; +; ER_Source_Handle - Source handle +; ER_Dest_Handle - Destination handle +; +; ER_Source_Phys_Page - Physical page number +; ER_Dest_Phys_Page - Physical page number +;========================================================================= + +ER_Det_Src_Dest_Seg proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + + cmp [si].Source_Memory_Type,ER_EMS_Memory ;EMS? ;an000; dms; + jne ER_Det_Source_Conv ;no - conventional mem. ;an000; dms; + + mov di,offset cs:ER_Save_Context_Buffer ;get addressibility to ;an000; dms; + ; the page frame save + ;buffer + add di,bp ;offset BP relative + mov ax,cs:[di].Phys_Page_Segment ;get seg value ;an000; dms; + mov cs:[bp].ER_Source_Seg,ax ;save it in variable ;an000; dms; + + mov ax,[si].Source_Handle ;get source handle ;an000; dms; + mov cs:[bp].ER_Source_Handle,ax ;save handle ;an000; dms; + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF22 + mov ax,[si].Region_Length_Low_Word ;get low word of move ;an000; dms; + mov dx,[si].Region_Length_High_Word ;get high word ;an000; dms; + add ax,[si].Source_Initial_Offset ;pick up offset value ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + mov bx,4000h ;get page size ;an000; dms; + div bx ;get end logical page ;an000; dms; + add ax,[si].Source_Initial_Seg_Page ;adjust it for 1st. ;an000; dms; + mov cs:[bp].ER_Source_Page,ax ;save log. page ;an000; dms; + dec dx ;adjust to end point ;an000; dms; + mov cs:[bp].ER_Source_Off,dx ;save offset in last pg ;an000; dms; + +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN22 +ER_IF22: + mov ax,[si].Source_Initial_Seg_Page ;get page ;an000; dms; + mov dx,[si].Source_Initial_Offset ;get offset ;an000; dms; + mov cs:[bp].ER_Source_Page,ax ;save page ;an000; dms; + mov cs:[bp].ER_Source_Off,dx ;save offset ;an000; dms; +; $endif ; ;an000; dms; +ER_EN22: + mov ax,cs:[di].Phys_Page_Number ;get phys. page ;an000; dms; + mov cs:[bp].ER_Source_Phys_Page,ax ;save it ;an000; dms; + jmp ER_Det_Dest_Check ;jump to dest check ;an000; dms; + +ER_Det_Source_Conv: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF25 + mov ax,[si].Region_Length_Low_Word ;get low word of move ;an000; dms; + mov dx,[si].Region_Length_High_Word ;get high word ;an000; dms; + mov bx,ER_10h ;get bytes/para ;an000; dms; + div bx ;get para count ;an000; dms; + ; AX = para's + ; DX = offset + mov bx,ax ;save across adjust call;an000; dms; + mov cx,dx ; ;an000; dms; + mov ax,[si].Source_Initial_Seg_Page ;get seg value ;an000; dms; + mov dx,[si].Source_Initial_Offset ;get off value ;an000; dms; + dec dx ;adjust to end byte + call ER_Segment_Adjust ;adjust it downward ;an000; dms; + add ax,bx ;new segment value ;an000; dms; + add dx,cx ;new offset value ;an000; dms; + + mov cs:[bp].ER_Source_Seg,ax ;save it in variable ;an000; dms; + mov cs:[bp].ER_Source_Off,dx ;save offset in var ;an000; dms; +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN25 +ER_IF25: + mov ax,[si].Source_Initial_Seg_Page ;get seg value ;an000; dms; + mov dx,[si].Source_Initial_Offset ;get off value ;an000; dms; + mov cs:[bp].ER_Source_Seg,ax ;save it in variable ;an000; dms; + mov cs:[bp].ER_Source_Off,dx ;save offset in var ;an000; dms; +; $endif ; ;an000; dms; +ER_EN25: + + +ER_Det_Dest_Check: + + cmp [si].Dest_Memory_Type,ER_EMS_Memory ;Dest. EMS? ;an000; dms; + jne ER_Det_Dest_Conv ;no - conventional mem. ;an000; dms; + + mov di,offset cs:ER_Save_Context_Buffer ;save frame buffer ;an000; dms; + add di,bp ;offset BP relative ;an000; dms; + cli ;ints off ;an000; dms; + cmp Map_Count,1 ;> 1 page frame? ;an000; dms; + sti ;ints on ;an000; dms; + jb ER_Det_Dest_Check1 ;don't adjust pointer ;an000; dms; + add di,Type Mappable_Phys_Page_Struct ;next entry in save buf ;an000; dms; + +ER_Det_Dest_Check1: + + mov ax,cs:[di].Phys_Page_Segment ;get seg value ;an000; dms; + mov cs:[bp].ER_Dest_Seg,ax ;save it in variable ;an000; dms; + + mov ax,[si].Dest_Handle ;get dest. handle ;an000; dms; + mov cs:[bp].ER_Dest_Handle,ax ;save handle ;an000; dms; + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF28 + mov ax,[si].Region_Length_Low_Word ;get low word of move ;an000; dms; + mov dx,[si].Region_Length_High_Word ;get high word ;an000; dms; + add ax,[si].Dest_Initial_Offset ;pick up offset value ;an000; dms; + adc dx,0 ;pick up carry ;an000; dms; + + mov bx,4000h ;get page size ;an000; dms; + div bx ;get end logical page ;an000; dms; + add ax,[si].Dest_Initial_Seg_Page ;adjust it for 1st. ;an000; dms; + mov cs:[bp].ER_Dest_Page,ax ;save log. page ;an000; dms; + dec dx ;adjust to end point ;an000; dms; + mov cs:[bp].ER_Dest_Off,dx ;save off. in last page ;an000; dms; + +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN28 +ER_IF28: + mov ax,[si].Dest_Initial_Seg_Page ;get page ;an000; dms; + mov dx,[si].Dest_Initial_Offset ;get offset ;an000; dms; + mov cs:[bp].ER_Dest_Page,ax ;save log. page ;an000; dms; + mov cs:[bp].ER_Dest_Off,dx ;save off. in last page ;an000; dms; +; $endif ; ;an000; dms; +ER_EN28: + mov ax,cs:[di].Phys_Page_Number ;get phys page number ;an000; dms; + mov cs:[bp].ER_Dest_Phys_Page,ax ;save it ;an000; dms; + jmp ER_Det_Exit ;exit routine ;an000; dms; + +ER_Det_Dest_Conv: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF31 + mov ax,[si].Region_Length_Low_Word ;get low word of move ;an000; dms; + mov dx,[si].Region_Length_High_Word ;get high word ;an000; dms; + mov bx,ER_10H ;get bytes/para ;an000; dms; + div bx ;get para count ;an000; dms; + ; AX = para's + ; DX = offset + mov bx,ax ;save across adjust call;an000; dms; + mov cx,dx ; ;an000; dms; + mov ax,[si].Dest_Initial_Seg_Page ;get seg value ;an000; dms; + mov dx,[si].Dest_Initial_Offset ;get off value ;an000; dms; + dec dx ;adjust to end byte ;an000; dms; + call ER_Segment_Adjust ;adjust it downward ;an000; dms; + add ax,bx ;new segment value ;an000; dms; + add dx,cx ;new offset value ;an000; dms; + + mov cs:[bp].ER_Dest_Seg,ax ;save it in variable ;an000; dms; + mov cs:[bp].ER_Dest_Off,dx ;save offset in var ;an000; dms; +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN31 +ER_IF31: + mov ax,[si].Dest_Initial_Seg_Page ;get seg value ;an000; dms; + mov dx,[si].Dest_Initial_Offset ;get off value ;an000; dms; + mov cs:[bp].ER_Dest_Seg,ax ;save it in variable ;an000; dms; + mov cs:[bp].ER_Dest_Off,dx ;save offset in var ;an000; dms; +; $endif ; ;an000; dms; +ER_EN31: + + +ER_Det_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Det_Src_Dest_Seg endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Det_Move_Count : This initializes the count variables for the +; loop iteration counter of the move/exchange. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : ER_Move_Count_Low - low word value of move count +; ER_Move_Count_High - high word value of move count +;========================================================================= + + +ER_Det_Move_Count proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push dx ; ;an000; dms; + + mov ax,[si].Region_Length_Low_Word ;get low word count ;an000; dms; + mov dx,[si].Region_Length_High_Word ;get high word count ;an000; dms; + mov cs:[bp].ER_Move_Count_Low,ax ;save low word ;an000; dms; + mov cs:[bp].ER_Move_Count_High,dx ;save high word ;an000; dms; + + pop dx ;restore regs ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Det_Move_Count endp ;end proc ;an000; dms; + +;========================================================================= +; ER_Move_Source_To_Buffer : This routine moves the source data to +; the buffer before it is transferred to +; its final destination. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; +; Outputs : ER_Move_Xchg_Buffer1 - Source data +;========================================================================= + +ER_Move_Source_To_Buffer proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push es ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Source_EMS_Memory;Source EMS? ;an000; dms; + jz ER_Move_Source_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Move_Source_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Move_Source_Conv_Mem: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF34 + mov ax,ds ;adjust segment:off ;an000; dms; + dec ax ;segment - 1 para ;an000; dms; + mov ds,ax ; ;an000; dms; + add si,ER_10H ;adjust offset for 1 ;an000; dms; +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN34 +ER_IF34: + mov ax,ds ;get segment value ;an000; dms; + mov dx,si ;get offset value ;an000; dms; + call ER_Segment_Adjust ;adjust the seg:off ;an000; dms; + mov ds,ax ;restore ds ;an000; dms; + mov si,dx ;restore offset ;an000; dms; +; $endif ; ;an000; dms; +ER_EN34: + jmp ER_Move_Source_Count ;determine count ;an000; dms; + +ER_Move_Source_EMS_Mem: + + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF37 + cmp si,0ffffh ;beginning of log page ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF38 + dec cs:[bp].ER_Source_Page ;adjust page ptr ;an000; dms; + mov si,EMS_Page_Size_In_Bytes;get page size ;an000; dms; +; $endif ; ;an000; dms; +ER_IF38: +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN37 +ER_IF37: + cmp si,4000h ;wrap beyond page ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF41 + inc cs:[bp].ER_Source_Page ;adjust page ptr ;an000; dms; + xor si,si ;clear si ;an000; dms; +; $endif ; ;an000; dms; +ER_IF41: +; $endif ; ;an000; dms; +ER_EN37: + mov bx,cs:[bp].ER_Source_Page ;pass page to map ;an000; dms; + call ER_Map_Next_Src_Page ;no - map in current pg;an000; dms; + +ER_Move_Source_Count: + + mov cx,ER_10H ;default count ;an000; dms; + cmp cs:[bp].ER_Move_Count_High,0 ;high word set ;an000; dms; + jne ER_Move_Source_High_Set ;yes - use default ;an000; dms; + cmp cs:[bp].ER_Move_Count_Low,cx ;>= 10h bytes ;an000; dms; + jae ER_Move_Source_High_Set ;yes - use default ;an000; dms; + mov cx,cs:[bp].ER_Move_Count_Low ;no - use last few bytes;an000; dms; + +ER_Move_Source_High_Set: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF44 + cmp si,di ;source >= dest? ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF45 + cmp si,ER_10H ;source >= 10h? ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF46 + mov cx,si ;get move count ;an000; dms; + inc cx ;always 1 byte off ;an000; dms; +; $endif ; ;an000; dms; +ER_IF46: +; $else ;source >= dest ;an000; dms; + JMP SHORT ER_EN45 +ER_IF45: + cmp di,ER_10H ;dest >= 10h? ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF49 + mov cx,di ;get move count ;an000; dms; + inc cx ;always 1 byte off ;an000; dms; +; $endif ; ;an000; dms; +ER_IF49: +; $endif ; ;an000; dms; +ER_EN45: +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN44 +ER_IF44: + cmp si,di ;source >= dest? ;an000; dms; +; $if a ;yes ;an000; dms; + JNA ER_IF53 + mov ax,4000h ;get end of page ;an000; dms; + sub ax,si ;get bytes remaining ;an000; dms; + cmp ax,ER_10H ;source >= 10h ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF54 + mov cx,ax ;get remaining count ;an000; dms; +; $endif ; ;an000; dms; +ER_IF54: +; $else ;source >= dest ;an000; dms; + JMP SHORT ER_EN53 +ER_IF53: + mov ax,4000h ;get end of page ;an000; dms; + sub ax,di ;get bytes remaining ;an000; dms; + cmp ax,ER_10H ;dest >= 10h ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF57 + mov cx,ax ;get remaining count ;an000; dms; +; $endif ; ;an000; dms; +ER_IF57: +; $endif ; ;an000; dms; +ER_EN53: +; $endif ; ;an000; dms; +ER_EN44: + + jmp ER_Move_Source_Default_Count ;continue routine ;an000; dms; + +ER_Move_Source_Default_Count: + + mov cs:[bp].ER_Current_Move_Count,cx ;save current move cnt ;an000; dms; + + sub cs:[bp].ER_Move_Count_Low,cx ;get new count ;an000; dms; + sbb cs:[bp].ER_Move_Count_High,0 ;pick up borrow ;an000; dms; + + mov ax,cs ;get seg for buffer ;an000; dms; + mov es,ax ;put into es ;an000; dms; + mov di,offset cs:ER_Move_Xchg_Buffer1 ;offset of buffer ;an000; dms; + add di,bp ;offset BP relative ;an000; dms; + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF61 + add di,ER_10H ;end of buffer + 1 ;an000; dms; + dec di ;end of buffer ;an000; dms; +; $endif ; ;an000; dms; +ER_IF61: + + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF63 + std ;reverse move ;an000; dms; +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN63 +ER_IF63: + cld ; ;an000; dms; +; $endif ; ;an000; dms; +ER_EN63: + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + +ER_Move_Source_Exit: + + pop es ;restore regs ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Move_Source_To_Buffer endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Move_Buffer_To_Dest : This routine moves the data in the buffer +; to the destination specified by the user. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; ER_Move_Xchg_Buffer1 - Source data +; +; Outputs : Adjusted segment:offset or page/offset +;========================================================================= + +ER_Move_Buffer_To_Dest proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Dest_EMS_Memory ;Source EMS? ;an000; dms; + jz ER_Move_Buffer_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Move_Buffer_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Move_Buffer_Conv_Mem: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF66 + mov ax,es ;adjust segment:off ;an000; dms; + dec ax ;segment - 1 para ;an000; dms; + mov es,ax ; ;an000; dms; + add di,ER_10H ;adjust offset for 1 ;an000; dms; +; $else ;forward move? ;an000; dms; + JMP SHORT ER_EN66 +ER_IF66: + mov ax,es ;adjust seg:off ;an000; dms; + mov dx,di ; ;an000; dms; + call ER_Segment_Adjust ; ;an000; dms; + mov es,ax ;new seg:off ;an000; dms; + mov di,dx ; ;an000; dms; +; $endif ; ;an000; dms; +ER_EN66: + ; para + jmp ER_Move_Buffer_Count ;determine count ;an000; dms; + +ER_Move_Buffer_EMS_Mem: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF69 + cmp di,0ffffh ;beginning of log page ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF70 + dec cs:[bp].ER_Dest_Page ;next page ;an000; dms; + mov di,EMS_Page_Size_In_Bytes;end of page ;an000; dms; +; $endif ; ;an000; dms; +ER_IF70: +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN69 +ER_IF69: + cmp di,4000h ;end of page? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF73 + inc cs:[bp].ER_Dest_Page ;next page ;an000; dms; + xor di,di ;clear di ;an000; dms; +; $endif ; ;an000; dms; +ER_IF73: +; $endif ; ;an000; dms; +ER_EN69: + mov bx,cs:[bp].ER_Dest_Page ;pass page to map ;an000; dms; + call ER_Map_Next_Dest_Page ;map in the page ;an000; dms; + +ER_Move_Buffer_Count: + + mov cx,cs:[bp].ER_Current_Move_Count ;get move from source ;an000; dms; + + mov ax,cs ;get seg for buffer ;an000; dms; + mov ds,ax ;put into es ;an000; dms; + mov si,offset cs:ER_Move_Xchg_Buffer1 ;offset of buffer ;an000; dms; + add si,bp ;offset BP relative ;an000; dms; + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF76 + add si,ER_10H ;end of buffer + 1 ;an000; dms; + dec si ;end of buffer ;an000; dms; +; $endif ; ;an000; dms; +ER_IF76: + + cmp cs:[bp].ER_Direction_Flag,ER_Down ;reverse move? ;an000; dms; +; $if e ;yes ;an000; dms; + JNE ER_IF78 + std ;reverse move ;an000; dms; +; $else ;forward move ;an000; dms; + JMP SHORT ER_EN78 +ER_IF78: + cld ; ;an000; dms; +; $endif ; ;an000; dms; +ER_EN78: + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + +ER_Move_Dest_Exit: + + pop ds ;restore regs ;an000; dms; + pop si ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Move_Buffer_To_Dest endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Xchg_Source_To_Buffer : This routine moves the source data to +; the buffer before it is exchanged with +; the destination data. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; +; Outputs : ER_Move_Xchg_Buffer1 - Source data +;========================================================================= + +ER_Xchg_Source_To_Buffer proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Source_EMS_Memory;Source EMS? ;an000; dms; + jz ER_Xchg_Source_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Xchg_Source_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Xchg_Source_Conv_Mem: + + mov ax,ds ;adjust segment:off ;an000; dms; + mov dx,si ; ;an000; dms; + call ER_Segment_Adjust ; ;an000; dms; + mov ds,ax ;new segment:off ;an000; dms; + mov si,dx ; ;an000; dms; + jmp ER_Xchg_Source_Count ;determine count ;an000; dms; + +ER_Xchg_Source_EMS_Mem: + + cmp si,4000h ;beginning of log page ;an000; dms; + je ER_Xchg_Source_EMS_Next ;yes - get next page ;an000; dms; + mov bx,cs:[bp].ER_Source_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Src_Page ;no - map in current pg;an000; dms; + jmp ER_Xchg_Source_Count ;get count for move ;an000; dms; + +ER_Xchg_Source_EMS_Next: + + mov bx,cs:[bp].ER_Source_Page ;pass log. page to call ;an000; dms; + inc bx ; adjusted upward ;an000; dms; + call ER_Map_Next_Src_Page ;map in the page ;an000; dms; + xor si,si ;reinit pointer ;an000; dms; + +ER_Xchg_Source_Count: + + mov cx,ER_10H ;default count ;an000; dms; + cmp cs:[bp].ER_Move_Count_High,0 ;high word set ;an000; dms; + jne ER_Xchg_Source_High_Set ;yes - use default ;an000; dms; + cmp cs:[bp].ER_Move_Count_Low,cx ;>= 10h bytes ;an000; dms; + jae ER_Xchg_Source_High_Set ;yes - use default ;an000; dms; + mov cx,cs:[bp].ER_Move_Count_Low ;no - use last few bytes;an000; dms; + +ER_Xchg_Source_High_Set: + + cmp si,di ;source >= dest? ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF81 + mov ax,4000h ;get end of page ;an000; dms; + sub ax,si ;get bytes remaining ;an000; dms; + cmp ax,ER_10H ;source >= 10h ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF82 + mov cx,ax ;get remaining count ;an000; dms; +; $endif ; ;an000; dms; +ER_IF82: +; $else ;source >= dest ;an000; dms; + JMP SHORT ER_EN81 +ER_IF81: + mov ax,4000h ;get end of page ;an000; dms; + sub ax,di ;get bytes remaining ;an000; dms; + cmp ax,ER_10H ;dest >= 10h ;an000; dms; +; $if b ;no ;an000; dms; + JNB ER_IF85 + mov cx,ax ;get remaining count ;an000; dms; +; $endif ; ;an000; dms; +ER_IF85: +; $endif ; ;an000; dms; +ER_EN81: + +ER_Xchg_Source_Default_Count: + + mov cs:[bp].ER_Current_Move_Count,cx ;save current move cnt ;an000; dms; + + sub cs:[bp].ER_Move_Count_Low,cx ;get new count ;an000; dms; + sbb cs:[bp].ER_Move_Count_High,0 ;pick up borrow ;an000; dms; + + mov ax,cs ;get seg for buffer ;an000; dms; + mov es,ax ;put into es ;an000; dms; + mov di,offset cs:ER_Move_Xchg_Buffer1 ;offset of buffer ;an000; dms; + add di,bp ;offset BP relative ;an000; dms; + + cld ;forward move ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + +ER_Xchg_Source_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Xchg_Source_To_Buffer endp ;end proc ;an000; dms; + + +;========================================================================= +; ER_Xchg_Dest_To_Buffer : This routine moves the destination data to +; the buffer before it is exchanged with +; the source data. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; +; Outputs : ER_Move_Xchg_Buffer2 - Destination data +;========================================================================= + +ER_Xchg_Dest_To_Buffer proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Dest_EMS_Memory ;Dest EMS? ;an000; dms; + jz ER_Xchg_Dest_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Xchg_Dest_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Xchg_Dest_Conv_Mem: + + mov ax,es ;adjust segment:off ;an000; dms; + mov dx,di ; ;an000; dms; + call ER_Segment_Adjust ; ;an000; dms; + mov es,ax ;new segment:off ;an000; dms; + mov di,dx ; ;an000; dms; + jmp ER_Xchg_Dest_Count ;determine count ;an000; dms; + +ER_Xchg_Dest_EMS_Mem: + + cmp di,4000h ;beginning of log page ;an000; dms; + je ER_Xchg_Dest_EMS_Next ;yes - get next page ;an000; dms; + mov bx,cs:[bp].ER_Dest_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Dest_Page ;no - map in current pg;an000; dms; + jmp ER_Xchg_Dest_Count ;get count for move ;an000; dms; + +ER_Xchg_Dest_EMS_Next: + + mov bx,cs:[bp].ER_Dest_Page ;pass log. page to call ;an000; dms; + inc bx ; adjusted upward ;an000; dms; + call ER_Map_Next_Dest_Page ;map in the page ;an000; dms; + xor di,di ;reinit pointer ;an000; dms; + +ER_Xchg_Dest_Count: + + mov cx,cs:[bp].ER_Current_Move_Count ;get move count ;an000; dms; + mov ax,es ;get destination seg ;an000; dms; + mov ds,ax ;put into ds for buffer ;an000; dms; + ; transfer + mov si,di ;get destination off ;an000; dms; + mov ax,cs ;get seg for buffer ;an000; dms; + mov es,ax ;put into es ;an000; dms; + mov di,offset cs:ER_Move_Xchg_Buffer2 ;offset of buffer ;an000; dms; + add di,bp ;offset BP relative ;an000; dms; + + cld ;forward move ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + +ER_Xchg_Dest_Exit: + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Xchg_Dest_To_Buffer endp ;end proc ;an000; dms; + + + + +;========================================================================= +; ER_Xchg_Buffer_To_Source ; This routine performs the actual exchange +; from the destination buffer to the source +; buffer. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; ER_Move_Xchg_Buffer2 - Destination data +; +; Outputs : Adjusted segment:offset or page/offset +;========================================================================= + +ER_Xchg_Buffer_To_Source proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push es ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Source_EMS_Memory;Source EMS? ;an000; dms; + jz ER_Xchg_Buf2_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Xchg_Buf2_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Xchg_Buf2_Conv_Mem: + + mov ax,ds ;adjust segment:off ;an000; dms; + mov dx,si ; ;an000; dms; + call ER_Segment_Adjust ; ;an000; dms; + mov ds,ax ;new segment:off ;an000; dms; + mov si,dx ; ;an000; dms; + jmp ER_Xchg_Buf2_Count ;determine count ;an000; dms; + +ER_Xchg_Buf2_EMS_Mem: + + cmp si,4000h ;beginning of log page ;an000; dms; + je ER_Xchg_Buf2_EMS_Next ;yes - get next page ;an000; dms; + mov bx,cs:[bp].ER_Source_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Src_Page ;no - map in current pg;an000; dms; + jmp ER_Xchg_Buf2_Count ;get count for move ;an000; dms; + +ER_Xchg_Buf2_EMS_Next: + + inc cs:[bp].ER_Source_Page ;adjust log page ;an000; dms; + mov bx,cs:[bp].ER_Source_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Src_Page ;map in the page ;an000; dms; + xor si,si ;reinit pointer ;an000; dms; + +ER_Xchg_Buf2_Count: + + mov cx,cs:[bp].ER_Current_Move_Count ;get move count ;an000; dms; + + mov ax,ds ;get destination seg ;an000; dms; + mov es,ax ;put into ds for buffer ;an000; dms; + ; transfer + mov di,si ;get destination off ;an000; dms; + add si,cx ;adjust source ptr ;an000; dms; + push si ;save across xchg ;an000; dms; + push ds ; ;an000; dms; + + mov ax,cs ;get seg for buffer ;an000; dms; + mov ds,ax ;put into es ;an000; dms; + mov si,offset cs:ER_Move_Xchg_Buffer2 ;offset of buffer ;an000; dms; + add si,bp ;offset BP relative ;an000; dms; + + cld ;forward move ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + + pop ds ;restore ptr ;an000; dms; + pop si ; ;an000; dms; + +ER_Xchg_Buf2_Exit: + + pop es ;restore regs ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Xchg_Buffer_To_Source endp ;end proc ;an000; dms; + + + +;========================================================================= +; ER_Xchg_Buffer_To_Dest ; This routine performs the actual exchange +; from the source buffer to the destination. +; +; Inputs : BP - carries type of memory for source/dest +; Bit 0 - Destination (EMS if set) +; Bit 1 - Source (EMS if set) +; ER_Move_Xchg_Buffer1 - Source data +; +; Outputs : Adjusted segment:offset or page/offset +;========================================================================= + +ER_Xchg_Buffer_To_Dest proc ; ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push dx ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + + test cs:[bp].ER_Mem_Type,ER_Dest_EMS_Memory ;Dest EMS? ;an000; dms; + jz ER_Xchg_Buf1_Conv_Mem ;no - adjust seg:off ;an000; dms; + jmp ER_Xchg_Buf1_EMS_Mem ;yes- continue move ;an000; dms; + +ER_Xchg_Buf1_Conv_Mem: + + mov ax,es ;adjust segment:off ;an000; dms; + mov dx,di ; ;an000; dms; + call ER_Segment_Adjust ; ;an000; dms; + mov es,ax ;new segment:off ;an000; dms; + mov di,dx ; ;an000; dms; + jmp ER_Xchg_Buf1_Count ;determine count ;an000; dms; + +ER_Xchg_Buf1_EMS_Mem: + + cmp di,4000h ;beginning of log page ;an000; dms; + je ER_Xchg_Buf1_EMS_Next ;yes - get next page ;an000; dms; + mov bx,cs:[bp].ER_Dest_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Dest_Page ;no - map in current pg;an000; dms; + jmp ER_Xchg_Buf1_Count ;get count for move ;an000; dms; + +ER_Xchg_Buf1_EMS_Next: + + inc cs:[bp].ER_Dest_Page ;adjust log page ;an000; dms; + mov bx,cs:[bp].ER_Dest_Page ;pass log. page to call ;an000; dms; + call ER_Map_Next_Dest_Page ;map in the page ;an000; dms; + mov di,EMS_Page_Size_In_Bytes ;reinit pointer ;an000; dms; + +ER_Xchg_Buf1_Count: + + mov cx,cs:[bp].ER_Current_Move_Count ;get move count ;an000; dms; + mov ax,cs ;get seg for buffer ;an000; dms; + mov ds,ax ;put into es ;an000; dms; + mov si,offset cs:ER_Move_Xchg_Buffer1 ;offset of buffer ;an000; dms; + add si,bp ;offset BP relative ;an000; dms; + + cld ;forward move ;an000; dms; + cli ;ints off ;an000; dms; + rep movsb ;move the data ;an000; dms; + sti ;ints on ;an000; dms; + +ER_Xchg_Buf1_Exit: + + pop ds ;restore regs ;an000; dms; + pop si ; ;an000; dms; + pop dx ; ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Xchg_Buffer_To_Dest endp ;end proc ;an000; dms; + + + +;========================================================================= +; ER_Map_Next_Src_Page : This routine maps in the page needed by +; the source of the move/exchange. +; +; Inputs : ER_Source_Phys_Page - Physical page of source +; ER_Source_Handle - Handle of source +; BX - logical page +; +; Outputs : newly mapped page +;========================================================================= + +ER_Map_Next_Src_Page proc ;map next src. page ;an000; dms; + + mov ax,cs:[bp].ER_Source_Phys_Page ;map the source page ;an000; dms; + mov dx,cs:[bp].ER_Source_Handle ;handle to use ;an000; dms; + call Map_L_To_P ;map the page ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Map_Next_Src_Page endp ;end proc ;an000; dms; + +;========================================================================= +; ER_Map_Next_Dest_Page : This routine maps in the page needed by +; the destination of the move/exchange. +; +; Inputs : ER_Dest_Phys_Page - Physical page of source +; ER_Dest_Handle - Handle of source +; BX - logical page to map +; +; Outputs : newly mapped page +;========================================================================= + +ER_Map_Next_Dest_Page proc ;map next dest. page ;an000; dms; + + mov ax,cs:[bp].ER_Dest_Phys_Page ;map the dest. page ;an000; dms; + mov dx,cs:[bp].ER_Dest_Handle ;handle to use ;an000; dms; + call Map_L_To_P ;map the page ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Map_Next_Dest_Page endp ;end proc ;an000; dms; + +;========================================================================= +; ER_Move_Data : This routine will perform the actual move of the +; data for the function 5700h. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +;========================================================================= + +ER_Move_Data proc ;move the data ;an000; dms; + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + call ER_Save_Context ;save off max of 2 pages;an000; dms; + call ER_Det_Src_Dest_Seg ;determine segs ;an000; dms; + call ER_Det_Move_Count ;ER_10h_Move_Count = ;an000; dms; + ; # of 10h moves + ;ER_10h_Move_Remainder = + ; # of bytes remaining + +ER_Move_Data_Now: + + ;set the flags to signal + ;the memory type in use + ;for Source/Destination. + + xor al,al ;al signals type of mem ;an000; dms; + or al,[si].Source_Memory_Type ;get source memory type ;an000; dms; + shl al,1 ;put into bit 1 ;an000; dms; + or al,[si].Dest_Memory_Type ;get dest. memory type ;an000; dms; + cbw ;make it a word value ;an000; dms; + mov cs:[bp].ER_Mem_Type,ax ;put flags in var ;an000; dms; + ;bp = bit 0 - dest mem + ; bit 1 - src mem + + mov di,cs:[bp].ER_Dest_Off ;get dest. offset ;an000; dms; + mov es,cs:[bp].ER_Dest_Seg ;get dest. seg ;an000; dms; + + mov si,cs:[bp].ER_Source_Off ;get src. offset ;an000; dms; + mov ds,cs:[bp].ER_Source_Seg ;get src. seg ;an000; dms; + +ER_Move_Data_Loop: + + call ER_Move_Source_To_Buffer ;move data to buffer ;an000; dms; + call ER_Move_Buffer_To_Dest ;move buffer to dest. ;an000; dms; + + cmp cs:[bp].ER_Move_Count_High,0 ;end of move? ;an000; dms; + jne ER_Move_Data_Loop ;no - continue loop ;an000; dms; + cmp cs:[bp].ER_Move_Count_Low,0 ;end of move? ;an000; dms; + jne ER_Move_Data_Loop ;no - continue loop ;an000; dms; + ;yes - end of loop ;an000; dms; + +ER_Move_Data_Error_Exit: + + call ER_Restore_Context ;restore the context ;an000; dms; + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Move_Data endp ;end proc ;an000; dms; + + + +;========================================================================= +; ER_Exchange_Data : This routine will perform the actual exchange of +; data for the function 5701h. +; +; Inputs : DS:SI - Pointer to Move_Source_Dest_Struc data +; +; Outputs : AH - Non-zero on error +;========================================================================= + +ER_Exchange_Data proc ;xchg the data ;an000; dms; + + push bx ;save regs ;an000; dms; + push cx ; ;an000; dms; + push dx ; ;an000; dms; + push di ; ;an000; dms; + push si ; ;an000; dms; + push ds ; ;an000; dms; + push es ; ;an000; dms; + + call ER_Save_Context ;save off max of 2 pages;an000; dms; + call ER_Det_Src_Dest_Seg ;determine segs ;an000; dms; + call ER_Det_Move_Count ;ER_10h_Move_Count = ;an000; dms; + ; # of 10h moves + ;ER_10h_Move_Remainder = + ; # of bytes remaining + +ER_Xchg_Data_Now: + + ;set the flags to signal + ;the memory type in use + ;for Source/Destination. + + xor al,al ;al signals type of mem ;an000; dms; + or al,[si].Source_Memory_Type ;get source memory type ;an000; dms; + shl al,1 ;put into bit 1 ;an000; dms; + or al,[si].Dest_Memory_Type ;get dest. memory type ;an000; dms; + cbw ;make it a word value ;an000; dms; + mov cs:[bp].ER_Mem_Type,ax ;put flags in var ;an000; dms; + ;bp = bit 0 - dest mem + ; bit 1 - src mem + + mov di,cs:[bp].ER_Dest_Off ;get dest. offset ;an000; dms; + mov es,cs:[bp].ER_Dest_Seg ;get dest. seg ;an000; dms; + + mov si,cs:[bp].ER_Source_Off ;get src. offset ;an000; dms; + mov ds,cs:[bp].ER_Source_Seg ;get src. seg ;an000; dms; + +ER_Xchg_Data_Loop: + + call ER_Xchg_Source_To_Buffer ;move source to buf 1 ;an000; dms; + call ER_Xchg_Dest_To_Buffer ;move dest. to buf 2 ;an000; dms; + call ER_Xchg_Buffer_To_Source ;move buf2 to source ;an000; dms; + call ER_Xchg_Buffer_To_Dest ;move buf1 to dest. ;an000; dms; + + cmp cs:[bp].ER_Move_Count_High,0 ;end of move? ;an000; dms; + jne ER_Xchg_Data_Loop ;no - continue loop ;an000; dms; + cmp cs:[bp].ER_Move_Count_Low,0 ;end of move? ;an000; dms; + jne ER_Xchg_Data_Loop ;no - continue loop ;an000; dms; + ;yes - end of loop ;an000; dms; + +ER_Xchg_Data_Error_Exit: + + call ER_Restore_Context ;restore the context ;an000; dms; + + pop es ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + pop si ; ;an000; dms; + pop di ; ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + pop bx ; ;an000; dms; + + ret ;return to caller ;an000; dms; + +ER_Exchange_Data endp ;end proc ;an000; dms; + + + + page + +;========================================================================= +;=============== Function 5Ah Logic - Allocate Raw Pages ============= +;========================================================================= + + +;========================================================================= +; Alloc_Raw - This routine allocates raw EMS pages, pages +; less than the standard 16k page. These pages +; are a sub-multiple of 16k. In the IBM version +; of this implementation the raw page is defined +; as 16k, thus we do not need to do anything +; special here. We map this call to the proc +; GET_HANDLE (function 43h) to allocate a handle. +; +; Inputs : AH - 5Ah (Allocate Raw Pages) +; BX - Number of raw pages to allocate +; +; Outputs : AH - Non-zero if error (Determined by Get_Handle proc) +; DX - Handle if no error +;========================================================================= + +Alloc_Raw proc ;Allocate raw pages ;an000; dms; + + PUSH BX + PUSH CX + PUSH DI + PUSH SI + PUSH DS ;save these registers + + PUSH CS ;get cs + POP DS ;into ds + + ;Remove test for BX = 0. This is @RH4 + ; valid under LIM 4.0 + + cmp al,AR_Sub_Max ;sub function out of range? ;an000; dms; + jna AR_OKSub ;no ;an000; dms; + mov ah,EMS_Code8F ;yes-signal error ;an000; dms; + jmp AR_Exit ;exit routine ;an000; dms; + +AR_OKSub: + + CMP BX,TOTAL_EMS_PAGES ;Enough total EMS pages? + JNA AR_OKTOTAL + MOV AH,EMS_CODE87 + JMP AR_EXIT + +AR_OKTOTAL: + cli ;ints off ;an000; dms; + CMP BX,FREE_PAGES ;Enough unallocated pages? + sti ;ints on ;an000; dms; + JNA AR_OKFREE + MOV AH,EMS_CODE88 + JMP AR_EXIT + ;----------------------------------------------------- + ; Search for a free handle @RH1 º + ;----------------------------------------------------- +AR_OKFREE: + MOV CX,NUM_HANDLES ;loop counter is #handles + DEC CX ;handle 0 reserved for op. sys. @RH1 + MOV DX,1 ;handle assignment set to 1 @RH1 + MOV DI,TYPE H_LOOKUP_STRUC ;init table index to 1st entry @RH1 +;-------------------------------- + CLI ;interrupts OFF during allocation +;-------------------------------- +AR_FREEHSRCH: + CMP HANDLE_LOOKUP_TABLE.H_PAGES[DI],REUSABLE_HANDLE + ;Is this handle available? @RH1 + JE AR_HFREE ;yes end search dx=handle id @RH1 + INC DX ;next handle assignment + ADD DI,TYPE H_LOOKUP_STRUC ;next entry in handle lookup @RH1 + ;repeat for all table entries + LOOP AR_FREEHSRCH + MOV AH,EMS_CODE85 ;no available handles + JMP AR_EXIT ;go to exit ;GGA + + ;----------------------------------------------------- + ; If here then there's enough pages for request. @RH1 º + ; DX = handle #, DI = ptr to hndl lookup entry @RH1 º +AR_HFREE: + + MOV CX,NUM_HANDLES ;loop counter + DEC CX ;handle 0 reserved for op. sys. @RH1 + ;si = index to hndl lookup tbl @RH1 + MOV SI,TYPE H_LOOKUP_STRUC ; for adding pages (skip 0 entry) @RH1 + XOR AX,AX ;clear page counter + CLC ;clear carry for addition +AR_PAGESUM: + CMP HANDLE_LOOKUP_TABLE.H_PAGES[SI],REUSABLE_HANDLE + JE AR_PGSUM_BOT ;If handle is free don't add @RH4 + ADD AX,HANDLE_LOOKUP_TABLE.H_PAGES[SI] + ;add lengths (pages) of PALs @RH1 + ADD SI,TYPE H_LOOKUP_STRUC ; next entry in handle lookup @RH1 +AR_PGSUM_BOT: + LOOP AR_PAGESUM + CMP AX,TOTAL_EMS_PAGES ;pages in handle lookup > total? @RH1 + JNA AR_CALCHLUP ;no OK @RH1 + MOV AH,EMS_CODE80 ;software error..we screwed up @RH1 + JMP AR_EXIT ;go to exit @RH1 ;GGA + +AR_CALCHLUP: ;calculate entry in hndl lkup tbl @RH1 + cmp bx,0 ;page request? ;an000; dms; + jne AR_Alloc_Cont ;yes continue ;an000; dms; + cli ;ints off ;an001; dms; + mov Handle_LookUp_Table.H_Pages[di],bx ;new page count ;an001; dms; + sti ;ints on ;an001; dms; + xor ah,ah ;clear flag ;an000; dms; + jmp AR_Exit ;exit routine ;an000; dms; + +AR_Alloc_Cont: + + cli ;ints off ;an001; dms; + mov cx,bx ;alloc count ;an000; dms; + call EMS_Page_Contig_Chk ;do we have contig pgs. ;an001; dms; + jnc AR_Alloc ;yes continue process ;an001; dms; + mov ah,EMS_Code88 ;no signal error ;an001; dms; + sti ;ints on ;an001; dms; + jmp AR_Exit ;exit routine ;an001; dms; + +AR_Alloc: + + call EMS_Link_Set ;set up links ;an001; dms; + + + sub Free_Pages,bx ;free = free - requested pages + mov Handle_LookUp_Table.H_Pages[di],bx ;page count ;an000; dms; + mov Handle_LookUp_Table.H_Pal_Ptr[di],si ;initialize to ptr for ;ac001; dms; + ; pages + sti ;ints on ;an001; dms; + xor ah,ah ;clear flag ;an000; dms; + + +AR_EXIT: ;GGA + + POP DS + POP SI + POP DI + POP CX + POP BX + + ret ;return to caller ;an000; dms; + +Alloc_Raw endp ;end proc ;an000; dms; + + page +;========================================================================= +;=============== Function 5Ch Logic - Prepare for Warm Boot ============= +;========================================================================= + + +;========================================================================= +; Prepare_Boot - This routine prepares the hardware for a +; warm boot. Since we have no special hardware +; requirements at this time, this routine sets +; a good error level and returns to the caller. +; +; Inputs : AH - 5Ch (Prepare for Warm Boot) +; +; Outputs : AH - Non-zero if error (Determined by Get_Handle proc) +;========================================================================= + +Prepare_Boot proc ;prepare for warm boot ;an000; dms; + + xor ah,ah ;signal no error ;an000; dms; + + ret ;return to caller ;an000; dms; + +Prepare_Boot endp ;end proc ;an000; dms; + + + diff --git a/v4.0/src/DEV/XMA2EMS/MAKEFILE b/v4.0/src/DEV/XMA2EMS/MAKEFILE new file mode 100644 index 0000000..c739b08 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/MAKEFILE @@ -0,0 +1,24 @@ +#************************ makefile for dev\xma2ems************************ + +msg =..\..\messages +dos =..\..\dos +inc =..\..\inc +hinc =..\..\h + +# +####################### dependencies begin here. ######################### +# + +all: xma2ems.sys + +xma2ems.ctl: xma2ems.skl $(MSG)\$(country).MSG makefile + +xma2ems.obj: xma2ems.asm xma1diag.inc xma2ems.cl1 $(inc)\COPYRIGH.INC \ + parmpars.inc lim40.inc ps2_5060.inc makefile \ + emsinit.inc genioctl.inc xma2emsp.inc lim40b.inc romscan.inc \ + $(inc)\psdata.inc + +xma2ems.sys: xma2ems.obj makefile + link xma2ems; + exe2bin xma2ems.exe xma2ems.sys + del xma2ems.exe diff --git a/v4.0/src/DEV/XMA2EMS/PARMPARS.INC b/v4.0/src/DEV/XMA2EMS/PARMPARS.INC new file mode 100644 index 0000000..42ea6e8 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/PARMPARS.INC @@ -0,0 +1,530 @@ + PAGE +;-----------------------------------------------------------------------; +; GET_PARMS extracts parameters from the command line buffer ; +; ; +; On entry: all letters after 'Device=' have been changed ; +; to upper case ; +; ; +; On exit: (zf)=0 if syntax error ; +; if (zf)=1 then... ; +; ; +; EMM_START_BLOCK has been updated ; +; ; +; AX,BX,CX,DX,DI,SI,DS are destroyed ; +;-----------------------------------------------------------------------; + +include xma2emsp.inc ; include parser things +include parse.asm + +GET_PARMS PROC + LDS BX,CS:RH_PTRA ;make ds:bx point to request header + + LDS SI,RH.RH0_BPBA ;make ds:si point to bios paramter buffer + CLD + mov cs:EMS_Pgs_Parm,E_Parm_Def ;default to all of memory ;an000; dms; + +;------------------------------------------------------------------- +; parser support added by GGA +;------------------------------------------------------------------- + push cs ; make ES:DI point to parm block + pop es + lea di,p_block + + xor cx,cx ; cx = 0, ordinal + xor dx,dx ; dx = 0, reserved + + push ds ; save ds + +get_args: + pop ds ; restore ds + call SysParse ; call the parser + cmp ax,0 ; end of line? + je check_frame ; no, find out what we got this time + cmp ax,-1 ; end of parse? + je end_of_input_line1 ; yes + cmp ax,-1 ; flag an error + ret ; return to caller + +end_of_input_line1: + + jmp end_of_input_line ; + +; find out which arg was processed this time + +check_frame: + +; make ds point to data area for these comparisons, must restore before +; calling parser again + + push ds ; save ds + push es ; make ds point to save areas + pop ds + + cmp frame_result.$P_Type,2 ; was there a FRAME= in this pass? + jne check_p0 ; no, look for a P0 + + mov parse_flag,1 ; set parse flag + + mov byte ptr frame_ctl+9,0 ; turn this off so we don't allow another + mov frame_result.$P_Type,0 ; clear this so we don't get fooled later + + mov byte ptr p0_ctl+9,0 ; turn these off so we don't allow any + mov byte ptr p1_ctl+9,0 ; others that would conflict + mov byte ptr p2_ctl+9,0 + mov byte ptr p3_ctl+9,0 + + push si ;save regs + + mov si,word ptr frame_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 ;clear the + mov word ptr ds:[si+4],0 ; pages + mov word ptr ds:[si+8],0 + mov word ptr ds:[si+12],0 + + pop si ;restore regs + + +; set flags for later code to fill in map_table + + or page_flags,frame_flag ; set frame flag + + jmp get_args ; go get another argument + +check_p0: + cmp p0_result.$P_Type,2 ; was there a P0= in this pass? + jne check_p1 ; no, look for a P0 + + mov parse_flag,1 ; set parse flag + + mov byte ptr p0_ctl+9,0 ; turn this off so we don't allow another + mov p0_result.$P_Type,0 ; clear this so we don't get fooled later + + mov byte ptr frame_ctl+9,0 ; turn this off so we don't allow another + + push si ;save regs + + mov si,word ptr p0_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p0_flag ; set p0 flag + + jmp get_args ; go get another argument + +check_p1: + cmp p1_result.$P_Type,2 ; was there a p1= in this pass? + jne check_p2 ; no, look for a P2 + + mov parse_flag,1 ; set parse flag + + mov byte ptr p1_ctl+9,0 ; turn this off so we don't allow another + mov p1_result.$P_Type,0 ; clear this so we don't get fooled later + + mov byte ptr frame_ctl+9,0 ; turn this off so we don't allow another + + push si ;save regs + + mov si,word ptr p1_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p1_flag ; set p1 flag + + jmp get_args ; go get another argument + +check_p2: + cmp p2_result.$P_Type,2 ; was there a p2= in this pass? + jne check_p3 ; no, look for a p3 + + mov parse_flag,1 ; set parse flag + + mov byte ptr p2_ctl+9,0 ; turn this off so we don't allow another + mov p2_result.$P_Type,0 ; clear this so we don't get fooled later + + mov byte ptr frame_ctl+9,0 ; turn this off so we don't allow another + + push si ;save regs + + mov si,word ptr p2_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p2_flag ; set p2 flag + + jmp get_args ; go get another argument + +check_p3: + cmp p3_result.$P_Type,2 ; was there a p3= in this pass? + jne check_p254 ; no, look for a P254 + + mov parse_flag,1 ; set parse flag + + mov byte ptr p3_ctl+9,0 ; turn this off so we don't allow another + mov p3_result.$P_Type,0 ; clear this so we don't get fooled later + + mov byte ptr frame_ctl+9,0 ; turn this off so we don't allow another + + push si ;save regs + + mov si,word ptr p3_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p3_flag ; set p3 flag + + jmp get_args ; go get another argument + +check_p254: + cmp p254_result.$P_Type,2 ; was there a p254= in this pass? + jne check_p255 ; no, look for a P255 + + mov parse_flag,1 ; set parse flag + + mov byte ptr p254_ctl+9,0 ; turn this off so we don't allow another + mov p254_result.$P_Type,0 ; clear this so we don't get fooled later + + push si ;save regs + + mov si,word ptr p254_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p254_flag ; set p254 flag + + jmp get_args ; go get another argument + +check_p255: + cmp p255_result.$P_Type,2 ; was there a P255= in this pass? + je do_p255 ; yes, process it + jmp Check_X ; no, find out if /X was included + +do_p255: + mov parse_flag,1 ; set parse flag + + mov byte ptr p255_ctl+9,0 ; turn this off so we don't allow another + mov p255_result.$P_Type,0 ; clear this so we don't get fooled later + + push si ;save regs + + mov si,word ptr p255_result.$P_Picked_Val[+0] + + mov word ptr ds:[si+0],0 + + pop si ;restore regs +; set flags for later code to fill in map_table + + or page_flags,p255_flag ; set p255 flag + + jmp get_args ; go get another argument + +Check_X: + cmp es:X_Result.$P_SYNONYM_Ptr,offset es:X_Switch.$P_KeyorSW ; switch Ptr ;an000; dms; + je Do_X ; yes, process it + jmp get_args ; no, must have been the positional, ignore it and go on + +Do_X: + + push ax ; save regs + mov ax,es:word ptr X_Result.$P_Picked_Val ;get low word of result ;an000; dms; + mov cs:EMS_Pgs_Parm,ax ; pass to program ;an000; dms; + pop ax ; restore regs + + jmp get_args ; go get another argument + + + + +; getting here means invalid argument, figure out what to do later + +end_of_input_line: + + cmp parse_flag,null ; were there command line args? + jne cmd_line_args ; yes, process them + jmp null_cmd_line ; no, skip processing + +cmd_line_args: + +; put the stuff into map_table, this is done by looking at flags set +; by the above code and putting the addresses into map_table + + push ax ; save some regs + push bx + push cx + push dx + push di + + xor di,di ; clear index pointer + + mov map_count,null ; clear map count default + + test page_flags,frame_flag ; was FRAME= included? + jz chk_p0 ; no, try p0 + +; yes, fix up page count and fill in map_table + + mov map_count,4 ; FRAME= takes up 4 map entries + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,frame_result.$P_Item_Tag ; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + +; do some math with di + + xor di,di ; clear index pointer + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p0 segment + mov map_table.phys_page_number[di],0 ; p0 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + + add ax,400h ; increase segment ID by 16K + add di,type mappable_phys_page_struct + + mov map_table.phys_page_segment[di],ax ; store p1 segment + mov map_table.phys_page_number[di],1 ; p1 page number + + add ax,400h ; increase segment ID by 16K + add di,type mappable_phys_page_struct + + mov map_table.phys_page_segment[di],ax ; store p2 segment + mov map_table.phys_page_number[di],2 ; p2 page number + + add ax,400h ; increase segment ID by 16K + add di,type mappable_phys_page_struct + + mov map_table.phys_page_segment[di],ax ; store p3 segment + mov map_table.phys_page_number[di],3 ; p3 page number + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + + jmp chk_p254 ; FRAME= implies that p0 - p3 were not present, + ; skip ahead and look for p254 and p255 + +; check for p0 + +chk_p0: + + test page_flags,p0_flag ; was p0= included? + jz chk_p1 ; no, try p1 + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p0_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p0 segment + mov map_table.phys_page_number[di],0 ; p0 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +;------------------------ +; check for p1 +;------------------------ + +chk_p1: + + test page_flags,p1_flag ; was p1= included? + jz chk_p2 ; no, try p2 + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p1_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p1 segment + mov map_table.phys_page_number[di],1 ; p0 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +;------------------------ +; check for p2 +;------------------------ + +chk_p2: + + test page_flags,p2_flag ; was p2= included? + jz chk_p3 ; no, try p3 + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p2_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p2 segment + mov map_table.phys_page_number[di],2 ; p2 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +;------------------------ +; check for p3 +;------------------------ + +chk_p3: + + test page_flags,p3_flag ; was p3= included? + jz chk_p254 ; no, try p254 + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p3_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p3 segment + mov map_table.phys_page_number[di],3 ; p3 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +;------------------------ +; check for p254 +;------------------------ + +chk_p254: + + test page_flags,p254_flag ; was p254= included? + jz chk_p255 ; no, try p255 + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p254_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p254 segment + mov map_table.phys_page_number[di],0feh ; p254 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +;------------------------ +; check for p255 +;------------------------ + +chk_p255: + + test page_flags,p255_flag ; was p255= included? + jz Chk_X ; no, /X switch + +; yes, fix up page count and fill in map_table + + add map_count,1 ; one extra map entry + +; convert the item tag into a segment address + + xor ah,ah ; make 0 + mov al,p255_result.$P_Item_Tag; get item tag + mov cx,8 ; need to shift left eight bits + shl ax,cl ; to convert to a segment address + + +; save the segment addresses in map_table + + mov map_table.phys_page_segment[di],ax ; store p255 segment + mov map_table.phys_page_number[di],0ffh ; p255 page number + mov cs:Page_Frame_Sta,ax ;save our page for XMA1 ;an000; dms; + ; diags. + +; do some math with di, this will be used as a pointer into map_table + + add di,type mappable_phys_page_struct + +Chk_X: + + pop di ; restore some regs + pop dx + pop cx + pop bx + pop ax + + +null_cmd_line: + CMP AL,AL ; else set zf to indicate no error + ret ; return to calling routine + + +GET_PARMS ENDP diff --git a/v4.0/src/DEV/XMA2EMS/PS2_5060.INC b/v4.0/src/DEV/XMA2EMS/PS2_5060.INC new file mode 100644 index 0000000..96425f5 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/PS2_5060.INC @@ -0,0 +1,735 @@ +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Include File: PS2_5060.INC ³ +;³ ³ +;³ Purpose: Initialization code for the Personal Systems/2 ³ +;³ models 50 and 60. ³ +;³ ³ +;³ Returns: INIT_ERR ³ +;³ Flag indicating if an error was detected. ³ +;³ DX = ptr to error message string if error. ³ +;³ ³ +;³ This procedure is called to initialize the XMO and/or XMA/A ³ +;³ card(s) on a PS/2 mod 50 or 60. Any mix of multiple XMA and ³ +;³ XMO cards are supported. The XMA cards will be used in ³ +;³ 'real' mode, meaning the virtual mode ports providing bank ³ +;³ swapping are not used (since this only works on 1 XMA card). ³ +;³ This procedure is not called if WSP's XMA/A device driver ³ +;³ (INDXMAA.SYS) is installed. In this case only the single XMA ³ +;³ card is used for EMS, and it is spoken to in 'virtual' mode. ³ +;³ The procedure searches each adapter slot for the presence of ³ +;³ an XMA or a XMO card by checking the card ID. It checks ³ +;³ the configuration registers on the cards to determine the amount ³ +;³ of memory they contain. ³ +;³ The procedure will then calculate for the /E parameter. This ³ +;³ states how much of the extended memory the user wants for EMS. ³ +;³ Extended memory will come from the top of the address range, ³ +;³ and EMS will come off the bottom (i.e. starting at 1M+384K). ³ +;³ Memory kept as extended has to be marked unusable in the Page ³ +;³ Allocation List. Translate table entries in extended memory ³ +;³ are disabled for memory used for EMS. ³ +;³ Note that the /E parameter is only valid within this ³ +;³ procedure, i.e. for PS/2 mod 50 and 60's. On family 1 machines, ³ +;³ only the XMA 1 card is supported, and it doesn't come up as ³ +;³ extended memory. On mod 50 or 60 with the XMA/A driver, the ³ +;³ driver takes all of the (uppermost) XMA card and resets CMOS. ³ +;³ On the mod 80 with the XMA emulator, this XMA/extended split ³ +;³ must be specified on the Emulator's parm line. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +include SYSVAR.INC ;system variables structure ;an007; dms; + + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ XMA/A declares ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +HI6BIT_MASK EQU 00000011b ;Mask for 2 bit bank descriptor +LO2BIT_FLIP EQU 00000011b ;Reverses bottom 2 bits in bank des + ; gives # of 1/2M in that bank +NUM_CONFR_BANKS EQU 3 ;Number of memory banks described + ; by the XMA/A config register + ; Bank 4 is on the control reg. +X_CONF_REG_VAL DB ? ;temporary holder for XMAA's + ; config (memory size) register +X_CTRL_REG_VAL DB ? ;temporary holder for XMAA's + ; control (mem size bank 4) reg. +X_BLKS_PER_HALFM DB 128 ;4K blocks per half meg of memory +XMAA_NUM_BLOCKS DW ? ;temp for # of 4K blocks on xmaa @RH2 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Expanded Memory Option (XMO) declares ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +NUM_CINFO_BANKS EQU 3 ;# of complete memory banks (4-2) + ; described by the XMO card info reg + ; Bank 1 - hi 1/2 bit - info, lo CC/P +H_CARD_INFO_VAL DB ? ;temporary holder for XMO card's + ; info (memory size) register +H_BLKS_PER_HALFM DB 32 ;16K XMO card blocks per 1/2M of mem +HLST_NUM_BLOCKS DW ? ;temp for # of 16K blocks on hlstr @RH3 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ /E option declares ³ + ;³ (used to set extended memory) ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +ems_pgs_parm dw 0 ;temp value for /E parameter +e_parm_def equ 0FFFFh ;default...take all for ems +MIN_EXTMEM_H EQU (1024+384)/16 ;Translate table pointer for the lowest +MIN_EXTMEM_X EQU (1024+384)/4 ; addr extended memory can start at on +BASE_MEM EQU 1024 ;Base planer memory ;an007; dms; + ; a PS/2 (16K XMO and 4K XMA) +PREV_EXT_PGS DW 0 ;Extended memory claimed by previous + ; drivers +NEEDED_EMS_PGS DW ? ;Pages that will go for EMS use +CARDS_PGS DW ? ;Number of pages on card being checked +CARD_EXT_S16K DW ? ; and where its extended memory starts + ; expressed in 16K blocks + +INIT_MOD_50_60 PROC + + PUSH AX + PUSH BX + PUSH CX + PUSH SI + PUSH DI + + MOV INIT_ERR,NO_ERROR ;Initialize error flag @RH4 + MOV TOTAL_SYS_PAGES,0 ;Init total number of pages in the @RH2 + MOV NUM_MEM_CARDS,0 ; system & # of memory cards found @RH2 + XOR DI,DI ;Clear offset into mem card table @RH2 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Search for XMO cards ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + XOR CX,CX ;Check all system slots starting @RH2 + ; at slot 0 RH2 +H_SLOT_SCAN: + MOV AL,CL ;Enable the specific slot by ORing @RH2 + OR AL,SLOT_SETUP ; the slot (bits 0-2) with the @RH2 + OUT 96h,AL ; setup flag (bit 3). @RH2 + + MOV DX,CARD_ID_LO ;Read the signature ID of the card @RH2 + IN AL,DX ; @RH2 + XCHG AL,AH ; @RH2 + MOV DX,CARD_ID_HI ; @RH2 + IN AL,DX ; @RH2 +HLST_CHECK: + CMP AX,HLST_CARD_ID ;If it's a XMO card then @RH3 + JNE H_NEXT_SLOT ; calculate the amount of memory @RH3 + CALL HLST_MEM_ADD ; on the card @RH3 + MOV WTT_CARD_SLOT,CL ;Set default slot # and card type @RH5 + MOV MEMCARD_MODE,HOLS_REAL ; for single card support @RH5 + + MOV BX,HLST_NUM_BLOCKS ;1 XMO card block = an EMS page + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Save info in the memory card table ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV MEM_CARD_TABLE.CARD_ID[DI],AX ;Save the card ID and @RH5 + MOV MEM_CARD_TABLE.CARD_SLOT[DI],CL ; slot # of this card @RH5 + MOV AX,TOTAL_SYS_PAGES ;Set # of the 1st EMS @RH5 + MOV MEM_CARD_TABLE.START_PG_NUM[DI],AX ; page this card maps @RH5 + ADD AX,BX ;Last page mapped = @RH5 + DEC AX ; 1st pg + pages on @RH5 + MOV MEM_CARD_TABLE.END_PG_NUM[DI],AX ; this card - 1. @RH5 + + ADD TOTAL_SYS_PAGES,BX ;Add card's pgs to tot. @RH5 + INC NUM_MEM_CARDS ;Inc # of cards found @RH5 + ADD DI,TYPE MEM_CARD_STRUC ;Next entry in card @RH5 + ; descriptor table RH5 + +H_NEXT_SLOT: + INC CL ;Check next adapter slot @RH2 + CMP CL,NUM_OF_SLOTS ;Is it <= system slots? @RH2 + JB H_SLOT_SCAN ;Yes..check next slot ;ac000; dms; + ;No fall through loop RH2 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Search for XMA/A cards ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + XOR CX,CX ;Check all slots starting at 0 @RH2 +X_SLOT_SCAN: + MOV AL,CL ;Enable the specific slot by ORing @RH2 + OR AL,SLOT_SETUP ; the slot (bits 0-2) with the @RH2 + OUT 96h,AL ; setup flag (bit 3). @RH2 + + MOV DX,CARD_ID_LO ;Read the signature ID of the card @RH2 + IN AL,DX ; @RH2 + XCHG AL,AH ; @RH2 + MOV DX,CARD_ID_HI ; @RH2 + IN AL,DX ; @RH2 +XMAA_CHECK: + CMP AX,XMAA_CARD_ID ;If it's an XMA/A card then @RH2 + JNE X_NEXT_SLOT ; calculate the amount of memory @RH2 + CALL XMAA_MEM_ADD ; on the card @RH2 + MOV WTT_CARD_SLOT,CL ;Set default slot # and card type @RH5 + MOV MEMCARD_MODE,XMAA_REAL ; for single card support @RH5 + + MOV BX,XMAA_NUM_BLOCKS ;Divide the # of 4K XMA/A blocks @RH2 + SHR BX,1 ; by 4 to get number or 16K EMS @RH2 + SHR BX,1 ; pages on this card @RH2 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Save info in the memory card table ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV MEM_CARD_TABLE.CARD_ID[DI],AX ;Save the card ID and @RH5 + MOV MEM_CARD_TABLE.CARD_SLOT[DI],CL ; slot # of this card @RH5 + MOV AX,TOTAL_SYS_PAGES ;Set # of the 1st EMS @RH5 + MOV MEM_CARD_TABLE.START_PG_NUM[DI],AX ; page this card maps @RH5 + ADD AX,BX ;Last page mapped = @RH5 + DEC AX ; 1st pg + pages on @RH5 + MOV MEM_CARD_TABLE.END_PG_NUM[DI],AX ; this card - 1. @RH5 + + ADD TOTAL_SYS_PAGES,BX ;Add card's pgs to tot. @RH5 + INC NUM_MEM_CARDS ;Inc # of cards found @RH5 + ADD DI,TYPE MEM_CARD_STRUC ;Next entry in card @RH5 + ; descriptor table RH5 + +X_NEXT_SLOT: + INC CL ;Check next adapter slot @RH2 + CMP CL,NUM_OF_SLOTS ;Is it <= system slots? @RH2 + JB X_SLOT_SCAN ;Yes..check next slot ;ac000; dms; + ;No fall through loop RH2 + + CMP TOTAL_SYS_PAGES,0 ;If one or more cards are found @RH4 + JA CALC_EXTENDED ; then everythang's cool so far @RH4 + MOV INIT_ERR,ERROR ;Else no card...set @RH4 + MOV DX,OFFSET NOT_FOUND_MSG ; 1st part of error msg @RH4 + JMP INIT_50_60_RET ; for no card found @RH4 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Calculate /E parameter - amount of memory for EMS ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Find ext mem addr of bottom card ³ + ;³ in case card memory ever starts at ³ + ;³ something other than 1M + 384K ³ + ;³ (i.e. if more planar memory is ³ + ;³ added or a new unsupported card ³ + ;³ comes in below XMO card) ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +CALC_EXTENDED: + push es ;this call kills these regs ;an007; dms; + push bx ; ;an007; dms; + + mov ah,52h ;get the sysvars ptr ;an007; dms; + int 21h ; to get total ext. memory at boot ;an007; dms; + mov ax,word ptr es:[bx].SYSI_Ext_Mem ; ;an007; dms; + + pop bx ;restore regs ;an007; dms; + pop es ; ;an007; dms; + + add ax,Base_Mem ; + base memory ;an007; dms; + MOV CL,4 ; convert to 16Kb pages ;an007; dms; + SHR AX,CL ; ;an007; dms; + sub ax,cs:Total_Sys_Pages ;get page where card begins ;an007; dms; + + xor di,di ;init. index value ;an008; dms + CMP MEM_CARD_TABLE.CARD_ID[DI],HLST_CARD_ID ;If 1st card holst @RH4 + JE FIND_H_1ST_TT ; then get hlst TT @RH4 +FIND_X_1ST_TT: ;XMAA is 1st card (lowest ext mem) @RH4 +;;;;; MOV AX,MIN_EXTMEM_X ;Set XMAA TT ptr at 1.384M and @RH4 + shl ax,1 ; ;an000; dms; + shl ax,1 ; ;an000; dms; +FIND_X_1ST_LOOP: ; search for start of ext mem @RH4 + CALL X_READ_TT ;Read trans tbl data at this addr @RH4 + CMP BX,XMA_TT_INHIBIT ;If not inhibitted then mem here. @RH4 + JE FIND_X_1ST_NEXT ;Divide the 4K translate table ptr @RH4 + MOV CL,2 ; by 4 to convert it to 16K format @RH4 + SHR AX,CL ; AX = start of ext mem (in 16K) @RH4 + JMP FIRST_EXT_FOUND ; @RH4 +FIND_X_1ST_NEXT: ; @RH4 + INC AX ;Else no mem...inc TT ptr and see @RH4 + JMP FIND_X_1ST_LOOP ; if ext mem starts at next 4K @RH4 + +FIND_H_1ST_TT: ;XMO is 1st card (lowest ext mem) @RH4 +;;;;; MOV AX,MIN_EXTMEM_H ;Set hlst TT ptr at 1.384M and @RH4 +FIND_H_1ST_LOOP: ; search for start of ext mem @RH4 + CALL H_READ_TT ;Read trans tbl data at this addr @RH4 + CMP BL,H_TT_INHIBIT ;If not inhibitted then mem here. @RH4 + JNE FIRST_EXT_FOUND ; found start of card ext mem @RH4 + INC AX ;Else no mem...inc TT ptr and see @RH4 + JMP FIND_H_1ST_LOOP ; if ext mem starts at next 16K @RH4 +FIRST_EXT_FOUND: + MOV CARD_EXT_S16K,AX ;Save the start of ext mem ptr @RH4 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Calc pages for extended memory ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AH,88H ;Go to BIOS and find amount of @RH4 + INT 15H ; extended memory (assume previous @RH4 + MOV CL,4 ; drivers have hooked INT 15h) @RH4 + SHR AX,CL ;Get # of 16k pages @RH4 + + MOV BX,CARD_EXT_S16K ;Pages of extended memory used @RH4 + ADD BX,TOTAL_SYS_PAGES ; by previous drivers = @RH4 + SUB BX,1024/16 ; what we know is the # of ext @RH4 + SUB BX,AX ; pages minus what BIOS tells us @RH4 + MOV PREV_EXT_PGS,BX ; @RH4 + + CMP EMS_PGS_PARM,E_PARM_DEF ;If no /E parm specified then @RH4 + JNE CHECK_E_PARM ; use the remaining pages for EMS @RH4 + MOV AX,TOTAL_SYS_PAGES ; (total on cards minus previously @RH4 + cmp Prev_Ext_Pgs,ax ;Previous ext pages >= avail on cards? ;an000; dms; + jae Default_Mem_Err_Exit ;yes - we have used the whole card ;an000; dms; + SUB AX,PREV_EXT_PGS ; used for extended memory) @RH4 + MOV NEEDED_EMS_PGS,AX ;Set counter for marking PAL and TT@RH4 + JMP SHORT MARK_EXT_IN_PAL + +Default_Mem_Err_Exit: + + mov Init_Err,Error ;flag an error occurred ;an000; dms; + lea dx,No_EMS_Memory ;no memory on cards left ;an000; dms; + jmp Init_50_60_Ret ;exit routine ;an000; dms; + +CHECK_E_PARM: ;Else test user specified # EMS pgs@RH4 + MOV BX,EMS_PGS_PARM ;Set counter for marking Page @RH4 + MOV NEEDED_EMS_PGS,BX ; Allocation List and TT entries @RH4 + MOV AX,TOTAL_SYS_PAGES ;If the requested EMS pages are @RH4 + SUB AX,PREV_EXT_PGS ; more than what's left @RH4 + CMP AX,EMS_PGS_PARM ; (total pages minus pages @RH4 + JGE MARK_EXT_IN_PAL ; used by other drivers) then set @RH4 + MOV INIT_ERR,ERROR ; an error condition flag @RH4 + LEA DX,REQ_EMS_ERR_MSG ; Set first part of error message @RH4 + JMP INIT_50_60_RET ; @RH4 + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Mark PAL for extended memory pages ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +MARK_EXT_IN_PAL: + xor di,di ;start at bottom of PAL to init EXT ;an002; dms; +MARK_NEW_IN_PAL: + MOV CX,TOTAL_SYS_PAGES ;Loop for the 'new' extended pages @RH4 + SUB CX,NEEDED_EMS_PGS ; (left over from /E parm and not @RH4 + SUB CX,PREV_EXT_PGS ; reserved by a previous driver) @RH4 + MOV RESR_EXT_PGS,CX ; @RH4 + CMP CX,0 ; This assumes that others anyone @RH4 + JE MARK_PREV_IN_PAL ; using extended memory after us @RH4 +MARK_NEW_LP: ; will take it from the top @RH4 + MOV PAGE_ALLOC_LIST[DI],RESR_EXT ;Place a 'RE' in the PAL @RH4 + ADD DI,TYPE PAGE_ALLOC_LIST ; (Reserved Extended) for @RH4 + LOOP MARK_NEW_LP ; these entries @RH4 + +MARK_PREV_IN_PAL: + MOV AX,NEEDED_EMS_PGS ;Set offset into Page Alloc List @RH4 + add ax,Resr_Ext_Pgs ;get end of area for EMS pages ;an002; dms; + MOV DX,TYPE PAGE_ALLOC_LIST ; for the page where extended mem @RH4 + MUL DX ; starts. This is done by skipping@RH4 + MOV DI,AX ; over the EMS pages on bottom @RH4 + MOV CX,PREV_EXT_PGS ;Loop for the previous extended @RH4 + CMP CX,0 ; memory pages (if any). This is @RH4 + JE DIS_EMS_TT ; ext mem claimed before we load @RH4 +MARK_PREV_LP: ; @RH4 + MOV PAGE_ALLOC_LIST[DI],PREV_EXT ;Place a 'PE' in the PAL @RH4 + ADD DI,TYPE PAGE_ALLOC_LIST ; (Previous Extended) for @RH4 + LOOP MARK_PREV_LP ; these entries @RH4 + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Disable translate table entries ³ + ;³ in extended memory for memory ³ + ;³ used as EMS ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +DIS_EMS_TT: + + mov cx,Resr_Ext_Pgs ;get extended page count ;ac008; dms; + ;1 based page count + + xor di,di ;set mem card table ptr ;an002; dms; + +Card_Find_Chk: + + cmp cx,Mem_Card_Table.End_Pg_Num[di];page > ending page on card? ;ac008; dms; + ja Card_Find_Loop ;yes - next card please ;an002; dms; + add Card_Ext_S16K,cx ;get 1st. avail page ;an008; dms; + mov cx,Mem_Card_Table.End_Pg_Num[di];Calc # pages remaining on card ;an002; dms; + sub cx,Resr_Ext_Pgs ; ;ac008; dms; + inc cx ; ;an002; dms; + jmp Calc_Cards_EMS ; ;an002; dms; + +Card_Find_Loop: + + add di,Type Mem_Card_Struc ;next pointer ;an002; dms; + jmp Card_Find_Chk ;continue loop ;an002; dms; + + +CALC_CARDS_EMS: + + MOV CARDS_PGS,CX ; @RH4 + + ;Calc # of pages to inhibit for. @RH4 + CMP CX,NEEDED_EMS_PGS ;If the card has less pgs than @RH4 + JBE ADJUST_NEEDED_EMS ; # needed for EMS then just loop @RH4 + MOV CX,NEEDED_EMS_PGS ; for card. Else loop for needed. @RH4 + +ADJUST_NEEDED_EMS: + SUB NEEDED_EMS_PGS,CX ;Remaining EMS pages to inhibit @RH4 + ; after this card is taken care of @RH4 + + MOV AL,MEM_CARD_TABLE.CARD_SLOT[DI] ;Activate the slot of @RH4 + OR AL,SLOT_SETUP ; the card and set ptr @RH4 + OUT 96h,AL ; to where it's ext mem @RH4 + MOV AX,CARD_EXT_S16K ; starts @RH4 + + CMP MEM_CARD_TABLE.CARD_ID[DI],HLST_CARD_ID ;Test card type @RH4 + JE H_INHIBIT_EMS ; @RH4 +X_INHIBIT_EMS: ;Inhibit TT on XMA/A for EMS @RH4 + PUSH CX ;Save ctr for # EMS on this card @RH4 + MOV CL,2 ;Convert 16K start of EMS ptr to @RH4 + SHL AX,CL ; 4K XMA/A translate table format @RH4 + POP CX ;Restore # EMS pages counter @RH4 +X_INH_EMS_PGS: ;----Loop for all XMA EMS pages----@RH4 + PUSH CX ;Save # EMS pages ctr @RH4 + MOV CX,BLOCKS_PER_PAGE ;Loop for all XMA blocks in a pg @RH4 +X_INH_ONE_PAGE: ;----Loop for one XMA EMS page-----@RH4 + CALL X_INH_FOR_EMS ;Inhibit TT entry (AX = 4K ptr) @RH4 + INC AX ;Next XMA block @RH4 + LOOP X_INH_ONE_PAGE ; @RH4 + POP CX ;Restore ctr for # EMS pgs on card @RH4 + LOOP X_INH_EMS_PGS ;Loop for # EMS pgs on card @RH4 + JMP short next_card_ems ;Now go fix that page alloc table @RH4 + +H_INHIBIT_EMS: ;Inhibit TT on XMO for EMS @RH4 + CALL H_INH_FOR_EMS ;Inhibit one TT entry per EMS page @RH4 + INC AX ;Next 16K pointer @RH4 + LOOP H_INHIBIT_EMS ; and do it again yahoooooo @RH4 + +NEXT_CARD_EMS: + CMP NEEDED_EMS_PGS,0 ;If this card had the rest of the @RH4 + JE INIT_50_60_RET ; EMS pages then done disabling TT @RH4 + ;Else EMS on next card. Set ptr @RH4 + MOV AX,CARDS_PGS ; to where next card's ext mem @RH4 + ADD CARD_EXT_S16K,AX ; starts (in units of 16K) and save@RH4 + + ADD DI,TYPE MEM_CARD_STRUC ;Next entry in the memory card @RH4 + + mov cx,Mem_Card_Table.End_Pg_Num[di] ;calc pages on ;an002; dms; + sub cx,Mem_Card_Table.Start_Pg_Num[di] ;card ;an002; dms; + inc cx ; ;an002; dms; + + JMP CALC_CARDS_EMS ; table. @RH4 + +INIT_50_60_RET: + + MOV AX,TOTAL_SYS_PAGES ;Total EMS pages in the system = @RH4 + SUB AX,PREV_EXT_PGS ; pages on cards - amount used @RH4 + SUB AX,RESR_EXT_PGS ; as extended memory @RH4 + MOV TOTAL_SYS_PAGES,AX ;Initialize values for: @RH4 + MOV TOTAL_EMS_PAGES,AX ; EMS pages - pages to back planar @RH4 + MOV FREE_PAGES,AX ; EMS pages free for applications @RH4 + + MOV AL,0 ;Reset the slot ID @RH5 + OUT 96h,AL ; @RH5 + + POP DI + POP SI + POP CX + POP BX + POP AX + RET +INIT_MOD_50_60 ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ HLST_MEM_ADD subprocedure ³ +;³ Calculates the amount of memory on the XMO card ³ +;³ on entry: (CL) = card slot # ³ +;³ card is in setup mode ³ +;³ ³ +;³ The following describes how to read memory size, where the 2 bit ³ +;³ pattern indicates SIP size. There are 2 SIPs per bank. ³ +;³ ³ +;³ Reg: Card Info Channel Check, Presence ³ +;³ Port: 102h 105h ³ +;³ SIPS: bank 4 bank 3 bank 2 bank 1 bank 1 ³ +;³ Bit: 7 6 5 4 3 2 1 0 ³ +;³ -----------------------------------------------------------------³ +;³ 1 1 1 1 1 1 1 1 No memory,error ³ +;³ 1 0 1 0 1 0 1 0 256K ³ +;³ 0 1 0 1 0 1 0 1 512K ³ +;³ 0 0 0 0 0 0 0 0 1M ³ +;³ ³ +;³ Note that for bank 0, 102's bit 1 forms the upper bit and ³ +;³ 105's bit 0 forms the lower of the 2 bit presence pattern. ³ +;³ Therefore, if the pattern is '10'B, then the bank has 256K. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +HLST_MEM_ADD PROC + PUSH DX ; @RH3 + PUSH CX ; @RH3 + PUSH AX ; @RH3 + + MOV HLST_NUM_BLOCKS,0 ;Init # of 16K blocks on card @RH3 + + MOV DX,H_CARD_INFO ;Read & store card info reg (102h) @RH3 + IN AL,DX ; bits 7-2 describe banks 4-2 @RH3 + AND AL,11111110B ; bit 1 upper half of bank 1 descr @RH3 + MOV H_CARD_INFO_VAL,AL ; (don't care about sleep bit 0) @RH3 + MOV DX,H_CC_PRES ;Read chan. check & presence (105) @RH3 + IN AL,DX ; for bit 0 - lower half of bank 1 @RH3 + AND AL,00000001B ; Turn off all other bits @RH3 + OR AL,H_CARD_INFO_VAL ;Join 2 bits - bank 1 descriptor @RH3 + + XOR AL,LO2BIT_FLIP ;Flip these 2 to get # of 1/2 Megs @RH3 + ; in bank 1 of XMO card @RH3 + AND AL,HI6BIT_MASK ;Clear other bits @RH3 + CMP AL,LO2BIT_FLIP ;Are both bits on (i.e. 1M sips)? @RH3 + JNE H_B1_HMEG_OK ;No # of 1/2 M for bank OK (0,1,2)@RH3 + INC AL ;Yes # of 1/2 M should be 4 not 3 @RH3 +H_B1_HMEG_OK: + MUL H_BLKS_PER_HALFM ;Multiply by # of 16k Blocks per @RH3 + ; half meg to get bank's blocks @RH3 + ADD HLST_NUM_BLOCKS,AX ;Add bank 1 to the total @RH3 + + SHR H_CARD_INFO_VAL,1 ;Shift bank 4-2 descriptors to @RH3 + SHR H_CARD_INFO_VAL,1 ; bits 0-5 @RH3 + + MOV CX,NUM_CINFO_BANKS ; Loop for banks accounted for by @RH3 + ; the XMO card info register @RH3 +HLST_MEM_LOOP: + MOV AL,H_CARD_INFO_VAL ;Get 2 bit bank descriptor & flip @RH3 + XOR AL,LO2BIT_FLIP ; the 2 bits. Bits now indicate @RH3 + ; the # of 1/2 meg in the bank @RH3 + AND AL,HI6BIT_MASK ;Ignore other banks @RH3 + CMP AL,LO2BIT_FLIP ;Are both bits on (i.e. 1M sips)? @RH3 + JNE H_B42_HMEG_OK ;No # of 1/2 M for bank OK (0,1,2)@RH3 + INC AL ;Yes # of 1/2 M should be 4 not 3 @RH3 +H_B42_HMEG_OK: + MUL H_BLKS_PER_HALFM ;Multiply by # of 4k blocks per @RH3 + ; half meg to get bank's blocks @RH3 + ADD HLST_NUM_BLOCKS,AX ;Add XMO banks 4-2 to total @RH3 + SHR H_CARD_INFO_VAL,1 ;Get next bank @RH3 + SHR H_CARD_INFO_VAL,1 ; @RH3 + LOOP HLST_MEM_LOOP ; @RH3 + + POP AX ; @RH3 + POP CX ; @RH3 + POP DX ; @RH3 + + RET +HLST_MEM_ADD ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ XMAA_MEM_ADD subprocedure ³ +;³ Calculates the amount of memory on the XMAA card ³ +;³ on entry: (CL) = card slot # ³ +;³ card is in setup mode ³ +;³ ³ +;³ The following describes how to read memory size, where the 2 bit ³ +;³ pattern indicates SIP size. There are 2 SIPs per bank. ³ +;³ ³ +;³ Reg: Control Reg Config, Channel Check reg ³ +;³ Port: 102h 105h ³ +;³ SIPS: bank 4 bank 3 bank 2 bank 1 ³ +;³ Bit: 7 6 5 4 3 2 1 0 ³ +;³ ------------------------------------------------- ³ +;³ 1 1 1 1 1 1 1 1 No memory or error ³ +;³ 1 0 1 0 1 0 1 0 256K ³ +;³ 0 1 0 1 0 1 0 1 512K ³ +;³ 0 0 0 0 0 0 0 0 1M ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +XMAA_MEM_ADD PROC + PUSH DX ; @RH2 + PUSH CX ; @RH2 + PUSH AX ; @RH2 + + ;Insure XMA/A init ROM is disabled @RH2 + ;When the high byte of the TT data @RH2 + MOV DX,X_CTRL_REG + IN AL,DX ; is read or written using port @RH2 + MOV X_CTRL_REG_VAL,AL ; SAVE FOR MEM COUNT + AND AL,CR_ROMSLEEP_DIS ; 104h (real mode), the upper @RH2 + OUT DX,AL ; nibble has info for setting the @RH2 + ; initialization ROM addresses. To @RH2 + ; insure this causes no problems, @RH2 + ; disable XMA/A ROM by clearing @RH2 + ; ROM sleep bit in the control reg @RH2 + + MOV XMAA_NUM_BLOCKS,0 ; @RH2 + + MOV AL,X_CTRL_REG_VAL ;Get bits 6&7 of control register @RH2 + MOV CL,6 ; to get memory configuration of @RH2 + SHR AL,CL ; bank 4 @RH2 + XOR AL,LO2BIT_FLIP ;Flip these 2 to get # of 1/2M @RH2 + ; in bank 4 of XMA/A card @RH2 + AND AL,HI6BIT_MASK ;Clear other bits @RH2 + CMP AL,LO2BIT_FLIP ;Are both bits on (i.e. 1M sips)? @RH2 + JNE CTRL_HMEG_OK ;No # of 1/2 M for bank OK (0,1,2)@RH2 + INC AL ;Yes # of 1/2 M should be 4 not 3 @RH2 +CTRL_HMEG_OK: + MUL X_BLKS_PER_HALFM ;Multiply by # of 4k blocks per @RH2 + ; half meg to get bank's blocks @RH2 + ADD XMAA_NUM_BLOCKS,AX + + + MOV DX,X_CONF_REG ;Read the config, channel check @RH2 + IN AL,DX ; register to get mem size of @RH2 + MOV X_CONF_REG_VAL,AL ; banks 1-3 @RH2 + + MOV CX,NUM_CONFR_BANKS ; Loop for banks accounted for by @RH2 + ; the config register @RH2 +XMAA_MEM_LOOP: + MOV AL,X_CONF_REG_VAL ;Get 2 bit bank descriptor & flip @RH2 + XOR AL,LO2BIT_FLIP ; the 2 bits. Bits now indicate @RH2 + ; the # of 1/2 meg in the bank @RH2 + AND AL,HI6BIT_MASK ;Ignore other banks @RH2 + CMP AL,LO2BIT_FLIP ;Are both bits on (i.e. 1M sips)? @RH2 + JNE CONF_HMEG_OK ;No # of 1/2 M for bank OK (0,1,2)@RH2 + INC AL ;Yes # of 1/2 M should be 4 not 3 @RH2 +CONF_HMEG_OK: + MUL X_BLKS_PER_HALFM ;Multiply by # of 4k blocks per @RH2 + ; half meg to get bank's blocks @RH2 + ADD XMAA_NUM_BLOCKS,AX ; @RH2 + SHR X_CONF_REG_VAL,1 ;Get next bank @RH2 + SHR X_CONF_REG_VAL,1 ; @RH2 + LOOP XMAA_MEM_LOOP ; @RH2 + + POP AX ; @RH2 + POP CX ; @RH2 + POP DX ; @RH2 + + RET +XMAA_MEM_ADD ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ H_READ_TT subprocedure ³ +;³ Reads the contents of a translate table entry on a XMO card ³ +;³ on entry: (AX) = Translate table pointer ³ +;³ on exit: (BL) = Data (byte) at that entry ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +H_READ_TT PROC + PUSH AX ;Save the TT pointer @RH4 + MOV DX,H_TTPTR_LO ;Set the low and high bytes of @RH4 + OUT DX,AL ; the XMO translate table @RH4 + XCHG AL,AH ; pointer, then read the value @RH4 + MOV DX,H_TTPTR_HI ; of the data for that entry @RH4 + OUT DX,AL ; @RH4 + MOV DX,H_TTDATA ; @RH4 + IN AL,DX ;Read the data into AL @RH4 + MOV BL,AL ; and store it in BL @RH4 + POP AX ;Restore TT pointer @RH4 + RET ; @RH4 +H_READ_TT ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ X_READ_TT subprocedure ³ +;³ Reads the contents of a translate table entry on an XMA/A card ³ +;³ on entry: (AX) = Translate table pointer ³ +;³ on exit: (BX) = Data (12 bits) at that entry ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +X_READ_TT PROC + PUSH AX ;Save the TT pointer @RH4 + MOV DX,RM_TTPTR_LO ;Set the low and high bytes of @RH4 + OUT DX,AL ; the XMA/A translate table @RH4 + XCHG AL,AH ; pointer, then read the value @RH4 + MOV DX,RM_TTPTR_HI ; of the data for that entry @RH4 + OUT DX,AL ; @RH4 + + MOV DX,RM_TTDATA_HI ;Read 12 bit TT data high byte @RH4 + IN AL,DX ; first, then read low byte. @RH4 + XCHG AL,AH ; @RH4 + MOV DX,RM_TTDATA_LO ; @RH4 + IN AL,DX ; @RH4 + MOV BX,AX ;Store result in BX @RH4 + AND BX,XMA_TT_MASK ;Turn off useless upper 4 bits @RH4 + POP AX ;Restore TT pointer @RH4 + RET ; @RH4 +X_READ_TT ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ H_INH_FOR_EMS subprocedure ³ +;³ Inhibits a single translate table entry of extended memory ³ +;³ on a XMO card. This entry (16K) is for use by EMS. ³ +;³ on entry: (AX) = XMO Translate table pointer (# of K / 16) ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +H_INH_FOR_EMS PROC + PUSH AX ;Save the TT pointer @RH4 + MOV DX,H_TTPTR_LO ;Set the low and high bytes of @RH4 + OUT DX,AL ; the XMO translate table @RH4 + XCHG AL,AH ; pointer, @RH4 + MOV DX,H_TTPTR_HI ; @RH4 + OUT DX,AL ; @RH4 + + MOV AL,H_TT_INHIBIT ;AL = XMO TT inhibit data @RH4 + MOV DX,H_TTDATA ;Inhibit this TT entry so that @RH4 + OUT DX,AL ; it is no longer extended memory @RH4 + POP AX ;Restore TT pointer @RH4 + RET ; @RH4 +H_INH_FOR_EMS ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ X_INH_FOR_EMS subprocedure ³ +;³ Inhibits a single translate table entry of extended memory ³ +;³ on a XMA/A card. This entry (4K) is for use by EMS. ³ +;³ on entry: (AX) = XMA/A Translate table pointer (# of K / 4) ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +X_INH_FOR_EMS PROC + PUSH AX ;Save the TT pointer @RH4 + MOV DX,RM_TTPTR_LO ;Set the low and high bytes of @RH4 + OUT DX,AL ; the XMA/A translate table @RH4 + XCHG AL,AH ; pointer, then read the value @RH4 + MOV DX,RM_TTPTR_HI ; of the data for that entry @RH4 + OUT DX,AL ; @RH4 + + MOV AX,XMA_TT_INHIBIT ;AX = XMA 12 bit TT inhibit data @RH4 + MOV DX,RM_TTDATA_LO ;Write 12 bit TT data low byte @RH4 + OUT DX,AL ; first, then write high byte. @RH4 + XCHG AL,AH ; @RH4 + MOV DX,RM_TTDATA_HI ; @RH4 + OUT DX,AL ; @RH4 + POP AX ;Restore TT pointer @RH4 + RET ; @RH4 +X_INH_FOR_EMS ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ ADJUST_CMOS subprocedure ³ +;³ Reset the CMOS value for amount of extended memory. The ³ +;³ memory off the 'top' (upper addresses) is used by EMS. ³ +;³ on entry: ³ +;³ CARD_EXT_S16K = First 16K translate table pointer past the ³ +;³ top of the last card. Example - One 2M card ³ +;³ that started at 1M+384K, AX = 58h + 80H = D8h ³ +;³ ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +ADJUST_CMOS PROC +CMOS_LO EQU 70h ;Port addrs of CMOS controller +CMOS_HI EQU 71h + + MOV BX,CARD_EXT_S16K ;Convert to 1st 16K TT ptr past @RH4 + SUB BX,ems_pgs_parm ; entries reserved for ext mem @RH4 + SUB BX,1024/16 ;Convert to # of 16K above 1M + MOV CL,4 ;Multiply by 16 to get # of K + SHL BX,CL ; above 1 Megabyte + + MOV AX,8800h ;Get BIOS' current value for # + INT 15h ; of K extended (above 1M) + + CMP AX,BX ;If already set below what we think + JBE CMOS_RET ; think then don't adjust it + + PUSHF ;Else adjust CMOS...save state of + CLI ; interrupts and disable + MOV AL,0B5h ;Select NMI off byte 35 + OUT CMOS_LO,AL ;Write to CMOS controller + JMP $+2 ; delay + MOV AL,BL ;Write low data byte to CMOS + OUT CMOS_HI,AL ; + JMP $+2 ; + + MOV AL,0B6h ;Select NMI off byte 36 + OUT CMOS_LO,AL ;Write to CMOS controller + JMP $+2 ; delay + MOV AL,BH ;Write high data byte to CMOS + OUT CMOS_HI,AL ; + JMP $+2 ; + + MOV AL,0Fh ;Select NMI on byte 0f + OUT CMOS_LO,AL ;Write to CMOS controller + JMP $+2 ; delay + IN AL,CMOS_HI ;Reset CMOS like BIOS does + POPF ;Restore interrupt state +CMOS_RET: + RET ; @RH4 +ADJUST_CMOS ENDP + + \ No newline at end of file diff --git a/v4.0/src/DEV/XMA2EMS/ROMSCAN.INC b/v4.0/src/DEV/XMA2EMS/ROMSCAN.INC new file mode 100644 index 0000000..8eeb1b8 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/ROMSCAN.INC @@ -0,0 +1,420 @@ + + page +;------------------------------------------------------------------- +; +; This file contains the code to do a pseudo-rom scan looking +; for possible EMS holes +; +;------------------------------------------------------------------- + + + +romscan proc near + + push ax + push dx + push cx + push di + + push cs ; make es and ds point to segment where messages are + pop es + + push cs + pop ds + +; must do rom scan with interrupts disabled + + cli + +;------------------------ + + cmp map_count,0 ; no segments specified, do rom scan + je no_pages_spec + + mov cx,map_count ; number of segments to check + xor di,di ; use di as pointer into table + +check_segs: + mov ax,map_table.phys_page_segment[di] + + call CHK_FREE_SEGMENT ; check a 16K block + jnc segment_ok + +; display the error + + mov segment_error,1 ; set segment error flag + + +; display conflict message + + push ax ; save some regs + push dx + push di + + MOV DI,OFFSET confl_address ; ascii string page frame + CALL CNVHEXAT + + MOV DX,OFFSET conflict_msg ; start of message + MOV AH,9 ; dos prt string + INT 21H ; + + pop di ; restore some regs + pop dx + pop ax + +segment_ok: + add di,type mappable_phys_page_struct + loop check_segs + +;------------------------ +; if there were no conflicts, then exit with no error + + cmp segment_error,0 + je rom_scan_no_error ; exit with no error (carry = 0) + +;------------------------ + + MOV DX,OFFSET CRLF ; skip a blank line + MOV AH,9 ; dos prt string + INT 21H ; + + jmp rom_scan_code + +; display no pages message + +no_pages_spec: + MOV DX,OFFSET NO_PAGES_MSG ; skip a blank line + MOV AH,9 ; dos prt string + INT 21H + + MOV DX,OFFSET CRLF ; skip a blank line + MOV AH,9 ; dos prt string + INT 21H ; + +;------------------------------------------------------------------- +; +; This routine scans the address range from c000 - FFFF looking +; for 16 K gaps. +; +;------------------------------------------------------------------- + +rom_scan_code: + + mov ax,0c000h ; start at c000 + xor bx,bx ; bx holds count of contiguous pages + mov cx,15 ; loop counter + mov dx,ax ; dx holds start of frame + +fam2_loop: + call CHK_FREE_SEGMENT ; check a 16K block + jc bad_seg + +; good 16 segment + + call FoundBlock + + add bx,1 ; add another page to frame counter + cmp bx,4 ; 4 means frame is found + jne no_frame_yet + +; a frame has been found + + mov bx,100 ; make sure we don't look for more frames + +no_frame_yet: + add ax,0400h ; point to next segment + jmp continue_loop + +; bad 16 segment + +bad_seg: + add ax,0400h ; point to next segment + cmp bx,100 + jae continue_loop ; don't reset frame info if one has been found + + xor bx,bx ; clear contiguous page counter + mov dx,ax ; make frame pointer point to next page + +continue_loop: + + loop fam2_loop + jmp rom_scan_exit + + +rom_scan_no_error: + clc + jmp clean_exit + + +;------------------------------------------------------------------- + +rom_scan_exit: + +; display frame if found + + cmp bx,100 ; >= 100 means frame was found + jb no_frame_exit + + mov ax,dx ; get frame address in ax + call FoundFrame ; display frame address + + +no_frame_exit: + STC ; carry = 1 means error + +clean_exit: + sti + + + pop di + pop dx + pop cx + pop ax + + ret + +romscan endp + + + +;------------------------------------------------------------------- +; +; FoundBlock assumes AX = segment address of good 16 K block +; +;------------------------------------------------------------------- + +FoundBlock proc near + + push ax + push dx + push es + push di + + push cs + pop es + + push cs + pop ds + + MOV DI,OFFSET hole_address ; ascii string page frame + CALL CNVHEXAT + + MOV DX,OFFSET hole_msg ; start of message + MOV AH,9 ; dos prt string + INT 21H ; + + + pop di + pop es + pop dx + pop ax + + ret + +FoundBlock endp + +;------------------------------------------------------------------- +; +; FoundFrame assumes AX = segment address of good 64 K block +; +;------------------------------------------------------------------- + +FoundFrame proc near + + push ax + push dx + push es + push di + + push cs + pop es + + push cs + pop ds + + MOV DI,OFFSET frame_address ; ascii string page frame + CALL CNVHEXAT + + MOV DX,OFFSET frame_msg ; start of message + MOV AH,9 ; dos prt string + INT 21H ; + + + pop di + pop es + pop dx + pop ax + + ret + +FoundFrame endp + + + + + + +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------- +;------------------------------------------------------------------------ +; 03/04/88 jwg: +; PROCEDURE NAME: CHK_FREE_SEGMENT : +; : +; THIS PROCEDURE CHECKS EACH OF THE 2K BOUNDARIES IN THE 16K SEGMENT : +; TO DETERMINE IF A ROM SEGMENT IS EMPTY. IT VERIFIES THAT NO ROM : +; FROM A PRECEEDING ADDRESS EXTENDS INTO THIS 16K SEGMENT. ALSO THE : +; 16K BLOCK IS CHECKED FOR THE PRESENCE OF ANY RESPONDING CARD. : +; : +; ENTRY: AX - CONTAINS 16K SEGMENT ADDRESS : +; EXIT: CARRY FLAG = 0 - SEGMENT FREE : +; CARRY FLAG = 1 - SEGMENT IN USE : +; : +;------------------------------------------------------------------------ + +ROM_SCAN EQU 0AA55H +CARD_SEL_PORT EQU 091h ; CARD SELECTED LATCH PORT + + +CHK_FREE_SEGMENT PROC NEAR + + PUSH AX ; Save work registers + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH ES ; Save data segment register + MOV BX,AX ; Save segment start address + MOV CX,AX ; Save in work register + ADD CX,0400h ; Determine End segment address of FIFE +; MOV DX,0C000h-00100h ; Get address of start of ROM area + mov dx,ax ; gga + sub dx,0100h ; gga +CHK_FREE_NEXT: + ADD DX,00100h ; Add offset to get next 2K segment + CMP DX,CX ; Check for past end of 16K ROM area + JAE CHK_FREE_OK ; IF (NC) then Exit, segment was free + + ; CHECK FOR ROM BLOCK SIGNATURE + MOV ES,DX ; Change to new ROM segment + CMP ES:WORD PTR [0],ROM_SCAN; Check if a ROM module is present + JE CHK_FREE_SIZE ; Go check length if ROM SCAN signature + + CMP BX,DX ; Check if into the target segment yet + JA CHK_FREE_NEXT ; Loop and check next 2K block in not + + ; CHECK FOR CARD RESPONDING IN 2K + NOP ; Following sequence can not be traced.. +;;;;; CALL CARD_SEL_NOW ; Reset CARD SELECTED FEED BACK latch . + XOR DI,DI ; Clear source pointer . + MOV AX,0FFFFh ; Get expected floating bus pattern . + PUSH CX ; Save CX . + MOV CX,00400h ; Get count of 1 K words (2K bytes) . + REPE SCASW ; Check for all bits on in block ES:DI . + POP CX ; Recover end segment address . + JNE CHK_FREE_ERROR ; Exit if anything there . + +;;;;;; cmp rom_scan_type,family1 ; gga only do the card select check on PS2's +;;;;;; je skip_ps2_check + +;;;;;; CALL CARD_SEL_NOW ; Check for a CARD SELECTED by scan . +;;;;;; JC CHK_FREE_ERROR ; Exit (CY) if a card responded ........ + +;;;;;;skip_ps2_check: + JMP CHK_FREE_NEXT ; ELSE check next 2K address + +CHK_FREE_SIZE: ; CHECK LENGTH INTO 16K SEGMENT + push cx ; gga + MOV AL,ES:BYTE PTR [2] ; Get ROM module length in 512 bytes + MOV AH,0 ; Clear high byte + mov cl,5 ; gga + SHL AX,cl ; gga convert to segment length (16 byte) + pop cx ; gga + ADD AX,DX ; Determine ending segment size + CMP BX,AX ; Does ROM extend into this 16K segment + JNB CHK_FREE_NEXT ; IF not then continue search + +CHK_FREE_ERROR: + STC ; ELSE (CY), Exit with segment not free +CHK_FREE_OK: + POP ES ; restore segment register + POP DI + POP DX + POP CX ; restore all registers + POP BX + POP AX + RET ; EXIT (NC) if segment free to test + +CHK_FREE_SEGMENT ENDP + + +;------------------------------------------------------------------------ +; 03/04/88 jwg: +; PROCEDURE NAME: CARD_SEL_FBK : +; : +; THIS PROCEDURE CHECKS THE CARD SELECTED FEEDBACK LINE AND LATCH : +; TO VERIFY THAT THIS LINE WAS ACTIVATED. METHOD IS TO CLEAR THE : +; LATCH AND READ A LOCATION USING THE PASSED SEGMENT ADDRESS. IF : +; ANY CARD RESPONDS THE LATCH WILL BE SET ON. : +; : +; NOTE: These routines can not be traced with a debug-er : +; as VIDEO updates also set the card selected latch. : +; : +; ENTRY: AX - ADDRESS OF SELECTED SEGMENT : +; : +; EXIT: CARRY FLAG = 0 - CARD SELECTED LATCH WAS NOT SET (OFF) : +; CARRY FLAG = 1 - CARD SELECTED LATCH WAS SET BY TEST : +; : +;------------------------------------------------------------------------ + +;;;;;CARD_SEL_FBK PROC NEAR ; TEST CARD SELECTED FEED BACK + +;;;;; CLI ; Block interrupts during operation +;;;;; CALL CARD_SEL_NOW ; Read current port value to clear +;;;;; PUSH DS ; Save segment register +;;;;; MOV DS,AX ; Set segment +;;;;; CMP DS:BYTE PTR [0],AL ; Read first byte with dummy compare +;;;;; POP DS ; Restore segment selector +;;;;; CALL CARD_SEL_NOW ; Read current port value and clear +;;;;; STI ; Enable interrupts +;;;;; RET ; RETurn (CY)= 1 if latch set by read + +;;;;;CARD_SEL_FBK ENDP + +;------------------------------------------------------------------------ +; 03/04/88 jwg: +; PROCEDURE NAME: CARD_SEL_NOW (CURRENT VALUE) : +; : +; THIS PROCEDURE READS AND RESETS THE CURRENT CARD SELECTED FEEDBACK : +; LATCH AND RETURNS THE STATUS. : +; : +; NOTE: This routine can not be traced with a debug-er : +; as VIDEO updates also set the card selected latch. : +; : +; ENTRY: NONE : +; : +; EXIT: CARRY FLAG = 0 - CARD SELECTED LATCH WAS NOT SET (OFF) : +; CARRY FLAG = 1 - CARD SELECTED LATCH WAS SET ON WHEN READ : +; : +;------------------------------------------------------------------------ + +;;;;;CARD_SEL_NOW PROC NEAR ; READ CARD SELECTED FEED BACK + +;;;;; PUSH AX ; Save segment address +;;;;; IN AL,CARD_SEL_PORT ; Read current port value and clear +;;;;; RCR AL,1 ; Move bit 0 into CY flag +;;;;; POP AX ; Recover segment address +;;;;; RET ; RETurn (CY)= 0 if latch set + +;;;;;CARD_SEL_NOW ENDP + + \ No newline at end of file diff --git a/v4.0/src/DEV/XMA2EMS/XMA1DIAG.INC b/v4.0/src/DEV/XMA2EMS/XMA1DIAG.INC new file mode 100644 index 0000000..bbf3875 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/XMA1DIAG.INC @@ -0,0 +1,1870 @@ +;-----------------------------------------------------------------------; +; This section contains the prescence test and diagnostic ; +; routines for the XMA 1 card. ; +; ; +;-----------------------------------------------------------------------; + +;-----------------------------------------------------------------------; +; DATA THAT IS UNIQUE TO THE DIAGNOSTICS PORTION OF ; +; THE DEVICE DRIVER. THIS AREA WILL NOT REMAIN PRESENT ; +; AFTER INITIALIZATION. ; +;-----------------------------------------------------------------------; + +MEM_INST DB '1' +TEST_ID DB ? ;SAVE AREA FOR CURRENT TEST ID +CTRLPARM DW ? ;SAVE AREA FOR CONTROL PARM +PAGE_UNDER_TEST DW 0 ;SAVE AREA FOR PAGE UNDER TEST +CUR_SAVE DW ? ;SAVE AREA FOR NEXT AVAILABLE LINE + ;FOR MESSAGES +ACTIVE_PAGE DB ? ;ACTIVE DISPLAY PAGE +TESTABLE_SEGMENTS DW ? + + +PAGE +;-----------------------------------------------------------------------; +; EQUATES THAT ARE UNIQUE TO THE DIAGNOSTICS PORTION OF ; +; THE DEVICE DRIVER. ; +;-----------------------------------------------------------------------; +BLK_ON EQU 11110111B ;MASK FOR ENABLING A BLOCK +BLK_OFF EQU 00001000B ;MASK FOR INHIBITING A BLOCK +VIRT_MODE EQU 00000010B ;MASK FOR VIRTUAL MODE +REAL_MODE EQU 11111101B ;MASK FOR REAL MODE +MAX_TASK_ID EQU 15 ;MAXIMIM TASK ID +ENABLE EQU 01H ;INDICATES THAT BLOCK SHOULD BE ENABLED +TABLEN EQU 1000H ;NUMBER OF ENTRIES IN XLAT TABLE +DMAREQ1 EQU 0009H ;I/O ADDRESS OF DMA CTRL 1 REQ REG +DMAREQ2 EQU 00D2H ;I/O ADDRESS OF DMA CTRL 2 REQ REG +DMAMODE1 EQU 000BH ;I/O ADDRESS OF DMA CTRL 1 MODE REG +DMAMODE2 EQU 00D6H ;I/O ADDRESS OF DMA CTRL 2 MODE REG +AT_NMI_REG EQU 70H ;AT NMI REG +AT_NMI_OFF EQU 80H ;AT NMI OFF MASK +AT_NMI_ON EQU 00H ;AT NMI ON MASK +AT_CHCHK_EN_REG EQU 61H ;AT CH CHK ENABLE REG +AT_CHCHK_REG EQU 61H ;AT CH CHK REG +AT_CHCHK_EN EQU 0F7H ;AT CH CHK ENABLE MASK +AT_CHCHK_DIS EQU 08H ;AT CH CHK DISABLE MASK +AT_CHCHK EQU 40H ;AT CH CHK MASK +XT_NMI_REG EQU 0A0H ;XT NMI REG +XT_NMI_OFF EQU 00H ;XT NMI OFF MASK +XT_NMI_ON EQU 80H ;XT NMI ON MASK +XT_CHCHK_EN_REG EQU 61H ;XT CH CHK ENABLE REG +XT_CHCHK_REG EQU 62H ;XT CH CHK REG +XT_CHCHK_EN EQU 0DFH ;XT CH CHK ENABLE MASK +XT_CHCHK_DIS EQU 20H ;XT CH CHK DISABLE MASK +XT_CHCHK EQU 40H ;XT CH CHK MASK +CR EQU 0DH ;CARRIAGE RETURN +LF EQU 0AH ;LINE FEED +PRES_TEST EQU 01 ;PRESENCE TEST ID +REG_TEST EQU 02 ;REG TEST ID +AUTO_INC EQU 03 ;AUTO INC TEST ID +XLAT_TABLE_TEST EQU 04 ;TT TEST ID +LOMEM_TEST EQU 05 ;ABOVE 640K TEST ID +DMA_CAPTURE EQU 06 ;DMA CAPTURE TEST ID +PAGE_TEST EQU 07 ;PAGE TEST ID +MEM_TEST EQU 10 ;MEMORY TEST ID + +;------------------------------------------------------------------------- +; +; PRESENCE TEST +; +; DESCRIPTION : This routine will determine if the XMA is in the system. +; It will also determine the amount of memory installed +; on the card in 1Meg increments (up to 4Meg). +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : PRESTST +; +; ENTRY : The assumption is that at least 1MB of memory is installed. +; CONDITIONS If the 2nd, 3rd or 4th MB of memory is installed then the +; TOTAL_SYS_PAGES, TOTAL_EMS_PAGES, FREE_PAGES and +; MEM_INST words are Revised accordingly. +; +; +; +; EXIT : (zero flag) = 0 indicates that the XMA is not installed. +; if (zero flag) <> 0 then +; TOTAL_SYS_PAGES, TOTAL_EMS_PAGES, FREE_PAGES and +; MEM_INST words are Revised accordingly. +; +; AX,BX,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +PRESTST PROC +; + MOV AL,PRES_TEST + MOV CS:TEST_ID,AL + +;SAVE CONTENTS OF MODE REG + MOV DX,MODE_REG + IN AL,DX + PUSH AX + +; TRANSLATE TABLE ADDRESS AND DATA REGISTERS +; + MOV AX,0AA55H ;DATA PATTERN (IN REAL MODE) + ;BE CERTAIN MODE REG GETS + ;REAL MODE + MOV DX,MODE_REG ;I/O TO MODE REG + OUT DX,AL ;WRITE PATTERN + MOV DX,TTPOINTER + 1 ;I/O TO TT POINTER (ODD ADDR) + XCHG AL,AH ;CHRG BUS WITH INVERSE PATTERN + OUT DX,AL ;WRITE IT + MOV DX,MODE_REG + IN AL,DX ;READ BACK MODE REG + XOR AL,AH + AND AL,0FH ;MASK OFF UNUSED BITS + ;ZERO FLAG = 0 IF ERROR +END_PRES: + POP AX + PUSHF ;SAVE FLAGS + MOV DX,MODE_REG + OUT DX,AL ;RESTORE MODE REG TO INITIAL STATE + POPF ;RESTORE FLAGS + RET ;BACK TO CALLER +; +PRESTST ENDP + +PAGE + +;------------------------------------------------------------------------; +; Diagnostics...on exit if ZF=0 then error ; +;------------------------------------------------------------------------; +XMA1DIAGS PROC + + MOV CS:TEST_ID,00H ;CLEAR TEST ID BYTE + MOV CS:CTRLPARM,0100H ;SAVE CONTROL PARM + CALL CUR_POS ;GET CURSOR READY FOR MESSAGES + CALL REGTST ;TEST XMA REGISTERS + JNE FOUND_ERROR ;JUMP IF ERROR + CALL INCTST + JNE FOUND_ERROR + CALL XLATST + JNE FOUND_ERROR + CALL LOMEMTST ;TEST FOR BELOW 640K + JNE FOUND_ERROR ;JUMP IF ERROR + CALL MEMARRAY ;TEST MEMORY ABOVE 640K + JNE FOUND_ERROR ;JUMP IF ERROR + CALL PAGETST + JNE FOUND_ERROR + CALL CAPTST ;TEST DMA CAPTURE + JNE FOUND_ERROR ;JUMP IF ERROR +FOUND_ERROR: + RET +XMA1DIAGS ENDP + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; SAVES CURSOR POSITION +; +; DESCRIPTION : This routine simply saves the cursor location +; in CS:CUR_SAVE. This cursor position +; should be used by the KB_OK routine to insure proper +; format of the screen. +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : CUR_POS +; +; ENTRY : +; CONDITIONS +; +; +; EXIT : new cursor position is saved in CS:CUR_SAVE +; +; All registers are preserved +; +;------------------------------------------------------------------------- +; +CUR_POS PROC +; + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS ;SAVE REGISTERS +; + PUSH CS + POP DS ;GET DS TO THIS CODE SEGMENT + ;MOVE CURSOR TO NEXT AVAILABLE LINE +;IF DOS +; MOV AH,9 ;DOS PRINT STRING +; MOV DX,OFFSET NEXT_LINE + 1 ;OFFSET OF NEXT LINE MSG +; INT 21H ;DISPLAY MESSAGE +;ELSE +; MOV BX,OFFSET NEXT_LINE ;GET OFFSET OF NEXT LINE MSG +; MOV AH,0 ;TELL DCP TO DISPLAY +; INT 82H ;DISPLAY MESSAGE +;ENDIF + ; rsh001 fix scroll problem + ; and remove IF DOS crap + ;READ CURRENT VIDEO PAGE ; rsh001 + MOV AH,15 ;READ CURRENT Video Page + INT 10H ;VIDEO CALL + MOV ACTIVE_PAGE,BH ;SAVE ACTIVE PAGE + + ;READ CURRENT CURSOR POSITION + MOV AH,3 ;READ CURRENT CURSOR POS + INT 10H ;VIDEO CALL + MOV CUR_SAVE,DX ;SAVE CURSOR POSITION + + ;RESTORE ALL REGISTERS + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX ;RESTORE ALL REGISTERS + + RET ;RETURN TO CALLER + +CUR_POS ENDP + + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; TEST FOR PRESENCE OF MORE THAN 1 MEGABYTE OF MEMORY +; +; DESCRIPTION : This routine will determine if the 2nd, 3rd or 4th MB is +; installed. Since there are no switches or other indicators +; to be tested, this test will make a "best guess" as to +; the presence of this memory. This test will roll a 0 +; and a 1 through the 1st word of the next Meg and if +; at least 1 bit is consistently good then it is assumed +; that the optional memory is installed. If successful +; then try next Meg. +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : TRY4MEG +; +; ENTRY : none +; CONDITIONS +; +; EXIT : +; +; AX,BX,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +TRY4MEG PROC + +;MEMORY TEST MUST RUN IN PAGE MODE +;BEFORE CARD IS PUT INTO PAGE MODE...MUST SET UP XLAT TABLE TO PASSOVER +;RESERVED MEMORY SPACES (IE.,BIOS, DISPLAY, DISTRIBUTED ROS, ETC) +; + CALL VIRT2REAL + + MOV DX,IDREG ;I/O TO ID REGISTER + MOV AL,0 ;ID = 0 + OUT DX,AL ;SWITCH TO ID = 0 +; + ;DISABLE NMI AND ENABLE I/O CHANNEL CHECK + MOV AL,CS:MODEL_BYTE ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE TR2M1 ;IF NO THEN TRY FOR PC_XT + CMP AL,PC_XT ;IS IT AN XT? + JE TR2M1 ;IF NO THEN TRY FOR AQUARIUS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE TR2M1 ;IF NO THEN USE AT NMI REGS + ;USE PC-AT NMI REGISTER + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + ;USE PC1, XT, AQUARIUS REGISTERS +TR2M1: + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED +; + ;MAP FIRST 64K OF 2ND MEG INTO PC SPACE BEGINNING AT 512K +;***jnw MOV CX,3 ;LOOK FOR PRESENCE OF NEXT 3 MB IN 1MB STEPS + MOV CX,99*1024/16 ;***jnw ;LOOK FOR PRESENCE OF NEXT n MB IN 1MB STEPS + MOV AX,CS:PAGE_FRAME_STA ;SEGMENT AT PAGE FRAME +;***jnw MOV DX,256 ;BEGINNING AT 2ND MEG OF XMA + MOV DX,256+3 ;***jnw ;AT end of 16k + MOV BH,0 ;ASSIGNED TO TASK ID 0 + MOV BL,01H ;ENABLE THIS MEMORY +TR2M1A: + PUSH AX + PUSH BX + PUSH CX + PUSH DX +;***jnw MOV CX,16 ;16 * 4K = 64K BLOCK + MOV CX,1 ;***jnw ;1 * 4K = 4K BLOCK + CALL SETXLAT ;SET TRANSLATE TABLE +; + MOV AX,CS:PAGE_FRAME_STA + MOV DS,AX ;SET SEGMENT AND + MOV SI,0 ;OFFSET TO TEST + MOV BX,0000000000000001B ;ROLL 1 THROUGH WORD + MOV DX,1111111111111110B ;ROLL 0 THROUGH WORD + MOV CX,16 ;16 BITS TO TEST +TR2M2: + MOV [SI],BX ;WRITE ROLLING 1 PATTERN + LOCK MOV [SI+2],DX ;CHARGE BUS INVERSE PATTERN + LOCK MOV AX,[SI] ;READ BACK INITIAL PATTERN + AND AX,BX ;ISOLATE BIT UNDER TEST +;***jnw JZ TR2M3 ;IF ZERO TRY ANOTHER BIT + JZ quit ;IF ZERO quit ***jnw + MOV [SI],DX ;WRITE ROLLING 0 PATTERN + LOCK MOV [SI+2],BX ;CHARGE BUS INVERSE PATTERN + LOCK MOV AX,[SI] ;READ BACK INITIAL PATTERN + AND AX,BX ;ISOLATE BIT UNDER TEST + AND AX,BX ;ISOLATE BIT UNDER TEST +;***jnw JZ TR2M4 ;IF ZERO THEN FOUND GOOD BIT + Jnz quit ;IF nonzero then quit ***jnw +TR2M3: + ROL BX,1 ;ROLL 1 TO NEXT POSITION + ROL DX,1 ;ROLL 0 TO NEXT POSITION + LOOP TR2M2 ;REPEAT FOR 16 BITS + jmp tr2m4 ;all 16 bits passed test ***jnw +quit: ;***jnw +;AT THIS POINT THERE ARE NO GOOD BITS SO END SEARCH FOR NEXT MB + POP DX ;RECOVER THESES REGISTERS + POP CX + POP BX + POP AX + JMP TR2M5 ;EXIT +;AT THIS POINT WE KNOW THERE IS MEMORY IN THIS MEG THAT WAS JUST TESTED +TR2M4: +;***jnw ADD CS:MEM_INST,1 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:TOTAL_XMA_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:TOTAL_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG +;***jnw ADD CS:FREE_PAGES,1024/16 ;ADD 1 MB TO THIS FLAG + ADD CS:TOTAL_SYS_PAGES,1 ;Add 16k ***jnw + ADD CS:TOTAL_EMS_PAGES,1 ;Add 16k ***jnw + ADD CS:FREE_PAGES,1 ;Add 16k ***jnw + POP DX ;RECOVER THESE REGISTERS + POP CX + POP BX + POP AX +;***jnw ADD DX,256 ;TRY NEXT MB + ADD DX,4 ;TRY NEXT 16k ***jnw + LOOP TR2M1A ;REPEAT LOOP +TR2M5: +;BEFORE NMI IS ENABLED, CLEAR PARITY CHECK LATCH ON XMA + MOV SI,0 + MOV AX,[SI] ;READ 1ST WORD OF THIS SEG + MOV [SI],AX ;WRITE BACK SAME WORD + ;THE WRITE WILL CLEAR PCHK LTCH +;PUT THE XMA CARD BACK INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG +;CLEAR I/O CHANNEL CHECK LATCHES AND ENABLE NMI + MOV AL,CS:MODEL_BYTE ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE TR2M6 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE TR2M6 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE TR2M6 ;USE XT REGISTERS +;IF NONE OF THE ABOVE THEN... +;USE AT NMI REGISTER + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +;USE XT/AQUARIUS NMI REGISTER +TR2M6: + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +; + RET ;RETURN TO CALLER + +TRY4MEG ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; REGISTER TESTS +; +; DESCRIPTION : This routine will test the following subset +; of XMA registers: +; 31A0...8 bits +; 31A1...4 bits +; 31A6...4 bits +; 31A7...4 bits (BIT 1 IS HELD LOW TO DISABLE +; THE VIRTUAL MODE) +; +; The test is performed by writing and reading +; AA, 55, FF, 00 from each of the above locations. +; +; NOTE: Regs 31A6 and 31A7 should always return 0 in +; the high nibble. +; +; The remainding registers will be tested in +; subsequent routines. +; +; +; FUNCTION/ : To ensure integrity of XMA registers that will be used +; PURPOSE in subsequent routines. +; +; ENTRY POINT : REGTST +; +; ENTRY : none +; CONDITIONS +; +; EXIT : XMA registers are set to zero +; +; (zero flag) = 0 indicates an error +; (DX) failing register +; (AL) expected data XOR'ed with actual data +; +;------------------------------------------------------------------------- +; +REGTST PROC +; + MOV AL,REG_TEST + MOV CS:TEST_ID,AL + +;SAVE CONTENTS OF MODE REG + MOV DX,MODE_REG + IN AL,DX + PUSH AX + +; TRANSLATE TABLE ADDRESS AND DATA REGISTERS +; + MOV BX,0AA55H ;SET UP INITIAL DATA PATTERN + MOV AX,BX + MOV CX,BX + +R1: + MOV DX,TTPOINTER ;FIRST REGISTER PAIR TO WRITE + + OUT DX,AX ;WRITE PATTERN TO REGS + ADD DX,6 ;POINT TO NEXT REG PAIR + XCHG AL,AH ;SETUP INVERSE PATTERN + AND AH,11111101B ;MASK OFF BIT 1 + OUT DX,AX ;BECAUSE AH -> 21B7 +R2: + SUB DX,6 ;POINT TO FIRST REGISTER PAIR + IN AX,DX ;READ REGISTER (21B1 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE OF 21B1 + JNE R_ERROR ;MISMATCH - GO TO ERROR ROUTINE + XCHG BH,BL ;NEXT PATTERN TO TEST + AND BX,0F0FH ;REGS RETURN 0 IN HI NIBBLE + ADD DX,6 ;POINT TO NEXT REGISTER PAIR + IN AX,DX ;READ IT (21B7 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0DFFH ;MASK OFF BIT 1 IN REG 21B7 + JNE R_ERROR ;MISMATCH - GO TO ERROR ROUTINE +; + CMP CH,CL ;LAST PASS ? + JE R_EXIT ;YES - THEN EXIT REG TEST +; + CMP CX,055AAH ;END OF AA55,55AA PATTERNS? + JNE R3 ; + MOV CX,000FFH ;SET UP NEXT VALUE TO WRITE + JMP R4 +R3: + CMP CX,00FFH ;END OF FF00,00FF PATTERNS? + JNE R4 ; + MOV CX,0 ;YES, THEN SET UP FOR LAST PASS +R4: + XCHG CL,CH ;SET UP INVERSE PATTERN + MOV AX,CX ;SAVE IT + MOV BX,CX ;SAVE IT +R5: + JMP R1 ;CONTINUE TILL ZERO PATTERN + +R_ERROR: +R_EXIT: + POP AX + MOV DX,MODE_REG + OUT DX,AL ;restore mode reg + RET +; +REGTST ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; MEMORY ARRAY TEST +; +; DESCRIPTION : This routine test all 1Meg (or 2Meg) of XMA memory +; through a 64K window in PC space beginning at PF:0 +; (where PF is the Page Frame Segment) +; This module looks at TOTAL_SYS_PAGES +; to determine the memory size to be tested. +; +; (i) write the Translate Table for the 1st 64K block +; of XMA memory to be mapped into PF:0 in PC space +; (ii) test PF:0 to PF:FFFF +; (iii) if good...write Translate Table to map next 64K block +; into PF:0 +; (iv) repeat 'till all XMA memory is tested +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : MEMARRAY +; +; ENTRY : +; CONDITIONS +; +; EXIT : All SMAS memory is set to zero. +; +; (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if AX = 0 and ZF = 0 then parity error +; DS:SI point to failing location +; CS:PAGE_UNDER_TEST point failing 64k block +; +; AX,BX,CX,DX,DS,ES,SI,DI ARE DESTROYED +; +;------------------------------------------------------------------------- + +MEMARRAY PROC + + MOV AL,MEM_TEST + MOV CS:TEST_ID,AL + +;MEMORY TEST MUST RUN IN PAGE MODE + + CALL VIRT2REAL + +;INDICATE 0 KB OK + MOV DX,(640-16)/4 ;CODE FOR 640 KB OK + CALL KB_OK +;SETUP FOR TEST OF SMAS MEMORY ARRAY + MOV AX,CS:PAGE_FRAME_STA ;PAGE MEMORY FROM THIS SEGMENT + MOV ES,AX ;SET UP DEST SEG + MOV DS,AX ;SET UP SOURCE SEG + MOV BL,01H ;ENABLE THIS BLOCK OF MEMORY + MOV BH,0 ;USING ID 0 + MOV DX,(640)/4 ;STARTING BLK IN SMAS ARRAY + ;DETERMINE HOW MUCH MEMORY TO TEST + MOV CX,CS:TOTAL_SYS_PAGES ;GET NUMBER OF 16K PAGES + SUB CX,640/16 ;SUBTRACT OFF 1ST 640K MEMORY ;an000; dms; +;BEGIN TEST +MA1: + MOV CS:PAGE_UNDER_TEST,DX ;INDICATE WHICH 64K BLOCK + PUSH AX ;IS UNDER TEST + PUSH BX + PUSH CX + PUSH DX ;SAVE ALL REGISTERS +; + MOV CX,4 ;test 16k at one time ;an000; dms; + ;4 x 4K = 16K + CALL SETXLAT ;SET UP XLAT TABLE + CALL STGTST ;TEST 64K OF STORAGE + JNZ MA2 ;WAS THERE AN ERROR + POP DX + POP CX + POP BX + POP AX ;RESTORE REGISTERS +; + PUSHF ;SAVE FLAGS FOR ADDITION + + CALL KB_OK ;INDICATE HOW MUCH + ;MEMORY HAS BEEN TESTED + + + ADD DX,4 ;POINT TO NEXT 64K BLOCK + POPF ;RESTORE FLAGS + LOOP MA1 ;LOOP FOR NEXT 64K + JMP MA3 ;EXIT WHEN COMPLETE +MA2: + POP DX + POP CX + POP BX ;BX IS POPPED TWICE + POP BX ;TO RESTORE STACK WHILE + ;MAINTAINING AX +MA3: + PUSH AX + PUSH DX + PUSHF ;SAVE THESE REGS...THEY CONTAIN + ;USEFULL ERROR INFO +;PUT THE SMAS CARD INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG + POPF + POP DX + POP AX ;RESTORE THESE REGS + RET +; +MEMARRAY ENDP + + + + +PAGE +;--------------------------------------------------------------------- +;--------------------------------------------------------------------- +; LO MEMORY TEST +; +; DESCRIPTION : This routine tests the first 256K or 512K +; of XMA memory depending on the starting +; position of the starting address jumper on +; the card. The memory that is used to +; fill conventional memory space is not tested +; it is tested during POST and may now contain +; parts of COMMAND.COM. +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : LOMEMTST +; +; ENTRY : +; CONDITIONS +; +; EXIT : All tested memory is set to zero +; +; (zero flag) = 0 if storage error +; (AX) = expected data XOR'ed with actual data +; if (AX)=0 and ZF=0 then parity error +; DS:SI point to failing location +; CS:PAGE_UNDER_TEST point to failing 64K block +; +; AX,BX,CX,DX,DI,SI,ES,DS ARE DESTROYED +; +;----------------------------------------------------------------------- +LOMEMTST PROC + + MOV AL,LOMEM_TEST + MOV CS:TEST_ID,AL + +;MEMORY TEST MUST RUN IN PAGE MODE + CALL VIRT2REAL + +;INDICATE 0 KB OK AT START OF TEST + MOV DX,03ffcH ;code for initial 0 kb ;an000; dms; + CALL KB_OK + +;DETERMINE HOW MUCH MEMORY TO TEST + MOV AX,CS:START_BACMEM_SEG ;get starting fill segment + XCHG AH,AL + MOV CL,2 ; ;an000; dms; + SHR AX,CL ;convert to 16k block number + MOV CS:TESTABLE_SEGMENTS,AX ;save...this is number of 64k blocks + ;that can be tested without + ;destroying DOS +;SET UP FOR TEST OF XMA MEMORY + MOV AX,CS:PAGE_FRAME_STA ;test through page frame + MOV DS,AX ;set up ds + MOV ES,AX ;and es + MOV BL,01H ;enable this block of memory + MOV BH,0 ;using id=0 + XOR DX,DX ;start at block 0 in xma + MOV CX,640/16 ;loop counter is # 16k blocks in + ;conventional memory +LM1: + MOV CS:PAGE_UNDER_TEST,DX ;save page under test + PUSH AX + PUSH BX + PUSH CX + PUSH DX ;save these registers + + MOV CX,4 ;test 16k at one time ;an000; dms; + ;4 * 4k = 16k + CALL SETXLAT ;set translate table + CMP CS:TESTABLE_SEGMENTS,0 ;if this segment under test is used for + ;fill then read only + JG LM2 ;else do storage test + CALL READ_ONLY + JMP LM3 +LM2: + CALL STGTST +LM3: + JNZ LM4 ;jump if there was an error + POP DX + POP CX + POP BX + POP AX ;recover registers + + PUSHF ;save flags for addition + CALL KB_OK + ;indicate kb ok + ADD DX,4 ;next 16k block ;an000; dms; + DEC CS:TESTABLE_SEGMENTS ;dec testable pages + POPF ;recover flags + LOOP LM1 ;repeat for next 64k block + JMP LM5 ;exit when complete +LM4: + POP DX ;recover these registers + POP CX + POP BX ;bx is popped twice to restore + POP BX ;satck while maintaining ax +LM5: + PUSH AX ;save these ... they contain + PUSH DX ;useful error information + PUSHF +;PUT CARD BACK TO REAL MODE + MOV DX,MODE_REG ;read mode reg + IN AL,DX + AND AL,REAL_MODE ;turn off virtual bit + OUT DX,AL ;write it to mode reg + POPF + POP DX + POP AX ;restore these registers + RET + + +READ_ONLY PROC ;INTERNAL PROC TO READ MEMORY WITHOUT DESTROYING CONTENTS + XOR SI,SI ;start of segment + XOR CX,CX ;test 64k + + LODSW ;just read each byte + XOR AX,AX ;and set zf=1 for return + RET ;back to caller +READ_ONLY ENDP + +LOMEMTST ENDP + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; PAGE TEST +; +; DESCRIPTION : This routine tests that the TASK ID register is +; actually paging in unique segments of memory. +; The test is performed through the page frame segment. +; The test assumes that the memory test has already +; completed successfully. The page test procedes as +; follows: +; (i) 6-64K blocks of XMA memory are mapped into a +; 64K segment of PC space (the page frame) +; These XMA blocks are from 640k to 1024k of XMA memory. +; (ii) Each of these blocks is assigned to a unique +; task ID ranging from 0 to 5. +; (iii) For each task ID, the page frame is filled with +; a pattern that is the same as the task ID. +; (iv) The page frame is then read for each task ID +; and compared with the expected data. +; +; FUNCTION/ : +; PURPOSE +; +; ENTRY POINT : PAGETST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : (zero flag) = 0 indicates an error +; (AL) expected data XOR'ed with actual data +; +; AX,BX,CX,DX,ES,DS,SI,DI ARE DESTROYED +;------------------------------------------------------------------------- +; +PAGETST PROC +; + MOV AL,PAGE_TEST + MOV CS:TEST_ID,AL +;MEMORY TEST MUST RUN IN PAGE MODE + CALL VIRT2REAL +;INITIALIZE TRANSLATE TABLE FOR THIS TEST + MOV AX,CS:PAGE_FRAME_STA ;SEMENT OF PAGE FRAME + MOV BL,01H ;ENABLE CODE + MOV BH,0 ;START WITH TASK ID = 0 + MOV DX,640/4 ;START WITH XMA BLOCK 160 + MOV CX,6 ;LOOP COUNT...6 TASK ID's + ;EACH TASK ID IS ASSIGNED 16K + ;FROM 640K TO 1024K +PT1: + PUSH AX + PUSH BX + PUSH CX + PUSH DX ;SAVE ALL REGISTERS +; + MOV CX,4 ;4 -4K BLOCKS IN 16K ;an000; dms; + CALL SETXLAT ;SET TRANSLATE TABLE + POP DX + POP CX + POP BX + POP AX ;RECOVER ALL + INC BH ;POINT TO NEXT TASK ID + ADD DX,4 ;NEXT 64K IN XMA MEMORY ;an000; dms; + LOOP PT1 ;REPEAT FOR ALL TASK ID's +;FILL MEMORY WITH A UNIQUE PATTERN FOR EACH TASK ID + MOV CX,6 ;6 TASK ID's + MOV DX,IDREG ;READY FOR I/O TO TASK ID REG + MOV AL,0 ;START WITH ID = 0 +PT2: + PUSH AX ;SAVE ID NUMBER + PUSH CX ;SAVE ID COUNT + OUT DX,AL ;SWITCH TASK ID + MOV BX,CS:PAGE_FRAME_STA + MOV ES,BX ;SEGMENT TO 1ST 64K 0F ID + SUB DI,DI ;POINT TO 1ST LOCATION + mov cx,4000h ;WRITE ALL 16K LOCATIONS ;an000; dms; +PT2X: + STOSB + LOOP PT2X + POP CX ;RECOVER ID COUNT + POP AX ;RECOVER CURRENT ID + INC AL + LOOP PT2 ;REPEAT FOR ALL TASK ID's +;NOW CHECK THAT THERE ARE 16 UNIQUE PATTERNS IN MEMORY + MOV CX,6 ;USE 6 TASK ID's + MOV AH,0 ;START WITH ID = 0 +PT3: + MOV AL,AH ;GET TASK ID IN AL + PUSH AX + PUSH CX ;SAVE ID COUNT + OUT DX,AL ;SWITCH TASK ID + MOV BX,CS:PAGE_FRAME_STA + MOV DS,BX + MOV ES,BX ;SEGMENT AT 1ST 64K + SUB DI,DI ;POINT TO 1ST LOCATION + SUB SI,SI ;POINT TO 1ST LOCATION + mov cx,4000h ;READ ALL 16K LOCATIONS +PT3X: + LODSB + XOR AL,AH ;DATA AS EXPECTED ? + JNE PT4X ;NO - THEN EXIT + STOSB ;AL SHOULD CONTAIN 0...WRITE IT + LOOP PT3X + + POP CX ;RECOVER ID COUNT + POP AX + INC AH ;NEXT TASK ID + LOOP PT3 ;REPEAT FOR ALL TASK ID's + XOR AL,AL ;IF WE GOT THIS FAR THEN + ;NO ERRORS...SET ZF TO + ;INDICATE SUCCESS +PT4: + PUSH AX + PUSH DX + PUSHF ;SAVE THESE REGS...THEY CONTAIN + ;USEFULL ERROR INFO +;PUT THE SMAS CARD INTO REAL MODE + MOV DX,MODE_REG ;READY FOR I/O TO MODE REG + IN AL,DX ;READ IT + AND AL,REAL_MODE ;TURN OFF VIRTUAL BIT + OUT DX,AL ;WRITE IT TO MODE REG +;MAKE SURE WE EXIT WHILE IN TASK ID=0 + MOV DX,IDREG + XOR AL,AL + OUT DX,AL + + POPF + POP DX + POP AX ;RESTORE THESE REGS + RET ;RETURN TO CALLER +PT4X: + POP CX ;ALTERNATE RETURN PATH + POP AX + JMP PT4 ;TO ADJUST STACK +; +PAGETST ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; DMA CAPTURE TEST +; +; DESCRIPTION : This routine is a test of the DMA capture logic. +; The test is as follows: +; (i) A bit is rolled through the second entry in the +; DMA cature register file. (The first entry is used +; for refresh on a PC-XT). +; (ii) A bit and address test is performed on the +; remainder of the register file(s). +; (iii) A test is made for the capture of both REQUEST and +; MODE registers of the DMA controller. +; (iv) DMA channel 0 is tested only on the PC-AT +; +; +; FUNCTION/ : To verify the functionality of the DMA capture logic. +; PURPOSE +; +; ENTRY POINT : CAPTST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : Each entry in the DMA capture register file is set to 0. +; +; (zero flag) = 0 indicates an error +; '31A8'X points to failing DMA capture reg +; (AL) expected data XOR'ed with actual data +; +; AX,BX,CX,DX,SI,DI ARE DESTROYED +;------------------------------------------------------------------------- +; +; +CAPTST PROC +; + MOV AL,DMA_CAPTURE + MOV CS:TEST_ID,AL +; +;ROLL A BIT THROUGH THE SECOND ENTRY IN THE DMA CAPTURE REGISTER FILE +; + MOV BL,01H ;SET UP INITIAL PATTERN + MOV BH,01H ;SET UP DMA CHANNEL 1 + MOV DI,DMACAPT ;SAVE FOR I/O TO DMA CAPTURE REG + MOV SI,DMAREQ1 ;SAVE FOR I/O TO DMA CTRL 1 REQ REG + MOV CX,4 ;ROLL 4 BIT POSITIONS +C1: + MOV DX,IDREG ;I/O TO ID REG + MOV AL,BL ;PATTERN TO WRITE + OUT DX,AX ;SETUP ID REG WITH DATA PATTERN + MOV DX,SI ;DMA CTRL 1 + MOV AL,BH ;CHANNEL 1 + OUT DX,AL ;SETUP DMA CH 1...CAPT ID IN 2nd ENTRY + MOV DX,DI ;DMA CAPTURE REG + OUT DX,AL ;POINT TO 2nd ENTRY + IN AL,DX ;READ IT + XOR AL,BL ;DATA READ AS EXPECTED ? + JNE CAPT_ERROR ;NO - THEN ERROR + SHL BL,1 ;SHIFT BIT TO NEXT POSITION + LOOP C1 ;REPEAT +; + MOV DI,DMAREQ2 ;SETUP FOR I/O TO DMA CTRL 2 REQ REG + MOV AL,05H ;DATA PATTERN TO CAPTURE + CALL CAPT_FILL ;FILL CAPTURE REGS WITH VALUE +; + MOV AH,05H ;SETUP INITIAL PATTERN + MOV BX,0F0AH ;OTHER PATTERNS TO USE +C2: + CALL CAPT_RMW + JNZ CAPT_ERROR ;ERROR - THEN EXIT + CMP AH,BL ;ZERO PATTERN ? + JE CAPT_EXIT ;EXIT IF YES + MOV AH,BL ;SET UP + MOV BL,BH ; NEXT + MOV BH,0 ; PATTERN + JMP C2 ;REPEAT + +;NOW REPEAT TEST FOR CATPURE OF DMA MODE REGISTERS + MOV SI,DMAMODE1 ;SETUP FOR I/O TO DMA CTRL 1 MODE REG + MOV DI,DMAMODE2 ;SETUP FOR I/O TO DMA CTRL 2 MODE REG + MOV AL,05H ;DATA PATTERN TO CAPTURE + CALL CAPT_FILL ;FILL CAPTURE REGS WITH VALUE +; + MOV AH,05H ;SETUP INITIAL PATTERN + MOV BX,0F0AH ;OTHER PATTERNS TO USE +C3: + CALL CAPT_RMW + JNZ CAPT_ERROR ;ERROR - THEN EXIT + CMP AH,BL ;ZERO PATTERN ? + JE CAPT_EXIT ;EXIT IF YES + MOV AH,BL ;SET UP + MOV BL,BH ; NEXT + MOV BH,0 ; PATTERN + JMP C3 ;REPEAT +CAPT_ERROR: +CAPT_EXIT: + RET + +CAPTST ENDP + + + +PAGE + +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; FILL DMA CAPTURE REG +; +; DESCRIPTION : This routine will fill the entire DMA capture register +; file with the pattern that is passed in AL +; +; FUNCTION/ : See Description. +; PURPOSE +; +; ENTRY POINT : CAPT_FILL +; +; ENTRY : AL contains the value to be captured into +; CONDITIONS the register file. +; SI contains the address of DMA controller 1 +; DI contains the address of DMA controller 2 +; +; EXIT : Each entry in the DMA capture register file is set to +; the value specified in AL. +;------------------------------------------------------------------------- +; +CAPT_FILL PROC NEAR +; + MOV DX,IDREG + OUT DX,AL ;LOAD ID REG WITH PAT TO BE CAPTURED + MOV DX,DI ;GET ADDRESS OF CTRL 2 + MOV CX,3 ;REP FOR CHANNELS 7,6,5 +CF1: + MOV AL,CL ;CL CONTAINS WHICH DMA CHANNEL + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL + LOOP CF1 ;REPEAT +; + MOV DX,SI ;GET ADDRESS OF CTRL 1 + MOV CX,3 ;REP FOR CHANNELS 3,2,1 +CF2: + MOV AL,CL ;CL CONTAINS WHICH DMA CHANNEL + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL + LOOP CF2 ;REPEAT + ;DO CHANNEL 0 IF NOT PC1, XT, AQUARIUS + CMP CS:MODEL_BYTE,PC1 ;IS THIS A PC1 ? + JE CF3 ;YES - THEN EXIT ELSE TRY PC_XT + CMP CS:MODEL_BYTE,PC_XT ;IS THIS AN XT ? + JE CF3 ;YES - THEN EXIT ELSE TRY AQUARIUS + CMP CS:MODEL_BYTE,XT_AQUARIUS ;IS THIS AN AQUARIUS? + JE CF3 ;YES - THEN EXIT ELSE FILL CH 0 CAPT + MOV AL,0 ;INDICATE CHANNEL 0 + OUT DX,AL ;SETUP & CAPTURE DMA CHANNEL +CF3: + RET ;RETURN TO CALLER +; +CAPT_FILL ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; READ-MODIFY-WRITE DMA CAPTURE REG +; +; DESCRIPTION : This routine will read the a DMA capture register +; and if the correct value is found will cause a capture +; of a new value. The next DMA capture reg is read and +; the process repeated. +; +; FUNCTION/ : See Description. +; PURPOSE +; +; ENTRY POINT : CAPT_RMW +; +; ENTRY : AH contains the value to be compared +; CONDITIONS BL contains the new value to be written +; SI contains the address of DMA controller 1 +; DI contains the address of DMA controller 2 +; +; EXIT : Each entry in the DMA capture register file is set to +; the value specified in BL. +; +; AL,CX,DX,ARE DESTROYED +;------------------------------------------------------------------------- +; +CAPT_RMW PROC NEAR +; + MOV CX,3 ;REP FOR CHANNELS 7,6,5 +RMW1: + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV AL,CL ;GET LOW BYTE OF COUNT + ADD AL,4 ;ADD 4 TO POINT TO DMA CAPTURE + CALL RMW + JNZ RMW4 ;EXIT IF ERROR + LOOP RMW1 ;REPEAT FOR CHANNEL 6,5 +; + MOV CX,3 ;REP FOR CHANNELS 3,2,1 + PUSH DI ;SAVE DMA CTRL 2 + MOV DI,SI ;GET DMA CTRL 1 INTO DI FOR PROC RMW +RMW2: + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV AL,CL ;GET LOW BYTE OF COUNT + CALL RMW + JNZ RMW3 ;EXIT IF ERROR + LOOP RMW2 ;REPEAT FOR DMA CHANNELS 2,1 + ;DO CHANNEL 0 IF NOT PC1, XT, AQUARIUS + CMP CS:MODEL_BYTE,PC1 ;IS THIS A PC1 ? + JE RMW3 ;YES - THEN EXIT ELSE TEST FOR PC_XT + CMP CS:MODEL_BYTE,PC_XT ;IS THIS AN XT ? + JE RMW3 ;YES - THEN EXIT ELSE TEST FOR AQUARIUS + CMP CS:MODEL_BYTE,XT_AQUARIUS ;IS THIS AN AQUARIUS? + JE RMW3 ;YES - THEN EXIT ELSE TEST CH 0 + MOV DX,DMACAPT ;I/O ADDRESS OF DMA CAPTURE REG + MOV CL,0 ;INDICATE CHANNEL 0 + MOV AL,CL ;ALSO INTO AL + CALL RMW +RMW3: + POP DI ;RESTORE DI (ADDR OF DMA CTRL 2) +RMW4: + RET ;RETURN TO CALLER +; +CAPT_RMW ENDP +; +RMW PROC +; + OUT DX,AL ;SETUP TO READ FROM DMA CAPTURE REG + IN AL,DX ;READ IT + XOR AL,AH ;DATA AS EXPECTED ? + JNE RMW5 ;NO THEN EXIT + ;DATA WAS GOOD---NOW GET NEXT PATTERN INTO THIS CAPTURE REG + MOV DX,IDREG ;ADDRESS OF ID REG + MOV AL,BL ;NEW PATTERN TO WRITE + OUT DX,AL ;WRITE IT TO ID REG + MOV DX,DI ;ADDRESS OF DMA CTRL 2 + MOV AL,CL ;DMA CHANNEL TO SET UP + OUT DX,AL ;SET UP DMA---THIS CAUSES CAPTURE OF ID +RMW5: + RET ;RETURN TO CALLER +; +RMW ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; INHIBIT A BLOCK OF MEMORY +; +; DESCRIPTION : This routine will set a block of SMAS memory with +; the code to enable or inhibit it. The user simply +; specifies the starting segment and length of the block in +; PC 'real' address space that is to be enabled/inhibited. +; The appropriate entries in the Translate Table are +; written so that this specified block in 'real' address +; is enabled or protected in all 16 possible TASK ID's. +; +; +; FUNCTION/ : To enable or inhibit SMAS memory in specified areas of +; PURPOSE PC 'real'address space (ie.,diplay buffer, BIOS, +; distributed ROS...) +; +; ENTRY POINT : INHIBLK +; +; ENTRY : (AX) starting segment in PC address space to be +; CONDITIONS protected/enabled. Must be on 4K boundary else +; this routine will round UP to next 4K block. +; +; (CX) number of 4K blocks to be protected +; +; (BL) 01 = ENABLE +; 00 = INHIBIT +; +; EXIT : specified entries in Translate Table are enabled or +; inhibited for all posible task ID's. +; +; AX,BH,CX,DX ARE DESTROYED +;------------------------------------------------------------------------- +; +INHIBLK PROC +; + ;ADJUST SI FOR TRANSLATE TABLE ENTRY + XCHG AL,AH ;ROTATE RIGHT BY 8 + XOR AH,AH ;CLEAR AH + ;AX IS NOW ADJUSTED FOR ENTRY INTO + ;XLAT TABLE FOR TASK ID=0 + PUSH AX ;SAVE IT + PUSH CX ;SAVE COUNT OF 4K BLOCKS +; + MOV SI,TTDATA ;ADDRESS OF TT DATA REG + MOV DI,AIDATA ;ADDRESS OF TT DATA WITH AUTO INC + XOR BH,BH ;BH IS TASK ID +INH1: + MOV DX,TTPOINTER ;ADDRESS OF TT POINTER + POP CX ;RESTORE COUNT + POP AX ;RESTORE TT ENTRY + PUSH AX ;SAVE BOTH + PUSH CX ; OF THEM + MOV AH,BH ;APPEND TASK ID TO TT POINTER + OUT DX,AX ;SET TT POINTER TO STARTING ENTRY +INH2: + MOV DX,SI ;TT DATA REG + IN AX,DX ;READ CURRENT ENTRY + MOV DX,DI ;ADDRESS OF TT DATA WITH AUTO INC + ;DETERMINE IF ENABLE OR INHIBIT BLOCK + CMP BL,ENABLE ;WANT TO ENABLE THIS BLOCK ? + JNE INH3 ;NO - THEN DISABLE IT + AND AH,BLK_ON ;MASK OFF INHIBIT BIT + JMP INH4 +INH3: + OR AH,BLK_OFF ;MASK ON INHIBIT BIT +INH4: + OUT DX,AX ;WRITE IT THEN INC TO NEXT TT ENTRY + LOOP INH2 ;REPEAT FOR EACH BLOCK OF 4K + INC BH ;NEXT TASK ID + CMP BH,MAX_TASK_ID ;COMPLETED FOR ALL TASK ID's ? + JBE INH1 ;NO - THEN LOOP TILL DONE +INHIBLK_EXIT: + POP CX + POP AX + RET +; +INHIBLK ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; STORAGE TEST +; +; DESCRIPTION : This routine performs a bit and address test on a +; 64K block of storage. +; +; (i) 55AA is written to each location. +; (ii) 55AA is read back +; (iii) if good, write AA55 and point to next location +; (iv) repeat step (iii) for all 64K locations +; (v) repeat steps (ii) to (iv) for AA55, FF00, 0101, 0000 +; (vi) check parity bits +; +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : STGTST +; +; ENTRY : (ES) storage segment to be tested +; CONDITIONS (DS) storage segment to be tested +; +; EXIT : (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if ax = 0 and zf = 0 then parity error +; DS:SI point to failing location +; +; AX,BX,CX,DX,DI,SI ARE DESTROYED +; +;------------------------------------------------------------------------- +; +STGTST PROC +; + CMP CS:WARM_START,'Y' ;is this a warm start? + JNE STG1A ;if no then do mem test + CALL CLEAR_MEM ;if yes then just clear memory + XOR AX,AX ;set zero flag + JMP STG6 ;exit + + + ;DISABLE NMI AND ENABLE I/O CHANNEL CHECK +STG1A: + MOV AL,CS:MODEL_BYTE ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG1 ;IF NO THEN TRY FOR PC_XT + CMP AL,PC_XT ;IS IT AN XT? + JE STG1 ;IF NO THEN TRY FOR AQUARIUS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG1 ;IF NO THEN USE AT NMI REGS + ;USE PC-AT NMI REGISTER + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + ;USE PC1, XT, AQUARIUS REGISTERS +STG1: + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_OFF ;MASK OFF NMI + OUT DX,AL ;OUTPUT IT + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + + + + ;ROLL A BIT THROUGH THE FIRST WORD + SUB DI,DI ;FIRST LOCATION + MOV CX,16 ;ROLL 16 BITS + MOV AX,0001H ;FIRST PATTERN TO WRITE + MOV BX,AX ;SAVE IT +STG2: + MOV [DI],AX ;WRITE PATTERN + MOV [DI+2],0FFFFH ;CHARGE BUS + MOV AX,[DI] ;READ PATTERN + XOR AX,BX ;IS IT CORRECT ? + JNE STG_EXIT ;IF NO - THEN EXIT + SHL BX,1 ;SHIFT BIT + MOV AX,BX ;GET IT INTO AX + LOOP STG2 ;REPEAT +; + CLD ;FILL FORWARD + SUB DI,DI ;POINT TO FIRST LOCATION + MOV CX,2000H ;8K WORDS ;an000; dms; + MOV AX,55AAH ;INITIAL PATTERN TO WRITE + REP STOSW ;FILL ENTIRE SEGMENT +; + MOV BX,55AAH ;PATTERN TO LOOK FOR + MOV DX,0AA55H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; + MOV BX,0AA55H ;PATTERN TO LOOK FOR + MOV DX,0101H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; + MOV BX,0101H ;PATTERN TO LOOK FOR + MOV DX,0000H ;NEXT PATTERN TO WRITE + CALL STG_CNT + JNZ STG_EXIT ;EXIT IF ERROR +; +; MOV BX,0000H ;PATTERN TO LOOK FOR +; MOV DX,0000H ;NEXT PATTERN TO WRITE +; CALL STG_CNT +; JNZ STG_EXIT ;EXIT IF ERROR +; + ;IF TEST REACHES THIS POINT THEN MEMORY IS GOOD + ;NEED TO CHECK PARITY BITS...IF PARITY ERROR EXISTS THEN + ;CAN ASSUME BAD PARITY BIT OR BAD PARITY GENERATOR +; + MOV AL,CS:MODEL_BYTE ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG3 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE STG3 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG3 ;USE XT REGISTERS + ;IF NONE OF THE ABOVE THEN... + ;USE AT NMI REGISTER + MOV DX,AT_CHCHK_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + AND AL,AT_CHCHK ;IS CH CHK BIT ON ? + JZ STG4 ;IF NO - THEN EXIT + MOV AX,0 ;ELSE - CLEAR AX TO INDICATE + ;PARITY ERROR + JMP STG4 ;EXIT + ;USE XT/AQUARIUS NMI REGISTER +STG3: + MOV DX,XT_CHCHK_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + AND AL,XT_CHCHK ;IS CH CHK BIT ON ? + JZ STG4 ;IF NO - THEN EXIT + MOV AX,0 ;ELSE - CLEAR AX TO INDICATE + ;PARITY ERROR +STG4: +STG_EXIT: + PUSH AX ;SAVE THESE REGS + PUSH DX ;THEY CONTAIN + PUSH SI + PUSHF ;USEFUL ERROR INFORMATION + ;BEFORE NMI IS ENABLED, CLEAR PARITY CHECK LATCH ON XMA + MOV SI,0 + MOV AX,[SI] ;READ 1ST WORD OF THIS SEG + MOV [SI],AX ;WRITE BACK SAME WORD + ;THE WRITE WILL CLEAR PCHK LTCH + ;CLEAR I/O CHANNEL CHECK LATCHES AND ENABLE NMI + MOV AL,CS:MODEL_BYTE ;GET SAVED MODEL BYTE + CMP AL,PC1 ;IS IT A PC1? + JE STG5 ;USE XT REGISTERS + CMP AL,PC_XT ;IS IT AN XT? + JE STG5 ;USE XT REGISTERS + CMP AL,XT_AQUARIUS ;IS IT AN AQUARIUS? + JE STG5 ;USE XT REGISTERS + ;IF NONE OF THE ABOVE THEN... + ;USE AT NMI REGISTER + MOV DX,AT_CHCHK_EN_REG ;AT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,AT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,AT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,AT_NMI_REG ;AT's NMI REGISTER + MOV AL,AT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT + ;USE XT/AQUARIUS NMI REGISTER +STG5: + MOV DX,XT_CHCHK_EN_REG ;XT's I/O CH CHK REG + IN AL,DX ;READ IT + OR AL,XT_CHCHK_DIS ;MASK OFF I/O CH CHK ENABLE + OUT DX,AL ;WRITE IT + AND AL,XT_CHCHK_EN ;MASK ON I/O CH CHK ENABLE + OUT DX,AL ;TOGGLE CH CHK LTCH AND LEAVE + ;ENABLED + MOV DX,XT_NMI_REG ;XT's NMI REGISTER + MOV AL,XT_NMI_ON ;MASK ON NMI + OUT DX,AL ;OUTPUT IT +; + POPF + POP SI + POP DX + POP AX ;RESTORE REGS +STG6: + RET ;RETURN TO CALLER + + + +CLEAR_MEM PROC ;INTERNAL PROC TO CLEAR MEMORY + XOR DI,DI ;start of segment + XOR CX,CX ;clear entire segment + XOR AX,AX ;write zeroes + + STOSB ;just write + RET ;back to caller +CLEAR_MEM ENDP + + +STGTST ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; STORAGE TEST SUBROUTINE +; +; DESCRIPTION : This routine performs a bit and address test on a +; 64K block of storage. +; +; (i) a word is read and compared against the value in (BX) +; (ii) if good the value in (DX) is written into that location +; (iii) point to next location and repeat steps (i) to (ii) +; +; +; FUNCTION/ : See description +; PURPOSE +; +; ENTRY POINT : STG_CNT +; +; ENTRY : (ES) storage segment to be tested +; CONDITIONS (DS) storage segment to be tested +; (BX) value to be compared +; (DX) new value to be written +; +; EXIT : (zero flag) = 0 if storage error +; (AX) expected data XOR'ed with actual data +; if ax = 0 and zf = 0 then parity error +; DS:SI point to failing location +;------------------------------------------------------------------------- +; +STG_CNT PROC +; + MOV CX,2000H ;8K WORDS ;an000; dms; + SUB DI,DI ;FIRST LOCATION + MOV SI,DI ;FIRST LOCATION +SC1: + LODSW ;READ OLD WORD FROM STORAGE + XOR AX,BX ;DATA AS EXPECTED ? + JNE SC2 ;IF NO - THEN EXIT + MOV AX,DX ;GET NEW PATTERN + STOSW ;WRITE IT + LOOP SC1 ;REPEAT +SC2: + RET + +STG_CNT ENDP + + + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; PRINT MEMORY GOOD +; +; DESCRIPTION : This routine will print to the screen how much memory +; has been tested. +; +; The format will be: xxxx KB TESTED +; +; FUNCTION/ : See description +; PURPOSE +; +; +; ENTRY POINT : KB_OK +; +; ENTRY : (DX) = 1/4 OF GOOD MEMORY + 64K IN KB +; CONDITIONS ex: if (DX) = 16 then +; (16 * 4) + 64 = 128KB is OK +; +; NOTE: if (DX) = FFF0 then 0 KB is OK +; +; +; EXIT : Message is displayed +; +; All registers are preserved +; +;------------------------------------------------------------------------- +; +KB_OK PROC +; + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH DS ;SAVE REGISTERS +; + PUSH CS + POP DS ;GET DS TO THIS CODE SEGMENT + ;CONVERT DX TO KILO BYTES + SHL DX,1 + SHL DX,1 ;MULTIPLY BY 4 + ADD DX,16 ;ADJUST BY 16 ;an000; dms; +; + MOV AX,DX ;GET NUMBER INTO AX + MOV BX,10 ;READY FOR DECIMAL CONVERT + MOV CX,4 ;OF 4 DIGITS +K1: + XOR DX,DX ;CLEAR HI WORD OF DIVIDEND + ;AX IS LOW WORD OF DIVIDEND + DIV BX ;DIVIDE BY 10 + OR DL,30H ;MAKE MODULO INTO ASCII + PUSH DX ;SAVE IT + LOOP K1 ;REPEAT FOR ALL DIGITS +; + XOR SI,SI ;CLEAR SI + MOV CX,4 +K2: + POP AX ;ASCII DIGIT GOES INTO AL + MOV BX,OFFSET MEM_OK + MOV CS:[BX+SI],AL ;BUILD ASCII MESSAGE + INC SI + LOOP K2 + ;MOVE THE CURSOR AND PRINT MESSAGE + MOV DX,CUR_SAVE + MOV BH,ACTIVE_PAGE + MOV AH,2 ;SET CURSOR + + INT 10H ;BIOS VIDEO CALL SET CURSOR + MOV AH,9 ;DOS PRINT STRING + MOV DX,OFFSET SIZE_MSG1 + 1 ;OFFSET OF MEM_OK MSG + INT 21H ;DISPLAY MESSAGE + + POP DS + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX ;RESTORE ALL REGISTERS + + RET ;RETURN TO CALLER + +KB_OK ENDP + + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; SET TRANSLATE TABLE +; +; DESCRIPTION : This routine will write the Translate Table so that +; a specified block of PC 'real' address will be mapped +; to a specified block of SMAS physycal memory. Note that +; this routine will map only into CONTIGUOUS blocks of +; SMAS memory. PC memory is referenced by segments +; (must be on 4K boundaries) while SMAS memory is referenced +; by block number (each block is 4K). +; +; EXAMPLE: segment 4000 can be mapped to block 5 +; segment 4100 can be mapped to block 6 +; +; FUNCTION/ : To map PC 'real' addresses into SMAS physical memory. +; PURPOSE +; +; +; ENTRY POINT : SETXLAT +; +; ENTRY : (AX) starting segment in PC address space to be +; CONDITIONS mapped. Must be on 4K boundary else +; this routine will round UP to next 4K block. +; +; (CX) number of 4K blocks translated. +; +; (BH) task ID for this memory allocation +; +; (BL) 01 = ENABLE +; 00 = INHIBIT +; +; (DX) starting block number in SMAS memory +; +; +; EXIT : specified entries in Translate Table are enabled or +; inhibited for all posible task ID's. +; +; +; AX,CX,DX ARE DESTROYED +; +;------------------------------------------------------------------------- +; +SETXLAT PROC +; + ;ADJUST AX FOR TRANSLATE TABLE ENTRY + XCHG AL,AH ;ROTATE RIGHT BY 8 + MOV AH,BH ;TASK ID INTO BH + ;AX IS NOW ADJUSTED FOR ENTRY INTO + ;XLAT TABLE FOR TASK ID=(BH) + PUSH DX ;SAVE STARTING SMAS BLOCK NUMBER +; + MOV DX,TTPOINTER ;ADDRESS OF TT POINTER + OUT DX,AX ;SET TT POINTER TO STARTING ENTRY + POP AX ;GET STARTING BLOCK NUMBER INTO AX +; + MOV DX,AIDATA ;TT DATA REG WITH AUTO INC + ;DETERMINE IF ENABLE OR INHIBIT BLOCK + CMP BL,ENABLE ;WANT TO ENABLE THIS BLOCK ? + JE SETX1 ;YES - THEN SKIP THE DISABLE STEP + OR AH,BLK_OFF ;MASK ON INHIBIT BIT +SETX1: + OUT DX,AX ;WRITE IT THEN INC TO NEXT TT ENTRY + INC AX ;NEXT BLOCK OF SMAS MEMORY + LOOP SETX1 ;REPEAT FOR EACH BLOCK OF 4K +SETXLAT_EXIT: + RET +; +SETXLAT ENDP + + PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; AUTO-INCREMENT TEST +; +; DESCRIPTION : This routine will test the auto-increment of +; the Translate Table pointer. The test will procede +; in the following manner: +; (i) A basic check of the TT pointer reg is performed +; (ii) The TT pointer is initialized to '00'H +; (iii) The auto increment data reg is written +; (iv) The TT pointer is read and checked for increment +; (v) Repeat until TT pointer wraps from 'FFF'H to '000'H +; (vi) Repeat test for auto-increment for read of data reg +; +; FUNCTION/ : To ensure that the Translate Table pointer can auto +; PURPOSE increment when 31A5 is written or read. +; +; ENTRY POINT : INCTST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : +; (zero flag) = 0 indicates an error +; (DX) failing register (ie.,TT pointer reg) +; (AX) expected data XOR'ed with actual data +;------------------------------------------------------------------------- +; +; +INCTST PROC +; + MOV AL,AUTO_INC + MOV CS:TEST_ID,AL +; +;PERFORM SIMPLE TEST OF TTPOINTER REG +; + MOV BX,0AA55H ;SET UP PATTERN TO WRITE + MOV AX,BX + MOV DX,TTPOINTER ;I/O TO TTPOINTER REG + MOV SI,TTDATA ;SAVE FOR I/O TO TTDATA + OUT DX,AX ;WRITE THE REGISTER + XCHG DX,SI ;I/O TO TTDATA REG + XCHG AH,AL ;INVERSE PATTERN + OUT DX,AX ;CHARGE BUS WITH OPPOSITE PATTERN + XCHG DX,SI ;I/O TO TTPOINTER REG + IN AX,DX ;READ TTPOINTER REG + XOR AX,BX ;READ AS EXPECTED + AND AX,0FFFH ;MASK OFF HI NIBBLE (INVALID) + JNE INC_ERROR ;NO - THEN EXIT +; +;CONTINUE WITH AUTO-INC TEST +; + MOV DI,2 ;2 PASSES...1 WRITE , 1 READ +AI1: + MOV SI,AIDATA ;SAVE FOR I/O TO TTDATA WITH AUTO-INC +AI2: + MOV CX,1000H ;TTPOINTER RANGE 0 -> FFF + MOV BX,0001H ;INITIAL COMPARE VALUE + MOV AX,0 ;SET TTPONTER TO ZERO + OUT DX,AX ;TTPOINTER IS INITIALIZED TO ZERO +AI2X: + XCHG DX,SI ;I/O TO TTDATA WITH AUTO-INC +; +;DETERMINE IF WRITE OR READ TEST +; + CMP DI,2 ;DOING A AUTO-INC WRITE TEST ? + JNE AI3 ;NO - THEN MUST BE AUTO-INC READ TEST + OUT DX,AX ;WRITE TO AUTO-INC DATA REG + JMP AI4 ;CONTINUE WITH TEST +AI3: + IN AX,DX ;READ FROM AUTO-INC DATA REG +AI4: + XCHG DX,SI ;I/O TO TTPOINTER REG + IN AX,DX ;READ TTPOINTER (31A1 -> AH) + XOR AX,BX ;DATA AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE (INVALID) + JNE INC_ERROR ;NO - GO TO ERROR + INC BX ;NEXT VALUE TO LOOK FOR + LOOP AI2X ;CONTINUE TIL ALL VALUES ARE TESTED +; + DEC DI + CMP DI,0 ;COMPLETE WITH WRITE AND READ TEST ? + JE INC_EXIT ;YES - THEN EXIT + JMP AI1 ;NO - THEN CONTINUE WITH READ TEST +; +INC_ERROR: +INC_EXIT: RET +; +INCTST ENDP + +PAGE +;------------------------------------------------------------------------- +;------------------------------------------------------------------------- +; +; TRANSLATE TABLE TEST +; +; DESCRIPTION : This routine performs a write/read storage test +; on the Translate Table. The test is as follows: +; (i) A bit is rolled through the first word of the TT +; (ii) A bit and address test is performed on the +; remainder of the TT. +; +; FUNCTION/ : To verify the integrity of the Translate Table. +; PURPOSE +; +; ENTRY POINT : XLATST +; +; ENTRY : NONE +; CONDITIONS +; +; EXIT : Entire Translate Table is left with FFF (passover code) +; +; (zero flag) = 0 indicates an error +; (DX) failing register (TT data register) +; (AX) expected data XOR'ed with actual data +; (31A0) address in TT of failure +;------------------------------------------------------------------------- +; +XLATST PROC +; + MOV AL,XLAT_TABLE_TEST + MOV CS:TEST_ID,AL +; +;ROLL A BIT THROUGH THE FIRST BYTE +; + MOV BX,0001H ;SET UP INITIAL PATTERN + MOV SI,TTDATA ;SAVE FOR I/O TO DATA REG + MOV DX,TTPOINTER ;I/O TO TTPOINTER REG + MOV CX,12 ;ROLL 12 BIT POSITIONS + XOR AX,AX ;CLEAR AX (WRITE TO 1st TT LOCATION) + OUT DX,AX ;SET TT POINTER + XCHG DX,SI ;READY FOR I/O TO TTDATA REG +X1: + MOV AX,BX ;GET BIT PATTERN + OUT DX,AX ;WRITE BIT PATTERN TO TT + XCHG DX,SI ;READY FOR I/O TO TTPOINTER REG + XOR AX,AX ;CLEAR AX + OUT DX,AX ;CHARGE BUS WITH 0000 PATTERN + XCHG DX,SI ;READY FOR I/O TO TTDATA REG + IN AX,DX ;READ TT (31A1 -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF UPPER NIBBLE (INVALID) + JNE XLA_ERROR ;NO - THEN EXIT + SHL BX,1 ;SHIFT BIT TO NEXT POSITION + LOOP X1 +; +;CONTINUE REMAINDER OF TRANSLATE TABLE +; + MOV DX,AIDATA +; + XCHG DX,SI ;READY FOR I/O TO TTPOINTER + XOR AX,AX ;CLEAR AX + OUT DX,AX ;TTPOINTER AT 1st LOCATION +; + XCHG DX,SI ;READY FOR I/O TO TT DATA W/AUTO-INC + MOV AX,0AA55H ;INITIAL DATA PATTERN + MOV CX,TABLEN ;NUMBER OF TT ENTRIES +X2: + OUT DX,AX ;SETUP INVERSE PATTERN + LOOP X2 ;FILL ENTIRE XLATE TABLE +; + MOV SI,TTDATA ;ADDRESS OF TTDATA WITHOUT INC. + MOV BX,AX ;SAVE VALUE FOR COMPARE + MOV DI,055AAH ;NEXT PATTERN TO WRITE +X3: + MOV CX,TABLEN ;NUMBER OF TT ENTRIES +X4: + XCHG DX,SI ;GET IT INTO DX...SI GETS AUTO-INC + IN AX,DX ;READ TABLE ENTRY (HI BYTE -> AH) + XOR AX,BX ;DATA READ AS EXPECTED ? + AND AX,0FFFH ;MASK OFF HI NIBBLE (INVALID) + JNE XLA_ERROR ;NO - THE EXIT + XCHG DX,SI ;GET TTDATA WITH AUTO-INC + MOV AX,DI ;RECOVER NEXT PATTERN TO WRITE + OUT DX,AX ;WRITE IT THEN INCREMENT + LOOP X4 ;REPEAT TILL TABLE FILLED + + +; + CMP DI,0FFFFH ;LAST PASS ? + JE XLA_EXIT ;YES - THEN EXIT REG TEST +; + XCHG BX,DI ;BX GETS NEXT PATTERN TO TEST +; + CMP BX,055AAH ;LAST PASS FOR AA55,55AA PATTERN? + JNE X5 ;NO + MOV DI,0FF00H ;YES- PREPARE TO WRITE NEW PATTERN + JMP X3 ;DO IT +X5: + CMP BX,0FF00H ;READY TO READ 0FF00 PATTERN + JNE X6 ;NO + MOV DI,00FFH ;YES- PREPARE TO WRITE NEW PATTERN + JMP X3 ;DO IT +X6: + MOV DI,0FFFFH ;PREPARE TO SET ALL OF TT INACTIVE + JMP X3 ;DO IT +; +XLA_ERROR: +XLA_EXIT: RET +; +XLATST ENDP diff --git a/v4.0/src/DEV/XMA2EMS/XMA2EMS.ASM b/v4.0/src/DEV/XMA2EMS/XMA2EMS.ASM new file mode 100644 index 0000000..43f038f --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/XMA2EMS.ASM @@ -0,0 +1,2591 @@ + +PAGE 85,132 ;Set for 5182 Pageprinter + ;85 lines per page, 132 col per line + ;(formerly 60,132) + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º º +;º This is the new version of the XMA2EMS driver for DOS 3.3. º +;º It contains the following revisions and code flags: º +;º º +;º @RH0 - Correct scrolling problem º +;º @RH1 - Expand table to 32M º +;º @RH2 - Real Mode support (XMA/A card) º +;º @RH3 - Memory Expansion Option (MXO a.k.a. XMO) support º +;º @RH4 - LIM 4.0 support º +;º @RH5 - Multicard support º +;º @RH6 - WSP interfaces º +;º @RH7 - 386 XMA Emulator support º +;º @RH8 - Make driver reentrant º +;º º +;º AN007 P5134 - Provide variable planar size support. º +;º Modify linked list to forward link vs. the º +;º reverse linked list. º +;º º +;º AN008 P5150 - Fix incorrect access of slot 0 when no º +;º Catskill/Holster card is in slot 0. º +;º º +;ÇÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĶ +;º It should be noted that certain EMS calls will alter the contents º +;º of the translate table pointer for any supported memory cards or º +;º emulators (i.e. MXO, XMA, XMA/A cards, 80386 XMA emulator). º +;º Therefore, software that writes to the translate table(s) has the º +;º responsiblity of keeping the integrity of the TT pointer. For º +;º example, programs should disable interrupts between setting the º +;º TT pointer and writing the TT data. This will prevent: An interrupt º +;º occurring between the two, control going to another application º +;º that makes an EMS call and thus screws up the TT ptr. The EMS calls º +;º that do this are: º +;º Function # EMS Call º +;º 5 Map logical to physical page º +;º 8, 15/0 Save (Get) mapping array º +;º 9, 15/1 Restore (Set) mapping array º +;º 15/2 Get and Set mapping array º +;º º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +;XMA2EMS provides a Lotus/Intel/Microsoft Expanded Memory (EMS) interface +;for the IBM Expanded Memory Adapter (XMA). + +;Program Property of Microsoft + +;Add the following statement to CONFIG.SYS +; DEVICE=[d:][path]XMA2EMS.SYS + + +;-----------------------------------------------------------------------; +; Equates go here ; +;-----------------------------------------------------------------------; +EMS_INT EQU 67H ;EMS INTERRUPT +EM_INT EQU 15H ;EM INTERRUPT ;an000; dms; +DK_Int equ 13h ;disk interrupt ;an004; dms; +EM_Size_Get EQU 88h ;get EM size ;an000; dms; +EMM_VERSION EQU 40H ;VERSION 4.0 +PF_HI_LIMIT EQU 0E000H ;highest allowable page frame segment +PF_LOW_LIMIT EQU 0A000H ;lowest allowable page frame segment +OK EQU 'OK' ;card is good +HW_ERROR EQU 'HW' ;card is not functional...HardWare error +SW_ERROR EQU 'SW' ;SoftWare error has been detected +PAGE_INHIBITTED EQU 0FFFFh ;Entry in the save area indicating + ; a page is currently inhibitted +REUSABLE_HANDLE EQU 'HR' ;Reusable (free) entry in the @RH1 + ; handle lookup table. Placed in @RH1 + ; the 'pages' field @RH1 +REUSABLE_SAVEA EQU 'SR' ;Reusable (free) entry in the @RH1 + ; handle save area. 0 is a valid @RH1 + ; page #, and 'FFFF' is for saving @RH1 + ; an inhibitted field, so S(ave) @RH1 + ; R(eusable) is stored. Page 5352 @RH1 + ; not a valid page (5352 = 333Meg) @RH1 + ;Page Allocation List entries + ; Allocated pages have the handle # +UNALLOCATED EQU 'U' ; Unused entry +ALLOCATED EQU 'X' ; Temporary...used by reallocate @RH4 +PAL_NULL EQU '--' ; End of list marker @RH8 +EXTENDED EQU 'ME' ; Extended memory (not for EMS use)@RH8 +BACMEM_ALLOC EQU 'MB' ; Allocated to back conventional @RH8 + ; memory (back disabled planar) +WSP_ALLOC EQU 'SW' ; Allocated to Workstation Program @RH8 + ; Pages kept as extended memory by: +RESR_EXT EQU 'ER' ; /E parameter +PREV_EXT EQU 'EP' ; Previously loaded drivers + ; These values are OK as long as the + ; # of handles supported (40h) is + ; not above the ascii 'B' (42h) +WARM_MASK EQU 1 ;ISOLATE WARM START BIT +OFFSET_IN_XREF EQU BYTE PTR[BX+SI] +LENGTH_IN_XREF EQU BYTE PTR[BX+SI+1] +PAGE_LIST_ENTRY EQU WORD PTR[SI + OFFSET PAGE_ALLOC_LIST] ; @RH8 +page_table_entry EQU byte PTR[SI + OFFSET PAGE_ALLOC_table] ;temp for assembl +XREF_TABLE_ENTRY EQU word PTR[DI + OFFSET HANDLE_XREF_TABLE] ; @RH1 +NUM_PHYSICAL_PAGES EQU 4 +STACK_SIZE EQU 100H +Instance_Size EQU 150 ;instance size ;an000; dms; +Instance_Count EQU 3 ;number of instances ;an000; dms; + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Common memory adapter declares ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +SLOT_SETUP EQU 08h ;Mask to put the desired adapter @RH2 + ; slot into setup mode, activating @RH2 + ; the 10X registers @RH2 +CARD_ID_LO EQU 100H ;PS/2 Adapter card id low and @RH2 +CARD_ID_HI EQU 101H ; high bytes - read only @RH2 + ;Card IDs read from port 100,101 @RH2 +XMAA_CARD_ID EQU 0FEF7h ; XMA/A Card ID @RH2 +HLST_CARD_ID EQU 0FEFEh ; MXO @RH3 +NO_CARD EQU 0FFFFh ; No card present @RH5 + ;Values for the flag MEMCARD_MODE @RH5 + ; indicating what type of memory @RH5 + ; card is being used. @RH5 +XMA1_VIRT EQU 00000001B ; XMA 1...always in virtual +XMAA_VIRT EQU 00000010B ; XMA/A card (PS/2) in virtual +EMUL_VIRT EQU 00000100B ; XMA emulator on 80386 @RH7 +XMAA_REAL EQU 00001000B ; XMA/A in real mode...no banking @RH3 +HOLS_REAL EQU 00010000B ; MXO card @RH3 + ;Combinations +XMA1A_VIRT EQU 00000011B ; XMA1 or XMA/A in virtual mode +WSP_VIRT EQU 00000111B ; Any virtual mode...banking used + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ XMA, XMA\A, and XMA emulator declares ³ + ;³ ³ + ;³ The XMA translate table is a 4K x 12 bit ³ + ;³ array. A 12 bit address points to entries ³ + ;³ in the TT. The data in the entry is: ³ + ;³ ³ + ;³ Bit Contents ³ + ;³ 12 Inhibit bit (1 = inhibit xlate) ³ + ;³ 10-0 On XMA 1, pointer to 4K block ³ + ;³ for up to 4 meg capability ³ + ;³ 11-0 On XMA/A, pointer to 4K block ³ + ;³ for up to 8 meg capability ³ + ;³ ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + ;All are byte ports unless indicated + +X_CTRL_REG EQU 102H ;Control register - en/disable functions +X_CONF_REG EQU 105H ;Config (mem size), channel check reg. +RM_TTPTR_LO EQU 106H ;Translate table pointer low and +RM_TTPTR_HI EQU 107H ; high bytes +RM_TTDATA_LO EQU 103H ;TT data - high and low bytes +RM_TTDATA_HI EQU 104H ; Low byte (103) auto incs the TT ptr + + ;Virtual mode port addresses for: +TTPOINTER EQU 31A0H ; Translate Table Pointer (word) +TTDATA EQU 31A2H ; Translate Table Data (word) +AIDATA EQU 31A4H ; TT Data with auto increment (word) +IDREG EQU 31A6H ; Bank ID register +MODE_REG EQU 31A7H ; Mode register +DMACAPT EQU 31A8H ; DMA capture register + +CR_ROMSLEEP_DIS EQU 11011111B ;XMA/A control register mask to + ; disable the ROM on XMA/A card +XMA_TT_INHIBIT EQU 0000100000000000B ;XMA mask for an inhibitted TT entry +XMA_TT_MASK EQU 0000111111111111B ;XMA mask for anding off unused bits +EMUL_TTDATA_ON EQU 1000000000000000B ;XMA translate table data - mask for + ; the emulator. On XMA cards, data + ; is only 12 bits. On the emulator, + ; bit 15 turned on indicates data is + ; 15 bits. This allows the emulator + ; to use more than 8 Meg. Note that + ; both 0FFFh and FFFFh are inhibit. + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ MXO declares ³ + ;³ ³ + ;³ The MXO translate table is a 1K x 8 bit ³ + ;³ array. A 10 bit address points to entries ³ + ;³ in the TT. The data in the entry is: ³ + ;³ ³ + ;³ Bit Contents ³ + ;³ 8 Inhibit bit (0 = inhibit xlate) ³ + ;³ 7-0 Pointer to 16K block for up to ³ + ;³ 2 meg capability ³ + ;³ ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + ;All are byte ports +H_CARD_INFO EQU 102H ;Info Bits 7-1 mem size Bit 0 sleep +H_CC_PRES EQU 105H ;Channel check, presence (Bit 0) +H_TTPTR_LO EQU 106H ;Translate table pointer low and +H_TTPTR_HI EQU 107H ; high bytes +H_TTDATA EQU 103H ;TT data - one byte. No auto inc. + +H_TT_INHIBIT EQU 00000000B ;MXO value for setting inhibitted + ; translate table entry +H_TT_ENBMASK EQU 10000000B ;Pattern to test if TT entry read is + ; enabled. 'and' with entry,jz inhib + + ;EMS ERROR CODES +EMS_CODE80 EQU 80H ; Sotware malfunction +EMS_CODE81 EQU 81H ; Hardware malfunction +EMS_CODE82 EQU 82H ; This return code not used +EMS_CODE83 EQU 83H ; Handle not found +EMS_CODE84 EQU 84H ; Invalid function code +EMS_CODE85 EQU 85H ; All handles used +EMS_CODE86 EQU 86H ; Save or restore mapping error +EMS_CODE87 EQU 87H ; Not enough pages to satisfy request +EMS_CODE88 EQU 88H ; Not enough unallocated pages +EMS_CODE89 EQU 89H ; Can't allocate zero pages +EMS_CODE8A EQU 8AH ; Logical page out of range +EMS_CODE8B EQU 8BH ; Physical page out of range +EMS_CODE8C EQU 8CH ; Hardware save area is full +EMS_CODE8D EQU 8DH ; Save area already saved for handle +EMS_CODE8E EQU 8EH ; Save area not saved for this handle +EMS_CODE8F EQU 8FH ; Subfunction parameter not defined +;------------------------------------------------------------------- +EMS_CODE91 EQU 091H +EMS_CODE92 EQU 092H ; added for DMS ;an000; +EMS_CODE93 EQU 093H ;an000; +EMS_CODE94 EQU 094H ;an000; +EMS_CODE95 EQU 095H ;an000; +EMS_CODE96 EQU 096H ;an000; +EMS_CODE97 EQU 097H ;an000; +EMS_CODE98 EQU 098H ;an000; +EMS_CODE9E EQU 09EH ;an000; +EMS_CODE9C EQU 09CH ;an000; +;------------------------------------------------------------------- ;an000; +EMS_CODEA0 EQU 0A0h ; No matching handle +EMS_CODEA1 EQU 0A1h ; Duplicate handle name +EMS_CODEA2 EQU 0A2h ; Memory wrap error +EMS_CODEA3 EQU 0A3h ; Data in control structure corrupted +EMS_CODEA4 EQU 0A4h ; Access to this function denied + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Request Header (Common portion) ³ +;³ ³ +;³ This structure defines the portion that is common to ³ +;³ all Request Headers. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +RH EQU DS:[BX] ;addressability to Request Header structure + +RHC STRUC ;fields common to all request types + DB ? ;length of Request Header (including data) + DB ? ;unit code (subunit) +RHC_CMD DB ? ;command code +RHC_STA DW ? ;status + DQ ? ;reserved for DOS +RHC ENDS ;end of common portion + +CMD_INPUT EQU 4 ;RHC_CMD is INPUT request + +;status values for RHC_STA + +STAT_GOOD EQU 0000H ;invalid command code error +STAT_DONE EQU 0100H ;function complete status (OR on bit) +STAT_CMDERR EQU 8003H ;invalid command code error +STAT_CRC EQU 8004H ;CRC error +STAT_SNF EQU 8008H ;sector not found error +STAT_GENFAIL EQU 800CH ;general failure +NOT_BUSY EQU 11111101B ;busy bit (9) NOT BUSY mask (high order byte) +BUSY_MASK EQU 00000010B ;busy bit (9) BUSY mask (high order byte) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Request Header for INIT command ³ +;³ ³ +;³ This structure defines the Request Header for the ³ +;³ INIT command ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +RH0 STRUC + DB (TYPE RHC) DUP (?) ;common portion + +RH0_NUN DB ? ;number of units + ;set to 1 if installation succeeds, + ;set to 0 to cause installation failure +RH0_ENDO DW ? ;offset of ending address +RH0_ENDS DW ? ;segment of ending address +RH0_BPBO DW ? ;offset of BPB array address +RH0_BPBS DW ? ;segment of BPB array address +RH0_DRIV DB ? ;drive code (DOS 3 only) +RH0_ERR DW 0 ; error flag used by DOS - gga +RH0 ENDS + +RH0_BPBA EQU DWORD PTR RH0_BPBO ;OFFSET/SEGMENT OF BPB +;note RH0_BPBA at entry to init points to all after DEVICE= on CONFIG.SYS stmt + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Request Header for OUTPUT STATUS command ³ +;³ ³ +;³ This structure defines the Request Header for the ³ +;³ Output Status command. ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +RH10 STRUC + DB (TYPE RHC) DUP (?) ;common portion +RH10 ENDS + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Request Header for Generic IOCTL Request ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +RH19 STRUC + DB (TYPE RHC) DUP (?) ; Reserve space for the header @RH6 + +RH19_MAJF DB ? ; Major function @RH6 +RH19_MINF DB ? ; Minor function @RH6 +RH19_SI DW ? ; Contents of SI @RH6 +RH19_DI DW ? ; Contents of DI @RH6 +RH19_RQPK DD ? ; Pointer to Generic IOCTL request packet @RH6 +RH19 ENDS + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Map EMS INT 67H vector in low storage ³ +;³ ³ +;³ The vector for the interrupt handler for INT 67H ³ +;³ is defined here. ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INT_VEC SEGMENT AT 00H + ORG 4*EMS_INT +EMS_VEC LABEL DWORD +EMS_VECO DW ? ;offset +EMS_VECS DW ? ;segment +INT_VEC ENDS + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Map EM INT 15H vector in low storage ³ +;³ ³ +;³ The vector for the extended memory interrupt handler INT 15h ³ +;³ is defined here. ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INT_VEC15 SEGMENT AT 00H ;an000; dms; + ORG 4*EM_INT ;an000; dms; +EM_VEC LABEL DWORD ;an000; dms; +EM_VECO DW ? ;offset ;an000; dms; +EM_VECS DW ? ;segment ;an000; dms; +INT_VEC15 ENDS ;an000; dms; + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Map INT 13h vector in low storage ³ +;³ ³ +;³ The vector for the disk access interrupt handler INT 13h ³ +;³ is defined here. ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INT_VEC13 SEGMENT AT 00H ;an004; dms; + ORG 4*DK_INT ;an004; dms; +DK_VEC LABEL DWORD ;an004; dms; +DK_VECO DW ? ;offset ;an004; dms; +DK_VECS DW ? ;segment ;an004; dms; +INT_VEC13 ENDS ;an004; dms; + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º This marks the start of the device driver code segment º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +CSEG SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:CSEG + +START EQU $ ;begin resident XMA2EMS data & code + +;DEVICE HEADER - must be at offset zero within device driver + DD -1 ;becomes pointer to next device header + DW 0C040H ;attribute (character device) + DW OFFSET STRATEGY ;pointer to device "strategy" routine + DW OFFSET IRPT ;pointer to device "interrupt handler" + DB 'EMMXXXX0' ;device name + + +;-----------------------------------------------------------------------; +; The next word is used to inform the 3270 Workstation Program ; +; which 4K block in XMA marks the start of EMS Expanded Memory. ; +;-----------------------------------------------------------------------; +EMS_START_IN_XMA DW 0 ;initially, memory manager uses all + +;-----------------------------------------------------------------------; +; The following is the Code Label: +;-----------------------------------------------------------------------; +COPYRIGHT DB '74X9921 (C)COPYRIGHT 1988 Microsoft ' + DB 'LEVEL 1.00 LICENSED MATERIAL - PROGRAM ' + DB 'PROPERTY OF Microsoft ' + +;-----------------------------------------------------------------------; +; Request Header (RH) address, saved here by "strategy" routine ; +;-----------------------------------------------------------------------; +RH_PTRA LABEL DWORD +RH_PTRO DW ? ;offset +RH_PTRS DW ? ;segment + db 7 dup(0) ;align following tables on seg. + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ HANDLE LOOKUP TABLE ³ +;³ ³ +;³ This table keeps track of EMS handles and pages assigned ³ +;³ to each handle. An entry exists for each of the 64 handles ³ +;³ supported. If the handle is active, the first field will ³ +;³ contain the number of pages it owns. Otherwise, the field ³ +;³ will indicate the handle is free. The second field is a head ³ +;³ pointer to the handle's pages in the linked Page Allocation List. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +H_LOOKUP_STRUC STRUC ;Structure for Handle lookup table @RH1 +H_PAGES DW REUSABLE_HANDLE ;If handle is active, # of owned @RH8 + ; pages. Init to reusable handle RH8 +H_PAL_PTR DW PAL_NULL ;Head ptr for owned pages in PAL @RH8 +H_NAME DB 8 DUP(0) ;Name - new for LIM 4.0 @GGA +H_BANK DB 0 ;If virtual, this handle's bank @RH6 +xref_pages dw 0 ;temp to compile +xref_index dw 0 ;temp to compile +H_LOOKUP_STRUC ENDS + +NUM_HANDLES EQU 64 ;One structure @RH1 +HANDLE_LOOKUP_TABLE H_LOOKUP_STRUC <0,,,,,> ; initialize handle 0 + H_LOOKUP_STRUC NUM_HANDLES-1 DUP (<>) ; for OS use - gga + +;-----------------------------------------------------------------------; +; HANDLE CROSS REFERENCE (XREF) TABLE ; +; Each entry in the Handle_Xref_Table points to a corresponding ; +; page in the page allocation table. Entries in the XREF table ; +; are contiguous for a handle, while PAT entries may not be. ; +;-----------------------------------------------------------------------; +XREF_TABLE_LEN EQU 2048 ; @RH1 + +HANDLE_XREF_TABLE DW XREF_TABLE_LEN DUP(0) ; Changed from byte to @RH1 + ; word table @RH1 +XREF_TABLE_END EQU ($) ;Used for table shift on deallocate @RH1 +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ PAGE ALLOCATION LIST ³ +;³ ³ +;³ This is the structure pointed to by the handle lookup table. ³ +;³ The Page Allocation list is a linked list governing EMS pages. ³ +;³ Each 16KB EMS page has an entry in the PAGE_ALLOC_LIST. ³ +;³ The entries correspond to the physical blocks on the extended ³ +;³ memory cards (ex. the first 2 Meg card in a system will use the ³ +;³ first 128 entries in the PAL). ³ +;³ At initialization time, a 'free' pointer will point to the last³ +;³ (top) page in the PAL, and all entries will be linked from top ³ +;³ down. Whenever pages are allocated they are retreived from the ³ +;³ free chain, and deallocated pages are placed back on the free ³ +;³ chain. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +EMS_PAGES_SUPPORTED EQU 1024 ;Support up to 16 Megabytes of EMS @RH8 + +PAGE_ALLOC_LIST DW EMS_PAGES_SUPPORTED DUP(0) + ;Page Allocation List (PAL) @RH8 +page_alloc_table db 1024 dup(unallocated) ;temp for assemble +;-----------------------------------------------------------------------; +; HANDLE SAVE AREA ; +; Each handle has 4 entries where the page frame map can ; +; be stored. Each entry contains a word for the handle and ; +; a word for the logical page active there. If no save has ; +; occurred for a handle, then the logical page field in the ; +; save area will contain a value indicating it's reusable. ; +;-----------------------------------------------------------------------; +H_SAVEA_ENTRY STRUC ;This is an overlay for one page's @RH5 +HSA_HNDL DW ? ; entry in the handle save area. @RH5 +HSA_LP DW ? ; It is used to clear the save @RH5 +H_SAVEA_ENTRY ENDS ; area after a restore. While not @RH5 + ; directly used by the structure @RH5 + ; below, its size should match @RH5 + ; that for one page entry @RH5 + +H_SAVE_STRUC STRUC ;Structure for Handle Save Area @RH1 +PG0_HNDL DW 0 +PG0_LP DW REUSABLE_SAVEA +PG1_HNDL DW 0 +PG1_LP DW REUSABLE_SAVEA +PG2_HNDL DW 0 +PG2_LP DW REUSABLE_SAVEA +PG3_HNDL DW 0 +PG3_LP DW REUSABLE_SAVEA +PGFE_HNDL DW 0 ;AN006; +PGFE_LP DW REUSABLE_SAVEA ;AN006; +PGFF_HNDL DW 0 ;AN006; +PGFF_LP DW REUSABLE_SAVEA ;AN006; +H_SAVE_STRUC ENDS + +HANDLE_SAVE_AREA H_SAVE_STRUC NUM_HANDLES DUP (<>) + ;One structure for each handle @RH1 + +H_SAVE_ENTRY EQU WORD PTR[DI + OFFSET HANDLE_SAVE_AREA] ; @RH1 + + +;------------------------------------------------------------------- +; +; mappable_phys_page table +; +; This table is used by function 5800h +; +;------------------------------------------------------------------- + +mappable_phys_page_struct STRUC ; define the structure + phys_page_segment dw ? ; segment + phys_page_number dw ? ; page ID + ppm_handle dw ? ; handle, -1 means unused + ppm_log_page dw ? ; logical page, -1 means unused +mappable_phys_page_struct ENDS + +; allocate the storage + +map_table mappable_phys_page_struct <-1, -1, -1, -1> ;p0 no default + mappable_phys_page_struct <-1, -1, -1, -1> ;p1 no default + mappable_phys_page_struct <-1, -1, -1, -1> ;p2 no default + mappable_phys_page_struct <-1, -1, -1, -1> ;p3 no default + mappable_phys_page_struct <-1, -1, -1, -1> ;p254 no default + mappable_phys_page_struct <-1, -1, -1, -1> ;p255 no default + +map_count_def equ 6 ; default 6 +map_count dw 0 ; +map_size dw type mappable_phys_page_struct * map_count_def ; size of default table +ppm_size equ 6 ;size of partial page map entry + +; flags and a word used in setting up map_table stuff, see parmpars.inc + +p0_flag equ 0001h ; flags used to indicate which p's were +p1_flag equ 0002h ; set on command line +p2_flag equ 0004h +p3_flag equ 0008h +p254_flag equ 0010h +p255_flag equ 0020h +frame_flag equ 8000h ; special flag used when FRAME= was found + +page_flags dw 0 ; word of above flags used in setting map_table +parse_flag dw 0 ; flag used to indicate command line args were encountered + +;------------------------------------------------------------------- +; rom scan stuff +;------------------------------------------------------------------- +family1 equ 1 +micro_channel equ 2 + + +rom_scan_type dw micro_channel ; +segment_error dw 0 ; segment error flag = 0 means all OK + +;----------------------------------------------------------------------- +; Tables added for multicard support º +; º +; These tables manage the mapping of multiple memory cards º +; on a PS/2 Model 50 and 60. These systems may have a combination º +; of MXO and XMA/A cards. The model 80 is excluded, since º +; it uses the XMA emulator. º +; º +;----------------------------------------------------------------------- + ;----------------------------------------------- + ; Memory Card Descriptor Table º + ;----------------------------------------------- + +MEM_CARD_STRUC STRUC ;Structure for the memory cards @RH5 +CARD_ID DW NO_CARD ;Card ID from ports 100 and 101 @RH5 +CARD_SLOT DB ? ;Physical slot of card (0 based) @RH5 +START_PG_NUM DW ? ;Starting and ending #s of the @RH5 +END_PG_NUM DW ? ; pages this card has within the @RH5 +MEM_CARD_STRUC ENDS ; total EMS page pool (0 based) @RH5 + + ;Memory Card Table - entries are @RH5 + ; filled in ascending order (from @RH5 + ; slot 0) for each card found. @RH5 + ; MXOs scanned 1st, then XMA/A @RH5 +MAX_SLOTS EQU 8 ;Max of 8, but most @RH5 +MEM_CARD_TABLE MEM_CARD_STRUC MAX_SLOTS DUP (<>) ; likely 1 or 2 cards @RH5 + + ;----------------------------------------------- + ; Multicard Page Frame Descriptor Table º + ;----------------------------------------------- +MULTIC_PM_STRUC STRUC ;Structure for storing the card ID @RH5 +PG_CARD DW NO_CARD ; and slot of the card currently @RH5 +PG_SLOT DB 0 ; mapped to this page of the page @RH5 +MULTIC_PM_STRUC ENDS ; frame @RH5 + + ;Multicard Page Mapping Table. + ; Entry for each page of the page + ; frame (including pages FE & FF) +MC_PM_TABLE MULTIC_PM_STRUC MAP_COUNT_DEF DUP (<>) + + ;----------------------------------------------- + ; Assorted Multicard declares º + ;----------------------------------------------- +NUM_MEM_CARDS DW 0 +NUM_OF_SLOTS DB ? ;Number of adapter slots RR 8 TB 4 @RH2 +WTT_CARD_SLOT DB ? ;Slot # of the memory card being @RH2 + ; used to map a page @RH2 + + +Instance_Entry_Struc struc ;required data in first 2 entries ;an000; dms; + IE_Alloc_Byte db ? ;instance allocated byte ;an000; dms; + IE_Saved_DI_Reg dw ? ;saved di register ;an000; dms; +Instance_Entry_Struc ends ;end struc ;an000; dms; + +;-----------------------------------------------------------------------; +; Table of DOS command processing routine entry points ; +; ; +; An '*' in the comment area indicates the command is handled ; +; by meaningful code. All other commands simply set a good ; +; return code and exit back to DOS. ; +;-----------------------------------------------------------------------; +CMD_TABLE LABEL WORD + DW OFFSET INIT ; 0 - *Initialization + DW OFFSET MEDIA_CHECK ; 1 - Media check + DW OFFSET BLD_BPB ; 2 - Build BPB + DW OFFSET INPUT_IOCTL ; 3 - IOCTL input + DW OFFSET INPUT ; 4 - Input + DW OFFSET INPUT_NOWAIT ; 5 - Non destructive input no wait + DW OFFSET INPUT_STATUS ; 6 - Input status + DW OFFSET INPUT_FLUSH ; 7 - Input flush + DW OFFSET OUTPUT ; 8 - Output + DW OFFSET OUTPUT_VERIFY ; 9 - Output with verify + DW OFFSET OUTPUT_STATUS ;10 - *Output status + DW OFFSET OUTPUT_FLUSH ;11 - Output flush + DW OFFSET OUTPUT_IOCTL ;12 - IOCTL output + DW OFFSET DEVICE_OPEN ;13 - Device OPEN + DW OFFSET DEVICE_CLOSE ;14 - Device CLOSE + DW OFFSET REMOVABLE_MEDIA ;15 - Removable media + DW OFFSET INVALID_FCN ;16 - Invalid IOCTL function gga ;AN003; + DW OFFSET INVALID_FCN ;17 - Invalid IOCTL function gga ;AN003; + DW OFFSET INVALID_FCN ;18 - Invalid IOCTL function gga ;AN003; + DW OFFSET GENERIC_IOCTL ;19 - *Generic IOCTL function gga ;AN003; + DW OFFSET INVALID_FCN ;20 - Invalid IOCTL function gga ;AN003; + DW OFFSET INVALID_FCN ;21 - Invalid IOCTL function gga ;AN003; + DW OFFSET INVALID_FCN ;22 - Invalid IOCTL function gga ;AN003; + DW OFFSET GET_LOG_DEVICE ;23 - Invalid IOCTL function gga ;AN003; +MAX_CMD EQU ($-CMD_TABLE)/2 ;highest valid command follows + DW OFFSET SET_LOG_DEVICE ;24 - Invalid IOCTL function gga ;AN003; + +;-----------------------------------------------------------------------; +; Table of Expanded Memory Manager routine entry points ; +;-----------------------------------------------------------------------; +FCN_TABLE LABEL WORD + DW OFFSET EMM_STATUS ;40 - Get status of memory manager + DW OFFSET Q_PAGE_FRAME ;41 - Get segment of page frame + DW OFFSET Q_PAGES ;42 - Get number of alloc & unalloc pgs + DW OFFSET GET_HANDLE ;43 - Request ID and allocate n pages + DW OFFSET MAP_L_TO_P ;44 - Map logical to physical page + DW OFFSET DE_ALLOCATE ;45 - Deallocate all pages of ID n + DW OFFSET Q_VERSION ;46 - Get version number + DW OFFSET SAVE_MAP ;47 - Save mapping array + DW OFFSET RESTORE_MAP ;48 - Restore mapping array + DW OFFSET GET_PORT_ARRAY ;49 - Get I/O port array + DW OFFSET GET_L_TO_P ;4A - Get logical to physical array + DW OFFSET Q_OPEN ;4B - Get number of open ID's + DW OFFSET Q_ALLOCATE ;4C - Get pages allocated to ID n + DW OFFSET Q_OPEN_ALL ;4D - Get all ID's and pages allocated + DW OFFSET GET_SET_MAP ;4E - Group of subfunctions that Get + ;and/or Set the page map + +;------------------------------------------------------------------- ;GGA +; these functions were added for LIM 4.0 support ;GGA +;------------------------------------------------------------------- ;GGA + ;GGA + dw offset partial_map ; 4F - get/set partial page map ;GGA + dw offset map_mult ; 50 - map/unmap multiple handle pages ;GGA + dw offset reallocate ; 51 - reallocate pages ;GGA + dw offset handle_attrib ; 52 - get/set handle attributes ;GGA + dw offset handle_name ; 53 - get/set handle name ;GGA + dw offset handle_dir ; 54 - get handle directory ;GGA + dw offset alter_and_jump ; 55 - alter page map and jump ;GGA + dw offset alter_and_call ; 56 - alter page map and call ;GGA + dw offset exchng_region ; 57 - move/exchange memory region ;GGA + dw offset address_array ; 58 - Get mappable physical address array ;GGA + dw offset hardware_info ; 59 - Get extended momory hardware information ;GGA + dw offset alloc_raw ; 5A - allocate raw pages ;GGA + dw offset alternate_map ; 5B - alternate map register set ;GGA + dw offset prepare_boot ; 5C - Prepare for WarmBoot ;GGA +MAX_FCN EQU ($-FCN_TABLE)/2 ; highest valid command follows ;GGA + dw offset enable_os ; 5D - enable/disable OS/E functions ;GGA + +;-----------------------------------------------------------------------; +; Data variables go here ; +;-----------------------------------------------------------------------; +PAGE_FRAME_STA DW 0D000H ;STARTING SEG OF PAGE FRAME +TOTAL_SYS_PAGES DW 1024/16 ;Total number of 16k pages on the + ; memory card(s) that are initially + ; expanded memory. On PS/2 50 + 60, + ; pages used as extended are subtracted. +TOTAL_EMS_PAGES DW 1024/16 ;Pages left after conventional + ; memory is backed +FREE_PAGES DW 1024/16 ;Total unallocated pages for EMS use +EM_Ksize dw ? ;size in Kb of extended memory ;an000; dms; +CARD_STATUS DW 'OK' ;STATUS OF THE HARDWARE + ; DEFAULT='OK' FAILURE='HW' +MANAGER_STATUS DW 'OK' ;STATUS OF THE MEMORY MANAGER + ; DEFAULT='OK' FAILURE='SW' +STARTING_BLOCK DW 0 ;number of 4K blocks reserved by pinta +OVERFLOW DB 0 +WARM_START DB 'N' ;initially not a warm start +MULTIPLIER DW ? ;Used for figuring table offsets @RH1 +TEN DW 10 ; via multiplication...not the @RH1 +SIXTEEN DW 16 ; most efficient, but flexible @RH1 +MEMCARD_MODE DB XMA1_VIRT ;Flag indicating the type of memory@RH2 + ; card being used. Default to @RH2 + ; XMA 1 card. +BANKID DB ? ;Current XMA Bank ID @RH1 +BLOCKS_PER_PAGE DW 4 ;XMA blocks per EMS page (multiply)@RH1 +SEG_PER_PAGE DW 1024 ;Segments(16 bytes) per EMS page @RH1 + +INTV15 LABEL DWORD ;an000; dms; +INTV15O DW ? ;offset ;an000; dms; +INTV15S DW ? ;segment ;an000; dms; + +INTV13 LABEL DWORD ;an004; dms; +INTV13O DW ? ;offset ;an004; dms; +INTV13S DW ? ;segment ;an004; dms; + +PAL_FREE_PTR DW PAL_NULL +;------------------------------------------------------------------- +; define some flags and storage for the enable/disable functions +;------------------------------------------------------------------- + +ose_enabled equ 1 ; flags used to enable/disable OS/E fcns ;an000; +ose_disabled equ 0 ;an000; + +access_code dd 0 ; access code used by OS/E functions ;an000; +ose_functions dw ose_enabled ; OS/E functions 1 = enabled, 0 = disabled ;an000; + +;------------------------------------------------------------------- +; define some storage for the ROM scan logic +;------------------------------------------------------------------- +where_to_start dw 0a000h ; start ROM scan at A000 + + +;-----------------------------------------------------------------------; +; INT 15H Interrupt Handler routine ; +;-----------------------------------------------------------------------; + +;========================================================================= +; XMA_INT15 : This routine traps the INT 15h requests to perform its +; own unique services. This routine provides 1 INT 15h +; service; function 8800h. +; +; Service - Function 8800h: Obtains the size of EM from the word +; value EM_KSize +; Call With: AX - 8800h +; Returns : AX - Kbyte size of EM +; +;========================================================================= +XMA_INT15 PROC ;an000; dms; + + cmp ah,EM_Size_Get ;an000; dms;function 88h? + jne XMA_INT15_Jump ;an000; dms;no - jump to old INT 15h + mov ax,cs:EM_KSize ;an000; dms;return size + clc ;an000; dms;clear CY + jmp XMA_INT15_Exit ;an000; dms;exit handler + +XMA_INT15_Jump: ;an000; dms; + + jmp cs:INTV15 ;an000; dms;jump to org. vector + +XMA_INT15_Exit: ;an000; dms; + + + iret ;an000; dms; + +XMA_INT15 ENDP ;an000; dms; + +include I13HOOK.INC ;an004; dms; + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Device "strategy" entry point º +;º º +;º Retain the Request Header address for use by Interrupt routine º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +STRATEGY PROC FAR + MOV CS:RH_PTRO,BX ;offset + MOV CS:RH_PTRS,ES ;segment + RET +STRATEGY ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º DOS Device "interrupt" entry point º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +IRPT PROC FAR ;device interrupt entry point + PUSH DS ;save all registers Revised + PUSH ES + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + ;BP isn't used, so it isn't saved + CLD ;all moves forward + + LDS BX,CS:RH_PTRA ;get RH address passed to "strategy" into DS:BX + + MOV AL,RH.RHC_CMD ;command code from Request Header + CBW ;zero AH (if AL > 7FH, next compare will + ;catch that error) + + CMP AL,MAX_CMD ;if command code is not too high + JNA IRPT_CMD_OK ; then handle the command + MOV RH.RHC_STA,STAT_CMDERR ;"invalid command" and error + JMP IRPT_CMD_EXIT + +IRPT_CMD_OK: + MOV RH.RHC_STA,STAT_GOOD ;initialize return to "no error" + + ADD AX,AX ;double command code for table offset + MOV DI,AX ;put into index register for JMP + +;At entry to command processing routine: +; DS:BX = Request Header address +; CS = VDISK code segment address +; AX = 0 + + CALL CS:CMD_TABLE[DI] ;call routine to handle the command + + +IRPT_CMD_EXIT: ;return from command routine + ;AX = value to OR into status word + LDS BX,CS:RH_PTRA ;restore DS:BX as Request Header pointer + OR RH.RHC_STA,STAT_DONE ;add "done" bit to status word + POP SI ;restore registers + POP DI + POP DX + POP CX + POP BX + POP AX + POP ES + POP DS + + RET ;far return back to DOS +IRPT ENDP + +include genioctl.inc ; include code for genioctl fcn gga + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Set 'OUTPUT STATUS' entry point º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +OUTPUT_STATUS PROC ;Output status + LDS BX,CS:RH_PTRA ;DS:BX as pointer to request header + MOV AX,RH.RHC_STA ;get status word +OS1: + AND AH,NOT_BUSY ;turn off busy bit +OS2: + MOV RH.RHC_STA,AX ;write it back to request header + RET +OUTPUT_STATUS ENDP + + +IGNORED_CMDS PROC +IRPT_CMD_ERROR: ;CALLed for unsupported character mode commands + +MEDIA_CHECK: ;Media check +BLD_BPB: ;Build BPB +INPUT_IOCTL: ;IOCTL input +INPUT: ;Input +INPUT_NOWAIT: ;Non destructive input no wait +INPUT_STATUS: ;Input status +INPUT_FLUSH: ;Input flush +OUTPUT: ;Output +OUTPUT_VERIFY: ;Output with verify +OUTPUT_FLUSH: ;Output flush +OUTPUT_IOCTL: ;IOCTL output +DEVICE_OPEN: ;Device OPEN +DEVICE_CLOSE: ;Device CLOSE +REMOVABLE_MEDIA: ;Removable media +INVALID_FCN: ; invalid IOCTL function ;AN003; +GET_LOG_DEVICE: ; get logical device ;AN003; +SET_LOG_DEVICE: ; set logical device ;AN003; + RET +IGNORED_CMDS ENDP + + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for EMM interrupt handler º +;º º +;º º +;º The interrupt vector 67H points here. º +;º º +;º On Entry: º +;º The AH register contains the function number and the º +;º necessary parameters are passed in registers defined º +;º by the Expanded Memory Specification. º +;º º +;º On Exit: º +;º (AH) = 0 if no error º +;º (AH) = error # if error º +;º º +;º other register contain information as specified by EMSº +;º otherwise all registers remain unchanged º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +EMS_INT67 PROC + push bp ;save instance pointer ;an000; dms; + call Set_Instance ;set BP to proper instance entry ;an000; dms; + jc INT67_Instance_Exit ;not enough instances ;an000; dms; + + mov cs:[bp].IE_Saved_DI_Reg,di ;save reg in instance table ;an000; dms; + + + SUB AH,40H ;adjust to range of fcn table + CMP AH,0 ;too low? +; $IF GE,AND + JNGE $$IF1 + CMP AH,MAX_FCN ;too high? +; $IF LE + JNLE $$IF1 + MOV DI,OFFSET INT67_EXIT ;get common exit addr + PUSH DI ;put it on stack + PUSH AX ;save ax...al may contain parms + XCHG AH,AL ;adjust + XOR AH,AH ; for ax + ADD AX,AX ; to be offset into table + MOV DI,AX ;use di for index into table + POP AX ;recover ax ... parms in al +;At entry to function handler: +; CS = INT67 code segment +; TOP OF STACK is return address, INT67_EXIT + + JMP CS:FCN_TABLE[DI] ;call routine handler +; $ENDIF +$$IF1: + MOV AH,EMS_CODE84 ;function call out of range + + + +INT67_EXIT: + + mov di,cs:[bp].IE_Saved_DI_Reg ;save reg in instance table ;an000; dms; + call Reset_Instance ;deallocte instance entry ;an000; dms; + +INT67_Instance_Exit: + + pop bp ;restore instance pointer ;an000; dms; + + IRET ;end of interrupt 67 +EMS_INT67 ENDP + + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for EMM STATUS Function 1 º +;º º +;º on entry: (AH) = '40'x º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +EMM_STATUS PROC + CMP MANAGER_STATUS,SW_ERROR ;is manager ok? +; $IF E ;if no then + JNE $$IF3 + MOV AH,EMS_CODE80 ;indicate bad status + JMP ST1 ;exit +; $ENDIF +$$IF3: + CMP CARD_STATUS,HW_ERROR ;is card ok? +; $IF E ;if no then + JNE $$IF5 + MOV AH,EMS_CODE81 ;indicate bad status + JMP ST1 ;exit +; $ENDIF +$$IF5: + XOR AH,AH ;set good return status +ST1: + RET ;return to caller +EMM_STATUS ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET PAGE FRAME Function 2 º +;º º +;º on entry: (AH) = '41'x º +;º º +;º on exit: (AH) = status º +;º (BX) = segment address of page frame º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_PAGE_FRAME PROC + push cx ;save regs ;an000; dms; + push dx ; ;an000; dms; + push si ; ;an000; dms; + + cmp cs:Map_Count,4 ;enough frames? ;an000; dms; + jb Q_Page_Frame_Error_Exit ;no - exit with error ;an000; dms; + + mov cx,4h ;loop only 4 times ;an000; dms; + xor ax,ax ;page number reference ;an000; dms; + mov si,offset cs:Map_Table ;point to map table ;an000; dms; + mov bx,cs:[si].Phys_Page_Segment ;set start segment value ;an000; dms; + mov dx,bx ;segment reference ;an000; dms; + +Q_Page_Frame_Loop: + + cmp cs:[si].Phys_Page_Number,ax ;page matches reference? ;an000; dms; + jne Q_Page_Frame_Error_Exit ;no - exit with error ;an000; dms; + + cmp cs:[si].Phys_Page_Segment,dx ;page frame match reference ;an000; dms; + jne Q_Page_Frame_Error_Exit ;no - exit with error ;an000; dms; + + add si,Type Mappable_Phys_Page_Struct;adjust pointer ;an000; dms; + add dx,400h ;next page frame ;an000; dms; + inc ax ;next page ;an000; dms; + loop Q_Page_Frame_Loop ;continue loop ;an000; dms; + + xor ah,ah ;set good return ;an000; dms; + jmp Q_Page_Exit ;exit the routine ;an000; dms; + +Q_Page_Frame_Error_Exit: + + mov ah,EMS_Code80 ;signal software error ;an000; dms; + +Q_Page_Exit: + + pop si ;restore regs ;an000; dms; + pop dx ; ;an000; dms; + pop cx ; ;an000; dms; + + RET +Q_PAGE_FRAME ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for QUERY TOTAL & UNALLOCATED PAGES Function 3 º +;º º +;º on entry: (AH) = '42'x º +;º º +;º on exit: (AH) = status º +;º (BX) = number of pages available in expanded memory º +;º (DX) = total number of pages in expanded memory º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_PAGES PROC + + XOR AH,AH ;Init good return status + MOV BX,CS:FREE_PAGES ;bx gets num unalloc pages + MOV DX,CS:TOTAL_EMS_PAGES ;dx gets num total pages + CMP BX,DX ;If unalloc <= total then OK + JNA Q_PAGES_RET ;Otherwise sumptin's rong + MOV AH,EMS_CODE81 ; set that return code +Q_PAGES_RET: + RET +Q_PAGES ENDP + + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET HANDLE AND ALLOCATE Function 4 º +;º º +;º on entry: (AH) = '43'x º +;º (BX) = number of pages to allocate º +;º º +;º on exit: (AH) = status º +;º (DX) = handle º +;º AX,DX Revised...all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +GET_HANDLE PROC + PUSH BX + PUSH CX + PUSH DI + PUSH SI + PUSH DS ;save these registers + + PUSH CS ;get cs + POP DS ;into ds + + ;Remove test for BX = 0. This is @RH4 + ; valid under LIM 4.0 + + cmp bx,0 ;0 page allocate is invalid ;an000; dms; + jne GH_OKCount ;0 pages not requested ;an000; dms; + mov ah,EMS_Code89 ;flag 0 pages requested ;an000; dms; + jmp GH_Exit ;exit routine ;an000; dms; + +GH_OKCount: + + CMP BX,TOTAL_EMS_PAGES ;Enough total EMS pages? + JNA GH_OKTOTAL + MOV AH,EMS_CODE87 + JMP GH_EXIT + +GH_OKTOTAL: + cli ;ints off ;an000; dms; + CMP BX,FREE_PAGES ;Enough unallocated pages? + sti ;ints on ;an000; dms; + JNA GH_OKFREE + MOV AH,EMS_CODE88 + JMP GH_EXIT + ;----------------------------------------------------- + ; Search for a free handle @RH1 º + ;----------------------------------------------------- +GH_OKFREE: + MOV CX,NUM_HANDLES ;loop counter is #handles + DEC CX ;handle 0 reserved for op. sys. @RH1 + MOV DX,1 ;handle assignment set to 1 @RH1 + MOV DI,TYPE H_LOOKUP_STRUC ;init table index to 1st entry @RH1 +;-------------------------------- + CLI ;interrupts OFF during allocation +;-------------------------------- +GH_FREEHSRCH: + CMP HANDLE_LOOKUP_TABLE.H_PAGES[DI],REUSABLE_HANDLE + ;Is this handle available? @RH1 + JE GH_HFREE ;yes end search dx=handle id @RH1 + INC DX ;next handle assignment + ADD DI,TYPE H_LOOKUP_STRUC ;next entry in handle lookup @RH1 + ;repeat for all table entries + LOOP GH_FREEHSRCH + MOV AH,EMS_CODE85 ;no available handles + JMP GH_EXIT ;go to exit ;GGA + + ;----------------------------------------------------- + ; If here then there's enough pages for request. @RH1 º + ; DX = handle #, DI = ptr to hndl lookup entry @RH1 º +GH_HFREE: + + MOV CX,NUM_HANDLES ;loop counter + DEC CX ;handle 0 reserved for op. sys. @RH1 + ;si = index to hndl lookup tbl @RH1 + MOV SI,TYPE H_LOOKUP_STRUC ; for adding pages (skip 0 entry) @RH1 + XOR AX,AX ;clear page counter + CLC ;clear carry for addition +GH_PAGESUM: + CMP HANDLE_LOOKUP_TABLE.H_PAGES[SI],REUSABLE_HANDLE + JE GH_PGSUM_BOT ;If handle is free don't add @RH4 + ADD AX,HANDLE_LOOKUP_TABLE.H_PAGES[SI] + ;add lengths (pages) of PALs @RH1 + ADD SI,TYPE H_LOOKUP_STRUC ; next entry in handle lookup @RH1 +GH_PGSUM_BOT: + LOOP GH_PAGESUM + CMP AX,TOTAL_EMS_PAGES ;pages in handle lookup > total? @RH1 + JNA GH_CALCHLUP ;no OK @RH1 + MOV AH,EMS_CODE80 ;software error..we screwed up @RH1 + JMP GH_EXIT ;go to exit @RH1 ;GGA + +GH_CALCHLUP: ;calculate entry in hndl lkup tbl @RH1 + + cli ;ints off ;an001; dms; + mov cx,bx ;alloc count ;an000; dms; + call EMS_Page_Contig_Chk ;do we have contig pgs. ;an001; dms; + jnc GH_Alloc ;yes continue process ;an001; dms; + mov ah,EMS_Code88 ;no signal error ;an001; dms; + sti ;ints on ;an001; dms; + jmp GH_Exit ;exit routine ;an001; dms; + +GH_Alloc: + + call EMS_Link_Set ;set up links ;an001; dms; + + + sub Free_Pages,bx ;free = free - requested pages + mov Handle_LookUp_Table.H_Pages[di],bx ;page count ;an000; dms; + mov Handle_LookUp_Table.H_Pal_Ptr[di],si ;initialize to ptr for ;ac001; dms; + ; pages + sti ;ints on ;an001; dms; + xor ah,ah ;clear flag ;an000; dms; + + +GH_EXIT: ;GGA + + POP DS + POP SI + POP DI + POP CX + POP BX + + RET +GET_HANDLE ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for MAP LOGICAL TO PHYSICAL PAGE Function 5 º +;º º +;º on entry: (AH) = '44'x º +;º (AL) = physical page j º +;º (BX) = logical page i º +;º (DX) = handle º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ + +MAP_L_TO_P PROC + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH DS ;save these registers + PUSH CS ;get cs + POP DS ;into ds + + CMP BX,PAGE_INHIBITTED ;If the log pg = inhibit, ignore @RH4 + JNE MLP_HANDLE_CHK ; checking handle ID. Restore PF @RH4 + MOV SI,BX ; calls this proc, and a saved pg @RH4 + JMP SHORT MLP_GET_SEG ; that has never been mapped will @RH4 + ; have no handle ID @RH4 + +MLP_HANDLE_CHK: + CMP DX,NUM_HANDLES-1 ;handle within range ? + JBE MLP_DXINRANGE + MOV AH,EMS_CODE83 ;handle not found + JMP MLP_EXIT ;exit +MLP_DXINRANGE: + push ax ;save affected regs ;an000; dms; + push dx ; ;an000; dms; + MOV AX,DX ; (DX:AX used in MUL @RH1 + MOV DX,TYPE H_LOOKUP_STRUC ;SI = entry's offset into @RH8 + MUL DX ; the handle lookup table @RH8 + MOV SI,AX ; @RH1 + pop dx ;restore affected regs ;an000; dms; + pop ax ; ;an000; dms; + + MOV CX,HANDLE_LOOKUP_TABLE.H_PAGES[SI] ;CX = handle's pages @RH8 + CMP CX,REUSABLE_HANDLE ;Handle have pages? + JNE MLP_DXHASPAGES ;Yes next check + MOV AH,EMS_CODE83 ;No handle not used + JMP MLP_EXIT ; set error and exit +MLP_DXHASPAGES: + CMP BX,TOTAL_EMS_PAGES ;Logical pg requested (0 based) @RH1 + JB MLP_BX_LE_TOT ; less than or = to total pages? @RH1 + MOV AH,EMS_CODE8A ;No... logical page out of range + JMP MLP_EXIT ;exit +MLP_BX_LE_TOT: + CMP BX,CX ;Logical page requested <= number @RH1 + JB MLP_LP_OK ; of pages for this handle? + MOV AH,EMS_CODE8A ;No...error log. page out of range @RH1 + JMP MLP_EXIT ;exit + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Convert handle's logical page to ³ + ;³ relative page in the EMS pool (SI) ³ + ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +MLP_LP_OK: ;Get this handle's @RH8 + MOV DI,HANDLE_LOOKUP_TABLE.H_PAL_PTR[SI] ; head index to PAL @RH8 + CMP BX,0 ;If 1st pg wanted @RH8 + JE MLP_GOT_PHYS_PG ; then we've got it @RH8 + MOV CX,BX ;Else scan linked PAL@RH8 + ; for log pg - 1. @RH8 +MLP_SCAN_PAL: ; (log p is 0 based) @RH8 + SHL DI,1 ;2 bytes per PAL ent + ; mult is slow here + MOV DI,PAGE_ALLOC_LIST[DI] ; This loop will get @RH8 + LOOP MLP_SCAN_PAL ; the index of the @RH8 +MLP_GOT_PHYS_PG: ; desired page @RH8 + MOV SI,DI ;SI = page on card @RH8 + + + + + ;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ;³ Get seg addr of the phys page (DI) ³ +MLP_GET_SEG: ;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + XOR DI,DI ;Clear offset into mappable phys. @RH4 + MOV CX,MAP_COUNT ; page table. Loop for # entries. @RH4 +MLP_PP_CHECK: + CMP AL,BYTE PTR MAP_TABLE.PHYS_PAGE_NUMBER[DI] ;AX = table pp? @RH4 + JE MLP_PP_OK ;Yes..get seg @RH4 + ADD DI,TYPE MAPPABLE_PHYS_PAGE_STRUCT ;No..check next @RH4 + LOOP MLP_PP_CHECK ; table entry @RH4 + MOV AH,EMS_CODE8B ;If here physical page not found @RH1 + JMP MLP_EXIT ; in mappable phys pg table..Error @RH1 +MLP_PP_OK: + MOV MAP_TABLE.PPM_LOG_PAGE[DI],BX ;Place the logical pg @RH4 + MOV MAP_TABLE.PPM_HANDLE[DI],DX ; the mappable pp table @RH4 + MOV DI,MAP_TABLE.PHYS_PAGE_SEGMENT[DI] ;DI= page's PC seg addr @RH1 + + ;------------------------------------- + ; Map L to P depending on memory card º + ;------------------------------------- +MLP_VIRTUAL: + TEST MEMCARD_MODE,WSP_VIRT ;Using either an XMA 1, XMA/A, or @RH2 + JZ MLP_MC_TEST ; XMA Emulator in virtual mode? @RH2 + CALL W_EMSPG_XVIRT ;Yes..Map one logical page to + JMP MLP_GOODRC ; physical page using 310X regs + ;Else not virtual...use real mode +MLP_MC_TEST: ;If system has multiple cards, @RH5 + CMP NUM_MEM_CARDS,1 ; then adjust absolute EMS page to @RH5 + JNA MLP_REAL ; its corresponding page on the @RH5 + CALL MLP_MCARD_SETUP ; card to be used @RH5 +MLP_REAL: + CMP MEMCARD_MODE,XMAA_REAL ;XMA/A card (on PS/2 mod 50 or 60) @RH3 + JNE MLP_HLST ; in real mode (WSP not loaded)? @RH3 + CALL W_EMSPG_XREAL ;Map one logical page to physical @RH2 + JMP MLP_GOODRC +MLP_HLST: ;If not XMA then MXO + CALL W_EMSPG_HLST ;Map one logical page to physical @RH3 +MLP_GOODRC: + XOR AH,AH ;Good return status..mapping + ; should always be successful +MLP_EXIT: + + POP DS ;restore these registers + POP SI + POP DI + POP DX + POP CX + POP BX + + RET +MAP_L_TO_P ENDP + + + + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subroutine: WRITE TRANSLATE TABLE FOR EMS PAGE ³ +;³ XMA VIRTUAL MODE ³ +;³ ³ +;³ This routine will write the Translate Table so that the ³ +;³ specified 16K page of 'real' address will be mapped to a ³ +;³ specified 16K page of XMA physical memory. ³ +;³ This routine is called if the XMA card is in 'virtual' ³ +;³ mode - i.e. bank swapping is active. The 16 bit 31AX ports ³ +;³ are used for setting up the XMA translate table. ³ +;³ The XMA 1 card and XMA emulator are always in virtual ³ +;³ mode. The XMA\A card is in virtual mode if bank switching ³ +;³ is active (used by the 3270 Workstation Program). ³ +;³ ³ +;³ On entry: (DI) is starting segment in PC address space. ³ +;³ Must be on 4K boundary else is rounded ³ +;³ down to the nearest 4K. ³ +;³ (SI) absolute EMS page number (not handle relative) RH4³ +;³ or FFFFh if page is to be inhibitted RH4³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +W_EMSPG_XVIRT PROC + MOV DX,IDREG ;Save the current bank ID @RH1 + IN AL,DX ; (bank of the requestor). Write @RH1 + MOV BANKID,AL ; to the trans. table for this bank@RH1 + + MOV AX,DI ;Get the PC seg. addr of the page @RH1 + XCHG AL,AH ;Div by 256 (Segments per 4K block)@RH1 + MOV AH,BANKID ;Join with the bank ID to get the @RH1 + MOV DX,TTPOINTER ; ptr to the translate table entry @RH1 + OUT DX,AX ;Set TT ptr @RH1 + + MOV AX,SI ;Get absolute EMS page number @RH4 + CMP AX,PAGE_INHIBITTED ;Is TT entry to be inhibitted? @RH4 + JE VM_TTDATA_OK ;Yes..write the FFFF in AX @RH4 + MUL BLOCKS_PER_PAGE ;Else convert page to XMA 4K block @RH1 + TEST MEMCARD_MODE,EMUL_VIRT ;If running on the emulator then @RH7 + JZ VM_TTDATA_OK ; turn high order bit of data on @RH7 + OR AX,EMUL_TTDATA_ON ; allowing >8M support on emulator @RH7 +VM_TTDATA_OK: + MOV CX,BLOCKS_PER_PAGE ;Set up one page - loop on blocks @RH1 + MOV DX,AIDATA ; per page using the auto inc reg @RH1 +VM_WRITE: + OUT DX,AX ;Write TT entry, inc TT ptr @RH1 + CMP AX,PAGE_INHIBITTED ;Inhibit TT entry? + JE VM_NEXT_TT ;Yes..don't inc AX + INC AX ;Inc block ptr..contiguous blocks @RH1 +VM_NEXT_TT: + LOOP VM_WRITE ;Loop for all blocks in a page @RH1 + + RET +W_EMSPG_XVIRT ENDP + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subroutine: WRITE TRANSLATE TABLE FOR EMS PAGE ³ +;³ XMA REAL MODE ³ +;³ ³ +;³ This routine performs basically the same functions as ³ +;³ the above routine. It is called if the XMA/A card is in ³ +;³ 'real' mode (i.e. bank switching not active, planar memory ³ +;³ is not disabled). The 8 bit 10X ports are used for setting ³ +;³ up the XMA translate table. ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +W_EMSPG_XREAL PROC + + MOV AL,WTT_CARD_SLOT ;Put the XMA/A card into setup @RH2 + OR AL,SLOT_SETUP ; mode @RH2 + OUT 96h,AL ; @RH2 + + XOR AL,AL ;Set the translate table ptr by @RH2 + MOV DX,RM_TTPTR_HI + OUT DX,AL ; dividing the PC seg. addr in DI @RH2 + MOV AX,DI + XCHG AL,AH ; by 256 (Segments per 4K block). @RH2 + MOV DX,RM_TTPTR_LO + OUT DX,AL ;High byte always 0..no banking @RH2 + + MOV AX,SI ;Get absolute EMS page number @RH4 + CMP AX,PAGE_INHIBITTED ;Is TT entry to be inhibitted? @RH4 + JE RM_TTDATA_OK ;Yes..write the FFFF in AX @RH4 + MUL BLOCKS_PER_PAGE ;Else convert page to XMA 4K block @RH1 +RM_TTDATA_OK: + MOV CX,BLOCKS_PER_PAGE ;Set up one page - loop on blocks @RH2 + ; per page using the auto inc regs @RH2 +RM_WRITE: + XCHG AH,AL ;Write TT data high byte first, @RH2 + MOV DX,RM_TTDATA_HI ; then write low byte. This is @RH2 + OUT DX,AL ; not an auto increment port. @RH2 + XCHG AH,AL ; @RH2 + MOV DX,RM_TTDATA_LO ; @RH2 + OUT DX,AL ; @RH1 + CMP AX,PAGE_INHIBITTED ;Inhibit TT entry? + JE RM_NEXT_TT ;Yes..don't inc AX + INC AX ;Inc block ptr..contiguous blocks @RH1 +RM_NEXT_TT: + LOOP RM_WRITE ;Loop for all blocks in a page @RH1 + + MOV AL,0 ;Reset the slot ID @RH5 + OUT 96h,AL ; @RH5 + RET +W_EMSPG_XREAL ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subroutine: WRITE TRANSLATE TABLE FOR EMS PAGE ³ +;³ Memory Expansion Option (MXO) ³ +;³ ³ +;³ This routine is used to map a logical page to a physical ³ +;³ page off the MXO card. MXO has 16K blocks, as opposed ³ +;³ to 4K on the XMA. The 8 bit 10X ports are used for setting ³ +;³ up MXO's translate table. Note that the data in the ³ +;³ translate table is only 8 bits, and the high order bit is a ³ +;³ 0 to inhibit translation (where inhibit = 1 on XMA). ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +W_EMSPG_HLST PROC + PUSH CX ; @RH3 + + MOV AL,WTT_CARD_SLOT ;Put the MXO card into setup @RH3 + OR AL,SLOT_SETUP ; mode @RH3 + OUT 96h,AL ; @RH3 + + MOV AX,DI ;Set the MXO translate table @RH3 + MOV CL,10 ; ptr by dividing the PC segment @RH3 + SHR AX,CL ; addr in DI by 1024 @RH3 + MOV DX,H_TTPTR_LO ; (segments per 16K MXO block). @RH3 + OUT DX,AL ; @RH3 + XCHG AL,AH ; @RH3 + MOV DX,H_TTPTR_HI ; @RH3 + OUT DX,AL ; @RH3 + + MOV AX,SI ;Get absolute EMS page number @RH4 + CMP AX,PAGE_INHIBITTED ;Is TT entry to be inhibitted? @RH4 + JE HM_TTDATA_INH ;Yes write MXO inhibit pattern @RH4 + ;Else turn on enable and write pg @RH3 + OR AL,H_TT_ENBMASK ; (no need to convert.. 16K EMS @RH3 + JMP SHORT HM_WRITETT ; page = 16K MXO block) @RH3 +HM_TTDATA_INH: ; + MOV AL,H_TT_INHIBIT ;AL = MXO TT inhibit data @RH3 +HM_WRITETT: + MOV DX,H_TTDATA ; Write to the 1 MXO TT entry. @RH3 + OUT DX,AL ; @RH3 + MOV AL,0 ;Reset the slot ID @RH5 + OUT 96h,AL ; @RH5 + + POP CX ; @RH3 + RET +W_EMSPG_HLST ENDP + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Subroutine: MULTIPLE MEMORY CARD SETUP ³ +;³ ³ +;³ This subroutine selects the correct card in a multicard ³ +;³ system for mapping a physical page. Given the absolute page ³ +;³ number within the EMS pool (SI), it finds the card to use for ³ +;³ this page, and converts SI to the offset of the page within ³ +;³ this card. Before this new page is mapped, it may be necessary ³ +;³ to disable the translate table entry of the card that's ³ +;³ currently mapped. ³ +;³ ³ +;³ On entry: (DI) is starting segment in PC address space. ³ +;³ (SI) absolute EMS page number (not handle relative) ³ +;³ or FFFFh if page is to be inhibitted ³ +;³ ³ +;³ On exit: (DI) is unchanged. ³ +;³ (SI) offset of the page within the selected card ³ +;³ or FFFFh if page is to be inhibitted ³ +;³ WTT_CARD_SLOT = Slot # of the new card to map ³ +;³ MEMCARD_MODE = Flag indicating if XMA/A or MXO ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +PG_NEW_CARD_ID DW ? ;Holders for the ID and the slot # @RH5 +PG_NEW_CARD_SLOT DB ? ; of the card that will be used @RH5 + ; in the new mapping @RH5 +MC_TABLE_OFFSET DW ? ;Holder for offset into the @RH5 + ; multicard page mapping table @RH5 + +MLP_MCARD_SETUP PROC + PUSH AX + PUSH CX + ;------------------------------------- + ; Get the ID and slot of the card to º + ; make active. Convert SI to be º + ; the correct page within this card. º + ;------------------------------------- + PUSH DI ;Loop through the mem @RH5 + XOR DI,DI ; card table to find @RH5 + MOV CX,NUM_MEM_CARDS ; card used to map the @RH5 +MC_GET_CARD: ; absolute page (SI) @RH5 + CMP MEM_CARD_TABLE.END_PG_NUM[DI],SI ;If the last pg this @RH5 + JAE MC_FOUND_CARD ; card maps <= SI then @RH5 + ADD DI,TYPE MEM_CARD_STRUC ; use this card @RH5 + LOOP MC_GET_CARD ;Else check next card @RH5 + ; Note: if SI = FFFF @RH5 + ; the last card is @RH5 + ; selected. This is @RH5 + ; OK, since it doesn't @RH5 + ; matter which is inh @RH5 +MC_FOUND_CARD: ; @RH5 + MOV AX,MEM_CARD_TABLE.CARD_ID[DI] ;Save the card ID and @RH5 + MOV PG_NEW_CARD_ID,AX ; the slot # of the @RH5 + MOV AL,MEM_CARD_TABLE.CARD_SLOT[DI] ; card used to map @RH5 + MOV PG_NEW_CARD_SLOT,AL ; the new page. @RH5 + MOV AX,MEM_CARD_TABLE.START_PG_NUM[DI] ;If SI is not inhibit, @RH5 + CMP SI,PAGE_INHIBITTED ; convert SI from the @RH5 + JE MC_DEACTIVATE ; absolute pg number @RH5 + SUB SI,AX ; to the offset of the @RH5 + ; page within this card @RH5 + + ;------------------------------------- +MC_DEACTIVATE: ; Deactivate (inhibit) the translate º + POP DI ; table entry of the current card. º + ;------------------------------------- + ; Search for the seg addr in the @RH5 + ; map phys pg table to get the @RH5 + ; corresponding entry in the @RH5 + PUSH SI ; multicard page mapping table @RH5 + XOR SI,SI ;SI = offset into map phy pg table @RH5 + XOR AX,AX ;AX = offset into multic pm table @RH5 + MOV CX,MAP_COUNT ;Loop on # phys pgs (incl FE & FF) @RH5 +MC_SRCH_MPP: ; @RH5 + CMP MAP_TABLE.PHYS_PAGE_SEGMENT[SI],DI ;If no segment match @RH5 + JE MC_CHECK_CUR_PG ; then next entry in @RH5 + ADD SI,TYPE MAPPABLE_PHYS_PAGE_STRUCT ; map phys pg tbl & @RH5 + ADD AX,TYPE MULTIC_PM_STRUC ; multicard pm table @RH5 + LOOP MC_SRCH_MPP ; @RH5 + + ;Examine the current card ID and @RH5 + ; slot used for this page @RH5 +MC_CHECK_CUR_PG: + MOV MC_TABLE_OFFSET,AX ;Save mc tbl offset @RH5 + MOV SI,AX ; and put it in SI @RH5 + CMP MC_PM_TABLE.PG_CARD[SI],NO_CARD ;If the page is @RH5 + JE MC_MAP_NEW ; inhibitted or if @RH5 + MOV AL,MC_PM_TABLE.PG_SLOT[SI] ; the new page is @RH5 + CMP AL,PG_NEW_CARD_SLOT ; on the same card @RH5 + JE MC_MAP_NEW ; as the old page @RH5 + ; then dont inhibit @RH5 + + ;Inhibit TT entry for current card @RH5 + MOV WTT_CARD_SLOT,AL ;Save slot # and ID @RH5 + MOV AX,MC_PM_TABLE.PG_CARD[SI] ; of current card @RH5 + MOV SI,PAGE_INHIBITTED ;Page = inhibitted @RH5 + CMP AX,XMAA_CARD_ID ;If card = XMA/A @RH5 + JNE MC_INH_HLST ; then inh XMA/A TT @RH5 + CALL W_EMSPG_XREAL ; entry for pg via @RH5 + JMP SHORT MC_MAP_NEW ; real mode regs @RH5 +MC_INH_HLST: ;Else inhibit TT @RH5 + CALL W_EMSPG_HLST ; entry for MXO @RH5 + + ;------------------------------------- + ; Activate (enable) the translate º + ; table entry of the new card. º +MC_MAP_NEW: ;------------------------------------- + ;Set the multicard page frame @RH5 + ; table for the new card @RH5 + POP SI ;Restore EMS page @RH5 + PUSH DI ; and save pc seg addr. @RH5 + MOV DI,MC_TABLE_OFFSET ; @RH5 + MOV AL,PG_NEW_CARD_SLOT ;Store slot # of new card in @RH5 + MOV MC_PM_TABLE.PG_SLOT[DI],AL ; multc pm tbl and in variable @RH5 + MOV WTT_CARD_SLOT,AL ; used by map log to phys proc @RH5 + CMP SI,PAGE_INHIBITTED ;If new pg is not inhibitted @RH5 + JE MC_NEWID_INH ; then set card ID field in @RH5 + MOV AX,PG_NEW_CARD_ID ; the multicard page mapping @RH5 + MOV MC_PM_TABLE.PG_CARD[DI],AX ; table to new card ID @RH5 + JMP SHORT MC_SET_FLGS ; @RH5 +MC_NEWID_INH: ; @RH5 + MOV AX,NO_CARD ;Else set card ID as no card @RH5 + MOV MC_PM_TABLE.PG_CARD[DI],AX ; @RH5 + ;............................ + ;Set flags so main MLP proc @RH5 + ; can map the new page @RH5 +MC_SET_FLGS: ;............................. @RH5 + POP DI ;Restore PC seg addr + CMP PG_NEW_CARD_ID,XMAA_CARD_ID ;Set the flag that tells @RH5 + JNE MC_MAP_HLST ; the main Map Log to P proc @RH5 + MOV MEMCARD_MODE,XMAA_REAL ; which subroutine to call @RH5 + JMP SHORT MC_END_PROC ;At this point, @RH5 +MC_MAP_HLST: ; DI = PC segment addr of page @RH5 + MOV MEMCARD_MODE,HOLS_REAL ; SI = page's offset into card @RH5 +MC_END_PROC: ; WTT_CARD_SLOT = card slot # @RH5 + POP CX ; MEMCARD_MODE = flag showing @RH5 + POP AX ; if card is XMAA or MXO @RH5 + RET ; @RH5 +MLP_MCARD_SETUP ENDP + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for DEALLOCATE PAGES Function 6 º +;º º +;º on entry: (AH) = '45'x º +;º (DX) = handle º +;º º +;º on exit: (AH) = status º +;º AX Revised...all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +DE_ALLOCATE PROC + PUSH BX ;save these registers + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH DS + PUSH ES ; @RH1 + + PUSH CS ;get this code segment + POP DS ;into ds + PUSH CS ;Set up ES for shifting (MOVSB) @RH1 + POP ES ; the PAL table @RH1 + + cmp dx,0 ;handle zero? ;an000; dms; + jne D_Check_Handle ;no continue ;an000; dms; + mov bx,0 ;reallocate to a page count of 0 ;an000; dms; + call Reallocate ; ;an000; dms; + jmp DA_Exit ;exit routine ;an000; dms; + +D_Check_Handle: + + CMP DX,NUM_HANDLES-1 ;handle within range ? + JBE D_OKRANGE ;if not then... + MOV AH,EMS_CODE83 ;handle not found + JMP DA_EXIT ;exit +D_OKRANGE: ;check if active (valid) handle + PUSH DX ;Save handle id @RH1 + MOV AX,DX ;set up indexing into h lookup @RH1 + MOV DX,TYPE H_LOOKUP_STRUC ; @RH8 + MUL DX ;get handle lookup entry offset @RH8 + POP DX ;Restore handle id @RH1 + MOV DI,AX ;Put offset into index reg @RH1 + + CMP HANDLE_LOOKUP_TABLE.H_Pages[DI],REUSABLE_HANDLE + ;Handle has pages? @RH1 + JNE D_OKHNDL ;Yes OK handle + MOV AH,EMS_CODE83 ;No handle not in use. error. + JMP DA_EXIT ;exit + ;----------------------------------------------------- +D_OKHNDL: ; Before deallocation can continue, insure the @RH1 º + ; page frame map is not saved under this handle @RH1 º + ;----------------------------------------------------- + PUSH DX ;Save handle id @RH1 + MOV AX,DX ;Get the correct offset @RH1 + MOV DX,TYPE H_SAVE_STRUC ; into the handle save @RH8 + MUL DX ; area for this handle @RH8 + POP DX ;Restore handle id @RH1 + MOV SI,AX ; @RH1 +D_HSAVECHK: + CMP HANDLE_SAVE_AREA.PG0_LP[SI],REUSABLE_SAVEA + JE D_PAT_UPDATE ;If the 1st entry for this handle @RH1 + MOV AH,EMS_CODE86 ; in the save area is not free + JMP DA_EXIT ; then in use...exit with error + ;----------------------------------------------------- + ; Update Page Allocation List - unallocate +D_PAT_UPDATE: + + PUSH DX ;Save handle id @RH1 + + + + MOV CX,HANDLE_LOOKUP_TABLE.H_PAGES[DI] ;Get the # of pages @RH1 + MOV AX,HANDLE_LOOKUP_TABLE.H_PAL_PTR[DI] ;Load si with ptr @RH1 + MOV SI,AX ;pass ptr ;an000; dms; + + push cx ;save loop count ;an000; dms; + + cmp cx,0 ;handle has 0 pages? ;an001; dms; + je D_Depat_Exit1 ;yes - don't changes ptr;an001; dms; + + mov ax,cs:PAL_Free_Ptr ;no - dealloc pages ;an001; dms; + mov cs:PAL_Free_Ptr,si ;set free ptr to root of;an001; dms; + ; handle list + dec cx ;don't loop past last pg;an001; dms; + +D_DEPAT: + + ;this loop scans to + ;the end of the allocated + ;chain + + cmp cx,0 ;end of deallocate? ;an000; dms; + je D_Depat_Exit ;yes - exit ;an000; dms; + shl si,1 ;no - adjust to index ;an001; dms; + mov si,Page_Alloc_List[si] ;get new ptr val ;an001; dms; + dec cx ;dec loop ctr ;an001; dms; + jmp D_DEPAT ;continue ;an000; dms; + +D_DEPAT_EXIT: + + shl si,1 ;adjust to index value ;an001; dms; + mov Page_Alloc_List[si],ax ;pt. last page to orig. ;an001; dms; + ; free ptr. + +D_Depat_Exit1: + + pop cx ;restore loop count ;an000; dms; + pop dx ;restore handle ;an000; dms; + + push ds ;save regs ;an000; dms; + push si ; ;an000; dms; + + mov ax,cs ;swap segs ;an000; dms; + mov ds,ax ; ;an000; dms; + mov si,offset cs:Null_Handle_Name ;point to null handle ;an000; dms; + mov ax,5301h ;set handle name func ;an000; dms; + call Handle_Name ;set the handle name to ;an000; dms; + ; nulls + pop si ;restore regs ;an000; dms; + pop ds ; ;an000; dms; + + cli ;ints off ;an000; dms; + add cs:Free_Pages,cx ;free up page ;an000; dms; + mov Handle_LookUp_Table.H_Pages[di],Reusable_Handle ;deallocate ;an000; dms; + ; handle + sti ;ints on ;an000; dms; + + xor ah,ah ;clear flag ;an000; dms; + +DA_EXIT: + + POP ES ; @RH1 + POP DS + POP SI + POP DI + POP DX + POP CX + POP BX + + RET +DE_ALLOCATE ENDP + + +;==================================================================== +; Deallocate_Chain - This routine deallocates a page from a +; handle and links it to the free list +; +; Inputs : SI - PTR to entry to deallocate +; +; Outputs : SI - PTR to next entry to deallocate +; +;==================================================================== + +Deallocate_Chain proc ;deallocate page ;an000; dms; + + push ax ;save regs ;an000; dms; + push bx ; ;an000; dms; + push cx ; ;an000; dms; + + cli ;ints off ;an000; dms; + + mov bx,si ;alloc_ptr ;an000; dms; + + mov ax,si ;get page_ptr ;an000; dms; + mov dx,Type Page_Alloc_List ;get entry size ;an000; dms; + mul dx ;get pointer val ;an000; dms; + mov si,ax ;page_ptr ;an000; dms; + + mov ax,Page_List_Entry ;page_ptr value ;an000; dms; + mov cx,cs:PAL_Free_PTR ;free_ptr ;an000; dms; + + + mov cs:PAL_Free_PTR,bx ;new free_ptr ;an000; dms; + mov Page_List_Entry,cx ;new free_ptr value ;an000; dms; + mov si,ax ;next page to deallocate;an000; dms; + sti ;ints on ;an000; dms; + + pop cx ;restore regs ;an000; dms; + pop bx ; ;an000; dms; + pop ax ; ;an000; dms; + + ret ; ;an000; dms; + +Deallocate_Chain endp ; ;an000; dms; + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for QUERY MEMORY MANAGER VERSION Function 7 º +;º º +;º on entry: (AH) = '46'x º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_VERSION PROC + MOV AL,EMM_VERSION ;al get version number + XOR AH,AH ;good return code + RET +Q_VERSION ENDP + + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for SAVE MAPPING CONTEXT Function 8 º +;º º +;º on entry: (AH) = '47'x º +;º (DX) = handle assigned to the interrupt service º +;º routine (i.e. save map under this handle). º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +SAVE_MAP PROC + PUSH DX + PUSH DI + PUSH SI + PUSH DS + PUSH ES ;save these registers + + PUSH CS ;get cs + POP DS ;into ds + PUSH CS ;Get CS into ES (save area is in + POP ES ; this segment) + + CMP DX,NUM_HANDLES-1 ;handle within range ? + JBE SM_DXINRANGE ;if not then... + MOV AH,EMS_CODE83 ;handle not found + JMP SM_EXIT ;exit +SM_DXINRANGE: + PUSH DX ;Handle destroyed by MUL @RH1 + MOV AX,DX ;SI = requested handle's @RH1 + MOV DX,TYPE H_LOOKUP_STRUC ; offset into the handle @RH8 + MUL DX ; lookup table @RH8 + MOV SI,AX ; @RH1 + POP DX ;Restore handle ID @RH1 + + CMP HANDLE_LOOKUP_TABLE.H_Pages[SI],REUSABLE_HANDLE + JNE SM_HACTIVE ;If handle is in use (active), ok @RH1 + MOV AH,EMS_CODE83 ;else handle not in use; error + JMP SM_EXIT ;exit +SM_HACTIVE: + MOV AX,DX ;DI = requested handle's @RH1 + MOV DX,TYPE H_SAVE_STRUC ; offset into the handle @RH1 + MUL DX ; save area @RH1 + MOV DI,AX ;Add the table base to @RH1 + ADD DI,OFFSET HANDLE_SAVE_AREA ; make ES:DI a pointer @RH1 + + ;------------------------------------- + ; Insure save area free for this hndl º +SM_AREACHECK: ;------------------------------------- + CMP [DI].PG0_LP,REUSABLE_SAVEA + JE SM_SAVE_OK ;If 1st entry free then OK to save @RH1 + MOV AH,EMS_CODE8D ;Else page map already saved for + JMP SM_EXIT ; this handle. Exit with error +SM_SAVE_OK: + CALL SAVE_PGFRM_MAP ;Save to area pointed to by ES:DI @RH1 + XOR AH,AH ;Set good return code +SM_EXIT: + POP ES ;restore these registers + POP DS + POP SI + POP DI + POP DX + RET ;return to caller +SAVE_MAP ENDP + +;-----------------------------------------------------------------------; +; Subroutine: SAVE PAGE FRAME MAP ; +; ; +; purpose: To save the map of the 4 pages within the ; +; page frame to a save area pointed to by ES:DI. ; +; The handle ID and logical page active within each ; +; of the 4 physical pages is saved. Each is a word ; +; value. ; +; called by: Save mapping array (Function 8) using a handle ID ; +; and our save area. ; +; Get page map (Function 15 subfunction 0) without ; +; a handle ID using the application's save area. ; +; ; +; on entry: ES:DI points to save area ; +; ; +; on exit: All registers preserved ; +;-----------------------------------------------------------------------; +SAVE_PGFRM_MAP PROC + PUSH AX ;save these registers + PUSH CX + PUSH DI + PUSH SI + PUSH DS + + PUSH CS ;get this segment into DS + POP DS + ;------------------------------------- + ; Read the current handle ID and log º + ; pg #s in the mappable phys pg tableº + ;------------------------------------- + CLD ;Set direction for STOSW forward @RH5 + XOR SI,SI ;Clear offset into mappable phys. @RH5 + MOV CX,map_count ; page table. Loop for # entries @RH5 +SM_HLP_STORE: ;Store the word for the @RH5 + MOV AX,MAP_TABLE.PPM_HANDLE[SI] ; currently active handle@RH5 + STOSW ; and logical page into @RH5 + MOV AX,MAP_TABLE.PPM_LOG_PAGE[SI] ; the save area at ES:DI @RH5 + STOSW ; STOSW moves AX to ES:DI@RH5 + ADD SI,TYPE MAPPABLE_PHYS_PAGE_STRUCT ;Next entry in mpp table @RH5 + LOOP SM_HLP_STORE ; @RH5 + + POP DS ;Recover these registers + POP SI + POP DI + POP CX + POP AX + RET ;return to caller +SAVE_PGFRM_MAP ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for RESTORE MAPPING CONTEXT Function 9 º +;º º +;º on entry: (AH) = '48'x º +;º (DX) = handle assigned to the interrupt service º +;º routine (i.e. handle map was saved under). º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +RESTORE_MAP PROC + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH DS ;save these registers + + PUSH CS ;Get CS into DS (save area is in + POP DS ; this segment) + + CMP DX,NUM_HANDLES-1 ;handle within range ? + JBE RM_DXINRANGE ;if not then... + MOV AH,EMS_CODE83 ;handle not found + JMP RM_EXIT ;exit +RM_DXINRANGE: + PUSH DX ;Handle destroyed by MUL @RH1 + MOV AX,DX ;SI = requested handle's @RH1 + MOV DX,TYPE H_LOOKUP_STRUC ; offset into the handle @RH1 + MUL DX ; lookup table @RH1 + MOV SI,AX ; @RH1 + POP DX ;Restore handle ID @RH1 + + CMP HANDLE_LOOKUP_TABLE.H_Pages[SI],REUSABLE_HANDLE + JNE RM_HACTIVE ;If handle is in use (active), ok @RH1 + MOV AH,EMS_CODE83 ;else handle not in use; error + JMP RM_EXIT ;exit +RM_HACTIVE: + MOV AX,DX ;SI = requested handle's @RH1 + MOV DX,TYPE H_SAVE_STRUC ; offset into the handle @RH1 + MUL DX ; save area @RH1 + MOV SI,AX ;Add the table base to @RH1 + ADD SI,OFFSET HANDLE_SAVE_AREA ; make DS:SI a pointer @RH1 + + ;------------------------------------- + ; Insure save area used for this hndl º +RM_AREACHECK: ;------------------------------------- + CMP [SI].PG0_LP,REUSABLE_SAVEA ;Unused save table entry? @RH1 + JNE RM_SAVE_OK ;No used..OK check next @RH1 + MOV AH,EMS_CODE8E ;Yes error ..no page map + JMP RM_EXIT ; saved. Exit. + + ;------------------------------------- + ; Call RESTORE_PGFRM_MAP º +RM_SAVE_OK: ;------------------------------------- + CALL RESTORE_PGFRM_MAP ;Restore page frame map + CMP AH,0 ;Successful? + JNE RM_EXIT ;No exit + + ;------------------------------------- + ; Clear the save area for the handle º + ;------------------------------------- + ;DS:SI still ptr to save area @RH5 + MOV CX,map_count ;Clear all saved entries @RH5 +RM_CLEAR_SA: ;Use an overlay to mark the @RH5 + MOV [SI].HSA_LP,REUSABLE_SAVEA ; save area free - put reusabl @RH5 + ADD SI,TYPE H_SAVEA_ENTRY ; indicator in the log p field @RH5 + LOOP RM_CLEAR_SA ; @RH5 + +RM_EXIT: + POP DS ;restore these registers + POP SI + POP DI + POP DX + POP CX + POP BX + RET ;return to caller +RESTORE_MAP ENDP + +;-----------------------------------------------------------------------; +; Subroutine: RESTORE PAGE FRAME MAP ; +; ; +; purpose: To restore the map of the 4 pages within the ; +; page frame from a save area pointed to by DS:SI. ; +; The save area consists of a handle ID and logical ; +; page for each of the 4 physical pages. Each is a ; +; word value. ; +; called by: Restore mapping context (Function 9) using a ; +; handle ID and our save area. ; +; Set page map (Function 15 subfunction 1) without ; +; a handle ID using the application's save area. ; +; ; +; on entry: DS:SI points to the save area ; +; ; +; on exit: (AX) = Status ; +; All other registers preserved ; +; ; +;-----------------------------------------------------------------------; +RESTORE_PGFRM_MAP PROC + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + + XOR DI,DI ;Use for mappable phys page table @RH5 + MOV CX,map_count ;Loop for all pages in page frame @RH5 +RP_RSTR_LP: ; @RH5 + PUSH DS ;Get the phys page from @RH5 + MOV AX,MAP_TABLE.PHYS_PAGE_NUMBER[DI] ; the map phys pg tbl @RH5 + POP DS ; (only AL is used) @RH5 + MOV DX,[SI] ;DX = Handle ID..inc SI @RH5 + ADD SI,TYPE PG0_HNDL ; by len needed for hnd @RH5 + MOV BX,[SI] ;BX = Log. page..inc SI @RH5 + ADD SI,TYPE PG0_LP ; by len needed for lp @RH5 + CALL MAP_L_TO_P ;Call main Map module @RH5 + CMP AH,0 ;If an error occurred @RH5 + JE RP_NEXT ; anywhere set software @RH5 + MOV AH,EMS_CODE80 ; error and exit @RH5 + JMP SHORT RP_EXIT ;Else map next page @RH5 +RP_NEXT: ;Advance offset into @RH5 + ADD DI,TYPE MAPPABLE_PHYS_PAGE_STRUCT ; map phys page table @RH5 + LOOP RP_RSTR_LP ;Loop for 4 EMS pages @RH5 + +RP_EXIT: + POP SI + POP DI ;Restore entry regs + POP DX + POP CX + POP BX + RET ;return to caller +RESTORE_PGFRM_MAP ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET EMM HANDLE COUNT Function 12 º +;º º +;º on entry: (AH) = '4B'x º +;º º +;º on exit: (AH) = status º +;º (BX) = number of open (active) EMS handles º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_OPEN PROC + PUSH CX ;save these registers + PUSH SI + PUSH DS + + PUSH CS ;get this segment + POP DS ;into ds + + XOR BX,BX ;clear open handle counter + XOR SI,SI ;SI = offset of handle lookup table@RH1 + MOV CX,NUM_HANDLES ;loop counter = number of handles +QH_CHECKALL: + CMP HANDLE_LOOKUP_TABLE.H_Pages[SI],REUSABLE_HANDLE + ;Handle have pages? @RH1 + JE QH_NEXTH ;No..not active..next @RH1 + INC BX ;Else open handle @RH1 +QH_NEXTH: + ADD SI,TYPE H_LOOKUP_STRUC ;Point to next handle lookup entry @RH1 + LOOP QH_CHECKALL ; and check it out @RH1 + XOR AH,AH ;good return status + + POP DS ;recover these registers + POP SI + POP CX + RET ;return to caller +Q_OPEN ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET EMM HANDLE PAGES Function 13 º +;º NOTE - CAN HANDLE HANDLE WITH 0 PAGES º +;º on entry: (AH) = '4C'x º +;º (DX) = handle id º +;º º +;º on exit: (AH) = status º +;º (BX) = number of pages allocated to this handle º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_ALLOCATE PROC + PUSH DX ;save these registers + PUSH SI + PUSH DS + + PUSH CS ;get this segment + POP DS ;into ds + + CMP DX,NUM_HANDLES-1 ;DX <= Number of handles @RH1 + JBE QP_DXINRANGE ;Yes OK @RH1 + MOV AH,EMS_CODE83 ;No out of range..error @RH1 + JMP Q_ALLOC_EXIT ;exit @RH1 +QP_DXINRANGE: + MOV AX,DX ;SI = offset into @RH1 + MOV DX,TYPE H_LOOKUP_STRUC ; handle lookup tbl @RH1 + MUL DX ; for the given @RH1 + MOV SI,AX ; handle @RH1 + MOV BX,HANDLE_LOOKUP_TABLE.H_Pages[SI] ;Return # of pages @RH1 + + CMP BX,REUSABLE_HANDLE ; is this one free ;AN004; + JNE QP_GOOD_RC ; no, must be a real number ;AN004; + mov ah,EMS_Code83 ; this page is not allocated currently ;an004; dms; + XOR BX,BX ; yes, zero BX (number of pages) ;AN004; + jmp Q_Alloc_Exit ; exit the routine ;an004; dms; + ;AN004; +QP_GOOD_RC: ;AN004; + XOR AH,AH ;good return status +Q_ALLOC_EXIT: + POP DS ;recover these registers + POP SI + POP DX + RET ;return to caller +Q_ALLOCATE ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET ALL OPEN HANDLES AND PAGES Function 14 º +;º º +;º on entry: (AH) = '4D'x º +;º ES:DI = Points to an array. Each entry consists of º +;º 2 words. The first word is for an active º +;º EMS handle and the 2nd word for the number º +;º of pages allocated to that handle. This º +;º procedure will fill in the table, but the º +;º requestor must supply a large enough array. º +;º º +;º on exit: (AH) = status º +;º (BX) = Number of active EMS handles º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +Q_OPEN_ALL PROC + PUSH CX ;save these registers + PUSH DX + PUSH DI + PUSH SI + PUSH DS + + PUSH CS ;get this segment + POP DS ;into ds + + MOV DI,cs:[bp].IE_Saved_DI_Reg ;restore di to its value on - gga P1501 ;an004; + ;entry + + XOR BX,BX ;Init number of active handles @RH1 + XOR DX,DX ; and handle id @RH1 + XOR SI,SI ;SI = offset into handle lup table @RH1 + MOV CX,NUM_HANDLES ;Loop for all entries in h lup tbl @RH1 +QHP_CHECKALL: + MOV AX,HANDLE_LOOKUP_TABLE.H_Pages[SI] ; @RH1 + CMP AX,REUSABLE_HANDLE ;If entry is reusable (free), @RH1 + JE QHP_NEXT ; don't count it. Check next hndl @RH1 + INC BX ;Else active handle. Inc hndl cnt @RH1 + MOV ES: WORD PTR [DI],DX ;Write handle # in the user's area @RH1 + MOV ES: WORD PTR [DI+2],AX ;Write # of pages in the 2nd word @RH1 + ADD DI,4 ;Advance ptr to user's area @RH1 +QHP_NEXT: ;Check next entry in h lup table @RH1 + ADD SI,TYPE H_LOOKUP_STRUC ;Inc offset into handle lup table @RH1 + INC DX ;Next handle ID + LOOP QHP_CHECKALL + + XOR AH,AH ;good return status + + POP DS ;restore these registers + POP SI + POP DI + POP DX + POP CX + RET ;return to caller +Q_OPEN_ALL ENDP + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for GET/SET PAGE MAP SUBFUNCTIONS Function 15 º +;º º +;º on entry: (AH) = '4E'x º +;º (AL) = subfunction number º +;º ES:DI = destination save area for Get Subfunction º +;º DS:SI = source save area for Set Subfunction º +;º º +;º on exit: (AH) = status º +;º all other registers preserved º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +SUBFCN_TABLE LABEL WORD + DW OFFSET GET_SUBFCN ;0 - Put page frame map into ES:DI array + DW OFFSET SET_SUBFCN ;1 - Set page frame map from DS:SI array + DW OFFSET GET_SET_SUBFCN ;2 - Put page frame map into ES:DI array + ;and Set page frame map from DS:SI array +MAX_SUBFCN EQU ($-SUBFCN_TABLE)/2 ;maximum allowable subfunction number + DW OFFSET SIZE_SUBFCN ;3 - Return storage requirements of the + ;Get and Set subfunctions +GET_SET_MAP PROC + MOV DI,cs:[bp].IE_Saved_DI_Reg ;restore di to its value on + PUSH BX ;save bx + CMP AL,MAX_SUBFCN ;is subfunctiion number within range? +; $IF BE ;do if yes... + JNBE $$IF86 + MOV BX,OFFSET GET_SET_EXIT ;get return address common to all subfcns + PUSH BX ;put it on stack for return + XOR AH,AH ;adjust ax to make it + ADD AX,AX ; offset into jump table + MOV BX,AX ;get it into bx for jump +;At entry to subfunction handler: +; CS = INT67 code segment +; TOP OF STACK is return address, GET_SET_EXIT + + JMP CS:SUBFCN_TABLE[BX] ;call subfunction handler +; $ENDIF +$$IF86: + ;if subfcn # is out of range then do... + MOV AH,EMS_CODE8F ;function call out of range +GET_SET_EXIT: + POP BX ;recover bx + RET ;return to caller +GET_SET_MAP ENDP + + + page +;-----------------------------------------------------------------------; +; Subfunction 0 to GET PAGE MAP Function 15/0 ; +; ; +; on entry: (AH) = '43'x ; +; (AL) = 0 ; +; ES:DI = Destination save area ; +; ; +; on exit: (AH) = status ; +; all other registers preserved ; +;-----------------------------------------------------------------------; +GET_SUBFCN PROC + PUSH DI ;save + PUSH ES ;save + + + CALL SAVE_PGFRM_MAP ;save page frame map to ES:DI + XOR AH,AH ;good return status + POP ES ;restore + POP DI ;restore + RET ;return to caller +GET_SUBFCN ENDP + + +;-----------------------------------------------------------------------; +; Subfunction 1 to SET PAGE MAP Function 15/1 ; +; ; +; on entry: (AH) = '43'x ; +; (AL) = 1 ; +; DS:SI = Source save area ; +; ; +; on exit: (AH) = status ; +; all other registers preserved ; +;-----------------------------------------------------------------------; +SET_SUBFCN PROC + PUSH SI ;save + PUSH DS ;save + CALL RESTORE_PGFRM_MAP ;restore page frame map from DS:SI + XOR AH,AH ;good return status + POP DS ;restore + POP SI ;restore + RET ;return to caller +SET_SUBFCN ENDP + + +;-----------------------------------------------------------------------; +; Subfunction 2 to GET and SET PAGE MAP Function 15/2 ; +; ; +; on entry: (AH) = '43'x ; +; (AL) = 2 ; +; ES:DI = destination save area ; +; DS:SI = source save area ; +; ; +; on exit: (AH) = status ; +; all other registers preserved ; +;-----------------------------------------------------------------------; +GET_SET_SUBFCN PROC + PUSH DI + PUSH SI + + MOV DI,cs:[bp].IE_Saved_DI_Reg ;restore di to its value on + ;entry into irpt handler + + CALL SAVE_PGFRM_MAP ;save page frame map to ES:DI + CALL RESTORE_PGFRM_MAP ;restore page frame map from DS:SI + XOR AH,AH ;good return status + + POP SI + POP DI + RET ;return to caller +GET_SET_SUBFCN ENDP + +;-----------------------------------------------------------------------; +; Subfunction 3 to RETURN SIZE OF SAVE ARRAY Function 15/3 ; +; ; +; on entry: (AH) = '43'x ; +; (AL) = 3 ; +; ; +; on exit: (AH) = status ; +; (AL) = Number of bytes needed for a GET or SET ; +; all other registers preserved ; +;-----------------------------------------------------------------------; +SIZE_SUBFCN PROC + MOV AL,TYPE H_SAVE_STRUC ;get size requirements for save area + XOR AH,AH ;good return status + RET ;return to caller +SIZE_SUBFCN ENDP + +;========================================================================= +; Set_Instance This routine accesses the instance table. +; +; Inputs : Instance_Table - Table of instances of reentrancy. +; +; Outputs : BP - pointer to instance table entry to use +; NC - instance table entry found +; CY - no instance table entry found +; AH - error code on CY +;========================================================================= + +Set_Instance proc ;set the instance table ;an000; dms; + + cli ;disable interrupts ;an000; dms; + push cx ; ;an000; dms; + + mov bp,offset cs:Instance_Table ;get pointer to instance table ;an000; dms; + mov cx,Instance_Count ;number of instances ;an000; dms; + +Set_Instance_Loop: + + cmp cs:[bp].IE_Alloc_Byte,Unallocated;unallocated entry? ;an000; dms; + je Set_Instance_Found ;open entry ;an000; dms; + add bp,Instance_Size ;next instance ;an000; dms; + loop Set_Instance_Loop ;continue ;an000; dms; + + mov ah,EMS_Code80 ;not enough instance entries ;an000; dms; + stc ;signal error ;an000; dms; + jmp Set_Instance_Exit ;exit routine ;an000; dms; + +Set_Instance_Found: + + mov cs:[bp].IE_Alloc_Byte,Allocated ;instance allocated ;an000; dms; + clc ;signal good exit ;an000; dms; + +Set_Instance_Exit: + + pop cx ;restore regs ;an000; dms; + sti ;turn on interrupts ;an000; dms; + + ret ;return ;an000; dms; + +Set_Instance endp ; ;an000; dms; + +;========================================================================= +; Reset_Instance This routine accesses the instance table. +; +; Inputs : BP - pointer to currently active instance entry +; +; Outputs : Instance_Table - Deactivated instance entry +;========================================================================= + +Reset_Instance proc + + cli ;turn off interrupts ;an000; dms; + mov cs:[bp].IE_Alloc_Byte,Unallocated;deallocate instance ;an000; dms; + sti ;set interrupts ;an000; dms; + + ret ;return ;an000; dms; + +Reset_Instance endp ; ;an000; dms; + + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Entry point for UNSUPPORTED FUNCTION CALLS º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ +UNSUPPORTED PROC + +GET_PORT_ARRAY: +GET_L_TO_P: + RET +UNSUPPORTED ENDP + + +;========================================================================= +; EMS_Page_Contig_Chk - This routine will take CX as input, which is +; the count of pages needed to satisfy the +; Allocate, Allocate Raw, or Reallocate functions. +; It will scan the unallocated page list to +; determine if there are CX number of contiguous +; pages. When it finds a block of contiguous +; pages it will return a pointer in SI pointing +; to the first page in the linked list that contains +; CX contiguous pages. If CX contiguous pages are +; not found a CY will be returned. +; +; Inputs : CX (Pages needed for request) +; +; Outputs : CY (There are no CX contiguous pages) +; NC (There are CX contiguous pages) +; SI (Pointer to 1st. page of CX contiguous pages) +;========================================================================= + +EMS_Page_Contig_Chk proc near ;determine contiguity ;an001; dms; + + push ax ;save regs ;an001; dms; + push bx ; ;an001; dms; + push cx ; ;an001; dms; + push dx ; ;an001; dms; + push di ; ;an001; dms; + +;;;; mov ax,cs:Free_Pages ;initialize page count ;an001; dms; + mov di,cs:PAL_Free_Ptr ;pointer to free list ;an001; dms; + mov si,di ;initialize ptr val ;an001; dms; +;;;; mov bx,di ;initialize base val ;an001; dms; +;;;; mov dx,1 ;initialize count val ;an001; dms; + +EMS_Page_Contig_Main_Loop: + +;;;; cmp dx,cx ;at end? ;an001; dms; +;;;; je EMS_Page_Found_Contig ;yes - found contig ;an001; dms; + +;;;; shl di,1 ;index value ;an001; dms; +;;;; mov si,Page_Alloc_List[di] ;point to next free ;an001; dms; +;;;; shr di,1 ;ptr value ;an001; dms; +;;;; dec di ;see if it is contig ;an001; dms; +;;;; cmp si,di ; ;an001; dms; +;;;; je EMS_Page_Contig_Loop ;contig - check next ;an001; dms; +;;;; jmp EMS_Page_Contig_Init_Loop ;not contig ;an001; dms; + +EMS_Page_Contig_Loop: + +;;;; inc dx ;inc loop counter ;an001; dms; +;;;; jmp EMS_Page_Contig_Main_Loop ;continue ;an001; dms; + +EMS_Page_Contig_Init_Loop: + +;;;; sub ax,dx ;adjust pages left cnt ;an001; dms; +;;;; cmp ax,cx ;enough left? ;an001; dms; +;;;; jb EMS_Page_Not_Contig ;no contig memory ;an001; dms; +;;;; mov bx,si ;reinit base val ;an001; dms; +;;;; mov di,si ;reinit ptr val ;an001; dms; +;;;; mov dx,1 ;reinit count val ;an001; dms; +;;;; jmp EMS_Page_Contig_Main_Loop ;continue check ;an001; dms; + +EMS_Page_Not_Contig: + +;;;; stc ;signal not contig ;an001; dms; +;;;; jmp EMS_Page_Contig_Exit ;exit routine ;an001; dms; + +EMS_Page_Found_Contig: + + clc ;signal contig ;an001; dms; +;;;; mov si,bx ;pass ptr to 1st. ;an001; dms; + +EMS_Page_Contig_Exit: + + pop di ;restore regs ;an001; dms; + pop dx ; ;an001; dms; + pop cx ; ;an001; dms; + pop bx ; ;an001; dms; + pop ax ; ;an001; dms; + + ret ;return to caller ;an001; dms; + +EMS_Page_Contig_Chk endp ;end proc ;an001; dms; + + + +;========================================================================= +; EMS_Link_Set - This routine takes the SI returned from +; EMS_Page_Cont_Chk and removes CX pages from +; the linked list for the new handle. +; +; Inputs : SI - Pointer value to the beginning of pages for handle +; CX - Count of pages to be allocated +; +; Outputs : Adjusted unallocated list +; SI - Pointer value to beginning of pages for handle +;========================================================================= + + +EMS_Link_Set proc near ;set contig links ;an001; dms; + + push ax ;save regs ;an001; dms; + push bx ; ;an001; dms; + push cx ; ;an001; dms; + push dx ; ;an001; dms; + push di ; ;an001; dms; + +;;;; cmp si,cs:PAL_Free_Ptr ;at root? ;an001; dms; +;;;; je EMS_Link_Set_Up_Root ;yes - set up links ;an001; dms; + +;;;; mov di,cs:PAL_Free_Ptr ;get first free link ;an001; dms; + +EMS_Link_Set_Up_Search_Loop: + +;;;; shl di,1 ;get index value ;an001; dms; +;;;; cmp si,Page_Alloc_List[di] ;pointers match? ;an001; dms; +;;;; je EMS_Link_Set_Up ;yes - set up links ;an001; dms; +;;;; mov di,Page_Alloc_List[di] ;get next pointer ;an001; dms; +;;;; jmp EMS_Link_Set_Up_Search_Loop ;continue ;an001; dms; + +EMS_Link_Set_Up: + +;;;; mov ax,di ;save index value ;an001; dms; +;;;; mov di,si ;point to first link ;an001; dms; +;;;; mov dx,1 ;init loop counter ;an001; dms; + +EMS_Link_Set_Up_Loop: + +;;;; cmp dx,cx ;at end? ;an001; dms; +;;;; je EMS_Link_Set_Up_Loop_Exit ;yes - exit ;an001; dms; + +;;;; shl di,1 ;index value ;an001; dms; +;;;; mov di,Page_Alloc_List[di] ;next ptr ;an001; dms; +;;;; inc dx ;inc counter ;an001; dms; +;;;; jmp EMS_Link_Set_Up_Loop ;continue ;an001; dms; + +EMS_Link_Set_Up_Loop_Exit: + +;;;; shl di,1 ;index value ;an001; dms; +;;;; mov bx,Page_Alloc_List[di] ;get next link ;an001; dms; +;;;; mov di,ax ;get orig. link ;an001; dms; +;;;; mov Page_Alloc_List[di],bx ;hook up links ;an001; dms; +;;;; jmp EMS_Link_Set_Up_Exit + + +EMS_Link_Set_Up_Root: + + mov di,si ;point to first link ;an001; dms; + xor dx,dx ;init loop counter ;an001; dms; + +EMS_Link_Set_Up_Root_Loop: + + cmp dx,cx ;at end? ;an001; dms; + je EMS_Link_Set_Up_Root_Exit ;yes - exit ;an001; dms; + + shl di,1 ;index value ;an001; dms; + mov di,Page_Alloc_List[di] ;next ptr ;an001; dms; + inc dx ;inc counter ;an001; dms; + jmp EMS_Link_Set_Up_Root_Loop ;continue ;an001; dms; + +EMS_Link_Set_Up_Root_Exit: + + mov cs:PAL_Free_Ptr,di ;new free ptr ;an001; dms; + jmp EMS_Link_Set_Up_Exit ;exit routine ;an001; dms; + +EMS_Link_Set_Up_Exit: + + pop di ;restore regs ;an001; dms; + pop dx ; ;an001; dms; + pop cx ; ;an001; dms; + pop bx ; ;an001; dms; + pop ax ; ;an001; dms; + + ret ;return to caller ;an001; dms; + +EMS_Link_Set endp ; ;an001; dms; + + + + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ ³ +;³ LIM 4.0 functions are kept in a seperate include file, ³ +;³ LIM40.INC ³ +;³ ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +include lim40.inc + +Instance_Table db Instance_Size*Instance_Count dup(Unallocated) ;instance table ;an000; dms; + +RESIDENT: ;last address that must stay resident +PAGE +PAGE + +INCLUDE EMSINIT.INC ;Main file for throwaway + ; initialization code +INCLUDE XMA1DIAG.INC ;XMA 1 diagnostics and routines +INCLUDE PS2_5060.INC ;Diagnostics for PS/2 models 50 @RH2 + ; and 60. Support for XMA/A and @RH2 + ; MXO cards @RH2 +INCLUDE XMA2EMS.CL1 + + +TEMP_STACK DB STACK_SIZE DUP(0) ;RESERVE FOR TEMP STACK +TOP_OF_STACK DB ? ;DURING INITIALIZATION + +CSEG ENDS + END START + + diff --git a/v4.0/src/DEV/XMA2EMS/XMA2EMS.LC b/v4.0/src/DEV/XMA2EMS/XMA2EMS.LC new file mode 100644 index 0000000..bee5cc6 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/XMA2EMS.LC @@ -0,0 +1,11 @@ +XMA2EMS.ASM +XMA2EMSP.INC +DIAGS.ASM +LIM40.INC +LIM40B.INC +PS2_5060.INC +PARMPARS.INC +EMSINIT.INC +XMA1DIAG.INC +GENIOCTL.INC + \ No newline at end of file diff --git a/v4.0/src/DEV/XMA2EMS/XMA2EMS.SKL b/v4.0/src/DEV/XMA2EMS/XMA2EMS.SKL new file mode 100644 index 0000000..d2a8169 --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/XMA2EMS.SKL @@ -0,0 +1,39 @@ +:class 1 + +:use 1 xma2ems CRLF +:use 2 xma2ems Welcome_Msg +:use 3 xma2ems DGS_Start_Msg +:use 4 xma2ems DGS_End_Msg +:use 5 xma2ems Page_Frame_Msg +:use 6 xma2ems PF_Start +:use 7 xma2ems Conv_Pages +:use 8 xma2ems Reserve_Msg +:use 9 xma2ems Res_Pages +:use 10 xma2ems Avail_Msg + +:use 11 xma2ems EMS_Pages +:use 12 xma2ems XMA1_Err_Msg +:use 13 xma2ems Not_Found_Msg +:use 14 xma2ems Parm_Err_Msg +:use 15 xma2ems No_Emul_Msg +:use 16 xma2ems Wrong_Emul_Msg +:use 17 xma2ems Wrong_XMAA_Msg +:use 18 xma2ems Req_EMS_Err_Msg +:use 19 xma2ems Not_Instl_Msg +:use 20 xma2ems Conflict_Msg + +:use 21 xma2ems Confl_Address +:use 22 xma2ems Hole_Msg +:use 23 xma2ems Hole_Address +:use 24 xma2ems Frame_Msg +:use 25 xma2ems Frame_Address +:use 26 xma2ems No_Pages_Msg +:use 27 xma2ems Size_Msg1 +:use 28 xma2ems Mem_OK +:use 29 xma2ems Next_Line +:use 28 common Prompt_Msg +:use 30 xma2ems XMA2EMS_Msg_Term +:use 16 common No_EMS_Memory +:use 30 xma2ems XMA2EMS_Msg_Term1 + +:end diff --git a/v4.0/src/DEV/XMA2EMS/XMA2EMSP.INC b/v4.0/src/DEV/XMA2EMS/XMA2EMSP.INC new file mode 100644 index 0000000..fa4196f --- /dev/null +++ b/v4.0/src/DEV/XMA2EMS/XMA2EMSP.INC @@ -0,0 +1,243 @@ + +INCSW EQU 0 ;INCLUDE PSDATA.INC ;AN000; +FARSW EQU 0 ;CALL THE PARSER BY NEAR CALL +DATESW EQU 1 ; ;SUPPRESS DATE CHECKING ;AN000; +TIMESW EQU 1 ; ;SUPPRESS TIME CHECKING ;AN000; +FILESW EQU 1 ;SUPPORT CHECKING FILE SPECIFICATION ;AN000; +CAPSW EQU 1 ; ;SUPPRESS FILE TABLE CAPS ;AN000; +CMPXSW EQU 1 ; ;SUPPRESS CHECKING COMPLEX LIST +DRVSW EQU 1 ; ;SUPPRESS SUPPORT OF DRIVE ONLY FORMAT +QUSSW EQU 1 ; ;SUPPRESS SUPPORT OF QUOTED STRING FORMAT ;AN000; +NUMSW EQU 1 ; ;SUPPRESS CHECKING NUMERIC VALUE +KEYSW EQU 1 ;SUPPORT KEYWORDS ;AN000; +SWSW EQU 1 ;DO SUPPORT SWITCHES ;AN000; +VAL1SW EQU 1 ;SUPPORT VALUE DEFINITION 1 ;AN000; +VAL2SW EQU 1 ; ;SUPPRESS SUPPORT OF VALUE DEFINITION 2 ;AN000; +VAL3SW EQU 1 ;DO SUPPORT VALUE DEFINITION 3 + +include psdata.inc + +;*********************************************************************** + +;------------------------------------------------------------------- +; +; parser stuff for XMA2EMS.SYS +; +;------------------------------------------------------------------- + +p_block: + dw offset px_block ; address of extended parms block + db 0 ; number of extra stuff + +;$P_PARMS_Blk ; parm block + +;------------------------ +; extended parameter block for APPEND first load + +px_block: + db 1 ; min number positional operands + db 1 ; max number positional operands + dw offset dummy_ctl ; dummy control block + + db 1 ; /X only switch + dw offset X_Switch ; control block for /X switch + + db 7 ; max number of keywords + dw offset frame_ctl ; offset of FRAME= keyword control block + dw offset p0_ctl ; offset of p0 keyword control block + dw offset p1_ctl ; offset of p1 keyword control block + dw offset p2_ctl ; offset of p2 keyword control block + dw offset p3_ctl ; offset of p3 keyword control block + dw offset p254_ctl ; offset of p254 keyword control block + dw offset p255_ctl ; offset of p255 keyword control block + +;------------------------ + +dummy_ctl: + dw 0200h ; + dw 0 ; no caps + dw offset dum_result ; pointer to dummy result block + dw offset dum_values ; pointer to null values block + db 0 ; number of switches and synonyms + +dum_values: + dw 0 ; null value list + +X_Switch: + dw $P_Num_Val ; /X:64 + dw 0002 ; caps + dw offset X_Result ; pointer to result block + dw offset X_Values ; pointer to values block, none + db 1 ; number of switches and synonyms + db "/X",0 ; only /X is valid + +X_Values: + db 1 ; numeric values + db 1 ; 1 ranges + db 1 ; = 1 means good range + dd 4 ; valid values range from 4 (64Kb)... + dd 512 ; 512 (8MB) + +;------------------------ + +frame_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset frame_result ; pointer to result block + dw offset address_values ; pointer to values block + db 1 ; number of synonyms + db "FRAME=",0 + +p0_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p0_result ; pointer to result block + dw offset address_values ; pointer to values block + db 3 ; number of synonyms + db "P0=",0 + db "P00=",0 + db "P000=",0 + +p1_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p1_result ; pointer to result block + dw offset address_values ; pointer to values block + db 3 ; number of synonyms + db "P1=",0 + db "P01=",0 + db "P001=",0 + +p2_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p2_result ; pointer to result block + dw offset address_values ; pointer to values block + db 3 ; number of synonyms + db "P2=",0 + db "P02=",0 + db "P002=",0 + +p3_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p3_result ; pointer to result block + dw offset address_values ; pointer to values block + db 3 ; number of synonyms + db "P3=",0 + db "P03=",0 + db "P003=",0 + +p254_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p254_result ; pointer to result block + dw offset address_values ; pointer to values block + db 1 ; number of synonyms + db "P254=",0 + +p255_ctl: + dw $P_Simple_S ; used for FRAME= and Pxxx= + dw 0 ; cap by char table + dw offset p255_result ; pointer to result block + dw offset address_values ; pointer to values block + db 1 ; number of synonyms + db "P255=",0 + +;------------------------ + +address_values: + db 3 ; strings + db 0 ; zeroes here for ranges + db 0 ; and values + db 24 ; 24 possible strings + db 0A0h + dw offset A0_str + db 0A4h + dw offset A4_str + db 0A8h + dw offset A8_str + db 0ACh + dw offset AC_str + db 0B0h + dw offset B0_str + db 0B4h + dw offset B4_str + db 0B8h + dw offset B8_str + db 0BCh + dw offset BC_str + db 0C0h + dw offset C0_str + db 0C4h + dw offset C4_str + db 0C8h + dw offset C8_str + db 0CCh + dw offset CC_str + db 0D0h + dw offset D0_str + db 0D4h + dw offset D4_str + db 0D8h + dw offset D8_str + db 0DCh + dw offset DC_str + db 0E0h + dw offset E0_str + db 0E4h + dw offset E4_str + db 0E8h + dw offset E8_str + db 0ECh + dw offset EC_str + db 0F0h + dw offset F0_str + db 0F4h + dw offset F4_str + db 0F8h + dw offset F8_str + db 0FCh + dw offset FC_str + + + +A0_str db "A000",0 +A4_str db "A400",0 +A8_str db "A800",0 +AC_str db "AC00",0 +B0_str db "B000",0 +B4_str db "B400",0 +B8_str db "B800",0 +BC_str db "BC00",0 +C0_str db "C000",0 +C4_str db "C400",0 +C8_str db "C800",0 +CC_str db "CC00",0 +D0_str db "D000",0 +D4_str db "D400",0 +D8_str db "D800",0 +DC_str db "DC00",0 +E0_str db "E000",0 +E4_str db "E400",0 +E8_str db "E800",0 +EC_str db "EC00",0 +F0_str db "F000",0 +F4_str db "F400",0 +F8_str db "F800",0 +FC_str db "FC00",0 + +;------------------------ + +dum_result $P_Result_Blk <> ; dummy result block +X_Result $P_Result_Blk <> ; /X result block +frame_result $P_Result_Blk <> ; FRAME= result block +p0_result $P_Result_Blk <> ; p0= result block +p1_result $P_Result_Blk <> ; p1= result block +p2_result $P_Result_Blk <> ; p2= result block +p3_result $P_Result_Blk <> ; p3= result block +p255_result $P_Result_Blk <> ; p254= result block +p254_result $P_Result_Blk <> ; p255= result block + + + \ No newline at end of file -- cgit v1.2.3