1 /*        $NetBSD: Locore.c,v 1.4 2009/03/14 15:36:14 dsl Exp $       */
2 
3 /*
4  * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5  * Copyright (C) 1995, 1996 TooLs GmbH.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *        This product includes software developed by TooLs GmbH.
19  * 4. The name of TooLs GmbH may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <lib/libsa/stand.h>
35 
36 #include <machine/cpu.h>
37 
38 #include <arm/armreg.h>
39 
40 #include "cache.h"
41 #include "extern.h"
42 #include "openfirm.h"
43 
44 static int (*openfirmware_entry)(void *);
45 static int openfirmware(void *);
46 
47 void startup(int (*)(void *), char *, int);
48 static void setup(void);
49 
50 void (*cache_syncI)(void);
51 
52 void abort(void);
abort(void)53 void abort(void)
54 {
55 
56           /* Stupid compiler (__dead). */
57           for (;;)
58                     continue;
59 }
60 
61 static int
openfirmware(void * arg)62 openfirmware(void *arg)
63 {
64 
65           (*openfirmware_entry)(arg);
66           return 0;
67 }
68 
69 static vaddr_t
ofw_getcleaninfo(void)70 ofw_getcleaninfo(void)
71 {
72           int cpu, vclean;
73 
74           if ((cpu = OF_finddevice("/cpu")) == -1)
75                     panic("no /cpu from OFW");
76 
77           if (OF_getprop(cpu, "d-cache-flush-address", &vclean,
78                            sizeof(vclean)) != sizeof(vclean)) {
79                     printf("WARNING: no OFW d-cache-flush-address property\n");
80                     return (RELOC);
81           }
82 
83           return (of_decode_int((unsigned char *)&vclean));
84 }
85 
86 void
startup(int (* openfirm)(void *),char * arg,int argl)87 startup(int (*openfirm)(void *), char *arg, int argl)
88 {
89           u_int cputype = cpufunc_id() & CPU_ID_CPU_MASK;
90 
91           openfirmware_entry = openfirm;
92           setup();
93 
94           /*
95            * Determine the CPU type, and set up the appropriate
96            * I$ sync routine.
97            */
98           if (cputype == CPU_ID_SA110 || cputype == CPU_ID_SA1100 ||
99               cputype == CPU_ID_SA1110) {
100                     extern vaddr_t sa110_cache_clean_addr;
101                     cache_syncI = sa110_cache_syncI;
102                     sa110_cache_clean_addr = ofw_getcleaninfo();
103           } else {
104                     printf("WARNING: no I$ sync routine for CPU 0x%x\n",
105                         cputype);
106           }
107 
108           main();
109           OF_exit();
110 }
111 
112 int
of_decode_int(const u_char * p)113 of_decode_int(const u_char *p)
114 {
115           unsigned int i = *p++ << 8;
116           i = (i + *p++) << 8;
117           i = (i + *p++) << 8;
118           return (i + *p);
119 }
120 
121 __dead void
OF_exit(void)122 OF_exit(void)
123 {
124           static struct {
125                     const char *name;
126                     int nargs;
127                     int nreturns;
128           } args = {
129                     "exit",
130                     0,
131                     0
132           };
133 
134           openfirmware(&args);
135           for (;;);                     /* just in case */
136 }
137 
138 int
OF_finddevice(const char * name)139 OF_finddevice(const char *name)
140 {
141           static struct {
142                     const char *name;
143                     int nargs;
144                     int nreturns;
145                     const char *device;
146                     int phandle;
147           } args = {
148                     "finddevice",
149                     1,
150                     1,
151           };
152 
153           args.device = name;
154           if (openfirmware(&args) == -1)
155                     return -1;
156           return args.phandle;
157 }
158 
159 int
OF_instance_to_package(int ihandle)160 OF_instance_to_package(int ihandle)
161 {
162           static struct {
163                     const char *name;
164                     int nargs;
165                     int nreturns;
166                     int ihandle;
167                     int phandle;
168           } args = {
169                     "instance-to-package",
170                     1,
171                     1,
172           };
173 
174           args.ihandle = ihandle;
175           if (openfirmware(&args) == -1)
176                     return -1;
177           return args.phandle;
178 }
179 
180 int
OF_getprop(int handle,const char * prop,void * buf,int buflen)181 OF_getprop(int handle, const char *prop, void *buf, int buflen)
182 {
183           static struct {
184                     const char *name;
185                     int nargs;
186                     int nreturns;
187                     int phandle;
188                     const char *prop;
189                     void *buf;
190                     int buflen;
191                     int size;
192           } args = {
193                     "getprop",
194                     4,
195                     1,
196           };
197 
198           args.phandle = handle;
199           args.prop = prop;
200           args.buf = buf;
201           args.buflen = buflen;
202           if (openfirmware(&args) == -1)
203                     return -1;
204           return args.size;
205 }
206 
207 #ifdef    __notyet__          /* Has a bug on FirePower */
208 int
OF_setprop(int handle,const char * prop,void * buf,int len)209 OF_setprop(int handle, const char *prop, void *buf, int len)
210 {
211           static struct {
212                     const char *name;
213                     int nargs;
214                     int nreturns;
215                     int phandle;
216                     const char *prop;
217                     void *buf;
218                     int len;
219                     int size;
220           } args = {
221                     "setprop",
222                     4,
223                     1,
224           };
225 
226           args.phandle = handle;
227           args.prop = prop;
228           args.buf = buf;
229           args.len = len;
230           if (openfirmware(&args) == -1)
231                     return -1;
232           return args.size;
233 }
234 #endif
235 
236 int
OF_open(char * dname)237 OF_open(char *dname)
238 {
239           static struct {
240                     const char *name;
241                     int nargs;
242                     int nreturns;
243                     char *dname;
244                     int handle;
245           } args = {
246                     "open",
247                     1,
248                     1,
249           };
250 
251 #ifdef OFW_DEBUG
252           printf("OF_open(%s) -> ", dname);
253 #endif
254           args.dname = dname;
255           if (openfirmware(&args) == -1 ||
256               args.handle == 0) {
257 #ifdef OFW_DEBUG
258                     printf("lose\n");
259 #endif
260                     return -1;
261           }
262 #ifdef OFW_DEBUG
263           printf("%d\n", args.handle);
264 #endif
265           return args.handle;
266 }
267 
268 void
OF_close(int handle)269 OF_close(int handle)
270 {
271           static struct {
272                     const char *name;
273                     int nargs;
274                     int nreturns;
275                     int handle;
276           } args = {
277                     "close",
278                     1,
279                     0,
280           };
281 
282 #ifdef OFW_DEBUG
283           printf("OF_close(%d)\n", handle);
284 #endif
285           args.handle = handle;
286           openfirmware(&args);
287 }
288 
289 int
OF_write(int handle,void * addr,int len)290 OF_write(int handle, void *addr, int len)
291 {
292           static struct {
293                     const char *name;
294                     int nargs;
295                     int nreturns;
296                     int ihandle;
297                     void *addr;
298                     int len;
299                     int actual;
300           } args = {
301                     "write",
302                     3,
303                     1,
304           };
305 
306 #ifdef OFW_DEBUG
307           if (len != 1)
308                     printf("OF_write(%d, %x, %x) -> ", handle, addr, len);
309 #endif
310           args.ihandle = handle;
311           args.addr = addr;
312           args.len = len;
313           if (openfirmware(&args) == -1) {
314 #ifdef OFW_DEBUG
315                     printf("lose\n");
316 #endif
317                     return -1;
318           }
319 #ifdef OFW_DEBUG
320           if (len != 1)
321                     printf("%x\n", args.actual);
322 #endif
323           return args.actual;
324 }
325 
326 int
OF_read(int handle,void * addr,int len)327 OF_read(int handle, void *addr, int len)
328 {
329           static struct {
330                     const char *name;
331                     int nargs;
332                     int nreturns;
333                     int ihandle;
334                     void *addr;
335                     int len;
336                     int actual;
337           } args = {
338                     "read",
339                     3,
340                     1,
341           };
342 
343 #ifdef OFW_DEBUG
344           if (len != 1)
345                     printf("OF_read(%d, %x, %x) -> ", handle, addr, len);
346 #endif
347           args.ihandle = handle;
348           args.addr = addr;
349           args.len = len;
350           if (openfirmware(&args) == -1) {
351 #ifdef OFW_DEBUG
352                     printf("lose\n");
353 #endif
354                     return -1;
355           }
356 #ifdef OFW_DEBUG
357           if (len != 1)
358                     printf("%x\n", args.actual);
359 #endif
360           return args.actual;
361 }
362 
363 int
OF_seek(int handle,u_quad_t pos)364 OF_seek(int handle, u_quad_t pos)
365 {
366           static struct {
367                     const char *name;
368                     int nargs;
369                     int nreturns;
370                     int handle;
371                     int poshi;
372                     int poslo;
373                     int status;
374           } args = {
375                     "seek",
376                     3,
377                     1,
378           };
379 
380 #ifdef OFW_DEBUG
381           printf("OF_seek(%d, %x, %x) -> ", handle, (int)(pos >> 32), (int)pos);
382 #endif
383           args.handle = handle;
384           args.poshi = (int)(pos >> 32);
385           args.poslo = (int)pos;
386           if (openfirmware(&args) == -1) {
387 #ifdef OFW_DEBUG
388                     printf("lose\n");
389 #endif
390                     return -1;
391           }
392 #ifdef OFW_DEBUG
393           printf("%d\n", args.status);
394 #endif
395           return args.status;
396 }
397 
398 void *
OF_claim(void * virt,u_int size,u_int align)399 OF_claim(void *virt, u_int size, u_int align)
400 {
401           static struct {
402                     const char *name;
403                     int nargs;
404                     int nreturns;
405                     void *virt;
406                     u_int size;
407                     u_int align;
408                     void *baseaddr;
409           } args = {
410                     "claim",
411                     3,
412                     1,
413           };
414 
415 #ifdef OFW_DEBUG
416           printf("OF_claim(%x, %x, %x) -> ", virt, size, align);
417 #endif
418           args.virt = virt;
419           args.size = size;
420           args.align = align;
421           if (openfirmware(&args) == -1) {
422 #ifdef OFW_DEBUG
423                     printf("lose\n");
424 #endif
425                     return (void *)-1;
426           }
427 #ifdef OFW_DEBUG
428           printf("%x\n", args.baseaddr);
429 #endif
430           return args.baseaddr;
431 }
432 
433 void
OF_release(void * virt,u_int size)434 OF_release(void *virt, u_int size)
435 {
436           static struct {
437                     const char *name;
438                     int nargs;
439                     int nreturns;
440                     void *virt;
441                     u_int size;
442           } args = {
443                     "release",
444                     2,
445                     0,
446           };
447 
448 #ifdef OFW_DEBUG
449           printf("OF_release(%x, %x)\n", virt, size);
450 #endif
451           args.virt = virt;
452           args.size = size;
453           openfirmware(&args);
454 }
455 
456 int
OF_milliseconds(void)457 OF_milliseconds(void)
458 {
459           static struct {
460                     const char *name;
461                     int nargs;
462                     int nreturns;
463                     int ms;
464           } args = {
465                     "milliseconds",
466                     0,
467                     1,
468           };
469 
470           openfirmware(&args);
471           return args.ms;
472 }
473 
474 void
OF_chain(void * virt,u_int size,void (* entry)(int (*)(void *),void *,u_int),void * arg,u_int len)475 OF_chain(void *virt, u_int size, void (*entry)(int (*)(void *), void *, u_int),
476     void *arg, u_int len)
477 {
478           struct {
479                     const char *name;
480                     int nargs;
481                     int nreturns;
482                     void *virt;
483                     u_int size;
484                     void (*entry)(int (*)(void *), void *, u_int);
485                     void *arg;
486                     u_int len;
487           } args;
488 
489           args.name = "chain";
490           args.nargs = 5;
491           args.nreturns = 0;
492           args.virt = virt;
493           args.size = size;
494           args.entry = entry;
495           args.arg = arg;
496           args.len = len;
497 #if 1
498           openfirmware(&args);
499 #else
500           entry(openfirmware_entry, arg, len);
501 #endif
502 }
503 
504 static int stdin;
505 static int stdout;
506 
507 static void
setup(void)508 setup(void)
509 {
510           u_char buf[sizeof(int)];
511           int chosen;
512 
513           if ((chosen = OF_finddevice("/chosen")) == -1)
514                     OF_exit();
515 
516           if (OF_getprop(chosen, "stdin", buf, sizeof(buf)) != sizeof(buf))
517                     OF_exit();
518           stdin = of_decode_int(buf);
519 
520           if (OF_getprop(chosen, "stdout", buf, sizeof(buf)) != sizeof(buf))
521                     OF_exit();
522           stdout = of_decode_int(buf);
523 }
524 
525 void
putchar(int c)526 putchar(int c)
527 {
528           char ch = c;
529 
530           if (c == '\n')
531                     putchar('\r');
532           OF_write(stdout, &ch, 1);
533 }
534 
535 int
getchar(void)536 getchar(void)
537 {
538           unsigned char ch = '\0';
539           int l;
540 
541           while ((l = OF_read(stdin, &ch, 1)) != 1)
542                     if (l != -2 && l != 0)
543                               return -1;
544           return ch;
545 }
546