
; File:   ministartup.s
; Author: Mikael Kalms <mikael@kalms.org>
; Date:   1 Oct 1999
; Title:  Startup routine
;
; Description:
;   Small startup routine, which tries to take over most of the system
;   resources in a correct manner


; If you add your own autovector interrupt handlers by changing the VBR
; directly, please remember to test it on a4000/060!

	include	lvo/dos_lib.i
	include	lvo/exec_lib.i
	include	lvo/graphics_lib.i
	include	hardware/custom.i
	include	hardware/dmabits.i
	include	hardware/intbits.i
	include	dos/dosextens.i
	include	exec/execbase.i
	include	graphics/gfxbase.i
	include	devices/audio.i

	IFND	STARTUP_ALLOCAUDIO
STARTUP_ALLOCAUDIO	EQU	0
	ENDC
	IFND	STARTUP_ALLOCBLITTER
STARTUP_ALLOCBLITTER	EQU	1
	ENDC

	IFND	STARTUP_INTBITS
STARTUP_INTBITS SET INTF_VERTB|INTF_COPER
	ENDC
	IFNE	STARTUP_ALLOCAUDIO
STARTUP_INTBITS SET STARTUP_INTBITS|INTF_AUD0|INTF_AUD1|INTF_AUD2|INTF_AUD3
	ENDC
	IFNE	STARTUP_ALLOCBLITTER
STARTUP_INTBITS SET STARTUP_INTBITS|INTF_BLIT
	ENDC

	IFND	STARTUP_DMABITS
STARTUP_DMABITS SET DMAF_SPRITE|DMAF_COPPER|DMAF_RASTER
	ENDC
	IFNE	STARTUP_ALLOCAUDIO
STARTUP_DMABITS SET STARTUP_DMABITS|DMAF_AUDIO
	ENDC
	IFNE	STARTUP_ALLOCBLITTER
STARTUP_DMABITS SET STARTUP_DMABITS|DMAF_BLITTER
	ENDC

	section	code,code

start	move.l	$4.w,a6			; Cache execbase in local memory
	move.l	a6,execbase		;  (helps on MMU-enabled systems
					;  and is good style in general)

	bsr.s	osinit
	bne.s	.error
	bsr	hwinit
	bsr	main
	bsr	hwexit
	sub.l	a5,a5
.error	bsr	osexit
	rts

osinit
	sub.l	a1,a1			; Receive WB message if started
	jsr	_LVOFindTask(a6)	;  from WB
	move.l	d0,a2
	tst.l	pr_CLI(a2)
	bne.s	.cli
	lea	pr_MsgPort(a2),a0
	jsr	_LVOWaitPort(a6)
	lea	pr_MsgPort(a2),a0
	jsr	_LVOGetMsg(a6)
	move.l	d0,wbmsg
.cli
	lea	msg_020needed,a5	; Check for 020+
	move.w	AttnFlags(a6),d0
	btst	#AFB_68020,d0
	beq.w	.error

; Alternative, OS-independent 020 check:
;	lea	msg_020needed,a0
;	moveq	#1,d0			; Detect 020+: Less-than-020
;.t020	tst.b	.t020(pc,d0.w*2)	;  will ignore the scaling prefix
;	bne	.error			;  instead of generating exception
;					; This is not documented in the
					;  Motorola manuals, but it worked
					;  on the 68000 in the Atari ST
					;  and applies *probably* to all
					;  68000/68010s.

	lea	msg_os3needed,a5
	lea	gfxname,a1		; Open graphics.library v39
	moveq	#39,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,gfxbase
	beq.w	.error
	lea	dosname,a1		; Open dos.library v39
	moveq	#39,d0
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,dosbase
	beq.s	.error

	lea	msg_aganeeded,a5	; Check for AGA
	move.l	gfxbase,a0
	btst	#GFXB_AA_ALICE,gb_ChipRevBits0(a0)
	beq.s	.error

	IFNE	STARTUP_ALLOCAUDIO
	move.l	execbase,a6
	lea	msg_nomemory,a5
	jsr	_LVOCreateMsgPort(a6)	; Open audio.device and allocate
	move.l	d0,audiomsgport		;  all channels
	beq.s	.error
	move.l	d0,a0
	moveq	#ioa_SIZEOF,d0
	jsr	_LVOCreateIORequest(a6)
	move.l	d0,audioioreq
	beq.s	.error
	move.l	d0,a0
	move.b	#127,LN_PRI(a0)
	move.l	#audiochalloc,ioa_Data(a0)
	move.l	#1,ioa_Length(a0)
	lea	msg_audiofailed,a5
	move.l	a0,a1
	lea	audioname,a0
	jsr	_LVOOpenDevice(a6)
	tst.l	d0
	bne.s	.error
	move.l	audioioreq,a0
	move.l	IO_DEVICE(a0),audiobase
	ENDC

	sub.l	a5,a5
.error	move.l	a5,d0
	rts


