;	[]===========================================================[]
;
;	NOTICE: THIS PROGRAM BELONGS TO AWARD SOFTWARE INTERNATIONAL(R)
;	        INC. IT IS CONSIDERED A TRADE SECRET AND IS NOT TO BE 	
;	        DIVULGED OR USED BY PARTIES WHO HAVE NOT RECEIVED	
;	        WRITTEN AUTHORIZATION FROM THE OWNER.
;
; 	[]===========================================================[]
;

;----------------------------------------------------------------------------
;Rev	Date	 Name	Description
;----------------------------------------------------------------------------
;R28	12/18/98 KGN	Add define for NS338 support LPT FDD , if choose LPT
;			is ECP Mode then we can't detect LPT Port
;R27	01/13/98 KEN	Fixed bug that WindowsNT can't recognize ISA/PNP modem
;			card "SupraExpress 336i PnP Modem" as COM3 device.
;R26	10/08/97 KVN	Remove CPINSTAL.ASM to XGROUP from EGROUP to reduce
;			compressed size for 2M BIOS code overflow (i.e. system
;			BIOS compressed code cover to decompress code)
;R25	06/20/97 LAW	Fixed Permedia 3Dlabs PCI VGA Use Com4 port test error
;R24	05/20/97 RAY	Somebody do not want the BIOS to touch game port since
;			it may cause their board to hang when some special add
;			on card is added. So add switch: No_Touch_Game_Port
;R23	10/17/96 KEN	Fixed some COMM ports can't be detected by Win95.
;R22	10/16/96 AVN	Special patch for NEXCOM com port
;R21	10/08/96 LRY	Out every parallel port with data FFh  (OPTIONAL)
;R20	04/08/96 TNY	Clear port data to zero after I/O port checking.
;R19	03/06/96 KGN	Before LPT detect, set port is output mode ,otherwise
;			LPT error after warm-boot with Keypro.
;R14C	11/09/95 KVN	Fixed MACH-32 PCI VGA screen become dark after test
;			COM4 port
;R18	11/01/95 DNL	Fixed LPT detect error bug
;R17	10/04/95 KEN	Split I/O port detection feature in CHECK_COMM and
;			CHECK_LPT for other procedure to call.
;R16	09/05/95 DNL	Support BIOS new structure
;R15	08/11/95 RCH	Fixed LPT port check error if one cable connect 
;			between two LPT ports for new UMC8663 super I/O
;R14B	07/26/95 RCH	The patch code cause CHECKIT COM4 data register fail
;			, and note that the ATI/MACH 32 always occupy addr.
;			of COM4.
;R14A	07/06/95 RCH	Fixed error coding of R14
;R12B	07/04/95 DNL	Fixed LPT detect error bug
;R14	06/30/95 AVN	Fixed MACH 32 PCI VGA Screen Dark After Test COM4.
;R13	06/13/95 KVN	Reduce Post_func_call and F000_call code size
;R12A	03/14/95 RCH	R12 still can not detect LPT port with FutureDomain
;			PNP/SCSI card installed
;R12	03/09/95 RCH	The current code can not detect parallel ports 
;			accurately, so test the LPT ports by using two 
;			different patterns
;R11A	03/06/95 DNL	Fixed LPT/COM detect error bug
;R11	02/13/95 AVN	Fixed LPT/COM Detect Error if Added Rising IDE Card.
;Rvv	01/24/95 AVN	Added Onboard I/O Detect by Auto.
;R10	01/20/95 DNL	Modify test pattern value to avoid the error of 
;			BIOS detect serial & parallel port.
;R09	12/27/94 RCH	Fixed error coding for "128k"
;			the complier will reference DS instead of ES.
;R08	09/21/94 RCH	Save more BIOS space
;R06	09/14/94 DNL	support 16550 UART
;R05	09/23/92 Alice  Added clear-bus codes & iodelay
;R04	04-DEC-91 TED  BF:Repoint DS segment to DGROUP to avoid the error of 
;			BIOS detect parallel port.
;R03	23-JUN-91 DRJ  FC:Added ifdef for extra checking for parallel port
;			scan as required for WD local bus ports, (plus added
;			severals newiodelays).
;R02B	31-MAY-91 KEB  NF:Made the serial and parallel detect/install routines
;			leave gaps in the BIOS data area tables which R02A
;			will fix up.
;R02A	31-MAY-91 KEB  NF:Added routine PACK_WDATA_TBL which packs the BIOS
;			data area I/O lists for COM and LPT.  This allows
;			the install routines to put the found serial and
;			parallel ports in their respective spots (I.E. com3 
;			in the third spot in the table).  This allows the
;			auto configure routines (if used) find and fill
;			any gaps.  The PACK routine will handle closing up
;			any remaining gaps.
;R01	05/20/91 JJ    FC:Removed FOUR_COMM flag since 4.2 BIOS always supports
;			4 COMs and 3 LPTs.
;R00	05/17/91 JJ    Initial release for 4.2 - from old ver. 2.5

		PAGE	56,132
		TITLE	CPINSTAL  
