loadbsd.c revision 1.10 1 1.7 chopps /*
2 1.10 chopps * $Id: loadbsd.c,v 1.10 1994/05/12 05:57:33 chopps Exp $
3 1.7 chopps */
4 1.7 chopps
5 1.1 mw #include <sys/types.h>
6 1.1 mw #include <a.out.h>
7 1.1 mw #include <stdio.h>
8 1.8 chopps #include <unistd.h>
9 1.1 mw
10 1.1 mw #include <exec/types.h>
11 1.1 mw #include <exec/execbase.h>
12 1.1 mw #include <exec/memory.h>
13 1.10 chopps #include <exec/resident.h>
14 1.1 mw #include <libraries/configregs.h>
15 1.1 mw #include <libraries/expansionbase.h>
16 1.5 mw #include <graphics/gfxbase.h>
17 1.1 mw
18 1.1 mw #include <inline/exec.h>
19 1.1 mw #include <inline/expansion.h>
20 1.5 mw #include <inline/graphics.h>
21 1.1 mw
22 1.3 mw /* Get definitions for boothowto */
23 1.3 mw #include "reboot.h"
24 1.3 mw
25 1.6 chopps static char usage[] =
26 1.6 chopps "
27 1.6 chopps NAME
28 1.6 chopps \t%s - loads NetBSD from amiga dos.
29 1.6 chopps SYNOPSIS
30 1.6 chopps \t%s some-vmunix [-a] [-b] [-k] [-m memory] [-p] [-t] [-V]
31 1.6 chopps OPTIONS
32 1.6 chopps \t-a Boot up to multiuser mode.
33 1.6 chopps \t-b Ask for which root device.
34 1.6 chopps \t Its possible to have multiple roots and choose between them.
35 1.6 chopps \t-k Reserve the first 4M of fast mem [Some one else
36 1.6 chopps \t is going to have to answer what that it is used for].
37 1.6 chopps \t-m Tweak amount of available memory, for finding minimum amount
38 1.6 chopps \t of memory required to run. Sets fastmem size to specified
39 1.6 chopps \t size in Kbytes.
40 1.6 chopps \t-p Use highest priority fastmem segement instead of the largest
41 1.6 chopps \t segment. The higher priority segment is usually faster
42 1.6 chopps \t (i.e. 32 bit memory), but some people have smaller amounts
43 1.6 chopps \t of 32 bit memory.
44 1.6 chopps \t-t This is a *test* option. It prints out the memory
45 1.6 chopps \t list information being passed to the kernel and also
46 1.6 chopps \t exits without actually starting NetBSD.
47 1.8 chopps \t-S Include kernel symbol table.
48 1.10 chopps \t-D Enter debugger
49 1.6 chopps \t-V Version of loadbsd program.
50 1.6 chopps HISTORY
51 1.6 chopps This version supports Kernel version 720 +
52 1.6 chopps ";
53 1.6 chopps
54 1.1 mw struct ExpansionBase *ExpansionBase;
55 1.5 mw struct GfxBase *GfxBase;
56 1.1 mw
57 1.1 mw #undef __LDPGSZ
58 1.1 mw #define __LDPGSZ 8192
59 1.1 mw
60 1.5 mw #define MAX_MEM_SEG 16
61 1.5 mw
62 1.6 chopps /*
63 1.6 chopps * Kernel parameter passing version
64 1.8 chopps * 1: first version of loadbsd
65 1.8 chopps * 2: needs esym location passed in a4
66 1.6 chopps */
67 1.8 chopps #define KERNEL_PARAMETER_VERSION 2
68 1.6 chopps
69 1.9 chopps /*
70 1.9 chopps * Version history:
71 1.10 chopps * 1.x Kernel parameter passing version check.
72 1.10 chopps * 2.0 Added symbol table end address and symbol table support.
73 1.10 chopps * 2.1 03/23/94 - Round up end of fastram segment.
74 1.10 chopps * Check fastram segment size for minimum of 2M.
75 1.10 chopps * Use largest segment of highest priority if -p option.
76 1.10 chopps * Print out fastram size in KB if not a multiple of MB.
77 1.10 chopps * 2.2 03/24/94 - Zero out all unused registers.
78 1.10 chopps * Started version history comment.
79 1.10 chopps * 2.3 04/26/94 - Added -D option to enter debugger on boot.
80 1.10 chopps * 2.4 04/30/94 - Cpuid includes base machine type.
81 1.10 chopps * Also check if CPU is capable of running NetBSD.
82 1.9 chopps */
83 1.9 chopps
84 1.5 mw struct MEM_LIST {
85 1.5 mw u_long num_mem;
86 1.5 mw struct MEM_SEG {
87 1.5 mw u_long mem_start;
88 1.5 mw u_long mem_size;
89 1.5 mw u_short mem_attrib;
90 1.5 mw short mem_prio;
91 1.5 mw } mem_seg[MAX_MEM_SEG];
92 1.5 mw } mem_list, *kmem_list;
93 1.5 mw
94 1.5 mw int k_opt;
95 1.5 mw int a_opt;
96 1.5 mw int b_opt;
97 1.5 mw int p_opt;
98 1.5 mw int t_opt;
99 1.6 chopps int m_opt;
100 1.8 chopps int S_opt;
101 1.10 chopps int D_opt;
102 1.10 chopps
103 1.10 chopps u_long cpuid;
104 1.5 mw
105 1.5 mw extern char *optarg;
106 1.5 mw extern int optind;
107 1.5 mw
108 1.1 mw void get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size);
109 1.10 chopps void get_cpuid (void);
110 1.6 chopps void Usage (char *program_name);
111 1.6 chopps void Version (void);
112 1.6 chopps
113 1.10 chopps static const char _version[] = "$VER: LoadBSD 2.4 (30.4.94)";
114 1.1 mw
115 1.10 chopps int
116 1.1 mw main (int argc, char *argv[])
117 1.1 mw {
118 1.1 mw struct exec e;
119 1.1 mw int fd;
120 1.3 mw int boothowto = RB_SINGLE;
121 1.1 mw
122 1.1 mw if (argc >= 2)
123 1.1 mw {
124 1.1 mw if ((fd = open (argv[1], 0)) >= 0)
125 1.10 chopps {
126 1.10 chopps if (read (fd, &e, sizeof (e)) == sizeof (e))
127 1.10 chopps {
128 1.10 chopps if (e.a_magic == NMAGIC)
129 1.10 chopps {
130 1.10 chopps u_char *kernel;
131 1.10 chopps int kernel_size;
132 1.1 mw int text_size;
133 1.1 mw struct ConfigDev *cd;
134 1.1 mw int num_cd;
135 1.5 mw void *fastmem_start;
136 1.5 mw u_long fastmem_size, chipmem_size;
137 1.5 mw int i;
138 1.6 chopps u_short *kern_vers;
139 1.8 chopps char *esym;
140 1.8 chopps int string_size;
141 1.10 chopps
142 1.5 mw GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", 0);
143 1.5 mw if (! GfxBase) /* not supposed to fail... */
144 1.5 mw abort();
145 1.1 mw ExpansionBase= (struct ExpansionBase *) OpenLibrary ("expansion.library", 0);
146 1.1 mw if (! ExpansionBase) /* not supposed to fail... */
147 1.1 mw abort();
148 1.5 mw optind = 2;
149 1.10 chopps while ((i = getopt (argc, argv, "kabptVm:SD")) != EOF)
150 1.5 mw switch (i) {
151 1.5 mw case 'k':
152 1.5 mw k_opt = 1;
153 1.5 mw break;
154 1.5 mw case 'a':
155 1.5 mw a_opt = 1;
156 1.5 mw break;
157 1.5 mw case 'b':
158 1.5 mw b_opt = 1;
159 1.5 mw break;
160 1.5 mw case 'p':
161 1.5 mw p_opt = 1;
162 1.5 mw break;
163 1.5 mw case 't':
164 1.5 mw t_opt = 1;
165 1.5 mw break;
166 1.6 chopps case 'm':
167 1.6 chopps m_opt = atoi (optarg) * 1024;
168 1.6 chopps break;
169 1.10 chopps case 'V':
170 1.10 chopps Version();
171 1.10 chopps break;
172 1.10 chopps case 'S':
173 1.10 chopps S_opt = 1;
174 1.10 chopps break;
175 1.10 chopps case 'D':
176 1.10 chopps D_opt = 1;
177 1.10 chopps break;
178 1.10 chopps default:
179 1.10 chopps Usage(argv[0]);
180 1.10 chopps fprintf(stderr,"Unrecognized option \n");
181 1.10 chopps exit(-1);
182 1.5 mw }
183 1.5 mw
184 1.1 mw for (cd = 0, num_cd = 0; cd = FindConfigDev (cd, -1, -1); num_cd++) ;
185 1.5 mw get_mem_config (&fastmem_start, &fastmem_size, &chipmem_size);
186 1.10 chopps get_cpuid ();
187 1.1 mw
188 1.1 mw text_size = (e.a_text + __LDPGSZ - 1) & (-__LDPGSZ);
189 1.8 chopps esym = NULL;
190 1.8 chopps kernel_size = text_size + e.a_data + e.a_bss
191 1.8 chopps + num_cd*sizeof(*cd) + 4
192 1.8 chopps + mem_list.num_mem*sizeof(struct MEM_SEG) + 4;
193 1.8 chopps /*
194 1.8 chopps * get symbol table size & string size
195 1.8 chopps * (should check kernel version to see if it will handle it)
196 1.8 chopps */
197 1.8 chopps if (S_opt && e.a_syms) {
198 1.8 chopps S_opt = 0; /* prepare for failure */
199 1.8 chopps if (lseek(fd, e.a_text + e.a_data + e.a_syms, SEEK_CUR) > 0) {
200 1.8 chopps if (read (fd, &string_size, 4) == 4) {
201 1.8 chopps if (lseek(fd, sizeof(e), SEEK_SET) < 0) {
202 1.8 chopps printf ("Error repositioning to text\n");
203 1.8 chopps exit(0); /* Give up! */
204 1.8 chopps }
205 1.8 chopps kernel_size += e.a_syms + 4 + string_size;
206 1.8 chopps S_opt = 1; /* sucess! Keep -S option */
207 1.8 chopps }
208 1.8 chopps }
209 1.10 chopps }
210 1.8 chopps
211 1.8 chopps kernel = (u_char *) malloc (kernel_size);
212 1.5 mw
213 1.5 mw if (t_opt)
214 1.5 mw for (i = 0; i < mem_list.num_mem; ++i) {
215 1.5 mw printf ("mem segment %d: start=%08lx size=%08lx attribute=%04lx pri=%d\n",
216 1.5 mw i + 1, mem_list.mem_seg[i].mem_start,
217 1.5 mw mem_list.mem_seg[i].mem_size,
218 1.5 mw mem_list.mem_seg[i].mem_attrib,
219 1.5 mw mem_list.mem_seg[i].mem_prio);
220 1.5 mw }
221 1.1 mw
222 1.10 chopps if (kernel)
223 1.10 chopps {
224 1.10 chopps if (read (fd, kernel, e.a_text) == e.a_text
225 1.1 mw && read (fd, kernel + text_size, e.a_data) == e.a_data)
226 1.1 mw {
227 1.1 mw int *knum_cd;
228 1.1 mw struct ConfigDev *kcd;
229 1.5 mw int mem_ix;
230 1.8 chopps
231 1.5 mw if (k_opt)
232 1.1 mw {
233 1.1 mw fastmem_start += 4*1024*1024;
234 1.1 mw fastmem_size -= 4*1024*1024;
235 1.1 mw }
236 1.6 chopps
237 1.6 chopps if (m_opt && m_opt <= fastmem_size)
238 1.6 chopps {
239 1.6 chopps fastmem_size = m_opt;
240 1.6 chopps }
241 1.10 chopps
242 1.5 mw if (a_opt)
243 1.3 mw {
244 1.3 mw printf("Autobooting...");
245 1.3 mw boothowto = RB_AUTOBOOT;
246 1.3 mw }
247 1.5 mw
248 1.5 mw if (b_opt)
249 1.5 mw {
250 1.5 mw printf("Askboot...");
251 1.5 mw boothowto |= RB_ASKNAME;
252 1.5 mw }
253 1.10 chopps
254 1.10 chopps if (D_opt)
255 1.10 chopps {
256 1.10 chopps boothowto |= RB_KDB;
257 1.10 chopps }
258 1.10 chopps
259 1.9 chopps printf ("Using %d%c FASTMEM at 0x%x, %dM CHIPMEM\n",
260 1.9 chopps (fastmem_size & 0xfffff) ? fastmem_size>>10 :
261 1.9 chopps fastmem_size>>20,
262 1.9 chopps (fastmem_size & 0xfffff) ? 'K' : 'M',
263 1.9 chopps fastmem_start, chipmem_size>>20);
264 1.6 chopps kern_vers = (u_short *) (kernel + e.a_entry - 2);
265 1.6 chopps if (*kern_vers > KERNEL_PARAMETER_VERSION &&
266 1.6 chopps *kern_vers != 0x4e73)
267 1.6 chopps {
268 1.6 chopps printf ("This kernel requires a newer version of loadbsd: %d\n", *kern_vers);
269 1.6 chopps exit (0);
270 1.6 chopps }
271 1.10 chopps if ((cpuid & AFB_68020) == 0)
272 1.10 chopps {
273 1.10 chopps printf ("Hmmm... You don't seem to have a CPU capable\n");
274 1.10 chopps printf (" of running NetBSD. You need a 68020\n");
275 1.10 chopps printf (" or better\n");
276 1.10 chopps exit (0);
277 1.10 chopps }
278 1.1 mw /* give them a chance to read the information... */
279 1.1 mw sleep(2);
280 1.1 mw
281 1.1 mw bzero (kernel + text_size + e.a_data, e.a_bss);
282 1.8 chopps /*
283 1.8 chopps * If symbols wanted (and kernel can handle them),
284 1.8 chopps * load symbol table & strings and set esym to end.
285 1.8 chopps */
286 1.1 mw knum_cd = (int *) (kernel + text_size + e.a_data + e.a_bss);
287 1.8 chopps if (*kern_vers != 0x4e73 && *kern_vers > 1 && S_opt && e.a_syms) {
288 1.8 chopps *knum_cd++ = e.a_syms;
289 1.8 chopps read(fd, (char *)knum_cd, e.a_syms);
290 1.8 chopps knum_cd = (int *)((char *)knum_cd + e.a_syms);
291 1.8 chopps read(fd, (char *)knum_cd, string_size);
292 1.8 chopps knum_cd = (int*)((char *)knum_cd + string_size);
293 1.8 chopps esym = (char *) (text_size + e.a_data + e.a_bss
294 1.8 chopps + e.a_syms + 4 + string_size);
295 1.8 chopps }
296 1.1 mw *knum_cd = num_cd;
297 1.5 mw for (kcd = (struct ConfigDev *) (knum_cd+1);
298 1.5 mw cd = FindConfigDev (cd, -1, -1);
299 1.6 chopps *kcd++ = *cd)
300 1.6 chopps ;
301 1.5 mw kmem_list = (struct MEM_LIST *)kcd;
302 1.5 mw kmem_list->num_mem = mem_list.num_mem;
303 1.5 mw for (mem_ix = 0; mem_ix < mem_list.num_mem; mem_ix++)
304 1.5 mw kmem_list->mem_seg[mem_ix] = mem_list.mem_seg[mem_ix];
305 1.8 chopps if (t_opt) /* if test option */
306 1.8 chopps exit (0); /* don't start kernel */
307 1.8 chopps /* AGA startup - may need more */
308 1.5 mw LoadView (NULL);
309 1.8 chopps startit (kernel, kernel_size,
310 1.1 mw e.a_entry, fastmem_start,
311 1.3 mw fastmem_size, chipmem_size,
312 1.10 chopps boothowto, esym, cpuid );
313 1.1 mw }
314 1.1 mw else
315 1.1 mw fprintf (stderr, "Executable corrupt!\n");
316 1.10 chopps }
317 1.10 chopps else
318 1.10 chopps fprintf (stderr, "Out of memory! (%d)\n", text_size + e.a_data + e.a_bss
319 1.5 mw + num_cd*sizeof(*cd) + 4
320 1.5 mw + mem_list.num_mem*sizeof(struct MEM_SEG) + 4);
321 1.10 chopps }
322 1.1 mw else
323 1.10 chopps fprintf (stderr, "Unsupported executable: %o\n", e.a_magic);
324 1.10 chopps }
325 1.10 chopps else
326 1.1 mw fprintf (stderr, "Can't read header of %s\n", argv[1]);
327 1.1 mw
328 1.1 mw close (fd);
329 1.10 chopps }
330 1.1 mw else
331 1.1 mw perror ("open");
332 1.1 mw }
333 1.1 mw else
334 1.6 chopps Usage(argv[0]);
335 1.6 chopps Version();
336 1.6 chopps }/* main() */
337 1.1 mw
338 1.1 mw void
339 1.1 mw get_mem_config (void **fastmem_start, u_long *fastmem_size, u_long *chipmem_size)
340 1.1 mw {
341 1.10 chopps extern struct ExecBase *SysBase;
342 1.1 mw struct MemHeader *mh, *nmh;
343 1.5 mw int num_mem = 0;
344 1.5 mw u_int seg_size;
345 1.5 mw u_int seg_start;
346 1.5 mw u_int seg_end;
347 1.9 chopps char mem_pri = -128;
348 1.10 chopps
349 1.1 mw *fastmem_size = 0;
350 1.1 mw *chipmem_size = 0;
351 1.10 chopps
352 1.1 mw /* walk thru the exec memory list */
353 1.1 mw Forbid ();
354 1.1 mw for (mh = (struct MemHeader *) SysBase->MemList.lh_Head;
355 1.1 mw nmh = (struct MemHeader *) mh->mh_Node.ln_Succ;
356 1.5 mw mh = nmh, num_mem++)
357 1.1 mw {
358 1.5 mw mem_list.mem_seg[num_mem].mem_attrib = mh->mh_Attributes;
359 1.5 mw mem_list.mem_seg[num_mem].mem_prio = mh->mh_Node.ln_Pri;
360 1.5 mw seg_start = (u_int)mh->mh_Lower;
361 1.5 mw seg_end = (u_int)mh->mh_Upper;
362 1.5 mw seg_size = seg_end - seg_start;
363 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
364 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
365 1.5 mw
366 1.1 mw if (mh->mh_Attributes & MEMF_CHIP)
367 1.10 chopps {
368 1.1 mw /* there should hardly be more than one entry for chip mem, but
369 1.1 mw handle it the same nevertheless */
370 1.5 mw /* chipmem always starts at 0, so include vector area */
371 1.6 chopps mem_list.mem_seg[num_mem].mem_start = seg_start = 0;
372 1.5 mw /* round to multiple of 512K */
373 1.5 mw seg_size = (seg_size + 512*1024 - 1) & -(512*1024);
374 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
375 1.5 mw if (seg_size > *chipmem_size)
376 1.1 mw {
377 1.5 mw *chipmem_size = seg_size;
378 1.1 mw }
379 1.10 chopps }
380 1.1 mw else
381 1.1 mw {
382 1.5 mw /* some heuristics.. */
383 1.5 mw seg_start &= -__LDPGSZ;
384 1.9 chopps seg_end = (seg_end + __LDPGSZ - 1) & -__LDPGSZ;
385 1.5 mw /* get the mem back stolen by incore kickstart on A3000 with
386 1.5 mw V36 bootrom. */
387 1.5 mw if (seg_end == 0x07f80000)
388 1.5 mw seg_end = 0x08000000;
389 1.5 mw
390 1.5 mw /* or by zkick on a A2000. */
391 1.5 mw if (seg_start == 0x280000
392 1.5 mw && strcmp (mh->mh_Node.ln_Name, "zkick memory") == 0)
393 1.5 mw seg_start = 0x200000;
394 1.5 mw
395 1.5 mw seg_size = seg_end - seg_start;
396 1.5 mw mem_list.mem_seg[num_mem].mem_start = seg_start;
397 1.5 mw mem_list.mem_seg[num_mem].mem_size = seg_size;
398 1.9 chopps /*
399 1.9 chopps * If this segment is smaller than 2M,
400 1.9 chopps * don't use it to load the kernel
401 1.9 chopps */
402 1.9 chopps if (seg_size < 2 * 1024 * 1024)
403 1.9 chopps continue;
404 1.5 mw /* if p_opt is set, select memory by priority instead of size */
405 1.6 chopps if ((!p_opt && seg_size > *fastmem_size) ||
406 1.10 chopps (p_opt && mem_pri <= mh->mh_Node.ln_Pri && seg_size > *fastmem_size))
407 1.1 mw {
408 1.5 mw *fastmem_size = seg_size;
409 1.5 mw *fastmem_start = (void *)seg_start;
410 1.9 chopps mem_pri = mh->mh_Node.ln_Pri;
411 1.1 mw }
412 1.1 mw }
413 1.1 mw }
414 1.5 mw mem_list.num_mem = num_mem;
415 1.1 mw Permit();
416 1.1 mw }
417 1.1 mw
418 1.10 chopps /*
419 1.10 chopps * Try to determine the machine ID by searching the resident module list
420 1.10 chopps * for modules only present on specific machines. (Thanks, Bill!)
421 1.10 chopps */
422 1.1 mw
423 1.10 chopps void
424 1.10 chopps get_cpuid ()
425 1.10 chopps {
426 1.10 chopps extern struct ExecBase *SysBase;
427 1.10 chopps u_long *rl;
428 1.10 chopps struct Resident *rm;
429 1.10 chopps
430 1.10 chopps cpuid = SysBase->AttnFlags; /* get FPU and CPU flags */
431 1.10 chopps rl = (u_long *) SysBase->ResModules;
432 1.10 chopps if (rl == NULL)
433 1.10 chopps return;
434 1.10 chopps
435 1.10 chopps while (*rl) {
436 1.10 chopps rm = (struct Resident *) *rl;
437 1.10 chopps if (strcmp (rm->rt_Name, "A4000 Bonus") == 0 ||
438 1.10 chopps strcmp (rm->rt_Name, "A1000 Bonus") == 0) {
439 1.10 chopps cpuid |= 4000 << 16;
440 1.10 chopps break;
441 1.10 chopps }
442 1.10 chopps if (strcmp (rm->rt_Name, "A3000 Bonus") == 0) {
443 1.10 chopps cpuid |= 3000 << 16;
444 1.10 chopps break;
445 1.10 chopps }
446 1.10 chopps if (strcmp (rm->rt_Name, "card.resource") == 0) {
447 1.10 chopps cpuid |= 1200 << 16; /* or A600 :-) */
448 1.10 chopps break;
449 1.10 chopps }
450 1.10 chopps ++rl;
451 1.10 chopps }
452 1.10 chopps if (*rl == 0) /* Nothing found, it's probably an A2000 or A500 */
453 1.10 chopps cpuid |= 2000 << 16;
454 1.10 chopps }
455 1.1 mw
456 1.1 mw
457 1.1 mw asm ("
458 1.1 mw .set ABSEXECBASE,4
459 1.1 mw
460 1.1 mw .text
461 1.1 mw .globl _startit
462 1.1 mw
463 1.1 mw _startit:
464 1.1 mw movel sp,a3
465 1.1 mw movel 4:w,a6
466 1.1 mw lea pc@(start_super-.+2),a5
467 1.1 mw jmp a6@(-0x1e) | supervisor-call
468 1.1 mw
469 1.1 mw start_super:
470 1.1 mw movew #0x2700,sr
471 1.1 mw
472 1.1 mw | the BSD kernel wants values into the following registers:
473 1.1 mw | a0: fastmem-start
474 1.1 mw | d0: fastmem-size
475 1.1 mw | d1: chipmem-size
476 1.5 mw | d5: AttnFlags (cpuid)
477 1.3 mw | d7: boothowto
478 1.8 chopps | a4: esym location
479 1.10 chopps | All other registers zeroed for possible future requirements.
480 1.1 mw
481 1.1 mw movel a3@(4),a1 | loaded kernel
482 1.1 mw movel a3@(8),d2 | length of loaded kernel
483 1.9 chopps movel a3@(12),sp@- | entry point [save on stack for rts]
484 1.1 mw movel a3@(16),a0 | fastmem-start
485 1.1 mw movel a3@(20),d0 | fastmem-size
486 1.1 mw movel a3@(24),d1 | chipmem-size
487 1.3 mw movel a3@(28),d7 | boothowto
488 1.8 chopps movel a3@(32),a4 | esym
489 1.10 chopps movel a3@(36),d5 | cpuid
490 1.8 chopps subl a5,a5 | target, load to 0
491 1.1 mw
492 1.5 mw btst #3,(ABSEXECBASE)@(0x129) | AFB_68040,SysBase->AttnFlags
493 1.5 mw beq not040
494 1.5 mw
495 1.5 mw | Turn off 68040 MMU
496 1.5 mw
497 1.8 chopps .word 0x4e7b,0xd003 | movec a5,tc
498 1.8 chopps .word 0x4e7b,0xd806 | movec a5,urp
499 1.8 chopps .word 0x4e7b,0xd807 | movec a5,srp
500 1.8 chopps .word 0x4e7b,0xd004 | movec a5,itt0
501 1.8 chopps .word 0x4e7b,0xd005 | movec a5,itt1
502 1.8 chopps .word 0x4e7b,0xd006 | movec a5,dtt0
503 1.8 chopps .word 0x4e7b,0xd007 | movec a5,dtt1
504 1.5 mw bra nott
505 1.5 mw
506 1.5 mw not040:
507 1.1 mw lea pc@(zero-.+2),a3
508 1.1 mw pmove a3@,tc | Turn off MMU
509 1.1 mw lea pc@(nullrp-.+2),a3
510 1.1 mw pmove a3@,crp | Turn off MMU some more
511 1.1 mw pmove a3@,srp | Really, really, turn off MMU
512 1.1 mw
513 1.1 mw | Turn off 68030 TT registers
514 1.1 mw
515 1.1 mw btst #2,(ABSEXECBASE)@(0x129) | AFB_68030,SysBase->AttnFlags
516 1.1 mw beq nott | Skip TT registers if not 68030
517 1.1 mw lea pc@(zero-.+2),a3
518 1.1 mw .word 0xf013,0x0800 | pmove a3@,tt0 (gas only knows about 68851 ops..)
519 1.1 mw .word 0xf013,0x0c00 | pmove a3@,tt1 (gas only knows about 68851 ops..)
520 1.1 mw
521 1.1 mw nott:
522 1.1 mw
523 1.1 mw movew #(1<<9),0xdff096 | disable DMA
524 1.1 mw
525 1.1 mw L0:
526 1.8 chopps moveb a1@+,a5@+
527 1.1 mw subl #1,d2
528 1.1 mw bcc L0
529 1.1 mw
530 1.1 mw
531 1.9 chopps moveq #0,d2 | zero out unused registers
532 1.9 chopps moveq #0,d3 | (might make future compatibility
533 1.9 chopps moveq #0,d4 | a little easier, since all registers
534 1.9 chopps moveq #0,d6 | would have known contents)
535 1.9 chopps movel d6,a1
536 1.9 chopps movel d6,a2
537 1.9 chopps movel d6,a3
538 1.9 chopps movel d6,a5
539 1.9 chopps movel d6,a6
540 1.9 chopps rts | return to kernel entry point
541 1.1 mw
542 1.1 mw
543 1.1 mw | A do-nothing MMU root pointer (includes the following long as well)
544 1.1 mw
545 1.1 mw nullrp: .long 0x7fff0001
546 1.1 mw zero: .long 0
547 1.1 mw
548 1.1 mw
549 1.1 mw ");
550 1.1 mw
551 1.6 chopps void Usage(char *program_name)
552 1.6 chopps {
553 1.6 chopps fprintf(stderr,usage,program_name,program_name);
554 1.6 chopps }
555 1.6 chopps
556 1.6 chopps void Version()
557 1.6 chopps {
558 1.6 chopps fprintf(stderr,"%s\n",_version + 6);
559 1.6 chopps }
560