	;; $Id: head.S,v 1.31 2000/10/04 12:37:45 jonashg Exp $
	;; Head of the kernel - alter with care
	;;
	;; Copyright (C) 1998, 1999 Axis Communications AB

#include <linux/config.h>
#define ASSEMBLER_MACROS_ONLY
#include <asm/sv_addr_ag.h>
	
	;; exported symbols
		
	.globl	_etrax_irv
	.globl	_romfs_start
	.globl	_romfs_length
	.globl	_running_from_flash
			
#undef SETUPTEST
#define JULDMAREAD
		
	.text

#ifndef SETUPTEST
	
	;; This is the entry point of the kernel
	;; 0x00000000 if Flash, 0x40000500 if DRAM
	;; since etrax actually starts at address 2 when booting from flash, we
	;; put a nop (2 bytes) here first so we dont accidentally skip the di
	
	nop	
	di

	;; Now we need to sort out the segments and their locations in RAM or
	;; Flash. The image in the Flash (or in DRAM) consists of 3 pieces:
	;; 1) kernel text, 2) kernel data, 3) ROM filesystem image
	;; But the linker has linked the kernel to expect this layout in
	;; DRAM memory:
	;; 1) kernel text, 2) kernel data, 3) kernel BSS
	;; (the location of the ROM filesystem is determined by the krom driver)
	;; If we boot this from Flash, we want to keep the ROM filesystem in
	;; the flash, we want to copy the text and need to copy the data to DRAM.
	;; But if we boot from DRAM, we need to move the ROMFS image
	;; from its position after kernel data, to after kernel BSS, BEFORE the
	;; kernel starts using the BSS area (since its "overlayed" with the ROMFS)
	;;
	;; In both cases, we start in un-cached mode, and need to jump into a
	;; cached PC after we're done fiddling around with the segments.
	;; 
	;; arch/etrax100/etrax100.ld sets some symbols that define the start
	;; and end of each segment.
	
	;; Check if we start from DRAM or FLASH by testing PC
	
	move.d	pc,r0
	and.d	0x7fffffff,r0	; get rid of the non-cache bit
	cmp.d	0x10000,r0	; arbitrary... just something above this code
	bcs	inflash
	nop

	jump	inram		; enter cached ram
	
inflash:

#ifndef CONFIG_SVINTO_SIM	

	;; We need to setup the bus registers before we start using the DRAM

	move.d   DEF_R_WAITSTATES, r0
	move.d   r0, [R_WAITSTATES]

	move.d   DEF_R_BUS_CONFIG, r0
	move.d   r0, [R_BUS_CONFIG]
  
	move.d   DEF_R_DRAM_CONFIG, r0
	move.d   r0, [R_DRAM_CONFIG]

	move.d   DEF_R_DRAM_TIMING, r0
	move.d   r0, [R_DRAM_TIMING]

#endif
	;; Copy text+data to DRAM
	
	moveq	0, r0		; source
	move.d	_text_start, r1	; destination
	move.d	_edata, r2	; end destination
	move.d	r2, r4
	sub.d	r1, r4		; r4 = _edata in flash, used below
1:	move.w	[r0+], r3
	move.w	r3, [r1+]
	cmp.d	r2, r1
	bcs	1b
	nop

	;; We keep the ROM fs in Flash

	move.d	r4, [_romfs_start]
	move.d	[r4 + 8], r0
	swapwb	r0		; ntohl(r0)
	move.d	r0, [_romfs_length]

	moveq	1, r0
	move.d	r0, [_running_from_flash]
		
	jump	start_it	; enter code, cached this time

inram:
	;; Move the ROM fs to after BSS end. This assumes that the ROM fs
	;; third longword contains the length of the ROMfs (that assumption
	;; is made in arch/etrax100/kernel/setup.c also, when the memory_start
	;; is calculated)

	moveq	0, r0
	move.d	r0, [_romfs_length] ; default if there is no ROM fs
	
	;; First check if there IS a ROMfs (magic value)

	move.d	_edata, r0	; romfs will be after the data segment
	move.d	[r0], r1
	swapwb	r1		; ntohl(r1)
	cmp.d	0x2d726f6d, r1	; magic value in ROMfs first longword
	bne	no_romfs
	nop

	;; Ok. What is its size ? 
	
	move.d	[r0 + 8], r2	; ri.size
	swapwb	r2		; ntohl(r2)
	
	;; We want to copy it to the end of the BSS

	move.d	_end, r1

	;; Remember values so krom and setup can find this info

	move.d	r1, [_romfs_start]	; new romfs location
	move.d	r2, [_romfs_length]

	;; We need to copy it backwards, since they can be overlapping

	add.d	r2, r0
	add.d	r2, r1
		
	;; Go ahead. Make my loop.

	lsrq	1, r2		; size is in bytes, we copy words

