;-----------------------------------------------------------------------;
;	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
