$NOLIST

;
;          INTEL CORPORATION PROPRIETARY INFORMATION
;
;       This software is supplied under the terms of a
;       license agreement or nondisclosure agreement with
;       Intel Corporation and may not be copied or disclosed
;       except in accordance with the terms of that agreement.
;


$LIST
	%IF (%first_device) THEN (

%IF (%is_auto_config_mem) THEN (
		public	mem_config_mode
mem_config_mode	db	%mode
		public	mem_start_address
mem_start_address	dw	%saddr
)FI
code		ends				;
;
; Declare the cico routines if needed
;
		%IF (%is_console OR %is_loadfile) THEN (
		extrn	co: far			; will need co in either case
		) FI
		%IF (%is_console) THEN (
		extrn	ci: far			; need ci here also
		)FI
		%IF(%is_cico) THEN (
        	extrn   cinit:  far		; must initialize the USART
		)FI  		

		%IF (%is_auto_config_mem) THEN (
		extrn	auto_config_mem:  far	; must initialize memory
		)FI
		
		;
	DEVICE_NOT_READY equ 11h	; stage one error
	TRUE		equ	0FFh			;
	FALSE		equ	000h			;
	BLANK		equ	020H			;
	CR		equ	00DH			; Carriage Return
	LF		equ	00AH			; Line Feed

data		segment	
		public	polltimes		; Declare the number of times to poll devices
polltimes	dw	?
data		ends
code		segment				;
		%IF (%is_console) THEN (
code		ends				;
data		segment				;
		public	line_buffer		; Declare line buffer
		public  debug			; 
line_buffer	db	80 DUP (?)		;
debug		db	?
			public	input_strng
; max length of input string is 100 bytes
;
input_strng	db	100 dup(?)

data		ends				;
						;
code		segment				;
		extrn	get_file_name: near	;
startup:
		%IF (%is_auto_config_mem) THEN (
		call	auto_config_mem
		mov	ss, cs: stackseg	; load stack segment
		mov	sp, stacksize		; load stack pointer
		mov	ds, cs: dataseg		; load data segment
		mov	inhibit_co, 0		; load global flag used by montior CO xface
		)FI
		%IF (%is_cico) THEN (
		call	cinit
		)FI
		call	get_file_name		; call console procedure
got_name:					;
    ; 
    ; copy the string typed by the user to
    ; a public variable input_strng
    ; will be used by the remote boot driver to parse
    ; the class code and can also be used by others
    ;
	mov	di,0
cp_strng:
	mov	ah, es:byte ptr [bx+di] ;
	mov	input_strng[di],ah 

	cmp	ax,CR
	jz	cp_done
	cmp	ax,LF
	jz	cp_done

	cmp	di,100
	jz	cp_done

	inc	di
	jmp	cp_strng

cp_done:
		mov	debug, FALSE		; default to no debug
		cmp	es:byte ptr [bx], CR	; check for null file name
		jz	set_default		; use default
		cmp	es:byte ptr [bx], LF	; check for null file name
		jz	set_default		; use default
		
		cmp	es:byte ptr [bx], 'D'	; Debug switch?
		jz	check_debug		; might be, check
		cmp	es:byte ptr [bx], 'd'	; check lower case too
		jnz	got_line		; no debug switch
						;
check_debug:	cmp	es:byte ptr [bx+1], BLANK	; next char blank?
		jnz	check_end		; no, check for <cr><lf>
		mov	debug, TRUE		; yes, there is a debug switch
						;
parse_blanks:	inc	bx			;
		cmp	es:byte ptr [bx+1], BLANK	; 
		jz	parse_blanks		; get past blanks
						;
check_end:	cmp	es:byte ptr [bx+1], CR	; if next char is a CR,
		jz	debug_default		; then debug the default file
		cmp	es:byte ptr [bx+1], LF	; ditto for LF
		jz	debug_default		;
						;
		cmp	debug, TRUE		; debug switch?
		jnz	got_line		; no, boot the file
		inc	bx			; yes, point to start of name
		jmp	got_line		; and debug the file
						;
debug_default:	mov	debug, TRUE		;
set_default:	lea	bx, default_file	; load up default file name
		mov	ax, cs			;
		mov	es, ax			;
						;
got_line:	mov	ax, cs:maxtimes		; set polltimes properly
		mov	polltimes, ax		;
						;
		cmp	debug, FALSE		; debug = FALSE?
		jz	no_debug		; debug switch off
		mov	ax, 37695		; first debug check word
		push	ax			;
		mov	ax, 49273		; second debug word
		push	ax			;
		jmp	push_check		;
						;
no_debug:	mov	ax,0			; check words are zero
		push	ax			;
		push	ax			;
						;
push_check:	mov	ax, 14156		; push the first check word
		push	ax			;
		mov	ax, 26778		; push the second check word
		push	ax			;
		mov	ax, seg bserror		; push the pointer to the error routine
		push	ax			;
		mov	ax, offset bserror	;
		push	ax			;
		push	es			; push file name pointer
		push	bx			;

		) ELSE (	; (no console)

startup:
		%IF (%is_auto_config_mem) THEN (
		call	auto_config_mem
		mov	ss, cs: stackseg	; load stack segment
		mov	sp, stacksize		; load stack pointer
		mov	ds, cs: dataseg		; load data segment
		)FI
		%IF (%is_cico) THEN (
		call	cinit
		)FI
got_name:					;
		mov	ax, cs:maxtimes		; set polltimes properly
		mov	polltimes, ax		;
						;
no_debug:	mov	ax,0			;
		push	ax			;
		push	ax			;
		mov	ax, 14156		; push the first check word
		push	ax			;
		mov	ax, 26778		; push the second check word
		push	ax			;
		mov	ax, seg bserror		; push the pointer to the error routine
		push	ax			;
		mov	ax, offset bserror	;
		push	ax			;
		lea	ax, default_file	; push default file name pointer
		push	cs			;
		push	ax			;
		) FI

		%IF (%is_manual) THEN (
		push	ax			; reserve dev name space
		push	ax			;
		extrn	manual_device_select: near
		call	manual_device_select	; call manual procedure
						; it will call auto if needed
		) ELSE (

			%IF (%is_auto) THEN (
		push	ax			; reserve dev name space
		push	ax			;

		%external(auto_device_select,near)
		call	auto_device_select	; call auto procedure
			) FI
		) FI

		%IF (NOT %device_select) THEN (
		mov	ax, %unit		; push unit
		push	ax			;
		les	bx, cs:uinfo		; unit information
		call	%device_init		; call device$init procedure
		or	ax, ax			; make sure device is there
		jnz	boot_ok			;
		mov	cx, DEVICE_NOT_READY	; call the error routine
		push	cx			;
		call	bserror
boot_ok:	les	bx, cs: dev_name_ptr	; get pointer to device name
		push	es			; push it
		push	bx			;
		les	bx, cs: dev_read	; get pointer to device$read
		mov	cx, %unit		; get unit
		) FI

		push	es			; push pointer to device$read
		push	bx			;
		push	cx			; push unit
		push	ax			; push dev$gran
		mov	bp, sp			; get pointer into stack
		push	cx			; push unit
		xor	ax, ax			; push zero for dev$loc
		push	ax			;
		push	ax			;
		mov	dx, boot		; push pointer to second stage

		push	dx			;
		push	ax			;
		mov	second_stage_s, dx	; save this pointer to
		mov	second_stage_o, ax	; call later
%IF (%is_loadfile) THEN (%'
		push	ds			; save ds for awhile
		mov	ax, cs
		mov	ds, ax			; print loading message
		lea	bx, load
		call	print
		mov	ds, word ptr [bp+10]	; get base to device name
		mov	bx, word ptr [bp+8]	; get offset to device name
		call	cprint
		mov	ds, word ptr [bp+14]	; get base to file name
		mov	bx, word ptr [bp+12]	; get the file name pointer
		call	print			; print the file name
%IF (%is_console) THEN (%'
		pop	ds			;
		cmp	debug, TRUE		;
		push	ds			;
		jnz	no_print		; no debug message	
		mov	ax, cs			;
		mov	ds, ax			; print debug message
		lea	bx, debug_msg		;
		call	print			;
) FI%'
						;
no_print:	mov	ax, cs			;
		mov	ds, ax			; print loading message
		lea	bx, crlf		;
		call	print			;
		pop	ds			; get the stack back to normal
) FI%'
%IF (%clear_ext) THEN (%'
		mov	ax, 0			;clear the 'U' extension
		mov	bx, 0			;NIL
		mov	es, bx			; "
		call	dword ptr setcommand
		mov	ax, 1			;clear the 'V' extension
		mov	bx, 0			;NIL
		mov	es, bx			; "
		call	dword ptr setcommand
		mov	ax, 2			;clear the 'W' extension
		mov	bx, 0			;NIL
		mov	es, bx			; "
		call	dword ptr setcommand
)FI%'
		call	dword ptr [bp+4]	; call device$read
		call	second_stage_ptr	; call second stage
%IF (%is_loadfile) THEN (%'
;
;	This routine prints the string pointed to by BX.
;
print		proc	near
		mov	al, byte ptr [bx]	; get a byte from the message
		cmp	al, ' '			; if a null then done
		jae	continue              
		ret
Continue:	and	al, 7fh			; remove high bit
		push	ax			; put the character where co wants it
		call	co			; print it
		inc	bx			; next character
		jmp	print
print		endp
;
;	This routine prints the counted string pointed to by bx
;
cprint		proc	near
		mov	cl, byte ptr [bx]	; get the name length in cl
		inc	bx			; first true character
		mov	ch, 0
		or	cx, cx			; check for null name
		jnz	cloop
		ret
cloop:
		mov	al, byte ptr [bx]	; load character from device name
		inc	bx
		push	ax			; al has the character in it
		call	co			; print it
		loop	cloop
		ret
cprint		endp
) FI%'
						;
stackseg	dw	stack			; stack segment
dataseg		dw	data			; data segment
maxtimes	dw	%times			; max times to poll - used to reset poll times

code	ends

bstime_code	segment	word	public	'code'

			public	delay_constant
delay_constant	dw	%delay		;system is %cpu_type

bstime_code	ends

code	segment

%IF(%clear_ext) THEN (
setcommand	dd	0FFFC0000H
)FI

%IF(%is_loadfile) THEN (
load		db 8dh,8ah,'Loading ',0		;
debug_msg	db '     <debug>',0		; printed if debug switch on
crlf		db 8dh,8ah,8ah,0		;
) FI

		%IF (%device_select) THEN (
device_table	label	byte			; table of devices
		public	device_table		;

		) ELSE (

dev_name_ptr	dd	dev_name		; pointer to device name
dev_name	db	%LEN(%name)+2		; fill in device name
		db	':%name:'		;
dev_read	dd	%device_read		; pointer to device$read
uinfo		dd	%unit_info		; information on the unit
		) FI

		%SET(first_device, 0) ;(end of first device macro)
	) ELSE (	;(not first device macro)

code		ends				;

code		segment				;
		%IF (NOT %device_select) THEN (
			%error ; MORE THAN ONE DEVICE MACRO ILLEGAL
		) FI
	) FI

	%IF (%device_select) THEN (
		db	%LEN(%name)+2		; Fill in name
		db	':%name:'		;
		dw	%unit			; unit
		dd	%device_init		; device$init procedure
		dd	%device_read		; device$read procedure
		dd	%unit_info		; information on the unit
	) FI