;R16.386
.386P						;R16
;		+-----------------------+
;		|			|
;		|    386 ROM/BIOS 	|
;		|			|
;		+-----------------------+

.XLIST
		INCLUDE BIOS.CFG
		INCLUDE BTROMSEG.EQU			;R26
		INCLUDE COMMON.EQU

		INCLUDE POST.EQU
		INCLUDE	LPT_PORT.EQU
		INCLUDE	SER_PORT.EQU
		INCLUDE GAMEPORT.EQU

		INCLUDE ATORGS.EXT
IFDEF     AUTO_CFG_COM							
		INCLUDE AUTO_CFG.EXT					
ELSEIFDEF AUTO_CFG_LPT							
		INCLUDE AUTO_CFG.EXT					
ENDIF	  ;AUTO_CFG_COM							

		INCLUDE COMMON.MAC
.LIST

;Rvv  - start
ifdef	AUTO_CFG_IO
;R13		extrn	F000_func_end:Near
;R13		extrn	F000_VECT:Near
		extrn	F000_call_proc:near	;R13
		extrn	GetItem_Value:near
		extrn	AUTO_IO_Item:near
		extrn	IO_CHIP_FUNC_DISABLE:near
		extrn	AUTO_CFG_IO_COM:near
		extrn	AUTO_CFG_IO_LPT:near
		extrn	F000_VECT:Near		;R16
		extrn	Ret_E_Seg:near		;R16
endif;	AUTO_CFG_IO
;Rvv - end
		extrn	xcall_proc:near		;R26

G_RAM		SEGMENT	USE16 AT 40H
		INCLUDE	G_RAM.INC
G_RAM		ENDS

EGROUP		GROUP	ECODE
ECODE		SEGMENT	USE16 PARA PUBLIC 'ECODE'
		ASSUME	CS:EGROUP,DS:G_RAM,ES:EGROUP

		PUBLIC	CP_INSTALL
CP_INSTALL	PROC	NEAR
		
;R26 start
ifdef CPINSTAL_IN_XGROUP

		Xcall	XCP_INSTALL
		ret
CP_INSTALL	ENDP
ECODE		ENDS

XGROUP		GROUP	XCODE
XCODE		SEGMENT	USE16 PARA PUBLIC 'XCODE'
		ASSUME	CS:XGROUP,DS:G_RAM,ES:XGROUP

XCP_INSTALL	PROC	NEAR

endif ;CPINSTAL_IN_XGROUP
;R26 end
		PUSH	DS
		PUSH	ES

		
;R08		call	Init_PRT_Wait_Cnt

;128k		push	cs
		push	0f000h	;128k
		pop	ds
;128k		ASSUME	DS:DGROUP
		ASSUME	DS:NOTHING		;R09
		
		mov	ax,G_RAM
		mov	es,ax
		ASSUME	ES:G_RAM

;R08 - start
;	Init printer wait constant in 40: area.
		mov	word ptr es:[PARL_PORT_TO_CNT],1414h
		mov	word ptr es:[PARL_PORT_TO_CNT+2],1414h
		mov	word ptr es:[COMM_PORT_TO_CNT],101h
		mov	word ptr es:[COMM_PORT_TO_CNT+2],101h
;R08 - end

		cld

IFDEF AUTO_CFG_COM							
;[]==================================================================[]
;
;	In an auto-detect situation we assume the following:
;
;	o The default/on-board COM ports can be assigned to any of the 
;	  four COM positions. 
;
;	o The default/on-board COM ports can be selected and deselected
;	  as desired.
;
;	o If the default/on-board serial controller supports more than
;	  four COM ports, these are not supported by the BIOS directly.
;
;	If this is correct, then these auto-detect routines may be used.
;	The algorithm is as follows:
;
;	1. Disable all default/on-board COM ports by using the routine
;	   Auto_Cfg_COM_Disable from AUTO_CFG.ASM
;	2. Starting at the COM1 address, look for a COM port. If it is
;	   present, place its address in the 40: area (G_RAM) 
;	   00-07h. If a COM port is not present, initialize its place
;	   to 0000h. (If AUTO_CFG_COM is not set, no gaps will be left
;	   in the table.)
;	3. Once all off-board COM ports have been enabled, call the
;	   routine Auto_Cfg_COM_Init in AUTO_CFG.ASM. This routine
;	   should look at the results in 40:00-07h. Wherever there
;	   is a 0000h entry, that is a COM port to enable.
;	4. CPINSTALL will then call PACK_WDATA_TBL to close up any	;R02A
;	   GAPS in the table						;R02A
;
;[]==================================================================[]

		call	Auto_Cfg_COM_Disable				