1:	move.w	[r0=r0-2],r3
	move.w	r3,[r1=r1-2]
	subq	1, r2
	bne	1b
	nop
	
	;; Dont worry that the BSS is tainted. It will be cleared in setup.
		
no_romfs:
	
	moveq	0, r0
	move.d	r0, [_running_from_flash]

	jump	start_it	; enter code, cached this time
	
start_it:
	move.d	_init_kernel_stack + 4096,sp	; set sp to the initial kernel stack
	move.d	_ibr_start,r0	; this symbol is set by the linker script 
	move	r0,ibr
	move.d	r0,[_etrax_irv]	; set the interrupt base register and pointer
#ifdef CONFIG_BLK_DEV_ETRAXIDE
	;; disable ATA before enabling it in genconfig below
	moveq	0,r0
	move.d	r0,[R_ATA_CTRL_DATA]
	move.d	r0,[R_ATA_TRANSFER_CNT]
	move.d	r0,[R_ATA_CONFIG]
#if 0
	move.d	R_PORT_G_DATA,r1
	move.d	r0,[r1]; assert ATA bus-reset
	nop
	nop
	nop
	nop
	nop
	nop
	move.d	0x08000000,r0
	move.d	r0,[r1]
#endif
#endif

#ifdef CONFIG_ETRAX100_OV5017
	;; Axel Burri
	;; disable ATA before enabling it in genconfig below
	moveq	0,r0
	move.d	r0,[R_ATA_CTRL_DATA]
	move.d	r0,[R_ATA_TRANSFER_CNT]
	move.d	r0,[R_ATA_CONFIG]
#endif

	
#ifdef CONFIG_JULIETTE
	;; configure external DMA channel 0 before enabling it in genconfig
	
	moveq	0,r0
	move.d	r0,[R_EXT_DMA_0_ADDR]
	move.d	0x860000,r0	; cnt enable, word size, output, stop, size 0
	move.d	r0,[R_EXT_DMA_0_CMD]

	;; reset dma4 and wait for completion
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH4_CMD]
w4u:	move.b	[R_DMA_CH4_CMD],r0
	and.b	7,r0
	cmp.b	4,r0
	beq	w4u
	nop

	;; reset dma5 and wait for completion
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH5_CMD]
w5u:	move.b	[R_DMA_CH5_CMD],r0
	and.b	7,r0
	cmp.b	4,r0
	beq	w5u
	nop
#endif	
			
	;; Etrax product HW genconfig setup

	moveq	0,r0
#if !defined(CONFIG_KGDB) && !defined(CONFIG_DMA_MEMCPY)
	or.d	0x140000,r0	; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
#endif
#if !defined(CONFIG_KGDB) || !defined(CONFIG_DEBUG_PORT1)
	or.d	0xc00000,r0	; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
#endif
#ifdef CONFIG_DMA_MEMCPY
	or.d	0x003c0000,r0	; 6/7 memory-memory DMA
#endif
#ifdef CONFIG_ETRAX100_SERIAL_PORT2
	or.d	0x2808,r0	; DMA channels 2 and 3 to serport 2, port 2 enabled
#endif
#ifdef CONFIG_ETRAX100_SERIAL_PORT3
	or.d	0x28100,r0	; DMA channels 4 and 5 to serport 3, port 3 enabled
#endif
#if defined(CONFIG_ETRAX100_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE) || defined(CONFIG_LCD_HD44780) || defined(CONFIG_ETRAX100_PARDATA)
	or.w	0x4,r0	; parport 0 enabled using DMA 2/3
#endif
#if defined(CONFIG_ETRAX100_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
	or.w	0x80,r0	; parport 1 enabled using DMA 4/5
