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