#include "opt_compat_netbsd.h"
#include "opt_compat_sunos.h"
#include "opt_fpsp.h"
#include "opt_ddb.h"
#include "opt_kgdb.h"
#include "opt_lockdebug.h"
#include "opt_m68k_arch.h"
#include "opt_mvmeconf.h"
#include "assym.h"
#include <machine/asm.h>
#include <machine/trap.h>
#include "ksyms.h"
.data
.space PAGE_SIZE
ASGLOBAL(tmpstk)
#define _RELOC(var, ar) \
lea var,ar
#define RELOC(var, ar) _RELOC(_C_LABEL(var), ar)
#define ASRELOC(var, ar) _RELOC(_ASM_LABEL(var), ar)
#define CALLBUG(func) \
trap #15; .short func
BSS(lowram,4)
BSS(esym,4)
.globl _C_LABEL(edata)
.globl _C_LABEL(etext),_C_LABEL(end)
.text
GLOBAL(kernel_text)
ASENTRY_NOPROFILE(start)
movw #PSL_HIGHIPL,%sr | no interrupts
movl #0,%a5 | RAM starts at 0 (a5)
movl %sp@(4), %d7 | get boothowto
movl %sp@(8), %d6 | get bootaddr
movl %sp@(12),%d5 | get bootctrllun
movl %sp@(16),%d4 | get bootdevlun
movl %sp@(20),%d3 | get bootpart
movl %sp@(24),%d2 | get esyms
RELOC(bootpart,%a0)
movl %d3, %a0@ | save bootpart
RELOC(bootdevlun,%a0)
movl %d4, %a0@ | save bootdevlun
RELOC(bootctrllun,%a0)
movl %d5, %a0@ | save booctrllun
RELOC(bootaddr,%a0)
movl %d6, %a0@ | save bootaddr
RELOC(boothowto,%a0)
movl %d7, %a0@ | save boothowto
ASRELOC(tmpstk, %a0)
movl %a0,%sp | give ourselves a temporary stack
RELOC(edata,%a0) | clear out BSS
movl #_C_LABEL(end) - 4, %d0 | (must be <= 256 kB)
subl #_C_LABEL(edata), %d0
lsrl #2,%d0
1: clrl %a0@+
dbra %d0,1b
RELOC(esym, %a0)
movl %d2,%a0@ | store end of symbol table
RELOC(lowram, %a0)
movl %a5,%a0@ | store start of physical memory
movl #CACHE_OFF,%d0
movc %d0,%cacr | clear and disable on-chip cache(s)
clrl %sp@-
CALLBUG(MVMEPROM_GETBRDID)
movl %sp@+,%a1
movl #MVMEPROM_BRDID_SIZE,%d0
RELOC(boardid,%a0)
1: movb %a1@+,%a0@+
subql #1,%d0
jbne 1b
clrl %d0
RELOC(boardid,%a1)
movw %a1@(MVMEPROM_BRDID_MODEL_OFFSET),%d0
RELOC(machineid,%a0)
movl %d0,%a0@
ASRELOC(Lbrdid2mach,%a0)
Lbrdmatch:
cmpw %a0@+,%d0
jbeq Lgotmatch
addw #10,%a0
tstw %a0@
jbne Lbrdmatch
movl #Lenotconf,%sp@-
movl #Lnotconf,%sp@-
CALLBUG(MVMEPROM_OUTSTRCRLF)
addql #8,%sp | clean up stack after call
CALLBUG(MVMEPROM_EXIT)
.data
Lnotconf:
.ascii "Sorry, the kernel isn't configured for this model."
Lenotconf:
.even
ASLOCAL(Lbrdid2mach)
#ifdef MVME147
.word MVME_147
.word CPU_68030
.word MMU_68030
.word FPU_68882
.long Linit147
#endif
#ifdef MVME162
.word MVME_162
.word CPU_68040
.word MMU_68040
.word FPU_68040
.long Linit1x2
#endif
#ifdef MVME167
.word MVME_167
.word CPU_68040
.word MMU_68040
.word FPU_68040
.long Linit1x7
#endif
#ifdef MVME172
.word MVME_172
.word CPU_68060
.word MMU_68040
.word FPU_68060
.long Linit1x2
#endif
#ifdef MVME177
.word MVME_177
.word CPU_68060
.word MMU_68040
.word FPU_68060
.long Linit1x7
#endif
.word 0
.text
.even
Lgotmatch:
movew %a0@+,%d1 | Copy the CPU type
extl %d1
RELOC(cputype,%a1)
movel %d1,%a1@
movew %a0@+,%d1 | Copy the MMU type
extl %d1
RELOC(mmutype,%a1)
movel %d1,%a1@
movew %a0@+,%d1 | Copy the FPU type
extl %d1
RELOC(fputype,%a1)
movel %d1,%a1@
movel %a0@,%a0 | Finally, the board-specific init code
jmp %a0@
#ifdef MVME147
Linit147:
movb #0, 0xfffe1026 | serial interrupt off
movb #0, 0xfffe1018 | timer 1 off
movb #0, 0xfffe1028 | ethernet off
RELOC(mvme_ea, %a0)
lea 0xfffe0778,%a1 | XXXCDC -- HARDWIRED HEX
movb #0x08,%a0@+
clrb %a0@+
movb #0x3e,%a0@+
movql #0x0f,%d0
andb %a1@+,%d0
orb #0x20,%d0
movb %d0,%a0@+
movb %a1@+,%a0@+
movb %a1@,%a0@
RELOC(intiobase_phys, %a0);
movl #INTIOBASE147,%a0@
RELOC(intiosize, %a0);
movl #INTIOSIZE147,%a0@
RELOC(phys_seg_list, %a0)
movl %a5,%a0@(PS_START) | phys_seg_list[0].ps_start
movl 0xfffe0774,%d1 | End + 1 of onboard memory
movl %d1,%a0@(PS_END) | phys_seg_list[0].ps_end
lea %a0@(SIZEOF_PHYSSEGLIST),%a0
clrl %a0@(PS_START) | phys_seg_list[1].ps_start
movl #PAGE_SIZE-1,%d0
addl 0xfffe0764,%d0 | Start of offboard segment
andl #-PAGE_SIZE,%d0 | Round up to page boundary
jbeq Lsavmaxmem | Jump if none defined
movl #PAGE_SIZE,%d1 | Note: implicit '+1'
addl 0xfffe0768,%d1 | End of offboard segment
andl #-PAGE_SIZE,%d1 | Round up to page boundary
cmpl %d1,%d0 | Quick and dirty validity check
jbcs Loff_ok | Yup, looks good.
RELOC(phys_seg_list, %a0)
movel %a0@(PS_END),%d1 | Just use onboard RAM otherwise
jbra Lsavmaxmem
Loff_ok:
movl %d0,%a0@(PS_START) | phys_seg_list[1].ps_start
movl %d1,%a0@(PS_END) | phys_seg_list[1].ps_end
movel %d0,%a0 | offboard start address again.
Lclearoff:
clrl %a0@+ | zap a word
cmpl %a0,%d1 | reached end?
jbne Lclearoff
jra Lsavmaxmem | save maxmem and continue with boot
#endif
#if defined(MVME162) || defined(MVME172)
Linit1x2:
btst #0,0xfff4202d | Clear == jumper installed
jne 1f | Ok.
movl #Le1x2jump,%sp@-
movl #L1x2jump,%sp@-
CALLBUG(MVMEPROM_OUTSTRCRLF)
addql #8,%sp | clean up stack after call
CALLBUG(MVMEPROM_EXIT)
1:
btst #1,0xfff4202e | VMEchip2 presence detect
jne 2f | Jump if it doesn't exist.
movl 0xfff40088,%d0
andl #0xff7fffff,%d0 | Clear 'MIEN'
movl %d0,0xfff40088
2:
movql #0x07,%d0
andb 0xfff42024,%d0
ASRELOC(Ldramsize1x2,%a0)
movl %a0@(%d0:w:4),%d1 | Lookup the size
jeq Lmemcquery | Assume a MEMC chip if this is zero.
jra Lis1xx_common
.data
.even
ASLOCAL(Ldramsize1x2)
.long 0x00100000
.long 0x00200000
.long 0x00000000
.long 0x00400000
.long 0x00400000
.long 0x00800000
.long 0x00000000
.long 0x01000000
L1x2jump:
.ascii "You must remove the jumper from pins 15-16 of J22 (mvme162)"
.ascii "or pins 1-2\015\012"
.ascii "J11 (mvme162-LX) first! See NetBSD/mvme68k FAQ for details."
Le1x2jump:
.even
.text
#endif
#if defined(MVME167) || defined(MVME177)
Linit1x7:
movel #0x00000001,%d0
andl 0xfff40088,%d0 | Clear == jumper installed
jne 1f | Ok.
movl #Le1x7jump,%sp@-
movl #L1x7jump,%sp@-
CALLBUG(MVMEPROM_OUTSTRCRLF)
addql #8,%sp | clean up stack after call
CALLBUG(MVMEPROM_EXIT)
1:
movl 0xfff40088,%d0
andl #0xff7fffff,%d0 | Clear 'MIEN'
movl %d0,0xfff40088
.data
.even
L1x7jump:
.ascii "You must remove the jumper from pins 1-2 of J1!\015\012"
.ascii "See NetBSD/mvme68k FAQ for details."
Le1x7jump:
.even
.text
#endif
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
Lmemcquery:
lea 0xfff43008,%a0 | MEMC040/MEMECC Controller #1
jbsr memc040read
movl %d0,%d1
lea 0xfff43108,%a0 | MEMC040/MEMECC Controller #2
jbsr memc040read
addl %d0,%d1
Lis1xx_common:
RELOC(mvme_ea, %a0)
lea 0xfffc1f2c,%a1
movb %a1@+,%a0@+
movb %a1@+,%a0@+
movb %a1@+,%a0@+
movb %a1@+,%a0@+
movb %a1@+,%a0@+
movb %a1@,%a0@
RELOC(intiobase_phys, %a0);
movl #INTIOBASE1xx,%a0@
RELOC(intiosize, %a0);
movl #INTIOSIZE1xx,%a0@
RELOC(phys_seg_list, %a0)
movl %a5,%a0@(PS_START) | phys_seg_list[0].ps_start
movl %d1,%a0@(PS_END) | phys_seg_list[0].ps_end
lea %a0@(SIZEOF_PHYSSEGLIST),%a0
clrl %a0@(PS_START) | phys_seg_list[1].ps_start
movl #PAGE_SIZE-1,%d0
addl 0xfffc0000,%d0 | Start of offboard segment
andl #-PAGE_SIZE,%d0 | Round up to page boundary
jbeq Lsavmaxmem | Jump if none defined
movl #PAGE_SIZE,%d1 | Note: implicit '+1'
addl 0xfffc0004,%d1 | End of offboard segment
andl #-PAGE_SIZE,%d1 | Round up to page boundary
cmpl %d1,%d0 | Quick and dirty validity check
jbcs Lramsave1xx | Yup, looks good.
RELOC(phys_seg_list, %a0)
movel %a0@(PS_END),%d1 | Just use onboard RAM otherwise
jbra Lsavmaxmem
Lramsave1xx:
movl %d0,%a0@(PS_START) | phys_seg_list[1].ps_start
movl %d1,%a0@(PS_END) | phys_seg_list[1].ps_end
movel %d0,%a0 | offboard start address again.
Lramclr1xx:
clrl %a0@+ | zap a word
cmpl %a0,%d1 | reached end?
jbne Lramclr1xx
#endif
Lsavmaxmem:
moveq #PGSHIFT,%d2
lsrl %d2,%d1 | convert to page (click) number
RELOC(physmem, %a0)
movl %d1,%a0@ | save into physmem
#if NKSYMS || defined(DDB) || defined(MODULAR)
RELOC(esym,%a0) | end of static kernel text/data syms
movl %a0@,%a4
tstl %a4
jne Lstart2
#endif
movl #_C_LABEL(end),%a4 | end of static kernel text/data
Lstart2:
addl %a5,%a4 | convert to PA
pea %a5@ | reloff
pea %a4@ | nextpa
RELOC(pmap_bootstrap1,%a0)
jbsr %a0@ | pmap1_bootstrap1(nextpa, reloff)
addql #8,%sp
movl %d0, %d7
#include <m68k/m68k/mmu_enable.s>
Lmmuenabled:
lea _ASM_LABEL(tmpstk),%sp | re-load temporary stack
jbsr _C_LABEL(vec_init) | initialize vector table
jbsr _C_LABEL(pmap_bootstrap2)
movl %a0,%sp | now running on lwp0's stack
movl #0,%a6 | terminate the stack back trace
movl %d7,%sp@- | push nextpa saved above
jbsr _C_LABEL(machine_init) | additional pre-main initialization
addql #4,%sp
movw #PSL_LOWIPL,%sr | lower SPL
jra _C_LABEL(main) | main() (never returns)
#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
ASLOCAL(memc040read)
moveml %d1-%d2/%a1-%a2,%sp@- | save scratch regs
movc %vbr,%d2 | Save vbr
RELOC(vectab,%a2) | Install our own vectab, temporarily
movc %a2,%vbr
ASRELOC(Lmemc040berr,%a1) | get address of bus error handler
movl %a2@(8),%sp@- | Save current bus error handler addr
movl %a1,%a2@(8) | Install our own handler
movl %sp,%d0 | Save current stack pointer value
movql #0x07,%d1
andb %a0@,%d1 | Access MEMC040/MEMECC
movl #0x400000,%d0
lsll %d1,%d0 | Convert to memory size, in bytes
Lmemc040ret:
movc %d2,%vbr | Restore original vbr
movl %sp@+,%a2@(8) | Restore original bus error handler
moveml %sp@+,%d1-%d2/%a1-%a2
rts
Lmemc040berr:
movl %d0,%sp | Get rid of the exception frame
movql #0,%d0 | No ASIC at this location, then!
jbra Lmemc040ret | Done
#endif
ENTRY_NOPROFILE(machine_reboot)
movw #PSL_HIGHIPL,%sr
movl _C_LABEL(boothowto),%d1 | load howto
movl %sp@(4),%d2 | arg
andl #RB_HALT,%d2 | %d2 == 0 -> autoboot, else halt
movl _C_LABEL(saved_vbr),%d3 | Fetch Bug's original VBR value
movl _C_LABEL(machineid),%d4 | What type of board is this?
movl #CACHE_OFF,%d0
#if defined(M68040) || defined(M68060)
cmpl #MMU_68040,_C_LABEL(mmutype) | 68040/68060?
jne Lnocache0 | no, skip
.word 0xf4f8 | cpusha bc - push and invalidate caches
nop
movl #CACHE40_OFF,%d0
#endif
Lnocache0:
movc %d0,%cacr | disable on-chip cache(s)
#if defined(M68040) || defined(M68060)
cmpl #MMU_68040,_C_LABEL(mmutype)
jne LmotommuF
movql #0,%d0
movc %d0,%cacr
.long 0x4e7b0003 | movc d0,tc
jra Lbootcommon
LmotommuF:
#endif
clrl %sp@- | value for pmove to TC (turn off MMU)
pmove %sp@,%tc | disable MMU
addql #4,%sp
Lbootcommon:
ASRELOC(tmpstk, %sp) | physical SP in case of NMI
movc %d3,%vbr | Restore Bug's VBR
andl #RB_SBOOT, %d1 | mask off
jbne Lsboot | sboot?
tstl %d2 | autoboot?
jbeq Ldoreset | yes!
CALLBUG(MVMEPROM_EXIT) | return to bug
Ldoreset:
movl #0xff800000,%a0 | Bug's reset vector address
movl %a0@+, %a7 | get SP
movl %a0@, %a0 | get PC
jmp %a0@ | go!
Lsboot:
tstl %d2 | autoboot?
jbeq 1f | yes!
jmp 0x4000 | back to sboot
1: jmp 0x400a | tell sboot to reboot us
STRONG_ALIAS(machine_halt,machine_reboot)
.data
GLOBAL(machineid)
.long MVME_147 | default to MVME_147
GLOBAL(mmutype)
.long MMU_68030 | default to MMU_68030
GLOBAL(cputype)
.long CPU_68030 | default to CPU_68030
GLOBAL(bootpart)
.long 0
GLOBAL(bootdevlun)
.long 0
GLOBAL(bootctrllun)
.long 0
GLOBAL(bootaddr)
.long 0
GLOBAL(intiobase)
.long 0 | KVA of base of internal IO space
GLOBAL(machine_bootmap)
.long _C_LABEL(intiobase) | [0].pmbm_vaddr_ptr = &intiobase
GLOBAL(intiobase_phys)
.long 0 | [0].pmbm_paddr = PA of internal I/O space
GLOBAL(intiosize)
.long 0 | [0].pmbm_size = size of internal I/O space
.long PMBM_F_CI | [0].pmbm_flags = cache-inhibited mapping
.long -1 | [1].pmbm_vaddr = end of list