#endif
#ifdef CONFIG_BLK_DEV_ETRAXIDE
	or.d	0x3c02,r0	; DMA channels 2 and 3 to ATA, ATA enabled
#endif
#ifdef CONFIG_JULIETTE
	or.d	0x3c000,r0	; DMA channels 4 and 5 to EXTDMA0, for Juliette
#ifndef CONFIG_BLK_DEV_ETRAXIDE
	or.d	0x41,r0		; HACK for now! To make G27 connected for the RTC
#endif
#endif
#ifdef CONFIG_ETRAX100_OV5017
	;; dma2=ata:	bit 10,11=3
	;; dma3=ata:	bit 12,13=3
	;; select ata:	bit 1=1
	or.d	0x3c02,r0	; DMA channels 2 and 3 to ATA, ATA enabled
#endif
	move.d	r0,[_genconfig_shadow] ; init a shadow register of R_GEN_CONFIG

#ifndef CONFIG_SVINTO_SIM
	move.d	r0,[R_GEN_CONFIG]

#if 0
	moveq	4,r0
	move.b	r0,[R_DMA_CH6_CMD]	; reset (ser0 dma out)
	move.b	r0,[R_DMA_CH7_CMD]	; reset (ser0 dma in)
w61:	move.b	[R_DMA_CH6_CMD],r0	; wait for reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w61
	nop
w71:	move.b	[R_DMA_CH7_CMD],r0	; wait for reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w71
	nop
#endif
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH8_CMD]	; reset (ser1 dma out)
	move.b	r0,[R_DMA_CH9_CMD]	; reset (ser1 dma in)
w81:	move.b	[R_DMA_CH8_CMD],r0	; wait for reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w81
	nop
w91:	move.b	[R_DMA_CH9_CMD],r0	; wait for reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w91
	nop

	;; Fix the TR_CTRL registers on the serial ports before init of
	;; PA and PB to get the right txd values ASAP
	;; if there are external hardware depending on them.

	;; setup the serial port 0 at 115200 baud for debug purposes
	
	moveq	0,r0
	move.d	r0,[R_SERIAL0_XOFF] 

	move.b	0x99,r0
	move.b	r0,[R_SERIAL0_BAUD]	; 115.2kbaud for both transmit and receive

	move.b	0x40,r0			; rec enable
	move.b	r0,[R_SERIAL0_REC_CTRL] 
	
	move.b	0xC0,r0			; txd =1 + tr enable
	move.b	r0,[R_SERIAL0_TR_CTRL]

	;; setup the serial port 1 at 115200 baud for debug purposes
	
	moveq	0,r0
	move.d	r0,[R_SERIAL1_XOFF] 

	move.b	0x99,r0
	move.b	r0,[R_SERIAL1_BAUD]	; 115.2kbaud for both transmit and receive

	move.b	0x40,r0			; rec enable
	move.b	r0,[R_SERIAL1_REC_CTRL] 
	
	move.b	0xC0,r0			; txd=1 + tr enable
	move.b	r0,[R_SERIAL1_TR_CTRL]

#ifdef CONFIG_ETRAX100_SERIAL_PORT2
	;; setup the serial port 2 at 115200 baud for debug purposes
	
	moveq	0,r0
	move.d	r0,[R_SERIAL2_XOFF] 

	move.b	0x99,r0
	move.b	r0,[R_SERIAL2_BAUD]	; 115.2kbaud for both transmit and receive

	move.b	0x40,r0			; rec enable
	move.b	r0,[R_SERIAL2_REC_CTRL] 
	
	move.b	0xC0,r0			; txd=1 + tr enable
	move.b	r0,[R_SERIAL2_TR_CTRL]
#endif
	
#ifdef CONFIG_ETRAX100_SERIAL_PORT3	
	;; setup the serial port 3 at 115200 baud for debug purposes
	
	moveq	0,r0
	move.d	r0,[R_SERIAL3_XOFF] 

	move.b	0x99,r0
	move.b	r0,[R_SERIAL3_BAUD]	; 115.2kbaud for both transmit and receive

	move.b	0x40,r0			; rec enable
	move.b	r0,[R_SERIAL3_REC_CTRL] 
	
	move.b	0xC0,r0			; txd=1 + tr enable
	move.b	r0,[R_SERIAL3_TR_CTRL]