ENDIF ; AUTO_CFG_COM							

;Rvv - start
ifdef	AUTO_CFG_IO
		push	es
		mov	si,offset AUTO_IO_Item
		F000_Call GetItem_Value
		test	al,al
		jz	com_cfg_exit			; JMP If not AUTO
		mov	al,04h				; Disable COM Port
		F000_Call IO_CHIP_FUNC_DISABLE
com_cfg_exit:
		pop	es
endif;	AUTO_CFG_IO
;Rvv - end

;
;	Get a COM port address. If the COM port responds, place its
;	address in the table and increment to the next 40: location.
;
;	When complete, BH will contain the number of serial ports
;
;	For COM ports past the first 4, no address is stored in the
;	40: area.
;

		call	CHECK_COMM				;Rvv
;Rvv		mov	cx,4
;Rvv
;Rvv		cld
;Rvv
;Rvv		mov	si,offset Aux_Addrs		; si = word list of port addresses
;Rvv		mov	di,offset Comm_Port_Addrs	; di = 40: area list of serial ports
;Rvv		xor	bx,bx				; bl = COM presence mask, bh = number of serial ports
;Rvv
;Rvv		ALIGN	4
;Rvvck_comm:
;Rvv		lodsw				; get port address
;Rvv
;Rvv		mov	dx,ax			; dx = port address
;Rvv		newiodelay								;R03
;Rvv		in	al,dx			; get port status...
;Rvv;R06		test	al,0f8h			; any COM present?
;Rvv		test	al,038h			;R06
;Rvv;R10		jz	short cc_2		; yes...		
;Rvv;R10 - start
;Rvv		jnz	short @F
;Rvv		   
;Rvv		and	al,0C0h
;Rvv		or	al,al
;Rvv		jz	short cc_2
;Rvv		cmp	al,0C0h
;Rvv		je	short cc_2
;Rvv@@:
;Rvv;R10 - end
;Rvv
;Rvv;									
;Rvv;	When doing detect we leave a blank entry in the table		;R02B
;Rvv;									
;Rvv
;Rvv		xor	ax,ax						
;Rvv		jmp	short cc_21					
;Rvv
;Rvv;	Found a COM port
;Rvv
;Rvvcc_2:
;Rvv
;Rvv		mov	ax,dx			; ax = port address
;Rvv		dec	ax
;Rvv		dec	ax
;Rvv
;Rvv		inc	bh			; inc total COM ports found
;Rvv
;Rvvcc_21:										
;Rvv		cmp	di, offset PRNTR_PORT_ADDRS	; already at 4 COM ports?	
;Rvv		jae	short cc_22			; yes, no more room...		
;Rvv		stosw							
;Rvv
;Rvvcc_22:									
;Rvv		loop	short ck_comm

IFDEF AUTO_CFG_COM							
;									
;	Here we call the initialization routine.			
;									
; Auto_Cfg_COM_Init:							
;									
;	Enable all COM ports which were marked as empty, as desired.	
;									
; Entry:	BH	Total number of COM ports found so far		
;
; Exit:		BH	Updated number of COM ports			
;									
; Note:		Should also update the COM ports table in 40: area	
;									
									
		call	Auto_Cfg_COM_Init				
									
ENDIF ;AUTO_CFG_COM							

;Rvv - start
ifdef	AUTO_CFG_IO
		pusha
		xor	bl,bl
		mov	di,offset COMM_PORT_ADDRS	; di=COM ports 
		mov	cx,4
Get_Next_Dummy_COM:
		mov	ax,word ptr es:[di]		; test any COM port
		inc	di
		inc	di
		test	ax,ax
		jz	short @f
		mov	dl,10h
		shr	dl,cl
		or	bl,dl				; bl :bit0 Set => COM1
							;     bit1 Set => COM2
							;     bit2 Set => COM3
							;     bit3 Set => COM4
@@:
		loop	Get_Next_Dummy_COM
		F000_Call AUTO_CFG_IO_COM
		mov	bh,al
		popa
		call	CHECK_COMM
