TITLE TEST2 ---- 06/10/85 POST TESTS AND INITIALIZATION ROUTINES
.286C
.287
.LIST
CODE	SEGMENT BYTE PUBLIC

	PUBLIC	C21
	PUBLIC	POST2
	PUBLIC	SHUT2
	PUBLIC	SHUT3
	PUBLIC	SHUT4
	PUBLIC	SHUT6
	PUBLIC 	SHUT7

	EXTRN	BLINK_INT:NEAR
	EXTRN	C8042:NEAR
	EXTRN	CMOS_READ:NEAR
	EXTRN	CMOS_WRITE:NEAR
	EXTRN	CONFIG_BAD:NEAR
	EXTRN	D1:NEAR
	EXTRN	D2:NEAR
	EXTRN	DDS:NEAR
	EXTRN	DISK_SETUP:NEAR
	EXTRN	DSKETTE_SETUP:NEAR
	EXTRN	ERR_BEEP:NEAR
	EXTRN	E_MSG:NEAR
	EXTRN	F3D:NEAR
	EXTRN	F3D1:NEAR
	EXTRN	GATE_A20:NEAR
	EXTRN	HD_INT:NEAR
	EXTRN	KBD_RESET:NEAR
	EXTRN	NMI_INT:NEAR
	EXTRN	OBF_42:NEAR
	EXTRN	POST3:NEAR
	EXTRN	PRINT_SCREEN:NEAR
	EXTRN	PROC_SHUTDOWN:NEAR
	EXTRN	PROT_PRT_HEX:NEAR
	EXTRN	PRT_HEX:NEAR
	EXTRN	P_MSG:NEAR
	EXTRN	ROM_CHECK:NEAR
	EXTRN	ROM_CHECKSUM:NEAR
	EXTRN	SEEK:NEAR
	EXTRN	SET_TOD:NEAR
	EXTRN	SLAVE_VECTOR_TABLE:NEAR
	EXTRN	SND_DATA:NEAR
	EXTRN	START_1:NEAR
	EXTRN	STGTST_CNT:NEAR
	EXTRN	SYSINIT1:NEAR
	EXTRN	VECTOR_TABLE:NEAR
	EXTRN	WAITF:NEAR
	EXTRN	XPC_BYTE:NEAR

	EXTRN	E101:NEAR	; 101 ERROR CODE - INTERRUPT FAILURE
	EXTRN	E102:NEAR	; 102 ERROR CODE - TIMER FAILURE
	EXTRN	E103:NEAR	; 103 ERROR CODE - TIMER INTERRUPT
	EXTRN	E104:NEAR	; 104 ERROR CODE - PROTECTED MODE ERROR
	EXTRN	E105:NEAR	; 105 ERROR CODE - 8042 COMMAND FAILURE
	EXTRN	E106:NEAR	; 106 ERROR CODE - CONVERTING LOGIC
	EXTRN	E107:NEAR	; 107 ERROR CODE - NMI ERROR
	EXTRN	E108:NEAR	; 108 ERROR CODE - TIMER BUS ERROR
	EXTRN	E109:NEAR	; 109 ERROR CODE - MEMORY SELECT ERROR
	EXTRN	E161:NEAR	; 161 ERROR CODE - BAD BATTERY
	EXTRN	E162:NEAR	; 162 ERROR CODE - CMOS CHECKSUM/CONFIG
	EXTRN	E163:NEAR	; 163 ERROR CODE - BAD REAL TIME CLOCK
	EXTRN	E164:NEAR	; 164 ERROR CODE - MEMORY SIZE WRONG
	EXTRN	E201:NEAR	; 201 ERROR CODE - MEMORY DATA ERROR
	EXTRN	E202:NEAR	; 202 ERROR CODE - MEMORY ADDRESS ERROR
	EXTRN	E203:NEAR	; 203 ERROR CODE - SEGMENT ADDRESS ERROR
	EXTRN	E301:NEAR	; 301 ERROR CODE - KEYBOARD ERROR
	EXTRN	E302:NEAR	; 302 ERROR CODE - LOCK IS ON
	EXTRN	E303:NEAR	; 303 ERROR CODE - KEYBOARD/PLANAR ERROR
	EXTRN	E304:NEAR	; 304 ERROR CODE - KEYBOARD/PLANAR ERROR
	EXTRN	E401:NEAR	; 401 ERROR CODE - MONOCHROME ADAPTER
	EXTRN	E501:NEAR	; 501 ERROR CODE - COLOR ADAPTER
	EXTRN	E601:NEAR	; 601 ERROR CODE - DISKETTE ADAPTER

;----------------------------------------------------------
; TEST.17				    :
;       8259 INTERRUPT CONTROLLER TEST			    :
; DESCRIPTION				    :
;       READ/WRITE THE INTERRUPT MASK REGISTER (IMR)	    :
;       WITH ALL ONES AND ZEROES, ENABLE SYSTEM		    :
;       INTERRUPTS, MASK DEVICE INTERRUPTS OFF.  CHECK    :
;       FOR HOT INTERRUPTS (UNEXPECTED).			    :
;----------------------------------------------------------

	ASSUME	CS:CODE,DS:DATA

POST2	PROC	NEAR

C21:	MOV	AL,10	; LINE FEED ON DISPLAY
	CALL	PRT_HEX
	CALL	DDS	; SET DATA SEGMENT

;-----	CLEAR ERROR FLAG REGISTER (BP) <=> 0 FLAGS ERROR

	SUB	BP,BP	; CLEAR (BP) REGISTER AS ERROR FLAG REG

;------	TEST THE INTERRUPT MASK REGISTER REGISTERS

C21A:	CLI		; TURN OFF INTERRUPTS
	MOV	AL,0	; SET INTERRUPT MASK REGISTER TO ZERO
	OUT	INTA01,AL
	OUT	INTB01,AL	; SEND TO 2ND INTERRUPT CONTROLLER ALSO
	JMP	$+2
	IN	AL,INTA01	; READ INTERRUPT MASK REGISTER
	MOV	AH,AL	; SAVE RESULTS
	IN	AL,INTB01	; READ 2ND INTERRUPT MASK REGISTER

	OR	AH,AL	; BOTH IMR = 0?
	JNZ	D6	; GO TO ERR ROUTINE IF NOT 0

	MOV	AL,25H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  25 <><>

	MOV	AL,0FFH	; DISABLE DEVICE INTERRUPTS
	OUT	INTA01,AL	; WRITE TO INTERRUPT MASK REGISTER
	OUT	INTB01,AL	; WRITE TO 2ND INTERRUPT MASK REGISTER
	JMP	$+2	; I/O DELAY
	IN	AL,INTA01	; READ INTERRUPT MASK REGISTER
	MOV	AH,AL	; SAVE RESULTS
	IN	AL,INTB01	; READ 2ND INTERRUPT MASK REGISTER
	ADD	AX,I	; ALL IMR BITS ON?
	JNZ	D6	; NO - GO TO ERR ROUTINE

;-----	CHECK FOR HOT INTERRUPTS

;-----	INTERRUPTS ARE MASKED OFF, CHECK THAT NO INTERRUPTS OCCUR.

	MOV	@INTR_FLAG,AL	; CLEAR INTERRUPT FLAG

	MOV	AL,26H	; 	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	; 	  <><> CHECKPOINT  26 <><>

	STI		; ENABLE EXTERNAL INTERRUPTS
	MOV	CX,6628	; WAIT 100 MILLISECONDS FOR ANY
	CALL	WAITF	;  INTERRUPTS THAT OCCUR
	CMP	@INTR_FLAG,00H	; DID ANY INTERRUPTS OCCUR?
	JZ	D7	; NO - GO TO NEXT TEST

D6:	MOV	@MFG_ERR_FLAG,05H	;	  <><><><><><><><><><><><>
			;	  <><> CHECKPOINT   5 <><>
	MOV	SI,OFFSET E101	; DISPLAY 101 ERROR
D6A:	CALL	E_MSG
	CLI
	HLT		; HALT THE SYSTEM

;-----	CHECK THE CONVERTING LOGIC

D7:	MOV	AL,27H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  27 <><>

	MOV	AX,0AA55H
	OUT	MFG_PORT+2,AX	; WRITE A WORD
	IN	AL,MFG_PORT+2	;  GET THE FIRST BYTE
	XCHG	AL,AH	;  SAVE IT
	IN	AL,MFG_PORT+3	;  GET THE SECOND BYTE
	CMP	AX,55AAH	; IS IT OK?
	JZ	D7_A	; GO IF YES

	MOV	SI,OFFSET E106	; DISPLAY 106 ERROR
	JMP	D6A

;-----	CHECK FOR HOT NMI INTERRUPTS WITHOUT I/O-MEMORY PARITY ENABLED

D7_A:
	MOV	AL,CMOS_REG_D	; TURN ON NMI
	OUT	CMOS_PORT,AL	; ADDRESS DEFAULT READ ONLY REGISTER
	MOV	CX,7	; DELAY COUNT FOR 100 MICROSECONDS
	CALL	WAITF	; WAIT FOR HOT NMI TO PROCESS
	MOV	AL,CMOS_REG_D+NMI	; TURN NMI ENABLE BACK OFF
	OUT	CMOS_PORT,AL
	CMP	@INTR_FLAG,00H	; DID ANY INTERRUPTS OCCUR?
	JZ	D7_C	; CONTINUE IF NOT

	MOV	AL,28H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	; 	  <><> CHECKPOINT  28 <><>

	MOV	SI,OFFSET E107	; DISPLAY 107 ERROR
	JMP	D6A

;-----	TEST THE DATA BUS TO TIMER 2

D7_C:	MOV	AL,29H	;	  <><><><><><><><><><><><>
	OUT	MFG PORT,AL	;	  <><> CHECKPOINT  29 <><>
	IN	AL,PORT_B	; GET CURRENT SETTING OF PORT
	MOV	AH,AL	; SAVE THAT SETTING
	AND	AL,0FCH	; INSURE SPEAKER OFF
	OUT	PORT_B,AL

	MOV	AL,10110000B	; SELECT TIM 2,LSB,MSB,BINARY,MODE 0
	OUT	TIMER+3,AL	; WRITE THE TIMER MODE REGISTER
	JMP	$+2	; I/O DELAY
	MOV	AX,0AA55H	; WRITE AN AA55
	OUT	TIMER+2,AL	; WRITE TIMER 2 COUNT - LSB
	JMP	$+2	; I/O DELAY
	MOV	AL,AH
	OUT	TIMER+2,AL	; WRITE TIMER 2 COUNT - MSB
	JMP	$+2	; I/O DELAY
	IN	AL,TIMER+2	; GET THE LSB
	XCHG	AH,AL	; SAVE IT
	JMP	$+2	; I/O DELAY
	IN	AL,TIMER+2	; GET THE MSB
	CMP	AX,055AAH	; BUS OK?
	JZ	D7_D	; GO IF OK

	MOV	SI,OFFSET E108	; DISPLAY 108 ERROR
	JMP	D6A

;--------------------------------------------------------
; TEST.18				  :
;       8254 TIMER CHECKOUT			  :
; DESCRIPTION				  :
;       VERIFY THAT THE SYSTEM TIMER (0) DOESN'T COUNT  :
;       TOO FAST OR TOO SLOW.			  :
;--------------------------------------------------------

D7_D:	MOV	AL,2AH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  2A <><>
	CLI
	MOV	AL,0FEH	; MASK ALL INTERRUPTS EXCEPT LEVEL 0
	OUT	INTA01,AL	; WRITE THE 8259 IMR
	MOV	AL,00010000B	; SELECT TIM 0, LSB, MODE 0, BINARY
	OUT	TIMER+3,AL	; WRITE TIMER CONTROL MODE REGISTER
	MOV	CX,2CH	; SET PROGRAM LOOP COUNT

	JMP	$+2	; I/O DELAY

	MOV	AL,CL	; SET TIMER 0 COUNT REGISTER
	OUT	TIMER+0,AL	; WRITE TIMER 0 COUNT REGISTER
	STI
