		subtitle	"< SYS0 IPL - Minimum initialization for eZ80F91 & eZ80F92. >"
		newpage
		scope

;	Copyright (C) 2022 - 2026 by Daniel Paul Martin.  All Rights Reserved.


__init	di
		im	2					; Prepare interrupt controller for mode 2.		

		LD	A,RETOPCODE			; Ignore stray interrupt requests.
		LD	(zNMI),A			; Ignore NMI, return to caller.
		LD	(zRST38),A			; Ignore RST 38h, return to caller.

		ld.lil	sp,0100FFh		; Setup 24 bit stack pointer.
		LD	SP,STACK$			; Point SP to stack area.

		XOR	A					; Initialize & clear stack.
		LD	HL,STACK$+1			; Start of Stack+1
CLRLOOP		DEC	L				; Move down a byte.
		LD	(HL),A				; Loop and fill.
		JR	NZ,CLRLOOP			; Fill from stack$ to bottom of stack$'s page with 0"s.

		
		ld	a,(U0DVR)
		ld	(quiet_default+1),a
		ld	a,(quiet_default_flg); Get quiet/default IPL code.
		ld	(quiet_default),a
		bit	7,a					; If bit 7 set, then go into quiet mode.
		jr	z,no_quiet
		ld	a,RETOPCODE			; Return op code.
		ld	(U0DVR),a			; Turn driver off.

no_quiet	push	bc			; Save pointer to 2nd file if any.
		push	de				; Save pointer to 1st file if any.

;		Set PFLAG$ in TRSDOS to 91h or 92h representing eZ80F91/eZ80f92.

		MVC	cpu_f91_msg,cpu_typ_msg,7	; Fill in splash screen <F91 detected> (default message).

		ld	a,1h				; Processor type F92.
		sla	a				; Shift it left one place.
		ld	(PFLAG$),a			; Store in processor byte.
		in0	a,(ZDI_ID_L)			; Get product ID.
		cp	08h				; 8=eZ80F91
		jr	z,tst_initial
		ld	a,02h				; Processor type F92.
		sla	a				; Pack it.
		ld	(PFLAG$),a			; If not 92h then set processor type to f92.
		MVC	cpu_f92_msg,cpu_typ_msg,7	; Tell splash screen F92 detected.

; 		Test in entry to this module from an already running CPU.

tst_initial	ld	a,HIGH(INTERRUPT.handler)	; Setup internal interrupt register to interrupt table.
		ld	i,a

		in0	a,(UART0_SPR)			; Test if IPL came from other OS.
		and	00001111b
		ld	(initialflg),a

		sla	a
		sla	a
		sla	a
		sla	a				; Shift left 4 bits to pack platform into zTFLAG$.
		ld	h,a
		ld	a,(zTFLAG$)
		or	h
		ld	(zTFLAG$),a			; Store platform bits into platform type byte.

		sra	a				; Unpack and get back platform nibble.
		sra	a
		sra	a
		sra	a

		or	a				; Is it <>0?
		jp	nz,NOINITIAL			; If <>0 we came from CPM, do not initialize CPU.

		add	'0'
		ld	(vendor$-6),a			; Embed this initial flag in boot menu for diagnostics.

		MVC	vendor_z$,vendor$,8
		MVC	from_por,ipl_from,4		; Tell splash screen we are booting from Power On Reset.

		pop	de				; Discard pointer to 1st data file (it doesnt exist).
		pop	bc				; Discard pointer to 2nd data file (it doesnt exist).

init_f91f92f93;	This section of code is common to both eZ80F91 & eZ80F92 processors.

		MVC	bootinitmsg,splashiplmode+1,bootinitmsglen-1

;	Disable internal peripheral interrupt sources, this will help during a RAM debug session.

		xor	a

		out0 	(PB_ALT1), a
		out0 	(PC_ALT1), a
		out0 	(PD_ALT1), a

;		OUT0	(PC_DR),A 			; to enable RS232 Driver

