#include "opt_fpu_emulate.h"
#include "opt_bb060stupidrom.h"
#include "opt_p5ppc68kboard.h"
#include "opt_compat_netbsd.h"
#include "opt_compat_sunos.h"
#include "opt_fpsp.h"
#include "opt_kgdb.h"
#include "opt_lockdebug.h"
#include "opt_lev6_defer.h"
#include "opt_m68k_arch.h"
#include "assym.h"
#include <machine/asm.h>
#include <machine/trap.h>
.text
GLOBAL(kernel_text)
L_base:
.long 0x4ef80400+PAGE_SIZE
.fill PAGE_SIZE/4-1,4,0
#include <amiga/amiga/vectors.s>
#include <amiga/amiga/custom.h>
#ifdef DRACO
#include <amiga/amiga/drcustom.h>
#endif
#define CIAAADDR(ar) movl _C_LABEL(CIAAbase),ar
#define CIABADDR(ar) movl _C_LABEL(CIABbase),ar
#define CUSTOMADDR(ar) movl _C_LABEL(CUSTOMbase),ar
#define INTREQRADDR(ar) movl _C_LABEL(INTREQRaddr),ar
#define INTREQWADDR(ar) movl _C_LABEL(INTREQWaddr),ar
#define INTENAWADDR(ar) movl _C_LABEL(amiga_intena_write),ar
#define INTENARADDR(ar) movl _C_LABEL(amiga_intena_read),ar
.text
pea Ljmp0panic
jbsr _C_LABEL(panic)
Ljmp0panic:
.asciz "kernel jump to zero"
.even
ENTRY_NOPROFILE(spurintr)
addql #1,_C_LABEL(intr_depth)
addql #1,_C_LABEL(intrcnt)+0
INTERRUPT_SAVEREG
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei)
ENTRY_NOPROFILE(lev5intr)
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
#include "ser.h"
#if NSER > 0
jsr _C_LABEL(ser_fastint)
#else
INTREQWADDR(%a0)
movew #INTF_RBF,%a0@ | clear RBF interrupt in intreq
#endif
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
addql #1,_C_LABEL(intrcnt)+20
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei)
#ifdef DRACO
ENTRY_NOPROFILE(DraCoLev2intr)
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
CIAAADDR(%a0)
movb %a0@(CIAICR),%d0 | read irc register (clears ints!)
jge Ldrintrcommon | CIAA IR not set, go through isr chain
movel _C_LABEL(draco_intpen),%a0
| andib #4,%a0@
|XXX this would better be
bclr #2,%a0@
btst #0,%d0 | timerA interrupt?
jeq Ldraciaend
movl %sp,%sp@- | push pointer to clockframe
movw #PSL_HIGHIPL,%sr | hardclock at high IPL
jbsr _C_LABEL(hardclock) | call generic clock int routine
addql #4,%sp | pop params
addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt
Ldraciaend:
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei)
ENTRY_NOPROFILE(DraCoLev1intr)
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
movl _C_LABEL(draco_ioct),%a0
btst #5,%a0@(7)
jeq Ldrintrcommon
btst #4,%a0@(7) | this only happens during autoconfiguration,
jeq Ldrintrcommon | so test last.
movw #PSL_HIGHIPL,%sr | run clock at high ipl
Ldrclockretry:
movl %sp,%sp@- | push pointer to clockframe
jbsr _C_LABEL(hardclock)
addql #4,%sp | pop params
addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt
movl _C_LABEL(draco_ioct),%a0
tstb %a0@(9) | latch timer value
movw %a0@(11),%d0 | can't use movpw here, might be 68060
movb %a0@(13),%d0
addw _C_LABEL(amiga_clk_interval)+2,%d0
movb %d0,%a0@(13) | low byte: latch write value
movw %d0,%a0@(11) | ...and write it into timer
tstw %d0 | already positive?
jcs Ldrclockretry | we lost more than one tick, call us again.
clrb %a0@(9) | reset timer irq
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei) | XXXX: shouldn't we call the normal lev1?
ENTRY_NOPROFILE(DraCoIntr)
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
Ldrintrcommon:
lea _ASM_LABEL(Drintrcnt)-4,%a0
movw %sp@(22),%d0 | use vector offset
andw #0xfff,%d0 | sans frame type
addql #1,%a0@(-0x60,%d0:w) | to increment apropos counter
movw %sr,%sp@- | push current SR value
clrw %sp@- | padded to longword
jbsr _C_LABEL(intrhand) | handle interrupt
addql #4,%sp | pop SR
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei)
#endif
ENTRY_NOPROFILE(lev1intr)
ENTRY_NOPROFILE(lev2intr)
ENTRY_NOPROFILE(lev3intr)
#ifndef LEV6_DEFER
ENTRY_NOPROFILE(lev4intr)
#endif
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
Lintrcommon:
lea _C_LABEL(intrcnt),%a0
movw %sp@(22),%d0 | use vector offset
andw #0xfff,%d0 | sans frame type
addql #1,%a0@(-0x60,%d0:w) | to increment apropos counter
movw %sr,%sp@- | push current SR value
clrw %sp@- | padded to longword
jbsr _C_LABEL(intrhand) | handle interrupt
addql #4,%sp | pop SR
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei)
ENTRY_NOPROFILE(lev6intr)
#ifdef LEV6_DEFER
addql #1,_C_LABEL(intr_depth)
moveml %d0/%a0,%sp@-
INTREQRADDR(%a0)
movew %a0@,%d0
btst #INTB_EXTER,%d0
jeq Llev6spur
INTREQWADDR(%a0)
movew #INTF_SETCLR+INTF_AUD3,%a0@
INTENAWADDR(%a0)
movew #INTF_EXTER,%a0@
movew #INTF_SETCLR+INTF_AUD3,%a0@ | make sure THIS one is ok...
moveml %sp@+,%d0/%a0
subql #1,_C_LABEL(intr_depth)
rte
Llev6spur:
addql #1,_C_LABEL(intrcnt)+36 | count spurious level 6 interrupts
moveml %sp@+,%d0/%a0
subql #1,_C_LABEL(intr_depth)
rte
ENTRY_NOPROFILE(lev4intr)
ENTRY_NOPROFILE(fake_lev6intr)
#endif
addql #1,_C_LABEL(intr_depth)
INTERRUPT_SAVEREG
#ifdef LEV6_DEFER
INTREQRADDR(%a0)
movew %a0@,%d0
btst #INTB_EXTER,%d0
jeq Lintrcommon | if EXTER not pending, handle normally
#endif
CIABADDR(%a0)
movb %a0@(CIAICR),%d0 | read irc register (clears ints!)
jge Lchkexter | CIAB IR not set, go through isr chain
INTREQWADDR(%a0)
#ifndef LEV6_DEFER
movew #INTF_EXTER,%a0@ | clear EXTER interrupt in intreq
#else
movew #INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 in intreq
INTENAWADDR(%a0)
movew #INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts
#endif
btst #0,%d0 | timerA interrupt?
jeq Ltstciab4 | no
movl %d0,%sp@- | push CIAB interrupt flags
lea %sp@(4),%a1 | get pointer to clockframe
movl %a1,%sp@- | push pointer to clockframe
jbsr _C_LABEL(hardclock) | call generic clock int routine
addql #4,%sp | pop params
addql #1,_C_LABEL(intrcnt)+32 | add another system clock interrupt
movl %sp@+,%d0 | pop interrupt flags
Ltstciab4:
#include "fd.h"
#if NFD > 0
btst #4,%d0 | FLG (dskindex) interrupt?
jeq Lskipciab | no
jbsr _C_LABEL(fdidxintr) | tell floppy driver we got it
Lskipciab:
#endif
| other ciab interrupts?
Llev6done:
CPUINFO_INCREMENT(CI_NINTR)
INTERRUPT_RESTOREREG
subql #1,_C_LABEL(intr_depth)
jra _ASM_LABEL(rei) | all done [can we do rte here?]
Lchkexter:
| check to see if EXTER request is really set?
movl _C_LABEL(isr_exter),%a0 | get head of EXTER isr chain
Lnxtexter:
movl %a0,%d0 | test if any more entries
jeq Lexterdone | (spurious interrupt?)
movl %a0,%sp@- | save isr pointer
movl %a0@(ISR_ARG),%sp@-
movl %a0@(ISR_INTR),%a0
jsr %a0@ | call isr handler
addql #4,%sp
movl %sp@+,%a0 | restore isr pointer
movl %a0@(ISR_FORW),%a0 | get next pointer
tstl %d0 | did handler process the int?
jeq Lnxtexter | no, try next
Lexterdone:
INTREQWADDR(%a0)
#ifndef LEV6_DEFER
movew #INTF_EXTER,%a0@ | clear EXTER interrupt
#else
movew #INTF_EXTER+INTF_AUD3,%a0@ | clear EXTER & AUD3 interrupt
INTENAWADDR(%a0)
movew #INTF_SETCLR+INTF_EXTER,%a0@ | reenable EXTER interrupts
#endif
addql #1,_C_LABEL(intrcnt)+24 | count EXTER interrupts
jra Llev6done
ENTRY_NOPROFILE(lev7intr)
addql #1,_C_LABEL(intrcnt)+28
rte | all done
BSS(esym,4)
BSS(lowram,4)
#define RELOC(var, ar) \
lea _C_LABEL(var),ar; \
addl %a5,ar
#define ASRELOC(var, ar) \
lea _ASM_LABEL(var),ar; \
addl %a5,ar
.text
| XXX should be a symbol?
| 2: needs a4 = esym
| 3: no chipmem requirement
| bootinfo data structure
.word 0
.word 0x0003 | loadbsd version required
ASENTRY_NOPROFILE(start)
lea %pc@(L_base),%a5 | initialize relocation register
movw #PSL_HIGHIPL,%sr | no interrupts
ASRELOC(tmpstk,%a6)
movl %a6,%sp | give ourselves a temporary stack
| save the passed parameters. "prepass" them on the stack for
| later catch by start_c()
movl %a5,%sp@- | pass loadbase
movl %d6,%sp@- | pass boot partition offset
movl %a2,%sp@- | pass sync inhibit flags
movl %d3,%sp@- | pass AGA mode
movl %a4,%sp@- | pass address of _esym
movl %d1,%sp@- | pass chipmem-size
movl %d0,%sp@- | pass fastmem-size
movl %a0,%sp@- | pass fastmem_start
movl %d5,%sp@- | pass machine id
#ifdef DRACO
cmpb #0x7D,%sp@
jne LisAmiga1
| debug code:
| we should need about 1 uSec for the loop.
| we dont need the AGA mode register.
movel #100000,%d3
LisDraco0:
#ifdef DEBUG_KERNEL_START
movb #0,0x200003c8
movb #00,0x200003c9
movb #40,0x200003c9
movb #00,0x200003c9
|XXX:
movb #0,0x200003c8
movb #40,0x200003c9
movb #00,0x200003c9
movb #00,0x200003c9
subql #1,%d3
jcc LisDraco0
#endif
RELOC(chipmem_start, %a0)
movl #0,%a0@
RELOC(CIAAbase, %a0)
movl #0x2801001, %a0@
RELOC(CIABbase, %a0)
movl #0x2800000, %a0@
jra LisDraco1
LisAmiga1:
#endif
RELOC(chipmem_start, %a0)
movl #0x400,%a0@
RELOC(CIAAbase, %a0)
movl #0xbfe001,%a0@
RELOC(CIABbase, %a0)
movl #0xbfd000,%a0@
RELOC(CUSTOMbase, %a0)
movl #0xdff000,%a0@
#ifdef DRACO
LisDraco1:
#endif
RELOC(eclockfreq, %a0)
movl %d4,%a0@
movl #AMIGA_68030,%d1 | 68030 Attn flag from exec
andl %d5,%d1
jeq Ltestfor020
RELOC(mmutype, %a0)
movl #MMU_68030,%a0@ | assume 020 means 851
RELOC(cputype, %a0)
movl #CPU_68030,%a0@
jra Lsetcpu040 | skip to init.
Ltestfor020:
movl #AMIGA_68020,%d1 | 68020 Attn flag from exec
andl %d5,%d1
jeq Lsetcpu040
RELOC(mmutype, %a0)
movl #MMU_68851,%a0@
RELOC(cputype, %a0)
movl #CPU_68020,%a0@
Lsetcpu040:
movl #CACHE_OFF,%d0 | 68020/030 cache
movl #AMIGA_68040,%d1
andl %d1,%d5
jeq Lstartnot040 | it is not 68040
RELOC(mmutype, %a0)
movl #MMU_68040,%a0@ | same as hp300 for compat
RELOC(cputype, %a0)
movl #CPU_68040,%a0@
.word 0xf4f8 | cpusha bc - push and invalidate caches
movl #CACHE40_OFF,%d0 | 68040 cache disable
#ifndef BB060STUPIDROM
btst #7,%sp@(3)
jeq Lstartnot040
movl #CPU_68060,%a0@ | and in the cputype
orl #IC60_CABC,%d0 | XXX and clear all 060 branch cache
#else
movc %d0,%cacr
bset #30,%d0 | not allocate data cache bit
movc %d0,%cacr | does it stick?
movc %cacr,%d0
tstl %d0
jeq Lstartnot040
bset #7,%sp@(3) | note it is '60 family in machineid
movl #CPU_68060,%a0@ | and in the cputype
orl #IC60_CABC,%d0 | XXX and clear all 060 branch cache
.word 0x4e7a,0x1808 | movc pcr,d1
swap %d1
cmpw #0x430,%d1
jne Lstartnot040 | but no FPU
bset #6,%sp@(3) | yes, we have FPU, note that
swap %d1
bclr #1,%d1 | ... and switch it on.
.word 0x4e7b,0x1808 | movc d1,pcr
#endif
Lstartnot040:
movc %d0,%cacr | clear and disable on-chip cache(s)
movl #_C_LABEL(vectab),%a0
movc %a0,%vbr
RELOC(start_c, %a0)
jbsr %a0@
lea %sp@(4*9),%sp
#ifdef DRACO
RELOC(machineid,%a0)
cmpb #0x7d,%a0@
jne LAmiga_enable_MMU
lea %pc@(0),%a0
movl %a0,%d0
andl #0xff000000,%d0
orl #0x0000c044,%d0 | 16 MB, ro, cache inhibited
.word 0x4e7b,0x0004 | movc %d0,%itt0
.word 0xf518 | pflusha
movl #MMU40_TCR_BITS,%d0 | enable MMU
.word 0x4e7b,0x0003 | movc %d0,%tc
jmp Lcleanitt0:l
Lcleanitt0:
movq #0,%d0
.word 0x4e7b,0x0004 | movc %d0,%itt0
bra LMMUenable_end
LAmiga_enable_MMU:
#endif
lea LMMUenable_start,%a0
movl #LMMUenable_start:l,%a1
lea LMMUenable_end,%a2
Lcopy_MMU_enabler:
movl %a0@+,%a1@+
cmpl %a0,%a2
jgt Lcopy_MMU_enabler
jmp LMMUenable_start:l
LMMUenable_start:
#if defined(M68040) || defined(M68060)
RELOC(mmutype, %a0)
cmpl #MMU_68040,%a0@
jne Lenable030
.word 0xf518 | pflusha
movl #MMU40_TCR_BITS,%d0 | enable MMU
.word 0x4e7b,0x0003 | movc %d0,%tc
jmp LMMUenable_end:l
#endif
Lenable030:
pflusha
lea Ltc,%a0
pmove %a0@,%tc
jmp LMMUenable_end:l
Ltc: .long MMU51_TCR_BITS | see pmap.h
LMMUenable_end:
lea _ASM_LABEL(tmpstk),%sp | give ourselves a temporary stack
jbsr _C_LABEL(vec_init) | initialize the vector table
jbsr _C_LABEL(start_c_finish)
movl %a0,%sp | now running on lwp0's stack
movl #0,%a6 | terminate the stack back trace
jbsr _C_LABEL(_TBIA) | invalidate TLB
movl #CACHE_ON,%d0
tstl %d5
jeq Lcacheon
| is this needed? MLH
.word 0xf4f8 | cpusha bc - push & invalidate caches
movl #CACHE40_ON,%d0
#ifdef M68060
cmpl #CPU_68060,_C_LABEL(cputype)
jne Lcacheon
movl #PCR_ESS,%d0 | enable superscalar dispatch
.long 0x4e7b0808 | movc %d0,%pcr
movl #CACHE60_ON,%d0
#endif
Lcacheon:
movc %d0,%cacr | clear cache(s)
movw #PSL_LOWIPL,%sr | lower SPL
movl %d7,_C_LABEL(boothowto) | save reboot flags
jra _C_LABEL(main) | main() (never returns)
ENTRY(qsetjmp)
movl %sp@(4),%a0 | savearea pointer
lea %a0@(40),%a0 | skip regs we do not save
movl %a6,%a0@+ | save FP
movl %sp,%a0@+ | save SP
movl %sp@,%a0@ | and return address
moveq #0,%d0 | return 0
rts
ENTRY(probeva)
movl %sp@(8),%d0
movec %d0,%dfc
movl %sp@(4),%a0
.word 0xf548 | ptestw (a0)
moveq #FC_USERD,%d0 | restore DFC to user space
movc %d0,%dfc
.word 0x4e7a,0x0805 | movec MMUSR,d0
rts
#if defined(P5PPC68KBOARD)
.data
GLOBAL(p5ppc)
.long 0
.text
#endif
ENTRY_NOPROFILE(machine_reboot)
movl #CACHE_OFF,%d0
cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040
jne Ldoboot0
.word 0xf4f8 | cpusha bc - push and invalidate caches
nop
movl #CACHE40_OFF,%d0
Ldoboot0:
movc %d0,%cacr | disable on-chip cache(s)
movw #0x2700,%sr | cut off any interrupts
#if defined(P5PPC68KBOARD)
tstl _C_LABEL(p5ppc)
jne Lp5ppcboot
#endif
#if defined(DRACO)
cmpb #0x7d,_C_LABEL(machineid)
jeq LdbOnDraCo
#endif
| clear first 4k of CHIPMEM
movl _C_LABEL(CHIPMEMADDR),%a0
movl %a0,%a1
movl #1024,%d0
Ldb1:
clrl %a0@+
dbra %d0,Ldb1
| now, copy the following code over
| lea %a1@(Ldoreboot),%a0 | KVA starts at 0, CHIPMEM is phys 0
| lea %a1@(Ldorebootend),%a1
| lea %pc@(Ldoreboot-.+2),%a0
| addl %a1,%a0
| lea %a0@(128),%a1
| lea %pc@(Ldoreboot-.+2),%a2
lea Ldoreboot,%a2
lea Ldorebootend,%a0
addl %a1,%a0
addl %a2,%a1
exg %a0,%a1
Ldb2:
movel %a2@+,%a0@+
cmpl %a1,%a0
jle Ldb2
| ok, turn off MMU..
Ldoreboot:
cmpl #MMU_68040,_C_LABEL(mmutype) | is it 68040
jeq Lmmuoff040
lea _ASM_LABEL(zero),%a0
pmove %a0@,%tc | Turn off MMU
lea _ASM_LABEL(nullrp),%a0
pmove %a0@,%crp | Turn off MMU some more
pmove %a0@,%srp | Really, really, turn off MMU
jra Ldoboot1
Lmmuoff040:
movl #0,%d0
.word 0x4e7b,0x0003 | movc d0,TC
.word 0x4e7b,0x0806 | movc d0,URP
.word 0x4e7b,0x0807 | movc d0,SRP
Ldoboot1:
| this weird code is the OFFICIAL way to reboot an Amiga ! ..
lea 0x1000000,%a0
subl %a0@(-0x14),%a0
movl %a0@(4),%a0
subl #2,%a0
cmpw #0x4e70,%a0@ | 68040 kludge: if ROM entry is not
jne Ldoreset | a reset, do the reset here
jmp %a0@ | otherwise, jump to the ROM to reset
| reset needs to be on longword boundary
nop
#ifdef __ELF__
.align 4
#else
.align 2
#endif
Ldoreset:
| reset unconfigures all memory!
reset
| now rely on prefetch for next jmp
jmp %a0@
| NOT REACHED
#if defined(P5PPC68KBOARD)
Lp5ppcboot:
| The Linux-Apus boot code does it in a similar way
| For 040 on uncached pages, eieio can be replaced by nothing.
movl _C_LABEL(ZTWOROMADDR),%a0
lea %a0@(0xf60000-0xd80000),%a0
movb #0x60,%a0@(0x20)
movb #0x50,%a0@(0x20)
movb #0x30,%a0@(0x20)
movb #0x40,%a0@(0x18)
movb #0x04,%a0@
Lwaithere:
jra Lwaithere
#endif
#ifdef DRACO
LdbOnDraCo:
| we use a TTR. We want to boot even if half of us is already dead.
movl _C_LABEL(boot_fphystart), %d0
lea LdoDraCoBoot, %a0
lea %a0@(%d0),%a0
andl #0xFF000000,%d0
orl #0x0000C044,%d0 | enable, supervisor, CI, RO
.word 0x4e7b,0x0004 | movc d0,ITT0
jmp %a0@
#ifdef __ELF__
.align 4
#else
.align 2
#endif
LdoDraCoBoot:
| turn off MMU now ... were more ore less guaranteed to run on 040/060:
movl #0,%d0
.word 0x4e7b,0x0003 | movc d0,TC
.word 0x4e7b,0x0806 | movc d0,URP
.word 0x4e7b,0x0807 | movc d0,SRP
.word 0x4e7b,0x0004 | movc d0,ITT0
nop
| map in boot ROM @0:
reset
| and simulate what a reset exception would have done.
movl 4,%a0
movl 0,%a7
jmp %a0@
| NOT REACHED
#endif
ENTRY_NOPROFILE(kernel_reload)
lea Lreload_copy,%a0 | cursory validity check of new kernel
movl %a0@,%d0 | to see if the kernel reload code
addl %sp@(4),%a0 | in new image matches running kernel
cmpl %a0@,%d0
jeq Lreload_ok
rts | It doesn't match - can't reload
Lreload_ok:
jsr _C_LABEL(bootsync)
CUSTOMADDR(%a5)
movew #(1<<9),%a5@(0x096) | disable DMA (before clobbering chipmem)
movl #CACHE_OFF,%d0
cmpl #MMU_68040,_C_LABEL(mmutype)
jne Lreload1
.word 0xf4f8 | cpusha bc - push and invalidate caches
nop
movl #CACHE40_OFF,%d0
Lreload1:
movc %d0,%cacr | disable on-chip cache(s)
movw #0x2700,%sr | cut off any interrupts
movel _C_LABEL(boothowto),%d7 | save boothowto
movel _C_LABEL(machineid),%d5 | (and machineid)
movel %sp@(16),%a0 | load memory parameters
movel %sp@(20),%d0
movel %sp@(24),%d1
movel %sp@(28),%a4 | esym
movel %sp@(32),%d4 | eclockfreq
movel %sp@(36),%d3 | AGA mode
movel %sp@(40),%a2 | sync inhibit flags
movel %sp@(44),%d6 | boot partition offset
movel %sp@(12),%a6 | find entrypoint (a6)
movel %sp@(4),%a1 | copy kernel to low chip memory
movel %sp@(8),%d2
movl _C_LABEL(CHIPMEMADDR),%a3
Lreload_copy:
movel %a1@+,%a3@+
subl #4,%d2
jcc Lreload_copy
| ok, turn off MMU..
cmpl #MMU_68040,_C_LABEL(mmutype)
jeq Lreload040
lea _ASM_LABEL(zero),%a3
pmove %a3@,%tc | Turn off MMU
lea _ASM_LABEL(nullrp),%a3
pmove %a3@,%crp | Turn off MMU some more
pmove %a3@,%srp | Really, really, turn off MMU
jra Lreload2
Lreload040:
movl #0,%d2
.word 0x4e7b,0x2003 | movc d2,TC
.word 0x4e7b,0x2806 | movc d2,URP
.word 0x4e7b,0x2807 | movc d2,SRP
Lreload2:
moveq #0,%d2 | clear unused registers
subl %a1,%a1
subl %a3,%a3
subl %a5,%a5
jmp %a6@ | start new kernel
| A do-nothing MMU root pointer (includes the following long as well)
ASLOCAL(nullrp)
.long 0x7fff0001
ASLOCAL(zero)
.long 0
Ldorebootend:
.data
.space PAGE_SIZE
.align 4
ASGLOBAL(tmpstk)
GLOBAL(mmutype)
.long MMU_68851
GLOBAL(cputype)
.long CPU_68020
GLOBAL(ectype)
.long EC_NONE
GLOBAL(delay_divisor)
.long 12 | should be enough for 80 MHz 68060
| will be adapted to other CPUs in
| start_c_cleanup and calibrated
| at clock attach time.
#ifdef DEBUG
ASGLOBAL(fulltflush)
.long 0
ASGLOBAL(fullcflush)
.long 0
ASGLOBAL(timebomb)
.long 0
#endif
GLOBAL(intrnames)
.asciz "spur" | spurious interrupt
.asciz "tbe/soft" | serial TBE & software
.asciz "kbd/ports" | keyboard & PORTS
.asciz "vbl" | vertical blank
.asciz "audio" | audio channels
.asciz "rbf" | serial receive
.asciz "exter" | EXTERN
.asciz "nmi" | non-maskable
.asciz "clock" | clock interrupts
.asciz "spur6" | spurious level 6
#ifdef DRACO
.asciz "kbd/soft" | 1: native keyboard, soft ints
.asciz "cia/zbus" | 2: cia, PORTS
.asciz "lclbus" | 3: local bus, e.g. Altais vbl
.asciz "drscsi" | 4: mainboard scsi
.asciz "superio" | 5: superio chip
.asciz "lcl/zbus" | 6: lcl/zorro lev6
.asciz "buserr" | 7: nmi: bus timeout
#endif
GLOBAL(eintrnames)
#ifdef __ELF__
.align 4
#else
.align 2
#endif
GLOBAL(intrcnt)
.long 0,0,0,0,0,0,0,0,0,0
#ifdef DRACO
ASLOCAL(Drintrcnt)
.long 0,0,0,0,0,0,0
#endif
GLOBAL(eintrcnt)