endif;	AUTO_CFG_IO
;Rvv - end

		push	bx		; save number of COM ports	

		mov	cx,4		;COM data table is 4 words	;R02A
		mov	di,offset Comm_Port_Addrs			;R02A
					; es:di = 40: COM ports list	;R02A
		call	pack_wdata_tbl					;R02A



IFDEF AUTO_CFG_LPT							
;[]==================================================================[]
;
;	In an auto-detect situation we assume the following:
;
;	o The default/on-board LPT ports can be selected and deselected
;	  as desired.
;
;	o If the default/on-board parallel controller supports more than
;	  three LPT ports, these are not supported by the BIOS directly.
;
;	If this is correct, then these auto-detect routines may be used.
;	The algorithm is as follows:
;
;	1. Disable all default/on-board COM ports by using the routine
;	   Auto_Cfg_LPT_Disable from AUTO_CFG.ASM
;	2. Starting at the LPT1 address, look for a LPT port. If it is
;	   present, place its address in the 40: area (G_RAM) 
;	   08-0Dh. If an LPT port is not present, initialize its place
;	   to 0000h. (If AUTO_CFG_COM is not set, no gaps will be left
;	   in the table.)
;	3. Once all off-board LPT ports have been enabled, call the
;	   routine Auto_Cfg_LPT_Init in AUTO_CFG.ASM. This routine
;	   should look at the results in 40:08-0Dh. Wherever there
;	   is a 0000h entry, that is a COM port to enable.
;
;[]==================================================================[]

		call	Auto_Cfg_LPT_Disable				
ENDIF ; AUTO_CFG_LPT							

;Rvv - start
ifdef	AUTO_CFG_IO
		push	es
		mov	si,offset AUTO_IO_Item
		F000_Call GetItem_Value
		test	al,al
		jz	lpt_cfg_exit			; JMP If not AUTO
		mov	al,08h				; Disable COM Port
		F000_Call IO_CHIP_FUNC_DISABLE
lpt_cfg_exit:
		pop	es
endif;	AUTO_CFG_IO
;Rvv - end
;
;	Get an LPT port address. If the LPT port responds, place its
;	address in the table and increment to the next 40: location.
;
;	When complete, BH will contain the number of parallel ports and
;
;	For LPT ports past the first 3, no address is stored in the
;	40: area.
;

		call	CHECK_LPT				;Rvv
;Rvv;128k		mov	ax,DGROUP				;R04
;Rvv		mov	ax,0f000h
;Rvv		mov	ds,ax					;R04
;Rvv;128k		assume	ds:DGROUP				;R04
;Rvv
;Rvv		mov	si,offset Aux_Prn_Addrs
;Rvv		mov	di,offset Prntr_Port_Addrs
;Rvv
;Rvv		mov	cx,3				; maximum number of LPTs
;Rvv		xor	bx,bx				; bh = number of parallel
;Rvv
;Rvv		ALIGN	4
;Rvvck_prn:		
;Rvv		lodsw
;Rvv
;Rvv		mov	dx,ax			; dx = port address
;Rvv;R10		mov	ax,0aaaah
;Rvv		mov	ax,05a5ah		;R10
;Rvv		newiodelay								;R03
;Rvv		out	dx,al			; write out test value
;Rvv		NEWIODELAY
;Rvv		;clear bus	      		;R05
;Rvv		xor	al,al			;R05
;Rvv		newiodelay			;R05
;Rvv
;Rvv;R03 - Begin
;RvvIFDEF	ENABLE_LPT_EXTRA_TEST
;Rvv		in	al,dx			; read pattern
;Rvv		not	ax			; modify pattern
;Rvv		newiodelay			; let newiodelay write modified pattern
;Rvv		not	ax			; restore pattern
;Rvv		in	al,dx			; read pattern twice to be sure
;Rvv		newiodelay
;RvvENDIF	;ENABLE_LPT_EXTRA_TEST
;Rvv;R03 - End
;Rvv		in	al,dx			; read in test value
;Rvv		NEWIODELAY			;R05
;Rvv		cmp	al,ah			; parallel port present?
;Rvv		je	short cp_2		; yes...
;Rvv
;Rvv;									
;Rvv;	When doing detect we leave a blank entry in the table		;R02B
;Rvv;									
;Rvv
;Rvv		xor	ax,ax						
;Rvv		jmp	short cp_21					
;Rvv									
;Rvv
;Rvvcp_2:
;Rvv		inc	bh
;Rvv		mov	ax,dx
;Rvv
;Rvvcp_21:
;Rvv		stosw				; save port address
;Rvv
;Rvvcp_22:
;Rvv		loop	short ck_prn