;   Port C = SF_HOLD, SF_WP, SF_MISO, SF_MOSI, CTS1#, RTS1#, RXD1, TXD1

		LD    	A,11111100b          		; Port C default data
		OUT0  	(PC_DR),A              		; and set it
		LD    	B,00001111b            		; ALT 2
		OUT0  	(PC_ALT2),B            		; and set it
		LD    	D,00101111b            		; Set bit directions
		OUT0  	(PC_DDR),D			; and "alternate functions"

		ld 	a,%04
		out0	(SPI_CTL), a			; SPI

		in0 	a,(RTC_CTRL)			; RTC,
		and 	a,%BE	       			; Writing to the RTC_CTRL register also resets the RTC count
		out0	(RTC_CTRL), a			; prescaler allowing RTC to be synchronized to other.time sourceS.

		ld	a, __CS0_LBR_INIT_PARAM		; Configure external memory & I/O.
		out0	(CS0_LBR), a
		ld	a, __CS0_UBR_INIT_PARAM
		out0	(CS0_UBR), a
		ld	a, __CS0_BMC_INIT_PARAM
		out0	(CS0_BMC), a
		ld	a, __CS0_CTL_INIT_PARAM
		out0	(CS0_CTL), a
		ld	a, __CS1_LBR_INIT_PARAM
		out0	(CS1_LBR), a
		ld	a, __CS1_UBR_INIT_PARAM
		out0	(CS1_UBR), a
		ld	a, __CS1_BMC_INIT_PARAM
		out0	(CS1_BMC), a
		ld	a, __CS1_CTL_INIT_PARAM
		out0	(CS1_CTL), a
		ld	a, __CS2_LBR_INIT_PARAM
		out0	(CS2_LBR), a
		ld	a, __CS2_UBR_INIT_PARAM
		out0	(CS2_UBR), a
		ld	a, __CS2_BMC_INIT_PARAM
		out0	(CS2_BMC), a
		ld	a, __CS2_CTL_INIT_PARAM
		out0	(CS2_CTL), a
		ld	a, __CS3_LBR_INIT_PARAM
		out0	(CS3_LBR), a
		ld	a, __CS3_UBR_INIT_PARAM
		out0	(CS3_UBR), a
		ld	a, __CS3_BMC_INIT_PARAM
		out0	(CS3_BMC), a
		ld	a, __CS3_CTL_INIT_PARAM
		out0	(CS3_CTL), a

;		enable internal memory

		ld	a, __FLASH_ADDR_U_INIT_PARAM
		out0	(FLASH_ADDR_U), a
		ld	a, __FLASH_CTL_INIT_PARAM
		out0	(FLASH_CTRL), a
		ld	a, __RAM_ADDR_U_INIT_PARAM
		out0	(RAM_ADDR_U), a
		ld	a, __RAM_CTL_INIT_PARAM
		out0	(RAM_CTL), a

; End of common processor code.

; Get processor model (91h,92h,93h) code.
; Continue setup by executing processor specific routines.

		ld	a,(PFLAG$)
		sra	a
		cp	01h
		jp	nz,init_f92

init_f91;	eZ80F91 Initialization.

		xor	a				; A=0.

		out0 	(EMAC_IEN), a			;**** EMAC
		out0 	(I2C_CTL), a			; I2C
		out0 	(FLASH_IRQ), a			; Flash.

		out0 	(TMR0_IER), a			;**** timers
		out0 	(TMR1_IER), a			;****
		out0 	(TMR2_IER), a			;****
		out0 	(TMR3_IER), a			;****

		out0 	(PA_ALT1), a			;***
		out0 	(PA_ALT2), a			;***

		out0 	(PB_ALT1), a			;***000000
		out0 	(PB_ALT2), a


		out0	(PD_DR),a

		ld	a,3
		OUT0	(PD_ALT2),A     

		ld	a,0FFh
		out0	(PA_DDR), a			;***	; GPIO
		out0	(PB_DDR), a

		ld	a,0EBh
		out0	(PD_DDR), a

; Set UART0 baud rate generator for eZ80F91. f91_baud is equated in eZ80.

		LD	A,83h				; Set bit 7 to enable UART BRG register access.
		OUT0	(UART0_LCTL),A  		; enable access to BRG.

		LD	A,LOW(f91_console_baud)  	; LSB of BRG divisor
		OUT0	(BRG0_DLR_L),A   		; load low byte of BRG.

		LD	A,HIGH(f91_console_baud) 	; MSB of BRG divisor
		OUT0	(BRG0_DLR_H),A   		; load high byte of BRG

		LD	A,03h           		; select 8bits, no parity, 1 stop
		OUT0	(UART0_LCTL),A  		; and lock BRG.

		LD	B,0
		DJNZ	$				; WARMUP, let BRG stabilize?

; Initialize real time interrupts here for f91 processor.
; Setup 60HZ real time interrupts using TMR1, setup registers but do not enable.
; Enable is done when background tasking is enabled.

		xor	a