D8:	TEST	9INTR_FLAG,01H	; DID TIMER 0 INTERRUPT OCCUR?

	JNZ	D9	; CHECK TIMER OPERATION FOR SLOW TIME
	LOOP	D8	; WAIT FOR INTERRUPT FOR SPECIFIED TIME

	MOV	@MFG_ERR_FLAG,02H	;	  <><><><><><><><><><><><><><><>
			;	  <><> TIMER CHECKPOINT (2) <><>


D8_A:	MOV	SI,OFFSET E102	; DISPLAY 102 ERROR
	JMP	D6A	; TIMER 0 INTERRUPT DID NOT OCCUR= ERROR


D9:	MOV	AL,28H	;	  <><><><><><><><><><><><> 
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  2B <><>

	CLI
	MOV	CL,12	; SET PROGRAM LOOP COUNT
	MOV	AL,0FFH	; WRITE TIMER 0 COUNT REGISTER
	OUT	TIMER+0,AL
	MOV	@INTR_FLAG,0	; RESET INTERRUPT RECEIVED FLAG
	MOV	AL,0FEH	; RE-ENABLE TIMER 0 INTERRUPTS
	OUT	INTA01,AL
	STI
D10:	TEST	@INTR_FLAG,01H	; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D8_A	; YES - TIMER COUNTING TOO FAST, ERROR
	LOOP	D10	; WAIT FOR INTERRUPT FOR SPECIFIED TIME

;-----	WAIT FOR INTERRUPT

	SUB	CX,CX

	MOV	AL,2CH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  2C <><>
D110:
	TEST	@INTR_FLAG,01H	; DID TIMER 0 INTERRUPT OCCUR?
	JNZ	D12	; GO IF YES
	LOOP	D110	; TRY AGAIN

	MOV	SI,OFFSET E103	; DISPLAY 103 ERROR
	JMP	D6A	; ERROR IF NOT

;-----	SETUP TIMER 0 TO MODE 3

D12:	CLI
	MOV	AL,0FFH	; DISABLE ALL DEVICE INTERRUPTS
	OUT	INTA01,AL
	MOV	AL,36H	; SELECT TIMER 0,LSB,MSB,MODE 3
	OUT	TIMER+3,AL	; WRITE TIMER MODE REGISTER
	JMP	$+2	; I/O DELAY
	MOV	AL,0
	OUT	TIMER+0,AL	; WRITE LSB TO TIMER 0 REGISTER
	JMP	$+2	; I/O DELAY
	OUT	TIMER+0,AL	; WRITE MSB TO TIMER 0 REGISTER

;-----	CHECK 8042 FOR LAST COMMAND ACCEPTED

	SUB	CX,CX	; SET WAIT TIME
	MOV	AL,2DH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  2D <><>
D13:	IN	AL,STATUS_PORT	; GET THE 8042 STATUS
	TEST	AL,INPT_BUF_FULL	; HAS THE LAST COMMAND BEEN ACCEPTED?
	JZ	E19	; GO IF YES
	LOOP	D13	; TRY AGAIN

;-----	ERROR EXIT (MESSAGE 105)

	MOV	SI,OFFSET E105	; PRINT 105 ERROR
	JMP	D6A	; GO ERROR HALT
;-------------------------------------------------------------------------
; TEST.19							 :
;       ADDITIONAL READ/WRITE STORAGE TEST					 :
;       ++++ MUST RUN IN PROTECTED MODE ++++					 :
; DESCRIPTION							 :
;       WRITE/READ DATA PATTERNS TO ANY READ/WRITE STORAGE AFTER THE     :
;       FIRST 64K.  STORAGE ADDRESSABILITY IS CHECKED.			 :
;-------------------------------------------------------------------------

	ASSUME	DS:DATA
E19:
	CALL	DDS	; SET DATA SEGMENT
	MOV	AL,2FH	; 	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  2F <><>

	CMP	@RESET_FLAG,1234H	; WARM START?
	JNE	E19A	; GO IF NOT
	JMP	SHUT2	; GO TO NEXT TEST IF WARM START
	
;-----	SET SHUTDOWN RETURN 2
	
E19A:	MOV	AL,30H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  30 <><>

	MOV	AX,2*H+CMOS_SHUT_DOWN+NMI		; ADDRESS FOR SHUTDOWN BYTE
	CALL	CMOS_WRITE	; SECOND ENTRY IN SHUTDOWN TABLE
	
;----- 	ENABLE PROTECTED MODE
	MOV	SP,POST_SS	; SET STACK FOR SYSINIT1
	MOV	SS,SP
	MOV	SP,POST_SP

	CALL	SYSINIT1	; GO ENABLE PROTECTED MODE

	MOV	AL,31H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  31 <><>
	
;-----	SET TEMPORARY STACK
	PUSH	BYTE PTR GDT_PTR
	POP	ES
	MOV	ES:SS_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(SS_TEMP.BASE_HI_BYTE),0
	MOV	SI,SS_TEMP
	MOV	SS,SI
	MOV	SP,MAX_SEG_LEN-2
	
;----- 	DATA SEGMENT TO SYSTEM DATA AREA
	
	PUSH	BYTE PTR RSDA_PTR	; POINT TO DATA AREA
	POP	DS

	MOV	AL,PARITY_CHECK	; SET CHECK PARITY
	OUT	DMA_PAGE+6,AL	; SAVE WHICH CHECK TO USE

;-----	PRINT 64 K BYTES OK
	
	MOV	AX,64	; STARTING AMOUNT OF MEMORY OK
	CALL	PRT_OK	; POST 64K OK MESSAGE
	
;-----	GET THE MEMORY SIZE DETERMINED (PREPARE BX AND DX FOR BAD CMOS)
	
	MOV	AX,(CMOS_U_M_S_LO+NMI)*H+CMOS_U_M_S_HI+NMI
	CALL	CMOS_READ	; HIGH BYTE
	XCHG	AH,AL	; SAVE HIGH BYTE
	CALL	CMOS_READ	; LOW BYTE
	MOV	BX,@MEMORY_SIZE	; LOAD THE BASE MEMORY SIZE
	MOV	DX,BX	; SAVE BASE MEMORY SIZE
	ADD	BX,AX	; SET TOTAL MEMORY SIZE
	
;-----	IS CMOS GOOD?
	
	MOV	AL,CMOS_DIAG+NMI	; DETERMINE THE CONDITION OF CMOS
	CALL	CMOS_READ	; GET THE CMOS STATUS

	TEST	AL,BAD_BAT+BAD_CKSUM	; CMOS OK?
	JZ	E20B0	; GO IF YES
	JMP	SHORT E20C	; DEFAULT IF NOT
	
;-----	GET THE BASE 0->640K MEMORY SIZE FROM CONFIGURATION IN CMOS 
E20B0:
	MOV	AX,(CMOS_B_M_S_LO+NMI)*H-CMOS_B_M_S_HI+NMI
	CALL	CMOS_READ	; HIGH BYTE
	AND	AL,03FH	; MASK OFF THE MANUFACTURING TEST SITS
	XCHG	AH,AL	; SAVE HIGH BYTE
	CALL	CMOS_READ	; LOW BYTE OF BASE MEMORY SIZE
	CMP	DX,AX	; IS MEMORY SIZE GREATER THAN CONFIG7
	JZ	E20B1	; GO IF EQUAL
	
;-----	SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIGURATION
	
	PUSH	AX	; SAVE AX
	MOV	AX,X*(CMOS_DIAG+NMI)	; ADDRESS THE STATUS BYTE
	CALL	CMOS_READ	; GET THE STATUS
	OR	AL,W_MEM_SIZE	; SET CMOS FLAG
	XCHG	AL,AH	; SAVE AL AND GET ADDRESS
	CALL	CMOS_WRITE	; WRITE UPDATED STATUS
	POP	AX	; RESTORE AX
	CMP	DX,AX	; IS MEMORY SIZE GREATER THAN CONFIG ?
	JA	E20C	; DEFAULT TO MEMORY SIZE DETERMINED ?
E20B1:
	MOV	BX,AX	; SET BASE MEMORY SIZE IN TOTAL REGISTER
	MOV	DX,AX	; SAVE IN BASE SIZE REGISTER
	
;-----	CHECK MEMORY SIZE ABOVE 640K FROM CONFIGURATION
	
	MOV	AX,(CMOS_E_M_S_LO+NMI)*H+(CMOS_E_M_S_HI+NMI)
	CALL	CMOS_READ	; HIGH BYTE
	XCHG	AH,AL	; SAVE HIGH BYTE
	CALL	CMOS_READ	; LOW BYTE
	MOV	CX,AX	; SAVE THE ABOVE 640K MEMORY SIZE

;-----	ABOVE 640K SIZE FROM MEMORY SIZE DETERMINE
;-----	CX=CONFIG  AX=MEMORY SIZE DETERMINE
	MOV	AX,(CMOS_U_M_S_LO+NMI)*H+(CMOS_U_M_S_HI+NMI)
	CALL	CMOS_READ	; HIGH BYTE
	XCHG	AH,AL	; SAVE HIGH BYTE
	CALL	CMOS_READ	; LOW BYTE

;------	WHICH IS GREATER - AX = MEMORY SIZE DETERMINE
;------	CX = CONFIGURATION (ABOVE 640) BX = SIZE (BELOW 640)
	
	CMP	CX,AX	; IS CONFIGURATION EQUAL TO DETERMINED?
	JZ	SET_MEM1	; GO IF EQUAL
	
;-----	SET MEMORY SIZE DETERMINE NOT EQUAL TO CONFIGURATION
	
	PUSH	AX	; SAVE AX
	MOV	AX,X*(CMOS_DIAG+NMI)	; ADDRESS THE STATUS BYTE
	CALL	CMOS_READ	; GET THE STATUS
	OR	AL,W_MEM_SIZE	; SET CMOS FLAG
	XCHG	AL,AH	; SAVE AL
	CALL	CMOS_WRITE	; UPDATE STATUS BYTE
	POP	AX	; RESTORE AX
	
SET_MEM1:
	CMP	CX,AX	; IS CONFIG GREATER THAN DETERMINED?
	JA	SET_MEW	; GO IF YES
	MOV	CX,AX	; USE MEMORY SIZE DETERMINE IF NOT
SET_MEM:
	ADD	BX,CX	; SET TOTAL MEMORY SIZE
E20C:
	CMP	DX,513	; CHECK IF BASE MEMORY LESS 512K
	JB	NO_640	; GO IF YES

	MOV	AX,X*(CMOS_INFO128+NMI)	; SET 640K BASE MEMORY BIT
	CALL	CMOS_READ	; GET THE CURRENT STATUS 
	OR	AL,M640K	; TURN ON 640K BIT IF NOT ALREADY ON
	XCHG	AL,AH	; SAVE THE CURRENT DIAGNOSTIC STATUS
	CALL	CMOS_WRITE	; RESTORE THE STATUS
NO_640:
	MOVE	WORD PTR @KB_FLAG,BX	; SAVE TOTAL SIZE FOR LATER TESTING
	SHR	BX,6	; DIVIDE BY 64
	DEC	BX	; 1ST 64K ALREADY DONE
	SHR	DX,6	; DIVIDE BY 64 FOR BASE

;-----	SAVE COUNTS IN STACK FOR BOTH MEMORY AND ADDRESSING TESTS
	
	PUSH	DX	; SAVE BASE MEMORY SIZE COUNT
	PUSH	BYTE PTR 64	; SAVE STARTING AMOUNT OF MEMORY OK
	PUSH	BX	; SAVE COUNT OF 64K BLOCKS TO BE TESTED

	PUSH	DX	; SAVE BASE MEMORY SIZE COUNT
	PUSH	BYTE PTR 64	; SAVE STARTING AMOUNT OF MEMORY OK
	PUSH	BX	; SAVE COUNT OF 64K BLOCKS TO BE TESTED
	