IFDEF AUTO_CFG_LPT
;									
;	Here we call the initialization routine.			
;									
; Auto_Cfg_LPT_Init:							
;									
;	Enable all LPT ports which were marked as empty, as desired.	
;									
; Entry:	BH	Total number of LPT ports found so far		
;
; Exit:		BH	Updated number of LPT ports			
;									
; Note:		Should also update the LPT ports table in 40: area	
;									
									
		call	Auto_Cfg_LPT_Init				
ENDIF ;AUTO_CFG_LPT							

;Rvv - start
ifdef	AUTO_CFG_IO
		push	bx
		push	di
		xor	bl,bl
		mov	di,offset Prntr_Port_Addrs
		mov	cx,3
Get_Next_Dummy_LPT:
		mov	ax,word ptr es:[di]		; test any COM port
		inc	di
		inc	di
		test	ax,ax
		jz	short @f
		mov	dl,08h
		shr	dl,cl
		or	bl,dl				; bl :bit0 Set => LPT1
							;     bit1 Set => LPT2
							;     bit2 Set => LPT3
@@:
		loop	Get_Next_Dummy_LPT
		F000_Call AUTO_CFG_IO_LPT
		mov	bh,al
		pop	di
		pop	bx
		call	CHECK_LPT
endif;	AUTO_CFG_IO
;Rvv - end
		mov	cx,3			; maximum number of LPTs;R02A
		mov	di,offset Prntr_Port_Addrs			;R02A
					; es:di = 40:LPT ports list	;R02A
		call	pack_wdata_tbl					;R02A

		pop	ax			; ah = # of COM ports

		shl	bh,6			; LPT ports = bits 14-15
		shl	ah,1
		or	bh,ah			; COM ports = bits 11-9
		xor	bl,bl
		or	es:Hardware,bx		;128k
;128k		or	Hardware,bx		; set com and prn ports

IFDEF AUTO_CFG_GAME							
		call	Auto_Cfg_Game_Disable				
ENDIF ;AUTO_CFG_GAME

ifndef	No_Touch_Game_Port				;R24
		mov	dx,GAME_DATA_PORT
		in	al,dx			; look for game card

		test	al,0fh
		jnz	short game_not_present

IFDEF AUTO_CFG_GAME							
		call	Auto_Cfg_Game_Init				
ENDIF ;AUTO_CFG_GAME							

		or	es:Hardware,1000h    	;R09
;R09		or	Hardware,1000h		;128k
;128k		or	Hardware,1000h		; set game card
		jmp	short CP_Install_Ret				
									
game_not_present:							
endif	;No_Touch_Game_Port				;R24

cp_install_ret:
		pop	es	     	
		pop	ds

		ret
ifdef CPINSTAL_IN_XGROUP	;R26
XCP_INSTALL	ENDP		;R26
else ;CPINSTAL_IN_XGROUP	;R26
CP_INSTALL	ENDP
endif ;CPINSTAL_IN_XGROUP	;R26


;R08 ;[]==============================================================[]
;R08 ;
;R08 ; Init_PRT_Wait_Cnt:
;R08 ;
;R08 ;	Init printer wait constant in 40: area.
;R08 ;
;R08 ;Saves:	All
;R08 ;
;R08 ;Entry:	NONE
;R08 ;Exit:	NONE
;R08 ;
;R08 ;Author: Award
;R08 ;Date:   05/22/90
;R08 ;
;R08 ; Name | Date	    | Description
;R08 ; ---------------------------------------------------------------
;R08 ; DC   | 30-May-90   | Init for EISA 4.0 
;R08 ;
;R08 ;[]==============================================================[]
;R08 
;R08 INIT_PRT_WAIT_CNT PROC	NEAR
;R08 		push	ax
;R08 		push	ds
;R08 		mov	ax,G_RAM
;R08 		mov	ds,ax
;R08 		assume	ds:G_RAM
;R08 		mov	word ptr ds:[PARL_PORT_TO_CNT],1414h
;R08 		mov	word ptr ds:[PARL_PORT_TO_CNT+2],1414h
;R08 		mov	word ptr ds:[COMM_PORT_TO_CNT],101h
;R08 		mov	word ptr ds:[COMM_PORT_TO_CNT+2],101h
;R08 		pop	ds
;R08 		pop	ax
;R08 		ret
;R08 INIT_PRT_WAIT_CNT	ENDP