#endif

	
	
	;; setup port PA and PB default initial directions and data
	;; including their shadow registers
		
	move.b	DEF_R_PORT_PA_DIR,r0
	move.b	r0,[_port_pa_dir_shadow]
	move.b	r0,[R_PORT_PA_DIR]
	move.b	DEF_R_PORT_PA_DATA,r0
	move.b	r0,[_port_pa_data_shadow]
	move.b	r0,[R_PORT_PA_DATA]
	
	move.b	DEF_R_PORT_PB_CONFIG,r0
	move.b	r0,[_port_pb_config_shadow]
	move.b	r0,[R_PORT_PB_CONFIG]
	move.b	DEF_R_PORT_PB_DIR,r0
	move.b	r0,[_port_pb_dir_shadow]
	move.b	r0,[R_PORT_PB_DIR]
	move.b	DEF_R_PORT_PB_DATA,r0
	move.b	r0,[_port_pb_data_shadow]
	move.b	r0,[R_PORT_PB_DATA]

	moveq	0,r0
	move.d	r0,[_port_g_data_shadow]
	move.d	r0,[R_PORT_G_DATA]


#ifdef CONFIG_ETRAX_90000000_LEDS
	;; clear LED's on Stallone and Olga boards
	moveq	-1,r0
	move.d	r0,[_port_90000000_shadow]
	move.d	r0,[0x90000000]
#endif
	
	
#endif /* CONFIG_SVINTO_SIM */
	
	jump	_start_kernel	; jump into the C-function _start_kernel in init/main.c

#else

	;; the rest in this file is just code for testing the hardware
		
	di
	
#if 1
	;; try to flush the cache
	move.d	0x08000000,r0
	movu.w	256,r2
clrlop:	move.d	[r0],r1
	subq	1,r2
	bne	clrlop
	addq	32,r0
#endif
	
#if 0
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop

	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
#endif

#if 1
	;; enter the cached area
	jump	cached_entry
#endif	
cached_entry:	
	
	move.d	0x40800000,sp	; stack at top of DRAM

	;; reset dma6 and wait for completion
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH6_CMD]
1:	move.b	[R_DMA_CH6_CMD],r0
	and.b	7,r0
	cmp.b	4,r0
	beq	1b
	nop

	;; reset dma4 and wait for completion
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH4_CMD]
2:	move.b	[R_DMA_CH4_CMD],r0
	and.b	7,r0
	cmp.b	4,r0
	beq	2b
	nop

	;; reset dma5 and wait for completion
	
	moveq	4,r0
	move.b	r0,[R_DMA_CH5_CMD]
3:	move.b	[R_DMA_CH5_CMD],r0
	and.b	7,r0
	cmp.b	4,r0
	beq	3b
	nop

	moveq	2,r0		; clear eop irq
	move.b	r0,[R_DMA_CH4_CLR_INTR]
	moveq	1,r0
	move.b	r0,[R_DMA_CH5_CLR_INTR]; clear descr irq
	
	move.d	0xffffffff,r0	; disable all irqs
	move.d	r0,[0xb00000c0]	; mask0
	move.d	r0,[0xb00000c8]	; mask1
	move.d	r0,[0xb00000d0]	; mask2
	move.d	r0,[0xb00000d8]	; vectmask

	;; setup the serial port 0 at 115200 baud for debug purposes
	
	moveq	0,r0
	move.d	r0,[R_SERIAL0_XOFF] 

	move.b	0x99,r0
	move.b	r0,[R_SERIAL0_BAUD]	; 115.2kbaud for both transmit and receive

	moveq	0,r0			; rec disable
	move.b	r0,[R_SERIAL0_REC_CTRL] 
	
	move.b	0x40,r0			; tr enable
	move.b	r0,[R_SERIAL0_TR_CTRL]

	move.d	0x860000,r0	; cnt enable, word size, output, stop, size 0
	move.d	r0,[R_EXT_DMA_0_CMD]

	;; setup GEN_CONFIG
	
	moveq	0,r0		; no dma to serial ports.
	;move.d	0x00d40000,r0	; DMA channels 6 and 7 are to ser 0, 8 and 9 to ser 1
	or.d	0x3c000,r0	; DMA channels 4 and 5 to EXTDMA0, for Juliette
	move.d	r0,[R_GEN_CONFIG]

	move.d	bossebass,r10	;  
	jsr	ser0print

	;; initialize Juliette
	
	move.d	0xa0000002,r10
	move.w	0x40a7,r11
	move.w	r11,[r10]	; 0->0xa7
	move.w	0x8068,r11
	move.w	r11,[r10]
	move.w	0x806,r11
	move.w	r11,[r10]		; 0x68->0x6

