diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/m68k/kernel/head.S |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'arch/m68k/kernel/head.S')
-rw-r--r-- | arch/m68k/kernel/head.S | 3940 |
1 files changed, 3940 insertions, 0 deletions
diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S new file mode 100644 index 000000000000..7cd6de17c20d --- /dev/null +++ b/arch/m68k/kernel/head.S | |||
@@ -0,0 +1,3940 @@ | |||
1 | /* -*- mode: asm -*- | ||
2 | ** | ||
3 | ** head.S -- This file contains the initial boot code for the | ||
4 | ** Linux/68k kernel. | ||
5 | ** | ||
6 | ** Copyright 1993 by Hamish Macdonald | ||
7 | ** | ||
8 | ** 68040 fixes by Michael Rausch | ||
9 | ** 68060 fixes by Roman Hodek | ||
10 | ** MMU cleanup by Randy Thelen | ||
11 | ** Final MMU cleanup by Roman Zippel | ||
12 | ** | ||
13 | ** Atari support by Andreas Schwab, using ideas of Robert de Vries | ||
14 | ** and Bjoern Brauel | ||
15 | ** VME Support by Richard Hirst | ||
16 | ** | ||
17 | ** 94/11/14 Andreas Schwab: put kernel at PAGESIZE | ||
18 | ** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari | ||
19 | ** ++ Bjoern & Roman: ATARI-68040 support for the Medusa | ||
20 | ** 95/11/18 Richard Hirst: Added MVME166 support | ||
21 | ** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with | ||
22 | ** Magnum- and FX-alternate ram | ||
23 | ** 98/04/25 Phil Blundell: added HP300 support | ||
24 | ** 1998/08/30 David Kilzer: Added support for font_desc structures | ||
25 | ** for linux-2.1.115 | ||
26 | ** 9/02/11 Richard Zidlicky: added Q40 support (initial vesion 99/01/01) | ||
27 | ** 2004/05/13 Kars de Jong: Finalised HP300 support | ||
28 | ** | ||
29 | ** This file is subject to the terms and conditions of the GNU General Public | ||
30 | ** License. See the file README.legal in the main directory of this archive | ||
31 | ** for more details. | ||
32 | ** | ||
33 | */ | ||
34 | |||
35 | /* | ||
36 | * Linux startup code. | ||
37 | * | ||
38 | * At this point, the boot loader has: | ||
39 | * Disabled interrupts | ||
40 | * Disabled caches | ||
41 | * Put us in supervisor state. | ||
42 | * | ||
43 | * The kernel setup code takes the following steps: | ||
44 | * . Raise interrupt level | ||
45 | * . Set up initial kernel memory mapping. | ||
46 | * . This sets up a mapping of the 4M of memory the kernel is located in. | ||
47 | * . It also does a mapping of any initial machine specific areas. | ||
48 | * . Enable the MMU | ||
49 | * . Enable cache memories | ||
50 | * . Jump to kernel startup | ||
51 | * | ||
52 | * Much of the file restructuring was to accomplish: | ||
53 | * 1) Remove register dependency through-out the file. | ||
54 | * 2) Increase use of subroutines to perform functions | ||
55 | * 3) Increase readability of the code | ||
56 | * | ||
57 | * Of course, readability is a subjective issue, so it will never be | ||
58 | * argued that that goal was accomplished. It was merely a goal. | ||
59 | * A key way to help make code more readable is to give good | ||
60 | * documentation. So, the first thing you will find is exaustive | ||
61 | * write-ups on the structure of the file, and the features of the | ||
62 | * functional subroutines. | ||
63 | * | ||
64 | * General Structure: | ||
65 | * ------------------ | ||
66 | * Without a doubt the single largest chunk of head.S is spent | ||
67 | * mapping the kernel and I/O physical space into the logical range | ||
68 | * for the kernel. | ||
69 | * There are new subroutines and data structures to make MMU | ||
70 | * support cleaner and easier to understand. | ||
71 | * First, you will find a routine call "mmu_map" which maps | ||
72 | * a logical to a physical region for some length given a cache | ||
73 | * type on behalf of the caller. This routine makes writing the | ||
74 | * actual per-machine specific code very simple. | ||
75 | * A central part of the code, but not a subroutine in itself, | ||
76 | * is the mmu_init code which is broken down into mapping the kernel | ||
77 | * (the same for all machines) and mapping machine-specific I/O | ||
78 | * regions. | ||
79 | * Also, there will be a description of engaging the MMU and | ||
80 | * caches. | ||
81 | * You will notice that there is a chunk of code which | ||
82 | * can emit the entire MMU mapping of the machine. This is present | ||
83 | * only in debug modes and can be very helpful. | ||
84 | * Further, there is a new console driver in head.S that is | ||
85 | * also only engaged in debug mode. Currently, it's only supported | ||
86 | * on the Macintosh class of machines. However, it is hoped that | ||
87 | * others will plug-in support for specific machines. | ||
88 | * | ||
89 | * ###################################################################### | ||
90 | * | ||
91 | * mmu_map | ||
92 | * ------- | ||
93 | * mmu_map was written for two key reasons. First, it was clear | ||
94 | * that it was very difficult to read the previous code for mapping | ||
95 | * regions of memory. Second, the Macintosh required such extensive | ||
96 | * memory allocations that it didn't make sense to propagate the | ||
97 | * existing code any further. | ||
98 | * mmu_map requires some parameters: | ||
99 | * | ||
100 | * mmu_map (logical, physical, length, cache_type) | ||
101 | * | ||
102 | * While this essentially describes the function in the abstract, you'll | ||
103 | * find more indepth description of other parameters at the implementation site. | ||
104 | * | ||
105 | * mmu_get_root_table_entry | ||
106 | * ------------------------ | ||
107 | * mmu_get_ptr_table_entry | ||
108 | * ----------------------- | ||
109 | * mmu_get_page_table_entry | ||
110 | * ------------------------ | ||
111 | * | ||
112 | * These routines are used by other mmu routines to get a pointer into | ||
113 | * a table, if necessary a new table is allocated. These routines are working | ||
114 | * basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root | ||
115 | * table needs of course only to be allocated once in mmu_get_root_table_entry, | ||
116 | * so that here also some mmu specific initialization is done. The second page | ||
117 | * at the start of the kernel (the first page is unmapped later) is used for | ||
118 | * the kernel_pg_dir. It must be at a position known at link time (as it's used | ||
119 | * to initialize the init task struct) and since it needs special cache | ||
120 | * settings, it's the easiest to use this page, the rest of the page is used | ||
121 | * for further pointer tables. | ||
122 | * mmu_get_page_table_entry allocates always a whole page for page tables, this | ||
123 | * means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense | ||
124 | * to manage page tables in smaller pieces as nearly all mappings have that | ||
125 | * size. | ||
126 | * | ||
127 | * ###################################################################### | ||
128 | * | ||
129 | * | ||
130 | * ###################################################################### | ||
131 | * | ||
132 | * mmu_engage | ||
133 | * ---------- | ||
134 | * Thanks to a small helping routine enabling the mmu got quite simple | ||
135 | * and there is only one way left. mmu_engage makes a complete a new mapping | ||
136 | * that only includes the absolute necessary to be able to jump to the final | ||
137 | * postion and to restore the original mapping. | ||
138 | * As this code doesn't need a transparent translation register anymore this | ||
139 | * means all registers are free to be used by machines that needs them for | ||
140 | * other purposes. | ||
141 | * | ||
142 | * ###################################################################### | ||
143 | * | ||
144 | * mmu_print | ||
145 | * --------- | ||
146 | * This algorithm will print out the page tables of the system as | ||
147 | * appropriate for an 030 or an 040. This is useful for debugging purposes | ||
148 | * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses. | ||
149 | * | ||
150 | * ###################################################################### | ||
151 | * | ||
152 | * console_init | ||
153 | * ------------ | ||
154 | * The console is also able to be turned off. The console in head.S | ||
155 | * is specifically for debugging and can be very useful. It is surrounded by | ||
156 | * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good | ||
157 | * kernels. It's basic algorithm is to determine the size of the screen | ||
158 | * (in height/width and bit depth) and then use that information for | ||
159 | * displaying an 8x8 font or an 8x16 (widthxheight). I prefer the 8x8 for | ||
160 | * debugging so I can see more good data. But it was trivial to add support | ||
161 | * for both fonts, so I included it. | ||
162 | * Also, the algorithm for plotting pixels is abstracted so that in | ||
163 | * theory other platforms could add support for different kinds of frame | ||
164 | * buffers. This could be very useful. | ||
165 | * | ||
166 | * console_put_penguin | ||
167 | * ------------------- | ||
168 | * An important part of any Linux bring up is the penguin and there's | ||
169 | * nothing like getting the Penguin on the screen! This algorithm will work | ||
170 | * on any machine for which there is a console_plot_pixel. | ||
171 | * | ||
172 | * console_scroll | ||
173 | * -------------- | ||
174 | * My hope is that the scroll algorithm does the right thing on the | ||
175 | * various platforms, but it wouldn't be hard to add the test conditions | ||
176 | * and new code if it doesn't. | ||
177 | * | ||
178 | * console_putc | ||
179 | * ------------- | ||
180 | * | ||
181 | * ###################################################################### | ||
182 | * | ||
183 | * Register usage has greatly simplified within head.S. Every subroutine | ||
184 | * saves and restores all registers that it modifies (except it returns a | ||
185 | * value in there of course). So the only register that needs to be initialized | ||
186 | * is the stack pointer. | ||
187 | * All other init code and data is now placed in the init section, so it will | ||
188 | * be automatically freed at the end of the kernel initialization. | ||
189 | * | ||
190 | * ###################################################################### | ||
191 | * | ||
192 | * options | ||
193 | * ------- | ||
194 | * There are many options available in a build of this file. I've | ||
195 | * taken the time to describe them here to save you the time of searching | ||
196 | * for them and trying to understand what they mean. | ||
197 | * | ||
198 | * CONFIG_xxx: These are the obvious machine configuration defines created | ||
199 | * during configuration. These are defined in include/linux/autoconf.h. | ||
200 | * | ||
201 | * CONSOLE: There is support for head.S console in this file. This | ||
202 | * console can talk to a Mac frame buffer, but could easily be extrapolated | ||
203 | * to extend it to support other platforms. | ||
204 | * | ||
205 | * TEST_MMU: This is a test harness for running on any given machine but | ||
206 | * getting an MMU dump for another class of machine. The classes of machines | ||
207 | * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.) | ||
208 | * and any of the models (030, 040, 060, etc.). | ||
209 | * | ||
210 | * NOTE: TEST_MMU is NOT permanent! It is scheduled to be removed | ||
211 | * When head.S boots on Atari, Amiga, Macintosh, and VME | ||
212 | * machines. At that point the underlying logic will be | ||
213 | * believed to be solid enough to be trusted, and TEST_MMU | ||
214 | * can be dropped. Do note that that will clean up the | ||
215 | * head.S code significantly as large blocks of #if/#else | ||
216 | * clauses can be removed. | ||
217 | * | ||
218 | * MMU_NOCACHE_KERNEL: On the Macintosh platform there was an inquiry into | ||
219 | * determing why devices don't appear to work. A test case was to remove | ||
220 | * the cacheability of the kernel bits. | ||
221 | * | ||
222 | * MMU_PRINT: There is a routine built into head.S that can display the | ||
223 | * MMU data structures. It outputs its result through the serial_putc | ||
224 | * interface. So where ever that winds up driving data, that's where the | ||
225 | * mmu struct will appear. On the Macintosh that's typically the console. | ||
226 | * | ||
227 | * SERIAL_DEBUG: There are a series of putc() macro statements | ||
228 | * scattered through out the code to give progress of status to the | ||
229 | * person sitting at the console. This constant determines whether those | ||
230 | * are used. | ||
231 | * | ||
232 | * DEBUG: This is the standard DEBUG flag that can be set for building | ||
233 | * the kernel. It has the effect adding additional tests into | ||
234 | * the code. | ||
235 | * | ||
236 | * FONT_6x11: | ||
237 | * FONT_8x8: | ||
238 | * FONT_8x16: | ||
239 | * In theory these could be determined at run time or handed | ||
240 | * over by the booter. But, let's be real, it's a fine hard | ||
241 | * coded value. (But, you will notice the code is run-time | ||
242 | * flexible!) A pointer to the font's struct font_desc | ||
243 | * is kept locally in Lconsole_font. It is used to determine | ||
244 | * font size information dynamically. | ||
245 | * | ||
246 | * Atari constants: | ||
247 | * USE_PRINTER: Use the printer port for serial debug. | ||
248 | * USE_SCC_B: Use the SCC port A (Serial2) for serial debug. | ||
249 | * USE_SCC_A: Use the SCC port B (Modem2) for serial debug. | ||
250 | * USE_MFP: Use the ST-MFP port (Modem1) for serial debug. | ||
251 | * | ||
252 | * Macintosh constants: | ||
253 | * MAC_SERIAL_DEBUG: Turns on serial debug output for the Macintosh. | ||
254 | * MAC_USE_SCC_A: Use the SCC port A (modem) for serial debug. | ||
255 | * MAC_USE_SCC_B: Use the SCC port B (printer) for serial debug (default). | ||
256 | */ | ||
257 | |||
258 | #include <linux/config.h> | ||
259 | #include <linux/linkage.h> | ||
260 | #include <linux/init.h> | ||
261 | #include <asm/bootinfo.h> | ||
262 | #include <asm/setup.h> | ||
263 | #include <asm/entry.h> | ||
264 | #include <asm/pgtable.h> | ||
265 | #include <asm/page.h> | ||
266 | #include <asm/offsets.h> | ||
267 | |||
268 | #ifdef CONFIG_MAC | ||
269 | |||
270 | #include <asm/machw.h> | ||
271 | |||
272 | /* | ||
273 | * Macintosh console support | ||
274 | */ | ||
275 | |||
276 | #define CONSOLE | ||
277 | #define CONSOLE_PENGUIN | ||
278 | |||
279 | /* | ||
280 | * Macintosh serial debug support; outputs boot info to the printer | ||
281 | * and/or modem serial ports | ||
282 | */ | ||
283 | #undef MAC_SERIAL_DEBUG | ||
284 | |||
285 | /* | ||
286 | * Macintosh serial debug port selection; define one or both; | ||
287 | * requires MAC_SERIAL_DEBUG to be defined | ||
288 | */ | ||
289 | #define MAC_USE_SCC_A /* Macintosh modem serial port */ | ||
290 | #define MAC_USE_SCC_B /* Macintosh printer serial port */ | ||
291 | |||
292 | #endif /* CONFIG_MAC */ | ||
293 | |||
294 | #undef MMU_PRINT | ||
295 | #undef MMU_NOCACHE_KERNEL | ||
296 | #define SERIAL_DEBUG | ||
297 | #undef DEBUG | ||
298 | |||
299 | /* | ||
300 | * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8. | ||
301 | * The 8x8 font is harder to read but fits more on the screen. | ||
302 | */ | ||
303 | #define FONT_8x8 /* default */ | ||
304 | /* #define FONT_8x16 */ /* 2nd choice */ | ||
305 | /* #define FONT_6x11 */ /* 3rd choice */ | ||
306 | |||
307 | .globl kernel_pg_dir | ||
308 | .globl availmem | ||
309 | .globl m68k_pgtable_cachemode | ||
310 | .globl m68k_supervisor_cachemode | ||
311 | #ifdef CONFIG_MVME16x | ||
312 | .globl mvme_bdid | ||
313 | #endif | ||
314 | #ifdef CONFIG_Q40 | ||
315 | .globl q40_mem_cptr | ||
316 | #endif | ||
317 | |||
318 | CPUTYPE_040 = 1 /* indicates an 040 */ | ||
319 | CPUTYPE_060 = 2 /* indicates an 060 */ | ||
320 | CPUTYPE_0460 = 3 /* if either above are set, this is set */ | ||
321 | CPUTYPE_020 = 4 /* indicates an 020 */ | ||
322 | |||
323 | /* Translation control register */ | ||
324 | TC_ENABLE = 0x8000 | ||
325 | TC_PAGE8K = 0x4000 | ||
326 | TC_PAGE4K = 0x0000 | ||
327 | |||
328 | /* Transparent translation registers */ | ||
329 | TTR_ENABLE = 0x8000 /* enable transparent translation */ | ||
330 | TTR_ANYMODE = 0x4000 /* user and kernel mode access */ | ||
331 | TTR_KERNELMODE = 0x2000 /* only kernel mode access */ | ||
332 | TTR_USERMODE = 0x0000 /* only user mode access */ | ||
333 | TTR_CI = 0x0400 /* inhibit cache */ | ||
334 | TTR_RW = 0x0200 /* read/write mode */ | ||
335 | TTR_RWM = 0x0100 /* read/write mask */ | ||
336 | TTR_FCB2 = 0x0040 /* function code base bit 2 */ | ||
337 | TTR_FCB1 = 0x0020 /* function code base bit 1 */ | ||
338 | TTR_FCB0 = 0x0010 /* function code base bit 0 */ | ||
339 | TTR_FCM2 = 0x0004 /* function code mask bit 2 */ | ||
340 | TTR_FCM1 = 0x0002 /* function code mask bit 1 */ | ||
341 | TTR_FCM0 = 0x0001 /* function code mask bit 0 */ | ||
342 | |||
343 | /* Cache Control registers */ | ||
344 | CC6_ENABLE_D = 0x80000000 /* enable data cache (680[46]0) */ | ||
345 | CC6_FREEZE_D = 0x40000000 /* freeze data cache (68060) */ | ||
346 | CC6_ENABLE_SB = 0x20000000 /* enable store buffer (68060) */ | ||
347 | CC6_PUSH_DPI = 0x10000000 /* disable CPUSH invalidation (68060) */ | ||
348 | CC6_HALF_D = 0x08000000 /* half-cache mode for data cache (68060) */ | ||
349 | CC6_ENABLE_B = 0x00800000 /* enable branch cache (68060) */ | ||
350 | CC6_CLRA_B = 0x00400000 /* clear all entries in branch cache (68060) */ | ||
351 | CC6_CLRU_B = 0x00200000 /* clear user entries in branch cache (68060) */ | ||
352 | CC6_ENABLE_I = 0x00008000 /* enable instruction cache (680[46]0) */ | ||
353 | CC6_FREEZE_I = 0x00004000 /* freeze instruction cache (68060) */ | ||
354 | CC6_HALF_I = 0x00002000 /* half-cache mode for instruction cache (68060) */ | ||
355 | CC3_ALLOC_WRITE = 0x00002000 /* write allocate mode(68030) */ | ||
356 | CC3_ENABLE_DB = 0x00001000 /* enable data burst (68030) */ | ||
357 | CC3_CLR_D = 0x00000800 /* clear data cache (68030) */ | ||
358 | CC3_CLRE_D = 0x00000400 /* clear entry in data cache (68030) */ | ||
359 | CC3_FREEZE_D = 0x00000200 /* freeze data cache (68030) */ | ||
360 | CC3_ENABLE_D = 0x00000100 /* enable data cache (68030) */ | ||
361 | CC3_ENABLE_IB = 0x00000010 /* enable instruction burst (68030) */ | ||
362 | CC3_CLR_I = 0x00000008 /* clear instruction cache (68030) */ | ||
363 | CC3_CLRE_I = 0x00000004 /* clear entry in instruction cache (68030) */ | ||
364 | CC3_FREEZE_I = 0x00000002 /* freeze instruction cache (68030) */ | ||
365 | CC3_ENABLE_I = 0x00000001 /* enable instruction cache (68030) */ | ||
366 | |||
367 | /* Miscellaneous definitions */ | ||
368 | PAGESIZE = 4096 | ||
369 | PAGESHIFT = 12 | ||
370 | |||
371 | ROOT_TABLE_SIZE = 128 | ||
372 | PTR_TABLE_SIZE = 128 | ||
373 | PAGE_TABLE_SIZE = 64 | ||
374 | ROOT_INDEX_SHIFT = 25 | ||
375 | PTR_INDEX_SHIFT = 18 | ||
376 | PAGE_INDEX_SHIFT = 12 | ||
377 | |||
378 | #ifdef DEBUG | ||
379 | /* When debugging use readable names for labels */ | ||
380 | #ifdef __STDC__ | ||
381 | #define L(name) .head.S.##name | ||
382 | #else | ||
383 | #define L(name) .head.S./**/name | ||
384 | #endif | ||
385 | #else | ||
386 | #ifdef __STDC__ | ||
387 | #define L(name) .L##name | ||
388 | #else | ||
389 | #define L(name) .L/**/name | ||
390 | #endif | ||
391 | #endif | ||
392 | |||
393 | /* The __INITDATA stuff is a no-op when ftrace or kgdb are turned on */ | ||
394 | #ifndef __INITDATA | ||
395 | #define __INITDATA .data | ||
396 | #define __FINIT .previous | ||
397 | #endif | ||
398 | |||
399 | /* Several macros to make the writing of subroutines easier: | ||
400 | * - func_start marks the beginning of the routine which setups the frame | ||
401 | * register and saves the registers, it also defines another macro | ||
402 | * to automatically restore the registers again. | ||
403 | * - func_return marks the end of the routine and simply calls the prepared | ||
404 | * macro to restore registers and jump back to the caller. | ||
405 | * - func_define generates another macro to automatically put arguments | ||
406 | * onto the stack call the subroutine and cleanup the stack again. | ||
407 | */ | ||
408 | |||
409 | /* Within subroutines these macros can be used to access the arguments | ||
410 | * on the stack. With STACK some allocated memory on the stack can be | ||
411 | * accessed and ARG0 points to the return address (used by mmu_engage). | ||
412 | */ | ||
413 | #define STACK %a6@(stackstart) | ||
414 | #define ARG0 %a6@(4) | ||
415 | #define ARG1 %a6@(8) | ||
416 | #define ARG2 %a6@(12) | ||
417 | #define ARG3 %a6@(16) | ||
418 | #define ARG4 %a6@(20) | ||
419 | |||
420 | .macro func_start name,saveregs,stack=0 | ||
421 | L(\name): | ||
422 | linkw %a6,#-\stack | ||
423 | moveml \saveregs,%sp@- | ||
424 | .set stackstart,-\stack | ||
425 | |||
426 | .macro func_return_\name | ||
427 | moveml %sp@+,\saveregs | ||
428 | unlk %a6 | ||
429 | rts | ||
430 | .endm | ||
431 | .endm | ||
432 | |||
433 | .macro func_return name | ||
434 | func_return_\name | ||
435 | .endm | ||
436 | |||
437 | .macro func_call name | ||
438 | jbsr L(\name) | ||
439 | .endm | ||
440 | |||
441 | .macro move_stack nr,arg1,arg2,arg3,arg4 | ||
442 | .if \nr | ||
443 | move_stack "(\nr-1)",\arg2,\arg3,\arg4 | ||
444 | movel \arg1,%sp@- | ||
445 | .endif | ||
446 | .endm | ||
447 | |||
448 | .macro func_define name,nr=0 | ||
449 | .macro \name arg1,arg2,arg3,arg4 | ||
450 | move_stack \nr,\arg1,\arg2,\arg3,\arg4 | ||
451 | func_call \name | ||
452 | .if \nr | ||
453 | lea %sp@(\nr*4),%sp | ||
454 | .endif | ||
455 | .endm | ||
456 | .endm | ||
457 | |||
458 | func_define mmu_map,4 | ||
459 | func_define mmu_map_tt,4 | ||
460 | func_define mmu_fixup_page_mmu_cache,1 | ||
461 | func_define mmu_temp_map,2 | ||
462 | func_define mmu_engage | ||
463 | func_define mmu_get_root_table_entry,1 | ||
464 | func_define mmu_get_ptr_table_entry,2 | ||
465 | func_define mmu_get_page_table_entry,2 | ||
466 | func_define mmu_print | ||
467 | func_define get_new_page | ||
468 | #if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) | ||
469 | func_define set_leds | ||
470 | #endif | ||
471 | |||
472 | .macro mmu_map_eq arg1,arg2,arg3 | ||
473 | mmu_map \arg1,\arg1,\arg2,\arg3 | ||
474 | .endm | ||
475 | |||
476 | .macro get_bi_record record | ||
477 | pea \record | ||
478 | func_call get_bi_record | ||
479 | addql #4,%sp | ||
480 | .endm | ||
481 | |||
482 | func_define serial_putc,1 | ||
483 | func_define console_putc,1 | ||
484 | |||
485 | func_define console_init | ||
486 | func_define console_put_stats | ||
487 | func_define console_put_penguin | ||
488 | func_define console_plot_pixel,3 | ||
489 | func_define console_scroll | ||
490 | |||
491 | .macro putc ch | ||
492 | #if defined(CONSOLE) || defined(SERIAL_DEBUG) | ||
493 | pea \ch | ||
494 | #endif | ||
495 | #ifdef CONSOLE | ||
496 | func_call console_putc | ||
497 | #endif | ||
498 | #ifdef SERIAL_DEBUG | ||
499 | func_call serial_putc | ||
500 | #endif | ||
501 | #if defined(CONSOLE) || defined(SERIAL_DEBUG) | ||
502 | addql #4,%sp | ||
503 | #endif | ||
504 | .endm | ||
505 | |||
506 | .macro dputc ch | ||
507 | #ifdef DEBUG | ||
508 | putc \ch | ||
509 | #endif | ||
510 | .endm | ||
511 | |||
512 | func_define putn,1 | ||
513 | |||
514 | .macro dputn nr | ||
515 | #ifdef DEBUG | ||
516 | putn \nr | ||
517 | #endif | ||
518 | .endm | ||
519 | |||
520 | .macro puts string | ||
521 | #if defined(CONSOLE) || defined(SERIAL_DEBUG) | ||
522 | __INITDATA | ||
523 | .Lstr\@: | ||
524 | .string "\string" | ||
525 | __FINIT | ||
526 | pea %pc@(.Lstr\@) | ||
527 | func_call puts | ||
528 | addql #4,%sp | ||
529 | #endif | ||
530 | .endm | ||
531 | |||
532 | .macro dputs string | ||
533 | #ifdef DEBUG | ||
534 | puts "\string" | ||
535 | #endif | ||
536 | .endm | ||
537 | |||
538 | #define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab | ||
539 | #define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab | ||
540 | #define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab | ||
541 | #define is_not_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jne lab | ||
542 | #define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab | ||
543 | #define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab | ||
544 | #define is_mvme147(lab) cmpl &MACH_MVME147,%pc@(m68k_machtype); jeq lab | ||
545 | #define is_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jeq lab | ||
546 | #define is_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jeq lab | ||
547 | #define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab | ||
548 | #define is_not_apollo(lab) cmpl &MACH_APOLLO,%pc@(m68k_machtype); jne lab | ||
549 | #define is_not_q40(lab) cmpl &MACH_Q40,%pc@(m68k_machtype); jne lab | ||
550 | #define is_not_sun3x(lab) cmpl &MACH_SUN3X,%pc@(m68k_machtype); jne lab | ||
551 | |||
552 | #define hasnt_leds(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); \ | ||
553 | jeq 42f; \ | ||
554 | cmpl &MACH_APOLLO,%pc@(m68k_machtype); \ | ||
555 | jne lab ;\ | ||
556 | 42:\ | ||
557 | |||
558 | #define is_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab | ||
559 | #define is_not_040_or_060(lab) btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab | ||
560 | #define is_040(lab) btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab | ||
561 | #define is_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab | ||
562 | #define is_not_060(lab) btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab | ||
563 | #define is_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab | ||
564 | #define is_not_020(lab) btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab | ||
565 | |||
566 | /* On the HP300 we use the on-board LEDs for debug output before | ||
567 | the console is running. Writing a 1 bit turns the corresponding LED | ||
568 | _off_ - on the 340 bit 7 is towards the back panel of the machine. */ | ||
569 | .macro leds mask | ||
570 | #if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) | ||
571 | hasnt_leds(.Lled\@) | ||
572 | pea \mask | ||
573 | func_call set_leds | ||
574 | addql #4,%sp | ||
575 | .Lled\@: | ||
576 | #endif | ||
577 | .endm | ||
578 | |||
579 | .text | ||
580 | ENTRY(_stext) | ||
581 | /* | ||
582 | * Version numbers of the bootinfo interface | ||
583 | * The area from _stext to _start will later be used as kernel pointer table | ||
584 | */ | ||
585 | bras 1f /* Jump over bootinfo version numbers */ | ||
586 | |||
587 | .long BOOTINFOV_MAGIC | ||
588 | .long MACH_AMIGA, AMIGA_BOOTI_VERSION | ||
589 | .long MACH_ATARI, ATARI_BOOTI_VERSION | ||
590 | .long MACH_MVME147, MVME147_BOOTI_VERSION | ||
591 | .long MACH_MVME16x, MVME16x_BOOTI_VERSION | ||
592 | .long MACH_BVME6000, BVME6000_BOOTI_VERSION | ||
593 | .long MACH_MAC, MAC_BOOTI_VERSION | ||
594 | .long MACH_Q40, Q40_BOOTI_VERSION | ||
595 | .long MACH_HP300, HP300_BOOTI_VERSION | ||
596 | .long 0 | ||
597 | 1: jra __start | ||
598 | |||
599 | .equ kernel_pg_dir,_stext | ||
600 | |||
601 | .equ .,_stext+PAGESIZE | ||
602 | |||
603 | ENTRY(_start) | ||
604 | jra __start | ||
605 | __INIT | ||
606 | ENTRY(__start) | ||
607 | /* | ||
608 | * Setup initial stack pointer | ||
609 | */ | ||
610 | lea %pc@(_stext),%sp | ||
611 | |||
612 | /* | ||
613 | * Record the CPU and machine type. | ||
614 | */ | ||
615 | get_bi_record BI_MACHTYPE | ||
616 | lea %pc@(m68k_machtype),%a1 | ||
617 | movel %a0@,%a1@ | ||
618 | |||
619 | get_bi_record BI_FPUTYPE | ||
620 | lea %pc@(m68k_fputype),%a1 | ||
621 | movel %a0@,%a1@ | ||
622 | |||
623 | get_bi_record BI_MMUTYPE | ||
624 | lea %pc@(m68k_mmutype),%a1 | ||
625 | movel %a0@,%a1@ | ||
626 | |||
627 | get_bi_record BI_CPUTYPE | ||
628 | lea %pc@(m68k_cputype),%a1 | ||
629 | movel %a0@,%a1@ | ||
630 | |||
631 | leds 0x1 | ||
632 | |||
633 | #ifdef CONFIG_MAC | ||
634 | /* | ||
635 | * For Macintosh, we need to determine the display parameters early (at least | ||
636 | * while debugging it). | ||
637 | */ | ||
638 | |||
639 | is_not_mac(L(test_notmac)) | ||
640 | |||
641 | get_bi_record BI_MAC_VADDR | ||
642 | lea %pc@(L(mac_videobase)),%a1 | ||
643 | movel %a0@,%a1@ | ||
644 | |||
645 | get_bi_record BI_MAC_VDEPTH | ||
646 | lea %pc@(L(mac_videodepth)),%a1 | ||
647 | movel %a0@,%a1@ | ||
648 | |||
649 | get_bi_record BI_MAC_VDIM | ||
650 | lea %pc@(L(mac_dimensions)),%a1 | ||
651 | movel %a0@,%a1@ | ||
652 | |||
653 | get_bi_record BI_MAC_VROW | ||
654 | lea %pc@(L(mac_rowbytes)),%a1 | ||
655 | movel %a0@,%a1@ | ||
656 | |||
657 | #ifdef MAC_SERIAL_DEBUG | ||
658 | get_bi_record BI_MAC_SCCBASE | ||
659 | lea %pc@(L(mac_sccbase)),%a1 | ||
660 | movel %a0@,%a1@ | ||
661 | #endif /* MAC_SERIAL_DEBUG */ | ||
662 | |||
663 | #if 0 | ||
664 | /* | ||
665 | * Clear the screen | ||
666 | */ | ||
667 | lea %pc@(L(mac_videobase)),%a0 | ||
668 | movel %a0@,%a1 | ||
669 | lea %pc@(L(mac_dimensions)),%a0 | ||
670 | movel %a0@,%d1 | ||
671 | swap %d1 /* #rows is high bytes */ | ||
672 | andl #0xFFFF,%d1 /* rows */ | ||
673 | subl #10,%d1 | ||
674 | lea %pc@(L(mac_rowbytes)),%a0 | ||
675 | loopy2: | ||
676 | movel %a0@,%d0 | ||
677 | subql #1,%d0 | ||
678 | loopx2: | ||
679 | moveb #0x55, %a1@+ | ||
680 | dbra %d0,loopx2 | ||
681 | dbra %d1,loopy2 | ||
682 | #endif | ||
683 | |||
684 | L(test_notmac): | ||
685 | #endif /* CONFIG_MAC */ | ||
686 | |||
687 | |||
688 | /* | ||
689 | * There are ultimately two pieces of information we want for all kinds of | ||
690 | * processors CpuType and CacheBits. The CPUTYPE was passed in from booter | ||
691 | * and is converted here from a booter type definition to a separate bit | ||
692 | * number which allows for the standard is_0x0 macro tests. | ||
693 | */ | ||
694 | movel %pc@(m68k_cputype),%d0 | ||
695 | /* | ||
696 | * Assume it's an 030 | ||
697 | */ | ||
698 | clrl %d1 | ||
699 | |||
700 | /* | ||
701 | * Test the BootInfo cputype for 060 | ||
702 | */ | ||
703 | btst #CPUB_68060,%d0 | ||
704 | jeq 1f | ||
705 | bset #CPUTYPE_060,%d1 | ||
706 | bset #CPUTYPE_0460,%d1 | ||
707 | jra 3f | ||
708 | 1: | ||
709 | /* | ||
710 | * Test the BootInfo cputype for 040 | ||
711 | */ | ||
712 | btst #CPUB_68040,%d0 | ||
713 | jeq 2f | ||
714 | bset #CPUTYPE_040,%d1 | ||
715 | bset #CPUTYPE_0460,%d1 | ||
716 | jra 3f | ||
717 | 2: | ||
718 | /* | ||
719 | * Test the BootInfo cputype for 020 | ||
720 | */ | ||
721 | btst #CPUB_68020,%d0 | ||
722 | jeq 3f | ||
723 | bset #CPUTYPE_020,%d1 | ||
724 | jra 3f | ||
725 | 3: | ||
726 | /* | ||
727 | * Record the cpu type | ||
728 | */ | ||
729 | lea %pc@(L(cputype)),%a0 | ||
730 | movel %d1,%a0@ | ||
731 | |||
732 | /* | ||
733 | * NOTE: | ||
734 | * | ||
735 | * Now the macros are valid: | ||
736 | * is_040_or_060 | ||
737 | * is_not_040_or_060 | ||
738 | * is_040 | ||
739 | * is_060 | ||
740 | * is_not_060 | ||
741 | */ | ||
742 | |||
743 | /* | ||
744 | * Determine the cache mode for pages holding MMU tables | ||
745 | * and for supervisor mode, unused for '020 and '030 | ||
746 | */ | ||
747 | clrl %d0 | ||
748 | clrl %d1 | ||
749 | |||
750 | is_not_040_or_060(L(save_cachetype)) | ||
751 | |||
752 | /* | ||
753 | * '040 or '060 | ||
754 | * d1 := cacheable write-through | ||
755 | * NOTE: The 68040 manual strongly recommends non-cached for MMU tables, | ||
756 | * but we have been using write-through since at least 2.0.29 so I | ||
757 | * guess it is OK. | ||
758 | */ | ||
759 | #ifdef CONFIG_060_WRITETHROUGH | ||
760 | /* | ||
761 | * If this is a 68060 board using drivers with cache coherency | ||
762 | * problems, then supervisor memory accesses need to be write-through | ||
763 | * also; otherwise, we want copyback. | ||
764 | */ | ||
765 | |||
766 | is_not_060(1f) | ||
767 | movel #_PAGE_CACHE040W,%d0 | ||
768 | jra L(save_cachetype) | ||
769 | #endif /* CONFIG_060_WRITETHROUGH */ | ||
770 | 1: | ||
771 | movew #_PAGE_CACHE040,%d0 | ||
772 | |||
773 | movel #_PAGE_CACHE040W,%d1 | ||
774 | |||
775 | L(save_cachetype): | ||
776 | /* Save cache mode for supervisor mode and page tables | ||
777 | */ | ||
778 | lea %pc@(m68k_supervisor_cachemode),%a0 | ||
779 | movel %d0,%a0@ | ||
780 | lea %pc@(m68k_pgtable_cachemode),%a0 | ||
781 | movel %d1,%a0@ | ||
782 | |||
783 | /* | ||
784 | * raise interrupt level | ||
785 | */ | ||
786 | movew #0x2700,%sr | ||
787 | |||
788 | /* | ||
789 | If running on an Atari, determine the I/O base of the | ||
790 | serial port and test if we are running on a Medusa or Hades. | ||
791 | This test is necessary here, because on the Hades the serial | ||
792 | port is only accessible in the high I/O memory area. | ||
793 | |||
794 | The test whether it is a Medusa is done by writing to the byte at | ||
795 | phys. 0x0. This should result in a bus error on all other machines. | ||
796 | |||
797 | ...should, but doesn't. The Afterburner040 for the Falcon has the | ||
798 | same behaviour (0x0..0x7 are no ROM shadow). So we have to do | ||
799 | another test to distinguish Medusa and AB040. This is a | ||
800 | read attempt for 0x00ff82fe phys. that should bus error on a Falcon | ||
801 | (+AB040), but is in the range where the Medusa always asserts DTACK. | ||
802 | |||
803 | The test for the Hades is done by reading address 0xb0000000. This | ||
804 | should give a bus error on the Medusa. | ||
805 | */ | ||
806 | |||
807 | #ifdef CONFIG_ATARI | ||
808 | is_not_atari(L(notypetest)) | ||
809 | |||
810 | /* get special machine type (Medusa/Hades/AB40) */ | ||
811 | moveq #0,%d3 /* default if tag doesn't exist */ | ||
812 | get_bi_record BI_ATARI_MCH_TYPE | ||
813 | tstl %d0 | ||
814 | jbmi 1f | ||
815 | movel %a0@,%d3 | ||
816 | lea %pc@(atari_mch_type),%a0 | ||
817 | movel %d3,%a0@ | ||
818 | 1: | ||
819 | /* On the Hades, the iobase must be set up before opening the | ||
820 | * serial port. There are no I/O regs at 0x00ffxxxx at all. */ | ||
821 | moveq #0,%d0 | ||
822 | cmpl #ATARI_MACH_HADES,%d3 | ||
823 | jbne 1f | ||
824 | movel #0xff000000,%d0 /* Hades I/O base addr: 0xff000000 */ | ||
825 | 1: lea %pc@(L(iobase)),%a0 | ||
826 | movel %d0,%a0@ | ||
827 | |||
828 | L(notypetest): | ||
829 | #endif | ||
830 | |||
831 | #ifdef CONFIG_VME | ||
832 | is_mvme147(L(getvmetype)) | ||
833 | is_bvme6000(L(getvmetype)) | ||
834 | is_not_mvme16x(L(gvtdone)) | ||
835 | |||
836 | /* See if the loader has specified the BI_VME_TYPE tag. Recent | ||
837 | * versions of VMELILO and TFTPLILO do this. We have to do this | ||
838 | * early so we know how to handle console output. If the tag | ||
839 | * doesn't exist then we use the Bug for output on MVME16x. | ||
840 | */ | ||
841 | L(getvmetype): | ||
842 | get_bi_record BI_VME_TYPE | ||
843 | tstl %d0 | ||
844 | jbmi 1f | ||
845 | movel %a0@,%d3 | ||
846 | lea %pc@(vme_brdtype),%a0 | ||
847 | movel %d3,%a0@ | ||
848 | 1: | ||
849 | #ifdef CONFIG_MVME16x | ||
850 | is_not_mvme16x(L(gvtdone)) | ||
851 | |||
852 | /* Need to get the BRD_ID info to differentiate between 162, 167, | ||
853 | * etc. This is available as a BI_VME_BRDINFO tag with later | ||
854 | * versions of VMELILO and TFTPLILO, otherwise we call the Bug. | ||
855 | */ | ||
856 | get_bi_record BI_VME_BRDINFO | ||
857 | tstl %d0 | ||
858 | jpl 1f | ||
859 | |||
860 | /* Get pointer to board ID data from Bug */ | ||
861 | movel %d2,%sp@- | ||
862 | trap #15 | ||
863 | .word 0x70 /* trap 0x70 - .BRD_ID */ | ||
864 | movel %sp@+,%a0 | ||
865 | 1: | ||
866 | lea %pc@(mvme_bdid),%a1 | ||
867 | /* Structure is 32 bytes long */ | ||
868 | movel %a0@+,%a1@+ | ||
869 | movel %a0@+,%a1@+ | ||
870 | movel %a0@+,%a1@+ | ||
871 | movel %a0@+,%a1@+ | ||
872 | movel %a0@+,%a1@+ | ||
873 | movel %a0@+,%a1@+ | ||
874 | movel %a0@+,%a1@+ | ||
875 | movel %a0@+,%a1@+ | ||
876 | #endif | ||
877 | |||
878 | L(gvtdone): | ||
879 | |||
880 | #endif | ||
881 | |||
882 | #ifdef CONFIG_HP300 | ||
883 | is_not_hp300(L(nothp)) | ||
884 | |||
885 | /* Get the address of the UART for serial debugging */ | ||
886 | get_bi_record BI_HP300_UART_ADDR | ||
887 | tstl %d0 | ||
888 | jbmi 1f | ||
889 | movel %a0@,%d3 | ||
890 | lea %pc@(L(uartbase)),%a0 | ||
891 | movel %d3,%a0@ | ||
892 | get_bi_record BI_HP300_UART_SCODE | ||
893 | tstl %d0 | ||
894 | jbmi 1f | ||
895 | movel %a0@,%d3 | ||
896 | lea %pc@(L(uart_scode)),%a0 | ||
897 | movel %d3,%a0@ | ||
898 | 1: | ||
899 | L(nothp): | ||
900 | #endif | ||
901 | |||
902 | /* | ||
903 | * Initialize serial port | ||
904 | */ | ||
905 | jbsr L(serial_init) | ||
906 | |||
907 | /* | ||
908 | * Initialize console | ||
909 | */ | ||
910 | #ifdef CONFIG_MAC | ||
911 | is_not_mac(L(nocon)) | ||
912 | #ifdef CONSOLE | ||
913 | console_init | ||
914 | #ifdef CONSOLE_PENGUIN | ||
915 | console_put_penguin | ||
916 | #endif /* CONSOLE_PENGUIN */ | ||
917 | console_put_stats | ||
918 | #endif /* CONSOLE */ | ||
919 | L(nocon): | ||
920 | #endif /* CONFIG_MAC */ | ||
921 | |||
922 | |||
923 | putc '\n' | ||
924 | putc 'A' | ||
925 | leds 0x2 | ||
926 | dputn %pc@(L(cputype)) | ||
927 | dputn %pc@(m68k_supervisor_cachemode) | ||
928 | dputn %pc@(m68k_pgtable_cachemode) | ||
929 | dputc '\n' | ||
930 | |||
931 | /* | ||
932 | * Save physical start address of kernel | ||
933 | */ | ||
934 | lea %pc@(L(phys_kernel_start)),%a0 | ||
935 | lea %pc@(_stext),%a1 | ||
936 | subl #_stext,%a1 | ||
937 | addl #PAGE_OFFSET,%a1 | ||
938 | movel %a1,%a0@ | ||
939 | |||
940 | putc 'B' | ||
941 | |||
942 | leds 0x4 | ||
943 | |||
944 | /* | ||
945 | * mmu_init | ||
946 | * | ||
947 | * This block of code does what's necessary to map in the various kinds | ||
948 | * of machines for execution of Linux. | ||
949 | * First map the first 4 MB of kernel code & data | ||
950 | */ | ||
951 | |||
952 | mmu_map #PAGE_OFFSET,%pc@(L(phys_kernel_start)),#4*1024*1024,\ | ||
953 | %pc@(m68k_supervisor_cachemode) | ||
954 | |||
955 | putc 'C' | ||
956 | |||
957 | #ifdef CONFIG_AMIGA | ||
958 | |||
959 | L(mmu_init_amiga): | ||
960 | |||
961 | is_not_amiga(L(mmu_init_not_amiga)) | ||
962 | /* | ||
963 | * mmu_init_amiga | ||
964 | */ | ||
965 | |||
966 | putc 'D' | ||
967 | |||
968 | is_not_040_or_060(1f) | ||
969 | |||
970 | /* | ||
971 | * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000 | ||
972 | */ | ||
973 | mmu_map #0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S | ||
974 | /* | ||
975 | * Map the Zorro III I/O space with transparent translation | ||
976 | * for frame buffer memory etc. | ||
977 | */ | ||
978 | mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE_S | ||
979 | |||
980 | jbra L(mmu_init_done) | ||
981 | |||
982 | 1: | ||
983 | /* | ||
984 | * 030: Map the 32Meg range physical 0x0 upto logical 0x8000.0000 | ||
985 | */ | ||
986 | mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 | ||
987 | mmu_map_tt #1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030 | ||
988 | |||
989 | jbra L(mmu_init_done) | ||
990 | |||
991 | L(mmu_init_not_amiga): | ||
992 | #endif | ||
993 | |||
994 | #ifdef CONFIG_ATARI | ||
995 | |||
996 | L(mmu_init_atari): | ||
997 | |||
998 | is_not_atari(L(mmu_init_not_atari)) | ||
999 | |||
1000 | putc 'E' | ||
1001 | |||
1002 | /* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping | ||
1003 | the last 16 MB of virtual address space to the first 16 MB (i.e. | ||
1004 | 0xffxxxxxx -> 0x00xxxxxx). For this, an additional pointer table is | ||
1005 | needed. I/O ranges are marked non-cachable. | ||
1006 | |||
1007 | For the Medusa it is better to map the I/O region transparently | ||
1008 | (i.e. 0xffxxxxxx -> 0xffxxxxxx), because some I/O registers are | ||
1009 | accessible only in the high area. | ||
1010 | |||
1011 | On the Hades all I/O registers are only accessible in the high | ||
1012 | area. | ||
1013 | */ | ||
1014 | |||
1015 | /* I/O base addr for non-Medusa, non-Hades: 0x00000000 */ | ||
1016 | moveq #0,%d0 | ||
1017 | movel %pc@(atari_mch_type),%d3 | ||
1018 | cmpl #ATARI_MACH_MEDUSA,%d3 | ||
1019 | jbeq 2f | ||
1020 | cmpl #ATARI_MACH_HADES,%d3 | ||
1021 | jbne 1f | ||
1022 | 2: movel #0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */ | ||
1023 | 1: movel %d0,%d3 | ||
1024 | |||
1025 | is_040_or_060(L(spata68040)) | ||
1026 | |||
1027 | /* Map everything non-cacheable, though not all parts really | ||
1028 | * need to disable caches (crucial only for 0xff8000..0xffffff | ||
1029 | * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder | ||
1030 | * isn't really used, except for sometimes peeking into the | ||
1031 | * ROMs (mirror at phys. 0x0), so caching isn't necessary for | ||
1032 | * this. */ | ||
1033 | mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030 | ||
1034 | |||
1035 | jbra L(mmu_init_done) | ||
1036 | |||
1037 | L(spata68040): | ||
1038 | |||
1039 | mmu_map #0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S | ||
1040 | |||
1041 | jbra L(mmu_init_done) | ||
1042 | |||
1043 | L(mmu_init_not_atari): | ||
1044 | #endif | ||
1045 | |||
1046 | #ifdef CONFIG_Q40 | ||
1047 | is_not_q40(L(notq40)) | ||
1048 | /* | ||
1049 | * add transparent mapping for 0xff00 0000 - 0xffff ffff | ||
1050 | * non-cached serialized etc.. | ||
1051 | * this includes master chip, DAC, RTC and ISA ports | ||
1052 | * 0xfe000000-0xfeffffff is for screen and ROM | ||
1053 | */ | ||
1054 | |||
1055 | putc 'Q' | ||
1056 | |||
1057 | mmu_map_tt #0,#0xfe000000,#0x01000000,#_PAGE_CACHE040W | ||
1058 | mmu_map_tt #1,#0xff000000,#0x01000000,#_PAGE_NOCACHE_S | ||
1059 | |||
1060 | jbra L(mmu_init_done) | ||
1061 | |||
1062 | L(notq40): | ||
1063 | #endif | ||
1064 | |||
1065 | #ifdef CONFIG_HP300 | ||
1066 | is_not_hp300(L(nothp300)) | ||
1067 | |||
1068 | /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx) | ||
1069 | * by mapping 32MB (on 020/030) or 16 MB (on 040) from 0xf0xxxxxx -> 0x00xxxxxx). | ||
1070 | * The ROM mapping is needed because the LEDs are mapped there too. | ||
1071 | */ | ||
1072 | |||
1073 | is_040(1f) | ||
1074 | |||
1075 | /* | ||
1076 | * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000 | ||
1077 | */ | ||
1078 | mmu_map #0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030 | ||
1079 | |||
1080 | jbra L(mmu_init_done) | ||
1081 | |||
1082 | 1: | ||
1083 | /* | ||
1084 | * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000 | ||
1085 | */ | ||
1086 | mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S | ||
1087 | |||
1088 | jbra L(mmu_init_done) | ||
1089 | |||
1090 | L(nothp300): | ||
1091 | #endif /* CONFIG_HP300 */ | ||
1092 | |||
1093 | #ifdef CONFIG_MVME147 | ||
1094 | |||
1095 | is_not_mvme147(L(not147)) | ||
1096 | |||
1097 | /* | ||
1098 | * On MVME147 we have already created kernel page tables for | ||
1099 | * 4MB of RAM at address 0, so now need to do a transparent | ||
1100 | * mapping of the top of memory space. Make it 0.5GByte for now, | ||
1101 | * so we can access on-board i/o areas. | ||
1102 | */ | ||
1103 | |||
1104 | mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE030 | ||
1105 | |||
1106 | jbra L(mmu_init_done) | ||
1107 | |||
1108 | L(not147): | ||
1109 | #endif /* CONFIG_MVME147 */ | ||
1110 | |||
1111 | #ifdef CONFIG_MVME16x | ||
1112 | |||
1113 | is_not_mvme16x(L(not16x)) | ||
1114 | |||
1115 | /* | ||
1116 | * On MVME16x we have already created kernel page tables for | ||
1117 | * 4MB of RAM at address 0, so now need to do a transparent | ||
1118 | * mapping of the top of memory space. Make it 0.5GByte for now. | ||
1119 | * Supervisor only access, so transparent mapping doesn't | ||
1120 | * clash with User code virtual address space. | ||
1121 | * this covers IO devices, PROM and SRAM. The PROM and SRAM | ||
1122 | * mapping is needed to allow 167Bug to run. | ||
1123 | * IO is in the range 0xfff00000 to 0xfffeffff. | ||
1124 | * PROM is 0xff800000->0xffbfffff and SRAM is | ||
1125 | * 0xffe00000->0xffe1ffff. | ||
1126 | */ | ||
1127 | |||
1128 | mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S | ||
1129 | |||
1130 | jbra L(mmu_init_done) | ||
1131 | |||
1132 | L(not16x): | ||
1133 | #endif /* CONFIG_MVME162 | CONFIG_MVME167 */ | ||
1134 | |||
1135 | #ifdef CONFIG_BVME6000 | ||
1136 | |||
1137 | is_not_bvme6000(L(not6000)) | ||
1138 | |||
1139 | /* | ||
1140 | * On BVME6000 we have already created kernel page tables for | ||
1141 | * 4MB of RAM at address 0, so now need to do a transparent | ||
1142 | * mapping of the top of memory space. Make it 0.5GByte for now, | ||
1143 | * so we can access on-board i/o areas. | ||
1144 | * Supervisor only access, so transparent mapping doesn't | ||
1145 | * clash with User code virtual address space. | ||
1146 | */ | ||
1147 | |||
1148 | mmu_map_tt #1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S | ||
1149 | |||
1150 | jbra L(mmu_init_done) | ||
1151 | |||
1152 | L(not6000): | ||
1153 | #endif /* CONFIG_BVME6000 */ | ||
1154 | |||
1155 | /* | ||
1156 | * mmu_init_mac | ||
1157 | * | ||
1158 | * The Macintosh mappings are less clear. | ||
1159 | * | ||
1160 | * Even as of this writing, it is unclear how the | ||
1161 | * Macintosh mappings will be done. However, as | ||
1162 | * the first author of this code I'm proposing the | ||
1163 | * following model: | ||
1164 | * | ||
1165 | * Map the kernel (that's already done), | ||
1166 | * Map the I/O (on most machines that's the | ||
1167 | * 0x5000.0000 ... 0x5300.0000 range, | ||
1168 | * Map the video frame buffer using as few pages | ||
1169 | * as absolutely (this requirement mostly stems from | ||
1170 | * the fact that when the frame buffer is at | ||
1171 | * 0x0000.0000 then we know there is valid RAM just | ||
1172 | * above the screen that we don't want to waste!). | ||
1173 | * | ||
1174 | * By the way, if the frame buffer is at 0x0000.0000 | ||
1175 | * then the Macintosh is known as an RBV based Mac. | ||
1176 | * | ||
1177 | * By the way 2, the code currently maps in a bunch of | ||
1178 | * regions. But I'd like to cut that out. (And move most | ||
1179 | * of the mappings up into the kernel proper ... or only | ||
1180 | * map what's necessary.) | ||
1181 | */ | ||
1182 | |||
1183 | #ifdef CONFIG_MAC | ||
1184 | |||
1185 | L(mmu_init_mac): | ||
1186 | |||
1187 | is_not_mac(L(mmu_init_not_mac)) | ||
1188 | |||
1189 | putc 'F' | ||
1190 | |||
1191 | is_not_040_or_060(1f) | ||
1192 | |||
1193 | moveq #_PAGE_NOCACHE_S,%d3 | ||
1194 | jbra 2f | ||
1195 | 1: | ||
1196 | moveq #_PAGE_NOCACHE030,%d3 | ||
1197 | 2: | ||
1198 | /* | ||
1199 | * Mac Note: screen address of logical 0xF000.0000 -> <screen physical> | ||
1200 | * we simply map the 4MB that contains the videomem | ||
1201 | */ | ||
1202 | |||
1203 | movel #VIDEOMEMMASK,%d0 | ||
1204 | andl %pc@(L(mac_videobase)),%d0 | ||
1205 | |||
1206 | mmu_map #VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3 | ||
1207 | /* ROM from 4000 0000 to 4200 0000 (only for mac_reset()) */ | ||
1208 | mmu_map_eq #0x40000000,#0x02000000,%d3 | ||
1209 | /* IO devices (incl. serial port) from 5000 0000 to 5300 0000 */ | ||
1210 | mmu_map_eq #0x50000000,#0x03000000,%d3 | ||
1211 | /* Nubus slot space (video at 0xF0000000, rom at 0xF0F80000) */ | ||
1212 | mmu_map_tt #1,#0xf8000000,#0x08000000,%d3 | ||
1213 | |||
1214 | jbra L(mmu_init_done) | ||
1215 | |||
1216 | L(mmu_init_not_mac): | ||
1217 | #endif | ||
1218 | |||
1219 | #ifdef CONFIG_SUN3X | ||
1220 | is_not_sun3x(L(notsun3x)) | ||
1221 | |||
1222 | /* oh, the pain.. We're gonna want the prom code after | ||
1223 | * starting the MMU, so we copy the mappings, translating | ||
1224 | * from 8k -> 4k pages as we go. | ||
1225 | */ | ||
1226 | |||
1227 | /* copy maps from 0xfee00000 to 0xff000000 */ | ||
1228 | movel #0xfee00000, %d0 | ||
1229 | moveq #ROOT_INDEX_SHIFT, %d1 | ||
1230 | lsrl %d1,%d0 | ||
1231 | mmu_get_root_table_entry %d0 | ||
1232 | |||
1233 | movel #0xfee00000, %d0 | ||
1234 | moveq #PTR_INDEX_SHIFT, %d1 | ||
1235 | lsrl %d1,%d0 | ||
1236 | andl #PTR_TABLE_SIZE-1, %d0 | ||
1237 | mmu_get_ptr_table_entry %a0,%d0 | ||
1238 | |||
1239 | movel #0xfee00000, %d0 | ||
1240 | moveq #PAGE_INDEX_SHIFT, %d1 | ||
1241 | lsrl %d1,%d0 | ||
1242 | andl #PAGE_TABLE_SIZE-1, %d0 | ||
1243 | mmu_get_page_table_entry %a0,%d0 | ||
1244 | |||
1245 | /* this is where the prom page table lives */ | ||
1246 | movel 0xfefe00d4, %a1 | ||
1247 | movel %a1@, %a1 | ||
1248 | |||
1249 | movel #((0x200000 >> 13)-1), %d1 | ||
1250 | |||
1251 | 1: | ||
1252 | movel %a1@+, %d3 | ||
1253 | movel %d3,%a0@+ | ||
1254 | addl #0x1000,%d3 | ||
1255 | movel %d3,%a0@+ | ||
1256 | |||
1257 | dbra %d1,1b | ||
1258 | |||
1259 | /* setup tt1 for I/O */ | ||
1260 | mmu_map_tt #1,#0x40000000,#0x40000000,#_PAGE_NOCACHE_S | ||
1261 | jbra L(mmu_init_done) | ||
1262 | |||
1263 | L(notsun3x): | ||
1264 | #endif | ||
1265 | |||
1266 | #ifdef CONFIG_APOLLO | ||
1267 | is_not_apollo(L(notapollo)) | ||
1268 | |||
1269 | putc 'P' | ||
1270 | mmu_map #0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030 | ||
1271 | |||
1272 | L(notapollo): | ||
1273 | jbra L(mmu_init_done) | ||
1274 | #endif | ||
1275 | |||
1276 | L(mmu_init_done): | ||
1277 | |||
1278 | putc 'G' | ||
1279 | leds 0x8 | ||
1280 | |||
1281 | /* | ||
1282 | * mmu_fixup | ||
1283 | * | ||
1284 | * On the 040 class machines, all pages that are used for the | ||
1285 | * mmu have to be fixed up. According to Motorola, pages holding mmu | ||
1286 | * tables should be non-cacheable on a '040 and write-through on a | ||
1287 | * '060. But analysis of the reasons for this, and practical | ||
1288 | * experience, showed that write-through also works on a '040. | ||
1289 | * | ||
1290 | * Allocated memory so far goes from kernel_end to memory_start that | ||
1291 | * is used for all kind of tables, for that the cache attributes | ||
1292 | * are now fixed. | ||
1293 | */ | ||
1294 | L(mmu_fixup): | ||
1295 | |||
1296 | is_not_040_or_060(L(mmu_fixup_done)) | ||
1297 | |||
1298 | #ifdef MMU_NOCACHE_KERNEL | ||
1299 | jbra L(mmu_fixup_done) | ||
1300 | #endif | ||
1301 | |||
1302 | /* first fix the page at the start of the kernel, that | ||
1303 | * contains also kernel_pg_dir. | ||
1304 | */ | ||
1305 | movel %pc@(L(phys_kernel_start)),%d0 | ||
1306 | subl #PAGE_OFFSET,%d0 | ||
1307 | lea %pc@(_stext),%a0 | ||
1308 | subl %d0,%a0 | ||
1309 | mmu_fixup_page_mmu_cache %a0 | ||
1310 | |||
1311 | movel %pc@(L(kernel_end)),%a0 | ||
1312 | subl %d0,%a0 | ||
1313 | movel %pc@(L(memory_start)),%a1 | ||
1314 | subl %d0,%a1 | ||
1315 | bra 2f | ||
1316 | 1: | ||
1317 | mmu_fixup_page_mmu_cache %a0 | ||
1318 | addw #PAGESIZE,%a0 | ||
1319 | 2: | ||
1320 | cmpl %a0,%a1 | ||
1321 | jgt 1b | ||
1322 | |||
1323 | L(mmu_fixup_done): | ||
1324 | |||
1325 | #ifdef MMU_PRINT | ||
1326 | mmu_print | ||
1327 | #endif | ||
1328 | |||
1329 | /* | ||
1330 | * mmu_engage | ||
1331 | * | ||
1332 | * This chunk of code performs the gruesome task of engaging the MMU. | ||
1333 | * The reason its gruesome is because when the MMU becomes engaged it | ||
1334 | * maps logical addresses to physical addresses. The Program Counter | ||
1335 | * register is then passed through the MMU before the next instruction | ||
1336 | * is fetched (the instruction following the engage MMU instruction). | ||
1337 | * This may mean one of two things: | ||
1338 | * 1. The Program Counter falls within the logical address space of | ||
1339 | * the kernel of which there are two sub-possibilities: | ||
1340 | * A. The PC maps to the correct instruction (logical PC == physical | ||
1341 | * code location), or | ||
1342 | * B. The PC does not map through and the processor will read some | ||
1343 | * data (or instruction) which is not the logically next instr. | ||
1344 | * As you can imagine, A is good and B is bad. | ||
1345 | * Alternatively, | ||
1346 | * 2. The Program Counter does not map through the MMU. The processor | ||
1347 | * will take a Bus Error. | ||
1348 | * Clearly, 2 is bad. | ||
1349 | * It doesn't take a wiz kid to figure you want 1.A. | ||
1350 | * This code creates that possibility. | ||
1351 | * There are two possible 1.A. states (we now ignore the other above states): | ||
1352 | * A. The kernel is located at physical memory addressed the same as | ||
1353 | * the logical memory for the kernel, i.e., 0x01000. | ||
1354 | * B. The kernel is located some where else. e.g., 0x0400.0000 | ||
1355 | * | ||
1356 | * Under some conditions the Macintosh can look like A or B. | ||
1357 | * [A friend and I once noted that Apple hardware engineers should be | ||
1358 | * wacked twice each day: once when they show up at work (as in, Whack!, | ||
1359 | * "This is for the screwy hardware we know you're going to design today."), | ||
1360 | * and also at the end of the day (as in, Whack! "I don't know what | ||
1361 | * you designed today, but I'm sure it wasn't good."). -- rst] | ||
1362 | * | ||
1363 | * This code works on the following premise: | ||
1364 | * If the kernel start (%d5) is within the first 16 Meg of RAM, | ||
1365 | * then create a mapping for the kernel at logical 0x8000.0000 to | ||
1366 | * the physical location of the pc. And, create a transparent | ||
1367 | * translation register for the first 16 Meg. Then, after the MMU | ||
1368 | * is engaged, the PC can be moved up into the 0x8000.0000 range | ||
1369 | * and then the transparent translation can be turned off and then | ||
1370 | * the PC can jump to the correct logical location and it will be | ||
1371 | * home (finally). This is essentially the code that the Amiga used | ||
1372 | * to use. Now, it's generalized for all processors. Which means | ||
1373 | * that a fresh (but temporary) mapping has to be created. The mapping | ||
1374 | * is made in page 0 (an as of yet unused location -- except for the | ||
1375 | * stack!). This temporary mapping will only require 1 pointer table | ||
1376 | * and a single page table (it can map 256K). | ||
1377 | * | ||
1378 | * OK, alternatively, imagine that the Program Counter is not within | ||
1379 | * the first 16 Meg. Then, just use Transparent Translation registers | ||
1380 | * to do the right thing. | ||
1381 | * | ||
1382 | * Last, if _start is already at 0x01000, then there's nothing special | ||
1383 | * to do (in other words, in a degenerate case of the first case above, | ||
1384 | * do nothing). | ||
1385 | * | ||
1386 | * Let's do it. | ||
1387 | * | ||
1388 | * | ||
1389 | */ | ||
1390 | |||
1391 | putc 'H' | ||
1392 | |||
1393 | mmu_engage | ||
1394 | |||
1395 | /* | ||
1396 | * After this point no new memory is allocated and | ||
1397 | * the start of available memory is stored in availmem. | ||
1398 | * (The bootmem allocator requires now the physicall address.) | ||
1399 | */ | ||
1400 | |||
1401 | movel L(memory_start),availmem | ||
1402 | |||
1403 | #ifdef CONFIG_AMIGA | ||
1404 | is_not_amiga(1f) | ||
1405 | /* fixup the Amiga custom register location before printing */ | ||
1406 | clrl L(custom) | ||
1407 | 1: | ||
1408 | #endif | ||
1409 | |||
1410 | #ifdef CONFIG_ATARI | ||
1411 | is_not_atari(1f) | ||
1412 | /* fixup the Atari iobase register location before printing */ | ||
1413 | movel #0xff000000,L(iobase) | ||
1414 | 1: | ||
1415 | #endif | ||
1416 | |||
1417 | #ifdef CONFIG_MAC | ||
1418 | is_not_mac(1f) | ||
1419 | movel #~VIDEOMEMMASK,%d0 | ||
1420 | andl L(mac_videobase),%d0 | ||
1421 | addl #VIDEOMEMBASE,%d0 | ||
1422 | movel %d0,L(mac_videobase) | ||
1423 | #if defined(CONSOLE) | ||
1424 | movel %pc@(L(phys_kernel_start)),%d0 | ||
1425 | subl #PAGE_OFFSET,%d0 | ||
1426 | subl %d0,L(console_font) | ||
1427 | subl %d0,L(console_font_data) | ||
1428 | #endif | ||
1429 | #ifdef MAC_SERIAL_DEBUG | ||
1430 | orl #0x50000000,L(mac_sccbase) | ||
1431 | #endif | ||
1432 | 1: | ||
1433 | #endif | ||
1434 | |||
1435 | #ifdef CONFIG_HP300 | ||
1436 | is_not_hp300(1f) | ||
1437 | /* | ||
1438 | * Fix up the iobase register to point to the new location of the LEDs. | ||
1439 | */ | ||
1440 | movel #0xf0000000,L(iobase) | ||
1441 | |||
1442 | /* | ||
1443 | * Energise the FPU and caches. | ||
1444 | */ | ||
1445 | is_040(1f) | ||
1446 | movel #0x60,0xf05f400c | ||
1447 | jbra 2f | ||
1448 | |||
1449 | /* | ||
1450 | * 040: slightly different, apparently. | ||
1451 | */ | ||
1452 | 1: movew #0,0xf05f400e | ||
1453 | movew #0x64,0xf05f400e | ||
1454 | 2: | ||
1455 | #endif | ||
1456 | |||
1457 | #ifdef CONFIG_SUN3X | ||
1458 | is_not_sun3x(1f) | ||
1459 | |||
1460 | /* enable copro */ | ||
1461 | oriw #0x4000,0x61000000 | ||
1462 | 1: | ||
1463 | #endif | ||
1464 | |||
1465 | #ifdef CONFIG_APOLLO | ||
1466 | is_not_apollo(1f) | ||
1467 | |||
1468 | /* | ||
1469 | * Fix up the iobase before printing | ||
1470 | */ | ||
1471 | movel #0x80000000,L(iobase) | ||
1472 | 1: | ||
1473 | #endif | ||
1474 | |||
1475 | putc 'I' | ||
1476 | leds 0x10 | ||
1477 | |||
1478 | /* | ||
1479 | * Enable caches | ||
1480 | */ | ||
1481 | |||
1482 | is_not_040_or_060(L(cache_not_680460)) | ||
1483 | |||
1484 | L(cache680460): | ||
1485 | .chip 68040 | ||
1486 | nop | ||
1487 | cpusha %bc | ||
1488 | nop | ||
1489 | |||
1490 | is_060(L(cache68060)) | ||
1491 | |||
1492 | movel #CC6_ENABLE_D+CC6_ENABLE_I,%d0 | ||
1493 | /* MMU stuff works in copyback mode now, so enable the cache */ | ||
1494 | movec %d0,%cacr | ||
1495 | jra L(cache_done) | ||
1496 | |||
1497 | L(cache68060): | ||
1498 | movel #CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0 | ||
1499 | /* MMU stuff works in copyback mode now, so enable the cache */ | ||
1500 | movec %d0,%cacr | ||
1501 | /* enable superscalar dispatch in PCR */ | ||
1502 | moveq #1,%d0 | ||
1503 | .chip 68060 | ||
1504 | movec %d0,%pcr | ||
1505 | |||
1506 | jbra L(cache_done) | ||
1507 | L(cache_not_680460): | ||
1508 | L(cache68030): | ||
1509 | .chip 68030 | ||
1510 | movel #CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0 | ||
1511 | movec %d0,%cacr | ||
1512 | |||
1513 | jra L(cache_done) | ||
1514 | .chip 68k | ||
1515 | L(cache_done): | ||
1516 | |||
1517 | putc 'J' | ||
1518 | |||
1519 | /* | ||
1520 | * Setup initial stack pointer | ||
1521 | */ | ||
1522 | lea init_task,%curptr | ||
1523 | lea init_thread_union+THREAD_SIZE,%sp | ||
1524 | |||
1525 | putc 'K' | ||
1526 | |||
1527 | subl %a6,%a6 /* clear a6 for gdb */ | ||
1528 | |||
1529 | /* | ||
1530 | * The new 64bit printf support requires an early exception initialization. | ||
1531 | */ | ||
1532 | jbsr base_trap_init | ||
1533 | |||
1534 | /* jump to the kernel start */ | ||
1535 | |||
1536 | putc '\n' | ||
1537 | leds 0x55 | ||
1538 | |||
1539 | jbsr start_kernel | ||
1540 | |||
1541 | /* | ||
1542 | * Find a tag record in the bootinfo structure | ||
1543 | * The bootinfo structure is located right after the kernel bss | ||
1544 | * Returns: d0: size (-1 if not found) | ||
1545 | * a0: data pointer (end-of-records if not found) | ||
1546 | */ | ||
1547 | func_start get_bi_record,%d1 | ||
1548 | |||
1549 | movel ARG1,%d0 | ||
1550 | lea %pc@(_end),%a0 | ||
1551 | 1: tstw %a0@(BIR_TAG) | ||
1552 | jeq 3f | ||
1553 | cmpw %a0@(BIR_TAG),%d0 | ||
1554 | jeq 2f | ||
1555 | addw %a0@(BIR_SIZE),%a0 | ||
1556 | jra 1b | ||
1557 | 2: moveq #0,%d0 | ||
1558 | movew %a0@(BIR_SIZE),%d0 | ||
1559 | lea %a0@(BIR_DATA),%a0 | ||
1560 | jra 4f | ||
1561 | 3: moveq #-1,%d0 | ||
1562 | lea %a0@(BIR_SIZE),%a0 | ||
1563 | 4: | ||
1564 | func_return get_bi_record | ||
1565 | |||
1566 | |||
1567 | /* | ||
1568 | * MMU Initialization Begins Here | ||
1569 | * | ||
1570 | * The structure of the MMU tables on the 68k machines | ||
1571 | * is thus: | ||
1572 | * Root Table | ||
1573 | * Logical addresses are translated through | ||
1574 | * a hierarchical translation mechanism where the high-order | ||
1575 | * seven bits of the logical address (LA) are used as an | ||
1576 | * index into the "root table." Each entry in the root | ||
1577 | * table has a bit which specifies if it's a valid pointer to a | ||
1578 | * pointer table. Each entry defines a 32KMeg range of memory. | ||
1579 | * If an entry is invalid then that logical range of 32M is | ||
1580 | * invalid and references to that range of memory (when the MMU | ||
1581 | * is enabled) will fault. If the entry is valid, then it does | ||
1582 | * one of two things. On 040/060 class machines, it points to | ||
1583 | * a pointer table which then describes more finely the memory | ||
1584 | * within that 32M range. On 020/030 class machines, a technique | ||
1585 | * called "early terminating descriptors" are used. This technique | ||
1586 | * allows an entire 32Meg to be described by a single entry in the | ||
1587 | * root table. Thus, this entry in the root table, contains the | ||
1588 | * physical address of the memory or I/O at the logical address | ||
1589 | * which the entry represents and it also contains the necessary | ||
1590 | * cache bits for this region. | ||
1591 | * | ||
1592 | * Pointer Tables | ||
1593 | * Per the Root Table, there will be one or more | ||
1594 | * pointer tables. Each pointer table defines a 32M range. | ||
1595 | * Not all of the 32M range need be defined. Again, the next | ||
1596 | * seven bits of the logical address are used an index into | ||
1597 | * the pointer table to point to page tables (if the pointer | ||
1598 | * is valid). There will undoubtedly be more than one | ||
1599 | * pointer table for the kernel because each pointer table | ||
1600 | * defines a range of only 32M. Valid pointer table entries | ||
1601 | * point to page tables, or are early terminating entries | ||
1602 | * themselves. | ||
1603 | * | ||
1604 | * Page Tables | ||
1605 | * Per the Pointer Tables, each page table entry points | ||
1606 | * to the physical page in memory that supports the logical | ||
1607 | * address that translates to the particular index. | ||
1608 | * | ||
1609 | * In short, the Logical Address gets translated as follows: | ||
1610 | * bits 31..26 - index into the Root Table | ||
1611 | * bits 25..18 - index into the Pointer Table | ||
1612 | * bits 17..12 - index into the Page Table | ||
1613 | * bits 11..0 - offset into a particular 4K page | ||
1614 | * | ||
1615 | * The algorithms which follows do one thing: they abstract | ||
1616 | * the MMU hardware. For example, there are three kinds of | ||
1617 | * cache settings that are relevant. Either, memory is | ||
1618 | * being mapped in which case it is either Kernel Code (or | ||
1619 | * the RamDisk) or it is MMU data. On the 030, the MMU data | ||
1620 | * option also describes the kernel. Or, I/O is being mapped | ||
1621 | * in which case it has its own kind of cache bits. There | ||
1622 | * are constants which abstract these notions from the code that | ||
1623 | * actually makes the call to map some range of memory. | ||
1624 | * | ||
1625 | * | ||
1626 | * | ||
1627 | */ | ||
1628 | |||
1629 | #ifdef MMU_PRINT | ||
1630 | /* | ||
1631 | * mmu_print | ||
1632 | * | ||
1633 | * This algorithm will print out the current MMU mappings. | ||
1634 | * | ||
1635 | * Input: | ||
1636 | * %a5 points to the root table. Everything else is calculated | ||
1637 | * from this. | ||
1638 | */ | ||
1639 | |||
1640 | #define mmu_next_valid 0 | ||
1641 | #define mmu_start_logical 4 | ||
1642 | #define mmu_next_logical 8 | ||
1643 | #define mmu_start_physical 12 | ||
1644 | #define mmu_next_physical 16 | ||
1645 | |||
1646 | #define MMU_PRINT_INVALID -1 | ||
1647 | #define MMU_PRINT_VALID 1 | ||
1648 | #define MMU_PRINT_UNINITED 0 | ||
1649 | |||
1650 | #define putZc(z,n) jbne 1f; putc z; jbra 2f; 1: putc n; 2: | ||
1651 | |||
1652 | func_start mmu_print,%a0-%a6/%d0-%d7 | ||
1653 | |||
1654 | movel %pc@(L(kernel_pgdir_ptr)),%a5 | ||
1655 | lea %pc@(L(mmu_print_data)),%a0 | ||
1656 | movel #MMU_PRINT_UNINITED,%a0@(mmu_next_valid) | ||
1657 | |||
1658 | is_not_040_or_060(mmu_030_print) | ||
1659 | |||
1660 | mmu_040_print: | ||
1661 | puts "\nMMU040\n" | ||
1662 | puts "rp:" | ||
1663 | putn %a5 | ||
1664 | putc '\n' | ||
1665 | #if 0 | ||
1666 | /* | ||
1667 | * The following #if/#endif block is a tight algorithm for dumping the 040 | ||
1668 | * MMU Map in gory detail. It really isn't that practical unless the | ||
1669 | * MMU Map algorithm appears to go awry and you need to debug it at the | ||
1670 | * entry per entry level. | ||
1671 | */ | ||
1672 | movel #ROOT_TABLE_SIZE,%d5 | ||
1673 | #if 0 | ||
1674 | movel %a5@+,%d7 | Burn an entry to skip the kernel mappings, | ||
1675 | subql #1,%d5 | they (might) work | ||
1676 | #endif | ||
1677 | 1: tstl %d5 | ||
1678 | jbeq mmu_print_done | ||
1679 | subq #1,%d5 | ||
1680 | movel %a5@+,%d7 | ||
1681 | btst #1,%d7 | ||
1682 | jbeq 1b | ||
1683 | |||
1684 | 2: putn %d7 | ||
1685 | andil #0xFFFFFE00,%d7 | ||
1686 | movel %d7,%a4 | ||
1687 | movel #PTR_TABLE_SIZE,%d4 | ||
1688 | putc ' ' | ||
1689 | 3: tstl %d4 | ||
1690 | jbeq 11f | ||
1691 | subq #1,%d4 | ||
1692 | movel %a4@+,%d7 | ||
1693 | btst #1,%d7 | ||
1694 | jbeq 3b | ||
1695 | |||
1696 | 4: putn %d7 | ||
1697 | andil #0xFFFFFF00,%d7 | ||
1698 | movel %d7,%a3 | ||
1699 | movel #PAGE_TABLE_SIZE,%d3 | ||
1700 | 5: movel #8,%d2 | ||
1701 | 6: tstl %d3 | ||
1702 | jbeq 31f | ||
1703 | subq #1,%d3 | ||
1704 | movel %a3@+,%d6 | ||
1705 | btst #0,%d6 | ||
1706 | jbeq 6b | ||
1707 | 7: tstl %d2 | ||
1708 | jbeq 8f | ||
1709 | subq #1,%d2 | ||
1710 | putc ' ' | ||
1711 | jbra 91f | ||
1712 | 8: putc '\n' | ||
1713 | movel #8+1+8+1+1,%d2 | ||
1714 | 9: putc ' ' | ||
1715 | dbra %d2,9b | ||
1716 | movel #7,%d2 | ||
1717 | 91: putn %d6 | ||
1718 | jbra 6b | ||
1719 | |||
1720 | 31: putc '\n' | ||
1721 | movel #8+1,%d2 | ||
1722 | 32: putc ' ' | ||
1723 | dbra %d2,32b | ||
1724 | jbra 3b | ||
1725 | |||
1726 | 11: putc '\n' | ||
1727 | jbra 1b | ||
1728 | #endif /* MMU 040 Dumping code that's gory and detailed */ | ||
1729 | |||
1730 | lea %pc@(kernel_pg_dir),%a5 | ||
1731 | movel %a5,%a0 /* a0 has the address of the root table ptr */ | ||
1732 | movel #0x00000000,%a4 /* logical address */ | ||
1733 | moveql #0,%d0 | ||
1734 | 40: | ||
1735 | /* Increment the logical address and preserve in d5 */ | ||
1736 | movel %a4,%d5 | ||
1737 | addil #PAGESIZE<<13,%d5 | ||
1738 | movel %a0@+,%d6 | ||
1739 | btst #1,%d6 | ||
1740 | jbne 41f | ||
1741 | jbsr mmu_print_tuple_invalidate | ||
1742 | jbra 48f | ||
1743 | 41: | ||
1744 | movel #0,%d1 | ||
1745 | andil #0xfffffe00,%d6 | ||
1746 | movel %d6,%a1 | ||
1747 | 42: | ||
1748 | movel %a4,%d5 | ||
1749 | addil #PAGESIZE<<6,%d5 | ||
1750 | movel %a1@+,%d6 | ||
1751 | btst #1,%d6 | ||
1752 | jbne 43f | ||
1753 | jbsr mmu_print_tuple_invalidate | ||
1754 | jbra 47f | ||
1755 | 43: | ||
1756 | movel #0,%d2 | ||
1757 | andil #0xffffff00,%d6 | ||
1758 | movel %d6,%a2 | ||
1759 | 44: | ||
1760 | movel %a4,%d5 | ||
1761 | addil #PAGESIZE,%d5 | ||
1762 | movel %a2@+,%d6 | ||
1763 | btst #0,%d6 | ||
1764 | jbne 45f | ||
1765 | jbsr mmu_print_tuple_invalidate | ||
1766 | jbra 46f | ||
1767 | 45: | ||
1768 | moveml %d0-%d1,%sp@- | ||
1769 | movel %a4,%d0 | ||
1770 | movel %d6,%d1 | ||
1771 | andil #0xfffff4e0,%d1 | ||
1772 | lea %pc@(mmu_040_print_flags),%a6 | ||
1773 | jbsr mmu_print_tuple | ||
1774 | moveml %sp@+,%d0-%d1 | ||
1775 | 46: | ||
1776 | movel %d5,%a4 | ||
1777 | addq #1,%d2 | ||
1778 | cmpib #64,%d2 | ||
1779 | jbne 44b | ||
1780 | 47: | ||
1781 | movel %d5,%a4 | ||
1782 | addq #1,%d1 | ||
1783 | cmpib #128,%d1 | ||
1784 | jbne 42b | ||
1785 | 48: | ||
1786 | movel %d5,%a4 /* move to the next logical address */ | ||
1787 | addq #1,%d0 | ||
1788 | cmpib #128,%d0 | ||
1789 | jbne 40b | ||
1790 | |||
1791 | .chip 68040 | ||
1792 | movec %dtt1,%d0 | ||
1793 | movel %d0,%d1 | ||
1794 | andiw #0x8000,%d1 /* is it valid ? */ | ||
1795 | jbeq 1f /* No, bail out */ | ||
1796 | |||
1797 | movel %d0,%d1 | ||
1798 | andil #0xff000000,%d1 /* Get the address */ | ||
1799 | putn %d1 | ||
1800 | puts "==" | ||
1801 | putn %d1 | ||
1802 | |||
1803 | movel %d0,%d6 | ||
1804 | jbsr mmu_040_print_flags_tt | ||
1805 | 1: | ||
1806 | movec %dtt0,%d0 | ||
1807 | movel %d0,%d1 | ||
1808 | andiw #0x8000,%d1 /* is it valid ? */ | ||
1809 | jbeq 1f /* No, bail out */ | ||
1810 | |||
1811 | movel %d0,%d1 | ||
1812 | andil #0xff000000,%d1 /* Get the address */ | ||
1813 | putn %d1 | ||
1814 | puts "==" | ||
1815 | putn %d1 | ||
1816 | |||
1817 | movel %d0,%d6 | ||
1818 | jbsr mmu_040_print_flags_tt | ||
1819 | 1: | ||
1820 | .chip 68k | ||
1821 | |||
1822 | jbra mmu_print_done | ||
1823 | |||
1824 | mmu_040_print_flags: | ||
1825 | btstl #10,%d6 | ||
1826 | putZc(' ','G') /* global bit */ | ||
1827 | btstl #7,%d6 | ||
1828 | putZc(' ','S') /* supervisor bit */ | ||
1829 | mmu_040_print_flags_tt: | ||
1830 | btstl #6,%d6 | ||
1831 | jbne 3f | ||
1832 | putc 'C' | ||
1833 | btstl #5,%d6 | ||
1834 | putZc('w','c') /* write through or copy-back */ | ||
1835 | jbra 4f | ||
1836 | 3: | ||
1837 | putc 'N' | ||
1838 | btstl #5,%d6 | ||
1839 | putZc('s',' ') /* serialized non-cacheable, or non-cacheable */ | ||
1840 | 4: | ||
1841 | rts | ||
1842 | |||
1843 | mmu_030_print_flags: | ||
1844 | btstl #6,%d6 | ||
1845 | putZc('C','I') /* write through or copy-back */ | ||
1846 | rts | ||
1847 | |||
1848 | mmu_030_print: | ||
1849 | puts "\nMMU030\n" | ||
1850 | puts "\nrp:" | ||
1851 | putn %a5 | ||
1852 | putc '\n' | ||
1853 | movel %a5,%d0 | ||
1854 | andil #0xfffffff0,%d0 | ||
1855 | movel %d0,%a0 | ||
1856 | movel #0x00000000,%a4 /* logical address */ | ||
1857 | movel #0,%d0 | ||
1858 | 30: | ||
1859 | movel %a4,%d5 | ||
1860 | addil #PAGESIZE<<13,%d5 | ||
1861 | movel %a0@+,%d6 | ||
1862 | btst #1,%d6 /* is it a table ptr? */ | ||
1863 | jbne 31f /* yes */ | ||
1864 | btst #0,%d6 /* is it early terminating? */ | ||
1865 | jbeq 1f /* no */ | ||
1866 | jbsr mmu_030_print_helper | ||
1867 | jbra 38f | ||
1868 | 1: | ||
1869 | jbsr mmu_print_tuple_invalidate | ||
1870 | jbra 38f | ||
1871 | 31: | ||
1872 | movel #0,%d1 | ||
1873 | andil #0xfffffff0,%d6 | ||
1874 | movel %d6,%a1 | ||
1875 | 32: | ||
1876 | movel %a4,%d5 | ||
1877 | addil #PAGESIZE<<6,%d5 | ||
1878 | movel %a1@+,%d6 | ||
1879 | btst #1,%d6 /* is it a table ptr? */ | ||
1880 | jbne 33f /* yes */ | ||
1881 | btst #0,%d6 /* is it a page descriptor? */ | ||
1882 | jbeq 1f /* no */ | ||
1883 | jbsr mmu_030_print_helper | ||
1884 | jbra 37f | ||
1885 | 1: | ||
1886 | jbsr mmu_print_tuple_invalidate | ||
1887 | jbra 37f | ||
1888 | 33: | ||
1889 | movel #0,%d2 | ||
1890 | andil #0xfffffff0,%d6 | ||
1891 | movel %d6,%a2 | ||
1892 | 34: | ||
1893 | movel %a4,%d5 | ||
1894 | addil #PAGESIZE,%d5 | ||
1895 | movel %a2@+,%d6 | ||
1896 | btst #0,%d6 | ||
1897 | jbne 35f | ||
1898 | jbsr mmu_print_tuple_invalidate | ||
1899 | jbra 36f | ||
1900 | 35: | ||
1901 | jbsr mmu_030_print_helper | ||
1902 | 36: | ||
1903 | movel %d5,%a4 | ||
1904 | addq #1,%d2 | ||
1905 | cmpib #64,%d2 | ||
1906 | jbne 34b | ||
1907 | 37: | ||
1908 | movel %d5,%a4 | ||
1909 | addq #1,%d1 | ||
1910 | cmpib #128,%d1 | ||
1911 | jbne 32b | ||
1912 | 38: | ||
1913 | movel %d5,%a4 /* move to the next logical address */ | ||
1914 | addq #1,%d0 | ||
1915 | cmpib #128,%d0 | ||
1916 | jbne 30b | ||
1917 | |||
1918 | mmu_print_done: | ||
1919 | puts "\n\n" | ||
1920 | |||
1921 | func_return mmu_print | ||
1922 | |||
1923 | |||
1924 | mmu_030_print_helper: | ||
1925 | moveml %d0-%d1,%sp@- | ||
1926 | movel %a4,%d0 | ||
1927 | movel %d6,%d1 | ||
1928 | lea %pc@(mmu_030_print_flags),%a6 | ||
1929 | jbsr mmu_print_tuple | ||
1930 | moveml %sp@+,%d0-%d1 | ||
1931 | rts | ||
1932 | |||
1933 | mmu_print_tuple_invalidate: | ||
1934 | moveml %a0/%d7,%sp@- | ||
1935 | |||
1936 | lea %pc@(L(mmu_print_data)),%a0 | ||
1937 | tstl %a0@(mmu_next_valid) | ||
1938 | jbmi mmu_print_tuple_invalidate_exit | ||
1939 | |||
1940 | movel #MMU_PRINT_INVALID,%a0@(mmu_next_valid) | ||
1941 | |||
1942 | putn %a4 | ||
1943 | |||
1944 | puts "##\n" | ||
1945 | |||
1946 | mmu_print_tuple_invalidate_exit: | ||
1947 | moveml %sp@+,%a0/%d7 | ||
1948 | rts | ||
1949 | |||
1950 | |||
1951 | mmu_print_tuple: | ||
1952 | moveml %d0-%d7/%a0,%sp@- | ||
1953 | |||
1954 | lea %pc@(L(mmu_print_data)),%a0 | ||
1955 | |||
1956 | tstl %a0@(mmu_next_valid) | ||
1957 | jble mmu_print_tuple_print | ||
1958 | |||
1959 | cmpl %a0@(mmu_next_physical),%d1 | ||
1960 | jbeq mmu_print_tuple_increment | ||
1961 | |||
1962 | mmu_print_tuple_print: | ||
1963 | putn %d0 | ||
1964 | puts "->" | ||
1965 | putn %d1 | ||
1966 | |||
1967 | movel %d1,%d6 | ||
1968 | jbsr %a6@ | ||
1969 | |||
1970 | mmu_print_tuple_record: | ||
1971 | movel #MMU_PRINT_VALID,%a0@(mmu_next_valid) | ||
1972 | |||
1973 | movel %d1,%a0@(mmu_next_physical) | ||
1974 | |||
1975 | mmu_print_tuple_increment: | ||
1976 | movel %d5,%d7 | ||
1977 | subl %a4,%d7 | ||
1978 | addl %d7,%a0@(mmu_next_physical) | ||
1979 | |||
1980 | mmu_print_tuple_exit: | ||
1981 | moveml %sp@+,%d0-%d7/%a0 | ||
1982 | rts | ||
1983 | |||
1984 | mmu_print_machine_cpu_types: | ||
1985 | puts "machine: " | ||
1986 | |||
1987 | is_not_amiga(1f) | ||
1988 | puts "amiga" | ||
1989 | jbra 9f | ||
1990 | 1: | ||
1991 | is_not_atari(2f) | ||
1992 | puts "atari" | ||
1993 | jbra 9f | ||
1994 | 2: | ||
1995 | is_not_mac(3f) | ||
1996 | puts "macintosh" | ||
1997 | jbra 9f | ||
1998 | 3: puts "unknown" | ||
1999 | 9: putc '\n' | ||
2000 | |||
2001 | puts "cputype: 0" | ||
2002 | is_not_060(1f) | ||
2003 | putc '6' | ||
2004 | jbra 9f | ||
2005 | 1: | ||
2006 | is_not_040_or_060(2f) | ||
2007 | putc '4' | ||
2008 | jbra 9f | ||
2009 | 2: putc '3' | ||
2010 | 9: putc '0' | ||
2011 | putc '\n' | ||
2012 | |||
2013 | rts | ||
2014 | #endif /* MMU_PRINT */ | ||
2015 | |||
2016 | /* | ||
2017 | * mmu_map_tt | ||
2018 | * | ||
2019 | * This is a specific function which works on all 680x0 machines. | ||
2020 | * On 030, 040 & 060 it will attempt to use Transparent Translation | ||
2021 | * registers (tt1). | ||
2022 | * On 020 it will call the standard mmu_map which will use early | ||
2023 | * terminating descriptors. | ||
2024 | */ | ||
2025 | func_start mmu_map_tt,%d0/%d1/%a0,4 | ||
2026 | |||
2027 | dputs "mmu_map_tt:" | ||
2028 | dputn ARG1 | ||
2029 | dputn ARG2 | ||
2030 | dputn ARG3 | ||
2031 | dputn ARG4 | ||
2032 | dputc '\n' | ||
2033 | |||
2034 | is_020(L(do_map)) | ||
2035 | |||
2036 | /* Extract the highest bit set | ||
2037 | */ | ||
2038 | bfffo ARG3{#0,#32},%d1 | ||
2039 | cmpw #8,%d1 | ||
2040 | jcc L(do_map) | ||
2041 | |||
2042 | /* And get the mask | ||
2043 | */ | ||
2044 | moveq #-1,%d0 | ||
2045 | lsrl %d1,%d0 | ||
2046 | lsrl #1,%d0 | ||
2047 | |||
2048 | /* Mask the address | ||
2049 | */ | ||
2050 | movel %d0,%d1 | ||
2051 | notl %d1 | ||
2052 | andl ARG2,%d1 | ||
2053 | |||
2054 | /* Generate the upper 16bit of the tt register | ||
2055 | */ | ||
2056 | lsrl #8,%d0 | ||
2057 | orl %d0,%d1 | ||
2058 | clrw %d1 | ||
2059 | |||
2060 | is_040_or_060(L(mmu_map_tt_040)) | ||
2061 | |||
2062 | /* set 030 specific bits (read/write access for supervisor mode | ||
2063 | * (highest function code set, lower two bits masked)) | ||
2064 | */ | ||
2065 | orw #TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d1 | ||
2066 | movel ARG4,%d0 | ||
2067 | btst #6,%d0 | ||
2068 | jeq 1f | ||
2069 | orw #TTR_CI,%d1 | ||
2070 | |||
2071 | 1: lea STACK,%a0 | ||
2072 | dputn %d1 | ||
2073 | movel %d1,%a0@ | ||
2074 | .chip 68030 | ||
2075 | tstl ARG1 | ||
2076 | jne 1f | ||
2077 | pmove %a0@,%tt0 | ||
2078 | jra 2f | ||
2079 | 1: pmove %a0@,%tt1 | ||
2080 | 2: .chip 68k | ||
2081 | jra L(mmu_map_tt_done) | ||
2082 | |||
2083 | /* set 040 specific bits | ||
2084 | */ | ||
2085 | L(mmu_map_tt_040): | ||
2086 | orw #TTR_ENABLE+TTR_KERNELMODE,%d1 | ||
2087 | orl ARG4,%d1 | ||
2088 | dputn %d1 | ||
2089 | |||
2090 | .chip 68040 | ||
2091 | tstl ARG1 | ||
2092 | jne 1f | ||
2093 | movec %d1,%itt0 | ||
2094 | movec %d1,%dtt0 | ||
2095 | jra 2f | ||
2096 | 1: movec %d1,%itt1 | ||
2097 | movec %d1,%dtt1 | ||
2098 | 2: .chip 68k | ||
2099 | |||
2100 | jra L(mmu_map_tt_done) | ||
2101 | |||
2102 | L(do_map): | ||
2103 | mmu_map_eq ARG2,ARG3,ARG4 | ||
2104 | |||
2105 | L(mmu_map_tt_done): | ||
2106 | |||
2107 | func_return mmu_map_tt | ||
2108 | |||
2109 | /* | ||
2110 | * mmu_map | ||
2111 | * | ||
2112 | * This routine will map a range of memory using a pointer | ||
2113 | * table and allocating the pages on the fly from the kernel. | ||
2114 | * The pointer table does not have to be already linked into | ||
2115 | * the root table, this routine will do that if necessary. | ||
2116 | * | ||
2117 | * NOTE | ||
2118 | * This routine will assert failure and use the serial_putc | ||
2119 | * routines in the case of a run-time error. For example, | ||
2120 | * if the address is already mapped. | ||
2121 | * | ||
2122 | * NOTE-2 | ||
2123 | * This routine will use early terminating descriptors | ||
2124 | * where possible for the 68020+68851 and 68030 type | ||
2125 | * processors. | ||
2126 | */ | ||
2127 | func_start mmu_map,%d0-%d4/%a0-%a4 | ||
2128 | |||
2129 | dputs "\nmmu_map:" | ||
2130 | dputn ARG1 | ||
2131 | dputn ARG2 | ||
2132 | dputn ARG3 | ||
2133 | dputn ARG4 | ||
2134 | dputc '\n' | ||
2135 | |||
2136 | /* Get logical address and round it down to 256KB | ||
2137 | */ | ||
2138 | movel ARG1,%d0 | ||
2139 | andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0 | ||
2140 | movel %d0,%a3 | ||
2141 | |||
2142 | /* Get the end address | ||
2143 | */ | ||
2144 | movel ARG1,%a4 | ||
2145 | addl ARG3,%a4 | ||
2146 | subql #1,%a4 | ||
2147 | |||
2148 | /* Get physical address and round it down to 256KB | ||
2149 | */ | ||
2150 | movel ARG2,%d0 | ||
2151 | andl #-(PAGESIZE*PAGE_TABLE_SIZE),%d0 | ||
2152 | movel %d0,%a2 | ||
2153 | |||
2154 | /* Add page attributes to the physical address | ||
2155 | */ | ||
2156 | movel ARG4,%d0 | ||
2157 | orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0 | ||
2158 | addw %d0,%a2 | ||
2159 | |||
2160 | dputn %a2 | ||
2161 | dputn %a3 | ||
2162 | dputn %a4 | ||
2163 | |||
2164 | is_not_040_or_060(L(mmu_map_030)) | ||
2165 | |||
2166 | addw #_PAGE_GLOBAL040,%a2 | ||
2167 | /* | ||
2168 | * MMU 040 & 060 Support | ||
2169 | * | ||
2170 | * The MMU usage for the 040 and 060 is different enough from | ||
2171 | * the 030 and 68851 that there is separate code. This comment | ||
2172 | * block describes the data structures and algorithms built by | ||
2173 | * this code. | ||
2174 | * | ||
2175 | * The 040 does not support early terminating descriptors, as | ||
2176 | * the 030 does. Therefore, a third level of table is needed | ||
2177 | * for the 040, and that would be the page table. In Linux, | ||
2178 | * page tables are allocated directly from the memory above the | ||
2179 | * kernel. | ||
2180 | * | ||
2181 | */ | ||
2182 | |||
2183 | L(mmu_map_040): | ||
2184 | /* Calculate the offset into the root table | ||
2185 | */ | ||
2186 | movel %a3,%d0 | ||
2187 | moveq #ROOT_INDEX_SHIFT,%d1 | ||
2188 | lsrl %d1,%d0 | ||
2189 | mmu_get_root_table_entry %d0 | ||
2190 | |||
2191 | /* Calculate the offset into the pointer table | ||
2192 | */ | ||
2193 | movel %a3,%d0 | ||
2194 | moveq #PTR_INDEX_SHIFT,%d1 | ||
2195 | lsrl %d1,%d0 | ||
2196 | andl #PTR_TABLE_SIZE-1,%d0 | ||
2197 | mmu_get_ptr_table_entry %a0,%d0 | ||
2198 | |||
2199 | /* Calculate the offset into the page table | ||
2200 | */ | ||
2201 | movel %a3,%d0 | ||
2202 | moveq #PAGE_INDEX_SHIFT,%d1 | ||
2203 | lsrl %d1,%d0 | ||
2204 | andl #PAGE_TABLE_SIZE-1,%d0 | ||
2205 | mmu_get_page_table_entry %a0,%d0 | ||
2206 | |||
2207 | /* The page table entry must not no be busy | ||
2208 | */ | ||
2209 | tstl %a0@ | ||
2210 | jne L(mmu_map_error) | ||
2211 | |||
2212 | /* Do the mapping and advance the pointers | ||
2213 | */ | ||
2214 | movel %a2,%a0@ | ||
2215 | 2: | ||
2216 | addw #PAGESIZE,%a2 | ||
2217 | addw #PAGESIZE,%a3 | ||
2218 | |||
2219 | /* Ready with mapping? | ||
2220 | */ | ||
2221 | lea %a3@(-1),%a0 | ||
2222 | cmpl %a0,%a4 | ||
2223 | jhi L(mmu_map_040) | ||
2224 | jra L(mmu_map_done) | ||
2225 | |||
2226 | L(mmu_map_030): | ||
2227 | /* Calculate the offset into the root table | ||
2228 | */ | ||
2229 | movel %a3,%d0 | ||
2230 | moveq #ROOT_INDEX_SHIFT,%d1 | ||
2231 | lsrl %d1,%d0 | ||
2232 | mmu_get_root_table_entry %d0 | ||
2233 | |||
2234 | /* Check if logical address 32MB aligned, | ||
2235 | * so we can try to map it once | ||
2236 | */ | ||
2237 | movel %a3,%d0 | ||
2238 | andl #(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d0 | ||
2239 | jne 1f | ||
2240 | |||
2241 | /* Is there enough to map for 32MB at once | ||
2242 | */ | ||
2243 | lea %a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a1 | ||
2244 | cmpl %a1,%a4 | ||
2245 | jcs 1f | ||
2246 | |||
2247 | addql #1,%a1 | ||
2248 | |||
2249 | /* The root table entry must not no be busy | ||
2250 | */ | ||
2251 | tstl %a0@ | ||
2252 | jne L(mmu_map_error) | ||
2253 | |||
2254 | /* Do the mapping and advance the pointers | ||
2255 | */ | ||
2256 | dputs "early term1" | ||
2257 | dputn %a2 | ||
2258 | dputn %a3 | ||
2259 | dputn %a1 | ||
2260 | dputc '\n' | ||
2261 | movel %a2,%a0@ | ||
2262 | |||
2263 | movel %a1,%a3 | ||
2264 | lea %a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a2 | ||
2265 | jra L(mmu_mapnext_030) | ||
2266 | 1: | ||
2267 | /* Calculate the offset into the pointer table | ||
2268 | */ | ||
2269 | movel %a3,%d0 | ||
2270 | moveq #PTR_INDEX_SHIFT,%d1 | ||
2271 | lsrl %d1,%d0 | ||
2272 | andl #PTR_TABLE_SIZE-1,%d0 | ||
2273 | mmu_get_ptr_table_entry %a0,%d0 | ||
2274 | |||
2275 | /* The pointer table entry must not no be busy | ||
2276 | */ | ||
2277 | tstl %a0@ | ||
2278 | jne L(mmu_map_error) | ||
2279 | |||
2280 | /* Do the mapping and advance the pointers | ||
2281 | */ | ||
2282 | dputs "early term2" | ||
2283 | dputn %a2 | ||
2284 | dputn %a3 | ||
2285 | dputc '\n' | ||
2286 | movel %a2,%a0@ | ||
2287 | |||
2288 | addl #PAGE_TABLE_SIZE*PAGESIZE,%a2 | ||
2289 | addl #PAGE_TABLE_SIZE*PAGESIZE,%a3 | ||
2290 | |||
2291 | L(mmu_mapnext_030): | ||
2292 | /* Ready with mapping? | ||
2293 | */ | ||
2294 | lea %a3@(-1),%a0 | ||
2295 | cmpl %a0,%a4 | ||
2296 | jhi L(mmu_map_030) | ||
2297 | jra L(mmu_map_done) | ||
2298 | |||
2299 | L(mmu_map_error): | ||
2300 | |||
2301 | dputs "mmu_map error:" | ||
2302 | dputn %a2 | ||
2303 | dputn %a3 | ||
2304 | dputc '\n' | ||
2305 | |||
2306 | L(mmu_map_done): | ||
2307 | |||
2308 | func_return mmu_map | ||
2309 | |||
2310 | /* | ||
2311 | * mmu_fixup | ||
2312 | * | ||
2313 | * On the 040 class machines, all pages that are used for the | ||
2314 | * mmu have to be fixed up. | ||
2315 | */ | ||
2316 | |||
2317 | func_start mmu_fixup_page_mmu_cache,%d0/%a0 | ||
2318 | |||
2319 | dputs "mmu_fixup_page_mmu_cache" | ||
2320 | dputn ARG1 | ||
2321 | |||
2322 | /* Calculate the offset into the root table | ||
2323 | */ | ||
2324 | movel ARG1,%d0 | ||
2325 | moveq #ROOT_INDEX_SHIFT,%d1 | ||
2326 | lsrl %d1,%d0 | ||
2327 | mmu_get_root_table_entry %d0 | ||
2328 | |||
2329 | /* Calculate the offset into the pointer table | ||
2330 | */ | ||
2331 | movel ARG1,%d0 | ||
2332 | moveq #PTR_INDEX_SHIFT,%d1 | ||
2333 | lsrl %d1,%d0 | ||
2334 | andl #PTR_TABLE_SIZE-1,%d0 | ||
2335 | mmu_get_ptr_table_entry %a0,%d0 | ||
2336 | |||
2337 | /* Calculate the offset into the page table | ||
2338 | */ | ||
2339 | movel ARG1,%d0 | ||
2340 | moveq #PAGE_INDEX_SHIFT,%d1 | ||
2341 | lsrl %d1,%d0 | ||
2342 | andl #PAGE_TABLE_SIZE-1,%d0 | ||
2343 | mmu_get_page_table_entry %a0,%d0 | ||
2344 | |||
2345 | movel %a0@,%d0 | ||
2346 | andil #_CACHEMASK040,%d0 | ||
2347 | orl %pc@(m68k_pgtable_cachemode),%d0 | ||
2348 | movel %d0,%a0@ | ||
2349 | |||
2350 | dputc '\n' | ||
2351 | |||
2352 | func_return mmu_fixup_page_mmu_cache | ||
2353 | |||
2354 | /* | ||
2355 | * mmu_temp_map | ||
2356 | * | ||
2357 | * create a temporary mapping to enable the mmu, | ||
2358 | * this we don't need any transparation translation tricks. | ||
2359 | */ | ||
2360 | |||
2361 | func_start mmu_temp_map,%d0/%d1/%a0/%a1 | ||
2362 | |||
2363 | dputs "mmu_temp_map" | ||
2364 | dputn ARG1 | ||
2365 | dputn ARG2 | ||
2366 | dputc '\n' | ||
2367 | |||
2368 | lea %pc@(L(temp_mmap_mem)),%a1 | ||
2369 | |||
2370 | /* Calculate the offset in the root table | ||
2371 | */ | ||
2372 | movel ARG2,%d0 | ||
2373 | moveq #ROOT_INDEX_SHIFT,%d1 | ||
2374 | lsrl %d1,%d0 | ||
2375 | mmu_get_root_table_entry %d0 | ||
2376 | |||
2377 | /* Check if the table is temporary allocated, so we have to reuse it | ||
2378 | */ | ||
2379 | movel %a0@,%d0 | ||
2380 | cmpl %pc@(L(memory_start)),%d0 | ||
2381 | jcc 1f | ||
2382 | |||
2383 | /* Temporary allocate a ptr table and insert it into the root table | ||
2384 | */ | ||
2385 | movel %a1@,%d0 | ||
2386 | addl #PTR_TABLE_SIZE*4,%a1@ | ||
2387 | orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0 | ||
2388 | movel %d0,%a0@ | ||
2389 | dputs " (new)" | ||
2390 | 1: | ||
2391 | dputn %d0 | ||
2392 | /* Mask the root table entry for the ptr table | ||
2393 | */ | ||
2394 | andw #-ROOT_TABLE_SIZE,%d0 | ||
2395 | movel %d0,%a0 | ||
2396 | |||
2397 | /* Calculate the offset into the pointer table | ||
2398 | */ | ||
2399 | movel ARG2,%d0 | ||
2400 | moveq #PTR_INDEX_SHIFT,%d1 | ||
2401 | lsrl %d1,%d0 | ||
2402 | andl #PTR_TABLE_SIZE-1,%d0 | ||
2403 | lea %a0@(%d0*4),%a0 | ||
2404 | dputn %a0 | ||
2405 | |||
2406 | /* Check if a temporary page table is already allocated | ||
2407 | */ | ||
2408 | movel %a0@,%d0 | ||
2409 | jne 1f | ||
2410 | |||
2411 | /* Temporary allocate a page table and insert it into the ptr table | ||
2412 | */ | ||
2413 | movel %a1@,%d0 | ||
2414 | /* The 512 should be PAGE_TABLE_SIZE*4, but that violates the | ||
2415 | alignment restriction for pointer tables on the '0[46]0. */ | ||
2416 | addl #512,%a1@ | ||
2417 | orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0 | ||
2418 | movel %d0,%a0@ | ||
2419 | dputs " (new)" | ||
2420 | 1: | ||
2421 | dputn %d0 | ||
2422 | /* Mask the ptr table entry for the page table | ||
2423 | */ | ||
2424 | andw #-PTR_TABLE_SIZE,%d0 | ||
2425 | movel %d0,%a0 | ||
2426 | |||
2427 | /* Calculate the offset into the page table | ||
2428 | */ | ||
2429 | movel ARG2,%d0 | ||
2430 | moveq #PAGE_INDEX_SHIFT,%d1 | ||
2431 | lsrl %d1,%d0 | ||
2432 | andl #PAGE_TABLE_SIZE-1,%d0 | ||
2433 | lea %a0@(%d0*4),%a0 | ||
2434 | dputn %a0 | ||
2435 | |||
2436 | /* Insert the address into the page table | ||
2437 | */ | ||
2438 | movel ARG1,%d0 | ||
2439 | andw #-PAGESIZE,%d0 | ||
2440 | orw #_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0 | ||
2441 | movel %d0,%a0@ | ||
2442 | dputn %d0 | ||
2443 | |||
2444 | dputc '\n' | ||
2445 | |||
2446 | func_return mmu_temp_map | ||
2447 | |||
2448 | func_start mmu_engage,%d0-%d2/%a0-%a3 | ||
2449 | |||
2450 | moveq #ROOT_TABLE_SIZE-1,%d0 | ||
2451 | /* Temporarily use a different root table. */ | ||
2452 | lea %pc@(L(kernel_pgdir_ptr)),%a0 | ||
2453 | movel %a0@,%a2 | ||
2454 | movel %pc@(L(memory_start)),%a1 | ||
2455 | movel %a1,%a0@ | ||
2456 | movel %a2,%a0 | ||
2457 | 1: | ||
2458 | movel %a0@+,%a1@+ | ||
2459 | dbra %d0,1b | ||
2460 | |||
2461 | lea %pc@(L(temp_mmap_mem)),%a0 | ||
2462 | movel %a1,%a0@ | ||
2463 | |||
2464 | movew #PAGESIZE-1,%d0 | ||
2465 | 1: | ||
2466 | clrl %a1@+ | ||
2467 | dbra %d0,1b | ||
2468 | |||
2469 | lea %pc@(1b),%a0 | ||
2470 | movel #1b,%a1 | ||
2471 | /* Skip temp mappings if phys == virt */ | ||
2472 | cmpl %a0,%a1 | ||
2473 | jeq 1f | ||
2474 | |||
2475 | mmu_temp_map %a0,%a0 | ||
2476 | mmu_temp_map %a0,%a1 | ||
2477 | |||
2478 | addw #PAGESIZE,%a0 | ||
2479 | addw #PAGESIZE,%a1 | ||
2480 | mmu_temp_map %a0,%a0 | ||
2481 | mmu_temp_map %a0,%a1 | ||
2482 | 1: | ||
2483 | movel %pc@(L(memory_start)),%a3 | ||
2484 | movel %pc@(L(phys_kernel_start)),%d2 | ||
2485 | |||
2486 | is_not_040_or_060(L(mmu_engage_030)) | ||
2487 | |||
2488 | L(mmu_engage_040): | ||
2489 | .chip 68040 | ||
2490 | nop | ||
2491 | cinva %bc | ||
2492 | nop | ||
2493 | pflusha | ||
2494 | nop | ||
2495 | movec %a3,%srp | ||
2496 | movel #TC_ENABLE+TC_PAGE4K,%d0 | ||
2497 | movec %d0,%tc /* enable the MMU */ | ||
2498 | jmp 1f:l | ||
2499 | 1: nop | ||
2500 | movec %a2,%srp | ||
2501 | nop | ||
2502 | cinva %bc | ||
2503 | nop | ||
2504 | pflusha | ||
2505 | .chip 68k | ||
2506 | jra L(mmu_engage_cleanup) | ||
2507 | |||
2508 | L(mmu_engage_030_temp): | ||
2509 | .space 12 | ||
2510 | L(mmu_engage_030): | ||
2511 | .chip 68030 | ||
2512 | lea %pc@(L(mmu_engage_030_temp)),%a0 | ||
2513 | movel #0x80000002,%a0@ | ||
2514 | movel %a3,%a0@(4) | ||
2515 | movel #0x0808,%d0 | ||
2516 | movec %d0,%cacr | ||
2517 | pmove %a0@,%srp | ||
2518 | pflusha | ||
2519 | /* | ||
2520 | * enable,super root enable,4096 byte pages,7 bit root index, | ||
2521 | * 7 bit pointer index, 6 bit page table index. | ||
2522 | */ | ||
2523 | movel #0x82c07760,%a0@(8) | ||
2524 | pmove %a0@(8),%tc /* enable the MMU */ | ||
2525 | jmp 1f:l | ||
2526 | 1: movel %a2,%a0@(4) | ||
2527 | movel #0x0808,%d0 | ||
2528 | movec %d0,%cacr | ||
2529 | pmove %a0@,%srp | ||
2530 | pflusha | ||
2531 | .chip 68k | ||
2532 | |||
2533 | L(mmu_engage_cleanup): | ||
2534 | subl #PAGE_OFFSET,%d2 | ||
2535 | subl %d2,%a2 | ||
2536 | movel %a2,L(kernel_pgdir_ptr) | ||
2537 | subl %d2,%fp | ||
2538 | subl %d2,%sp | ||
2539 | subl %d2,ARG0 | ||
2540 | |||
2541 | func_return mmu_engage | ||
2542 | |||
2543 | func_start mmu_get_root_table_entry,%d0/%a1 | ||
2544 | |||
2545 | #if 0 | ||
2546 | dputs "mmu_get_root_table_entry:" | ||
2547 | dputn ARG1 | ||
2548 | dputs " =" | ||
2549 | #endif | ||
2550 | |||
2551 | movel %pc@(L(kernel_pgdir_ptr)),%a0 | ||
2552 | tstl %a0 | ||
2553 | jne 2f | ||
2554 | |||
2555 | dputs "\nmmu_init:" | ||
2556 | |||
2557 | /* Find the start of free memory, get_bi_record does this for us, | ||
2558 | * as the bootinfo structure is located directly behind the kernel | ||
2559 | * and and we simply search for the last entry. | ||
2560 | */ | ||
2561 | get_bi_record BI_LAST | ||
2562 | addw #PAGESIZE-1,%a0 | ||
2563 | movel %a0,%d0 | ||
2564 | andw #-PAGESIZE,%d0 | ||
2565 | |||
2566 | dputn %d0 | ||
2567 | |||
2568 | lea %pc@(L(memory_start)),%a0 | ||
2569 | movel %d0,%a0@ | ||
2570 | lea %pc@(L(kernel_end)),%a0 | ||
2571 | movel %d0,%a0@ | ||
2572 | |||
2573 | /* we have to return the first page at _stext since the init code | ||
2574 | * in mm/init.c simply expects kernel_pg_dir there, the rest of | ||
2575 | * page is used for further ptr tables in get_ptr_table. | ||
2576 | */ | ||
2577 | lea %pc@(_stext),%a0 | ||
2578 | lea %pc@(L(mmu_cached_pointer_tables)),%a1 | ||
2579 | movel %a0,%a1@ | ||
2580 | addl #ROOT_TABLE_SIZE*4,%a1@ | ||
2581 | |||
2582 | lea %pc@(L(mmu_num_pointer_tables)),%a1 | ||
2583 | addql #1,%a1@ | ||
2584 | |||
2585 | /* clear the page | ||
2586 | */ | ||
2587 | movel %a0,%a1 | ||
2588 | movew #PAGESIZE/4-1,%d0 | ||
2589 | 1: | ||
2590 | clrl %a1@+ | ||
2591 | dbra %d0,1b | ||
2592 | |||
2593 | lea %pc@(L(kernel_pgdir_ptr)),%a1 | ||
2594 | movel %a0,%a1@ | ||
2595 | |||
2596 | dputn %a0 | ||
2597 | dputc '\n' | ||
2598 | 2: | ||
2599 | movel ARG1,%d0 | ||
2600 | lea %a0@(%d0*4),%a0 | ||
2601 | |||
2602 | #if 0 | ||
2603 | dputn %a0 | ||
2604 | dputc '\n' | ||
2605 | #endif | ||
2606 | |||
2607 | func_return mmu_get_root_table_entry | ||
2608 | |||
2609 | |||
2610 | |||
2611 | func_start mmu_get_ptr_table_entry,%d0/%a1 | ||
2612 | |||
2613 | #if 0 | ||
2614 | dputs "mmu_get_ptr_table_entry:" | ||
2615 | dputn ARG1 | ||
2616 | dputn ARG2 | ||
2617 | dputs " =" | ||
2618 | #endif | ||
2619 | |||
2620 | movel ARG1,%a0 | ||
2621 | movel %a0@,%d0 | ||
2622 | jne 2f | ||
2623 | |||
2624 | /* Keep track of the number of pointer tables we use | ||
2625 | */ | ||
2626 | dputs "\nmmu_get_new_ptr_table:" | ||
2627 | lea %pc@(L(mmu_num_pointer_tables)),%a0 | ||
2628 | movel %a0@,%d0 | ||
2629 | addql #1,%a0@ | ||
2630 | |||
2631 | /* See if there is a free pointer table in our cache of pointer tables | ||
2632 | */ | ||
2633 | lea %pc@(L(mmu_cached_pointer_tables)),%a1 | ||
2634 | andw #7,%d0 | ||
2635 | jne 1f | ||
2636 | |||
2637 | /* Get a new pointer table page from above the kernel memory | ||
2638 | */ | ||
2639 | get_new_page | ||
2640 | movel %a0,%a1@ | ||
2641 | 1: | ||
2642 | /* There is an unused pointer table in our cache... use it | ||
2643 | */ | ||
2644 | movel %a1@,%d0 | ||
2645 | addl #PTR_TABLE_SIZE*4,%a1@ | ||
2646 | |||
2647 | dputn %d0 | ||
2648 | dputc '\n' | ||
2649 | |||
2650 | /* Insert the new pointer table into the root table | ||
2651 | */ | ||
2652 | movel ARG1,%a0 | ||
2653 | orw #_PAGE_TABLE+_PAGE_ACCESSED,%d0 | ||
2654 | movel %d0,%a0@ | ||
2655 | 2: | ||
2656 | /* Extract the pointer table entry | ||
2657 | */ | ||
2658 | andw #-PTR_TABLE_SIZE,%d0 | ||
2659 | movel %d0,%a0 | ||
2660 | movel ARG2,%d0 | ||
2661 | lea %a0@(%d0*4),%a0 | ||
2662 | |||
2663 | #if 0 | ||
2664 | dputn %a0 | ||
2665 | dputc '\n' | ||
2666 | #endif | ||
2667 | |||
2668 | func_return mmu_get_ptr_table_entry | ||
2669 | |||
2670 | |||
2671 | func_start mmu_get_page_table_entry,%d0/%a1 | ||
2672 | |||
2673 | #if 0 | ||
2674 | dputs "mmu_get_page_table_entry:" | ||
2675 | dputn ARG1 | ||
2676 | dputn ARG2 | ||
2677 | dputs " =" | ||
2678 | #endif | ||
2679 | |||
2680 | movel ARG1,%a0 | ||
2681 | movel %a0@,%d0 | ||
2682 | jne 2f | ||
2683 | |||
2684 | /* If the page table entry doesn't exist, we allocate a complete new | ||
2685 | * page and use it as one continues big page table which can cover | ||
2686 | * 4MB of memory, nearly almost all mappings have that alignment. | ||
2687 | */ | ||
2688 | get_new_page | ||
2689 | addw #_PAGE_TABLE+_PAGE_ACCESSED,%a0 | ||
2690 | |||
2691 | /* align pointer table entry for a page of page tables | ||
2692 | */ | ||
2693 | movel ARG1,%d0 | ||
2694 | andw #-(PAGESIZE/PAGE_TABLE_SIZE),%d0 | ||
2695 | movel %d0,%a1 | ||
2696 | |||
2697 | /* Insert the page tables into the pointer entries | ||
2698 | */ | ||
2699 | moveq #PAGESIZE/PAGE_TABLE_SIZE/4-1,%d0 | ||
2700 | 1: | ||
2701 | movel %a0,%a1@+ | ||
2702 | lea %a0@(PAGE_TABLE_SIZE*4),%a0 | ||
2703 | dbra %d0,1b | ||
2704 | |||
2705 | /* Now we can get the initialized pointer table entry | ||
2706 | */ | ||
2707 | movel ARG1,%a0 | ||
2708 | movel %a0@,%d0 | ||
2709 | 2: | ||
2710 | /* Extract the page table entry | ||
2711 | */ | ||
2712 | andw #-PAGE_TABLE_SIZE,%d0 | ||
2713 | movel %d0,%a0 | ||
2714 | movel ARG2,%d0 | ||
2715 | lea %a0@(%d0*4),%a0 | ||
2716 | |||
2717 | #if 0 | ||
2718 | dputn %a0 | ||
2719 | dputc '\n' | ||
2720 | #endif | ||
2721 | |||
2722 | func_return mmu_get_page_table_entry | ||
2723 | |||
2724 | /* | ||
2725 | * get_new_page | ||
2726 | * | ||
2727 | * Return a new page from the memory start and clear it. | ||
2728 | */ | ||
2729 | func_start get_new_page,%d0/%a1 | ||
2730 | |||
2731 | dputs "\nget_new_page:" | ||
2732 | |||
2733 | /* allocate the page and adjust memory_start | ||
2734 | */ | ||
2735 | lea %pc@(L(memory_start)),%a0 | ||
2736 | movel %a0@,%a1 | ||
2737 | addl #PAGESIZE,%a0@ | ||
2738 | |||
2739 | /* clear the new page | ||
2740 | */ | ||
2741 | movel %a1,%a0 | ||
2742 | movew #PAGESIZE/4-1,%d0 | ||
2743 | 1: | ||
2744 | clrl %a1@+ | ||
2745 | dbra %d0,1b | ||
2746 | |||
2747 | dputn %a0 | ||
2748 | dputc '\n' | ||
2749 | |||
2750 | func_return get_new_page | ||
2751 | |||
2752 | |||
2753 | |||
2754 | /* | ||
2755 | * Debug output support | ||
2756 | * Atarians have a choice between the parallel port, the serial port | ||
2757 | * from the MFP or a serial port of the SCC | ||
2758 | */ | ||
2759 | |||
2760 | #ifdef CONFIG_MAC | ||
2761 | |||
2762 | L(scc_initable_mac): | ||
2763 | .byte 9,12 /* Reset */ | ||
2764 | .byte 4,0x44 /* x16, 1 stopbit, no parity */ | ||
2765 | .byte 3,0xc0 /* receiver: 8 bpc */ | ||
2766 | .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */ | ||
2767 | .byte 9,0 /* no interrupts */ | ||
2768 | .byte 10,0 /* NRZ */ | ||
2769 | .byte 11,0x50 /* use baud rate generator */ | ||
2770 | .byte 12,10,13,0 /* 9600 baud */ | ||
2771 | .byte 14,1 /* Baud rate generator enable */ | ||
2772 | .byte 3,0xc1 /* enable receiver */ | ||
2773 | .byte 5,0xea /* enable transmitter */ | ||
2774 | .byte -1 | ||
2775 | .even | ||
2776 | #endif | ||
2777 | |||
2778 | #ifdef CONFIG_ATARI | ||
2779 | /* #define USE_PRINTER */ | ||
2780 | /* #define USE_SCC_B */ | ||
2781 | /* #define USE_SCC_A */ | ||
2782 | #define USE_MFP | ||
2783 | |||
2784 | #if defined(USE_SCC_A) || defined(USE_SCC_B) | ||
2785 | #define USE_SCC | ||
2786 | /* Initialisation table for SCC */ | ||
2787 | L(scc_initable): | ||
2788 | .byte 9,12 /* Reset */ | ||
2789 | .byte 4,0x44 /* x16, 1 stopbit, no parity */ | ||
2790 | .byte 3,0xc0 /* receiver: 8 bpc */ | ||
2791 | .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */ | ||
2792 | .byte 9,0 /* no interrupts */ | ||
2793 | .byte 10,0 /* NRZ */ | ||
2794 | .byte 11,0x50 /* use baud rate generator */ | ||
2795 | .byte 12,24,13,0 /* 9600 baud */ | ||
2796 | .byte 14,2,14,3 /* use master clock for BRG, enable */ | ||
2797 | .byte 3,0xc1 /* enable receiver */ | ||
2798 | .byte 5,0xea /* enable transmitter */ | ||
2799 | .byte -1 | ||
2800 | .even | ||
2801 | #endif | ||
2802 | |||
2803 | #ifdef USE_PRINTER | ||
2804 | |||
2805 | LPSG_SELECT = 0xff8800 | ||
2806 | LPSG_READ = 0xff8800 | ||
2807 | LPSG_WRITE = 0xff8802 | ||
2808 | LPSG_IO_A = 14 | ||
2809 | LPSG_IO_B = 15 | ||
2810 | LPSG_CONTROL = 7 | ||
2811 | LSTMFP_GPIP = 0xfffa01 | ||
2812 | LSTMFP_DDR = 0xfffa05 | ||
2813 | LSTMFP_IERB = 0xfffa09 | ||
2814 | |||
2815 | #elif defined(USE_SCC_B) | ||
2816 | |||
2817 | LSCC_CTRL = 0xff8c85 | ||
2818 | LSCC_DATA = 0xff8c87 | ||
2819 | |||
2820 | #elif defined(USE_SCC_A) | ||
2821 | |||
2822 | LSCC_CTRL = 0xff8c81 | ||
2823 | LSCC_DATA = 0xff8c83 | ||
2824 | |||
2825 | #elif defined(USE_MFP) | ||
2826 | |||
2827 | LMFP_UCR = 0xfffa29 | ||
2828 | LMFP_TDCDR = 0xfffa1d | ||
2829 | LMFP_TDDR = 0xfffa25 | ||
2830 | LMFP_TSR = 0xfffa2d | ||
2831 | LMFP_UDR = 0xfffa2f | ||
2832 | |||
2833 | #endif | ||
2834 | #endif /* CONFIG_ATARI */ | ||
2835 | |||
2836 | /* | ||
2837 | * Serial port output support. | ||
2838 | */ | ||
2839 | |||
2840 | /* | ||
2841 | * Initialize serial port hardware for 9600/8/1 | ||
2842 | */ | ||
2843 | func_start serial_init,%d0/%d1/%a0/%a1 | ||
2844 | /* | ||
2845 | * Some of the register usage that follows | ||
2846 | * CONFIG_AMIGA | ||
2847 | * a0 = pointer to boot info record | ||
2848 | * d0 = boot info offset | ||
2849 | * CONFIG_ATARI | ||
2850 | * a0 = address of SCC | ||
2851 | * a1 = Liobase address/address of scc_initable | ||
2852 | * d0 = init data for serial port | ||
2853 | * CONFIG_MAC | ||
2854 | * a0 = address of SCC | ||
2855 | * a1 = address of scc_initable_mac | ||
2856 | * d0 = init data for serial port | ||
2857 | */ | ||
2858 | |||
2859 | #ifdef CONFIG_AMIGA | ||
2860 | #define SERIAL_DTR 7 | ||
2861 | #define SERIAL_CNTRL CIABBASE+C_PRA | ||
2862 | |||
2863 | is_not_amiga(1f) | ||
2864 | lea %pc@(L(custom)),%a0 | ||
2865 | movel #-ZTWOBASE,%a0@ | ||
2866 | bclr #SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE | ||
2867 | get_bi_record BI_AMIGA_SERPER | ||
2868 | movew %a0@,CUSTOMBASE+C_SERPER-ZTWOBASE | ||
2869 | | movew #61,CUSTOMBASE+C_SERPER-ZTWOBASE | ||
2870 | 1: | ||
2871 | #endif | ||
2872 | #ifdef CONFIG_ATARI | ||
2873 | is_not_atari(4f) | ||
2874 | movel %pc@(L(iobase)),%a1 | ||
2875 | #if defined(USE_PRINTER) | ||
2876 | bclr #0,%a1@(LSTMFP_IERB) | ||
2877 | bclr #0,%a1@(LSTMFP_DDR) | ||
2878 | moveb #LPSG_CONTROL,%a1@(LPSG_SELECT) | ||
2879 | moveb #0xff,%a1@(LPSG_WRITE) | ||
2880 | moveb #LPSG_IO_B,%a1@(LPSG_SELECT) | ||
2881 | clrb %a1@(LPSG_WRITE) | ||
2882 | moveb #LPSG_IO_A,%a1@(LPSG_SELECT) | ||
2883 | moveb %a1@(LPSG_READ),%d0 | ||
2884 | bset #5,%d0 | ||
2885 | moveb %d0,%a1@(LPSG_WRITE) | ||
2886 | #elif defined(USE_SCC) | ||
2887 | lea %a1@(LSCC_CTRL),%a0 | ||
2888 | lea %pc@(L(scc_initable)),%a1 | ||
2889 | 2: moveb %a1@+,%d0 | ||
2890 | jmi 3f | ||
2891 | moveb %d0,%a0@ | ||
2892 | moveb %a1@+,%a0@ | ||
2893 | jra 2b | ||
2894 | 3: clrb %a0@ | ||
2895 | #elif defined(USE_MFP) | ||
2896 | bclr #1,%a1@(LMFP_TSR) | ||
2897 | moveb #0x88,%a1@(LMFP_UCR) | ||
2898 | andb #0x70,%a1@(LMFP_TDCDR) | ||
2899 | moveb #2,%a1@(LMFP_TDDR) | ||
2900 | orb #1,%a1@(LMFP_TDCDR) | ||
2901 | bset #1,%a1@(LMFP_TSR) | ||
2902 | #endif | ||
2903 | jra L(serial_init_done) | ||
2904 | 4: | ||
2905 | #endif | ||
2906 | #ifdef CONFIG_MAC | ||
2907 | is_not_mac(L(serial_init_not_mac)) | ||
2908 | #ifdef MAC_SERIAL_DEBUG | ||
2909 | #if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B) | ||
2910 | #define MAC_USE_SCC_B | ||
2911 | #endif | ||
2912 | #define mac_scc_cha_b_ctrl_offset 0x0 | ||
2913 | #define mac_scc_cha_a_ctrl_offset 0x2 | ||
2914 | #define mac_scc_cha_b_data_offset 0x4 | ||
2915 | #define mac_scc_cha_a_data_offset 0x6 | ||
2916 | |||
2917 | #ifdef MAC_USE_SCC_A | ||
2918 | /* Initialize channel A */ | ||
2919 | movel %pc@(L(mac_sccbase)),%a0 | ||
2920 | lea %pc@(L(scc_initable_mac)),%a1 | ||
2921 | 5: moveb %a1@+,%d0 | ||
2922 | jmi 6f | ||
2923 | moveb %d0,%a0@(mac_scc_cha_a_ctrl_offset) | ||
2924 | moveb %a1@+,%a0@(mac_scc_cha_a_ctrl_offset) | ||
2925 | jra 5b | ||
2926 | 6: | ||
2927 | #endif /* MAC_USE_SCC_A */ | ||
2928 | |||
2929 | #ifdef MAC_USE_SCC_B | ||
2930 | /* Initialize channel B */ | ||
2931 | #ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */ | ||
2932 | movel %pc@(L(mac_sccbase)),%a0 | ||
2933 | #endif /* MAC_USE_SCC_A */ | ||
2934 | lea %pc@(L(scc_initable_mac)),%a1 | ||
2935 | 7: moveb %a1@+,%d0 | ||
2936 | jmi 8f | ||
2937 | moveb %d0,%a0@(mac_scc_cha_b_ctrl_offset) | ||
2938 | moveb %a1@+,%a0@(mac_scc_cha_b_ctrl_offset) | ||
2939 | jra 7b | ||
2940 | 8: | ||
2941 | #endif /* MAC_USE_SCC_B */ | ||
2942 | #endif /* MAC_SERIAL_DEBUG */ | ||
2943 | |||
2944 | jra L(serial_init_done) | ||
2945 | L(serial_init_not_mac): | ||
2946 | #endif /* CONFIG_MAC */ | ||
2947 | |||
2948 | #ifdef CONFIG_Q40 | ||
2949 | is_not_q40(2f) | ||
2950 | /* debug output goes into SRAM, so we don't do it unless requested | ||
2951 | - check for '%LX$' signature in SRAM */ | ||
2952 | lea %pc@(q40_mem_cptr),%a1 | ||
2953 | move.l #0xff020010,%a1@ /* must be inited - also used by debug=mem */ | ||
2954 | move.l #0xff020000,%a1 | ||
2955 | cmp.b #'%',%a1@ | ||
2956 | bne 2f /*nodbg*/ | ||
2957 | addq.w #4,%a1 | ||
2958 | cmp.b #'L',%a1@ | ||
2959 | bne 2f /*nodbg*/ | ||
2960 | addq.w #4,%a1 | ||
2961 | cmp.b #'X',%a1@ | ||
2962 | bne 2f /*nodbg*/ | ||
2963 | addq.w #4,%a1 | ||
2964 | cmp.b #'$',%a1@ | ||
2965 | bne 2f /*nodbg*/ | ||
2966 | /* signature OK */ | ||
2967 | lea %pc@(L(q40_do_debug)),%a1 | ||
2968 | tas %a1@ | ||
2969 | /*nodbg: q40_do_debug is 0 by default*/ | ||
2970 | 2: | ||
2971 | #endif | ||
2972 | |||
2973 | #ifdef CONFIG_APOLLO | ||
2974 | /* We count on the PROM initializing SIO1 */ | ||
2975 | #endif | ||
2976 | |||
2977 | #ifdef CONFIG_HP300 | ||
2978 | /* We count on the boot loader initialising the UART */ | ||
2979 | #endif | ||
2980 | |||
2981 | L(serial_init_done): | ||
2982 | func_return serial_init | ||
2983 | |||
2984 | /* | ||
2985 | * Output character on serial port. | ||
2986 | */ | ||
2987 | func_start serial_putc,%d0/%d1/%a0/%a1 | ||
2988 | |||
2989 | movel ARG1,%d0 | ||
2990 | cmpib #'\n',%d0 | ||
2991 | jbne 1f | ||
2992 | |||
2993 | /* A little safe recursion is good for the soul */ | ||
2994 | serial_putc #'\r' | ||
2995 | 1: | ||
2996 | |||
2997 | #ifdef CONFIG_AMIGA | ||
2998 | is_not_amiga(2f) | ||
2999 | andw #0x00ff,%d0 | ||
3000 | oriw #0x0100,%d0 | ||
3001 | movel %pc@(L(custom)),%a0 | ||
3002 | movew %d0,%a0@(CUSTOMBASE+C_SERDAT) | ||
3003 | 1: movew %a0@(CUSTOMBASE+C_SERDATR),%d0 | ||
3004 | andw #0x2000,%d0 | ||
3005 | jeq 1b | ||
3006 | jra L(serial_putc_done) | ||
3007 | 2: | ||
3008 | #endif | ||
3009 | |||
3010 | #ifdef CONFIG_MAC | ||
3011 | is_not_mac(5f) | ||
3012 | |||
3013 | #ifdef MAC_SERIAL_DEBUG | ||
3014 | |||
3015 | #ifdef MAC_USE_SCC_A | ||
3016 | movel %pc@(L(mac_sccbase)),%a1 | ||
3017 | 3: btst #2,%a1@(mac_scc_cha_a_ctrl_offset) | ||
3018 | jeq 3b | ||
3019 | moveb %d0,%a1@(mac_scc_cha_a_data_offset) | ||
3020 | #endif /* MAC_USE_SCC_A */ | ||
3021 | |||
3022 | #ifdef MAC_USE_SCC_B | ||
3023 | #ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */ | ||
3024 | movel %pc@(L(mac_sccbase)),%a1 | ||
3025 | #endif /* MAC_USE_SCC_A */ | ||
3026 | 4: btst #2,%a1@(mac_scc_cha_b_ctrl_offset) | ||
3027 | jeq 4b | ||
3028 | moveb %d0,%a1@(mac_scc_cha_b_data_offset) | ||
3029 | #endif /* MAC_USE_SCC_B */ | ||
3030 | |||
3031 | #endif /* MAC_SERIAL_DEBUG */ | ||
3032 | |||
3033 | jra L(serial_putc_done) | ||
3034 | 5: | ||
3035 | #endif /* CONFIG_MAC */ | ||
3036 | |||
3037 | #ifdef CONFIG_ATARI | ||
3038 | is_not_atari(4f) | ||
3039 | movel %pc@(L(iobase)),%a1 | ||
3040 | #if defined(USE_PRINTER) | ||
3041 | 3: btst #0,%a1@(LSTMFP_GPIP) | ||
3042 | jne 3b | ||
3043 | moveb #LPSG_IO_B,%a1@(LPSG_SELECT) | ||
3044 | moveb %d0,%a1@(LPSG_WRITE) | ||
3045 | moveb #LPSG_IO_A,%a1@(LPSG_SELECT) | ||
3046 | moveb %a1@(LPSG_READ),%d0 | ||
3047 | bclr #5,%d0 | ||
3048 | moveb %d0,%a1@(LPSG_WRITE) | ||
3049 | nop | ||
3050 | nop | ||
3051 | bset #5,%d0 | ||
3052 | moveb %d0,%a1@(LPSG_WRITE) | ||
3053 | #elif defined(USE_SCC) | ||
3054 | 3: btst #2,%a1@(LSCC_CTRL) | ||
3055 | jeq 3b | ||
3056 | moveb %d0,%a1@(LSCC_DATA) | ||
3057 | #elif defined(USE_MFP) | ||
3058 | 3: btst #7,%a1@(LMFP_TSR) | ||
3059 | jeq 3b | ||
3060 | moveb %d0,%a1@(LMFP_UDR) | ||
3061 | #endif | ||
3062 | jra L(serial_putc_done) | ||
3063 | 4: | ||
3064 | #endif /* CONFIG_ATARI */ | ||
3065 | |||
3066 | #ifdef CONFIG_MVME147 | ||
3067 | is_not_mvme147(2f) | ||
3068 | 1: btst #2,M147_SCC_CTRL_A | ||
3069 | jeq 1b | ||
3070 | moveb %d0,M147_SCC_DATA_A | ||
3071 | jbra L(serial_putc_done) | ||
3072 | 2: | ||
3073 | #endif | ||
3074 | |||
3075 | #ifdef CONFIG_MVME16x | ||
3076 | is_not_mvme16x(2f) | ||
3077 | /* | ||
3078 | * If the loader gave us a board type then we can use that to | ||
3079 | * select an appropriate output routine; otherwise we just use | ||
3080 | * the Bug code. If we haev to use the Bug that means the Bug | ||
3081 | * workspace has to be valid, which means the Bug has to use | ||
3082 | * the SRAM, which is non-standard. | ||
3083 | */ | ||
3084 | moveml %d0-%d7/%a2-%a6,%sp@- | ||
3085 | movel vme_brdtype,%d1 | ||
3086 | jeq 1f | No tag - use the Bug | ||
3087 | cmpi #VME_TYPE_MVME162,%d1 | ||
3088 | jeq 6f | ||
3089 | cmpi #VME_TYPE_MVME172,%d1 | ||
3090 | jne 5f | ||
3091 | /* 162/172; it's an SCC */ | ||
3092 | 6: btst #2,M162_SCC_CTRL_A | ||
3093 | nop | ||
3094 | nop | ||
3095 | nop | ||
3096 | jeq 6b | ||
3097 | moveb #8,M162_SCC_CTRL_A | ||
3098 | nop | ||
3099 | nop | ||
3100 | nop | ||
3101 | moveb %d0,M162_SCC_CTRL_A | ||
3102 | jra 3f | ||
3103 | 5: | ||
3104 | /* 166/167/177; it's a CD2401 */ | ||
3105 | moveb #0,M167_CYCAR | ||
3106 | moveb M167_CYIER,%d2 | ||
3107 | moveb #0x02,M167_CYIER | ||
3108 | 7: | ||
3109 | btst #5,M167_PCSCCTICR | ||
3110 | jeq 7b | ||
3111 | moveb M167_PCTPIACKR,%d1 | ||
3112 | moveb M167_CYLICR,%d1 | ||
3113 | jeq 8f | ||
3114 | moveb #0x08,M167_CYTEOIR | ||
3115 | jra 7b | ||
3116 | 8: | ||
3117 | moveb %d0,M167_CYTDR | ||
3118 | moveb #0,M167_CYTEOIR | ||
3119 | moveb %d2,M167_CYIER | ||
3120 | jra 3f | ||
3121 | 1: | ||
3122 | moveb %d0,%sp@- | ||
3123 | trap #15 | ||
3124 | .word 0x0020 /* TRAP 0x020 */ | ||
3125 | 3: | ||
3126 | moveml %sp@+,%d0-%d7/%a2-%a6 | ||
3127 | jbra L(serial_putc_done) | ||
3128 | 2: | ||
3129 | #endif /* CONFIG_MVME16x */ | ||
3130 | |||
3131 | #ifdef CONFIG_BVME6000 | ||
3132 | is_not_bvme6000(2f) | ||
3133 | /* | ||
3134 | * The BVME6000 machine has a serial port ... | ||
3135 | */ | ||
3136 | 1: btst #2,BVME_SCC_CTRL_A | ||
3137 | jeq 1b | ||
3138 | moveb %d0,BVME_SCC_DATA_A | ||
3139 | jbra L(serial_putc_done) | ||
3140 | 2: | ||
3141 | #endif | ||
3142 | |||
3143 | #ifdef CONFIG_SUN3X | ||
3144 | is_not_sun3x(2f) | ||
3145 | movel %d0,-(%sp) | ||
3146 | movel 0xFEFE0018,%a1 | ||
3147 | jbsr (%a1) | ||
3148 | addq #4,%sp | ||
3149 | jbra L(serial_putc_done) | ||
3150 | 2: | ||
3151 | #endif | ||
3152 | |||
3153 | #ifdef CONFIG_Q40 | ||
3154 | is_not_q40(2f) | ||
3155 | tst.l %pc@(L(q40_do_debug)) /* only debug if requested */ | ||
3156 | beq 2f | ||
3157 | lea %pc@(q40_mem_cptr),%a1 | ||
3158 | move.l %a1@,%a0 | ||
3159 | move.b %d0,%a0@ | ||
3160 | addq.l #4,%a0 | ||
3161 | move.l %a0,%a1@ | ||
3162 | jbra L(serial_putc_done) | ||
3163 | 2: | ||
3164 | #endif | ||
3165 | |||
3166 | #ifdef CONFIG_APOLLO | ||
3167 | is_not_apollo(2f) | ||
3168 | movl %pc@(L(iobase)),%a1 | ||
3169 | moveb %d0,%a1@(LTHRB0) | ||
3170 | 1: moveb %a1@(LSRB0),%d0 | ||
3171 | andb #0x4,%d0 | ||
3172 | beq 1b | ||
3173 | jbra L(serial_putc_done) | ||
3174 | 2: | ||
3175 | #endif | ||
3176 | |||
3177 | #ifdef CONFIG_HP300 | ||
3178 | is_not_hp300(3f) | ||
3179 | movl %pc@(L(iobase)),%a1 | ||
3180 | addl %pc@(L(uartbase)),%a1 | ||
3181 | movel %pc@(L(uart_scode)),%d1 /* Check the scode */ | ||
3182 | jmi 3f /* Unset? Exit */ | ||
3183 | cmpi #256,%d1 /* APCI scode? */ | ||
3184 | jeq 2f | ||
3185 | 1: moveb %a1@(DCALSR),%d1 /* Output to DCA */ | ||
3186 | andb #0x20,%d1 | ||
3187 | beq 1b | ||
3188 | moveb %d0,%a1@(DCADATA) | ||
3189 | jbra L(serial_putc_done) | ||
3190 | 2: moveb %a1@(APCILSR),%d1 /* Output to APCI */ | ||
3191 | andb #0x20,%d1 | ||
3192 | beq 2b | ||
3193 | moveb %d0,%a1@(APCIDATA) | ||
3194 | jbra L(serial_putc_done) | ||
3195 | 3: | ||
3196 | #endif | ||
3197 | |||
3198 | L(serial_putc_done): | ||
3199 | func_return serial_putc | ||
3200 | |||
3201 | /* | ||
3202 | * Output a string. | ||
3203 | */ | ||
3204 | func_start puts,%d0/%a0 | ||
3205 | |||
3206 | movel ARG1,%a0 | ||
3207 | jra 2f | ||
3208 | 1: | ||
3209 | #ifdef CONSOLE | ||
3210 | console_putc %d0 | ||
3211 | #endif | ||
3212 | #ifdef SERIAL_DEBUG | ||
3213 | serial_putc %d0 | ||
3214 | #endif | ||
3215 | 2: moveb %a0@+,%d0 | ||
3216 | jne 1b | ||
3217 | |||
3218 | func_return puts | ||
3219 | |||
3220 | /* | ||
3221 | * Output number in hex notation. | ||
3222 | */ | ||
3223 | |||
3224 | func_start putn,%d0-%d2 | ||
3225 | |||
3226 | putc ' ' | ||
3227 | |||
3228 | movel ARG1,%d0 | ||
3229 | moveq #7,%d1 | ||
3230 | 1: roll #4,%d0 | ||
3231 | move %d0,%d2 | ||
3232 | andb #0x0f,%d2 | ||
3233 | addb #'0',%d2 | ||
3234 | cmpb #'9',%d2 | ||
3235 | jls 2f | ||
3236 | addb #'A'-('9'+1),%d2 | ||
3237 | 2: | ||
3238 | #ifdef CONSOLE | ||
3239 | console_putc %d2 | ||
3240 | #endif | ||
3241 | #ifdef SERIAL_DEBUG | ||
3242 | serial_putc %d2 | ||
3243 | #endif | ||
3244 | dbra %d1,1b | ||
3245 | |||
3246 | func_return putn | ||
3247 | |||
3248 | #ifdef CONFIG_MAC | ||
3249 | /* | ||
3250 | * mac_serial_print | ||
3251 | * | ||
3252 | * This routine takes its parameters on the stack. It then | ||
3253 | * turns around and calls the internal routine. This routine | ||
3254 | * is used until the Linux console driver initializes itself. | ||
3255 | * | ||
3256 | * The calling parameters are: | ||
3257 | * void mac_serial_print(const char *str); | ||
3258 | * | ||
3259 | * This routine does NOT understand variable arguments only | ||
3260 | * simple strings! | ||
3261 | */ | ||
3262 | ENTRY(mac_serial_print) | ||
3263 | moveml %d0/%a0,%sp@- | ||
3264 | #if 1 | ||
3265 | move %sr,%sp@- | ||
3266 | ori #0x0700,%sr | ||
3267 | #endif | ||
3268 | movel %sp@(10),%a0 /* fetch parameter */ | ||
3269 | jra 2f | ||
3270 | 1: serial_putc %d0 | ||
3271 | 2: moveb %a0@+,%d0 | ||
3272 | jne 1b | ||
3273 | #if 1 | ||
3274 | move %sp@+,%sr | ||
3275 | #endif | ||
3276 | moveml %sp@+,%d0/%a0 | ||
3277 | rts | ||
3278 | #endif /* CONFIG_MAC */ | ||
3279 | |||
3280 | #if defined(CONFIG_HP300) || defined(CONFIG_APOLLO) | ||
3281 | func_start set_leds,%d0/%a0 | ||
3282 | movel ARG1,%d0 | ||
3283 | #ifdef CONFIG_HP300 | ||
3284 | is_not_hp300(1f) | ||
3285 | movel %pc@(L(iobase)),%a0 | ||
3286 | moveb %d0,%a0@(0x1ffff) | ||
3287 | jra 2f | ||
3288 | #endif | ||
3289 | 1: | ||
3290 | #ifdef CONFIG_APOLLO | ||
3291 | movel %pc@(L(iobase)),%a0 | ||
3292 | lsll #8,%d0 | ||
3293 | eorw #0xff00,%d0 | ||
3294 | moveb %d0,%a0@(LCPUCTRL) | ||
3295 | #endif | ||
3296 | 2: | ||
3297 | func_return set_leds | ||
3298 | #endif | ||
3299 | |||
3300 | #ifdef CONSOLE | ||
3301 | /* | ||
3302 | * For continuity, see the data alignment | ||
3303 | * to which this structure is tied. | ||
3304 | */ | ||
3305 | #define Lconsole_struct_cur_column 0 | ||
3306 | #define Lconsole_struct_cur_row 4 | ||
3307 | #define Lconsole_struct_num_columns 8 | ||
3308 | #define Lconsole_struct_num_rows 12 | ||
3309 | #define Lconsole_struct_left_edge 16 | ||
3310 | #define Lconsole_struct_penguin_putc 20 | ||
3311 | |||
3312 | func_start console_init,%a0-%a4/%d0-%d7 | ||
3313 | /* | ||
3314 | * Some of the register usage that follows | ||
3315 | * a0 = pointer to boot_info | ||
3316 | * a1 = pointer to screen | ||
3317 | * a2 = pointer to Lconsole_globals | ||
3318 | * d3 = pixel width of screen | ||
3319 | * d4 = pixel height of screen | ||
3320 | * (d3,d4) ~= (x,y) of a point just below | ||
3321 | * and to the right of the screen | ||
3322 | * NOT on the screen! | ||
3323 | * d5 = number of bytes per scan line | ||
3324 | * d6 = number of bytes on the entire screen | ||
3325 | */ | ||
3326 | |||
3327 | lea %pc@(L(console_globals)),%a2 | ||
3328 | movel %pc@(L(mac_videobase)),%a1 | ||
3329 | movel %pc@(L(mac_rowbytes)),%d5 | ||
3330 | movel %pc@(L(mac_dimensions)),%d3 /* -> low byte */ | ||
3331 | movel %d3,%d4 | ||
3332 | swap %d4 /* -> high byte */ | ||
3333 | andl #0xffff,%d3 /* d3 = screen width in pixels */ | ||
3334 | andl #0xffff,%d4 /* d4 = screen height in pixels */ | ||
3335 | |||
3336 | movel %d5,%d6 | ||
3337 | | subl #20,%d6 | ||
3338 | mulul %d4,%d6 /* scan line bytes x num scan lines */ | ||
3339 | divul #8,%d6 /* we'll clear 8 bytes at a time */ | ||
3340 | moveq #-1,%d0 /* Mac_black */ | ||
3341 | subq #1,%d6 | ||
3342 | |||
3343 | L(console_clear_loop): | ||
3344 | movel %d0,%a1@+ | ||
3345 | movel %d0,%a1@+ | ||
3346 | dbra %d6,L(console_clear_loop) | ||
3347 | |||
3348 | /* Calculate font size */ | ||
3349 | |||
3350 | #if defined(FONT_8x8) && defined(CONFIG_FONT_8x8) | ||
3351 | lea %pc@(font_vga_8x8),%a0 | ||
3352 | #elif defined(FONT_8x16) && defined(CONFIG_FONT_8x16) | ||
3353 | lea %pc@(font_vga_8x16),%a0 | ||
3354 | #elif defined(FONT_6x11) && defined(CONFIG_FONT_6x11) | ||
3355 | lea %pc@(font_vga_6x11),%a0 | ||
3356 | #elif defined(CONFIG_FONT_8x8) /* default */ | ||
3357 | lea %pc@(font_vga_8x8),%a0 | ||
3358 | #else /* no compiled-in font */ | ||
3359 | lea 0,%a0 | ||
3360 | #endif | ||
3361 | |||
3362 | /* | ||
3363 | * At this point we make a shift in register usage | ||
3364 | * a1 = address of console_font pointer | ||
3365 | */ | ||
3366 | lea %pc@(L(console_font)),%a1 | ||
3367 | movel %a0,%a1@ /* store pointer to struct fbcon_font_desc in console_font */ | ||
3368 | tstl %a0 | ||
3369 | jeq 1f | ||
3370 | lea %pc@(L(console_font_data)),%a4 | ||
3371 | movel %a0@(FONT_DESC_DATA),%d0 | ||
3372 | subl #L(console_font),%a1 | ||
3373 | addl %a1,%d0 | ||
3374 | movel %d0,%a4@ | ||
3375 | |||
3376 | /* | ||
3377 | * Calculate global maxs | ||
3378 | * Note - we can use either an | ||
3379 | * 8 x 16 or 8 x 8 character font | ||
3380 | * 6 x 11 also supported | ||
3381 | */ | ||
3382 | /* ASSERT: a0 = contents of Lconsole_font */ | ||
3383 | movel %d3,%d0 /* screen width in pixels */ | ||
3384 | divul %a0@(FONT_DESC_WIDTH),%d0 /* d0 = max num chars per row */ | ||
3385 | |||
3386 | movel %d4,%d1 /* screen height in pixels */ | ||
3387 | divul %a0@(FONT_DESC_HEIGHT),%d1 /* d1 = max num rows */ | ||
3388 | |||
3389 | movel %d0,%a2@(Lconsole_struct_num_columns) | ||
3390 | movel %d1,%a2@(Lconsole_struct_num_rows) | ||
3391 | |||
3392 | /* | ||
3393 | * Clear the current row and column | ||
3394 | */ | ||
3395 | clrl %a2@(Lconsole_struct_cur_column) | ||
3396 | clrl %a2@(Lconsole_struct_cur_row) | ||
3397 | clrl %a2@(Lconsole_struct_left_edge) | ||
3398 | |||
3399 | /* | ||
3400 | * Initialization is complete | ||
3401 | */ | ||
3402 | 1: | ||
3403 | func_return console_init | ||
3404 | |||
3405 | func_start console_put_stats,%a0/%d7 | ||
3406 | /* | ||
3407 | * Some of the register usage that follows | ||
3408 | * a0 = pointer to boot_info | ||
3409 | * d7 = value of boot_info fields | ||
3410 | */ | ||
3411 | puts "\nMacLinux\n\n" | ||
3412 | |||
3413 | #ifdef SERIAL_DEBUG | ||
3414 | puts " vidaddr:" | ||
3415 | putn %pc@(L(mac_videobase)) /* video addr. */ | ||
3416 | |||
3417 | puts "\n _stext:" | ||
3418 | lea %pc@(_stext),%a0 | ||
3419 | putn %a0 | ||
3420 | |||
3421 | puts "\nbootinfo:" | ||
3422 | lea %pc@(_end),%a0 | ||
3423 | putn %a0 | ||
3424 | |||
3425 | puts "\ncpuid:" | ||
3426 | putn %pc@(L(cputype)) | ||
3427 | putc '\n' | ||
3428 | |||
3429 | #ifdef MAC_SERIAL_DEBUG | ||
3430 | putn %pc@(L(mac_sccbase)) | ||
3431 | putc '\n' | ||
3432 | #endif | ||
3433 | # if defined(MMU_PRINT) | ||
3434 | jbsr mmu_print_machine_cpu_types | ||
3435 | # endif /* MMU_PRINT */ | ||
3436 | #endif /* SERIAL_DEBUG */ | ||
3437 | |||
3438 | func_return console_put_stats | ||
3439 | |||
3440 | #ifdef CONSOLE_PENGUIN | ||
3441 | func_start console_put_penguin,%a0-%a1/%d0-%d7 | ||
3442 | /* | ||
3443 | * Get 'that_penguin' onto the screen in the upper right corner | ||
3444 | * penguin is 64 x 74 pixels, align against right edge of screen | ||
3445 | */ | ||
3446 | lea %pc@(L(mac_dimensions)),%a0 | ||
3447 | movel %a0@,%d0 | ||
3448 | andil #0xffff,%d0 | ||
3449 | subil #64,%d0 /* snug up against the right edge */ | ||
3450 | clrl %d1 /* start at the top */ | ||
3451 | movel #73,%d7 | ||
3452 | lea %pc@(L(that_penguin)),%a1 | ||
3453 | L(console_penguin_row): | ||
3454 | movel #31,%d6 | ||
3455 | L(console_penguin_pixel_pair): | ||
3456 | moveb %a1@,%d2 | ||
3457 | lsrb #4,%d2 | ||
3458 | console_plot_pixel %d0,%d1,%d2 | ||
3459 | addq #1,%d0 | ||
3460 | moveb %a1@+,%d2 | ||
3461 | console_plot_pixel %d0,%d1,%d2 | ||
3462 | addq #1,%d0 | ||
3463 | dbra %d6,L(console_penguin_pixel_pair) | ||
3464 | |||
3465 | subil #64,%d0 | ||
3466 | addq #1,%d1 | ||
3467 | dbra %d7,L(console_penguin_row) | ||
3468 | |||
3469 | func_return console_put_penguin | ||
3470 | |||
3471 | /* include penguin bitmap */ | ||
3472 | L(that_penguin): | ||
3473 | #include "../mac/mac_penguin.S" | ||
3474 | #endif | ||
3475 | |||
3476 | /* | ||
3477 | * Calculate source and destination addresses | ||
3478 | * output a1 = dest | ||
3479 | * a2 = source | ||
3480 | */ | ||
3481 | |||
3482 | func_start console_scroll,%a0-%a4/%d0-%d7 | ||
3483 | lea %pc@(L(mac_videobase)),%a0 | ||
3484 | movel %a0@,%a1 | ||
3485 | movel %a1,%a2 | ||
3486 | lea %pc@(L(mac_rowbytes)),%a0 | ||
3487 | movel %a0@,%d5 | ||
3488 | movel %pc@(L(console_font)),%a0 | ||
3489 | tstl %a0 | ||
3490 | jeq 1f | ||
3491 | mulul %a0@(FONT_DESC_HEIGHT),%d5 /* account for # scan lines per character */ | ||
3492 | addal %d5,%a2 | ||
3493 | |||
3494 | /* | ||
3495 | * Get dimensions | ||
3496 | */ | ||
3497 | lea %pc@(L(mac_dimensions)),%a0 | ||
3498 | movel %a0@,%d3 | ||
3499 | movel %d3,%d4 | ||
3500 | swap %d4 | ||
3501 | andl #0xffff,%d3 /* d3 = screen width in pixels */ | ||
3502 | andl #0xffff,%d4 /* d4 = screen height in pixels */ | ||
3503 | |||
3504 | /* | ||
3505 | * Calculate number of bytes to move | ||
3506 | */ | ||
3507 | lea %pc@(L(mac_rowbytes)),%a0 | ||
3508 | movel %a0@,%d6 | ||
3509 | movel %pc@(L(console_font)),%a0 | ||
3510 | subl %a0@(FONT_DESC_HEIGHT),%d4 /* we're not scrolling the top row! */ | ||
3511 | mulul %d4,%d6 /* scan line bytes x num scan lines */ | ||
3512 | divul #32,%d6 /* we'll move 8 longs at a time */ | ||
3513 | subq #1,%d6 | ||
3514 | |||
3515 | L(console_scroll_loop): | ||
3516 | movel %a2@+,%a1@+ | ||
3517 | movel %a2@+,%a1@+ | ||
3518 | movel %a2@+,%a1@+ | ||
3519 | movel %a2@+,%a1@+ | ||
3520 | movel %a2@+,%a1@+ | ||
3521 | movel %a2@+,%a1@+ | ||
3522 | movel %a2@+,%a1@+ | ||
3523 | movel %a2@+,%a1@+ | ||
3524 | dbra %d6,L(console_scroll_loop) | ||
3525 | |||
3526 | lea %pc@(L(mac_rowbytes)),%a0 | ||
3527 | movel %a0@,%d6 | ||
3528 | movel %pc@(L(console_font)),%a0 | ||
3529 | mulul %a0@(FONT_DESC_HEIGHT),%d6 /* scan line bytes x font height */ | ||
3530 | divul #32,%d6 /* we'll move 8 words at a time */ | ||
3531 | subq #1,%d6 | ||
3532 | |||
3533 | moveq #-1,%d0 | ||
3534 | L(console_scroll_clear_loop): | ||
3535 | movel %d0,%a1@+ | ||
3536 | movel %d0,%a1@+ | ||
3537 | movel %d0,%a1@+ | ||
3538 | movel %d0,%a1@+ | ||
3539 | movel %d0,%a1@+ | ||
3540 | movel %d0,%a1@+ | ||
3541 | movel %d0,%a1@+ | ||
3542 | movel %d0,%a1@+ | ||
3543 | dbra %d6,L(console_scroll_clear_loop) | ||
3544 | |||
3545 | 1: | ||
3546 | func_return console_scroll | ||
3547 | |||
3548 | |||
3549 | func_start console_putc,%a0/%a1/%d0-%d7 | ||
3550 | |||
3551 | is_not_mac(L(console_exit)) | ||
3552 | tstl %pc@(L(console_font)) | ||
3553 | jeq L(console_exit) | ||
3554 | |||
3555 | /* Output character in d7 on console. | ||
3556 | */ | ||
3557 | movel ARG1,%d7 | ||
3558 | cmpib #'\n',%d7 | ||
3559 | jbne 1f | ||
3560 | |||
3561 | /* A little safe recursion is good for the soul */ | ||
3562 | console_putc #'\r' | ||
3563 | 1: | ||
3564 | lea %pc@(L(console_globals)),%a0 | ||
3565 | |||
3566 | cmpib #10,%d7 | ||
3567 | jne L(console_not_lf) | ||
3568 | movel %a0@(Lconsole_struct_cur_row),%d0 | ||
3569 | addil #1,%d0 | ||
3570 | movel %d0,%a0@(Lconsole_struct_cur_row) | ||
3571 | movel %a0@(Lconsole_struct_num_rows),%d1 | ||
3572 | cmpl %d1,%d0 | ||
3573 | jcs 1f | ||
3574 | subil #1,%d0 | ||
3575 | movel %d0,%a0@(Lconsole_struct_cur_row) | ||
3576 | console_scroll | ||
3577 | 1: | ||
3578 | jra L(console_exit) | ||
3579 | |||
3580 | L(console_not_lf): | ||
3581 | cmpib #13,%d7 | ||
3582 | jne L(console_not_cr) | ||
3583 | clrl %a0@(Lconsole_struct_cur_column) | ||
3584 | jra L(console_exit) | ||
3585 | |||
3586 | L(console_not_cr): | ||
3587 | cmpib #1,%d7 | ||
3588 | jne L(console_not_home) | ||
3589 | clrl %a0@(Lconsole_struct_cur_row) | ||
3590 | clrl %a0@(Lconsole_struct_cur_column) | ||
3591 | jra L(console_exit) | ||
3592 | |||
3593 | /* | ||
3594 | * At this point we know that the %d7 character is going to be | ||
3595 | * rendered on the screen. Register usage is - | ||
3596 | * a0 = pointer to console globals | ||
3597 | * a1 = font data | ||
3598 | * d0 = cursor column | ||
3599 | * d1 = cursor row to draw the character | ||
3600 | * d7 = character number | ||
3601 | */ | ||
3602 | L(console_not_home): | ||
3603 | movel %a0@(Lconsole_struct_cur_column),%d0 | ||
3604 | addql #1,%a0@(Lconsole_struct_cur_column) | ||
3605 | movel %a0@(Lconsole_struct_num_columns),%d1 | ||
3606 | cmpl %d1,%d0 | ||
3607 | jcs 1f | ||
3608 | console_putc #'\n' /* recursion is OK! */ | ||
3609 | 1: | ||
3610 | movel %a0@(Lconsole_struct_cur_row),%d1 | ||
3611 | |||
3612 | /* | ||
3613 | * At this point we make a shift in register usage | ||
3614 | * a0 = address of pointer to font data (fbcon_font_desc) | ||
3615 | */ | ||
3616 | movel %pc@(L(console_font)),%a0 | ||
3617 | movel %pc@(L(console_font_data)),%a1 /* Load fbcon_font_desc.data into a1 */ | ||
3618 | andl #0x000000ff,%d7 | ||
3619 | /* ASSERT: a0 = contents of Lconsole_font */ | ||
3620 | mulul %a0@(FONT_DESC_HEIGHT),%d7 /* d7 = index into font data */ | ||
3621 | addl %d7,%a1 /* a1 = points to char image */ | ||
3622 | |||
3623 | /* | ||
3624 | * At this point we make a shift in register usage | ||
3625 | * d0 = pixel coordinate, x | ||
3626 | * d1 = pixel coordinate, y | ||
3627 | * d2 = (bit 0) 1/0 for white/black (!) pixel on screen | ||
3628 | * d3 = font scan line data (8 pixels) | ||
3629 | * d6 = count down for the font's pixel width (8) | ||
3630 | * d7 = count down for the font's pixel count in height | ||
3631 | */ | ||
3632 | /* ASSERT: a0 = contents of Lconsole_font */ | ||
3633 | mulul %a0@(FONT_DESC_WIDTH),%d0 | ||
3634 | mulul %a0@(FONT_DESC_HEIGHT),%d1 | ||
3635 | movel %a0@(FONT_DESC_HEIGHT),%d7 /* Load fbcon_font_desc.height into d7 */ | ||
3636 | subq #1,%d7 | ||
3637 | L(console_read_char_scanline): | ||
3638 | moveb %a1@+,%d3 | ||
3639 | |||
3640 | /* ASSERT: a0 = contents of Lconsole_font */ | ||
3641 | movel %a0@(FONT_DESC_WIDTH),%d6 /* Load fbcon_font_desc.width into d6 */ | ||
3642 | subql #1,%d6 | ||
3643 | |||
3644 | L(console_do_font_scanline): | ||
3645 | lslb #1,%d3 | ||
3646 | scsb %d2 /* convert 1 bit into a byte */ | ||
3647 | console_plot_pixel %d0,%d1,%d2 | ||
3648 | addq #1,%d0 | ||
3649 | dbra %d6,L(console_do_font_scanline) | ||
3650 | |||
3651 | /* ASSERT: a0 = contents of Lconsole_font */ | ||
3652 | subl %a0@(FONT_DESC_WIDTH),%d0 | ||
3653 | addq #1,%d1 | ||
3654 | dbra %d7,L(console_read_char_scanline) | ||
3655 | |||
3656 | L(console_exit): | ||
3657 | func_return console_putc | ||
3658 | |||
3659 | /* | ||
3660 | * Input: | ||
3661 | * d0 = x coordinate | ||
3662 | * d1 = y coordinate | ||
3663 | * d2 = (bit 0) 1/0 for white/black (!) | ||
3664 | * All registers are preserved | ||
3665 | */ | ||
3666 | func_start console_plot_pixel,%a0-%a1/%d0-%d4 | ||
3667 | |||
3668 | movel %pc@(L(mac_videobase)),%a1 | ||
3669 | movel %pc@(L(mac_videodepth)),%d3 | ||
3670 | movel ARG1,%d0 | ||
3671 | movel ARG2,%d1 | ||
3672 | mulul %pc@(L(mac_rowbytes)),%d1 | ||
3673 | movel ARG3,%d2 | ||
3674 | |||
3675 | /* | ||
3676 | * Register usage: | ||
3677 | * d0 = x coord becomes byte offset into frame buffer | ||
3678 | * d1 = y coord | ||
3679 | * d2 = black or white (0/1) | ||
3680 | * d3 = video depth | ||
3681 | * d4 = temp of x (d0) for many bit depths | ||
3682 | */ | ||
3683 | L(test_1bit): | ||
3684 | cmpb #1,%d3 | ||
3685 | jbne L(test_2bit) | ||
3686 | movel %d0,%d4 /* we need the low order 3 bits! */ | ||
3687 | divul #8,%d0 | ||
3688 | addal %d0,%a1 | ||
3689 | addal %d1,%a1 | ||
3690 | andb #7,%d4 | ||
3691 | eorb #7,%d4 /* reverse the x-coordinate w/ screen-bit # */ | ||
3692 | andb #1,%d2 | ||
3693 | jbne L(white_1) | ||
3694 | bsetb %d4,%a1@ | ||
3695 | jbra L(console_plot_pixel_exit) | ||
3696 | L(white_1): | ||
3697 | bclrb %d4,%a1@ | ||
3698 | jbra L(console_plot_pixel_exit) | ||
3699 | |||
3700 | L(test_2bit): | ||
3701 | cmpb #2,%d3 | ||
3702 | jbne L(test_4bit) | ||
3703 | movel %d0,%d4 /* we need the low order 2 bits! */ | ||
3704 | divul #4,%d0 | ||
3705 | addal %d0,%a1 | ||
3706 | addal %d1,%a1 | ||
3707 | andb #3,%d4 | ||
3708 | eorb #3,%d4 /* reverse the x-coordinate w/ screen-bit # */ | ||
3709 | lsll #1,%d4 /* ! */ | ||
3710 | andb #1,%d2 | ||
3711 | jbne L(white_2) | ||
3712 | bsetb %d4,%a1@ | ||
3713 | addq #1,%d4 | ||
3714 | bsetb %d4,%a1@ | ||
3715 | jbra L(console_plot_pixel_exit) | ||
3716 | L(white_2): | ||
3717 | bclrb %d4,%a1@ | ||
3718 | addq #1,%d4 | ||
3719 | bclrb %d4,%a1@ | ||
3720 | jbra L(console_plot_pixel_exit) | ||
3721 | |||
3722 | L(test_4bit): | ||
3723 | cmpb #4,%d3 | ||
3724 | jbne L(test_8bit) | ||
3725 | movel %d0,%d4 /* we need the low order bit! */ | ||
3726 | divul #2,%d0 | ||
3727 | addal %d0,%a1 | ||
3728 | addal %d1,%a1 | ||
3729 | andb #1,%d4 | ||
3730 | eorb #1,%d4 | ||
3731 | lsll #2,%d4 /* ! */ | ||
3732 | andb #1,%d2 | ||
3733 | jbne L(white_4) | ||
3734 | bsetb %d4,%a1@ | ||
3735 | addq #1,%d4 | ||
3736 | bsetb %d4,%a1@ | ||
3737 | addq #1,%d4 | ||
3738 | bsetb %d4,%a1@ | ||
3739 | addq #1,%d4 | ||
3740 | bsetb %d4,%a1@ | ||
3741 | jbra L(console_plot_pixel_exit) | ||
3742 | L(white_4): | ||
3743 | bclrb %d4,%a1@ | ||
3744 | addq #1,%d4 | ||
3745 | bclrb %d4,%a1@ | ||
3746 | addq #1,%d4 | ||
3747 | bclrb %d4,%a1@ | ||
3748 | addq #1,%d4 | ||
3749 | bclrb %d4,%a1@ | ||
3750 | jbra L(console_plot_pixel_exit) | ||
3751 | |||
3752 | L(test_8bit): | ||
3753 | cmpb #8,%d3 | ||
3754 | jbne L(test_16bit) | ||
3755 | addal %d0,%a1 | ||
3756 | addal %d1,%a1 | ||
3757 | andb #1,%d2 | ||
3758 | jbne L(white_8) | ||
3759 | moveb #0xff,%a1@ | ||
3760 | jbra L(console_plot_pixel_exit) | ||
3761 | L(white_8): | ||
3762 | clrb %a1@ | ||
3763 | jbra L(console_plot_pixel_exit) | ||
3764 | |||
3765 | L(test_16bit): | ||
3766 | cmpb #16,%d3 | ||
3767 | jbne L(console_plot_pixel_exit) | ||
3768 | addal %d0,%a1 | ||
3769 | addal %d0,%a1 | ||
3770 | addal %d1,%a1 | ||
3771 | andb #1,%d2 | ||
3772 | jbne L(white_16) | ||
3773 | clrw %a1@ | ||
3774 | jbra L(console_plot_pixel_exit) | ||
3775 | L(white_16): | ||
3776 | movew #0x0fff,%a1@ | ||
3777 | jbra L(console_plot_pixel_exit) | ||
3778 | |||
3779 | L(console_plot_pixel_exit): | ||
3780 | func_return console_plot_pixel | ||
3781 | #endif /* CONSOLE */ | ||
3782 | |||
3783 | #if 0 | ||
3784 | /* | ||
3785 | * This is some old code lying around. I don't believe | ||
3786 | * it's used or important anymore. My guess is it contributed | ||
3787 | * to getting to this point, but it's done for now. | ||
3788 | * It was still in the 2.1.77 head.S, so it's still here. | ||
3789 | * (And still not used!) | ||
3790 | */ | ||
3791 | L(showtest): | ||
3792 | moveml %a0/%d7,%sp@- | ||
3793 | puts "A=" | ||
3794 | putn %a1 | ||
3795 | |||
3796 | .long 0xf0119f15 | ptestr #5,%a1@,#7,%a0 | ||
3797 | |||
3798 | puts "DA=" | ||
3799 | putn %a0 | ||
3800 | |||
3801 | puts "D=" | ||
3802 | putn %a0@ | ||
3803 | |||
3804 | puts "S=" | ||
3805 | lea %pc@(L(mmu)),%a0 | ||
3806 | .long 0xf0106200 | pmove %psr,%a0@ | ||
3807 | clrl %d7 | ||
3808 | movew %a0@,%d7 | ||
3809 | putn %d7 | ||
3810 | |||
3811 | putc '\n' | ||
3812 | moveml %sp@+,%a0/%d7 | ||
3813 | rts | ||
3814 | #endif /* 0 */ | ||
3815 | |||
3816 | __INITDATA | ||
3817 | .align 4 | ||
3818 | |||
3819 | #if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || \ | ||
3820 | defined(CONFIG_HP300) || defined(CONFIG_APOLLO) | ||
3821 | L(custom): | ||
3822 | L(iobase): | ||
3823 | .long 0 | ||
3824 | #endif | ||
3825 | |||
3826 | #if defined(CONSOLE) | ||
3827 | L(console_globals): | ||
3828 | .long 0 /* cursor column */ | ||
3829 | .long 0 /* cursor row */ | ||
3830 | .long 0 /* max num columns */ | ||
3831 | .long 0 /* max num rows */ | ||
3832 | .long 0 /* left edge */ | ||
3833 | .long 0 /* mac putc */ | ||
3834 | L(console_font): | ||
3835 | .long 0 /* pointer to console font (struct font_desc) */ | ||
3836 | L(console_font_data): | ||
3837 | .long 0 /* pointer to console font data */ | ||
3838 | #endif /* CONSOLE */ | ||
3839 | |||
3840 | #if defined(MMU_PRINT) | ||
3841 | L(mmu_print_data): | ||
3842 | .long 0 /* valid flag */ | ||
3843 | .long 0 /* start logical */ | ||
3844 | .long 0 /* next logical */ | ||
3845 | .long 0 /* start physical */ | ||
3846 | .long 0 /* next physical */ | ||
3847 | #endif /* MMU_PRINT */ | ||
3848 | |||
3849 | L(cputype): | ||
3850 | .long 0 | ||
3851 | L(mmu_cached_pointer_tables): | ||
3852 | .long 0 | ||
3853 | L(mmu_num_pointer_tables): | ||
3854 | .long 0 | ||
3855 | L(phys_kernel_start): | ||
3856 | .long 0 | ||
3857 | L(kernel_end): | ||
3858 | .long 0 | ||
3859 | L(memory_start): | ||
3860 | .long 0 | ||
3861 | L(kernel_pgdir_ptr): | ||
3862 | .long 0 | ||
3863 | L(temp_mmap_mem): | ||
3864 | .long 0 | ||
3865 | |||
3866 | #if defined (CONFIG_MVME147) | ||
3867 | M147_SCC_CTRL_A = 0xfffe3002 | ||
3868 | M147_SCC_DATA_A = 0xfffe3003 | ||
3869 | #endif | ||
3870 | |||
3871 | #if defined (CONFIG_MVME16x) | ||
3872 | M162_SCC_CTRL_A = 0xfff45005 | ||
3873 | M167_CYCAR = 0xfff450ee | ||
3874 | M167_CYIER = 0xfff45011 | ||
3875 | M167_CYLICR = 0xfff45026 | ||
3876 | M167_CYTEOIR = 0xfff45085 | ||
3877 | M167_CYTDR = 0xfff450f8 | ||
3878 | M167_PCSCCTICR = 0xfff4201e | ||
3879 | M167_PCTPIACKR = 0xfff42025 | ||
3880 | #endif | ||
3881 | |||
3882 | #if defined (CONFIG_BVME6000) | ||
3883 | BVME_SCC_CTRL_A = 0xffb0000b | ||
3884 | BVME_SCC_DATA_A = 0xffb0000f | ||
3885 | #endif | ||
3886 | |||
3887 | #if defined(CONFIG_MAC) | ||
3888 | L(mac_booter_data): | ||
3889 | .long 0 | ||
3890 | L(mac_videobase): | ||
3891 | .long 0 | ||
3892 | L(mac_videodepth): | ||
3893 | .long 0 | ||
3894 | L(mac_dimensions): | ||
3895 | .long 0 | ||
3896 | L(mac_rowbytes): | ||
3897 | .long 0 | ||
3898 | #ifdef MAC_SERIAL_DEBUG | ||
3899 | L(mac_sccbase): | ||
3900 | .long 0 | ||
3901 | #endif /* MAC_SERIAL_DEBUG */ | ||
3902 | #endif | ||
3903 | |||
3904 | #if defined (CONFIG_APOLLO) | ||
3905 | LSRB0 = 0x10412 | ||
3906 | LTHRB0 = 0x10416 | ||
3907 | LCPUCTRL = 0x10100 | ||
3908 | #endif | ||
3909 | |||
3910 | #if defined(CONFIG_HP300) | ||
3911 | DCADATA = 0x11 | ||
3912 | DCALSR = 0x1b | ||
3913 | APCIDATA = 0x00 | ||
3914 | APCILSR = 0x14 | ||
3915 | L(uartbase): | ||
3916 | .long 0 | ||
3917 | L(uart_scode): | ||
3918 | .long -1 | ||
3919 | #endif | ||
3920 | |||
3921 | __FINIT | ||
3922 | .data | ||
3923 | .align 4 | ||
3924 | |||
3925 | availmem: | ||
3926 | .long 0 | ||
3927 | m68k_pgtable_cachemode: | ||
3928 | .long 0 | ||
3929 | m68k_supervisor_cachemode: | ||
3930 | .long 0 | ||
3931 | #if defined(CONFIG_MVME16x) | ||
3932 | mvme_bdid: | ||
3933 | .long 0,0,0,0,0,0,0,0 | ||
3934 | #endif | ||
3935 | #if defined(CONFIG_Q40) | ||
3936 | q40_mem_cptr: | ||
3937 | .long 0 | ||
3938 | L(q40_do_debug): | ||
3939 | .long 0 | ||
3940 | #endif | ||