xref: /netbsd-src/sys/arch/atari/atari/atari_init.c (revision ce0bb6e8d2e560ecacbe865a848624f94498063b)
1 /*	$NetBSD: atari_init.c,v 1.1.1.1 1995/03/26 07:12:21 leo Exp $	*/
2 
3 /*
4  * Copyright (c) 1995 Leo Weppelman
5  * Copyright (c) 1994 Michael L. Hitch
6  * Copyright (c) 1993 Markus Wild
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *      This product includes software developed by Markus Wild.
20  * 4. The name of the author may not be used to endorse or promote products
21  *    derived from this software without specific prior written permission
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/proc.h>
38 #include <vm/vm.h>
39 #include <sys/user.h>
40 #include <sys/ioctl.h>
41 #include <sys/select.h>
42 #include <sys/tty.h>
43 #include <sys/proc.h>
44 #include <sys/buf.h>
45 #include <sys/msgbuf.h>
46 #include <sys/mbuf.h>
47 #include <sys/protosw.h>
48 #include <sys/domain.h>
49 #include <sys/dkbad.h>
50 #include <sys/reboot.h>
51 #include <sys/exec.h>
52 #include <vm/pmap.h>
53 #include <machine/vmparam.h>
54 #include <machine/pte.h>
55 #include <machine/cpu.h>
56 #include <machine/iomap.h>
57 #include <machine/mfp.h>
58 #include <machine/scu.h>
59 #include <atari/atari/misc.h>
60 
61 extern u_int 	lowram;
62 extern u_int	Sysptmap, Sysptsize, Sysseg, Umap, proc0paddr;
63 u_int		*Sysmap;
64 int		machineid, mmutype, cpu040, astpending, cpuspeed;
65 char		*vmmap;
66 pv_entry_t	pv_table;
67 
68 /*
69  * Need-to-know for kernel reload code.
70  */
71 static u_long	boot_ttphystart, boot_ttphysize, boot_stphysize;
72 
73 extern char	*esym;
74 
75 /*
76  * The following vars become valid just before pmap_bootstrap is called.
77  * They give info about free memory with the kernel and the tables allocated
78  * in 'start_c' excluded.
79  */
80 extern vm_offset_t st_ramstart;	/* First available ST RAM address	*/
81 extern vm_offset_t st_ramend;	/* First ST RAM address	not available	*/
82 extern vm_offset_t tt_ramstart;	/* First available TT RAM address	*/
83 extern vm_offset_t tt_ramend;	/* First TT RAM address	not available	*/
84 
85 
86 /*
87  * This is the virtual address of physical page 0. Used by 'do_boot()'.
88  */
89 vm_offset_t	page_zero;
90 
91 /*
92  * Crude support for allocation in ST-ram. Currently only used to allocate
93  * video ram.
94  * The physical address is also returned because the video init needs it to
95  * setup the controller at the time the vm-system is not yet operational so
96  * 'kvtop()' cannot be used.
97  */
98 #define	ST_POOL_SIZE	(40*NBPG)	/* XXX: enough? */
99 
100 u_long	st_pool_size = ST_POOL_SIZE;	/* Patchable	*/
101 u_long	st_pool_virt, st_pool_phys;
102 
103 #if 0
104 void
105 *stmem_steal(amount, phys)
106 long amount;
107 vm_offset_t	*phys;
108 {
109 	/*
110 	 * steal from top of st-memory, so we don't collide with
111 	 * the kernel loaded into st-memory in the not-yet-mapped state.
112 	 */
113 	vm_offset_t p = st_pool_virt;
114 
115 	if(amount & 1)
116 		amount++;
117 	if(amount > st_pool_size)
118 		panic("not enough ST memory");
119 	*phys = st_pool_phys;
120 
121 	st_pool_virt  += amount;
122 	st_pool_phys  += amount;
123 	st_pool_size  -= amount;
124 
125 	return((void *)p);
126 }
127 #endif
128 
129 /*
130  * this is the C-level entry function, it's called from locore.s.
131  * Preconditions:
132  *	Interrupts are disabled
133  *	PA == VA, we don't have to relocate addresses before enabling
134  *		the MMU
135  * 	Exec is no longer available (because we're loaded all over
136  *		low memory, no ExecBase is available anymore)
137  *
138  * It's purpose is:
139  *	Do the things that are done in locore.s in the hp300 version,
140  *		this includes allocation of kernel maps and enabling the MMU.
141  *
142  * Some of the code in here is `stolen' from Amiga MACH, and was
143  * written by Bryan Ford and Niklas Hallqvist.
144  *
145  * Very crude 68040 support by Michael L. Hitch.
146  */
147 
148 void
149 start_c(id, ttphystart, ttphysize, stphysize, esym_addr)
150 int	id;			/* Machine id				*/
151 u_int	ttphystart, ttphysize;	/* Start address and size of TT-ram	*/
152 u_int	stphysize;		/* Size of ST-ram	 		*/
153 char	*esym_addr;		/* Address of kernel '_esym' symbol	*/
154 {
155 	extern char	end[];
156 	extern void	etext();
157 	extern u_long	protorp[2];
158 	u_int		pstart;		/* Next available physical address*/
159 	u_int		vstart;		/* Next available virtual address */
160 	u_int		avail;
161 	u_int		pt, ptsize;
162 	u_int		tc, i;
163 	u_int		*sg, *pg, *pg2;
164 	u_int		sg_proto, pg_proto;
165 	u_int		umap;
166 	u_int		p0_pt, p0_u_area, end_loaded;
167 	u_int		ptextra;
168 	u_long		kbase;
169 
170 	boot_ttphystart = ttphystart;
171 	boot_ttphysize  = ttphysize;
172 	boot_stphysize  = stphysize;
173 
174 	/*
175 	 * The following is a hack. We do not know how much ST memory we
176 	 * really need until after configuration has finished. At this
177 	 * time I have no idea how to grab ST memory at that time.
178 	 */
179 	st_pool_phys   = stphysize - st_pool_size;
180 	stphysize      = st_pool_phys;
181 
182 	machineid      = id;
183 	esym           = esym_addr;
184 
185 	/*
186 	 * the kernel ends at end() or esym.
187 	 */
188 	if(esym == NULL)
189 		end_loaded = (u_int)end;
190 	else end_loaded = (u_int)esym;
191 
192 
193 	/*
194 	 * If we have enough fast-memory to put the kernel in, do it!
195 	 */
196 	if(ttphysize >= end_loaded)
197 		kbase = ttphystart;
198 	else kbase = 0;
199 
200 	/*
201 	 * update these as soon as possible!
202 	 */
203 	PAGE_SIZE  = NBPG;
204 	PAGE_MASK  = NBPG-1;
205 	PAGE_SHIFT = PG_SHIFT;
206 
207 	/*
208 	 * We run the kernel from ST memory at the moment.
209 	 * The kernel segment table is put just behind the loaded image.
210 	 * pstart: start of usable ST memory
211 	 * avail : size of ST memory available.
212 	 */
213 	pstart = (u_int)end_loaded;
214 	pstart = atari_round_page(pstart);
215 	avail  = stphysize - pstart;
216 
217 	/*
218 	 * allocate the kernel segment table
219 	 */
220 	Sysseg  = pstart;
221 	pstart += NBPG;
222 	avail  -= NBPG;
223 
224 	/*
225 	 * We only allocate 1 extra pagetable. it currently only contains
226 	 * entries for Sysmap.
227 	 */
228 	ptextra = 0;
229 
230 	/*
231 	 * allocate initial page table pages
232 	 */
233 	pt      = pstart;
234 	ptsize  = (Sysptsize + howmany(ptextra, NPTEPG)) << PGSHIFT;
235 	pstart += ptsize;
236 	avail  -= ptsize;
237 
238 	/*
239 	 * allocate kernel page table map
240 	 */
241 	Sysptmap = pstart;
242 	pstart  += NBPG;
243 	avail   -= NBPG;
244 
245 	/*
246 	 * Set Sysmap; mapped after page table pages. Because I too (LWP)
247 	 * didn't understand the reason for this, I borrowed the following
248 	 * (sligthly modified) comment from mac68k/locore.s:
249 	 * LAK:  There seems to be some confusion here about the next line,
250 	 * so I'll explain.  The kernel needs some way of dynamically modifying
251 	 * the page tables for its own virtual memory.  What it does is that it
252 	 * has a page table map.  This page table map is mapped right after the
253 	 * kernel itself (in our implementation; in HP's it was after the I/O
254 	 * space). Therefore, the first three (or so) entries in the segment
255 	 * table point to the first three pages of the page tables (which
256 	 * point to the kernel) and the next entry in the segment table points
257 	 * to the page table map (this is done later).  Therefore, the value
258 	 * of the pointer "Sysmap" will be something like 16M*3 = 48M.  When
259 	 * the kernel addresses this pointer (e.g., Sysmap[0]), it will get
260 	 * the first longword of the first page map (== pt[0]).  Since the
261 	 * page map mirrors the segment table, addressing any index of Sysmap
262 	 * will give you a PTE of the page maps which map the kernel.
263 	 */
264 	Sysmap = (u_int *)(ptsize << (SEGSHIFT - PGSHIFT));
265 
266 	/*
267 	 * Initialize segment table and page table map.
268 	 */
269 	sg_proto = (pt + kbase) | SG_RW | SG_V;
270 	pg_proto = (pt + kbase) | PG_RW | PG_CI | PG_V;
271 	/*
272 	 * map so many segs
273 	 */
274 	sg = (u_int *)Sysseg;
275 	pg = (u_int *)Sysptmap;
276 	while(sg_proto < (pstart + kbase)) {
277 		*sg++ = sg_proto;
278 		*pg++ = pg_proto;
279 		sg_proto += NBPG;
280 		pg_proto += NBPG;
281 	}
282 	/*
283 	 * invalidate the remainder of the tables
284 	 * (except last entry)
285 	 */
286 	do {
287 		*sg++ = SG_NV;
288 		*pg++ = PG_NV;
289 	} while(sg < (u_int *)(Sysseg + ATARI_STSIZE - 4));
290 
291 	/*
292 	 * the end of the last segment (0xFF000000)
293 	 * of KVA space is used to map the u-area of
294 	 * the current process (u + kernel stack).
295 	 */
296 	sg_proto = (pstart + kbase) | SG_RW | SG_V; /* use next availabe PA */
297 	pg_proto = (pstart + kbase) | PG_RW | PG_CI | PG_V;
298 	umap     = pstart;	/* remember for later map entry */
299 
300 	/*
301 	 * enter the page into the segment table
302 	 * (and page table map)
303 	 */
304 	*sg++     = sg_proto;
305 	*pg++     = pg_proto;
306 
307 	/*
308 	 * invalidate all pte's (will validate u-area afterwards)
309 	 */
310 	for(pg = (u_int *) pstart; pg < (u_int *) (pstart + NBPG); )
311 		*pg++ = PG_NV;
312 
313 	/*
314 	 * account for the allocated page
315 	 */
316 	pstart   += NBPG;
317 	avail    -= NBPG;
318 
319 	/*
320 	 * record KVA at which to access current u-area PTE(s)
321 	 */
322 	Umap = (u_int)Sysmap + ATARI_MAX_PTSIZE - UPAGES * 4;
323 
324 	/*
325 	 * initialize kernel page table page(s).
326 	 * Assume load at VA 0.
327 	 * - Text pages are RO
328 	 */
329 	pg_proto = (0 + kbase) | PG_RO | PG_V;
330 	pg       = (u_int *) pt;
331 	for(i = 0; i < (u_int)etext; i += NBPG, pg_proto += NBPG)
332 		*pg++ = pg_proto;
333 
334 	/*
335 	 * data, bss and dynamic tables are read/write
336 	 */
337 	pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V;
338 
339 	/*
340 	 * go till end of data allocated so far
341 	 * plus proc0 PT/u-area (to be allocated)
342 	 */
343 	for(; i < pstart + (UPAGES + 1)*NBPG; i += NBPG, pg_proto += NBPG)
344 		*pg++ = pg_proto;
345 
346 	/*
347 	 * invalidate remainder of kernel PT
348 	 */
349 	while(pg < (u_int *)(pt + ptsize))
350 		*pg++ = PG_NV;
351 
352 	/*
353 	 * Go back and validate internal IO PTEs. They MUST be Cache inhibited!
354 	 */
355 	pg       = (u_int *) pt + (AD_IO / NBPG);
356 	pg_proto = AD_IO | PG_RW | PG_CI | PG_V;
357 	while(pg_proto < AD_EIO) {
358 		*pg++     = pg_proto;
359 		pg_proto += NBPG;
360 	}
361 
362 	/*
363 	 * Setup page table for process 0.
364 	 * We set up page table access for the kernel via Usrptmap (usrpt)
365 	 * [no longer used?] and access to the u-area itself via Umap (u).
366 	 * First available page (pstart) is used for proc0 page table.
367 	 * Next UPAGES page(s) following are for u-area.
368 	 */
369 
370 	p0_pt   = pstart;
371 	pstart += NBPG;
372 	avail  -= NBPG;
373 
374 	p0_u_area = pstart;		/* base of u-area and end of PT */
375 
376 	/*
377 	 * invalidate entire page table
378 	 */
379 	for(pg = (u_int *)p0_pt; pg < (u_int *) p0_u_area; )
380 		*pg++ = PG_NV;
381 
382 	/*
383 	 * now go back and validate u-area PTE(s) in PT and in Umap
384 	 */
385 	pg  -= UPAGES;
386 	pg2  = (u_int *) (umap + 4*(NPTEPG - UPAGES));
387 	pg_proto = (p0_u_area + kbase) | PG_RW | PG_V;
388 	for(i = 0; i < UPAGES; i++, pg_proto += NBPG) {
389 		*pg++  = pg_proto;
390 		*pg2++ = pg_proto;
391 	}
392 	bzero((u_char *)p0_u_area, UPAGES * NBPG);
393 
394 	/*
395 	 * save KVA of proc0 u-area
396 	 */
397 	proc0paddr = pstart;
398 	pstart    += UPAGES * NBPG;
399 	avail     -= UPAGES * NBPG;
400 
401 	/*
402 	 * At this point, virtual and physical allocation starts to divert.
403 	 */
404 	vstart     = pstart;
405 
406 	/*
407 	 * Map the allocated space in ST-ram now. In the contig-case, there
408 	 * is no need to make a distinction between virtual and physical
409 	 * adresses. But I make it anyway to be prepared.
410 	 * Physcal space is already reserved!
411 	 */
412 	st_pool_virt = vstart;
413 	pg           = (u_int *) pt + (vstart / NBPG);
414 	pg_proto     = st_pool_phys | PG_RW | PG_CI | PG_V;
415 	vstart      += st_pool_size;
416 	while(pg_proto < (st_pool_phys + st_pool_size)) {
417 		*pg++     = pg_proto;
418 		pg_proto += NBPG;
419 	}
420 
421 	/*
422 	 * Map physical page zero (First ST-ram page)
423 	 */
424 	page_zero  = vstart;
425 	pg         = (u_int *) pt + (vstart / NBPG);
426 	*pg        = PG_RW | PG_CI | PG_V;
427 	vstart    += NBPG;
428 
429 	lowram  = 0 >> PGSHIFT; /* XXX */
430 
431 	/*
432 	 * Initialize memory sizes
433 	 */
434 	st_ramstart    = 0;
435 	st_ramend      = stphysize;
436 	tt_ramstart    = ttphystart;
437 	tt_ramend      = ttphystart + ttphysize;
438 	if(kbase) {
439 		/*
440 		 * First page of ST-ram is unusable.
441 		 */
442 		st_ramstart  = NBPG;
443 		tt_ramstart += pstart;
444 	}
445 	else {
446 		/*
447 		 * Because the first 8 addresses of ST-memory are mapped to
448 		 * ROM, we remap them. This makes the debugger stack-trace
449 		 * work.
450 		 */
451 		extern	u_long	first_8_bytes[];
452 			u_long	*sp, *dp;
453 
454 		/*
455 		 * Copy page zero and set first 8 bytes.
456 		 */
457 		sp = (u_long *)0;
458 		dp = (u_long *)pstart;
459 		while(dp < (u_long *)(pstart+NBPG))
460 			*dp++ = *sp++;
461 		dp    = (u_long *)pstart;
462 		*dp++ = first_8_bytes[0];
463 		*dp   = first_8_bytes[1];
464 
465 		/*
466 		 * Enter into the page-table
467 		 */
468 		pg  = (u_int *)pt;
469 		*pg = pstart | PG_RO | PG_V;
470 
471 
472 		/*
473 		 * Reserve space for page 0
474 		 */
475 		pstart += NBPG;
476 
477 		st_ramstart += pstart;
478 	}
479 
480 	physmem = ((st_ramend-st_ramstart)+(tt_ramend-tt_ramstart)) >> PGSHIFT;
481 
482 	/*
483 	 * get the pmap module in sync with reality.
484 	 */
485 	pmap_bootstrap(vstart);
486 
487 
488 	/*
489 	 * Prepare to enable the MMU.
490 	 * Setup and load SRP nolimit, share global, 4 byte PTE's
491 	 */
492 	protorp[0] = 0x80000202;
493 	protorp[1] = Sysseg + kbase;	/* + segtable address */
494 
495 	/*
496 	 * copy over the kernel (and all now initialized variables)
497 	 * to fastram.  DONT use bcopy(), this beast is much larger
498 	 * than 128k !
499 	 */
500 	if(kbase) {
501 		register u_long	*lp, *le, *fp;
502 		extern	 u_long	first_8_bytes[];
503 
504 		lp = (u_long *)0;
505 		le = (u_long *)pstart;
506 		fp = (u_long *)kbase;
507 		while(lp < le)
508 			*fp++ = *lp++;
509 
510 		/*
511 		 * Fill in reset stuff
512 		 */
513 		fp    = (u_long *)kbase;
514 		*fp++ = first_8_bytes[0];
515 		*fp   = first_8_bytes[1];
516 	}
517 
518 	asm volatile ("pmove %0@,srp" : : "a" (&protorp[0]));
519 	/*
520 	 * setup and load TC register.
521 	 * enable_cpr, enable_srp, pagesize=8k,
522 	 * A = 8 bits, B = 11 bits
523 	 */
524 	tc = 0x82d08b00;
525 	asm volatile ("pmove %0@,tc" : : "a" (&tc));
526 
527 	/* Is this to fool the optimizer?? */
528 	i = *(int *)proc0paddr;
529 	*(volatile int *)proc0paddr = i;
530 
531 	/*
532 	 * Initialize both MFP chips to generate auto-vectored interrupts
533 	 * with EOI. The active-edge registers are set up. The interrupt
534 	 * enable registers are set to disable all interrupts.
535 	 */
536 	MFP->mf_iera  = MFP->mf_ierb = 0;
537 	MFP->mf_imra  = MFP->mf_imrb = 0;
538 	MFP->mf_aer   = 0;
539 	MFP->mf_vr    = 0x40;
540 	MFP2->mf_iera = MFP2->mf_ierb = 0;
541 	MFP2->mf_imra = MFP2->mf_imrb = 0;
542 	MFP2->mf_aer  = 0x80;
543 	MFP2->mf_vr   = 0x50;
544 
545 	/*
546 	 * Initialize the SCU, to enable interrupts on the SCC (ipl5),
547 	 * MFP (ipl6) and softints (ipl1).
548 	 */
549 	SCU->sys_mask = SCU_MFP | SCU_SCC | SCU_SYS_SOFT;
550 
551 	/*
552 	 * Initialize stmem allocator
553 	 */
554 	init_stmem();
555 }
556 
557 #ifdef DEBUG
558 void
559 dump_segtable(stp)
560 	u_int *stp;
561 {
562 	u_int *s, *es;
563 	int shift, i;
564 
565 	s = stp;
566 	{
567 		es = s + (ATARI_STSIZE >> 2);
568 		shift = SG_ISHIFT;
569 	}
570 
571 	/*
572 	 * XXX need changes for 68040
573 	 */
574 	for (i = 0; s < es; s++, i++)
575 		if (*s & SG_V)
576 			printf("$%08lx: $%08lx\t", i << shift, *s & SG_FRAME);
577 	printf("\n");
578 }
579 
580 void
581 dump_pagetable(ptp, i, n)
582 	u_int *ptp, i, n;
583 {
584 	u_int *p, *ep;
585 
586 	p = ptp + i;
587 	ep = p + n;
588 	for (; p < ep; p++, i++)
589 		if (*p & PG_V)
590 			printf("$%08lx -> $%08lx\t", i, *p & PG_FRAME);
591 	printf("\n");
592 }
593 
594 u_int
595 vmtophys(ste, vm)
596 	u_int *ste, vm;
597 {
598 	ste = (u_int *) (*(ste + (vm >> SEGSHIFT)) & SG_FRAME);
599 		ste += (vm & SG_PMASK) >> PGSHIFT;
600 	return((*ste & -NBPG) | (vm & (NBPG - 1)));
601 }
602 
603 #endif
604