1 /* tag: openbios forth environment, executable code
2 *
3 * Copyright (C) 2003 Patrick Mauritz, Stefan Reinauer
4 *
5 * See the file "COPYING" for further information about
6 * the copyright and warranty status of this work.
7 */
8
9 #include "config.h"
10 #include "libopenbios/openbios.h"
11 #include "libopenbios/bindings.h"
12 #include "libopenbios/console.h"
13 #include "drivers/drivers.h"
14 #include "asm/types.h"
15 #include "dict.h"
16 #include "kernel/kernel.h"
17 #include "kernel/stack.h"
18 #include "arch/common/nvram.h"
19 #include "packages/nvram.h"
20 #include "../../drivers/timer.h" // XXX
21 #include "libopenbios/sys_info.h"
22 #include "openbios.h"
23 #include "boot.h"
24 #include "romvec.h"
25 #include "openprom.h"
26 #include "psr.h"
27 #include "libopenbios/video.h"
28 #define NO_QEMU_PROTOS
29 #include "arch/common/fw_cfg.h"
30 #include "arch/sparc32/ofmem_sparc32.h"
31
32 #define MEMORY_SIZE (128*1024) /* 128K ram for hosted system */
33 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
34 #define FW_CFG_SUN4M_DEPTH (FW_CFG_ARCH_LOCAL + 0x00)
35
36 int qemu_machine_type;
37
38 struct hwdef {
39 uint64_t iommu_base, slavio_base;
40 uint64_t intctl_base, counter_base, nvram_base, ms_kb_base, serial_base;
41 unsigned long fd_offset, counter_offset, intr_offset;
42 unsigned long aux1_offset, aux2_offset;
43 uint64_t dma_base, esp_base, le_base;
44 uint64_t tcx_base;
45 uint32_t simm_size;
46 int intr_ncpu;
47 int mid_offset;
48 int machine_id_low, machine_id_high;
49 };
50
51 static const struct hwdef hwdefs[] = {
52 /* SS-5 */
53 {
54 .iommu_base = 0x10000000,
55 .tcx_base = 0x50000000,
56 .slavio_base = 0x71000000,
57 .ms_kb_base = 0x71000000,
58 .serial_base = 0x71100000,
59 .nvram_base = 0x71200000,
60 .fd_offset = 0x00400000,
61 .counter_offset = 0x00d00000,
62 .intr_offset = 0x00e00000,
63 .intr_ncpu = 1,
64 .aux1_offset = 0x00900000,
65 .aux2_offset = 0x00910000,
66 .dma_base = 0x78400000,
67 .esp_base = 0x78800000,
68 .le_base = 0x78c00000,
69 .simm_size = 0x2000000,
70 .mid_offset = 0,
71 .machine_id_low = 32,
72 .machine_id_high = 63,
73 },
74 /* SS-10, SS-20 */
75 {
76 .iommu_base = 0xfe0000000ULL,
77 .tcx_base = 0xe20000000ULL,
78 .slavio_base = 0xff1000000ULL,
79 .ms_kb_base = 0xff1000000ULL,
80 .serial_base = 0xff1100000ULL,
81 .nvram_base = 0xff1200000ULL,
82 .fd_offset = 0x00700000, // 0xff1700000ULL,
83 .counter_offset = 0x00300000, // 0xff1300000ULL,
84 .intr_offset = 0x00400000, // 0xff1400000ULL,
85 .intr_ncpu = 4,
86 .aux1_offset = 0x00800000, // 0xff1800000ULL,
87 .aux2_offset = 0x00a01000, // 0xff1a01000ULL,
88 .dma_base = 0xef0400000ULL,
89 .esp_base = 0xef0800000ULL,
90 .le_base = 0xef0c00000ULL,
91 .simm_size = 0x4000000,
92 .mid_offset = 8,
93 .machine_id_low = 64,
94 .machine_id_high = 65,
95 },
96 /* SS-600MP */
97 {
98 .iommu_base = 0xfe0000000ULL,
99 .tcx_base = 0xe20000000ULL,
100 .slavio_base = 0xff1000000ULL,
101 .ms_kb_base = 0xff1000000ULL,
102 .serial_base = 0xff1100000ULL,
103 .nvram_base = 0xff1200000ULL,
104 .fd_offset = -1,
105 .counter_offset = 0x00300000, // 0xff1300000ULL,
106 .intr_offset = 0x00400000, // 0xff1400000ULL,
107 .intr_ncpu = 4,
108 .aux1_offset = 0x00800000, // 0xff1800000ULL,
109 .aux2_offset = 0x00a01000, // 0xff1a01000ULL, XXX should not exist
110 .dma_base = 0xef0081000ULL,
111 .esp_base = 0xef0080000ULL,
112 .le_base = 0xef0060000ULL,
113 .simm_size = 0x4000000,
114 .mid_offset = 8,
115 .machine_id_low = 66,
116 .machine_id_high = 66,
117 },
118 };
119
120 static const struct hwdef *hwdef;
121
setup_timers(void)122 void setup_timers(void)
123 {
124 }
125
udelay(unsigned int usecs)126 void udelay(unsigned int usecs)
127 {
128 }
129
mdelay(unsigned int msecs)130 void mdelay(unsigned int msecs)
131 {
132 }
133
mb86904_init(void)134 static void mb86904_init(void)
135 {
136 PUSH(32);
137 fword("encode-int");
138 push_str("cache-line-size");
139 fword("property");
140
141 PUSH(512);
142 fword("encode-int");
143 push_str("cache-nlines");
144 fword("property");
145
146 PUSH(0x23);
147 fword("encode-int");
148 push_str("mask_rev");
149 fword("property");
150 }
151
tms390z55_init(void)152 static void tms390z55_init(void)
153 {
154 push_str("");
155 fword("encode-string");
156 push_str("ecache-parity?");
157 fword("property");
158
159 push_str("");
160 fword("encode-string");
161 push_str("bfill?");
162 fword("property");
163
164 push_str("");
165 fword("encode-string");
166 push_str("bcopy?");
167 fword("property");
168
169 push_str("");
170 fword("encode-string");
171 push_str("cache-physical?");
172 fword("property");
173
174 PUSH(0xf);
175 fword("encode-int");
176 PUSH(0xf8fffffc);
177 fword("encode-int");
178 fword("encode+");
179 PUSH(4);
180 fword("encode-int");
181 fword("encode+");
182
183 PUSH(0xf);
184 fword("encode-int");
185 fword("encode+");
186 PUSH(0xf8c00000);
187 fword("encode-int");
188 fword("encode+");
189 PUSH(0x1000);
190 fword("encode-int");
191 fword("encode+");
192
193 PUSH(0xf);
194 fword("encode-int");
195 fword("encode+");
196 PUSH(0xf8000000);
197 fword("encode-int");
198 fword("encode+");
199 PUSH(0x1000);
200 fword("encode-int");
201 fword("encode+");
202
203 PUSH(0xf);
204 fword("encode-int");
205 fword("encode+");
206 PUSH(0xf8800000);
207 fword("encode-int");
208 fword("encode+");
209 PUSH(0x1000);
210 fword("encode-int");
211 fword("encode+");
212 push_str("reg");
213 fword("property");
214 }
215
rt625_init(void)216 static void rt625_init(void)
217 {
218 PUSH(32);
219 fword("encode-int");
220 push_str("cache-line-size");
221 fword("property");
222
223 PUSH(512);
224 fword("encode-int");
225 push_str("cache-nlines");
226 fword("property");
227
228 }
229
bad_cpu_init(void)230 static void bad_cpu_init(void)
231 {
232 printk("This CPU is not supported yet, freezing.\n");
233 for(;;);
234 }
235
236 struct cpudef {
237 unsigned long iu_version;
238 const char *name;
239 int psr_impl, psr_vers, impl, vers;
240 int dcache_line_size, dcache_lines, dcache_assoc;
241 int icache_line_size, icache_lines, icache_assoc;
242 int ecache_line_size, ecache_lines, ecache_assoc;
243 int mmu_nctx;
244 void (*initfn)(void);
245 };
246
247 static const struct cpudef sparc_defs[] = {
248 {
249 .iu_version = 0x00 << 24, /* Impl 0, ver 0 */
250 .name = "FMI,MB86900",
251 .initfn = bad_cpu_init,
252 },
253 {
254 .iu_version = 0x04 << 24, /* Impl 0, ver 4 */
255 .name = "FMI,MB86904",
256 .psr_impl = 0,
257 .psr_vers = 4,
258 .impl = 0,
259 .vers = 4,
260 .dcache_line_size = 0x10,
261 .dcache_lines = 0x200,
262 .dcache_assoc = 1,
263 .icache_line_size = 0x20,
264 .icache_lines = 0x200,
265 .icache_assoc = 1,
266 .ecache_line_size = 0x20,
267 .ecache_lines = 0x4000,
268 .ecache_assoc = 1,
269 .mmu_nctx = 0x100,
270 .initfn = mb86904_init,
271 },
272 {
273 .iu_version = 0x05 << 24, /* Impl 0, ver 5 */
274 .name = "FMI,MB86907",
275 .psr_impl = 0,
276 .psr_vers = 5,
277 .impl = 0,
278 .vers = 5,
279 .dcache_line_size = 0x20,
280 .dcache_lines = 0x200,
281 .dcache_assoc = 1,
282 .icache_line_size = 0x20,
283 .icache_lines = 0x200,
284 .icache_assoc = 1,
285 .ecache_line_size = 0x20,
286 .ecache_lines = 0x4000,
287 .ecache_assoc = 1,
288 .mmu_nctx = 0x100,
289 .initfn = mb86904_init,
290 },
291 {
292 .iu_version = 0x10 << 24, /* Impl 1, ver 0 */
293 .name = "LSI,L64811",
294 .initfn = bad_cpu_init,
295 },
296 {
297 .iu_version = 0x11 << 24, /* Impl 1, ver 1 */
298 .name = "CY,CY7C601",
299 .psr_impl = 1,
300 .psr_vers = 1,
301 .impl = 1,
302 .vers = 1,
303 .mmu_nctx = 0x10,
304 .initfn = bad_cpu_init,
305 },
306 {
307 .iu_version = 0x13 << 24, /* Impl 1, ver 3 */
308 .name = "CY,CY7C611",
309 .initfn = bad_cpu_init,
310 },
311 {
312 .iu_version = 0x40000000,
313 .name = "TI,TMS390Z55",
314 .psr_impl = 4,
315 .psr_vers = 0,
316 .impl = 0,
317 .vers = 4,
318 .dcache_line_size = 0x20,
319 .dcache_lines = 0x80,
320 .dcache_assoc = 4,
321 .icache_line_size = 0x40,
322 .icache_lines = 0x40,
323 .icache_assoc = 5,
324 .ecache_line_size = 0x20,
325 .ecache_lines = 0x8000,
326 .ecache_assoc = 1,
327 .mmu_nctx = 0x10000,
328 .initfn = tms390z55_init,
329 },
330 {
331 .iu_version = 0x41000000,
332 .name = "TI,TMS390S10",
333 .psr_impl = 4,
334 .psr_vers = 1,
335 .impl = 4,
336 .vers = 1,
337 .dcache_line_size = 0x10,
338 .dcache_lines = 0x80,
339 .dcache_assoc = 4,
340 .icache_line_size = 0x20,
341 .icache_lines = 0x80,
342 .icache_assoc = 5,
343 .ecache_line_size = 0x20,
344 .ecache_lines = 0x8000,
345 .ecache_assoc = 1,
346 .mmu_nctx = 0x10000,
347 .initfn = tms390z55_init,
348 },
349 {
350 .iu_version = 0x42000000,
351 .name = "TI,TMS390S10",
352 .psr_impl = 4,
353 .psr_vers = 2,
354 .impl = 4,
355 .vers = 2,
356 .dcache_line_size = 0x10,
357 .dcache_lines = 0x80,
358 .dcache_assoc = 4,
359 .icache_line_size = 0x20,
360 .icache_lines = 0x80,
361 .icache_assoc = 5,
362 .ecache_line_size = 0x20,
363 .ecache_lines = 0x8000,
364 .ecache_assoc = 1,
365 .mmu_nctx = 0x10000,
366 .initfn = tms390z55_init,
367 },
368 {
369 .iu_version = 0x43000000,
370 .name = "TI,TMS390S10",
371 .psr_impl = 4,
372 .psr_vers = 3,
373 .impl = 4,
374 .vers = 3,
375 .dcache_line_size = 0x10,
376 .dcache_lines = 0x80,
377 .dcache_assoc = 4,
378 .icache_line_size = 0x20,
379 .icache_lines = 0x80,
380 .icache_assoc = 5,
381 .ecache_line_size = 0x20,
382 .ecache_lines = 0x8000,
383 .ecache_assoc = 1,
384 .mmu_nctx = 0x10000,
385 .initfn = tms390z55_init,
386 },
387 {
388 .iu_version = 0x44000000,
389 .name = "TI,TMS390S10",
390 .psr_impl = 4,
391 .psr_vers = 4,
392 .impl = 4,
393 .vers = 4,
394 .dcache_line_size = 0x10,
395 .dcache_lines = 0x80,
396 .dcache_assoc = 4,
397 .icache_line_size = 0x20,
398 .icache_lines = 0x80,
399 .icache_assoc = 5,
400 .ecache_line_size = 0x20,
401 .ecache_lines = 0x8000,
402 .ecache_assoc = 1,
403 .mmu_nctx = 0x10000,
404 .initfn = tms390z55_init,
405 },
406 {
407 .iu_version = 0x1e000000,
408 .name = "Ross,RT625",
409 .psr_impl = 1,
410 .psr_vers = 14,
411 .impl = 1,
412 .vers = 7,
413 .dcache_line_size = 0x20,
414 .dcache_lines = 0x80,
415 .dcache_assoc = 4,
416 .icache_line_size = 0x40,
417 .icache_lines = 0x40,
418 .icache_assoc = 5,
419 .ecache_line_size = 0x20,
420 .ecache_lines = 0x8000,
421 .ecache_assoc = 1,
422 .mmu_nctx = 0x10000,
423 .initfn = rt625_init,
424 },
425 {
426 .iu_version = 0x1f000000,
427 .name = "Ross,RT620",
428 .psr_impl = 1,
429 .psr_vers = 15,
430 .impl = 1,
431 .vers = 7,
432 .dcache_line_size = 0x20,
433 .dcache_lines = 0x80,
434 .dcache_assoc = 4,
435 .icache_line_size = 0x40,
436 .icache_lines = 0x40,
437 .icache_assoc = 5,
438 .ecache_line_size = 0x20,
439 .ecache_lines = 0x8000,
440 .ecache_assoc = 1,
441 .mmu_nctx = 0x10000,
442 .initfn = rt625_init,
443 },
444 {
445 .iu_version = 0x20000000,
446 .name = "BIT,B5010",
447 .initfn = bad_cpu_init,
448 },
449 {
450 .iu_version = 0x50000000,
451 .name = "MC,MN10501",
452 .initfn = bad_cpu_init,
453 },
454 {
455 .iu_version = 0x90 << 24, /* Impl 9, ver 0 */
456 .name = "Weitek,W8601",
457 .initfn = bad_cpu_init,
458 },
459 {
460 .iu_version = 0xf2000000,
461 .name = "GR,LEON2",
462 .initfn = bad_cpu_init,
463 },
464 {
465 .iu_version = 0xf3000000,
466 .name = "GR,LEON3",
467 .initfn = bad_cpu_init,
468 },
469 };
470
471 static const struct cpudef *
id_cpu(void)472 id_cpu(void)
473 {
474 unsigned long iu_version;
475 unsigned int i;
476
477 asm("rd %%psr, %0\n"
478 : "=r"(iu_version) :);
479 iu_version &= 0xff000000;
480
481 for (i = 0; i < sizeof(sparc_defs)/sizeof(struct cpudef); i++) {
482 if (iu_version == sparc_defs[i].iu_version)
483 return &sparc_defs[i];
484 }
485 printk("Unknown cpu (psr %lx), freezing!\n", iu_version);
486 for (;;);
487 }
488
setup_cpu(int mid_offset)489 static void setup_cpu(int mid_offset)
490 {
491 uint32_t temp;
492 unsigned int i;
493 const struct cpudef *cpu;
494
495 // Add cpus
496 temp = fw_cfg_read_i32(FW_CFG_NB_CPUS);
497
498 printk("CPUs: %x", temp);
499 cpu = id_cpu();
500 printk(" x %s\n", cpu->name);
501 for (i = 0; i < temp; i++) {
502 push_str("/");
503 fword("find-device");
504
505 fword("new-device");
506
507 push_str(cpu->name);
508 fword("device-name");
509
510 push_str("cpu");
511 fword("device-type");
512
513 PUSH(cpu->psr_impl);
514 fword("encode-int");
515 push_str("psr-implementation");
516 fword("property");
517
518 PUSH(cpu->psr_vers);
519 fword("encode-int");
520 push_str("psr-version");
521 fword("property");
522
523 PUSH(cpu->impl);
524 fword("encode-int");
525 push_str("implementation");
526 fword("property");
527
528 PUSH(cpu->vers);
529 fword("encode-int");
530 push_str("version");
531 fword("property");
532
533 PUSH(4096);
534 fword("encode-int");
535 push_str("page-size");
536 fword("property");
537
538 PUSH(cpu->dcache_line_size);
539 fword("encode-int");
540 push_str("dcache-line-size");
541 fword("property");
542
543 PUSH(cpu->dcache_lines);
544 fword("encode-int");
545 push_str("dcache-nlines");
546 fword("property");
547
548 PUSH(cpu->dcache_assoc);
549 fword("encode-int");
550 push_str("dcache-associativity");
551 fword("property");
552
553 PUSH(cpu->icache_line_size);
554 fword("encode-int");
555 push_str("icache-line-size");
556 fword("property");
557
558 PUSH(cpu->icache_lines);
559 fword("encode-int");
560 push_str("icache-nlines");
561 fword("property");
562
563 PUSH(cpu->icache_assoc);
564 fword("encode-int");
565 push_str("icache-associativity");
566 fword("property");
567
568 PUSH(cpu->ecache_line_size);
569 fword("encode-int");
570 push_str("ecache-line-size");
571 fword("property");
572
573 PUSH(cpu->ecache_lines);
574 fword("encode-int");
575 push_str("ecache-nlines");
576 fword("property");
577
578 PUSH(cpu->ecache_assoc);
579 fword("encode-int");
580 push_str("ecache-associativity");
581 fword("property");
582
583 PUSH(2);
584 fword("encode-int");
585 push_str("ncaches");
586 fword("property");
587
588 PUSH(cpu->mmu_nctx);
589 fword("encode-int");
590 push_str("mmu-nctx");
591 fword("property");
592
593 PUSH(8);
594 fword("encode-int");
595 push_str("sparc-version");
596 fword("property");
597
598 push_str("");
599 fword("encode-string");
600 push_str("cache-coherence?");
601 fword("property");
602
603 PUSH(i + mid_offset);
604 fword("encode-int");
605 push_str("mid");
606 fword("property");
607
608 cpu->initfn();
609
610 fword("finish-device");
611 }
612 }
613
dummy_mach_init(uint64_t base)614 static void dummy_mach_init(uint64_t base)
615 {
616 }
617
618 struct machdef {
619 uint16_t machine_id;
620 const char *banner_name;
621 const char *model;
622 const char *name;
623 void (*initfn)(uint64_t base);
624 };
625
626 static const struct machdef sun4m_defs[] = {
627 {
628 .machine_id = 32,
629 .banner_name = "SPARCstation 5",
630 .model = "SUNW,501-3059",
631 .name = "SUNW,SPARCstation-5",
632 .initfn = ss5_init,
633 },
634 {
635 .machine_id = 33,
636 .banner_name = "SPARCstation Voyager",
637 .model = "SUNW,501-2581",
638 .name = "SUNW,SPARCstation-Voyager",
639 .initfn = dummy_mach_init,
640 },
641 {
642 .machine_id = 34,
643 .banner_name = "SPARCstation LX",
644 .model = "SUNW,501-2031",
645 .name = "SUNW,SPARCstation-LX",
646 .initfn = dummy_mach_init,
647 },
648 {
649 .machine_id = 35,
650 .banner_name = "SPARCstation 4",
651 .model = "SUNW,501-2572",
652 .name = "SUNW,SPARCstation-4",
653 .initfn = ss5_init,
654 },
655 {
656 .machine_id = 36,
657 .banner_name = "SPARCstation Classic",
658 .model = "SUNW,501-2326",
659 .name = "SUNW,SPARCstation-Classic",
660 .initfn = dummy_mach_init,
661 },
662 {
663 .machine_id = 37,
664 .banner_name = "Tadpole S3 GX",
665 .model = "S3",
666 .name = "Tadpole_S3GX",
667 .initfn = ss5_init,
668 },
669 {
670 .machine_id = 64,
671 .banner_name = "SPARCstation 10 (1 X 390Z55)",
672 .model = "SUNW,S10,501-2365",
673 .name = "SUNW,SPARCstation-10",
674 .initfn = ob_eccmemctl_init,
675 },
676 {
677 .machine_id = 65,
678 .banner_name = "SPARCstation 20 (1 X 390Z55)",
679 .model = "SUNW,S20,501-2324",
680 .name = "SUNW,SPARCstation-20",
681 .initfn = ob_eccmemctl_init,
682 },
683 {
684 .machine_id = 66,
685 .banner_name = "SPARCsystem 600(1 X 390Z55)",
686 .model = NULL,
687 .name = "SUNW,SPARCsystem-600",
688 .initfn = ob_eccmemctl_init,
689 },
690 };
691
692 static const struct machdef *
id_machine(uint16_t machine_id)693 id_machine(uint16_t machine_id)
694 {
695 unsigned int i;
696
697 for (i = 0; i < sizeof(sun4m_defs)/sizeof(struct machdef); i++) {
698 if (machine_id == sun4m_defs[i].machine_id)
699 return &sun4m_defs[i];
700 }
701 printk("Unknown machine (ID %d), freezing!\n", machine_id);
702 for (;;);
703 }
704
setup_machine(uint64_t base)705 static void setup_machine(uint64_t base)
706 {
707 uint16_t machine_id;
708 const struct machdef *mach;
709
710 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
711 mach = id_machine(machine_id);
712
713 push_str("/");
714 fword("find-device");
715 push_str(mach->banner_name);
716 fword("encode-string");
717 push_str("banner-name");
718 fword("property");
719
720 if (mach->model) {
721 push_str(mach->model);
722 fword("encode-string");
723 push_str("model");
724 fword("property");
725 }
726 push_str(mach->name);
727 fword("encode-string");
728 push_str("name");
729 fword("property");
730
731 mach->initfn(base);
732 }
733
734 /* Add /uuid */
setup_uuid(void)735 static void setup_uuid(void)
736 {
737 static uint8_t qemu_uuid[16];
738
739 fw_cfg_read(FW_CFG_UUID, (char *)qemu_uuid, 16);
740
741 printk("UUID: " UUID_FMT "\n", qemu_uuid[0], qemu_uuid[1], qemu_uuid[2],
742 qemu_uuid[3], qemu_uuid[4], qemu_uuid[5], qemu_uuid[6],
743 qemu_uuid[7], qemu_uuid[8], qemu_uuid[9], qemu_uuid[10],
744 qemu_uuid[11], qemu_uuid[12], qemu_uuid[13], qemu_uuid[14],
745 qemu_uuid[15]);
746
747 push_str("/");
748 fword("find-device");
749
750 PUSH((long)&qemu_uuid);
751 PUSH(16);
752 fword("encode-bytes");
753 push_str("uuid");
754 fword("property");
755 }
756
setup_stdio(void)757 static void setup_stdio(void)
758 {
759 char nographic;
760 const char *stdin, *stdout;
761 phandle_t display_ph;
762
763 fw_cfg_read(FW_CFG_NOGRAPHIC, &nographic, 1);
764
765 /* Check to see if any framebuffer present */
766 display_ph = dt_iterate_type(0, "display");
767 if (display_ph == 0) {
768 nographic = 1;
769 }
770
771 if (nographic) {
772 obp_stdin = PROMDEV_TTYA;
773 obp_stdout = PROMDEV_TTYA;
774 stdin = "ttya";
775 stdout = "ttya";
776 } else {
777 obp_stdin = PROMDEV_KBD;
778 obp_stdout = PROMDEV_SCREEN;
779 stdin = "keyboard";
780 stdout = "screen";
781 }
782
783 push_str(stdin);
784 push_str("input-device");
785 fword("$setenv");
786
787 push_str(stdout);
788 push_str("output-device");
789 fword("$setenv");
790
791 obp_stdin_path = stdin;
792 obp_stdout_path = stdout;
793 }
794
init_memory(void)795 static void init_memory(void)
796 {
797 phys_addr_t phys;
798 ucell virt;
799
800 /* Claim the memory from OFMEM */
801 phys = ofmem_claim_phys(-1, MEMORY_SIZE, PAGE_SIZE);
802 if (!phys)
803 printk("panic: not enough physical memory on host system.\n");
804
805 virt = ofmem_claim_virt(OF_CODE_START - MEMORY_SIZE, MEMORY_SIZE, 0);
806 if (!virt)
807 printk("panic: not enough virtual memory on host system.\n");
808
809 /* Generate the mapping (and lock translation into the TLBs) */
810 ofmem_map(phys, virt, MEMORY_SIZE, ofmem_arch_default_translation_mode(phys));
811
812 /* we push start and end of memory to the stack
813 * so that it can be used by the forth word QUIT
814 * to initialize the memory allocator
815 */
816
817 PUSH(virt);
818 PUSH(virt + MEMORY_SIZE);
819 }
820
821 /* ( size -- virt ) */
822 static void
dma_alloc(void)823 dma_alloc(void)
824 {
825 ucell size = POP();
826 unsigned long *va;
827
828 va = dvma_alloc(size);
829
830 PUSH(pointer2cell(va));
831 }
832
833 /* ( virt devaddr size -- ) */
834 static void
dma_sync(void)835 dma_sync(void)
836 {
837 ucell size = POP();
838 POP();
839 ucell virt = POP();
840
841 dvma_sync(cell2pointer(virt), size);
842 }
843
844 /* ( virt size cacheable? -- devaddr ) */
845 static void
dma_map_in(void)846 dma_map_in(void)
847 {
848 unsigned int iova;
849
850 POP();
851 POP();
852 ucell virt = POP();
853
854 iova = dvma_map_in(cell2pointer(virt));
855 PUSH((ucell)iova);
856 }
857
858 static void
arch_init(void)859 arch_init( void )
860 {
861 char *cmdline;
862 const char *kernel_cmdline;
863 uint32_t temp;
864 uint16_t machine_id;
865 char buf[256];
866 unsigned long mem_size;
867
868 fw_cfg_init();
869
870 fw_cfg_read(FW_CFG_SIGNATURE, buf, 4);
871 buf[4] = '\0';
872
873 printk("Configuration device id %s", buf);
874
875 temp = fw_cfg_read_i32(FW_CFG_ID);
876 machine_id = fw_cfg_read_i16(FW_CFG_MACHINE_ID);
877
878 printk(" version %d machine id %d\n", temp, machine_id);
879
880 if (temp != 1) {
881 printk("Incompatible configuration device version, freezing\n");
882 for(;;);
883 }
884
885 graphic_depth = fw_cfg_read_i16(FW_CFG_SUN4M_DEPTH);
886
887 openbios_init();
888 modules_init();
889 ob_init_mmu(hwdef->simm_size);
890 ob_init_iommu(hwdef->iommu_base);
891
892 bind_func("(sparc32-dma-alloc)", dma_alloc);
893 feval("['] (sparc32-dma-alloc) to (dma-alloc)");
894 bind_func("(sparc32-dma-sync)", dma_sync);
895 feval("['] (sparc32-dma-sync) to (dma-sync)");
896 bind_func("(sparc32-dma-map-in)", dma_map_in);
897 feval("['] (sparc32-dma-map-in) to (dma-map-in)");
898
899 #ifdef CONFIG_DRIVER_OBIO
900 mem_size = fw_cfg_read_i32(FW_CFG_RAM_SIZE);
901 ob_obio_init(hwdef->slavio_base, hwdef->fd_offset,
902 hwdef->counter_offset, hwdef->intr_offset, hwdef->intr_ncpu,
903 hwdef->aux1_offset, hwdef->aux2_offset,
904 mem_size);
905
906 setup_machine(hwdef->slavio_base);
907
908 nvconf_init();
909 #endif
910 #ifdef CONFIG_DRIVER_SBUS
911 #ifdef CONFIG_DEBUG_CONSOLE_VIDEO
912 setup_video();
913 #endif
914 ob_sbus_init(hwdef->iommu_base + 0x1000ULL, qemu_machine_type);
915 #endif
916 device_end();
917
918 setup_cpu(hwdef->mid_offset);
919
920 setup_stdio();
921 /* Initialiase openprom romvec */
922 romvec = init_openprom();
923
924 kernel_size = fw_cfg_read_i32(FW_CFG_KERNEL_SIZE);
925 if (kernel_size) {
926 kernel_image = fw_cfg_read_i32(FW_CFG_KERNEL_ADDR);
927
928 /* Map krnel memory a similar way to SILO */
929 ofmem_map(PAGE_ALIGN(kernel_image), IMAGE_VIRT_ADDR, PAGE_ALIGN(kernel_size), -1);
930 }
931
932 kernel_cmdline = (const char *) fw_cfg_read_i32(FW_CFG_KERNEL_CMDLINE);
933 if (kernel_cmdline) {
934 cmdline = strdup(kernel_cmdline);
935 } else {
936 cmdline = strdup("");
937 }
938 obp_arg.argv[1] = cmdline;
939 qemu_cmdline = (uint32_t)cmdline;
940
941 initrd_size = fw_cfg_read_i32(FW_CFG_INITRD_SIZE);
942 if (initrd_size) {
943 initrd_image = fw_cfg_read_i32(FW_CFG_INITRD_ADDR);
944
945 /* Map krnel memory a similar way to SILO */
946 ofmem_map(PAGE_ALIGN(initrd_image), INITRD_VIRT_ADDR, PAGE_ALIGN(initrd_size), -1);
947 }
948
949 if (kernel_size)
950 printk("kernel phys 0x%x virt 0x%x size 0x%x\n", kernel_image, 0x4000, kernel_size);
951 if (initrd_size)
952 printk("initrd phys 0x%x virt 0x%x size 0x%x\n", initrd_image, INITRD_VIRT_ADDR, initrd_size);
953
954 /* Setup nvram variables */
955 push_str("/options");
956 fword("find-device");
957 push_str(cmdline);
958 fword("encode-string");
959 push_str("boot-file");
960 fword("property");
961
962 boot_device = fw_cfg_read_i16(FW_CFG_BOOT_DEVICE);
963
964 switch (boot_device) {
965 case 'a':
966 push_str("floppy");
967 break;
968 case 'c':
969 push_str("disk:a disk");
970 break;
971 default:
972 case 'd':
973 push_str("cdrom:d cdrom");
974 break;
975 case 'n':
976 push_str("net");
977 break;
978 }
979
980 fword("encode-string");
981 push_str("boot-device");
982 fword("property");
983
984 device_end();
985
986 bind_func("platform-boot", boot );
987 bind_func("(arch-go)", setup_romvec );
988
989 /* Set up other properties */
990 push_str("/chosen");
991 fword("find-device");
992
993 setup_uuid();
994
995 /* Enable interrupts */
996 temp = get_psr();
997 temp = (temp & ~PSR_PIL) | (13 << 8); /* Enable CPU timer interrupt (level 14) */
998 put_psr(temp);
999 }
1000
1001 extern struct _console_ops arch_console_ops;
1002
openbios(void)1003 int openbios(void)
1004 {
1005 unsigned int i;
1006
1007 for (i = 0; i < sizeof(hwdefs) / sizeof(struct hwdef); i++) {
1008 if (hwdefs[i].machine_id_low <= qemu_machine_type &&
1009 hwdefs[i].machine_id_high >= qemu_machine_type) {
1010 hwdef = &hwdefs[i];
1011 break;
1012 }
1013 }
1014 if (!hwdef)
1015 for(;;); // Internal inconsistency, hang
1016
1017 #ifdef CONFIG_DEBUG_CONSOLE
1018 init_console(arch_console_ops);
1019 #endif
1020 /* Make sure we setup OFMEM before the MMU as we need malloc() to setup page tables */
1021 ofmem_init();
1022
1023 #ifdef CONFIG_DRIVER_SBUS
1024 init_mmu_swift();
1025 #endif
1026 #ifdef CONFIG_DEBUG_CONSOLE
1027 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
1028 escc_uart_init(hwdef->serial_base | (CONFIG_SERIAL_PORT? 0ULL: 4ULL),
1029 CONFIG_SERIAL_SPEED);
1030 #endif
1031 #ifdef CONFIG_DEBUG_CONSOLE_VIDEO
1032 kbd_init(hwdef->ms_kb_base);
1033 #endif
1034 #endif
1035
1036 collect_sys_info(&sys_info);
1037
1038 dict = (unsigned char *)sys_info.dict_start;
1039 dicthead = (cell)sys_info.dict_end;
1040 last = sys_info.dict_last;
1041 dictlimit = sys_info.dict_limit;
1042
1043 forth_init();
1044
1045 #ifdef CONFIG_DEBUG_BOOT
1046 printk("forth started.\n");
1047 printk("initializing memory...");
1048 #endif
1049
1050 init_memory();
1051
1052 #ifdef CONFIG_DEBUG_BOOT
1053 printk("done\n");
1054 #endif
1055
1056 PUSH_xt( bind_noname_func(arch_init) );
1057 fword("PREPOST-initializer");
1058
1059 PC = (ucell)findword("initialize-of");
1060
1061 if (!PC) {
1062 printk("panic: no dictionary entry point.\n");
1063 return -1;
1064 }
1065 #ifdef CONFIG_DEBUG_DICTIONARY
1066 printk("done (%d bytes).\n", dicthead);
1067 printk("Jumping to dictionary...\n");
1068 #endif
1069
1070 enterforth((xt_t)PC);
1071
1072 free(dict);
1073 return 0;
1074 }
1075