#ifndef JULDMAREAD
	;; setup juliette for accepting a DMA transfer
tjulwrite:	
	movu.w	0x200,r12	; r12 = size in words of transfer

	move.d	0xa0000002,r10
	move.w	0xe820,r11
	move.w	r11,[r10]
	move.w	0x803,r11
	move.w	r11,[r10]		; 0x6820->3
	
	move.w	0x8068,r11
	move.w	r11,[r10]
	move.w	0x806,r11
	move.w	r11,[r10]		; 0x68->0x6
	
	move.w	0x4061,r11
	move.w	r11,[r10]		; 0->0x61

	move.w	0x4169,r11
	move.w	r11,[r10]		; 1->0x69

	move.w	0x4162,r11
	move.w	r11,[r10]		; 1->0x69

	or.w	0x8000,r12
	move.w	r12,[r10]		; (MC6 counter... r12 words) 
	move.w	0x860,r11
	move.w	r11,[r10]
	
	move.w	0x4906,r11
	move.w	r11,[r10]		; 9->6

	move.w	0x60a7,r11
	move.w	r11,[r10]		; 0x20->0xa7
	
	;; setup descriptor
	
	move.d	0x40200000,r1	; start of our DMA output descriptor
	move.d	r1,[R_DMA_CH4_FIRST]
	move.d	0x00070400,r0
	move.d	r0,[r1+]	; eol,eop, wait
	moveq	0,r0
	move.d	r0,[r1+]		; next = 0
	move.d	0x40200010,r0
	move.d	r0,[r1+]; adress of buffer, right after descriptor
	moveq	0,r0
	move.d	r0,[r1+]		; status

	move.d	0xa0000000,r0	; juliette data in register
	move.d	r0,[R_EXT_DMA_0_ADDR]

	;; start DMA4

	moveq	1,r0
	move.b	r0,[R_DMA_CH4_CMD]

	;;movu.w	0xbeef,r0
			
	;; start EXT DMA 0

	move.d	0x870200,r1	; cnt enable, word size, output, run, size 0x100 words
	move.d	r1,[R_EXT_DMA_0_CMD]
	
	;; tell the world we're running

	move.d	bossebass,r10	; 2
	jsr	ser0print

#if 0
	;; neverending loop which is magically skipped sometimes
nlop1:	ba	nlop1
	nop
#endif
	
	;; wait for DMA4 eop
w4v:	move.d	[R_IRQ_READ2],r0
	btstq	9,r0
	bpl	w4v
	nop

	moveq	2,r0		; clear eop irq
	move.b	r0,[R_DMA_CH4_CLR_INTR]
	
	move.d	bossebass,r10	; 3		 
	jsr	ser0print

	;; wait for Juliette IRQ

wjlop:	move.d	[R_IRQ_READ0],r0
	btstq	4,r0
	bpl	wjlop
	nop

	move.d	bossebass,r10	; 4
	jsr	ser0print

die42:			
	moveq	0,r0	
looop:	nop
	move.d	r0,[0x90000000]
	not	r0
	ba	looop
	nop

#else
	;; setup juliette for accepting a DMA transfer