;R02A Begin-								;R02A
;[]==============================================================[]
;
; PACK_WDATA_TBL:
;
;	Packs a table of words to contain no gaps.  Useful for tables 
;	 of I/O addresses in the 40: area for devices such as the serial 
;	 and parallel port.
;
;Saves:	All 
;
;Entry:	ES:DI = begin of table to pack
;	CX    = no. of word entries
;
;Exit:	NONE
;
;Author: Award
;Date:   05/22/90
;
; Name | Date	    | Description
; ---------------------------------------------------------------
; KEB  | 17-May-91  | Initial for 4.0 
;
;[]==============================================================[]

PACK_WDATA_TBL	proc	near

		push	ax
		push	si
		push	ds

;R08		mov	ax, es
;R08		mov	ds, ax		; point DS to table also

		push	es		; R08
		pop	ds		; R08

		xor	ax, ax		; Set AX for GAP value to look for

PACK_WDATA_loop:
		push	di		; preserve passed values
		push	cx		;  for latter
		
;	ES:DI points to begin of table and CX has the word count
;	 now look for the first zero entry (AX is zero)

		repne	scasw		; look for first gap

;	Now if see if CX is zero to see if we are at the end of the table

		or	cx, cx		; End of table??
		jz	short PACK_WDATA_TBL_exit ;Yes... table was FULL

;	CX was non-zero, we have found a gap so preserve the address

		mov	si, DI		; store address of gap
		sub	si, 2		; fix it to point TO the gap

;	and look for the next filled entry in the table

		repe	scasw		; look for next filled entry

;	Now check if zero flag is set to see if we are at the end 
;	 of the table

		jz	short PACK_WDATA_TBL_exit ;Yes... table had no gaps!
	
;	Zero flag was clear so we have found a filled entry.
;	 Now need to move it to the gap. SI points to gap and DI points
;	 to entry+2 BUT we need SI to point to entry and DI to point to
;	 the GAP for the MOVSW to work SO...

		sub	di, 2		; POINT DI to the correct place
		xchg	si, di		; set up for movsw-swap SI & DI
		movsw			; move entry to gap
		mov	word ptr[si-2], 0 ; clear old entry

		pop	cx
		pop	di	
		jmp	short	pack_wdata_loop ;go do it again


PACK_WDATA_TBL_exit:

		pop	cx
		pop	di

		pop	ds	
		pop	si
		pop	ax
		ret	

PACK_WDATA_TBL	endp
;R02A -End								;R02A

;Rvv - start
;=====================================================================
;
;	Get a COM port address. If the COM port responds, place its
;	address in the table and increment to the next 40: location.
;
;	When complete, BH will contain the number of serial ports
;
;	For COM ports past the first 4, no address is stored in the
;	40: area.
;=====================================================================
CHECK_COMM	proc	near
		mov	cx,4

		cld

		mov	si,offset Aux_Addrs		; si = word list of port addresses
		mov	di,offset Comm_Port_Addrs	; di = 40: area list of serial ports
		xor	bx,bx				; bl = COM presence mask, bh = number of serial ports

		ALIGN	4
ck_comm:
		lodsw				; get port address

		mov	dx,ax			; dx = port address
		call	Test_COMM		;R17
		jz	short cc_2		;R17
;R17		mov	al,38h			;R11A
;R17		out	dx,al			;R11A
;R17		iodelay				;R11A
;R17;R11		newiodelay								;R03
;R17		in	al,dx			; get port status...
;R17;R11		newiodelay								;R11
;R17		iodelay				; R11
;R17;R06		test	al,0f8h			; any COM present?
;R17		test	al,038h			;R06
;R17;R10		jz	short cc_2		; yes...		
;R17;R10 - start
;R17		jnz	short @F
;R17		   
;R17		and	al,0C0h
;R17		or	al,al
;R17		jz	short cc_2
;R17		cmp	al,0C0h
;R17		je	short cc_2
;R17@@:
;R10 - end

;									
;	When doing detect we leave a blank entry in the table		;R02B
;									

		xor	ax,ax						
		jmp	short cc_21					

;	Found a COM port

cc_2:

		mov	ax,dx			; ax = port address
		dec	ax
		dec	ax

		inc	bh			; inc total COM ports found

cc_21:										
		cmp	di, offset PRNTR_PORT_ADDRS	; already at 4 COM ports?	
		jae	short cc_22			; yes, no more room...		
		stosw							

cc_22:									
		loop	short ck_comm

;R14A		mov	dx,2e8h				;R14
;R14B		mov	dx,2eAH				;R14A
;R14B		mov	al,0ffh				;R14
;R14B		out	dx,al				;R14
;R14B		iodelay					;R14

		ret
CHECK_COMM	endp

;R17 - start
;[]==============================================================[]
; Input:	DX = Serial port base address + 2
; Output:	ZF = 1 Serial port found
;		ZF = 0 Serial port not found
;[]==============================================================[]
		public	Test_COMM