;-----	MODIFY DESCRIPTOR TABLES
	
	PUSH	BYTE PTR GDT_PTR	; MODIFY THE DESCRIPTOR TABLE
	POP 	ES
	
;-----	SET TEMPORARY ES DESCRIPTOR 64K SEGMENT LIMIT STARTING AT 000000
	
	MOV	ES:ES_TEMP.SEG_LIMIT,MAX_SEG_LEN
	MOV	ES:ES_TEMP,BASE_LO_WORD,0
	MOV	BYTE PTR ES:(ES_TEMP.BASE_HI_BYTE),0		; FIRST 65K
	MOV	BYTE PTR ES:(ES_TEMP,DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;-----	SET TEMPORARY DS DESCRIPTOR 64K SEGMENT LIMIT AT FIRST 65K BLOCK

	MOV	ES:DS_TEMP.SEG_LIMIT,MAX_SEG_LEN
	MOV	ES:DS_TEMP.BASE_LO_WORD,0
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV	BYTE PTR ES:(DS_TEMP,DATA_ACC_RIGHTS),CPL0_DATA_ACCESS

;-----	TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER FOR SECOND 65K BLOCK
	
	SUB	AL,AL	; INITIALIZE VALUES TO 010000
	OUT	DMA_PAGE+4,AL	; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL	; LOW BYTE OF LOW WORD OF SEGMENT
	INC	AL	; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL	; HIGH BYTE OF SEGMENT
	
;-----	MEMORY TEST LOOP - POINT TO NEXT BLOCK OF 32K WORDS (64K)
	
E21:			; 	MEMORY TEST LOOP
	PUSH	BYTE PTR GDT_PTR	; POINT TO START OF DESCRIPTOR TABLE
	POP	DS
	INC	BYTE PTR DS:(DS_TEMP,BASE_HI_BYTE)	; POINT TO NEXT BLOCK
	INC	BYTE PTR DS:(ES_TEMP,BASE_HI_BYTE)
	
;-----	CHECK FOR END OF 256K PLANAR MEMORY
	
	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),04H
	JB	E21_0 	; GO IF STILL FIRST 256K OF BASE MEMORY'
	
	MOV	AL,PARITY_CHECK+IO_CHECK	; CHECK FOR ANY TYPE OF PARITY 	ERROR
	OUT	DMA_PAGE+6,AL 	; AFTER FIRST 256K
	
;----- 	CHECK END OF FIRST 640K OR ABOVE (END OF MAXIMUM BASE MEMORY)
E21_0:
	CMP	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),0AH
	JA	NEXT	; CONTINUE IF ABOVE 1 MEG

;-----	CHECK FOR END OF BASE MEMORY TO BE TESTED
	
	POP	CX	; GET COUNT
	POP	BX	; GET COUNT TESTED
	POP	AX	; RECOVER COUNT OF BASE MEMORY BLOCKS
	PUSH	AX	; SAVE BASE COUNT
	PUSH	BX	; SAVE TESTED COUNT
	PUSH	CX	; SAVE TOTAL COUNT
	CMP	BYTE PTR DS:(DS_TEMP,BASE_HI_BYTE),AL		; MAX BASE COUNT
	JS	NEXT	; CONTINUE IF NOT DONE WITH BASE MEMORY
	
;----- 	DO ADDITIONAL STORAGE ABOVE 1 MEG
	
	MOV	BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE),10H
	MOV	BYTE PTR DS:(ES_TEMP.BASE_HI_BYTE),10H

;----- 	SAVE BASE_HI_BYTE IN DMA PAGE REGISTERS 3

NEXT:	MOV	AL,BYTE PTR DS:(DS_TEMP.BASE_HI_BYTE)
	OUT	DMA_PAGE+3,AL	; SAVE THE HIGH BYTE OF SEGMENT
			;  FOR POSSIBLE ERROR

;-----	CHECK FOR TOP OF MEMORY (FE0000) 16 MEG

	CMP	BYTE PTR DS:(ES_TEMP,BASE_HI_BYTE),0FEH 	; TOP OF MEMORY?
	JE	KB_LOOP3				; EXIT NEXT TEST IF DONE
	
;-----	SET ES AND DS REGISTERS TO MEMORY BLOCK
	
	PUSH	BYTE PTR DS_TEMP
	POP	DS
	PUSH	BYTE PTR ES_TEMP
	POP	ES
	
	MOV	AL,31H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  31 <><>

	MOV	CX,8000H	; SET COUNT FOR 32K WORDS
	CALL	STGTST_CNT
	JZ	N1	; SKIP IF OK
	JMP	E21A	; GO PRINT ERROR

N1:	
	POP	CX	; POP CX TO GET AX
	POP	AX	; RECOVER TESTED MEMORY

;-----	WRITE THE CURRENT SIZE FOR (ADDRESS LINES 23-17 TEST) USED LATER

	SUB	DI,DI	; POINT TO BEGINNING OR A BLOCK
	STOSW		; WRITE THE CURRENT SIZE
			;  AT THE STARTING ADDRESS
	ADD	AX,64	; ADVANCE COUNT TO NEXT BLOCK
	PUSH	AX	; SAVE TESTED MEMORY
	PUSH	CX	; SAVE LOOP COUNT
	
	CALL	PRT_OK	; DISPLAY "0XXXX OK" MESSAGE
	
	POP	CX	; RECOVER 64K BLOCK COUNT
	DEC	CX	; DECREMENT BLOCK COUNT FOR LOOP
	JCXZ	KB-LOOP3	; CONTINUE TO NEXT TEST IF DONE

	PUSH	CX	; SAVE LOOP COUNT
	JMP	E21	; LOOP TILL ALL MEMORY CHECKED
	
KB_LOOP3:		; 	  END MAIN TEST LOOP
	POP	AX	; CLEAR MAXIMUM BLOCK COUNT
	POP	AX	; CLEAR BASE SIZE COUNT FROM STACK			
			; ADDRESS TEST VALUES ARE IN STACK
;-----	ADDRESS LINE 16-23 TEST 
			;	  LET FIRST PASS BE SEEN
	MOV	CX,16571	; COUNT FOR 250 MS FIXED TIME DELAY
	CALL	WAITF	; ALLOW SIX DISPLAY REFRESH CYCLES
	
;-----	INITIALIZE DS DESCRIPTOR
	
	PUSH	BYTE PTR GDT_PRT
	POP	ES
	MOV	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0
	MOV 	ES:DS_TEMP.BASE_LO_WORD,0
	
;-----	TEMPORARY SEGMENT SAVE IN DMA PAGE REGISTER
	
	SUB	AL,AL
	OUT	DMA_PAGE+4,AL	; HIGH BYTE OF LOW WORD OF SEGMENT
	OUT	DMA_PAGE+5,AL	; LOW BYTE OF LOW WORD OF SEGMENT
	MOV	AL,01H	; SET HIGH BYTE OF SEGMENT WORD
	OUT	DMA_PAGE+3,AL	; HIGH BYTE OF SEGMENT
	
;-----	POINT TO NEXT BLOCK OF 64K
	
E21_A:	MOV	AL,33H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  33 <><>
	ADD	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),01
	
;-----	CHECK FOR END OF BASE MEMORY TO BE TESTED
	
	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),0AH
	JA	NEXT_A	; CONTINUE IF ABOVE 1 MEG

	POP	CX	; GET COUNT
	POP	BX	; GET COUNT TESTED
	POP	AX	; RECOVER COUNT OF BASE MEMORY BLOCKS
	PUSH	AX	; SAVE BASE COUNT
	PUSH	BX	; SAVE TESTED COUNT
	PUSH	CX	; SAVE TOTAL COUNT
	CMP	BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE),AL		; MAX BASE COUNT
	JS	NEXT_A	; CONTINUE IF NOT DONE WITH BASE MEMORY
	
;-----	DO ADDITIONAL STORAGE ABOVE 1 MEG
	