;		out0	(TMR_ISS),a			; Clock is derived from divided systems clock.MISTAKE?
		out0	(TMR1_CTL),a			; Disable.

		ld	hl,52083			; Get reload values.
		out0	(TMR1_RR_L),l			; Put low byte in register.
		out0	(TMR1_RR_H),h			; Load upper byte in reload counter high.


		ld	a,00001100b			; Clock derrived from dividing system clock by 16.
		out0	(TMR1_CTL),a			; Disable.
		in0	a,(TMR1_IIR)			; Read to reset.
		ld	a,01				; Enable interrupt at end of count.
		out0	(TMR1_IER),a			; IRQ EOC EN.

		jp	START_UARTS

init_f92;	Initialize here for f92 processor.

		LD	A,11110100b			; PCB V1.1+ Port B default data
		LD	B,11001100b			; ALT 2
		LD	D,11001100b			; bit directions

		OUT0	(PB_DR),A			; Set default data
		OUT0	(PB_ALT2),B			; Set ALT 2.
		OUT0	(PB_DDR),D			; Set bit directions

;   Port C = SF_HOLD, SF_WP, SF_MISO, SF_MOSI, CTS1#, RTS1#, RXD1, TXD1

		LD	A,11111100b			; Port C default data
		LD	B,00001111b			; ALT 2
		LD	D,00101111b			; Set bit directions.

		OUT0	(PC_DR),A			; and set it
		OUT0	(PC_ALT2),B			; and set it
		OUT0	(PC_DDR),D			; and "alternate functions"

;     Port D = SD_CD#, N/A, SF_CE#, SF_CLK, CTS0#, RTS0#, RXD0, TXD0


		LD	A,10101100b			; Set Port D default data
		OUT0	(PD_DR),A			; before changing direction
		LD	A,00001111b			; Allocate UART 0
		OUT0	(PD_ALT2),A			; bits to

		out0 	(UART0_IER), a      		; UARTs
		out0 	(UART1_IER), a


;	Set baud rate generator. f92_baud rate is equated in eZ80.

		LD	A,83h				; Set bit 7 to enable UART BRG register access.
		OUT0	(UART0_LCTL),A  		; enable access to BRG.

		LD	A,LOW(f92_console_baud)  	; LSB of BRG divisor
		OUT0	(BRG0_DLR_L),A   		; load low byte of BRG.

		LD	A,HIGH(f92_console_baud)	; MSB of BRG divisor
		OUT0	(BRG0_DLR_H),A   		; load high byte of BRG

		LD	A,03h           		; select 8bits, no parity, 1 stop
		OUT0	(UART0_LCTL),A  		; and lock BRG.

		LD	B,0
		DJNZ	$				; WARMUP, let BRG stabilize?

; Initialize Timers here for f92 processor.
; Ensure all f92 timers are disabled & clear.

		xor	a				; Load  0's into following registers.
		out0	(TMR_ISS),a			; Clock is derived from divided systems clock.
		out0	(f92_TMR0_CTL),a		; Disable and procede with initial register load.
		out0	(f92_TMR2_CTL),a
		out0	(f92_TMR3_CTL),a
		out0	(f92_TMR4_CTL),a
		out0	(f92_TMR5_CTL),a

; Now read these same registers to clear pending interrupts.

		in0	a,(f92_TMR0_CTL)
		in0	a,(f92_TMR1_CTL)
		in0	a,(f92_TMR2_CTL)
		in0	a,(f92_TMR3_CTL)
		in0	a,(f92_TMR4_CTL)
		in0	a,(f92_TMR5_CTL)

; Setup 60HZ real time interrupts using TMR1.
; Setup but do not enable timer.
; Enable is done when background tasking enabled.

		ld	bc,19200			; Get high/low byte of count down value.
		out0	(f92_TMR1_RR_L),c		; Put in register.			
		out0	(f92_TMR1_RR_H),b		; Upper byte, load in reload counter high.
		ld	a,00010100b			; Set divider in register.
		out0	(f92_TMR1_CTL),a

START_UARTS;	*** START UART 0 SERIAL COMMUNICATIONS WITH HOST. ***

		LD	A,01h  				; Per Zilog manual, 1st set bit 0.
		OUT0	(UART0_FCTL),A			; Then set bits 1 & 2..

		LD	A,07h   			; Activate receive and transmit FIFOs.
		OUT0	(UART0_FCTL),A			; Transmit/Receive Enable.

;	Tell world UART's & hardware ready by setting DTR. CTS set later when driver is initialized.

		LD	A,00000011b			; Set DTR active, RTS inactive.
		OUT0	(UART0_MCTL),A			; UART0 tell other end we are ready.

