added concrete implementations of putc(), getc(), getchar() and gets()
[tangerine.git] / arch / ppc-all / prep / startup / c_start.c
blob485c403908903d040d942090f6914252d84dad30
1 /*
2 c_start.c - description
3 $Id$
4 */
6 /*
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your opinion) any later version.
13 #include <exec/types.h>
14 #include <aros/abi.h>
15 #include <aros/multiboot.h>
16 #include "of1275.h"
18 void com1_putc(char c);
19 extern char *core_id;
21 /* Convert the integer D to a string and save the string in BUF. If
22 BASE is equal to 'd', interpret that D is decimal, and if BASE is
23 equal to 'x', interpret that D is hexadecimal. */
24 static void itoa (char *buf, int base, int d)
26 char *p = buf;
27 char *p1, *p2;
28 unsigned long ud = d;
29 int divisor = 10;
31 /* If %d is specified and D is minus, put `-' in the head. */
32 if (base == 'd' && d < 0)
34 *p++ = '-';
35 buf++;
36 ud = -d;
38 else if (base == 'x')
39 divisor = 16;
41 /* Divide UD by DIVISOR until UD == 0. */
44 int remainder = ud % divisor;
46 *p++ = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
48 while (ud /= divisor);
50 /* Terminate BUF. */
51 *p = 0;
53 /* Reverse BUF. */
54 p1 = buf;
55 p2 = p - 1;
56 while (p1 < p2)
58 char tmp = *p1;
59 *p1 = *p2;
60 *p2 = tmp;
61 p1++;
62 p2--;
66 static void _com1_putc(char c)
68 if (c=='\n')
70 com1_putc('\r');
72 com1_putc(c);
75 /* Format a string and print it on the screen, just like the libc
76 function printf. */
77 void com1_printf(const char *format, ...)
79 __builtin_va_list ap;
80 __builtin_varargs_start(ap);
82 int c;
83 char buf[20];
85 while ((c = *format++) != 0)
87 if (c != '%')
88 _com1_putc(c);
89 else
91 char *p;
92 int n;
94 c = *format++;
95 switch (c)
97 case 'd':
98 case 'u':
99 case 'x':
100 itoa (buf, c, __builtin_va_arg(ap, int));
101 p = buf;
102 goto string;
103 break;
105 case 's':
106 p = __builtin_va_arg(ap, char*);
107 if (! p)
108 p = "(null)";
110 string:
111 while (*p)
112 _com1_putc(*p++);
113 break;
115 default:
116 _com1_putc(__builtin_va_arg(ap, int));
117 break;
121 __builtin_va_end(ap);
124 ULONG findMem(APTR ofw, ULONG orig_MSR)
126 ULONG volatile *mem=(APTR)(16*1024*1024);
127 ULONG msr;
128 int i;
130 ULONG dev_handle, res, size;
131 ULONG mem_info[2];
133 asm volatile("mfmsr %0":"=r"(msr));
135 while(ofw && ((ULONG)ofw < 0x10000000))
137 asm volatile("mtmsr %0"::"r"(orig_MSR));
138 of_init(ofw);
140 res = of_finddevice("/memory@0", &dev_handle);
142 if (res)
143 break;
145 res = of_getprop(dev_handle, "reg", mem_info, sizeof(mem_info), &size);
146 if (res) break;
148 mem = (ULONG *)mem_info[1];
150 break;
153 asm volatile("mtmsr %0"::"r"(msr));
154 return (ULONG)mem;
157 void cstart(APTR load_addr, APTR real_addr, ULONG kernel_size,
158 APTR residual, APTR ofw, ULONG orig_MSR)
160 int i=1;
161 struct CallOS callos;
164 Define CallOS on stack temporarly. It is allowed since Launch kernel
165 from this function while local variables remains reserved
168 CallOS = &callos;
170 ULONG mem_avail; //=findMem(); /* Assume 16MB of ram */
171 com1_printf("\n%s\n",&core_id);
173 com1_printf("\n[startup] load_addr : $%x"
174 "\n[startup] real_addr : $%x"
175 "\n[startup] kernel_size: %dKB"
176 "\n[startup] residual : $%x"
177 "\n[startup] ofw_iface : $%x\n",
178 load_addr, real_addr, (kernel_size+1023) >> 10, residual, ofw);
180 mem_avail = findMem(ofw, orig_MSR);
182 com1_printf("[startup] memory detected: %dMB\n",
183 mem_avail >> 20);
186 Multiboot structure is forced to appear at physical address
187 location 0x00000008. It is allowable since the exception
188 vectors are at 0xfff00100 and will be fixed later. By this
189 time we create multiboot here.
191 struct multiboot *mb = (struct multiboot*)0x8;
192 struct mb_mmap *mmap = (struct mb_mmap*)(0x8 + sizeof(struct multiboot));
194 /* Prepare multiboot structure */
195 mb->flags = MB_FLAGS_LDRNAME
196 | MB_FLAGS_CMDLINE
197 | MB_FLAGS_MMAP;
198 mb->loader_name = "PowerPC bootloader";
199 mb->cmdline = "";
200 mb->mmap_addr = (ULONG)mmap;
201 mb->mmap_length = ((mem_avail > 16*1024*1024) ? 2 : 1) * sizeof(struct mb_mmap);
204 Do mmap setup. Usually we have 1 or 2 entries, the
205 first is the DMA memory and the second is everything
206 else.
208 mmap[0].size = sizeof(struct mb_mmap) - 4;
209 mmap[0].type = MMAP_TYPE_RAM;
210 mmap[0].addr_low = 0x4000;
211 mmap[0].addr_high = 0;
212 mmap[0].len_low = (ULONG)real_addr - 0x4000;
213 mmap[0].len_high = 0;
215 if (mem_avail > 16*1024*1024)
217 mmap[1].size = sizeof(struct mb_mmap) - 4;
218 mmap[1].type = MMAP_TYPE_RAM;
219 mmap[1].addr_low = 16*1024*1024;
220 mmap[1].addr_high = 0;
221 mmap[1].len_low = mem_avail - 16*1024*1024;
222 mmap[1].len_high = 0;
227 // cmain(MULTIBOOT_BOOTLOADER_MAGIC, (ULONG)mb);
229 do {} while(1);