$genonly
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'	TITLE: bcico.inc
%'	Date:	12 Sept 1983
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'	Bootstrap Loader  and Bootstrap Loader UTILITY MACROS AND LITERALS
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%DEFINE(FALSE)(0)%'
%DEFINE(TRUE)(0FFH)%'
%DEFINE(no_cntr_code)(0)%'
%DEFINE(c8253_code)(1)%'
%DEFINE(c80186_code)(2)%'
%DEFINE(c82530_code)(3)%'
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'  TRIM(a) - returns the input parameter trimmed of leading and
%'	 trailing blanks.
%*DEFINE(TRIM(a)) LOCAL x y (%MATCH( x y)(%a)%x)%'
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'   ARG -  gets the next comma-delimited arg from variable named TAIL,
%'	stripped and trimmed.  Any macro that has a valid type of NONE
%'	uses this macro so that the other parameters are not needed.
%*DEFINE(ARG) LOCAL a (%MATCH(a,tail)(%tail)%TRIM(%a))%'
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'  ADD_DEV_INIT - places device initialization data into segment.
%SET(dev_cnt,0)%'	set to 0 when file read
%*DEFINE(ADD_DEV_INIT(d1,d2,d3,d4))(%'
dev_init<%d1,%d2,%d3,%d4>
%SET(dev_cnt,%dev_cnt+1))%'
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'  This is the structure that add_dev_init fills in.  All non-serial
%'   channel init uses this data form.
dev_init	struc
	port			DW	?
	byte_port		DB	?
	value			DW	?
	delay			DW	?
dev_init	ends
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'	TITLE:   SERIAL_CHANNEL
%'	INPUTS:  SER_TYPE - the type of Serial Device used.
%'		SER_BASE - the base port of the Serial Device.
%'		SER_PORT_DELTA - the spacing of the Serial Device ports
%'
%'		CNTR_TYPE - the type of Timer connected to the USART
%'		CNTR_BASE - the numerically lowest port in the
%'		timer connected to the Serial Device clock input.
%'		CNTR_PORT_DELTA - the spacing of the Baud Rate timers ports
%'		CNTR_BAUD_COUNTER - the counter in the Timer used for
%'		USART clock input, only values 0-2 are valid.
%'		MAX_BAUD_RATE_COUNT - count to generate 9600 baud.
%'	OUTPUTS:A table of structures of the data:
%'		SERIAL_DATA_PORT - the I/O port of the Serial Device.
%'		SERIAL_STATUS_PORT - the status port of the Serial Device.
%'		TXRDY_MASK - the txrdy mask for the USART.
%'		RXRDY_MASK - the rxrdy mask for the USART.
%'		TXINT_RESET_MASK - mask to reset TX int bit.
%'				Only 8274 uses it, others are null.
%'		CNTR_CONTROL_PORT - the timer control port
%'		CNTR_PORT_A - the counter port connected to
%'		the USART.
%'		CNTR_PORT_B - the counter port connected to
%'		the USART when 80186 counters are used.
%'		CNTR_MODE - the control word used to program
%'		the Baud Rate Timer.
%'		BAUD_RATE_COUNT - count to generate the default Baud Rate.
%'	Additionally, the following constants are declared in the
%'	code segment:
%'		SERIAL_EXISTS - a boolean indicating whether or not
%'		the monitor is used in a system with a serial port.
%'	ABSTRACT:
%'	This macro defines all aspects of a Serial Channel - the
%'	serial device, the Baud Rate timer and count.  This macro may be
%'	invoked any number of times to define all the serial channels
%'	in the system.
%'	The programming words are hard-wired in the configuration
%'	macro since it is felt that these will not need to
%'	change.  If they do, change those values here accordingly.
%'	TTY mode is not supported by the iAPX 86, 88 monitor.  The 
%'	supported serial devices are the 8251A, 82530, 8274 and NONE.  The
%'	supported Baud Rate timers are 8253/4, 82530, 80130 and 80186.
%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*


