;	ConfigMem.asm - resident module to configure PPI 32bit memory
;
;	Written by Michael L. Hitch
;		Montana State University
;		osymh@msu.oscs.montana.edu
;

	include	"exec/types.i"
	include	"exec/nodes.i"
	include	"exec/memory.i"
	include	"exec/resident.i"
	include	"exec/execbase.i"
	include	"libraries/configvars.i"
	include	"libraries/expansion.i"
	include	"hardware/cia.i"
	include	"hardware/custom.i"

	xref	_LVOAddMemList
	xref	_LVOOpenLibrary
	xref	_LVOCloseLibrary
	xref	_LVOFindConfigDev
	xref	_LVOAllocMem
	xref	_LVOSumKickData
	xref	_LVOForbid
	xref	_LVOPermit
	xref	_LVOSupervisor
	xref	_LVOCacheControl
	xref	_ciaa
	xref	_custom

	csect	text
;
; Program entry point
;
	movem.l	d2-d3/a2/a6,-(sp)
	move.l	4,a6
;
; *** process command line arguments
;
	jsr	AddResident(pc)		; Add program to KickMemPtr list
;*** check status?
;
	btst	#AFB_68040,AttnFlags+1(a6)	; is it 68040?
	bne.s	Init_68040
; *** 68040 not detected on WB1.3
	cmp.w	#36,LIB_VERSION(a6)		; check if 2.0 or later
	bge.s	Skip_Init			; AFB_68040 is valid
	moveq	#AFF_68030!AFF_68020,d0
	and.w	AttnFlags(a6),d0		; Kludge for WB1.3
	bne.s	Skip_Init
Init_68040:
	lea	myCacheClear(pc),a5
	jsr	_LVOSupervisor(a6)
	moveq	#0,d0
	move.l	#CACRF_EnableD,d1
	jsr	_LVOCacheControl(a6)
	move.l	d0,-(sp)
	jsr	TagInit(pc)
	move.l	d0,d3
	move.l	(sp)+,d0
	move.l	#CACRF_EnableD,d1
	jsr	_LVOCacheControl(a6)
	move.l	d3,d0
Skip_Init:
	movem.l	(sp)+,d2-d3/a2/a6
	rts

myCacheClear:
	cpusha	bc
	rte
;
;
AddResident
	move.l	KickMemPtr(a6),a0
1$:
	move.l	a0,d0
	beq.s	NewResident		; Not found
	move.l	LN_NAME(a0),a1		; name of this entry
	lea	TagName(pc),a2		; my name
2$:
	move.b	(a1)+,d0
	cmp.b	(a2)+,d0
	bne.s	3$
	tst.b	d0
	bne	2$
; found entry
	moveq	#1,d0
	rts
3$:
	move.l	(a0),a0			; Next entry
	bra	1$
;
; Layout of memory block
;	ds.b	8		Overhead space for AllocAbs
;	ds.b	ML_SIZE		Memory entry list
;	ds.b	ME_SIZE		Memory entry
;	ds.b	8		RomTab pointer array
;	ds.b	nnn		Resident module
;
KM_RTPTR equ	ML_SIZE+ME_SIZE		; Location of RomTag pointer array
KM_SIZE	equ	KM_RTPTR+8		; Size of KickMem info header
;
NewResident:
	moveq	#KM_SIZE+8,d0		; size of KickMem header + 8 byte overhead
	add.l	RomTag+6(pc),d0
	sub.l	RomTag+2(pc),d0		; add length of resident module
	move.l	#MEMF_24BITDMA!MEMF_CLEAR,d1
	jsr	_LVOAllocMem(a6)	; allocate memory
	tst.l	d0
	bne.s	1$
	moveq	#KM_SIZE+8,d0		; size of KickMem header + 8 byte overhead
	add.l	RomTag+6(pc),d0
	sub.l	RomTag+2(pc),d0		; add length of resident module
	move.l	#MEMF_CHIP!MEMF_CLEAR,d1
	jsr	_LVOAllocMem(a6)	; allocate memory
	tst.l	d0
	bne.s	1$
	moveq	#2,d0
	rts
