xref: /netbsd-src/sys/arch/mvme68k/mvme68k/locore.s (revision 2c6fc41c810f5088457889d00eba558e8bc74d9e)
1/*	$NetBSD: locore.s,v 1.114 2014/03/15 12:04:22 tsutsui Exp $	*/
2
3/*
4 * Copyright (c) 1988 University of Utah.
5 * Copyright (c) 1980, 1990, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * the Systems Programming Group of the University of Utah Computer
10 * Science Department.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. Neither the name of the University nor the names of its contributors
21 *    may be used to endorse or promote products derived from this software
22 *    without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * from: Utah $Hdr: locore.s 1.66 92/12/22$
37 *
38 *	@(#)locore.s	8.6 (Berkeley) 5/27/94
39 */
40
41#include "opt_compat_netbsd.h"
42#include "opt_compat_svr4.h"
43#include "opt_compat_sunos.h"
44#include "opt_fpsp.h"
45#include "opt_ddb.h"
46#include "opt_kgdb.h"
47#include "opt_lockdebug.h"
48#include "opt_m68k_arch.h"
49
50#include "assym.h"
51#include <machine/asm.h>
52#include <machine/trap.h>
53
54#include "ksyms.h"
55
56/*
57 * Temporary stack for a variety of purposes.
58 * Try and make this the first thing is the data segment so it
59 * is page aligned.  Note that if we overflow here, we run into
60 * our text segment.
61 */
62	.data
63	.space	PAGE_SIZE
64ASLOCAL(tmpstk)
65
66ASLOCAL(bug_vbr)
67	.long	0
68
69#include <mvme68k/mvme68k/vectors.s>
70
71
72/*
73 * Macro to relocate a symbol, used before MMU is enabled.
74 */
75#define	_RELOC(var, ar)		\
76	lea	var,ar
77
78#define	RELOC(var, ar)		_RELOC(_C_LABEL(var), ar)
79#define	ASRELOC(var, ar)	_RELOC(_ASM_LABEL(var), ar)
80
81/*
82 * Macro to call into the Bug ROM monitor
83 */
84#define	CALLBUG(func)	\
85	trap #15; .short func
86
87/*
88 * Initialization
89 *
90 * The bootstrap loader loads us in starting at 0, and VBR is non-zero.
91 * On entry, args on stack are boot device, boot filename, console unit,
92 * boot flags (howto), boot device name, filesystem type name.
93 */
94BSS(lowram,4)
95BSS(esym,4)
96
97	.globl	_C_LABEL(edata)
98	.globl	_C_LABEL(etext),_C_LABEL(end)
99
100
101/*
102 * This is for kvm_mkdb, and should be the address of the beginning
103 * of the kernel text segment (not necessarily the same as kernbase).
104 */
105	.text
106GLOBAL(kernel_text)
107
108/*
109 * start of kernel and .text!
110 */
111ASENTRY_NOPROFILE(start)
112	movw	#PSL_HIGHIPL,%sr	| no interrupts
113	movl	#0,%a5			| RAM starts at 0 (a5)
114	movl	%sp@(4), %d7		| get boothowto
115	movl	%sp@(8), %d6		| get bootaddr
116	movl	%sp@(12),%d5		| get bootctrllun
117	movl	%sp@(16),%d4		| get bootdevlun
118	movl	%sp@(20),%d3		| get bootpart
119	movl	%sp@(24),%d2		| get esyms
120
121	RELOC(bootpart,%a0)
122	movl	%d3, %a0@		| save bootpart
123	RELOC(bootdevlun,%a0)
124	movl	%d4, %a0@		| save bootdevlun
125	RELOC(bootctrllun,%a0)
126	movl	%d5, %a0@		| save booctrllun
127	RELOC(bootaddr,%a0)
128	movl	%d6, %a0@		| save bootaddr
129	RELOC(boothowto,%a0)
130	movl	%d7, %a0@		| save boothowto
131	/* note: d3-d7 free, d2 still in use */
132
133	ASRELOC(tmpstk, %a0)
134	movl	%a0,%sp			| give ourselves a temporary stack
135
136	RELOC(edata,%a0)		| clear out BSS
137	movl	#_C_LABEL(end) - 4, %d0	| (must be <= 256 kB)
138	subl	#_C_LABEL(edata), %d0
139	lsrl	#2,%d0
1401:	clrl	%a0@+
141	dbra	%d0,1b
142
143	RELOC(esym, %a0)
144	movl	%d2,%a0@		| store end of symbol table
145	/* d2 now free */
146	RELOC(lowram, %a0)
147	movl	%a5,%a0@		| store start of physical memory
148	movl	#CACHE_OFF,%d0
149	movc	%d0,%cacr		| clear and disable on-chip cache(s)
150
151	/* ask the Bug what we are... */
152	clrl	%sp@-
153	CALLBUG(MVMEPROM_GETBRDID)
154	movl	%sp@+,%a1
155
156	/* copy to a struct mvmeprom_brdid */
157	movl	#MVMEPROM_BRDID_SIZE,%d0
158	RELOC(boardid,%a0)
1591:	movb	%a1@+,%a0@+
160	subql	#1,%d0
161	jbne	1b
162
163	/*
164	 * Grab the model number from _boardid and use the value
165	 * to setup machineid, cputype, and mmutype.
166	 */
167	clrl	%d0
168	RELOC(boardid,%a1)
169	movw	%a1@(MVMEPROM_BRDID_MODEL_OFFSET),%d0
170	RELOC(machineid,%a0)
171	movl	%d0,%a0@
172
173	ASRELOC(Lbrdid2mach,%a0)
174Lbrdmatch:
175	cmpw	%a0@+,%d0
176	jbeq	Lgotmatch
177	addw	#0x12,%a0		| Each entry is 20-2 bytes long
178	tstw	%a0@
179	jbne	Lbrdmatch
180
181	/*
182	 * If we fall to here, the board is not supported.
183	 * Print a warning, then drop out to the Bug.
184	 */
185	movl	#Lenotconf,%sp@-
186	movl	#Lnotconf,%sp@-
187	CALLBUG(MVMEPROM_OUTSTRCRLF)
188	addql	#8,%sp			| clean up stack after call
189
190	CALLBUG(MVMEPROM_EXIT)
191	/* NOTREACHED */
192
193	.data
194Lnotconf:
195	.ascii	"Sorry, the kernel isn't configured for this model."
196Lenotconf:
197	.even
198
199ASLOCAL(Lbrdid2mach)
200#ifdef MVME147
201	.word	MVME_147
202	.word		CPU_68030
203	.word		MMU_68030
204	.word		FPU_68882
205	.long		_C_LABEL(busaddrerr2030)
206	.long		_C_LABEL(busaddrerr2030)
207	.long		Linit147
208#endif
209#ifdef MVME162
210	.word	MVME_162
211	.word		CPU_68040
212	.word		MMU_68040
213	.word		FPU_68040
214	.long		_C_LABEL(buserr40)
215	.long		_C_LABEL(addrerr4060)
216	.long		Linit1x2
217#endif
218#ifdef MVME167
219	.word	MVME_167
220	.word		CPU_68040
221	.word		MMU_68040
222	.word		FPU_68040
223	.long		_C_LABEL(buserr40)
224	.long		_C_LABEL(addrerr4060)
225	.long		Linit1x7
226#endif
227#ifdef MVME172
228	.word	MVME_172
229	.word		CPU_68060
230	.word		MMU_68040
231	.word		FPU_68060
232	.long		_C_LABEL(buserr60)
233	.long		_C_LABEL(addrerr4060)
234	.long		Linit1x2
235#endif
236#ifdef MVME177
237	.word	MVME_177
238	.word		CPU_68060
239	.word		MMU_68040
240	.word		FPU_68060
241	.long		_C_LABEL(buserr60)
242	.long		_C_LABEL(addrerr4060)
243	.long		Linit1x7
244#endif
245	.word	0
246	.text
247	.even
248
249/*
250 * We have a match, so the kernel should support this board.
251 * a0 points to the matching entry in Lbrdid2mach.
252 */
253Lgotmatch:
254	movew	%a0@+,%d1		| Copy the CPU type
255	extl	%d1
256	RELOC(cputype,%a1)
257	movel	%d1,%a1@
258	movew	%a0@+,%d1		| Copy the MMU type
259	extl	%d1
260	RELOC(mmutype,%a1)
261	movel	%d1,%a1@
262	movew	%a0@+,%d1		| Copy the FPU type
263	extl	%d1
264	RELOC(fputype,%a1)
265	movel	%d1,%a1@
266	movel	%a0@+,%a2		| Fetch the bus error vector
267	RELOC(vectab,%a1)
268	movl	%a2,%a1@(8)
269	movel	%a0@+,%a2		| Fetch the address error vector
270	movl	%a2,%a1@(12)
271	movel	%a0@,%a0		| Finally, the board-specific init code
272	jmp	%a0@
273
274
275#ifdef MVME147
276Linit147:
277	/* MVME-147 - 68030 CPU/MMU, 68882 FPU */
278	/* XXXCDC SHUTUP 147 CALL */
279	movb	#0, 0xfffe1026		| serial interrupt off
280	movb	#0, 0xfffe1018		| timer 1 off
281	movb	#0, 0xfffe1028		| ethernet off
282	/* XXXCDC SHUTUP 147 CALL */
283
284	/* Save our ethernet address */
285	RELOC(mvme_ea, %a0)
286	lea	0xfffe0778,%a1		| XXXCDC -- HARDWIRED HEX
287	movb	#0x08,%a0@+
288	clrb	%a0@+
289	movb	#0x3e,%a0@+
290	movql	#0x0f,%d0
291	andb	%a1@+,%d0
292	orb	#0x20,%d0
293	movb	%d0,%a0@+
294	movb	%a1@+,%a0@+
295	movb	%a1@,%a0@
296
297	/*
298	 * Fix up the physical addresses of the MVME147's onboard
299	 * I/O registers.
300	 */
301	RELOC(intiobase_phys, %a0);
302	movl	#INTIOBASE147,%a0@
303	RELOC(intiotop_phys, %a0);
304	movl	#INTIOTOP147,%a0@
305
306	/* initialise list of physical memory segments for pmap_bootstrap */
307	RELOC(phys_seg_list, %a0)
308	movl	%a5,%a0@		| phys_seg_list[0].ps_start
309	movl	0xfffe0774,%d1		| End + 1 of onboard memory
310	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
311	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
312
313	/* offboard RAM */
314	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
315	movl	#PAGE_SIZE-1,%d0
316	addl	0xfffe0764,%d0		| Start of offboard segment
317	andl	#-PAGE_SIZE,%d0		| Round up to page boundary
318	jbeq	Lsavmaxmem		| Jump if none defined
319	movl	#PAGE_SIZE,%d1		| Note: implicit '+1'
320	addl	0xfffe0768,%d1		| End of offboard segment
321	andl	#-PAGE_SIZE,%d1		| Round up to page boundary
322	cmpl	%d1,%d0			| Quick and dirty validity check
323	jbcs	Loff_ok			| Yup, looks good.
324	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
325	jbra	Lsavmaxmem
326Loff_ok:
327	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
328	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
329	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
330
331	/*
332	 * Offboard RAM needs to be cleared to zero to initialise parity
333	 * on most VMEbus RAM cards. Without this, some cards will buserr
334	 * when first read.
335	 */
336	movel	%d0,%a0			| offboard start address again.
337Lclearoff:
338	clrl	%a0@+			| zap a word
339	cmpl	%a0,%d1			| reached end?
340	jbne	Lclearoff
341
342Lsavmaxmem:
343	moveq	#PGSHIFT,%d2
344	lsrl	%d2,%d1			| convert to page (click) number
345	RELOC(maxmem, %a0)
346	movl	%d1,%a0@		| save as maxmem
347	jra	Lstart1
348#endif
349
350#if defined(MVME162) || defined(MVME172)
351Linit1x2:
352	/* MVME-162 - 68040 CPU/MMU/FPU */
353	/* MVME-172 - 68060 CPU/MMU/FPU */
354
355	/*
356	 * Verify the user has removed the GPIO#0 jumper...
357	 */
358	btst	#0,0xfff4202d		| Clear == jumper installed
359	jne	1f			| Ok.
360
361	movl	#Le1x2jump,%sp@-
362	movl	#L1x2jump,%sp@-
363	CALLBUG(MVMEPROM_OUTSTRCRLF)
364	addql	#8,%sp			| clean up stack after call
365
366	CALLBUG(MVMEPROM_EXIT)
367	/* NOTREACHED */
368
3691:
370	/*
371	 * Determine if this board has a VMEchip2
372	 */
373	btst	#1,0xfff4202e		| VMEchip2 presence detect
374	jne	2f			| Jump if it doesn't exist.
375
376	/*
377	 * Disable all interrupts from VMEchip2. This is especially
378	 * useful when the kernel doesn't have the VMEchip2 driver
379	 * configured. If we didn't do this, then we're at the mercy
380	 * of whatever VMEchip2 interrupts the ROM set up. For example,
381	 * hitting the ABORT switch could kill the system...
382	 */
383	movl	0xfff40088,%d0
384	andl	#0xff7fffff,%d0		| Clear 'MIEN'
385	movl	%d0,0xfff40088
3862:
387	/*
388	 * Determine how much onboard memory is installed
389	 */
390	movql	#0x07,%d0
391	andb	0xfff42024,%d0
392	ASRELOC(Ldramsize1x2,%a0)
393	movl	%a0@(%d0:w:4),%d1	| Lookup the size
394	jeq	Lmemcquery		| Assume a MEMC chip if this is zero.
395	jra	Lis1xx_common
396
397	.data
398	.even
399	/*
400	 * Table of DRAM register size values -> actual size in bytes
401	 */
402ASLOCAL(Ldramsize1x2)
403	.long	0x00100000
404	.long	0x00200000
405	.long	0x00000000
406	.long	0x00400000
407	.long	0x00400000
408	.long	0x00800000
409	.long	0x00000000
410	.long	0x01000000
411
412L1x2jump:
413	.ascii	"You must remove the jumper from pins 15-16 of J22 (mvme162)"
414	.ascii	"or pins 1-2\015\012"
415	.ascii	"J11 (mvme162-LX) first! See NetBSD/mvme68k FAQ for details."
416Le1x2jump:
417	.even
418
419	.text
420#endif
421
422#if defined(MVME167) || defined(MVME177)
423Linit1x7:
424	/* MVME-167 - 68040 CPU/MMU/FPU */
425	/* MVME-177 - 68060 CPU/MMU/FPU */
426
427	/*
428	 * Verify the user has removed the GPIO#0 jumper...
429	 */
430	movel	#0x00000001,%d0
431	andl	0xfff40088,%d0		| Clear == jumper installed
432	jne	1f			| Ok.
433
434	movl	#Le1x7jump,%sp@-
435	movl	#L1x7jump,%sp@-
436	CALLBUG(MVMEPROM_OUTSTRCRLF)
437	addql	#8,%sp			| clean up stack after call
438
439	CALLBUG(MVMEPROM_EXIT)
440	/* NOTREACHED */
441
4421:
443	/*
444	 * Disable all interrupts from VMEchip2. This is especially
445	 * useful when the kernel doesn't have the VMEchip2 driver
446	 * configured. If we didn't do this, then we're at the mercy
447	 * of whatever VMEchip2 interrupts the ROM set up. For example,
448	 * hitting the ABORT switch could kill the system...
449	 */
450	movl	0xfff40088,%d0
451	andl	#0xff7fffff,%d0		| Clear 'MIEN'
452	movl	%d0,0xfff40088
453
454	.data
455	.even
456L1x7jump:
457	.ascii	"You must remove the jumper from pins 1-2 of J1!\015\012"
458	.ascii	"See NetBSD/mvme68k FAQ for details."
459Le1x7jump:
460	.even
461
462	.text
463#endif
464
465#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
466Lmemcquery:
467	/*
468	 * Figure out the size of onboard DRAM by querying
469	 * the memory controller ASIC(s)
470	 */
471	lea	0xfff43008,%a0		| MEMC040/MEMECC Controller #1
472	jbsr	memc040read
473	movl	%d0,%d1
474
475	lea	0xfff43108,%a0		| MEMC040/MEMECC Controller #2
476	jbsr	memc040read
477	addl	%d0,%d1
478
479Lis1xx_common:
480	/* Save our ethernet address */
481	RELOC(mvme_ea, %a0)
482	lea	0xfffc1f2c,%a1
483	movb	%a1@+,%a0@+
484	movb	%a1@+,%a0@+
485	movb	%a1@+,%a0@+
486	movb	%a1@+,%a0@+
487	movb	%a1@+,%a0@+
488	movb	%a1@,%a0@
489
490	/*
491	 * Fix up the physical addresses of the onboard
492	 * I/O registers.
493	 */
494	RELOC(intiobase_phys, %a0);
495	movl	#INTIOBASE1xx,%a0@
496	RELOC(intiotop_phys, %a0);
497	movl	#INTIOTOP1xx,%a0@
498
499	/*
500	 * Initialise first physical memory segment with onboard RAM details
501	 */
502	RELOC(phys_seg_list, %a0)
503	movl	%a5,%a0@		| phys_seg_list[0].ps_start
504	movl	%d1,%a0@(4)		| phys_seg_list[0].ps_end
505	clrl	%a0@(8)			| phys_seg_list[0].ps_startpage
506
507	/* offboard RAM */
508	clrl	%a0@(0x0c)		| phys_seg_list[1].ps_start
509	movl	#PAGE_SIZE-1,%d0
510	addl	0xfffc0000,%d0		| Start of offboard segment
511	andl	#-PAGE_SIZE,%d0		| Round up to page boundary
512	jbeq	Ldone1xx		| Jump if none defined
513	movl	#PAGE_SIZE,%d1		| Note: implicit '+1'
514	addl	0xfffc0004,%d1		| End of offboard segment
515	andl	#-PAGE_SIZE,%d1		| Round up to page boundary
516	cmpl	%d1,%d0			| Quick and dirty validity check
517	jbcs	Lramsave1xx		| Yup, looks good.
518	movel	%a0@(4),%d1		| Just use onboard RAM otherwise
519	jbra	Ldone1xx
520
521Lramsave1xx:
522	movl	%d0,%a0@(0x0c)		| phys_seg_list[1].ps_start
523	movl	%d1,%a0@(0x10)		| phys_seg_list[1].ps_end
524	clrl	%a0@(0x14)		| phys_seg_list[1].ps_startpage
525
526	/*
527	 * Offboard RAM needs to be cleared to zero to initialise parity
528	 * on most VMEbus RAM cards. Without this, some cards will buserr
529	 * when first read.
530	 */
531	movel	%d0,%a0			| offboard start address again.
532Lramclr1xx:
533	clrl	%a0@+			| zap a word
534	cmpl	%a0,%d1			| reached end?
535	jbne	Lramclr1xx
536
537Ldone1xx:
538	moveq	#PGSHIFT,%d2
539	lsrl	%d2,%d1			| convert to page (click) number
540	RELOC(maxmem, %a0)
541	movl	%d1,%a0@		| save as maxmem
542
543	/* FALLTHROUGH to Lstart1 */
544#endif
545
546
547Lstart1:
548/* initialize source/destination control registers for movs */
549	moveq	#FC_USERD,%d0		| user space
550	movc	%d0,%sfc		|   as source
551	movc	%d0,%dfc		|   and destination of transfers
552/*
553 * configure kernel and lwp0 VA space so we can get going
554 */
555#if NKSYMS || defined(DDB) || defined(MODULAR)
556	RELOC(esym,%a0)			| end of static kernel text/data syms
557	movl	%a0@,%d2
558	jne	Lstart2
559#endif
560	movl	#_C_LABEL(end),%d2	| end of static kernel text/data
561Lstart2:
562	addl	#PAGE_SIZE-1,%d2
563	andl	#PG_FRAME,%d2		| round to a page
564	movl	%d2,%a4
565	addl	%a5,%a4			| convert to PA
566	pea	%a5@			| firstpa
567	pea	%a4@			| nextpa
568	RELOC(pmap_bootstrap,%a0)
569	jbsr	%a0@			| pmap_bootstrap(firstpa, nextpa)
570	addql	#8,%sp
571
572/*
573 * Enable the MMU.
574 * Since the kernel is mapped logical == physical, we just turn it on.
575 */
576	RELOC(Sysseg_pa, %a0)		| system segment table addr
577	movl	%a0@,%d1		| read value (a PA)
578	RELOC(mmutype, %a0)
579	cmpl	#MMU_68040,%a0@		| 68040?
580	jne	Lmotommu1		| no, skip
581	.long	0x4e7b1807		| movc d1,srp
582	jra	Lstploaddone
583Lmotommu1:
584	RELOC(protorp, %a0)
585	movl	#0x80000202,%a0@	| nolimit + share global + 4 byte PTEs
586	movl	%d1,%a0@(4)		| + segtable address
587	pmove	%a0@,%srp		| load the supervisor root pointer
588	movl	#0x80000002,%a0@	| reinit upper half for CRP loads
589Lstploaddone:
590	RELOC(mmutype, %a0)
591	cmpl	#MMU_68040,%a0@		| 68040?
592	jne	Lmotommu2		| no, skip
593	moveq	#0,%d0			| ensure TT regs are disabled
594	.long	0x4e7b0004		| movc d0,itt0
595	.long	0x4e7b0005		| movc d0,itt1
596	.long	0x4e7b0006		| movc d0,dtt0
597	.long	0x4e7b0007		| movc d0,dtt1
598	.word	0xf4d8			| cinva bc
599	.word	0xf518			| pflusha
600	movl	#0x8000,%d0
601	.long	0x4e7b0003		| movc d0,tc
602#ifdef M68060
603	RELOC(cputype, %a0)
604	cmpl	#CPU_68060,%a0@		| 68060?
605	jne	Lnot060cache
606	movl	#1,%d0
607	.long	0x4e7b0808		| movcl d0,pcr
608	movl	#0xa0808000,%d0
609	movc	%d0,%cacr		| enable store buffer, both caches
610	jmp	Lenab1
611Lnot060cache:
612#endif
613	movl	#0x80008000,%d0
614	movc	%d0,%cacr		| turn on both caches
615	jmp	Lenab1
616Lmotommu2:
617	pflusha
618	movl	#0x82c0aa00,%sp@-	| value to load TC with
619	pmove	%sp@,%tc		| load it
620
621/*
622 * Should be running mapped from this point on
623 */
624Lenab1:
625/* Point the CPU VBR at our vector table */
626	movc	%vbr,%d0		| Preserve Bug's VBR address
627	movl	%d0,_ASM_LABEL(bug_vbr)
628	movl	#_C_LABEL(vectab),%d0	| get our VBR address
629	movc	%d0,%vbr
630	lea	_ASM_LABEL(tmpstk),%sp	| temporary stack
631/* call final pmap setup */
632	jbsr	_C_LABEL(pmap_bootstrap_finalize)
633/* set kernel stack, user SP */
634	movl	_C_LABEL(lwp0uarea),%a1	| get lwp0 uarea
635	lea	%a1@(USPACE-4),%sp	| set kernel stack to end of area
636	movl	#USRSTACK-4,%a2
637	movl	%a2,%usp		| init user SP
638	tstl	_C_LABEL(fputype)	| Have an FPU?
639	jeq	Lenab2			| No, skip.
640	clrl	%a1@(PCB_FPCTX)		| ensure null FP context
641	movl	%a1,%sp@-
642	jbsr	_C_LABEL(m68881_restore) | restore it (does not kill a1)
643	addql	#4,%sp
644Lenab2:
645	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040?
646	jeq	Ltbia040		| yes, cache already on
647	pflusha
648	movl	#CACHE_ON,%d0
649	movc	%d0,%cacr		| clear cache(s)
650	jra	Lenab3
651Ltbia040:
652	.word	0xf518
653Lenab3:
654/*
655 * final setup for C code:
656 * Create a fake exception frame so that cpu_lwp_fork() can copy it.
657 * main() nevers returns; we exit to user mode from a forked process
658 * later on.
659 */
660	jbsr	_C_LABEL(mvme68k_init)	| additional pre-main initialization
661	movw	#PSL_LOWIPL,%sr		| lower SPL
662	clrw	%sp@-			| vector offset/frame type
663	clrl	%sp@-			| PC - filled in by "execve"
664	movw	#PSL_USER,%sp@-		| in user mode
665	clrl	%sp@-			| stack adjust count and padding
666	lea	%sp@(-64),%sp		| construct space for D0-D7/A0-A7
667	lea	_C_LABEL(lwp0),%a0	| save pointer to frame
668	movl	%sp,%a0@(L_MD_REGS)	|   in lwp0.l_md.md_regs
669
670	jra	_C_LABEL(main)		| main()
671
672#if defined(MVME162) || defined(MVME167) || defined(MVME172) || defined(MVME177)
673/*
674 * Probe for a memory controller ASIC (MEMC040 or MEMECC) at the
675 * address in a0. If found, return the size in bytes of any RAM
676 * controlled by the ASIC in d0. Otherwise return zero.
677 */
678ASLOCAL(memc040read)
679	moveml	%d1-%d2/%a1-%a2,%sp@-	| save scratch regs
680	movc	%vbr,%d2		| Save vbr
681	RELOC(vectab,%a2)		| Install our own vectab, temporarily
682	movc	%a2,%vbr
683	ASRELOC(Lmemc040berr,%a1)	| get address of bus error handler
684	movl	%a2@(8),%sp@-		| Save current bus error handler addr
685	movl	%a1,%a2@(8)		| Install our own handler
686	movl	%sp,%d0			| Save current stack pointer value
687	movql	#0x07,%d1
688	andb	%a0@,%d1		| Access MEMC040/MEMECC
689	movl	#0x400000,%d0
690	lsll	%d1,%d0			| Convert to memory size, in bytes
691Lmemc040ret:
692	movc	%d2,%vbr		| Restore original vbr
693	movl	%sp@+,%a2@(8)		| Restore original bus error handler
694	moveml  %sp@+,%d1-%d2/%a1-%a2
695	rts
696/*
697 * If the memory controller doesn't exist, we get a bus error trying
698 * to access a0@ above. Control passes here, where we flag 'no bytes',
699 * ditch the exception frame and return as normal.
700 */
701Lmemc040berr:
702	movl	%d0,%sp			| Get rid of the exception frame
703	movql	#0,%d0			| No ASIC at this location, then!
704	jbra	Lmemc040ret		| Done
705#endif
706
707/*
708 * Trap/interrupt vector routines
709 */
710#include <m68k/m68k/trap_subr.s>
711
712/*
713 * Use common m68k bus error and address error handlers.
714 */
715#include <m68k/m68k/busaddrerr.s>
716
717/*
718 * FP exceptions.
719 */
720ENTRY_NOPROFILE(fpfline)
721#if defined(M68040)
722	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
723	jne	Lfp_unimp		| no, skip FPSP
724	cmpw	#0x202c,%sp@(6)		| format type 2?
725	jne	_C_LABEL(illinst)	| no, not an FP emulation
726#ifdef FPSP
727	jmp	_ASM_LABEL(fpsp_unimp)	| yes, go handle it
728#else
729	clrl	%sp@-			| stack adjust count
730	moveml	#0xFFFF,%sp@-		| save registers
731	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
732	jra	_ASM_LABEL(fault)	| do it
733#endif
734Lfp_unimp:
735#endif /* M68040 */
736	jra	_C_LABEL(illinst)
737
738ENTRY_NOPROFILE(fpunsupp)
739#if defined(M68040)
740	cmpl	#FPU_68040,_C_LABEL(fputype) | 68040 FPU?
741	jne	Lfp_unsupp		| No, skip FPSP
742#ifdef FPSP
743	jmp	_ASM_LABEL(fpsp_unsupp)	| yes, go handle it
744#else
745	clrl	%sp@-			| stack adjust count
746	moveml	#0xFFFF,%sp@-		| save registers
747	moveq	#T_FPEMULD,%d0		| denote as FP emulation trap
748	jra	_ASM_LABEL(fault)	| do it
749#endif
750Lfp_unsupp:
751#endif /* M68040 */
752	jra	_C_LABEL(illinst)
753
754/*
755 * Handles all other FP coprocessor exceptions.
756 * Note that since some FP exceptions generate mid-instruction frames
757 * and may cause signal delivery, we need to test for stack adjustment
758 * after the trap call.
759 */
760ENTRY_NOPROFILE(fpfault)
761	clrl	%sp@-		| stack adjust count
762	moveml	#0xFFFF,%sp@-	| save user registers
763	movl	%usp,%a0	| and save
764	movl	%a0,%sp@(FR_SP)	|   the user stack pointer
765	clrl	%sp@-		| no VA arg
766	movl	_C_LABEL(curpcb),%a0 | current pcb
767	lea	%a0@(PCB_FPCTX),%a0 | address of FP savearea
768	fsave	%a0@		| save state
769#if defined(M68040) || defined(M68060)
770	/* always null state frame on 68040, 68060 */
771	cmpl	#FPU_68040,_C_LABEL(fputype)
772	jge	Lfptnull
773#endif
774	tstb	%a0@		| null state frame?
775	jeq	Lfptnull	| yes, safe
776	clrw	%d0		| no, need to tweak BIU
777	movb	%a0@(1),%d0	| get frame size
778	bset	#3,%a0@(0,%d0:w) | set exc_pend bit of BIU
779Lfptnull:
780	fmovem	%fpsr,%sp@-	| push fpsr as code argument
781	frestore %a0@		| restore state
782	movl	#T_FPERR,%sp@-	| push type arg
783	jra	_ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
784
785
786/*
787 * Other exceptions only cause four and six word stack frame and require
788 * no post-trap stack adjustment.
789 */
790
791ENTRY_NOPROFILE(badtrap)
792	moveml	#0xC0C0,%sp@-		| save scratch regs
793	movw	%sp@(22),%sp@-		| push exception vector info
794	clrw	%sp@-
795	movl	%sp@(22),%sp@-		| and PC
796	jbsr	_C_LABEL(straytrap)	| report
797	addql	#8,%sp			| pop args
798	moveml	%sp@+,#0x0303		| restore regs
799	jra	_ASM_LABEL(rei)		| all done
800
801ENTRY_NOPROFILE(trap0)
802	clrl	%sp@-			| stack adjust count
803	moveml	#0xFFFF,%sp@-		| save user registers
804	movl	%usp,%a0		| save the user SP
805	movl	%a0,%sp@(FR_SP)		|   in the savearea
806	movl	%d0,%sp@-		| push syscall number
807	jbsr	_C_LABEL(syscall)	| handle it
808	addql	#4,%sp			| pop syscall arg
809	tstl	_C_LABEL(astpending)	| AST pending?
810	jne	Lrei1			| Yup, go deal with it.
811	movl	%sp@(FR_SP),%a0		| grab and restore
812	movl	%a0,%usp		|   user SP
813	moveml	%sp@+,#0x7FFF		| restore most registers
814	addql	#8,%sp			| pop SP and stack adjust
815	rte
816
817/*
818 * Trap 12 is the entry point for the cachectl "syscall" (both HPUX & BSD)
819 *	cachectl(command, addr, length)
820 * command in d0, addr in a1, length in d1
821 */
822ENTRY_NOPROFILE(trap12)
823	movl	_C_LABEL(curlwp),%a0
824	movl	%a0@(L_PROC),%sp@-	| push current proc pointer
825	movl	%d1,%sp@-		| push length
826	movl	%a1,%sp@-		| push addr
827	movl	%d0,%sp@-		| push command
828	jbsr	_C_LABEL(cachectl1)	| do it
829	lea	%sp@(16),%sp		| pop args
830	jra	_ASM_LABEL(rei)		| all done
831
832/*
833 * Trace (single-step) trap.  Kernel-mode is special.
834 * User mode traps are simply passed on to trap().
835 */
836ENTRY_NOPROFILE(trace)
837	clrl	%sp@-			| stack adjust count
838	moveml	#0xFFFF,%sp@-
839	moveq	#T_TRACE,%d0
840
841	| Check PSW and see what happen.
842	|   T=0 S=0	(should not happen)
843	|   T=1 S=0	trace trap from user mode
844	|   T=0 S=1	trace trap on a trap instruction
845	|   T=1 S=1	trace trap from system mode (kernel breakpoint)
846
847	movw	%sp@(FR_HW),%d1		| get PSW
848	notw	%d1			| XXX no support for T0 on 680[234]0
849	andw	#PSL_TS,%d1		| from system mode (T=1, S=1)?
850	jeq	Lkbrkpt			| yes, kernel breakpoint
851	jra	_ASM_LABEL(fault)	| no, user-mode fault
852
853/*
854 * Trap 15 is used for:
855 *	- GDB breakpoints (in user programs)
856 *	- KGDB breakpoints (in the kernel)
857 *	- trace traps for SUN binaries (not fully supported yet)
858 * User mode traps are simply passed to trap().
859 */
860ENTRY_NOPROFILE(trap15)
861	clrl	%sp@-			| stack adjust count
862	moveml	#0xFFFF,%sp@-
863	moveq	#T_TRAP15,%d0
864	movw	%sp@(FR_HW),%d1		| get PSW
865	andw	#PSL_S,%d1		| from system mode?
866	jne	Lkbrkpt			| yes, kernel breakpoint
867	jra	_ASM_LABEL(fault)	| no, user-mode fault
868
869Lkbrkpt: | Kernel-mode breakpoint or trace trap. (d0=trap_type)
870	| Save the system sp rather than the user sp.
871	movw	#PSL_HIGHIPL,%sr	| lock out interrupts
872	lea	%sp@(FR_SIZE),%a6	| Save stack pointer
873	movl	%a6,%sp@(FR_SP)		|  from before trap
874
875	| If were are not on tmpstk switch to it.
876	| (so debugger can change the stack pointer)
877	movl	%a6,%d1
878	cmpl	#_ASM_LABEL(tmpstk),%d1
879	jls	Lbrkpt2			| already on tmpstk
880	| Copy frame to the temporary stack
881	movl	%sp,%a0			| a0=src
882	lea	_ASM_LABEL(tmpstk)-96,%a1 | a1=dst
883	movl	%a1,%sp			| sp=new frame
884	movql	#FR_SIZE,%d1
885Lbrkpt1:
886	movl	%a0@+,%a1@+
887	subql	#4,%d1
888	jbgt	Lbrkpt1
889
890Lbrkpt2:
891	| Call the trap handler for the kernel debugger.
892	| Do not call trap() to do it, so that we can
893	| set breakpoints in trap() if we want.  We know
894	| the trap type is either T_TRACE or T_BREAKPOINT.
895	| If we have both DDB and KGDB, let KGDB see it first,
896	| because KGDB will just return 0 if not connected.
897	| Save args in d2, a2
898	movl	%d0,%d2			| trap type
899	movl	%sp,%a2			| frame ptr
900#ifdef KGDB
901	| Let KGDB handle it (if connected)
902	movl	%a2,%sp@-		| push frame ptr
903	movl	%d2,%sp@-		| push trap type
904	jbsr	_C_LABEL(kgdb_trap)	| handle the trap
905	addql	#8,%sp			| pop args
906	cmpl	#0,%d0			| did kgdb handle it?
907	jne	Lbrkpt3			| yes, done
908#endif
909#ifdef DDB
910	| Let DDB handle it
911	movl	%a2,%sp@-		| push frame ptr
912	movl	%d2,%sp@-		| push trap type
913	jbsr	_C_LABEL(kdb_trap)	| handle the trap
914	addql	#8,%sp			| pop args
915#endif
916	/* Sun 3 drops into PROM here. */
917Lbrkpt3:
918	| The stack pointer may have been modified, or
919	| data below it modified (by kgdb push call),
920	| so push the hardware frame at the current sp
921	| before restoring registers and returning.
922
923	movl	%sp@(FR_SP),%a0		| modified sp
924	lea	%sp@(FR_SIZE),%a1	| end of our frame
925	movl	%a1@-,%a0@-		| copy 2 longs with
926	movl	%a1@-,%a0@-		| ... predecrement
927	movl	%a0,%sp@(FR_SP)		| sp = h/w frame
928	moveml	%sp@+,#0x7FFF		| restore all but sp
929	movl	%sp@,%sp		| ... and sp
930	rte				| all done
931
932/*
933 * Use common m68k sigreturn routine.
934 */
935#include <m68k/m68k/sigreturn.s>
936
937/*
938 * Interrupt handlers.
939 *
940 * For auto-vectored interrupts, the CPU provides the
941 * vector 0x18+level.
942 *
943 * intrhand_autovec is the entry point for auto-vectored
944 * interrupts.
945 *
946 * For vectored interrupts, we pull the pc, evec, and exception frame
947 * and pass them to the vectored interrupt dispatcher.  The vectored
948 * interrupt dispatcher will deal with strays.
949 *
950 * intrhand_vectored is the entry point for vectored interrupts.
951 */
952
953ENTRY_NOPROFILE(intrhand_autovec)
954	addql	#1,_C_LABEL(interrupt_depth)
955	INTERRUPT_SAVEREG
956	lea	%sp@(16),%a1		| get pointer to frame
957	movl	%a1,%sp@-
958	jbsr	_C_LABEL(isrdispatch_autovec)  | call dispatcher
959	addql	#4,%sp
960	jbra	Lintrhand_exit
961
962ENTRY_NOPROFILE(intrhand_vectored)
963	addql	#1,_C_LABEL(interrupt_depth)
964	INTERRUPT_SAVEREG
965	lea	%sp@(16),%a1		| get pointer to frame
966	movl	%a1,%sp@-
967	movw	%sr,%d0
968	bfextu	%d0,21,3,%d0		| Get current ipl
969	movl	%d0,%sp@-		| Push it
970	jbsr	_C_LABEL(isrdispatch_vectored) | call dispatcher
971	addql	#8,%sp
972Lintrhand_exit:
973	INTERRUPT_RESTOREREG
974	subql	#1,_C_LABEL(interrupt_depth)
975
976	/* FALLTHROUGH to rei */
977
978#undef INTERRUPT_SAVEREG
979#undef INTERRUPT_RESTOREREG
980
981/*
982 * Emulation of VAX REI instruction.
983 *
984 * This code deals with checking for and servicing ASTs
985 * (profiling, scheduling).
986 * After identifing that we need an AST we drop the IPL to allow device
987 * interrupts.
988 *
989 * This code is complicated by the fact that sendsig may have been called
990 * necessitating a stack cleanup.
991 */
992ASENTRY_NOPROFILE(rei)
993	tstl	_C_LABEL(astpending)	| AST pending?
994	jeq	Ldorte			| Nope. Just return.
995	btst	#5,%sp@			| Returning to kernel mode?
996	jne	Ldorte			| Yup. Can't do ASTs
997	movw	#PSL_LOWIPL,%sr		| lower SPL
998	clrl	%sp@-			| stack adjust
999	moveml	#0xFFFF,%sp@-		| save all registers
1000	movl	%usp,%a1		| including
1001	movl	%a1,%sp@(FR_SP)		|    the users SP
1002Lrei1:	clrl	%sp@-			| VA == none
1003	clrl	%sp@-			| code == none
1004	movl	#T_ASTFLT,%sp@-		| type == async system trap
1005	pea	%sp@(12)		| fp == address of trap frame
1006	jbsr	_C_LABEL(trap)		| go handle it
1007	lea	%sp@(16),%sp		| pop value args
1008	movl	%sp@(FR_SP),%a0		| restore user SP
1009	movl	%a0,%usp		|   from save area
1010	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
1011	jne	Laststkadj		| yes, go to it
1012	moveml	%sp@+,#0x7FFF		| no, restore most user regs
1013	addql	#8,%sp			| toss SP and stack adjust
1014Ldorte:	rte				| and do real RTE
1015
1016Laststkadj:
1017	lea	%sp@(FR_HW),%a1		| pointer to HW frame
1018	addql	#8,%a1			| source pointer
1019	movl	%a1,%a0			| source
1020	addw	%d0,%a0			|  + hole size = dest pointer
1021	movl	%a1@-,%a0@-		| copy
1022	movl	%a1@-,%a0@-		|  8 bytes
1023	movl	%a0,%sp@(FR_SP)		| new SSP
1024	moveml	%sp@+,#0x7FFF		| restore user registers
1025	movl	%sp@,%sp		| and our SP
1026	rte				| and do real RTE
1027
1028/*
1029 * Use common m68k sigcode.
1030 */
1031#include <m68k/m68k/sigcode.s>
1032#ifdef COMPAT_SUNOS
1033#include <m68k/m68k/sunos_sigcode.s>
1034#endif
1035#ifdef COMPAT_SVR4
1036#include <m68k/m68k/svr4_sigcode.s>
1037#endif
1038
1039/*
1040 * Primitives
1041 */
1042
1043/*
1044 * Use common m68k support routines.
1045 */
1046#include <m68k/m68k/support.s>
1047
1048/*
1049 * Use common m68k process/lwp switch and context save subroutines.
1050 */
1051#define	FPCOPROC	/* XXX: Temp. Reqd. */
1052#include <m68k/m68k/switch_subr.s>
1053
1054
1055#if defined(M68040) || defined(M68060)
1056ENTRY(suline)
1057	movl	%sp@(4),%a0		| address to write
1058	movl	_C_LABEL(curpcb),%a1	| current pcb
1059	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
1060	movl	%sp@(8),%a1		| address of line
1061	movl	%a1@+,%d0		| get lword
1062	movsl	%d0,%a0@+		| put lword
1063	nop				| sync
1064	movl	%a1@+,%d0		| get lword
1065	movsl	%d0,%a0@+		| put lword
1066	nop				| sync
1067	movl	%a1@+,%d0		| get lword
1068	movsl	%d0,%a0@+		| put lword
1069	nop				| sync
1070	movl	%a1@+,%d0		| get lword
1071	movsl	%d0,%a0@+		| put lword
1072	nop				| sync
1073	moveq	#0,%d0			| indicate no fault
1074	jra	Lsldone
1075Lslerr:
1076	moveq	#-1,%d0
1077Lsldone:
1078	movl	_C_LABEL(curpcb),%a1	| current pcb
1079	clrl	%a1@(PCB_ONFAULT)	| clear fault address
1080	rts
1081#endif
1082
1083
1084ENTRY(ecacheon)
1085	rts
1086
1087ENTRY(ecacheoff)
1088	rts
1089
1090/*
1091 * Get callers current SP value.
1092 * Note that simply taking the address of a local variable in a C function
1093 * doesn't work because callee saved registers may be outside the stack frame
1094 * defined by A6 (e.g. GCC generated code).
1095 */
1096ENTRY_NOPROFILE(getsp)
1097	movl	%sp,%d0			| get current SP
1098	addql	#4,%d0			| compensate for return address
1099	movl	%d0,%a0
1100	rts
1101
1102/*
1103 * Load a new user segment table pointer.
1104 */
1105ENTRY(loadustp)
1106	movl	%sp@(4),%d0		| new USTP
1107	moveq	#PGSHIFT, %d1
1108	lsll	%d1,%d0			| convert to addr
1109#if defined(M68040) || defined(M68060)
1110	cmpl    #MMU_68040,_C_LABEL(mmutype) | 68040?
1111	jne     LmotommuC               | no, skip
1112	.word	0xf518			| pflusha
1113	.long   0x4e7b0806              | movc d0,urp
1114#ifdef M68060
1115	cmpl	#CPU_68060,_C_LABEL(cputype)
1116	jne	Lldno60
1117	movc	%cacr,%d0
1118	orl	#IC60_CUBC,%d0		| clear user branch cache entries
1119	movc	%d0,%cacr
1120Lldno60:
1121#endif
1122	rts
1123LmotommuC:
1124#endif
1125	pflusha				| flush entire TLB
1126	lea	_C_LABEL(protorp),%a0	| CRP prototype
1127	movl	%d0,%a0@(4)		| stash USTP
1128	pmove	%a0@,%crp		| load root pointer
1129	movl	#CACHE_CLR,%d0
1130	movc	%d0,%cacr		| invalidate cache(s)
1131	rts
1132
1133ENTRY(ploadw)
1134#ifdef M68030
1135#if defined(M68040) || defined(M68060)
1136	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1137	jeq	Lploadwskp		| yes, skip
1138#endif
1139	movl	%sp@(4),%a0		| address to load
1140	ploadw	#1,%a0@			| pre-load translation
1141Lploadwskp:
1142#endif
1143	rts
1144
1145ENTRY(getsr)
1146	moveq	#0,%d0
1147	movw	%sr,%d0
1148	rts
1149
1150/*
1151 * _delay(unsigned N)
1152 *
1153 * Delay for at least (N/1024) microseconds.
1154 * This routine depends on the variable:  delay_divisor
1155 * which should be set based on the CPU clock rate.
1156 */
1157ENTRY_NOPROFILE(_delay)
1158	| d0 = arg = (usecs << 10)
1159	movl	%sp@(4),%d0
1160	| d1 = delay_divisor
1161	movl	_C_LABEL(delay_divisor),%d1
1162	jra	L_delay			/* Jump into the loop! */
1163
1164	/*
1165	 * Align the branch target of the loop to a half-line (8-byte)
1166	 * boundary to minimize cache effects.  This guarantees both
1167	 * that there will be no prefetch stalls due to cache line burst
1168	 * operations and that the loop will run from a single cache
1169	 * half-line.
1170	 */
1171#ifdef __ELF__
1172	.align	8
1173#else
1174	.align	3
1175#endif
1176L_delay:
1177	subl	%d1,%d0
1178	jgt	L_delay
1179	rts
1180
1181/*
1182 * Handle the nitty-gritty of rebooting the machine.
1183 * Basically we just turn off the MMU, restore the Bug's initial VBR
1184 * and either return to Bug or jump through the ROM reset vector
1185 * depending on how the system was halted.
1186 */
1187ENTRY_NOPROFILE(doboot)
1188	movw	#PSL_HIGHIPL,%sr
1189	movl	_C_LABEL(boothowto),%d1	| load howto
1190	movl	%sp@(4),%d2		| arg
1191	movl	_ASM_LABEL(bug_vbr),%d3	| Fetch Bug's original VBR value
1192	movl	_C_LABEL(machineid),%d4	| What type of board is this?
1193	movl	#CACHE_OFF,%d0
1194#if defined(M68040) || defined(M68060)
1195	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040/68060?
1196	jne	Lnocache0		| no, skip
1197	.word	0xf4f8			| cpusha bc - push and invalidate caches
1198	nop
1199	movl	#CACHE40_OFF,%d0
1200#endif
1201Lnocache0:
1202	movc	%d0,%cacr		| disable on-chip cache(s)
1203
1204#if defined(M68040) || defined(M68060)
1205	cmpl	#MMU_68040,_C_LABEL(mmutype)
1206	jne	LmotommuF
1207	movql	#0,%d0
1208	movc	%d0,%cacr
1209	.long	0x4e7b0003              | movc d0,tc
1210	jra	Lbootcommon
1211LmotommuF:
1212#endif
1213	clrl	%sp@-			| value for pmove to TC (turn off MMU)
1214	pmove	%sp@,%tc		| disable MMU
1215	addql	#4,%sp
1216
1217Lbootcommon:
1218	/*
1219	 * MMU Switched off by now, so relocate all absolute references
1220	 */
1221	ASRELOC(tmpstk, %sp)		| physical SP in case of NMI
1222	movc	%d3,%vbr		| Restore Bug's VBR
1223	andl	#RB_SBOOT, %d1		| mask off
1224	jbne	Lsboot			| sboot?
1225	/* NOT sboot */
1226	tstl	%d2			| autoboot?
1227	jbeq	Ldoreset		| yes!
1228	CALLBUG(MVMEPROM_EXIT)		| return to bug
1229	/* NOTREACHED */
1230
1231Ldoreset:
1232	movl	#0xff800000,%a0		| Bug's reset vector address
1233	movl	%a0@+, %a7		| get SP
1234	movl	%a0@, %a0		| get PC
1235	jmp	%a0@			| go!
1236
1237Lsboot: /* sboot */
1238	tstl	%d2			| autoboot?
1239	jbeq	1f			| yes!
1240	jmp 	0x4000			| back to sboot
12411:	jmp	0x400a			| tell sboot to reboot us
1242
1243
1244/*
1245 * Misc. global variables.
1246 */
1247	.data
1248
1249GLOBAL(machineid)
1250	.long	MVME_147	| default to MVME_147
1251
1252GLOBAL(mmutype)
1253	.long	MMU_68030	| default to MMU_68030
1254
1255GLOBAL(cputype)
1256	.long	CPU_68030	| default to CPU_68030
1257
1258GLOBAL(fputype)
1259	.long	FPU_68882	| default to FPU_68882
1260
1261GLOBAL(protorp)
1262	.long	0,0		| prototype root pointer
1263
1264/*
1265 * Information from first stage boot program
1266 */
1267GLOBAL(bootpart)
1268	.long	0
1269GLOBAL(bootdevlun)
1270	.long	0
1271GLOBAL(bootctrllun)
1272	.long	0
1273GLOBAL(bootaddr)
1274	.long	0
1275
1276GLOBAL(intiobase)
1277	.long	0		| KVA of base of internal IO space
1278
1279GLOBAL(intiolimit)
1280	.long	0		| KVA of end of internal IO space
1281
1282GLOBAL(intiobase_phys)
1283	.long	0		| PA of board's I/O registers
1284
1285GLOBAL(intiotop_phys)
1286	.long	0		| PA of top of board's I/O registers
1287
1288/*
1289 * interrupt counters.
1290 * XXXSCW: Will go away soon; kept here to keep vmstat happy
1291 */
1292GLOBAL(intrnames)
1293	.asciz	"spur"
1294	.asciz	"lev1"
1295	.asciz	"lev2"
1296	.asciz	"lev3"
1297	.asciz	"lev4"
1298	.asciz	"clock"
1299	.asciz	"lev6"
1300	.asciz	"nmi"
1301	.asciz	"statclock"
1302GLOBAL(eintrnames)
1303	.even
1304
1305GLOBAL(intrcnt)
1306	.long	0,0,0,0,0,0,0,0,0,0
1307GLOBAL(eintrcnt)
1308