NEXT_A2:
	MOV	BYTE PTR ES:(DS_TEMP,BASE_HI_BYTEJ,10H
NEXT_A:	
	MOV	AL,BYTE PTR ES:(DS_TEMP.BASE_HI_BYTE)
	
;-----	DMA PAGE REGISTERS 3
			; SAVE THE HIGH BYTE OF SEGMENT
	OUT	DMA_PAGE+3,AL	;  FOR POSSIBLE ERROR
	
;-----	CHECK FOR TOP OF MEMORY (FE0000) 16 MEG
	
	CMP	AL,0FEH	; TOP OF MEMORY7
	JZ	KB_LOOP_3	; GO NEXT TEST IF IT IS
	
;-----	SET DS REGISTER
	
	PUSH	BYTE PTR DS_TEMP
	POP	DS
	SUB	DI,DI	; POINT TO START OF BLOCK
	MOV	DX,DS:[DI]	; GET THE VALUE OF THIS BLOCK
	MOV	SI,DI	; SET SI FOR POSSIBLE ERROR
	SUB	AX,AX	; CLEAR MEMORY LOCATION
	MOV 	[DI],AX
	
;-----	ALLOW DISPLAY TIME TO DISPLAY MESSAGE AND REFRESH TO RUN
	
	MOV	CX,6761	; COUNT FOR 102 MS FIXED TIME DELAY
	CALL	WAITF	; ALLOW FIVE DISPLAY REFRESH CYCLES
	POP	CX	; GET THE LOOP COUNT
	POP	AX	; RECOVER TESTED MEMORY
	PUSH	AX	; SAVE TESTED MEMORY
	PUSH	CX	; SAVE LOOP COUNT
	CMP	AX,DX	; DOES THE BLOCK ID MATCH
	MOV	AX,DX	; GET THE BLOCK ID FOR POSSIBLE ERROR
	JNZ	E21A	; GO PRINT ERROR
	
;-----	CHECK FOR CHECK PARITY
	
	IN	AL,PORT_B	; CHECK FOR I/O OR PARITY CHECK
	AND	AL,PARITY_ERR	; STRIP UNWANTED BITS
	JNZ	E21A	; EXIT IF PARITY ERROR

	POP	CX	; POP CX TO GET AX
	POP	AX	; RECOVER TESTED MEMORY
	ADD	AX,64	; 64K INCREMENTS
	PUSH	AX	; SAVE TESTED MEMORY
	PUSH	CX	; SAVE LOOP COUNT
	CALL	PRT_OK	; DISPLAY OK MESSAGE
	POP	CX	; RECOVER 64K BLOCK COUNT
	DEC	CX	; LOOP TILL ALL MEMORY CHECKED
	JCXZ	KB_LOOP_3	; CONTINUE

	PUSH	CX	; SAVE LOOP COUNT
	JMP	E21_A	; CONTINUE TILL DONE

;-----	BACK TO REAL MODE - MEMORY TESTS DONE

KB_LOOP_3:
	MOV	AL,34H	;	  <><><><><><><><><><><><>
	OUT 	MFG_PORT,AL	;	  <><> CHECKPOINT  34 <><>
			; BACK TO REAL MODE
	JMP	PROC_SHUTDOWN	; NEXT TEST VIA JUMP TABLE (SHUT2)
	

;-----	PRINT FAILING ADDRESS AND XOR'ED PATTERN IF DATA COMPARE ERROR
;-----	USE DMA PAGE REGISTERS AS TEMPORARY SAVE AREA FOR ERROR
;	SET SHUTDOWN 3
	
E21A:	OUT	DMA_PAGE+1,AL	; SAVE FAILING SIT PATTERN (LOW BYTE)
	MOV	AL,AH	; SAVE HIGH BYTE
	OUT	DMA_PAGE+2,AL
	MOV	AX,AI	; GET THE FAILING OFFSET
	OUT	DMA_PAGE+S,AL
	XCHG	AH,AL
	OUT	DMA_PAGE+4,AL
	
;-----	CLEAR I/O CHANNEL CHECK OR R/W PARITY CHECK
	
	SUB	S1,SI	; WRITE TO FAILING BLOCK
	STOSW
	IN	AL,PORT_B	; GET PARITY CHECK LATCHES
	OUT	DMA_PAGE+7,AL	; SAVE FOR ERROR HANDLER
	OR	AL,RAM_PAR_OFF	; TOGGLE I/O-PARITY CHECK ENABLE
	OUT	PORT_B,AL	;  TO RESET CHECKS
	AND	AL,RAM_PAR_ON
	OUT	PORT_B,AL
	
;-----	GET THE LAST OF GOOD MEMORY
	
	POP	AX	; CLEAR BLOCK COUNT
	POP	AX	; GET THE LAST OF GOOD MEMORY
	POP	BX	; GET BASE MEMORY COUNTER
	SHL	BX,6	; CONVERT TO MEMORY SIZE COUNTS
	SUB	AX,BX	; COMPARE LAST GOOD MEMORY WITH BASE
	JAE	E211	; IF ABOVE OR EQUAL, USE REMAINDER IN
			;  CMOS_U_M_S_(H/L)
;-----ELSE SET BASE MEMORY SIZE
	
	PUSH	BYTE PTR RSDA_PTR	; SET THE DATA SEGMENT
	POP	DS	; IN PROTECTED MODE

	ADD	AX,BX	; CONVERT BACK TO LAST WORKING MEMORY
	MOV	@MEMORY_SIZE,AX	; TO INDICATE HOW MUCH MEMORY WORKING
	
;-----	RESET 512K --> 640K OPTION IF SET
	
	MOV	AX,X*(CMOS_INFO128+NMI)	; ADDRESS OPTIONS INFORMATION BYTE
	CALL	CMOS_READ	; READ THE MEMORY INFORMATION FLAG
	AND	AL,NOT M640K	; SET 640K OPTION OFF
	XCHG	AL,AH	; MOVE TO WORK REGISTER
	CALL	CMOS_WRITE	; UPDATE STATUS IF IT WAS ON
	XOR	AX,AX	; CLEAR VALUE FOR EXTENSION MEMORY
E211:
	MOV	CX,AX	; SAVE ADJUSTED MEMORY SIZE
	MOV	AL,CMOS_U_M_S_HI+NMI
	CALL	CMOS_WRITE	; SAVE THE HIGH BYTE MEMORY SIZE
	MOV	AH,CL	; GET THE LOW BYTE
	MOV	AL,CMOS_U_M_S_LO+NMI	; DO THE LOW BYTE
	CALL	CMOS_WRITE	; WRITE IT
	
;-----	SET SHUTDOWN 3
	
	MOV	AX,3*H+CMOS_SHUT_DOWN+NMI		; ADDRESS FOR SHUTDOWN RETURN
	CALL	CMOS_WRITE		; SET RETURN 3
	
;-----	SHUTDOWN

	JMP	PROC_SHUTDOWN
	
	
;---------------------------------------------------------------------
; MEMORY ERROR REPORTING         (R/W/ MEMORY OR PARITY ERRORS)      :
;							   :
;DESCRIPTION FOR ERRORS 201 (CMP ERROR OR PARITY)			   :
;                    OR 202 (ADDRESS LINE 0-15 ERROR)			   :
;							   :
;      "AABBCC DDEE 201" (OR 202)					   :
;                        AA=HIGH BYTE OF 24 BIT ADDRESS		   :
;                        BB=MIDDLE BYTE OF 24 BIT ADDRESS		   :
;                        CC=LOW BYTE OF 24 BIT ADDRESS		   :
;                        DD=HIGH BYTE OF XOR FAILING BIT PATTERN	   :
;                        EE=LOW BYTE OF XOR FAILING BIT PATTERN	   :
;							   :
; DESCRIPTION FOR ERROR 202 (ADDRESS LINE 00-15)			   :
;       A WORD OF FFFF IS WRITTEN AT THE FIRST WORD AND LAST WORD    :
;       OF EACH 64K BLOCK WITH ZEROS AT ALL OTHER LOCATIONS OF THE   :
;       BLOCK.  A SCAN OF THE BLOCK IS MADE TO INSURE ADDRESS LINE   :
;       0-15 ARE FUNCTIONING.					   :
;							   :
; DESCRIPTION FOR ERROR 203 (ADDRESS LINE 16-23)			   :
;       AT THE LAST PASS OF THE STORAGE TEST, FOR EACH BLOCK OF	   :
;       64K, THE CURRENT STORAGE SIZE (ID) IS WRITTEN AT THE FIRST   :
;       WORD OF EACH BLOCK. IT IS USED TO FIND ADDRESSING FAILURES.  :
;							   :
;       "AABBCC DDEE 203"					   :
;		         SAME AS ABOVE EXCEPT FOR DDEE		   :
;							   :
; GENERAL DESCRIPTION FOR BLOCK ID (DDEE WILL NOW CONTAINED THE ID)  :
;       DD=HIGH BYTE OF BLOCK ID					   :
;       EE=LOW BYTE OF BLOCK ID					   :
;							   :
;       BLOCK ID       ADDRESS RANGE					   :
;       0000           000000 --> 00FFFF					   :
;       0040           010000 --> 01FFFF					   :
;       //						   :
;       0200           090000 --> 09FFFF (512->576K) IF 640K BASE	   :
;                      100000 --> 10FFFF (1024->1088K) IF 512K BASE  :
;							   :
; EXAMPLE (640K BASE MEMORY + 512K I/O MEMORY = 1152K TOTAL)	   :
;       NOTE: THE CORRECT BLOCK ID FOR THID FAILURE IS 0280 HEX, 	   :
;             DUE TO AN ADDRESS FAILURE THE BLOCK ID+128K OVERLAYED  :
;             THE CORRECT BLOCK ID.					   :
;							   :
;       00640K OK        <-- LAST OK MEMORY				   :
;       10000 0300 202   <-- ERROR DUE TO ADDRESS FAILURE		   :
;							   :
; IF A PARITY LATCH WAS SET, THE CORRESPONDING MESSAGE WILL DISPLAY. :
;							   :
;       "PARITY CHECK 1" (OR 2)					   :
;							   :
; DMA PAGE REGISTERS ARE USED AS TEMPORARY SAVE AREAS FOR SEGMENT    :
; DESCRIPTOR VALUES.					   :
;---------------------------------------------------------------------
	
SHUT3:			;       ENTRY FROM PROCESSOR SHUTDOWN 3
	CALL	DDS	; SET REAL MODE DATA SEGMENT

			;	  <><> MEMORY FAILED  <><>
	MOV	@MFG_ERR_FLAG+1,MEM_FAIL 	; CLEAR AND SET MANUFACTURING ERROR FLAG
	MOV	AL,CR	; CARRIAGE RETURN
	CALL	PRT_HEX
	MOV	AL,LF	; LINE FEED
	CALL	PRT_HEX
	IN	AL,DMA_PAGE+3	; GET THE HIGH BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE	; CONVERT AND PRINT CODE
	IN	AL,DMA_PAGE+4	; GET THE MIDDLE BYTE OF 24 BIT ADORES
	CALL	XPC_BYTE
	IN	AL,DMA_PAGE+5	; GET THE LOW BYTE OF 24 BIT ADDRESS
	CALL	XPC_BYTE
	MOV	AL,' '	; SPACE TO MESSAGE
	CALL	PRT_HEX
	IN	AL,DMA_PAGE+2	; GET HIGH BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE	; CONVERT AND PRINT CODE
	IN	AL,DMA_PAGE+1	; GET LOW BYTE FAILING BIT PATTERN
	CALL	XPC_BYTE	; CONVERT AND PRINT CODE
	
;-----	CHECK FOR ADDRESS ERROR
	
	IN	AL,MFG_PORT	; GET THE CHECKPOINT
	CMP	AL,33H	; IS IT AN ADDRESS FAILURE?
	MOV	SI,OFFSET E203	; LOAD ADDRESS ERROR 16->23
	JZ	ERR2	; GO IF YES

	MOV	SI,OFFSET E202	; LOAD ADDRESS ERROR 00->15
	CMP	AL,32H	; GO IF YES
	JZ	ERR2

	MOV	SI,OFFSET E201	; SETUP ADDRESS OF ERROR MESSAGE
ERR2:
	CALL	E_MSG	; PRINT ERROR MESSAGE
	IN	AL,DMA_PAGE+7	; GET THE PORT_B VALUE
	
;----- 	DISPLAY "PARITY CHECK ?* ERROR MESSAGES
	
	TEST	AL,PARITY_CHECK	; CHECK FOR PLANAR ERROR
	JZ	NMI-ML	; SKIP IF NOT

	PUSH	AX	; SAVE STATUS
	CALL	PACING	; INSERT BLANKS
	WAY	SI,OFFSET OF	; PLANAR ERROR, ADDRESS "PARITY CHECK"
	CALL	P MSG	; DISPLAY "PARITY CHECK 1" MESSAGE
	POP	AL	; AND RECOVER STATUS
NMI_M1:
	TEST	AL,IO_CHECK	; I/O PARITY CHECK?
	JZ	NMI_M2	; SKIP IF CORRECT ERROR DISPLAYED

	CALL	PADDING	; INSERT BLANKS
	MOV	SI,OFFSET D2	; ADDRESS OF "PARITY CHECK 2" MESSAGE
	CALL	P_MSG	; DISPLAY "PARITY CHECK 2" ERROR
NMI_M2:
			; CONTINUE TESTING SYSTEM ....
	
;----- 	ENTRY FROM SHUTDOWN
	
SHUT2:
;---------------------------------------------------------
; TEST.20				   :
;       ADDITIONAL PROTECTED (VIRTUAL MODE) TEST         :
; DESCRIPTION				   :
;       THE PROCESSOR IS PUT IN PROTECTED MODE AND	   :
;       THE FOLLOWING FUNCTIONS ARE VERIFIED		   :
;					   :
;       1. VERIFY PROTECTED MODE			   :
;          THE MACHINE STATUS IS CHECK FOR VIRTUAL MODE  :
;       2. PROGRAMMED INTERRUPT TEST			   :
;          AN PROGRAMMED INTERRUPT 32 IS ISSUED AND	   :
;          AND VERIFIED			   :
;       3. EXCEPTION INTERRUPT 13 TEST			   :
;          A DESCRIPTOR SEGMENT LIMIT IS SET TO ZERO     :
;          AND A WRITE TO THAT SEGMENT IS ATTEMPTED	   :
;          AN EXCEPTION 13 IS EXPECTED AND VERIFIED	   :
;       4. LDT/SDT LTR/STR TEST			   :
;          LOAD LDT REGISTER AND VERIFY CORRECT		   :
;          LOAD TASK REGISTER AND VERIFY CORRECT	   :
;          THEY ARE VERIFIED VIA THE STORE INSTRUCTION   :
;       5. THE CONTROL FLAGS OF THE 286 FOR DIRECTION    :
;          ARE VERIFIED VIA THE STD AND CLD COMMANDS	   :
;          IN PROTECTED MODE			   :
;       6. BOUND INSTRUCTION TEST (EXCEPTION INT 5)	   :
;          CREATE A SIGNED ARRAY INDEX WITHIN AND	   :
;          OUTSIDE THE LIMITS.  CHECK THAT NO EXC INT	   :
;          IF WITHIN LIMIT AND THAT AN EXC INT 5	   :
;          OCCURS IF OUTSIDE THE LIMITS.			   :
;       7. PUSH ALL POP ALL TEST			   :
;          SET GENERAL PURPOSE REGISTERS TO DIFFERENT	   :
;          VALUES, ISSUE A PUSH ALL, CLEAR THE REGISTERS :
;          THEN ISSUE A POP ALL AND VERIFY CORRECT.	   : 
;       8. CHECK THE VERR/VERW INSTRUCTIONS		   :
;          THE ACCESS BYTE IS SET TO READ ONLY THEN TO   :
;          A WRITE ONLY AND THE VERR/VERW INSTRUCTIONS   :
;          ARE VERIFIED.			   :
;       9. CAUSE AN INTERRUPT 13 VIA A WRITE TO A	   :
;          READ ONLY SEGMENT			   :
;      10. VERIFY THE ARPL INSTRUCTION FUNCTIONS 	   :
;          SET THE RPL FIELD OF A SELECTOR AND 		   :
;          VERIFY THAT CURRENT SELECTOR RPL IS SET	   :
;          CORRECTLY.			   :
;      11. VERIFY THE LAR INSTRUCTION FUNCTIONS		   :
;      12. VERIFY THE LSL INSTRUCTION FUNCTIONS		   :
;      13. LOW MEG CHIP SELECT TEST			   :
;---------------------------------------------------------
	
	JMP	POST3	; GO TEST THE 286 PROTECTED MODE
	
;-----	FAILURE ENTRY FROM A SHUTDOWN
	
SHUT7:	CALL	DDS	; ESTABLISH THE DATA SEGMENT
	IN	AL,MFG_PORT	; CHECK FOR CHIP SELECT ERROR
	CMP	AL,35H
	MOV	SI,OFFSET E109	; PRINT ERROR 109
	JZ	SHUT7B	; GO IF NOT
SHUT7A:	MOV	SI,OFFSET E104	; PROTECTED MODE FAILED

	OR	@MFG_ERR_FLAG+1,PRO_FAIL	;	  <><><><><><><><><><><><><><><>
			;	  <><> VIRTUAL MODE FAILED  <><>

	CALL	E_MSG	; PRINT MESSAGE
	JMP	SHORT SHUT6
SHUT7B:	CALL	E_MSG	; PRINT MESSAGE

	OR	@MFG_ERR_FLAG+1,LMCS_FAIL	;	  <><><><><><><><><><><><><><><>
			;	  <><> LOW MEG CHIP SELECT  <><>
	
;-----	PROTECTED MODE TEST PASSED ENTRY FROM A SHUTDOWN
	
SHUT6:	CALL	DDS	; PROTECTED MODE TEST PASSED
	SUB	AX,AX	; CLEAR KEYBOARD STATE FLAGS
	MOV	WORD PTR @KB_FLAG,AX
	MOV	CX,0EH	; CLEAR PACE REGISTERS
	MOV	DX,DMA_PAGE+1
CLR_LOOP:
	SUB	AL,AL
	OUT	DX,AL
	INC	DX
	LOOP	CLR_LOOP

;------------------------------------------------
;TEST.21				:
;      KEYBOARD TEST		:
; DESCRIPTION			:
;      RESET THE KEYBOARD AND CHECK THAT SCAN	:
;      CODE *AA" IS RETURNED TO THE PROCESSOR.	:
;      CHECK FOR STUCK KEYS.		:
;------------------------------------------------
	
	MOV	AL,35H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT	 35 <><>

	TEST	@MFG_TST,MFG_LOOP	; MANUFACTURING BURN IN TEST MODE?
	JNZ	F7_A
	JMP	F7	; YES - SKIP KEYBOARD TEST
F7_A:	CMP	BYTE PTR @RESET_FLAG,064H ; MANUFACTURING RUN IN MODE?
	JNZ	F7_B
	JMP	F7	; YES - SKIP KEYBOARD TEST
F7_B:	MOV	AL,36H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  36 <><>
	CLI
	CMP	@RESET_FLAG,1234H	; SOFT RESET?
	JZ	G10
	CMP	BYTE PTR @RESET_FLAG,KB_OK ; CHECK FOR AA ALREADY RECEIVED
	JZ	G10	; GO IF YES
	MOV	AL,ENA_KBD
	CALL	C8042	; ENABLE KEYBOARD
	MOV	BH,4	; TRY 4 TIMES
LOOP1:	CALL	OBF_42	; CHECK FOR OUTPUT BUFFER FULL
	JNZ	G10	; GO IF BUFFER FULL
	DEC	BH
	JNZ	LOOP1
G10:	MOV	AL,DIS_KBD	; DISABLE KEYBOARD
	CALL	C8042
	IN	AL,PORT_A	; FLUSH
	MOV	AL,KYBD_CLK_DATA	; GET THE CLOCK AND DATA LINES
	CALL	C8042
	CALL	OBF_42	; WAIT FOR OUTPUT BUFFER FULL
	IN	AL,PORT_A	; GET THE RESULTS
	TEST	AL,KYBD_CLK	; KEYBOARD CLOCK MUST BE LOW
	JZ	G11
	
	OR	@MFG_ERR_FLAG+1,KYCLK_FAIL ;	  <><><><><><><><><><><><><><><>
			;	  <><> KEYBOARD CLOCK HIGH  <><>
	MOV	SI,OFFSET E304	; DISPLAY 304 ERROR
	JMP	SHORT F6D	; REPORT ERROR
G11:	CALL	KBD_RESET	; ISSUE RESET TO KEYBOARD
	JCXZ	F6	; PRINT ERROR MESSAGE IF NO INTERRUPT
	MOV	AL,37H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  37 <><>
	CMP	BL,KB_OK	; SCAN CODE AS EXPECTED?
	JNE	F6	; NO - DISPLAY ERROR MESSAGE
	
;----- 	CHECK FOR STUCK KEYS
	
	MOV	AL,38H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  38 <><>

	MOV	AL,ENA_KBD	; ASSURE KEYBOARD ENABLED
	CALL	C8042	; ISSUE THE COMMAND
	MOV	CX,6628	; COUNT FOR 100 MILLISECONDS
	CALL	WAITF	; DELAY FOR A WHILE
	IN	AL,STATUS_PORT	; CHECK FOR STUCK KEYS
	TEST	AL,OUT_BUF_FULL	; OUT BUFFER FULL?
	JE	F7	; YES - CONTINUE TESTING

	MOV	AL,39H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  39 <><>

	IN	AL,PORT_A	; GET THE SCAN CODE
	CALL	XPC_BYTE	; CONVERT AND PRINT
	JMP	SHORT F6C	; CONTINUE
	
;-----	KEYBOARD ERROR TRY TO DETERMINE IF 8042 INTERFACE IS WORKING
	
F6:	CLI
	MOV	AL,INTR_FACE_CK	; COMMAND TO 8042
	OUT	STATUS_PORT,AL
	SUB	CX,CX
	MOV	BH,05	; WAIT FOR OUTPUT BUFFER FULL
F6A:	IN	AL,STATUS_PORT
	TEST	AL,OUT_BUF_FULL	; 8042 FINISHED TEST?
	LOOPZ 	F6A
	JNZ	F6B	; GO CHECK RESULTS
	DEC	BH
	JNZ	F6A	; TRY AGAIN
	MOV	SI,OFFSET E303	; INDICATE PLANAR FAILURE
	JMP	SHORT F6D	; (REMOVE KEYBOARD TRY AGAIN)
F6B:	IN	AL,PORT_A	; GET THE RESULTS OF INTERFACE TEST
	CMP	AL,0	; IS THE INTERFACE OK?
	JZ	F6C
	OR	@MFG_ERR_FLAG+1,KY_SYS_FAIL  ;	  <><><><><><><><><><><><><>
			;	  <><> KEYBOARD/SYSTEM  <><>
	MOV	SI,OFFSET E303	; PLANAR FAILURE
	JMP	SHORT F6D	; GO IF YES
F6C:	MOV	SI,OFFSET E301	; GET MESSAGE ADDRESS
	
	OR	@MFG_ERR_FLAG+1,KYBD_FAIL	;	  <><><><><><><><><><><><><>
			;	  <><> KEYBOARD FAILED  <><>
	
F6D:	CALL	E_MSG	; PRINT MESSAGE ON SCREEN
	
;-----	INITIALIZE 8042 TO HONOR KEY LOCK
	
F7I	MOV	AL,3AH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT	 3A <><>

	MOV	AL,0FFH	; DISABLE INTERRUPTS
	OUT	INTA01,AL
	CLI
	MOV	AL,WRITE_042_LOC	; WRITE 8042 MEMORY COMMAND
	CALL	C8042	; ISSUE THE COMMAND
	MOV	AL,45H	; SET SYSTEM FLAG - OUTBUF INTERRUPT
	OUT	PORT_A,AL	; PC COMPATIBILITY
			; RESET INHIBIT OVER RIDE

;-----	DEGATE ADDRESS LINE 20
	
	MOV	AH,DISABLE_BIT20	; SET COMMAND IN AH
	CALL	GATE_A20	; ISSUE THE COMMAND
	
;-----	SETUP HARDWARE INTERRUPT VECTOR TABLE LEVEL 0-7
	
	SUB	AX,AX
	MOV	ES,AX
	MOV	CX,08	; GET VECTOR COUNT
	PUSH	CS	; SETUP DS SEGMENT REGISTER
	POP	DS
	MOV	SI,OFFSET VECTOR_TABLE
	MOV	DI,OFFSET @INT_PTR
F7A:	MOVSW
	INC	DI	; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A

;-----	SETUP HARDWARE INTERRUPT VECTORS LEVEL 8-15 (VECTORS START AT INT 70H)

	ASSUME ES:ABS0
	SUB	AX,AX
	MOV	ES,AX
	MOV	CX,08	; GET VECTOR COUNT
	PUSH	CS	; SETUP DS SEGMENT REGISTER
	PUSH	DS
	MOV	SI,OFFSET SLAVE_VECTOR_TABLE
	MOV	DI,OFFSET @SLAVE_INT_PTR
F7A1: 	MOVSW
	INC	DI	; SKIP OVER SEGMENT
	INC	DI
	LOOP	F7A1
	
;-----	SET UP OTHER INTERRUPTS AS NECESSARY
	
	ASSUME	DS:ABS0
	SUB	AX,AX	; DS=0
	MOV	DS,AX
	MOV	WORD PTR @NMI_PTR,OFFSET NMI_INT ; NMI INTERRUPT
	MOV	WORD PTR @INT5_PTR,OFFSET PRTNT_SCREEN	; PRINT SCREEN
	MOV	WORD PTR @BASIC_PTR+2,0F600H	  ; SEGMENT FOR CASSETTE BASIC
	
;-----	ZERO RESERVED VECTORS
	
	MOV	DI,60H*4	; FILL INTERRUPT 60 THRU 67 WITH ZERO
	MOV	CX,16	; CLEAR 16 WORDS
F7A2:	MOV	WORD PTR DS:[DI],0
	ADD	DI,2	; POINT TO NEXT LOCATION
	LOOP	F7A2
	
;-----	SETUP TIMER 0 TO BLINK LED IF MANUFACTURING TEST MODE
	
	ASSUME	DS:DATA
	CALL	DDS	; ESTABLISH DATA SEGMENT
	
	TEST	@MFG_TST,MFG_LOOP	; MFG. TEST MODE?
	JNZ	F9
	MOV	WORD PTR ES:@INT_PTR,OFFSET BLINK_INT ; SETUP TIMER TO BLINK LED
	MOV	AL,0FEH	; ENABLE TIMER INTERRUPT
	OUT	INTA01,AL
F9:	STI		; ALLOW INTERRUPTS
	
;-----	ISSUE A RESET TO THE HARD FILE IF SOFT RESET
	
	CMP	@RESET_FLAG,1234H	; SOFT RESET?
	JNZ	F9A	; CONTINUE IF NOT
	MOV	CX,0FFH
	MOV	DX,03F6H
	MOV	AL,04H	; RESET
	OUT	DX,AL
F9_A:	LOOP	F9_A	; HOLD RESET
	SUB	AL,AL
	OUT	DX,AL	; REMOVE RESET

;-----------------------------------------------------------------
; TEST.23			:
;	DISKETTE ATTACHMENT TEST 		:
; DESCRIPTION 			:
;        CHECK IF IPL DISKETTE DRIVE IS ATTACHED TO SYSTEM, IF	:
;        ATTACHED, VERIFY STATUS OF NEC FDC AFTER A RESET. ISSUE	:
;        A RECALIBRATE AND SEEK COMMAND TO FDC AND CHECK STATUS.	:
;        COMPLETE SYSTEM INITIALIZATION THEN PASS CONTROL TO THE	:
;        BOOT LOADER PROGRAM.		:
;-----------------------------------------------------------------
	
F9A:	MOV	AL,3CH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  3C <><>
	
	MOV	AL,02H	; SET DATA RATE TO 250 K BITS PER SECOND
	MOV	DX,3F7H
	OUT	DX,AL
	TEST	BYTE PTR @EQUIP_FLAG,1H	; DISKETTE PRESENT?
	JZ	F15
	TEST	@MFG_TST,MFG_LOOP	; MFG JUMPER INSTALLED?
	JZ	F15	; GO IF YES
F10:			; DISK_TEST:
	IN	AL,INTA01
	JMP	$+2	; I/O DELAY
	AND	AL,0BFH	; ENABLE DISKETTE INTERRUPTS
	OUT	INTA01,AL
	MOV	AH,0	; RESET NEC FDC
	MOV	DL,AH	; SET FOR DRIVE 0
	INT	13H	; VERIFY STATUS AFTER RESET
	TEST	AH,0FFH	; STATUS OK?
	JNZ	F13	; NO - FDC FAILED
	
;-----	TURN DRIVE 0 MOTOR ON
	MOV	DX,03F2H	; GET ADDRESS OF FDC CARD
	MOV	AL,1CH	; TURN MOTOR ON, ENABLE DMA, INTERRUPTS
	OUT	DX,AL	; WRITE FDC CONTROL REGISTER
	SUB	CX,CX	; WAITF COUNT FOR 0.988 SECONDS
	CALL	WAITF	; WAIT 1 SECOND FOR MOTOR

	XOR	DI,DI	; SELECT DRIVE 0
	MOV	CH,1	; SELECT TRACK 1
	MOV	@SEEK_STATUS,0	; INSURE RECALIBRATE
	OR	@RTC_WAIT_FLAG,01	; NO REAL TIME CLOCK, USE WAIT LOOP
	CALL	SEEK	; RECALIBRATE DISKETTE
	JC	F13	; GO TO ERR SUBROUTINE IF ERR
	MOV	CH,34	; SELECT TRACK 34
	CALL	SEEK	; SEEK TO TRACK 34
	JNC	F14	; OK, TURN MOTOR OFF
F13:			; DSK_ERR:
	OR	@MFG_ERR_FLAG+1,DSK_FAIL	;	  <><><><><><><><><><><><><>
			;	  <><> DISKETTE FAILED  <><>
	MOV	SI,OFFSET E601	; GET ADDRESS OF MESSAGE
	CALL	E_MSG	; GO PRINT ERROR MESSAGE

;-----	TURN DRIVE 0 MOTOR OFF

F14:			; DR0_OFF:
	AND	@RTC_WAIT_FLAG,0FEH	; ALLOW FOR RTC WAIT
	MOV	AL,0CH	; TURN DRIVE 0 MOTOR OFF
	MOV	DX,03F2H	; FDC CONTROLLER ADDRESS
	OUT	DX,AL

;-----	SETUP KEYBOARD PARAMETERS

F15:
	MOV	@INTR_FLAG,00H	; SET STRAY INTERRUPT FLAG = 00
	MOV	SI,OFFSET @KB_BUFFER	; SETUP KEYBOARD PARAMETERS
	MOV	@BUFFER_HEAD,SI
	MOV	@BUFFER_TAIL,SI
	MOV	@BUFFER_START,SI
	ADD	SI,32	; DEFAULT BUFFER OF 32 BYTES
	MOV	@BUFFER_END,SI

;-----	SET PRINTER TIMEOUT DEFAULT

	MOV	DI,OFFSET @PRINT_TIM_OUT	; SET DEFAULT PRINTER TIMEOUT
	PUSH	DS
	POP	ES
	MOV	AX,1414H	; DEFAULT=20
	STOSW
	STOSW

;-----	SET RS232 DEFAULT

	MOV	AX,0101H	; RS232 DEFAULT=01
	STOSW
	STOSW

;-----	ENABLE TIMER INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FFH	; ENABLE TIMER INTERRUPTS
	JMP	$+2	; I/O DELAY
	OUT	INTA01,AL

;----- 	CHECK CMOS BATTERY AND CHECKSUM

	TEST	@MFG_TST,MFG_LOOP	; MFG JUMPER?
	JNZ	B1_OK	; GO IF NOT
	JMP	F15C	; BYPASS IF YES
B1_OK:
	MOV	AL,CMOS_DIAG+NMI	; ADDRESS DIAGNOSTIC STATUS BYTE
	CALL	CMOS_READ	; READ IT FROM CMOS

	MOV	SI,OFFSET E161	; LOAD BAD BATTERY MESSAGE 161
	TEST	AL,BAD_BAT	; BATTERY BAD?
	JNZ	B1_ER	; DISPLAY ERROR IF BAD

	MOV	SI,OFFSET E162	; LOAD CHECKSUM BAD MESSAGE 162
	TEST	AL,BAD_CKSUM+BAD_CONFIG	; CHECK FOR CHECKSUM OR NO DISKETTE
	JZ	C_OK	; SKIP AND CONTINUE TESTING CMOS CLOCK
B1_ER:
	CALL	E_MSG	; ELSE DISPLAY ERROR MESSAGE
	OR	BP,08000H	; FLAG "SET SYSTEM OPTIONS" DISPLAYED
	JMP	SHORT H_OK1A	; SKIP CLOCK TESTING IF ERROR

;-----	TEST CLOCK UPDATING

C_OK:	MOV	BL,04H	; OUTER LOOP COUNT
D_OK:	SUB	CX,CX	; INNER LOOP COUNT
E_OK:	MOV	AL,CMOS_REG_A+NMI	; GET THE CLOCK UPDATE BYTE
	CALL	CMOS_READ
	TEST	AL,80H	; CHECK FOR UPDATE IN PROGRESS
	JNZ	G_OK	; GO IF YES
	LOOP	E_OK	; TRY AGAIN
	DEC	BL	; DEC OUTER LOOP
	JNZ	0 OK	; TRY AGAIN
F_OK:	MOV	SI,OFFSET E163	; PRINT MESSAGE
	CALL	E_MSG

;-----	SET CMOS DIAGNOSTIC STATUS TO 04 (CLOCK ERROR)

	MOV	AX,X*CMQS_DIAG+NMI	; SET CLOCK ERROR
	CALL	CMOS_READ	; GET THE CURRENT STATUS
	OR	AL,CMOS_CLK_FAIL	; SET NEW STATUS
	XCHG	AL,AH	; GET STATUS ADDRESS AND SAVE NEW STATUS
	CALL	CMOS_WRITE	; MOVE NEW DIAGNOSTIC STATUS TO CMOS
	JMP	SHORT H_OK	; CONTINUE

;-----	CHECK CLOCK UPDATE

G_OK:	MOV	CX,800	; LOOP COUNT
I_OK:	MOV	AL,CMOS_REG_A+NMI	; CHECK FOR OPPOSITE STATE
	CALL	CMOS_READ
	TEST	AL,80H
	LOOPNZ	I_OK	; TRY AGAIN
	JCXZ	F_OK	; PRINT ERROR IF TIMEOUT

;-----	CHECK MEMORY SIZE DETERMINED CONFIGURATION

H_OK:
	MOV	AL,CMOS_DIAG+NMI	; GET THE STATUS BYTE
	CALL	CMOS_READ
	TEST	AL,W_MEM_SIZE	; WAS THE CONFIG= MEM_SIZE_DETERMINED?
	JZ	H_OK1A	; GO IF YES

;-----	MEMORY SIZE ERROR

	MOV	SI,OFFSET E164	; PRINT SIZE ERROR
	CALL	E_MSG	; DISPLAY ERROR

;-----	CHECK FOR CRT ADAPTER ERROR

H_OK1A:	CMP	@MFG_ERR_FLAG,0CH	; CHECK FOR MONOCHROME CRT ERROR
	MOV	SI,OFFSET E401	; LOAD MONOCHROME CRT ERROR
	JZ	H_OK1B	; GO IF YES

	CMP	@MFG_ERR_FLAG,0DH	; CHECK FOR COLOR CRT ADAPTER ERROR
	JNZ	J_OK	; CONTINUE IF NOT
	MOV	SI,OFFSET E501	; CRT ADAPTER ERROR MESSAGE
H_OK1B:
	CALL	E_MSG

;-----	CHECK FOR MULTIPLE DATA RATE CAPABILITY

J_OK:
	MOV	DX,03F1H	; D/S/P DIAGNOSTIC REGISTER
	IN	AL,DX	; READ D/S/P TYPE CODE
	AND	AL,11111000B	; KEEP ONLY UNIQUE CODE FOR D/S/P
	CMP	AL,01010000B	; D/S/P CARD - MULTIPLE DATA RATE?
	JZ	J_OK3	; IF SO JUMP

	MOV	DX,05F7H	; FIXED DISK DIAGNOSTIC REGISTER
	IN	AL,DX	; READ FIXED DISK TYPE CODE
	AND	AL,11110000B	; KEEP ONLY UNIQUE CODE FOR F/D
	CMP	AL,10100000B	; FIXED DISK ADAPTER ?
	JZ	J_FAIL	; MUST BE COMBO ELSE ERROR

	MOV	BL,0FH	; OUTER LOOP COUNT WAIT FOR BUSY OFF
	SUB	CX,CX
	MOV	DX,01F7H	; HARD FILE STATUS PORT
J_OK1:
	IN	AL,DX	; GET THE STATUS
	TEST	AL,080H	; IS THE CONTROLLER BUSY?
	JZ	J_OK2	; CONTINUE IF NOT
	LOOP	J_OK1	; TRY AGAIN
	DEC	BL	; DECREMENT OUTER LOOP
	JNZ	J_OK1	; TRY AGAIN IF NOT ZERO
	AND	AL,0CH	; BITS 2 & 3 = 0 IF MULTI DATA CAPABLE
	JZ	J_OK3	; GO IF YES
	JMP	SHORT J_FAIL	; NO MULTIPLE DATA RATE CAPABILITY
J_OK2:	
	MOV	DX,1F4H	; VERIFY MULTIPLE DATA RATE CAPABLE
	MOV	AL,055H	; WRITE TO THE CYLINDER BYTE
	OUT	DX,AL
	JMP	$+2	; I/O DELAY
	IN	AL,DX	; CHECK DATA WRITTEN = DATA READ
	CMP	AL,055H
	JNZ	J_FAIL	; GO IF NOT
	MOV	AL,0AAH	; WRITE ANOTHER PATTERN
	OUT	DX,AL
	JMP	$+2	; I/O DELAY
	IN	AL,DX
	CMP	AL,0AAH	; IS DATA PATTERN THE SAME?
	JZ	J_OK3	; GO IF SO

J_FAIL:
	OR	@MFG_ERR_FLAG+1,DSK_FAIL	;	  <><><><><><><><><><><><><>
			;	  <><> DISKETTE FAILED  <><>
	MOV	SI,OFFSET E601	; GET ADDRESS OF MESSAGE
	CALL	E_MSG	; GO PRINT ERROR MESSAGE
	JMP	SHORT F15C	; SKIP SETUP IF ERROR

J_OK3:
	OR	@LASTRATE,DUAL	; TURN ON DSP/COMBO FLAG

;-----	INITIALIZE FLOPPY FOR DRIVE TYPE

	MOV	AL,3DH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT 3D  <><>
	CALL	DSKETTE_SETUP	; INITIALIZE FLOPPY

;-----	CHECK FOR 2ND DISKETTE DRIVE

	CALL	DDS	; INSURE DATA SEGMENT
	MOV	AH,@DSK_STATE+1	; GET STATE OF SECOND DRIVE
	OR	AH,AH	; IS THERE A DRIVE 2 ATTACHED?
	JZ	F15C	; SKIP IF NOT
	OR	BYTE PTR @EQUIP_FLAG,40H	; ELSE SET SECOND DRIVE INSTALLED
	MOV	AH,0FFH	; SET TEST MASK FOR DRIVE PRESENT
F15C:
	MOV	AL,CMOS_DIAG+NMI	; GET THE CMOS DIAGNOSTIC STATUS
	CALL	CMOS_READ
	TEST	AL,BAD_BAT+BAD_CKSUM	; BATTERY/CHECKSUM OK
	JNZ	ROM_SCAN1	; BYPASS DISK SETUP IF NOT

	MOV	AL,CMOS_DISKETTE+NMI	; ADDRESS DISKETTE TYPE BYTE
	CALL	CMOS_READ	; GET DISKETTE TYPES
	AND	AL,00FH	; LOOK AT SECOND DRIVE TYPE DEFINED
	CMP	AL,AH	; ARE BOTH INDICATORS ZERO
	JE	F15D	; SKIP IF NO SECOND DRIVE

	AND	AL,AH	; ARE BOTH INDICATORS NON-ZERO
	JNZ	F15D	; SKIP IF DRIVE FOUND AND DEFINED

	CALL	CONFIG_BAD	; SET BAD_CONFIG IN CMOS_DIAG

;-----	INITIALIZE HARD FILE
F15D:
	MOV	AL,3EH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT	 3E <><>

	MOV	AL,CMOS_DISK+NMI	; INSURE CMOS DEFINES TYPE OF FIXED DISK
	CALL	CMOS_READ
	CMP	AL,0H	; INSURE TYPE IS DEFINED
	JZ	ROM_SCAN1	; BYPASS DISK SETUP IF NOT

	CALL	DISK_SETUP	; INITIALIZE HARD FILE(S)

;-----------------------------------------------------------
; TEST.22			:
; CHECK FOR OPTIONAL ROM FROM C800->E000 IN 2K BLOCKS	:
;       (A VALID MODULE HAS '55AA' IN THE FIRST 2 LOCATIONS	:
;       LENGTH INDICATOR (LENGTH/512) IN THE 3RD LOCATION	:
;       AND TEST/INIT. CODE STARTING IN THE 4TH LOCATION)	:
;-----------------------------------------------------------

ROM_SCAN1:
	STI		; ALLOW INTERRUPTS
	MOV	AL,3BH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT	 3B <><>
	CALL	DDS	; SET REAL MODE DATA SEGMENT
	MOV	AL,10	; LINE FEED ON DISPLAY
	CALL	PRT_HEX
ROM_SCAN:

;-----	SET DMA MASK AND REQUEST REGISTERS

	SUB	AL,AL
	OUT	DMA18+2,AL	; SEND ZERO TO MASK REGISTER
	JMP	$+2
	OUT	DMA18+4,AL	; SEND ZERO TO REQUEST REGISTER
	MOV	DX,0C800H	; SET BEGINNING ADDRESS
ROM_SCAN2:
	MOV	DS,DX 
	PUSH	DI	; SAVE WORK REGISTER
	MOV	DI,0AA55H	; GET TEST PATTERN
	SUB	BX,BX	; SET BX=0000
	MOV	AX,[BX]	; GET 1ST WORD FROM MODULE
	CMP	AX,DI	; = TO ID WORD?
	POP	DI	; RECOVER WORK REGISTER
	JNZ	NEXT_ROM	; PROCEED TO NEXT ROM IF NOT
	CALL	ROM_CHECK	; GO CHECK OUT MODULE
	JMP	SHORT ARE_WE_DONE	; CHECK FOR END OF ROM SPACE
NEXT_ROM:
	ADD	DX,0080H	; POINT TO NEXT 2K ADDRESS
ARE_WE_DONE:
	CMP	DX,0E000H	; AT E0000 YET?
	JL	ROM_SCAN2	; GO CHECK ANOTHER ADD. IF NOT

;-----	TEST FOR KEYBOARD LOCKED

	CALL	DDS	; SET DATA SEGMENT
	IN	AL,STATUS_PORT	; IS KEYBOARD UNLOCKED?
	AND	AL,KYBD_INH
	JZ	KEY1	; NO - SET ERROR FLAGS AND PRINT MESSAGE
	JMP	SHORT KEY10	; GO IF OFF
KEY1:
	OR	@MFG_ERR_FLAG+1,KEY_FAIL	;	  <><><><><><><><><><><><><><>
			;	  <><> KEYBOARD IS LOCKED <><>
	ASSUME	DS:DATA
	MOV	SI,OFFSET E302	; PRINT LOCKED MESSAGE	(302)
	CALL	E_MSG
KEY10: 
	;===================
;-----	 SETUP @PRINTER_BASE
	;===================

	MOV	DI,OFFSET F4	; OFFSET OF PRINTER ADDRESS TABLE
	MOV	SI,0
F16:
	MOV	DX,CS:[DI]	; GET PRINTER BASE ADDRESS
	MOV	AL,0AAH	; WRITE DATA TO PORT A
	OUT	DX,AL
	JMP	$+2	; I/O DELAY
	PUSH	DS	; BUS SETTLING
	IN	AL,DX	; READ PORT A
	POP	DS
	CMP	AL,0AAH	; DATA PATTERN SAME
	JNE	F17	; NO - CHECK NEXT PRINTER CARD
	MOV	@PRINTER_BASE[SI],DX	; YES	- STORE PRINTER BASE ADDRESS
	INC	SI	; INCREMENT TO NEXT WORD
	INC	SI
F17:
	INC	DI	; POINT TO NEXT BASE ADDRESS
	INC	DI
	CMP	DI,OFFSET F4E	; ALL POSSIBLE ADDRESSES CHECKED?
	JNE	F16	; PRT_BASE
	;===========
;-----	 SETUP RS232
	;===========
	MOV	BX,0	; POINTER TO RS232 TABLE
	MOV	DX,3FAH	; CHECK IF RS232 CARD 1 ATTACHED ?
	IN	AL,DX	; READ INTERRUPT ID REGISTER
	TEST	AL,0F8H
	JNZ	F18
	MOV	@RS232_BASE[BX],3F8H	; SETUP RS232 CARD #1 ADDRESS
	INC	BX
	INC	BX
F18:	MOV	DX,2FAH	; CHECK IF RS232 CARD 2 ATTACHED
	IN	AL,DX	; READ INTERRUPT ID REGISTER
	TEST	AL,0F8H
	JNZ	F19	; BASE_END
	MOV	@RS232_BASE[BX],2F8H	; SETUP RS232 CARD #2
	INC	BX
	INC	BX
	;=================================================================
;-----	 SET UP @EQUIP_FLAG TO INDICATE NUMBER OF PRINTERS AND RS232 CARDS
	;=================================================================
F19:			; BASE_END:
	MOV	AX,SI	; SI HAS 2* NUMBER OF RS232
	MOV	CL,3	; SHIFT COUNT
	ROR	AL,CL	; ROTATE RIGHT 3 POSITIONS
	OR	AL,BL	; OR IN THE PRINTER COUNT
	MOV	BYTE PTR @EQUIP_FLAG+1,AL		; STORE AS SECOND BYTE

;-----	INSURE CMOS CLOCK HAS VALID HOURS.MINUTES.SECONDS

	CALL	SET_TOD	; INSURE CMOS CLOCK IS VALID

;-----	ENABLE HARDWARE INTERRUPT IF MATH PROCESSOR (80287)

	MOV	AL,40H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	; 	  <><> CHECKPOINT  40 <><>

	MOV	DI,OFFSET @IO_ROM_INIT	; ADDRESS WORK STORAGE LOCATION
	XOR	AX,AX	; CLEAR WORK REGISTER (AH)= 0 (NO 287)
	MOV	WORD PTR [DI],AX	; CLEAR THE WORK LOCATION
	FNINIT		; INITIALIZE THE 80287 WITH NO WAIT
	JMP	$+2	; DELAY
	FNSTCW	WORD PTR [DI]	; WRITE THE CURRENT 80287 CONTROL WORD
	PUSHA		; TIME FOR 80287 TO RESPOND
	POPA
	AND	WORD PTR [DI],01F3FH	; CLEAR UNUSED 80287 BITS
	CMP	WORD PTR [DI],0033FH	; IS THE 80287 INSTALLED?
	JNE	NO_287	; GO IF MATH PROCESSOR IS NOT INSTALLED

	FSTSW	WORD PTR [DI]	; STORE THE STATUS WORD (WITH WAIT)
	PUSHA		; TIME FOR 80257 TO RESPOND
	POPA
	TEST	WORD PTR [DI],0B8BFH	; ALL BITS SHOULD BE OFF (OR ERROR)
	JNZ	NO_287	; GO IF NOT INSTALLED

	IN	AL,INTB01	; GET THE SLAVE INTERRUPT MASK
	AND	AL,0DFH	; ENABLE 80287 INTERRUPTS
	MOV	AH,002H	; SET WORK REGISTER FOR 80287 FOUND
	OUT	INTB01,AL
NO_287:
	MOV	BYTE PTR @EQUIP_FLAG	; GET LOW EQUIPMENT FLAG	
	AND	AL,002H	; STRIP OFF OTHER BITS
	CMP	AL,AH	; DOES CMOS MATCH HARDWARE ?
	JE	OK_287	; SKIP IF EQUIPMENT FLAG CORRECT

	XOR	BYTE PTR @EQUIP_FLAG,2H 	; ELSE SET 80287 BIT TO CORRECT VALUE OK 2571
	CALL	CONFIG_BAD	; AND SET THE CONFIGURATION ERROR FLAG
OK_287:
;-----	SET KEYBOARD STATE FLAGS

	MOV	WORD PTR @KB_FLAG,0	; RESET ALL KEYBOARD STATUS FLAGS

;-----	ENABLE KEYBOARD/TIMER INTERRUPTS

	IN	AL,INTA01
	AND	AL,0FCH	; ENABLE TIMER AND KEYBOARD INTERRUPTS
	JMP	$+2	; I/O DELAY
	OUT	INTA01,AL
	MOV	@MFG_ERR_FLAG,0	; CLEAR MFG ERROR FLAG
	
;-----	READ KEYBOARD ID TO INITIALIZE KEYBOARD TYPE AND NUM LOCK STATE

	MOV	@KB_FLAG_3,RD_ID+SET_NUM_LK 	; SET READ ID COMMAND FOR KBX
	MOV	AL,KB_READ_ID	; GET THIS SYSTEMS KEYBOARD ID REQUEST
	CALL	SND_DATA	; USE KEYBOARD TRANSMISSION ROUTINE
	MOV	CX,1658	; SET DELAY COUNT TO 25 MILLISECONDS
	CALL	WAITF	; WAIT FOR READ ID RESPONSE (20 MS)
	AND	@KB_FLAG_3,NOT RD_ID+LC_AB+SET_NUM_LK		; RESET READ ID COMMAND

;-----	CHECK FOR SECOND FIXED DISK PRESENT BUT NOT DEFINED

	CMP	@HF_NUM,2	; CHECK FOR TWO DRIVES DEFINED BY CMOS
	JE	F15G	; SKIP TEST IF TWO DRIVES DEFINED

	MOV	AH,010H	; GET TEST DRIVE READY COMMAND
	MOV	DL,081H	; POINT TO SECOND FIXED DISK
	INC	@HF_NUM	; TELL BIOS IT HAS TWO DRIVES
	INT	13H	; CHECK READY THROUGH BIOS
	DEC	@HF_NUM	; RESTORE CORRECT COUNT (RETAIN CY)
	JC	F15G	; SKIP IF SECOND DRIVE NOT READY
			;       SECOND DRIVE NOT DEFINED
	CALL	CONFIG_BAD	; SET CONFIGURATION BAD
F15G:
;------------------------------------------
;   TEST FOR ANY ERRORS (BP NOT ZERO)	:
;------------------------------------------

	OR	BP,BP	; CHECK (BP)= NON-ZERO	(ERROR HAPPENED)
	JE	F15A_0	; SKIP PAUSE IF NO ERROR

	CMP	BYTE PTR @RESET_FLAG,64H	; MFG RUN IN MODE?
	MOV	DX,2	; 2 SHORT BEEP COUNT FOR ERROR(S)
	JNZ	ERR_WAIT	; GO IF NOT

;-----	MFG RUN IN MODE -> SET ERROR FLAG

	MOV	@MFG_ERR_FLAG,0AAH	; INDICATE ERROR
	IN	AL,STATUS_PORT	; CHECK KEY LOCK STATUS
	AND	AL,KYBD_INH	; IS THE KEYBOARD LOCKED
	JNZ	F15A_0	; CONTINUE MFG MODE IF NOT LOCKED ELSE

	MOV	DX,5	; 5 SHORT BEEPS FOR MFG SETUP ERROR
ERR_WAIT:
	CALL	ERR_BEEP	; BEEPS FOR ERROR(S)
	MOV	AL,CMOS_DIAG	; ADDRESS CMOS
	CALL	CMOS_READ	; GET THE DIAGNOSTIC STATUS BYTE
	TEST	AL,BAD_CONFIG	; CHECK FOR BAD HARDWARE CONFIGURATION
	JZ	ERR_WKEY	; SKIP IF NOT SET

	TEST	BP,08000H	; ELSE CHECK FOR E161/E162 POSTED
	JNZ	ERR_WKEY	; SKIP IF DISPLAYED BEFORE NOW

	MOV	SI,OFFSET E162	; ELSE DISPLAY 'OPTIONS NOT SET'
	CALL	P_MSG	; WITH NON HALTING ROUTINE

;-----	CHECK FOR "UNLOCK SYSTEM UNIT KEYLOCK" MESSAGE REQUIRED

ERR_WKEY:
	IN	AL,STATUS_PORT	; CHECK IF RESUME MESSAGE NEEDED
	AND	AL,KYBD_INH	; IS THE KEYBOARD LOCKED
	JNZ	ERR_WAIT2	; SKIP LOCK MESSAGE IF NOT

	MOV	SI,OFFSET F3D1	; ERROR MESSAGE FOR KEYBOARD LOCKED
	CALL	P_MSG

;-----	DISPLAY '(RESUME = "F1" KEY)' FOR ERRORS

ERR-WAIT2:
	MOV	SI,OFFSET F3D	; RESUME ERROR MESSAGE
	CALL 	P_MSG

;-----	INITIALIZE PRINTER (ALTERNATE DISPLAY DEVICE)

	MOV	AH,1	;
	SUB	DX,DX	; FIRST PRINTER
	INT	17H	;
ERR_WAIT1:
	MOV	AL,3FH	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  3F <><>
	MOV	AH,00
	INT	16H	; WAIT FOR 'F1' KEY
	CMP	AH,3BH
	JNE	ERR_WAIT1
F15A_0:
	TEST	@MFG_TST,MFG_LOOP	; MFG BURN IN MODE
	JNZ	F15A	; GO IF NOT
	JMP	START_1	; GO LOOP POST
F15A:	CMP	BYTE PTR @RESET_FLAG,64H	; MFG RUN IN?
	JZ	F15B	; BYPASS BEEP IF YES

	MOV	DX,1	; 1 SHORT BEEP (NO ERRORS)
	CALL	ERR_BEEP
	;===============
;-----	SET TIME OF DAY
	;===============

F15B:	CALL 	SET_TOD

;-----	CLEAR DISPLAY SCREEN

	SUB	AH,AH	; CLEAR FLAGS
	MOV	AL,@CRT_MODE
	INT	10H	; CLEAR SCREEN

;-----	CLEAR DESCRIPTOR TABLES

F20:	MOV	CX,0500	; CLEAR 1K
	MOV	DI,SYS_IDT_LOC	; POINT ES TO START OF DESCRIPTORS
	SUB	AX,AX
	MOV	ES,AX
F20_A:	MOV	ES:[DI],AX	; CLEAR
	ADD	DI,2	; POINT TO NEXT LOCATION
	LOOP	F20_A	; CONTINUE TILL DONE

;-----	SET POST SYSTEM STACK

	MOV	AX,ABS0	; GET THE POST STACK SEGMENT
	MOV	SS,AX
	MOV	SP,OFFSET @TOS

;-----	ENSURE THAT MASTER LEVEL 2 ENABLED

	IN	AL,INTA01	; GET THE CURRENT MASK
	AND	AL,OFBH
	JMP	$+2	; I/O DELAY
	OUT	INTA01,AL

;-----	TEST FOR MFG RUN-IN TEST

	CMP	BYTE PTR @RESET_FLAG,64H	; IS THE MFG RUN-IN TEST?
	JNZ	END_287	; GO IF NOT
	JMP	SHORT SHUT4	; BOOT LOAD IF YES

;-----	UNMASK SLAVE HARDWARE INTERRUPT 9 (LEVEL 71)
END_287:
	IN	AL,INTB01	; GET THE CURRENT MASK
	AND	AL,0FDH
	JMP	$+2	; I/O DELAY
	OUT	INTB01,AL	; SET NEW MASK

;------------------------------------------------------------------
; TEST FOR SYSTEM CODE AT SEGMENT E000:0
;   FIRST WORD = AA55H
;   LAST BYTE = CHECKSUM
;   ENTRY POINT = FIRST BYTE + 3
; IF TEST IS SUCCESSFUL A CALL FAR TO THE ENTRY POINT IS EXECUTED
-------------------------------------------------------------------
	MOV	AL,41H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  41 <><>

	MOV	AL,CMOS_REG_D+NMI	; INSURE NMI OFF AND CMOS AT DEFAULT
	OUT	CMOS_PORT,AL

ENDIF

	MOV	BYTE PTR @RESET_FLAG,0	; CLEAR FLAG
	MOV	AX,0E0000H	; SEGMENT OF SYSTEM CODE
	MOV	ES,AX
	SUB	DI,DI
	MOV	AX,ES:[DI]	; CHECK FOR AA55
	PUSH	BX	; BUS SETTLE
	POP	BX
	CMP	AX,0AA55H
	PUSHF		; SAVE FLAGS
	MOV	ES:[DI],AX	; CLEAR POSSIBLE PARITY CHECK
	IN	AL,PORT_B
	OR	AL,RAM_PAR_OFF	; TOGGLE I/O-PARITY CHECK ENABLES
	OUT	PORT_B,AL
	AND	AL,RAM_PAR_ON
	OUT	PORT_B,AL
	POPF		; RESTORE FLAGS
	JNZ	SHUT4	; CONTINUE

;-----	CHECKSUM SYSTEM CODE

	PUSH	DS
	PUSH	ES	; SET SEGMENT TO TEST
	POP	DS
	SUB	BX,BX	; STARTING OFFSET
	CALL	ROM_CHECKSUM
	POP	DS	; RESTORE DATA SEGMENT
	JNZ	SHUT4	; GO IF CHECKSUM NOT OK

;-----	ENABLE NMI AND I/O-MEMORY PARITY CHECKS

	MOV	AL,CMOS_REG_D	; ENABLE NMI AND SET DEFAULT ADDRESS
	OUT	CMOS_PORT,AL

	IN	AL,PORT_8	; ENABLE PARITY
	AND	AL,RAM_PAR_ON	; ENABLE MEMORY PARITY CHECK / I/O CHECK
	OUT	PORT_B,AL

	MOV	@IO_ROM_INIT,0003H	; SET THE OFFSET
	MOV	@IO_ROM_SEG,ES	; SET THE SEGMENT

	MOV	AL,42H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  42 <><>

;-----	EXIT TO SYSTEM CODE

	CALL	DWORD PTR @IO_ROM_INIT	; GO TO SYSTEM CODE
			; VIA CALL THROUGH DATA AREA LOCATION

;-----	ENABLE NMI INTERRUPTS + ENTRY FROM SHUTDOWN WITH BOOT REQUEST

SHUT4:	MOV	AL,CMOS_REG_D	; ENABLE NMI AND SET DEFAULT ADDRESS
	OUT	CMOS_PORT,AL
	IN	AL,PORT_B	; ENABLE PARITY
	AND	AL,RAM_PAR_ON	; ENABLE MEMORY PARITY CHECK / I/O CHECK
	OUT	PORT_B,AL

	MOV	AL,43H	;	  <><><><><><><><><><><><>
	OUT	MFG_PORT,AL	;	  <><> CHECKPOINT  43 <><>
	STI		;  ENABLE INTERRUPTS IF DISABLED

	INT	19H	; GO TO BOOT LOADER

	HLT

PADING	PROC	NEAR	;	  INSERT PADDING
	MOV	CX,15	; GET BLANK CHARACTER COUNT
PAD1:
	MOV	AL,' '	; GET FILL SPACE
	CALL	PRT_HEX	; WRITE A SPACE
	LOOP	PAD1	; LOOP TILL INSERT DONE
	MOV	AL,'-'	; GET DASH CHARACTER
	CALL	PRT_HEX	; WRITE TO DISPLAY
	RET
PADING	ENDP

PRT_OK	PROC	NEAR	;	  PRINT "00000 KB OK"
	PUSH	AX	; SAVE WORK REGISTER
	MOV	BX,10	; SET DECIMAL CONVERT

;-----	CONVERT AND SAVE

	MOV	CX,5	; OF 5 NIBBLES XX,XXX KB
	SUB	DI,DI	; DISPLAY REGEN BUFFER POSITION
PRT_DIV:
	XOR	DX,DX
	DIV	BX	; DIVIDE BY 10
	OR	DL,30H	; MAKE INTO ASCII
	PUSH	DX	; SAVE
	LOOP	PRT_DIV

;-----	DISPLAY LAST OK MEMORY

	MOV	CX,S
PRT_DEC:
	POP	AX	; RECOVER A NUMBER
	CALL	PROT_PRT_HEX
	INC	DI	; POINT TO DISPLAY REGEN BUFFER
	LOOP	PRT_DEC
	MOV	CX,OFFSET F3B_PAD-OFFSET F3B	; LOAD MESSAGE LENGTH
	MOV	SI,OFFSET F3B	; POINT TO PRINT ' KB OK','    ' MESSAGE
PRT_LOOP:
	MOV	AL,CS:[SI]
	INC	SI
	CALL	PROT_PRT_HEX
	INC	DI	; INCREMENT BUFF PTR
	LOOP	PRT_LOOP
	POP	AX	; RECOVER WORK REGISTERS
	RET

F3B	DB	' KB OK'	; OK MESSAGE
F3B_OK	DB	' '	; PAD A SPACE
F3B_PAD	EQU	$
.LIST
PRT_OK	ENDP

;-----------------------
;PRINTER TABLE
;-----------------------

F4	DW	03BCH	; ADDRESS OF MONOCHROME PARALLEL ADAPTER
	DW	0378H	; BASE ADDRESS STANDARD PARALLEL ADAPTER
	DW	0278H	; ADDRESS OF ALTERNATE PARALLEL ADAPTER
F4E	LABEL	WORD

POST2	ENDP
CODE	ENDS
	END

