xref: /netbsd-src/sys/arch/mvme68k/mvme68k/locore.s (revision 8ecbf5f02b752fcb7debe1a8fab1dc82602bc760)
1/*	$NetBSD: locore.s,v 1.115 2018/12/19 13:57:48 maxv 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#undef INTERRUPT_SAVEREG
978#undef INTERRUPT_RESTOREREG
979
980/*
981 * Emulation of VAX REI instruction.
982 *
983 * This code deals with checking for and servicing ASTs
984 * (profiling, scheduling).
985 * After identifing that we need an AST we drop the IPL to allow device
986 * interrupts.
987 *
988 * This code is complicated by the fact that sendsig may have been called
989 * necessitating a stack cleanup.
990 */
991ASENTRY_NOPROFILE(rei)
992	tstl	_C_LABEL(astpending)	| AST pending?
993	jeq	Ldorte			| Nope. Just return.
994	btst	#5,%sp@			| Returning to kernel mode?
995	jne	Ldorte			| Yup. Can't do ASTs
996	movw	#PSL_LOWIPL,%sr		| lower SPL
997	clrl	%sp@-			| stack adjust
998	moveml	#0xFFFF,%sp@-		| save all registers
999	movl	%usp,%a1		| including
1000	movl	%a1,%sp@(FR_SP)		|    the users SP
1001Lrei1:	clrl	%sp@-			| VA == none
1002	clrl	%sp@-			| code == none
1003	movl	#T_ASTFLT,%sp@-		| type == async system trap
1004	pea	%sp@(12)		| fp == address of trap frame
1005	jbsr	_C_LABEL(trap)		| go handle it
1006	lea	%sp@(16),%sp		| pop value args
1007	movl	%sp@(FR_SP),%a0		| restore user SP
1008	movl	%a0,%usp		|   from save area
1009	movw	%sp@(FR_ADJ),%d0	| need to adjust stack?
1010	jne	Laststkadj		| yes, go to it
1011	moveml	%sp@+,#0x7FFF		| no, restore most user regs
1012	addql	#8,%sp			| toss SP and stack adjust
1013Ldorte:	rte				| and do real RTE
1014
1015Laststkadj:
1016	lea	%sp@(FR_HW),%a1		| pointer to HW frame
1017	addql	#8,%a1			| source pointer
1018	movl	%a1,%a0			| source
1019	addw	%d0,%a0			|  + hole size = dest pointer
1020	movl	%a1@-,%a0@-		| copy
1021	movl	%a1@-,%a0@-		|  8 bytes
1022	movl	%a0,%sp@(FR_SP)		| new SSP
1023	moveml	%sp@+,#0x7FFF		| restore user registers
1024	movl	%sp@,%sp		| and our SP
1025	rte				| and do real RTE
1026
1027/*
1028 * Use common m68k sigcode.
1029 */
1030#include <m68k/m68k/sigcode.s>
1031#ifdef COMPAT_SUNOS
1032#include <m68k/m68k/sunos_sigcode.s>
1033#endif
1034
1035/*
1036 * Primitives
1037 */
1038
1039/*
1040 * Use common m68k support routines.
1041 */
1042#include <m68k/m68k/support.s>
1043
1044/*
1045 * Use common m68k process/lwp switch and context save subroutines.
1046 */
1047#define	FPCOPROC	/* XXX: Temp. Reqd. */
1048#include <m68k/m68k/switch_subr.s>
1049
1050
1051#if defined(M68040) || defined(M68060)
1052ENTRY(suline)
1053	movl	%sp@(4),%a0		| address to write
1054	movl	_C_LABEL(curpcb),%a1	| current pcb
1055	movl	#Lslerr,%a1@(PCB_ONFAULT) | where to return to on a fault
1056	movl	%sp@(8),%a1		| address of line
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	movl	%a1@+,%d0		| get lword
1067	movsl	%d0,%a0@+		| put lword
1068	nop				| sync
1069	moveq	#0,%d0			| indicate no fault
1070	jra	Lsldone
1071Lslerr:
1072	moveq	#-1,%d0
1073Lsldone:
1074	movl	_C_LABEL(curpcb),%a1	| current pcb
1075	clrl	%a1@(PCB_ONFAULT)	| clear fault address
1076	rts
1077#endif
1078
1079
1080ENTRY(ecacheon)
1081	rts
1082
1083ENTRY(ecacheoff)
1084	rts
1085
1086/*
1087 * Get callers current SP value.
1088 * Note that simply taking the address of a local variable in a C function
1089 * doesn't work because callee saved registers may be outside the stack frame
1090 * defined by A6 (e.g. GCC generated code).
1091 */
1092ENTRY_NOPROFILE(getsp)
1093	movl	%sp,%d0			| get current SP
1094	addql	#4,%d0			| compensate for return address
1095	movl	%d0,%a0
1096	rts
1097
1098/*
1099 * Load a new user segment table pointer.
1100 */
1101ENTRY(loadustp)
1102	movl	%sp@(4),%d0		| new USTP
1103	moveq	#PGSHIFT, %d1
1104	lsll	%d1,%d0			| convert to addr
1105#if defined(M68040) || defined(M68060)
1106	cmpl    #MMU_68040,_C_LABEL(mmutype) | 68040?
1107	jne     LmotommuC               | no, skip
1108	.word	0xf518			| pflusha
1109	.long   0x4e7b0806              | movc d0,urp
1110#ifdef M68060
1111	cmpl	#CPU_68060,_C_LABEL(cputype)
1112	jne	Lldno60
1113	movc	%cacr,%d0
1114	orl	#IC60_CUBC,%d0		| clear user branch cache entries
1115	movc	%d0,%cacr
1116Lldno60:
1117#endif
1118	rts
1119LmotommuC:
1120#endif
1121	pflusha				| flush entire TLB
1122	lea	_C_LABEL(protorp),%a0	| CRP prototype
1123	movl	%d0,%a0@(4)		| stash USTP
1124	pmove	%a0@,%crp		| load root pointer
1125	movl	#CACHE_CLR,%d0
1126	movc	%d0,%cacr		| invalidate cache(s)
1127	rts
1128
1129ENTRY(ploadw)
1130#ifdef M68030
1131#if defined(M68040) || defined(M68060)
1132	cmpl	#MMU_68040,_C_LABEL(mmutype) | 68040?
1133	jeq	Lploadwskp		| yes, skip
1134#endif
1135	movl	%sp@(4),%a0		| address to load
1136	ploadw	#1,%a0@			| pre-load translation
1137Lploadwskp:
1138#endif
1139	rts
1140
1141ENTRY(getsr)
1142	moveq	#0,%d0
1143	movw	%sr,%d0
1144	rts
1145
1146/*
1147 * _delay(unsigned N)
1148 *
1149 * Delay for at least (N/1024) microseconds.
1150 * This routine depends on the variable:  delay_divisor
1151 * which should be set based on the CPU clock rate.
1152 */
1153ENTRY_NOPROFILE(_delay)
1154	| d0 = arg = (usecs << 10)
1155	movl	%sp@(4),%d0
1156	| d1 = delay_divisor
1157	movl	_C_LABEL(delay_divisor),%d1
1158	jra	L_delay			/* Jump into the loop! */
1159
1160	/*
1161	 * Align the branch target of the loop to a half-line (8-byte)
1162	 * boundary to minimize cache effects.  This guarantees both
1163	 * that there will be no prefetch stalls due to cache line burst
1164	 * operations and that the loop will run from a single cache
1165	 * half-line.
1166	 */
1167#ifdef __ELF__
1168	.align	8
1169#else
1170	.align	3
1171#endif
1172L_delay:
1173	subl	%d1,%d0
1174	jgt	L_delay
1175	rts
1176
1177/*
1178 * Handle the nitty-gritty of rebooting the machine.
1179 * Basically we just turn off the MMU, restore the Bug's initial VBR
1180 * and either return to Bug or jump through the ROM reset vector
1181 * depending on how the system was halted.
1182 */
1183ENTRY_NOPROFILE(doboot)
1184	movw	#PSL_HIGHIPL,%sr
1185	movl	_C_LABEL(boothowto),%d1	| load howto
1186	movl	%sp@(4),%d2		| arg
1187	movl	_ASM_LABEL(bug_vbr),%d3	| Fetch Bug's original VBR value
1188	movl	_C_LABEL(machineid),%d4	| What type of board is this?
1189	movl	#CACHE_OFF,%d0
1190#if defined(M68040) || defined(M68060)
1191	cmpl	#MMU_68040,_C_LABEL(mmutype)	| 68040/68060?
1192	jne	Lnocache0		| no, skip
1193	.word	0xf4f8			| cpusha bc - push and invalidate caches
1194	nop
1195	movl	#CACHE40_OFF,%d0
1196#endif
1197Lnocache0:
1198	movc	%d0,%cacr		| disable on-chip cache(s)
1199
1200#if defined(M68040) || defined(M68060)
1201	cmpl	#MMU_68040,_C_LABEL(mmutype)
1202	jne	LmotommuF
1203	movql	#0,%d0
1204	movc	%d0,%cacr
1205	.long	0x4e7b0003              | movc d0,tc
1206	jra	Lbootcommon
1207LmotommuF:
1208#endif
1209	clrl	%sp@-			| value for pmove to TC (turn off MMU)
1210	pmove	%sp@,%tc		| disable MMU
1211	addql	#4,%sp
1212
1213Lbootcommon:
1214	/*
1215	 * MMU Switched off by now, so relocate all absolute references
1216	 */
1217	ASRELOC(tmpstk, %sp)		| physical SP in case of NMI
1218	movc	%d3,%vbr		| Restore Bug's VBR
1219	andl	#RB_SBOOT, %d1		| mask off
1220	jbne	Lsboot			| sboot?
1221	/* NOT sboot */
1222	tstl	%d2			| autoboot?
1223	jbeq	Ldoreset		| yes!
1224	CALLBUG(MVMEPROM_EXIT)		| return to bug
1225	/* NOTREACHED */
1226
1227Ldoreset:
1228	movl	#0xff800000,%a0		| Bug's reset vector address
1229	movl	%a0@+, %a7		| get SP
1230	movl	%a0@, %a0		| get PC
1231	jmp	%a0@			| go!
1232
1233Lsboot: /* sboot */
1234	tstl	%d2			| autoboot?
1235	jbeq	1f			| yes!
1236	jmp 	0x4000			| back to sboot
12371:	jmp	0x400a			| tell sboot to reboot us
1238
1239
1240/*
1241 * Misc. global variables.
1242 */
1243	.data
1244
1245GLOBAL(machineid)
1246	.long	MVME_147	| default to MVME_147
1247
1248GLOBAL(mmutype)
1249	.long	MMU_68030	| default to MMU_68030
1250
1251GLOBAL(cputype)
1252	.long	CPU_68030	| default to CPU_68030
1253
1254GLOBAL(fputype)
1255	.long	FPU_68882	| default to FPU_68882
1256
1257GLOBAL(protorp)
1258	.long	0,0		| prototype root pointer
1259
1260/*
1261 * Information from first stage boot program
1262 */
1263GLOBAL(bootpart)
1264	.long	0
1265GLOBAL(bootdevlun)
1266	.long	0
1267GLOBAL(bootctrllun)
1268	.long	0
1269GLOBAL(bootaddr)
1270	.long	0
1271
1272GLOBAL(intiobase)
1273	.long	0		| KVA of base of internal IO space
1274
1275GLOBAL(intiolimit)
1276	.long	0		| KVA of end of internal IO space
1277
1278GLOBAL(intiobase_phys)
1279	.long	0		| PA of board's I/O registers
1280
1281GLOBAL(intiotop_phys)
1282	.long	0		| PA of top of board's I/O registers
1283
1284/*
1285 * interrupt counters.
1286 * XXXSCW: Will go away soon; kept here to keep vmstat happy
1287 */
1288GLOBAL(intrnames)
1289	.asciz	"spur"
1290	.asciz	"lev1"
1291	.asciz	"lev2"
1292	.asciz	"lev3"
1293	.asciz	"lev4"
1294	.asciz	"clock"
1295	.asciz	"lev6"
1296	.asciz	"nmi"
1297	.asciz	"statclock"
1298GLOBAL(eintrnames)
1299	.even
1300
1301GLOBAL(intrcnt)
1302	.long	0,0,0,0,0,0,0,0,0,0
1303GLOBAL(eintrcnt)
1304