tjulread:	
	movu.w	0x200,r12	; r12 = size in words of transfer

	move.d	0xa0000002,r10
	move.w	0x8050,r11
	move.w	r11,[r10]
	move.w	0x803,r11
	move.w	r11,[r10]		; 0x8050->3
	
	move.w	0x8060,r11
	move.w	r11,[r10]
	move.w	0x806,r11
	move.w	r11,[r10]		; 0x60->0x6
	
	move.w	0x4061,r11
	move.w	r11,[r10]		; 0->0x61

	move.w	0x4069,r11
	move.w	r11,[r10]		; 0->0x69

	move.w	0x4162,r11
	move.w	r11,[r10]		; 1->0x62

	or.w	0x8000,r12
	move.w	r12,[r10]		; (MC6 counter... r12 words) 
	move.w	0x860,r11
	move.w	r11,[r10]
	
	move.w	0x4106,r11
	move.w	r11,[r10]		; 1->6

	move.w	0x60a7,r11
	move.w	r11,[r10]		; 0x20->0xa7
	
	;; setup descriptor
	
	move.d	0x40200000,r1	; start of our DMA output descriptor
	move.d	r1,[R_DMA_CH5_FIRST]
	move.d	0x00090400,r0
	move.d	r0,[r1+]	; eol,intr
	moveq	0,r0
	move.d	r0,[r1+]		; next = 0
	move.d	0x40200010,r0
	move.d	r0,[r1+]; adress of buffer, right after descriptor
	moveq	0,r0
	move.d	r0,[r1+]		; status

	move.d	0xa0000000,r0	; juliette data in register
	move.d	r0,[R_EXT_DMA_0_ADDR]

	;; start DMA5

	moveq	1,r0
	move.b	r0,[R_DMA_CH5_CMD]

	;;movu.w	0xbeef,r0
			
	;; start EXT DMA 0

	move.d	0x850200,r1	; cnt enable, word size, input, run, size 0x100 words
	move.d	r1,[R_EXT_DMA_0_CMD]
	
	;; tell the world we're running

	move.d	bossebass,r10	; 2
	jsr	ser0print

#if 0
	;; neverending loop which is magically skipped sometimes
nlop1:	ba	nlop1
	nop
#endif
	
	;; wait for DMA5 descr
1:	move.d	[R_IRQ_READ2],r0
	btstq	10,r0
	bpl	1b
	nop

	moveq	1,r0		; clear descr irq
	move.b	r0,[R_DMA_CH5_CLR_INTR]
	
	move.d	bossebass,r10	; 3		 
	jsr	ser0print

	;; wait for Juliette IRQ

2:	move.d	[R_IRQ_READ0],r0
	btstq	4,r0
	bpl	2b
	nop

	move.d	bossebass,r10	; 4
	jsr	ser0print

die42:			
	moveq	0,r0	
3:	nop
	move.d	r0,[0x90000000]
	not	r0
	ba	3b
	nop
#endif
		
	;; make a dma input descriptor at c0200020
	move.d	0x000b0010,r0
	move.d	r0,[r1+]	; intr, eol, eop, 16 bytes size
	moveq	0,r0
	move.d	r0,[r1+]		; next = 0
	move.d	0xc0200030,r0
	move.d	r0,[r1+]; adress of buffer, right after descriptor
	moveq	0,r0
	move.d	r0,[r1+]		; status
	
	move.d	0xc0000000,r1
	move	r1,ibr
	move.d	IRQ15_interrupt,r0
	movu.w	256,r2
yeman:	move.d	r0,[r1]
	addq	4,r1
	subq	1,r2
	bne	yeman
	nop

	move.d	-16,r0		; 0-sw -> timeout check var
	move.d	r0,[pipelen]
		
	move.b	0x1c,r0
	move.b	r0,[0xb0000031]	; port PA dir
	move.b	0xff,r0
	move.b	r0,[0xb0000030]	; clear all LED's
	
#if 1
	moveq	0,r0
	move.b	r0,[0xb000007c]	; zero R_SERIAL3_XOFF

	move.b	0x99,r0
	move.b	r0,[0xb000007b]	; 115.2kbaud

	move.b	0x50,r0		; rec enable + majority sampling
	move.b	r0,[0xb000007a]	; R_SERIAL3_REC_CTRL
	
	move.b	0x40,r0		; tr enable
	move.b	r0,[0xb0000079]	; R_SERIAL3_TR_CTRL

	moveq	4,r0
	move.b	r0,[0xb00001e0]	; R_DMA_CH4_CMD = reset (ser0 dma out)
	move.b	r0,[0xb00001e4]	; R_DMA_CH5_CMD = reset (ser0 dma in)
#if 1
w6:	move.b	[0xb00001e0],r0	; wait for DMA_CH4_CMD reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w6
	nop
w7:	move.b	[0xb00001e4],r0	; wait for DMA_CH5_CMD reset cycle to finish
	and.b	7,r0
	cmp.b	4,r0
	beq	w7
	nop
#endif
#endif
		
