xref: /netbsd-src/sys/arch/atari/atari/atari_init.c (revision 9573504567626934c7ee01c7dce0c4bb1dfe7403)
1 /*	$NetBSD: atari_init.c,v 1.8 1995/08/17 20:31:31 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 <machine/video.h>
60 #include <atari/atari/misc.h>
61 
62 extern u_int 	lowram;
63 extern u_int	Sysptmap, Sysptsize, Sysseg, proc0paddr;
64 u_int		*Sysmap;
65 int		machineid, mmutype, cpu040, astpending;
66 char		*vmmap;
67 pv_entry_t	pv_table;
68 
69 /*
70  * Need-to-know for kernel reload code.
71  */
72 u_long	boot_ttphystart, boot_ttphysize, boot_stphysize;
73 
74 extern char	*esym;
75 
76 /*
77  * This is the virtual address of physical page 0. Used by 'do_boot()'.
78  */
79 vm_offset_t	page_zero;
80 
81 /*
82  * Crude support for allocation in ST-ram. Currently only used to allocate
83  * video ram.
84  * The physical address is also returned because the video init needs it to
85  * setup the controller at the time the vm-system is not yet operational so
86  * 'kvtop()' cannot be used.
87  */
88 #ifndef ST_POOL_SIZE
89 #define	ST_POOL_SIZE	40			/* XXX: enough? */
90 #endif
91 
92 u_long	st_pool_size = ST_POOL_SIZE * NBPG;	/* Patchable	*/
93 u_long	st_pool_virt, st_pool_phys;
94 
95 /*
96  * this is the C-level entry function, it's called from locore.s.
97  * Preconditions:
98  *	Interrupts are disabled
99  *	PA == VA, we don't have to relocate addresses before enabling
100  *		the MMU
101  * 	Exec is no longer available (because we're loaded all over
102  *		low memory, no ExecBase is available anymore)
103  *
104  * It's purpose is:
105  *	Do the things that are done in locore.s in the hp300 version,
106  *		this includes allocation of kernel maps and enabling the MMU.
107  *
108  * Some of the code in here is `stolen' from Amiga MACH, and was
109  * written by Bryan Ford and Niklas Hallqvist.
110  *
111  * Very crude 68040 support by Michael L. Hitch.
112  */
113 
114 void
115 start_c(id, ttphystart, ttphysize, stphysize, esym_addr)
116 int	id;			/* Machine id				*/
117 u_int	ttphystart, ttphysize;	/* Start address and size of TT-ram	*/
118 u_int	stphysize;		/* Size of ST-ram	 		*/
119 char	*esym_addr;		/* Address of kernel '_esym' symbol	*/
120 {
121 	extern char	end[];
122 	extern void	etext();
123 	extern u_long	protorp[2];
124 	u_int		pstart;		/* Next available physical address*/
125 	u_int		vstart;		/* Next available virtual address */
126 	u_int		avail;
127 	u_int		pt, ptsize;
128 	u_int		tc, i;
129 	u_int		*sg, *pg;
130 	u_int		sg_proto, pg_proto;
131 	u_int		end_loaded;
132 	u_int		ptextra;
133 	u_long		kbase;
134 
135 	boot_ttphystart = ttphystart;
136 	boot_ttphysize  = ttphysize;
137 	boot_stphysize  = stphysize;
138 
139 	/*
140 	 * The following is a hack. We do not know how much ST memory we
141 	 * really need until after configuration has finished. At this
142 	 * time I have no idea how to grab ST memory at that time.
143 	 * The round_page() call is ment to correct errors made by
144 	 * binpatching!
145 	 */
146 	st_pool_size   = atari_round_page(st_pool_size);
147 	st_pool_phys   = stphysize - st_pool_size;
148 	stphysize      = st_pool_phys;
149 
150 	machineid      = id;
151 	esym           = esym_addr;
152 
153 	/*
154 	 * the kernel ends at end() or esym.
155 	 */
156 	if(esym == NULL)
157 		end_loaded = (u_int)end;
158 	else end_loaded = (u_int)esym;
159 
160 
161 	/*
162 	 * If we have enough fast-memory to put the kernel in, do it!
163 	 */
164 	if(ttphysize >= end_loaded)
165 		kbase = ttphystart;
166 	else kbase = 0;
167 
168 	/*
169 	 * update these as soon as possible!
170 	 */
171 	PAGE_SIZE  = NBPG;
172 	PAGE_MASK  = NBPG-1;
173 	PAGE_SHIFT = PG_SHIFT;
174 
175 	/*
176 	 * We run the kernel from ST memory at the moment.
177 	 * The kernel segment table is put just behind the loaded image.
178 	 * pstart: start of usable ST memory
179 	 * avail : size of ST memory available.
180 	 */
181 	pstart = (u_int)end_loaded;
182 	pstart = atari_round_page(pstart);
183 	avail  = stphysize - pstart;
184 
185 	/*
186 	 * allocate the kernel segment table
187 	 */
188 	Sysseg  = pstart;
189 	pstart += NBPG;
190 	avail  -= NBPG;
191 
192 	/*
193 	 * We only allocate 1 extra pagetable. it currently only contains
194 	 * entries for Sysmap.
195 	 */
196 	ptextra = 0;
197 
198 	/*
199 	 * allocate initial page table pages
200 	 */
201 	pt      = pstart;
202 	ptsize  = (Sysptsize + howmany(ptextra, NPTEPG)) << PGSHIFT;
203 	pstart += ptsize;
204 	avail  -= ptsize;
205 
206 	/*
207 	 * allocate kernel page table map
208 	 */
209 	Sysptmap = pstart;
210 	pstart  += NBPG;
211 	avail   -= NBPG;
212 
213 	/*
214 	 * Set Sysmap; mapped after page table pages. Because I too (LWP)
215 	 * didn't understand the reason for this, I borrowed the following
216 	 * (sligthly modified) comment from mac68k/locore.s:
217 	 * LAK:  There seems to be some confusion here about the next line,
218 	 * so I'll explain.  The kernel needs some way of dynamically modifying
219 	 * the page tables for its own virtual memory.  What it does is that it
220 	 * has a page table map.  This page table map is mapped right after the
221 	 * kernel itself (in our implementation; in HP's it was after the I/O
222 	 * space). Therefore, the first three (or so) entries in the segment
223 	 * table point to the first three pages of the page tables (which
224 	 * point to the kernel) and the next entry in the segment table points
225 	 * to the page table map (this is done later).  Therefore, the value
226 	 * of the pointer "Sysmap" will be something like 16M*3 = 48M.  When
227 	 * the kernel addresses this pointer (e.g., Sysmap[0]), it will get
228 	 * the first longword of the first page map (== pt[0]).  Since the
229 	 * page map mirrors the segment table, addressing any index of Sysmap
230 	 * will give you a PTE of the page maps which map the kernel.
231 	 */
232 	Sysmap = (u_int *)(ptsize << (SEGSHIFT - PGSHIFT));
233 
234 	/*
235 	 * Initialize segment table and page table map.
236 	 */
237 	sg_proto = (pt + kbase) | SG_RW | SG_V;
238 	pg_proto = (pt + kbase) | PG_RW | PG_CI | PG_V;
239 	/*
240 	 * map so many segs
241 	 */
242 	sg = (u_int *)Sysseg;
243 	pg = (u_int *)Sysptmap;
244 	while(sg_proto < (pstart + kbase)) {
245 		*sg++ = sg_proto;
246 		*pg++ = pg_proto;
247 		sg_proto += NBPG;
248 		pg_proto += NBPG;
249 	}
250 	/*
251 	 * invalidate the remainder of the tables
252 	 */
253 	do {
254 		*sg++ = SG_NV;
255 		*pg++ = PG_NV;
256 	} while(sg < (u_int *)(Sysseg + ATARI_STSIZE));
257 
258 	/*
259 	 * initialize kernel page table page(s).
260 	 * Assume load at VA 0.
261 	 * - Text pages are RO
262 	 */
263 	pg_proto = (0 + kbase) | PG_RO | PG_V;
264 	pg       = (u_int *) pt;
265 	for(i = 0; i < (u_int)etext; i += NBPG, pg_proto += NBPG)
266 		*pg++ = pg_proto;
267 
268 	/*
269 	 * data, bss and dynamic tables are read/write
270 	 */
271 	pg_proto = (pg_proto & PG_FRAME) | PG_RW | PG_V;
272 
273 	/*
274 	 * go till end of data allocated so far
275 	 * plus proc0 u-area (to be allocated)
276 	 */
277 	for(; i < pstart + USPACE; i += NBPG, pg_proto += NBPG)
278 		*pg++ = pg_proto;
279 
280 	/*
281 	 * invalidate remainder of kernel PT
282 	 */
283 	while(pg < (u_int *)(pt + ptsize))
284 		*pg++ = PG_NV;
285 
286 	/*
287 	 * Go back and validate internal IO PTEs. They MUST be Cache inhibited!
288 	 */
289 	pg       = (u_int *) pt + (AD_IO / NBPG);
290 	pg_proto = AD_IO | PG_RW | PG_CI | PG_V;
291 	while(pg_proto < AD_EIO) {
292 		*pg++     = pg_proto;
293 		pg_proto += NBPG;
294 	}
295 
296 	/*
297 	 * Clear proc0 user-area
298 	 */
299 	bzero((u_char *)pstart, USPACE);
300 
301 	/*
302 	 * Save KVA of proc0 user-area and allocate it
303 	 */
304 	proc0paddr = pstart;
305 	pstart    += USPACE;
306 	avail     -= USPACE;
307 
308 	/*
309 	 * At this point, virtual and physical allocation starts to divert.
310 	 */
311 	vstart     = pstart;
312 
313 	/*
314 	 * Map the allocated space in ST-ram now. In the contig-case, there
315 	 * is no need to make a distinction between virtual and physical
316 	 * adresses. But I make it anyway to be prepared.
317 	 * Physcal space is already reserved!
318 	 */
319 	st_pool_virt = vstart;
320 	pg           = (u_int *) pt + (vstart / NBPG);
321 	pg_proto     = st_pool_phys | PG_RW | PG_CI | PG_V;
322 	vstart      += st_pool_size;
323 	while(pg_proto < (st_pool_phys + st_pool_size)) {
324 		*pg++     = pg_proto;
325 		pg_proto += NBPG;
326 	}
327 
328 	/*
329 	 * Map physical page zero (First ST-ram page)
330 	 */
331 	page_zero  = vstart;
332 	pg         = (u_int *) pt + (vstart / NBPG);
333 	*pg        = PG_RW | PG_CI | PG_V;
334 	vstart    += NBPG;
335 
336 	lowram  = 0 >> PGSHIFT; /* XXX */
337 
338 	/*
339 	 * Fill in segments. The page indexes will be initialized
340 	 * later when all reservations are made.
341 	 */
342 	phys_segs[0].start       = 0;
343 	phys_segs[0].end         = stphysize;
344 	phys_segs[1].start       = ttphystart;
345 	phys_segs[1].end         = ttphystart + ttphysize;
346 	phys_segs[2].start       = 0; /* End of segments! */
347 
348 	if(kbase) {
349 		/*
350 		 * First page of ST-ram is unusable, reserve the space
351 		 * for the kernel in the TT-ram segment.
352 		 */
353 		phys_segs[0].start  = NBPG;
354 		phys_segs[1].start += pstart;
355 	}
356 	else {
357 		/*
358 		 * Because the first 8 addresses of ST-memory are mapped to
359 		 * ROM, we remap them. This makes the debugger stack-trace
360 		 * work.
361 		 */
362 		extern	u_long	first_8_bytes[];
363 			u_long	*sp, *dp;
364 
365 		/*
366 		 * Copy page zero and set first 8 bytes.
367 		 */
368 		sp = (u_long *)0;
369 		dp = (u_long *)pstart;
370 		while(dp < (u_long *)(pstart+NBPG))
371 			*dp++ = *sp++;
372 		dp    = (u_long *)pstart;
373 		*dp++ = first_8_bytes[0];
374 		*dp   = first_8_bytes[1];
375 
376 		/*
377 		 * Enter into the page-table
378 		 */
379 		pg  = (u_int *)pt;
380 		*pg = pstart | PG_RO | PG_V;
381 
382 
383 		/*
384 		 * Reserve space for page 0, and allocate the kernel
385 		 * space from the ST-ram segment.
386 		 */
387 		pstart += NBPG;
388 		phys_segs[0].start += pstart;
389 	}
390 
391 	/*
392 	 * As all segment sizes are now valid, calculate page indexes and
393 	 * available physical memory.
394 	 */
395 	phys_segs[0].first_page = 0;
396 	for (i = 1; phys_segs[i].start; i++) {
397 		phys_segs[i].first_page  = phys_segs[i-1].first_page;
398 		phys_segs[i].first_page +=
399 			(phys_segs[i-1].end - phys_segs[i-1].start) / NBPG;
400 	}
401 	for (i = 0, physmem = 0; phys_segs[i].start; i++)
402 		physmem += phys_segs[i].end - phys_segs[i].start;
403 	physmem >>= PGSHIFT;
404 
405 	/*
406 	 * get the pmap module in sync with reality.
407 	 */
408 	pmap_bootstrap(vstart);
409 
410 	/*
411 	 * Prepare to enable the MMU.
412 	 * Setup and load SRP nolimit, share global, 4 byte PTE's
413 	 */
414 	protorp[0] = 0x80000202;
415 	protorp[1] = Sysseg + kbase;	/* + segtable address */
416 
417 	/*
418 	 * copy over the kernel (and all now initialized variables)
419 	 * to fastram.  DONT use bcopy(), this beast is much larger
420 	 * than 128k !
421 	 */
422 	if(kbase) {
423 		register u_long	*lp, *le, *fp;
424 		extern	 u_long	first_8_bytes[];
425 
426 		lp = (u_long *)0;
427 		le = (u_long *)pstart;
428 		fp = (u_long *)kbase;
429 		while(lp < le)
430 			*fp++ = *lp++;
431 
432 		/*
433 		 * Fill in reset stuff
434 		 */
435 		fp    = (u_long *)kbase;
436 		*fp++ = first_8_bytes[0];
437 		*fp   = first_8_bytes[1];
438 	}
439 
440 	asm volatile ("pmove %0@,srp" : : "a" (&protorp[0]));
441 	/*
442 	 * setup and load TC register.
443 	 * enable_cpr, enable_srp, pagesize=8k,
444 	 * A = 8 bits, B = 11 bits
445 	 */
446 	tc = 0x82d08b00;
447 	asm volatile ("pmove %0@,tc" : : "a" (&tc));
448 
449 	/* Is this to fool the optimizer?? */
450 	i = *(int *)proc0paddr;
451 	*(volatile int *)proc0paddr = i;
452 
453 	/*
454 	 * Initialize the sound-chip YM2149:
455 	 *   All sounds off, both ports output.
456 	 */
457 	SOUND->sd_selr = YM_MFR;
458 	SOUND->sd_wdat = 0xff;
459 
460 	/*
461 	 * Initialize both MFP chips (if both present!) to generate
462 	 * auto-vectored interrupts with EOI. The active-edge registers are
463 	 * set up. The interrupt enable registers are set to disable all
464 	 * interrupts.
465 	 * A test on presence on the second MFP determines if this is a
466 	 * TT030 or a Falcon. This is added to 'machineid'.
467 	 */
468 	MFP->mf_iera  = MFP->mf_ierb = 0;
469 	MFP->mf_imra  = MFP->mf_imrb = 0;
470 	MFP->mf_aer   = 0;
471 	MFP->mf_vr    = 0x40;
472 	if(!badbaddr(&MFP2->mf_gpip)) {
473 		machineid |= ATARI_TT;
474 		MFP2->mf_iera = MFP2->mf_ierb = 0;
475 		MFP2->mf_imra = MFP2->mf_imrb = 0;
476 		MFP2->mf_aer  = 0x80;
477 		MFP2->mf_vr   = 0x50;
478 
479 		/*
480 		 * Initialize the SCU, to enable interrupts on the SCC (ipl5),
481 		 * MFP (ipl6) and softints (ipl1).
482 		 */
483 		SCU->sys_mask = SCU_MFP | SCU_SCC | SCU_SYS_SOFT;
484 	}
485 	else machineid |= ATARI_FALCON;
486 
487 	/*
488 	 * Initialize stmem allocator
489 	 */
490 	init_stmem();
491 }
492 
493 #ifdef DEBUG
494 void
495 dump_segtable(stp)
496 	u_int *stp;
497 {
498 	u_int *s, *es;
499 	int shift, i;
500 
501 	s = stp;
502 	{
503 		es = s + (ATARI_STSIZE >> 2);
504 		shift = SG_ISHIFT;
505 	}
506 
507 	/*
508 	 * XXX need changes for 68040
509 	 */
510 	for (i = 0; s < es; s++, i++)
511 		if (*s & SG_V)
512 			printf("$%08lx: $%08lx\t", i << shift, *s & SG_FRAME);
513 	printf("\n");
514 }
515 
516 void
517 dump_pagetable(ptp, i, n)
518 	u_int *ptp, i, n;
519 {
520 	u_int *p, *ep;
521 
522 	p = ptp + i;
523 	ep = p + n;
524 	for (; p < ep; p++, i++)
525 		if (*p & PG_V)
526 			printf("$%08lx -> $%08lx\t", i, *p & PG_FRAME);
527 	printf("\n");
528 }
529 
530 u_int
531 vmtophys(ste, vm)
532 	u_int *ste, vm;
533 {
534 	ste = (u_int *) (*(ste + (vm >> SEGSHIFT)) & SG_FRAME);
535 		ste += (vm & SG_PMASK) >> PGSHIFT;
536 	return((*ste & -NBPG) | (vm & (NBPG - 1)));
537 }
538 
539 #endif
540