;	*** START UART 1 SERIAL COMMUNICATIONS WITH HOST. ***

		LD	A,83h				; Set bit 7 to enable UART BRG register access.
		OUT0	(UART1_LCTL),A  		; enable access to BRG.

;	Set baud rate generator. Baud rate is equated in eZ80.

		LD	A,LOW(f91_serialnet_baud)  	; LSB of BRG divisor
		OUT0	(UART1_BRG_L),A   		; load low byte of BRG.

		LD	A,HIGH(f91_serialnet_baud) 	; MSB of BRG divisor
		OUT0	(UART1_BRG_H),A   		; load high byte of BRG

		LD	A,03h           		; select 8bits, no parity, 1 stop.
		OUT0	(UART1_LCTL),A  		; and lock BRG.

		LD	B,0
		DJNZ	$				; WARMUP, let BRG stabilize?

		LD	A,01h  				; Per Zilog manual, 1st set bit 0.
		OUT0	(UART1_FCTL),A			; Then set bits 1 & 2..

		LD	A,07h  				; Activate receive and transmit FIFOs.
		OUT0	(UART1_FCTL),A			; Transmit/Receive Enable.

		UART1.dtr.set

		jp	finish_init

; 	We arrive here, IPL was warm started by other OS.
;       Test for optional data files passed.
;	If no file passed, skip altering storage map.
;       If file was loaded adjust map to reflect variable size files.

;	Tell world UART's & hardware ready by setting DTR. CTS set later when driver is initialized.

NOINITIAL:	MVC	vendor_undef$,vendor$,8		; Prepare for unrecognized vendor.
		ld	a,(initialflg)
		push	af
		add	'0'
		ld	(vendor$-6),a			; Embed this initial flag in boot menu for diagnostics.
		pop	af

		cp	1				; Circle M platform?
		IF_NE_GOTO	cir_tst
		MVC	vendor_cirm$,vendor$,8
		GOTO	plat_set

cir_tst		cp	2				; Circle M platform?
		IF_NE_GOTO	agon_tst
		MVC	vendor_cirm$,vendor$,8
		GOTO	plat_set

agon_tst	cp	3				; AGON platform?
		IF_NE_GOTO	dinno_tst
		MVC	vendor_agon$,vendor$,8		; Tell operator we are on AGON platform.
		GOTO	plat_set

dinno_tst	cp	4				; dinno platform?
		IF_NE_GOTO	plat_set
		MVC	vendor_dinno$,vendor$,8		; Tell operator we are on dinno platform.
		GOTO	plat_set

		cp	5				; Circle M platform?
		IF_NE_GOTO	plat_set
		MVC	vendor_cirm$,vendor$,8
		GOTO	plat_set

plat_set	MVC	from_cpm,ipl_from,4		; Tell splash screen we are booting from CPM.

;	If file was loaded, DE contained pointer to first. BC to 2nd file.

		pop	de				; Recover pointer to 1st data file.
		pop	bc				; Recover pointer to 2nd data file.

		ld	hl,de				; No file loaded DE =0.
		xor	a				; Compare D to 0. 0=no file loaded.
		cp	d				; If no file loaded leave default storage map in place.
		jr	z,finish_init			; If B was 0 then file was  <64k, cannot be <64k+1.

		ld	de,0101h
		or	a
		sbc	hl,de
		ld.lil	(010101h),hl			; Store offset from slice 1 to diskdisk file.
			
;	If file was loaded BC points to start of file. No file loaded B =0.

		ld	hl,bc
		xor	a				; Compare B to 0, it cannot be 0.
		or	B				; a zero if a file was loaded.
		jr	z,finish_init			; If B was 0 then file was less than 64k, cannot be <64k+1.
		ld	de,0101h
		or	a
		sbc	hl,de
		ld.lil	(010104h),hl			; Offset to drive 1 image file loaded by Bill@Circle-M.

;		Initialization of CPU complete, splash first welcome/copyright screen.

finish_init	UART0.dtr.set				; Set DTR active tell other end we are powered on & ready.
		UART1.dtr.set				; Set DTR active tell other end we are powered on & ready.
		ld	c,020h				; Get fill byte in accumulator.
		ld	hl,CRTBGN$
		ld	b,8				; Fill 8 pages with spaces.
more_fill	push	bc
		ld	b,0				; Setup for 256 chars.
fill_loop	ld	(hl),c				; Stuff a copy of fill byte.
		inc	hl
		LOOP	fill_loop
		pop	bc
		LOOP	more_fill

		MVC	welcomemsg,CRTBGN$,RDYMSGLEN	; Move welcome message to video RAM.

		JP	STARTBIOS			; Start BIOS.