#if 0
	;; dont use the timer right now...
	move.d	0x60600505,r0	; 96 div for both, stop_ld, 9600 hz
	move.d	r0,[0xb0000020]	; stop and load timer0 (and 1)
	move.d	0x60600525,r0	; start timer0, keep timer1 stopped
	move.d	r0,[0xb0000020]
	;; now set irq mask and enable irqs
	
	moveq	1,r0
	move.d	r0,[0xb00000c4]	; mask0, enable timer0 irq
#endif

	
#ifdef NODMA
	move.d	0x200,r0
	move.d	r0,[0xb00000cc]	; mask1, enable serial irq
	move.d	0x104,r0
	move.d	r0,[0xb00000dc]	; vectmask, enable serial and timer0
#else
	move.d	0x00000d00,r0	; dma4/5 descr irq (not eop, doesnt work with serial)
	move.d	r0,[0xb00000d4]	; R_IRQ_MASK2_SET
	move.d	0x00300000,r0
	move.d	r0,[0xb00000dc]	; vectmask, dma4 and dma5
#if 0
	;; setup DMA 7 to do some input from the serial0 port
	moveq	3,r0
	move.b	r0,[0xb00001ed]	; clear eop and descr irq in R_DMA_CH7_CLR_INTR
	move.d	0xc0200020,r0	; our input descriptor
	move.d	r0,[0xb00001bc]	; write first dma desc to R_DMA_CH7_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001ec]	; cmd=start to R_DMA_CH7_CMD
#endif
#if 1
	;; setup DMA 4 to do some output to the serial3 port
	moveq	3,r0
	move.b	r0,[0xb00001e1]	; clear eop and descr irq in R_DMA_CH4_CLR_INTR
	move.d	0xc0200000,r0	; our output descriptor
	move.d	r0,[0xb00001b0]	; write first dma desc to R_DMA_CH4_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001e0]	; cmd=start to R_DMA_CH4_CMD
#endif


	
#endif	

#if 0
	move.b	65,r0
	move.b	r0,[0xb0000060]	; write one initial A to serial0_tr_data
#endif
	ei
	nop
	nop
	
endless:nop
	ba	endless
	nop

_fast_IRQ15_interrupt:
_bad_IRQ15_interrupt:
IRQ15_interrupt:
	push	irp
	push	srp
	push	ccr
	di
	subq	14*4,sp
	movem	r13,[sp]
	push	r0
	
#if 0
	push	dccr
	di
	push	irp
	push	srp
	push	r0
#endif

	move.d	[0xb00000d8],r0	; read the irq bits that triggered the multiple irq
	btstq	20,r0		; check for dma4 irq
	bmi	dma4_interrupt
	nop
#if 0
	btstq	21,r0		; check for dma5 irq
	bmi	dma5_interrupt
	nop
	btstq	2,r0		; check for timer irq
	bmi	test_interrupt
	nop
#endif
	ba	Rexit
	nop

#if 1
#define USENOPS
#endif

#if 1
#define USEBLOCKING
#undef USEBLOCKINGS
#endif
		
test_interrupt:
	move.d	0x60600565,r0
	move.d	r0,[0xb0000020]	; ack timer0 irq
#ifdef USEBLOCKING
	moveq	4,r0
	move.d	r0,[0xb00000d8]	; block timer irq
#endif

	moveq	0,r2
	move.w	[0xb00001ee],r2	; read R_DMA_CH7_STATUS
	and.w	0x3f,r2		; r2 = fifo size
	move.d	[0xb0000170],r1	; read R_DMA_CH7_HWSW
	lsrq	16,r1		; get the hw size (r1 = number of bytes free in DMA)
	sub.d	r1,r2		; r2 = fifo amount - bytes free in dma buffer
	cmp.d	[pipelen],r2	; compare with last value
	bne	recving		; if it has changed, we're still receiving stuff
	nop
	move.d	pipetimeout,r1
	move.w	[r1],r0
	subq	1,r0		; decrement timeout
	move.w	r0,[r1]
	bne	noend		; no timeout
	nop
	moveq	4,r0		; we hit the timeout, force an end-of-packet
	move.d	r0,[0xb000003c]	; force EOP for DMA7, R_SET_EOP	
recving:
	move.d	r2,[pipelen]	; remember the new value
restim:	moveq	1,r0
	move.d	r0,[pipetimeout]; reset the timeout