%SET(first_ser_ch,%TRUE)%'	set to ff when the file is read.
%SET(ser_ex,%FALSE)%'		set to 0 when the file is read.
%*DEFINE(SERIAL_CHANNEL(parameters))(%DEFINE(tail)(%parameters)%'
%DEFINE(ser_type)(%ARG)%'

%' *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'
%'	The following code is assembled in-line when serial_channel
%'	is invoked

code		ends

cgroup	group	code, boot_dev_init

assume	cs:cgroup, ds:data

;
;	The following labels in the init segments must be the first
;	items in the segments because they are used to form pointers.
;

boot_dev_init	segment	public	'CODE'

bdev_init_table	label	WORD
		PUBLIC	bdev_init_table,bdev_init_len,bdev_init_struc_len

boot_dev_init	ends


code	segment	public	'CODE'
		PUBLIC	bser_init_table
		PUBLIC  bsio_data_port, bsio_status_port
		PUBLIC	bsio_txrdy, bsio_rxrdy
		PUBLIC	bsio_tx_int_reset
code	ends

            assume cs:code, ss:stack, ds:data
code		segment				;

%IF ((%EQS(%ser_type,none)) OR (%EQS(%ser_type,NONE))) THEN (%'
$eject
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;
;	There is no Serial Channel in this configuration.
;
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%'	'%IF(%first_ser_ch) THEN(%'
%'		'%SET(ser_ex,%TRUE)%'
%'		'%SET(first_ser_ch,%FALSE)%'
PUBLIC	bserial_exists

code	segment
bserial_exists	DB	%FALSE
code	ends
%'	')FI%'
) ELSE (%'
$eject
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
;
;	%ser_type Serial Channel Public Constants
;
; *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
%DEFINE(ser_base)(%ARG)%'
%DEFINE(ser_p_del)(%ARG)%'
%DEFINE(cntr_type)(%ARG)%'
%DEFINE(cntr_base)(%ARG)%'
%DEFINE(cntr_p_del)(%ARG)%'
%DEFINE(br_cntr)(%ARG)%'
%DEFINE(max_cnt)(%ARG)%'
%'
%IF ((%EQS(%ser_type,8251A)) OR (%EQS(%ser_type,8251a))) THEN (%'
%'	'%IF(%first_ser_ch) THEN(%'
%'		'%SET(ser_ex,%TRUE)%'
%'		'%SET(first_ser_ch,%FALSE)%'
PUBLIC	bserial_exists

code	segment
bserial_exists	DB	%TRUE
code	ends

%'	')FI%'
%'	'%IF (%ser_p_del le 0h ) THEN (%'
ERROR -- Invalid port delta for the %ser_type Serial Channel
%'	')FI%'
%DEFINE(sio_tx)(01h)%'
%DEFINE(sio_rx)(02h)%'
%DEFINE(sio_tx_res)(0)%'
%DEFINE(sio_data_p)(%ser_base)%'
%DEFINE(sio_stat_p)(%ser_base + %ser_p_del)%'

boot_dev_init	segment
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,80h,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,40h,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,4eh,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,37h,1)
boot_dev_init	ends
) ELSE (%IF (%EQS(%ser_type,8274)) THEN (%'
%'	'%IF(%first_ser_ch) THEN(%'
%'		'%SET(ser_ex,%TRUE)%'
%'		'%SET(first_ser_ch,%FALSE)%'
PUBLIC	bserial_exists

code	segment
bserial_exists	DB	%TRUE
code	ends

%'	')FI%'
%'	'%IF (%ser_p_del le 0h) THEN (%'
ERROR -- Invalid port delta for the %ser_type Serial Channel
%'	')FI%'
%DEFINE(sio_tx)(04h)%'
%DEFINE(sio_rx)(01h)%'
%DEFINE(sio_tx_res)(28h)%'
%DEFINE(sio_data_p)(%ser_base)%'
%DEFINE(sio_stat_p)(%ser_base + (2 * %ser_p_del))%'

boot_dev_init	segment
%ADD_DEV_INIT(%sio_stat_p,%TRUE,18h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,18h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,4h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,44h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,5h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0eah,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,3h,0)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0c1h,0)
boot_dev_init	ends
) ELSE (%IF (%EQS(%ser_type,82530)) THEN (%'
%'	'%IF(%first_ser_ch) THEN(%'
%'		'%SET(ser_ex,%TRUE)%'
%'		'%SET(first_ser_ch,%FALSE)%'
PUBLIC	bserial_exists

code	segment
bserial_exists	DB	%TRUE
code	ends

%'	')FI%'
%'	'%IF (%ser_p_del le 0h) THEN (%'
ERROR -- Invalid port delta for the %ser_type Serial Channel
%'	')FI%'
%DEFINE(sio_tx)(04h)%'
%DEFINE(sio_rx)(01h)%'
%DEFINE(sio_tx_res)(28h)%'
%DEFINE(sio_data_p)(%ser_base + %ser_p_del)%'
%DEFINE(sio_stat_p)(%ser_base)%'
%DEFINE(ch_res)(%ARG)%'

boot_dev_init	segment
%ADD_DEV_INIT(%sio_stat_p,%TRUE,9,1)
%'		select the correct channel reset
%'	'%IF ((%EQS(%ch_res,A)) OR (%EQS(%ch_res,a))) THEN (%'
%'	'%ADD_DEV_INIT(%sio_stat_p,%TRUE,080h,2)
%'	') ELSE (%'
%'	'%IF ((%EQS(%ch_res,B)) OR (%EQS(%ch_res,b))) THEN (%'
%'	'%ADD_DEV_INIT(%sio_stat_p,%TRUE,040h,2)
%'	') ELSE (%'
ERROR -- 82530 channel must be specified as A or B only
%'	')FI )FI%'
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,4,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,44h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,1,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,2,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%'	leave Rx disabled until the timers are initialized.
%ADD_DEV_INIT(%sio_stat_p,%TRUE,3,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0c0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,5,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0eah,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,6,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,7,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,9,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,10,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,11,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,52h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,14,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,02h,1)
%'
%ADD_DEV_INIT(%sio_stat_p,%TRUE,15,1)
%ADD_DEV_INIT(%sio_stat_p,%TRUE,0h,1)
boot_dev_init	ends
) ELSE (%'
ERROR -- %ser_type is an invalid Serial Channel type
%DEFINE(sio_tx)(0)%'
%DEFINE(sio_rx)(0)%'
%DEFINE(sio_tx_res)(0)%'
%DEFINE(sio_data_p)(0)%'
%DEFINE(sio_stat_p)(0)%'
)FI )FI )FI%'
%'
%'********************  counter config. section  ******************
%IF ((%EQS(%cntr_type,none)) OR (%EQS(%cntr_type,NONE))) THEN (%'
%'	'%DEFINE(cntr_ctl_p)(0)%'
%'	'%DEFINE(cntr_p_a)(0)%'
%'	'%DEFINE(cntr_p_b)(0)%'
%'	'%DEFINE(cntr_code)(%no_cntr_code)%'
%'	'%DEFINE(cntr_mode)(0)%'
) ELSE (%'
%IF (%LEN(%cntr_p_del) eq 0) THEN (%SET(cntr_p_del,0))FI%'
%IF (%LEN(%br_cntr) eq 0) THEN (%SET(br_cntr,0))FI%'
%IF (%cntr_p_del le 0h) THEN (%'
ERROR -- Invalid port delta for the Baud Rate Timer
)FI%'
%IF ((%EQS(%cntr_type,8253)) OR (%EQS(%cntr_type,8254))) THEN (%'
%'	'%SET(cntr_ctl_p,(%cntr_base +(3 * %cntr_p_del)))%'
%'	'%DEFINE(cntr_code)(%c8253_code)%'
%'	'%IF (%br_cntr eq 0) THEN (%'
%'		'%DEFINE(cntr_p_a)(%cntr_base)%'
%'		'%DEFINE(cntr_p_b)(0)%'
%'		'%DEFINE(cntr_mode)(036h)%'
%'	') ELSE (%'
%'	'%IF (%br_cntr eq 1) THEN (%'
%'		'%DEFINE(cntr_p_a)(%cntr_base + %cntr_p_del)%'
%'		'%DEFINE(cntr_p_b)(0)%'
%'		'%DEFINE(cntr_mode)(076h)%'
%'	') ELSE (%'
%'	'%IF (%br_cntr eq 2) THEN (%'
%'		'%DEFINE(cntr_p_a)(%cntr_base + (2 * %cntr_p_del))%'
%'		'%DEFINE(cntr_p_b)(0)%'
%'		'%DEFINE(cntr_mode)(0b6h)%'
%'	') ELSE (%'
ERROR -- 8253/4 Baud Rate Counter number is not 0, 1 or 2.
%'	')FI )FI )FI
) ELSE (%'
%IF(%EQS(%cntr_type,80130))THEN (%'                         80130 TIMER USED
%'	'%IF (%br_cntr eq 2) THEN (%'
%'		'%DEFINE(cntr_ctl_p)(%cntr_base + (7 * %cntr_p_del))%'
%'		'%DEFINE(cntr_p_a)(%cntr_base + (6 * %cntr_p_del))%'
%'		'%DEFINE(cntr_p_b)(0)%'
%'		'%DEFINE(cntr_code)(%c8253_code)%' treat 80130 as 8253
%'		'%DEFINE(cntr_mode)(0b6h)%'
%'	') ELSE (%'
ERROR -- Counter 2 is the only valid 80130 Baud Rate Counter
%'	')FI
) ELSE (%'
%IF ((%EQS(%cntr_type,80186)) OR (%EQS(%cntr_type,80188))) THEN (%'
%'	'%DEFINE(cntr_mode)(0c003h)
%'	'%DEFINE(cntr_code)(%c80186_code)%'
%'	'%IF (%br_cntr eq 0) THEN (%'
%'		'%DEFINE(cntr_ctl_p)(%cntr_base + 56h)%'
%'		'%DEFINE(cntr_p_a)(%cntr_base + 52h)%'
%'		'%DEFINE(cntr_p_b)(%cntr_base + 54h)%'
%'	') ELSE (%'
%'	'%IF (%br_cntr eq 1) THEN (%'
%'		'%DEFINE(cntr_ctl_p)(%cntr_base + 5eh)%'
%'		'%DEFINE(cntr_p_a)(%cntr_base + 5ah)%'
%'		'%DEFINE(cntr_p_b)(%cntr_base + 5ch)%'
%'	') ELSE (%'
ERROR -- 80186 counter %br_cntr is not a valid Baud Rate Counter.
%'	')FI )FI %'
) ELSE (%'
%IF (%EQS(%cntr_type,82530)) THEN (%'
%'	'%DEFINE(cntr_mode)(0)
%'	'%DEFINE(cntr_code)(%c82530_code)%'
%'	'%IF (%br_cntr eq 0) THEN (%'
%'	SCC Baud Rate ports are set by the SCC port addresses
%'		'%DEFINE(cntr_ctl_p)(%sio_stat_p)%' only this port needed
%'		'%DEFINE(cntr_p_a)(0)%'
%'		'%DEFINE(cntr_p_b)(0)%'
%'	') ELSE (%'
ERROR -- Counter 0 is the only valid 82530 Baud Rate Counter.
%'	' )FI%'
) ELSE (%'
ERROR -- %cntr_type is an invalid Baud Rate Timer type
%DEFINE(cntr_mode)(0)%'
%DEFINE(cntr_code)(0)%'
%DEFINE(cntr_ctl_p)(0)%'
%DEFINE(cntr_p_a)(0)%'
%DEFINE(cntr_p_b)(0)%'
)FI )FI )FI )FI )FI%'
%'
%'********************  max count section  ******************
%IF ((%EQS(%cntr_type,none)) OR (%EQS(%cntr_type,NONE))) THEN (%'
%'	'%DEFINE(br_cnt)(0)%'
) ELSE (%'
%'	'%IF (%max_cnt LE 1) THEN (%'
ERROR -- Max Baud Rate Count must be greater than 1
%'	')FI%'
%'	'%DEFINE(br_cnt)(%max_cnt)%'
)FI%'
%'
%'	Put it all together

code	segment

bser_init_table	LABEL	WORD

	bsio_data_port		DW	%sio_data_p
	bsio_status_port	DW	%sio_stat_p
	bsio_txrdy		DB	%sio_tx
	bsio_rxrdy		DB	%sio_rx
	bsio_tx_int_reset	DB	%sio_tx_res
	cntr_control_port	DW	%cntr_ctl_p
	cntr_port_a		DW	%cntr_p_a
	cntr_port_b		DW	%cntr_p_b
	cntr_code		DB	%cntr_code
	cntr_mode		DW	%cntr_mode
	baud_rate_cnt		DW	%br_cnt

code	ends
)FI%'	end of the none type
)%'	END OF THE SERIAL_CHANNEL MACRO