hwinit
	IFNE	STARTUP_ALLOCBLITTER
	move.l	gfxbase,a6		; Allocate blitter
	jsr	_LVOOwnBlitter(a6)
	jsr	_LVOWaitBlit(a6)
	ENDC

	move.l	execbase,a6
	jsr	_LVOForbid(a6)		; Disable taskswitching

	lea	.getvbr,a5		; Retreive VBR
	jsr	_LVOSupervisor(a6)
	sub.l	a5,a5

	move.l	gfxbase,a6
	move.l	gb_ActiView(a6),wbview	; Save information about currently
	move.l	gb_copinit(a6),wbcopinit ; active View

	sub.l	a1,a1			; Zero screen (and activate AGA
	jsr	_LVOLoadView(a6)	;  graphics if a gfxcard currently
	jsr	_LVOWaitTOF(a6)		;  is the topmost screen)
	jsr	_LVOWaitTOF(a6)

	lea	$dff000,a0		; Save dma & int bits,
	move.w	dmaconr(a0),olddmacon	;  and disable user-defined ones
	move.w	intenar(a0),oldintena
	move.w	#STARTUP_DMABITS,dmacon(a0)
	move.w	#STARTUP_INTBITS,intena(a0)
	move.w	#STARTUP_INTBITS,intreq(a0)
	rts

.getvbr	movec	vbr,d0
	move.l	d0,vectorbase
	rte

hwexit
	lea	$dff000,a0		; Restore user-defined dma & int
	move.w	olddmacon,d0		;  bits, as well as the master bits
	not.w	d0
	and.w	#STARTUP_DMABITS|DMAF_MASTER,d0
	move.w	d0,dmacon(a0)
	not.w	d0
	and.w	#STARTUP_DMABITS|DMAF_MASTER|$8000,d0
	move.w	d0,dmacon(a0)
	move.w	oldintena,d0
	not.w	d0
	and.w	#STARTUP_INTBITS|INTF_INTEN,d0
	move.w	d0,intena(a0)
	move.w	d0,d1
	and.w	#~INTF_INTEN,d1
	move.w	d1,intreq(a0)
	not.w	d0
	and.w	#STARTUP_INTBITS|INTF_INTEN|$8000,d0
	move.w	d0,intena(a0)

	move.l	gfxbase,a6
	move.l	wbview,a1		; Restore previously active View
	jsr	_LVOLoadView(a6)
	move.l	wbcopinit,cop1lc+$dff000
	move.w	d0,copjmp1+$dff000

	move.l	execbase,a6		; Enable taskswitching
	jsr	_LVOPermit(a6)

	IFNE	STARTUP_ALLOCBLITTER
	move.l	gfxbase,a6		; Deallocate blitter
	jsr	_LVODisownBlitter(a6)
	ENDC
	rts

osexit
	move.l	execbase,a6

	IFNE	STARTUP_ALLOCAUDIO
	tst.l	audiobase		; Close audio.device and free all
	beq.s	.naudio			;  allocated channels
	move.l	audioioreq,a1
	jsr	_LVOCloseDevice(a6)
.naudio
	move.l	audioioreq,d0
	beq.s	.naudioioreq
	move.l	d0,a0
	jsr	_LVODeleteIORequest(a6)
.naudioioreq
	move.l	audiomsgport,d0
	beq.s	.naudiomsgport
	move.l	d0,a0
	jsr	_LVODeleteMsgPort(a6)
.naudiomsgport
	ENDC

	move.l	gfxbase,d0		; Close graphics.library, if open
	beq.s	.ngfxlib
	move.l	d0,a1
	jsr	_LVOCloseLibrary(a6)
.ngfxlib
	move.l	dosbase,d0		; Close dos.library, if open
	beq.s	.ndoslib
	move.l	d0,a1
	jsr	_LVOCloseLibrary(a6)
.ndoslib

	cmp.w	#0,a5			; Any error message?
	beq.s	.nerrmsg
	lea	dosname,a1		; If so, print using dos.library
	moveq	#32,d0			;  v32, using Write() [should work
	jsr	_LVOOpenLibrary(a6)	;  on _all_ Amigas]
	tst.l	d0
	beq.s	.nerrmsg
	move.l	d0,a6
	jsr	_LVOOutput(a6)
	move.l	d0,d1
	moveq	#0,d3
	move.b	(a5)+,d3
	move.l	a5,d2
	jsr	_LVOWrite(a6)
	move.l	a6,a1
	move.l	execbase,a6
	jsr	_LVOCloseLibrary(a6)
.nerrmsg

	move.l	wbmsg,d2		; Reply WB message, if any
	beq.s	.nwbmsg
	jsr	_LVOForbid(a6)
	move.l	d2,a1
	jsr	_LVOReplyMsg(a6)
.nwbmsg
	rts

	section	data,data

execbase dc.l	0
gfxbase	dc.l	0
dosbase	dc.l	0
wbmsg	dc.l	0
wbview	dc.l	0
wbcopinit dc.l	0
vectorbase dc.l	0
	IFNE	STARTUP_ALLOCAUDIO
audiomsgport dc.l 0
audioioreq dc.l	0
audiobase dc.l	0
	ENDC
olddmacon dc.w	0
oldintena dc.w	0

msg_020needed
	dc.b	.end-msg_020needed-1
	dc.b	"68020+ required",10
.end

msg_os3needed
	dc.b	.end-msg_os3needed-1
	dc.b	"OS3.0+ required",10
.end

msg_aganeeded
	dc.b	.end-msg_aganeeded-1
	dc.b	"AGA required",10
.end

msg_nomemory
	dc.b	.end-msg_nomemory-1
	dc.b	"Out of memory",10
.end

msg_audiofailed
	dc.b	.end-msg_audiofailed-1
	dc.b	"Failed allocating all audio channels",10
.end

gfxname	dc.b	"graphics.library",0
dosname	dc.b	"dos.library",0

	IFNE	STARTUP_ALLOCAUDIO
audioname dc.b	"audio.device",0
audiochalloc dc.b $f,0
	ENDC

	cnop	0,4