Test_COMM	proc	near
		mov	al,38h
		out	dx,al
		iodelay
		in	al,dx			; get port status...
		iodelay
		push	ax			;R23
		xor	al, al			;R23
		out	dx, al			;R23
		pop	ax			;R23
;R14C start
		cmp	al,0ffh			;no port present ?	;R27
		je	short NoComPort					;R27
		cmp	al,38h			;COMM port exist?
		jne	short @F		;Yes,jump
NoComPort:								;R27
		or	al,0ffh			;No,Out value 0ffh to port and
						;Report serial port not found
		out	dx,al
		ret
@@:
;R14C end
;R25ifdef	NEXCOM_SPECIAL_COM_PORT			;R22
;R25		test	al,018h			;R22
;R25else	;NEXCOM_SPECIAL_COM_PORT		;R22
;R25		test	al,038h
;R25endif	;NEXCOM_SPECIAL_COM_PORT		;R22
;R25		jnz	short @F
;R25
;R25		and	al,0C0h
;R25		or	al,al
;R25		jz	short @f
;R25		cmp	al,0C0h
;R25@@:
;R25 -	start
		push	dx			;save comm port address
		inc	dx			;set dx to regist B 
		in	al,dx						;R27
		push	ax			;save register B	;R27
		push	dx						;R27
		mov	al, 80h			;set BDLAB
		out	dx, al			
		and	dl, 0f8h		;set dx to transmitter regist
		mov	al, 55h			
		out	dx, al			;seend dx 55h for check comm test
		inc	dx			;set dx to interrupt control
		xor	al, al			;clear interrupt control
		out	dx, al			
		dec	dx			;set dx to receiver buffer regist
		in	al, dx			;read receiver buffer regist
		cmp	al, 55h			;compler comm post data	;R27
		pop	dx						;R27
		pop	ax						;R27
		out	dx,al			;restore register B	;R27
		pop	dx
;R27		cmp	al, 55h			;compler comm post data
		ret
;R25 - end
		ret
Test_COMM	endp
;R17 - end

;=====================================================================
;
;	Get an LPT port address. If the LPT port responds, place its
;	address in the table and increment to the next 40: location.
;
;	When complete, BH will contain the number of parallel ports and
;
;	For LPT ports past the first 3, no address is stored in the
;	40: area.
;
;=====================================================================
CHECK_LPT	proc	near
;R12		mov	ax,0f000h
;R12		mov	ds,ax					;R04
;R12
;R12		mov	si,offset Aux_Prn_Addrs
;R12		mov	di,offset Prntr_Port_Addrs
;R12
;R12		mov	cx,3				; maximum number of LPTs
;R12		xor	bx,bx				; bh = number of parallel
;R12
;R12		ALIGN	4
;R12ck_prn:		
;R12		lodsw
;R12
;R12		mov	dx,ax			; dx = port address
;R12;R10		mov	ax,0aaaah
;R12		mov	ax,05a5ah		;R10
;R12;R11		newiodelay								;R11
;R12		iodelay				; R11
;R12		out	dx,al			; write out test value
;R12;R11		newiodelay								;R11
;R12		iodelay				; R11
;R12		;clear bus	      		;R05
;R12		xor	al,al			;R05
;R12;R11		newiodelay								;R11
;R12;R11A		iodelay				; R11
;R12		NEWIODELAY			;R11A
;R12
;R12;R03 - Begin
;R12IFDEF	ENABLE_LPT_EXTRA_TEST
;R12		in	al,dx			; read pattern
;R12		not	ax			; modify pattern
;R12;R11		newiodelay								;R11
;R12		iodelay				; R11
;R12		not	ax			; restore pattern
;R12		in	al,dx			; read pattern twice to be sure
;R12;R11		newiodelay								;R11
;R12		iodelay				; R11
;R12ENDIF	;ENABLE_LPT_EXTRA_TEST
;R12;R03 - End
;R12		in	al,dx			; read in test value
;R12;R11		newiodelay								;R11
;R12		iodelay				; R11
;R12		cmp	al,ah			; parallel port present?
;R12		je	short cp_2		; yes...
;R12
;R12;									
;R12;	When doing detect we leave a blank entry in the table		;R02B
;R12;									
;R12
;R12		xor	ax,ax						
;R12		jmp	short cp_21					
;R12									
;R12
;R12cp_2:
;R12		inc	bh
;R12		mov	ax,dx
;R12
;R12cp_21:
;R12		stosw				; save port address
;R12
;R12cp_22:
;R12		loop	short ck_prn