1$:
	move.l	d0,a0			; a0 = address of allocated memory
	lea	8(a0),a2		; a2 = address of MemList
	move.b	#NT_MEMORY,LN_TYPE(a2)	; initialize MemList
	move.w	#1,ML_NUMENTRIES(a2)
	move.l	a0,ML_ME(a2)
	moveq	#KM_SIZE+8,d0		; size of KickMem header + 8 byte overhead
	move.l	d0,ML_ME+ME_LENGTH(a2)
	move.l	RomTag+6(pc),d0
	sub.l	RomTag+2(pc),d0		; d0 = length of resident module
	add.l	d0,ML_ME+ME_LENGTH(a2)
	lea	KM_SIZE+8(a0),a0	; point to RomTag structure
	lea	RomTag(pc),a1
	move.l	a0,d1
	sub.l	a1,d1			; relocation offset for RomTag addresses
	move.l	a0,KM_RTPTR(a2)		; RomTag Pointer
	subq.l	#1,d0
2$:	move.b	(a1)+,(a0)+		; copy resident module
	dbra	d0,2$
	move.l	KM_RTPTR(a2),a0		; Point to RomTag structure
	add.l	d1,RT_MATCHTAG(a0)	; relocate absolute addresses
	add.l	d1,RT_ENDSKIP(a0)
	add.l	d1,RT_NAME(a0)
	add.l	d1,RT_IDSTRING(a0)
	add.l	d1,RT_INIT(a0)
	move.l	RT_NAME(a0),LN_NAME(a2)	; set MemList name same as RomTag name
;*** add to KickMemPtr & KickTagPtr
	jsr	_LVOForbid(a6)
	lea	KickMemPtr(a6),a0
3$:	move.l	(a0),d0
	beq.s	4$
	move.l	d0,a0
	bra	3$
4$:	tst.l	KickMemPtr(a6)
	beq.s	5$
	move.l	a0,LN_PRED(a2)		; is this really needed?
	move.l	a2,(a0)
	bra.s	6$
5$:	move.l	a2,KickMemPtr(a6)
6$:	move.l	KickTagPtr(a6),d0
	beq.s	7$
	bset	#31,d0
	move.l	d0,KM_RTPTR+4(a2)	; link to existing RomTag pointer array
7$:	lea	KM_RTPTR(a2),a0		; address of our RomTag pointer array
	move.l	a0,KickTagPtr(a6)
	jsr	_LVOSumKickData(a6)
	move.l	d0,KickCheckSum(a6)
	jsr	_LVOPermit(a6)
;*** call resident initialization routine?
	moveq	#0,d0
	rts
;
	dc.b	"$VER: ConfigMem 37.4 (19.10.93)",0
;
; The resident RomTag structure
;
RomTag:	dc.w	RTC_MATCHWORD
	dc.l	RomTag
	dc.l	EndModule
	dc.b	RTF_COLDSTART
	dc.b	37
	dc.b	NT_KICKMEM
	dc.b	111
	dc.l	TagName
	dc.l	TagID
	dc.l	TagInit

TagName: dc.b	"Config32",0
TagID:	dc.b	"PPI ConfigMem32 37.4 (19.10.93)",$0d,$0a,0
MemName: dc.b	"PPI 32Bit RAM",0
ZeusName: dc.b	"ZEUS 32Bit RAM",0
;ZeusName2: dc.b	"ZEUS 32Bit RAM ][",0
ExpName: EXPANSIONNAME
	ds.w	0
MemAttr: dc.l	MEMF_LOCAL!MEMF_FAST!MEMF_PUBLIC

TagInit:
	movem.l	d2/d3/a2/a4,-(sp)
	lea	_custom,a0			; Address of custom chip
	move.w	potinp(a0),d0			; Read register
	ori.w	#$0c00,d0			; Set output, data = 1
	move.w	d0,potgo(a0)
	moveq	#127,d0
1$:	dbra	d0,1$
	move.w	potinp(a0),d0			; Read data
	andi.w	#$0400,d0			; Test if Mouse right button pressed
	beq.s	SkipMouse			; Yes, don't check left button
	lea	_ciaa,a0
	btst	#6,ciapra(a0)			; Test if Mouse left button pressed
	beq.s	TagExit				; Yes, skip it
SkipMouse:
	btst	#AFB_68040,AttnFlags+1(a6)	; is it 68040?
	bne.s	Is_68040
	cmp.w	#36,LIB_VERSION(a6)		; if 2.0 or later
	bge.s	TagExit				; AFB_68040 is valid
; *** 68040 not detected on WB1.3
	moveq	#AFF_68030!AFF_68020,d0
	and.w	AttnFlags(a6),d0		; Kludge for WB1.3
	bne.s	Is_68040
TagExit:
	moveq	#0,d0
	movem.l	(sp)+,d2/d3/a2/a4
	rts

Is_68040:
	lea	MemList(a6),a0			; get address of memory list