noend:	
	
#ifdef USENOPS
	nop
	nop
	nop
	nop
	ei
	nop
	nop
	move.d	150,r0
bossu:	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	subq	1,r0
	bne	bossu
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
#endif
	di
	
#ifdef USEBLOCKING
	moveq	4,r0
	move.d	r0,[0xb00000dc]	; unblock timer irq
#endif
	ba	Rexit
	nop
			
test2_interrupt:
#ifdef USEBLOCKINGS
	move.d	0x100,r0
	move.d	r0,[0xb00000d8]	; block ser irq
#endif
	move.b	67,r0
	move.b	r0,[0xb0000060]	; write new and ack
#ifdef USENOPS
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
	nop
#endif
	di
#ifdef USEBLOCKINGS
	move.d	0x100,r0
	move.d	r0,[0xb00000dc]	; unblock ser irq
#endif
	ba	Rexit
	nop

dma6_interrupt:
	moveq	1,r0
	move.b	r0,[0xb00001e9]	; clr_descr in R_DMA_CH6_CLR_INTR
#if 0	
	move.d	0xc0200000,r0
	move.d	r0,[0xb00001b8]	; write first dma desc to R_DMA_CH6_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001e8]	; cmd=start to R_DMA_CH6_CMD
#endif
	ba	Rexit
	nop

dma4_interrupt:
	moveq	1,r0
	move.b	r0,[0xb00001e1]	; clr_descr in R_DMA_CH4_CLR_INTR
#if 1
	move.d	0xc0200000,r0
	move.d	r0,[0xb00001b0]	; write first dma desc to R_DMA_CH4_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001e0]	; cmd=start to R_DMA_CH4_CMD
#endif
	ba	Rexit
	nop

	
dma7_interrupt:
	move.d	[bosse],r0
	addq	1,r0
	move.d	r0,[bosse]
	lslq	2,r0
	move.b	r0,[0xb0000030]	; flash leds some...

	move.d	0xc0200030,r0
	move.d	0xc0200010,r1
	move.w	[0xc020002c],r2	; read hw len
	move.w	r2,[0xc0200000]	; write len to output descriptor

	move.d	[r0+],r3	; copy the data
	move.d	r3,[r1+]
	move.d	[r0+],r3	; copy the data
	move.d	r3,[r1+]
	move.d	[r0+],r3	; copy the data
	move.d	r3,[r1+]
	move.d	[r0+],r3	; copy the data
	move.d	r3,[r1+]
		
	;; first ack and restart the input dma7
	moveq	3,r0
	move.b	r0,[0xb00001ed]	; clr_descr and eop in R_DMA_CH7_CLR_INTR
	move.d	0xc0200020,r0
	move.d	r0,[0xb00001bc]	; write first dma desc to R_DMA_CH7_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001ec]	; cmd=start to R_DMA_CH7_CMD

	;; then start the output dma6 to echo the data
	
	moveq	1,r0
	move.b	r0,[0xb00001e9]	; clr_descr in R_DMA_CH6_CLR_INTR
	move.d	0xc0200000,r0
	move.d	r0,[0xb00001b8]	; write first dma desc to R_DMA_CH6_FIRST
	moveq	1,r0
	move.b	r0,[0xb00001e8]	; cmd=start to R_DMA_CH6_CMD
	
	ba	Rexit
	nop

Rexit:	addq	4,sp		; skip r0 for now
	movem	[sp+],r13	; pop registers orig_r0-r13
	move.d	[sp-60],r0	; grab the skipped r0
	pop	ccr		; pop condition codes
	pop	srp		; pop subroutine return pointer
	jump	[sp+]		; return by popping irp and jumping there

ser0print:
	;; string in r10
	move.b	[R_SERIAL0_STATUS],r11
	btstq	5,r11		; tr_ready
	bpl	ser0print
	nop
	
	move.b	[r10+],r11
	beq	prend
	nop
	
	move.b	r11,[R_SERIAL0_TR_DATA]
	ba	ser0print
	nop
	
prend:	ret
	nop
	
#endif  /* SETUPTEST */
	
	.data
_etrax_irv:	
	.dword	0
_romfs_start:
	.dword	0
_romfs_length:
	.dword	0
_running_from_flash:
	.dword	0