;R12 - start
		mov	ax,0f000h
		mov	ds,ax					

		mov	si,offset Aux_Prn_Addrs
		mov	di,offset Prntr_Port_Addrs

		mov	cx,3				; maximum number of LPTs
		xor	bx,bx				; bh = number of parallel

		ALIGN	4
ck_prn:		

;R15 - start
;Set data of all LPT ports to 0FFH to avoid ramdom output driving LPT bus,
;because the UMC8663 input data port reading from LPT bus instead of internal
;register value. Note, this only happen on new version of UMC8663 (08/11/95)
;and must have a cable connect between two LPT ports.
		lodsw				;R17
		mov	dx,ax			;R17
		call	Test_LPT		;R17
		jz	short cp_2		;R17
;R17		pusha
;R17Init_Next_Port:
;R17		lodsw				;load LPT port
;R17		mov	dx,ax
;R17		mov	al,0ffh			;clear LPT bus data
;R17		out	dx,al
;R17		loop	short Init_Next_Port	;next port to clear
;R17		popa
;R17;R15 - end
;R17
;R17		lodsw
;R17		mov	dx,ax			; dx = port address
;R17
;R17;R12A		mov	ax,05a5aH		;first pattern 
;R17		mov	al,05aH			;first pattern 		;R12A
;R17		call	Chk_Port_Exist
;R17		jne	short No_LptPort	;no
;R17
;R17;R12A		mov	ax,0aaaaH		;first pattern 
;R17;R12B		mov	al,0aaH			;first pattern 		;R12A
;R17		mov	al,0a5H			;first pattern 		;R12B
;R17		call	Chk_Port_Exist
;R17		je	short cp_2		;yes
;R17
;R17No_LptPort:
;									
;	When doing detect we leave a blank entry in the table		
;									

		xor	ax,ax						
		jmp	short cp_21					
									

cp_2:
		inc	bh
		mov	ax,dx

cp_21:
		stosw				; save port address

cp_22:
		loop	short ck_prn
;R12 - end
		ret
CHECK_LPT	endp
;Rvv - end

;R17 - start
;[]==============================================================[]
; Input:	DX = Parallel port base address
; Output:	ZF = 1 Parallel port found
;		ZF = 0 Parallel port not found
;[]==============================================================[]
		public	Test_LPT
Test_LPT	proc	near
		mov	al,0ffh			;clear LPT bus data
		out	dx,al
;R19 - Start
		add	dx, 2			;control register
		in	al, dx			;control register value
		and	al, 11011111b		;set output mode
		out	dx, al
		sub	dx, 2			;data register
;R19 - End
ifdef	PARALLEL_PORT_DATA_FF					;R21
		mov	al,05Fh			;first pattern	;R21
else	;PARALLEL_PORT_DATA_FF					;R21
		mov	al,05Ah			;first pattern
endif	;PARALLEL_PORT_DATA_FF					;R21
ifdef	Special_Value_For_LPT_Test				;R28
		mov	al,Special_Value_For_LPT_Test		;R28
endif	;Special_Value_For_LPT_Test				;R28
		call	Chk_Port_Exist
		jne	short @f		;no

ifdef	PARALLEL_PORT_DATA_FF					;R21
		mov	al,0AFh			;second pattern	;R21
else	;PARALLEL_PORT_DATA_FF					;R21
		mov	al,0A5h			;second pattern
endif	;PARALLEL_PORT_DATA_FF					;R21
ifdef	Special_Value_For_LPT_Test				;R28
		mov	al,Special_Value_For_LPT_Test		;R28
endif	;Special_Value_For_LPT_Test				;R28
		call	Chk_Port_Exist
@@:
		ret
Test_LPT	endp
;R17 - end

;R12 - start
;Input : AL - pattern to test
Chk_Port_Exist:
		out	dx,al			;write pattern
;R18		NEWIODELAY
		mov	ah,al			;R12A
		xor	al,al			;R18
		NEWIODELAY			;R18

		in	al,dx			;read in port value
		NEWIODELAY
		cmp	ah,al			;port existed ?

ifdef	PARALLEL_PORT_DATA_FF					;R21
		mov	al,0FFh					;R21
else	;PARALLEL_PORT_DATA_FF					;R21
		mov	al,0			;R20
endif	;PARALLEL_PORT_DATA_FF					;R21
		out	dx,al			;R20
		NEWIODELAY			;R20

		ret
;R12 - end

ifdef CPINSTAL_IN_XGROUP	;R26
XCODE		ENDS		;R26
else ;CPINSTAL_IN_XGROUP	;R26
ECODE		ENDS
endif ;CPINSTAL_IN_XGROUP	;R26
		END