Chk_0:	move.l	(a0),d0				; get next entry
	beq.s	Chk_1				; End of list
	move.l	d0,a0
	move.l	LN_NAME(a0),a1			; memory node name
	lea	MemName(pc),a2			; Check PPI 040 memory
	moveq	#13,d0
1$:	cmpm.b	(a1)+,(a2)+
	dbne	d0,1$
	beq.s	TagExit				; matched: already configured
	move.l	LN_NAME(a0),a1
	lea	ZeusName(pc),a2			; Check Zeus 040 memory
	moveq	#14,d0
2$:	cmpm.b	(a1)+,(a2)+
	dbne	d0,2$
	beq.s	TagExit				; matched: already configured
	bra.s	Chk_0
Chk_1:

;
; Get PP&S board address, read configuration switches
;
	lea	ExpName(pc),a1			; open expansion library
	moveq	#0,d0
	jsr	_LVOOpenLibrary(a6)
	tst.l	d0
	beq	TagExit				; couldn't open library
	move.l	a6,-(sp)
	move.l	d0,a6
	move.l	#2026,d0			; manufacturer code
;	move.l	#105,d1				; product code = PPI 040
;	move.l	#150,d1				; product code = Zeus 040
	moveq	#-1,d1				; product code = any
	lea	0,a0
	jsr	_LVOFindConfigDev(a6)
	move.l	a6,a1
	move.l	(sp)+,a6
	move.l	d0,a2
	jsr	_LVOCloseLibrary(a6)
	move.l	a2,d0
	beq	TagExit
	cmpi.b	#150,cd_Rom+er_Product(a2)	; product code = Zeus 040
	bne	TagExit
	move.l	cd_BoardAddr(a2),a0
;get flags & compute autoconfig setting
;**** turn off caching ****
	
;
; Need to leave hole if autoconfiguring memory
;
	lea	$08000000,a0			; search 32 bit memory area for
Next_32:					; installed memory
	move.l	#$aaaaaaaa,d2
	move.l	#$55555555,d3			; patterns for test
Find_Start:
	move.l	(a0),d0				; save contents
	move.l	4(a0),d1
	move.l	d2,(a0)				; write pattern 1
	move.l	d3,4(a0)			; write pattern 2
	nop
	nop
	cmp.l	(a0),d2				; compare pattern 1
	bne.s	1$				; failed
	cmp.l	4(a0),d3			; compare pattern 2
	beq.s	Found_Start			; found start of memory
1$:
	move.l	d0,(a0)
	move.l	d1,4(a0)
	add.l	#$00100000,a0			; test on 1Meg boundary
	cmp.l	#$0a000000,a0			; at end of region?
	blt	Find_Start
No_More:
;*** turn caching back on ***
	moveq	#1,d0
	movem.l	(sp)+,d2/d3/a2/a4
	rts

Found_Start:
	move.l	d0,(a0)				; restore original contents
	move.l	d1,4(a0)
	cmp.l	#$0c000000,a2	;*** Kludge
	beq.s	No_More
	move.l	a0,a2				; copy memory start
Find_End:
	cmp.l	#$0c000000,a2	;*** Kludge
;	cmp.l	#$08100000,a2	;*** Kludge
	beq.s	Found_End	;*** Kludge
	move.l	(a2),d0				; save contents
	move.l	4(a2),d1
	move.l	d2,(a2)				; write pattern 1
	move.l	d3,4(a2)			; write pattern 2
	nop
	nop
	cmp.l	(a2),d2				; compare pattern 1
	bne.s	Found_End			; failed, at end of region
	cmp.l	4(a2),d3			; compare pattern 2
	bne.s	Found_End
	move.l	d0,(a2)				; restore original contents
	move.l	d1,4(a2)
	add.l	#$00100000,a2
	bra	Find_End

Found_End:
	move.l	a2,d0				; compute size
	sub.l	a0,d0
	move.l	MemAttr(pc),d1			; attributes
	moveq	#30,d2				; priority
;	lea	MemName(pc),a1			; name
	lea	ZeusName(pc),a1			; name
;	cmp.l	#$08100000,a2	;*** Kludge
;	beq.s	1$
;	lea	ZeusName2(pc),a1
1$:
	jsr	_LVOAddMemList(a6)
	move.l	a2,a0
	cmp.l	#$08100000,a0	;*** Kludge
	bne	Next_32		;*** Kludge
	move.l	#$08200000,a0	;*** Kludge
	bra	Next_32

EndModule:

	end
