source: trunk/packages/xen-3.1/xen-3.1/xen/arch/powerpc/of_handler/ofh.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 10.7 KB
Line 
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
15 *
16 * Copyright (C) IBM Corp. 2005
17 *
18 * Authors: Jimi Xenidis <jimix@watson.ibm.com>
19 */
20
21#include "ofh.h"
22#include <stdarg.h>
23#include <xen/lib.h>
24
25/*
26 * 6.3.1 Access to the client interface functions
27 * This is the spec'd maximum
28 */
29#define PFW_MAXSRVCLEN 31
30
31static u32 ofh_maxsrvclen;
32
33extern s32 debug(const char *fmt, ...);
34
35s32 debug(const char *fmt, ...)
36{
37    s32 sz;
38    va_list ap;
39    char buf[512];
40    va_start(ap, fmt);
41    sz = vsnprintf(buf, 512, fmt, ap);
42    va_end(ap);
43    ofh_cons_write(buf, sz, &sz);
44
45    return sz;
46}
47
48
49
50void
51assprint(const char *expr, const char *file, int line, const char *fmt, ...)
52{
53    char a[15];
54
55    a[0]  = '\n';
56    a[1]  = '\n';
57    a[2]  = 'O';
58    a[3]  = 'F';
59    a[4]  = 'H';
60    a[5]  = ':';
61    a[6]  = 'A';
62    a[7]  = 'S';
63    a[8]  = 'S';
64    a[9]  = 'E';
65    a[10] = 'R';
66    a[11] = 'T';
67    a[12] = '!';
68    a[13] = '\n';
69    a[14] = '\n';
70
71    s32 actual;
72    u32 t = 1;
73    volatile u32 *tp = &t;
74
75    (void)expr; (void)file; (void)line; (void)fmt;
76
77    ofh_cons_write(a, sizeof (a), &actual);
78
79    /* maybe I can break out of this loop manually (like with a
80     * debugger) */
81    while (*tp) {
82        continue;
83    }
84}
85
86/*
87 * we use elf hash since it is pretty standard
88 */
89static u32
90of_hash(const char *s)
91{
92    u32 hash = 0;
93    u32 hnib;
94
95    if (s != NULL) {
96        while (*s != '\0') {
97            hash = (hash << 4) + *s++;
98            hnib = hash & 0xf0000000UL;
99            if (hnib != 0) {
100                hash ^= hnib >> 24;
101            }
102            hash &= ~hnib;
103        }
104    }
105    return hash;
106}
107
108static void
109ofh_service_init(ulong b)
110{
111    ulong sz;
112    int i;
113    int j = 0;
114    struct ofh_srvc *o;
115    struct ofh_srvc *ofs[] = {
116        DRELA(&ofh_srvc[0], b),
117        DRELA(&ofh_isa_srvc[0], b),
118        NULL
119    };
120
121    j = 0;
122    while (ofs[j] != NULL) {
123        /* find the maximum string length for services */
124        o = &ofs[j][0];
125        while (o->ofs_name != NULL) {
126            const char *n;
127
128            n = DRELA(&o->ofs_name[0], b);
129            /* fix it up so we don't have to fix it anymore */
130            o->ofs_name = n;
131
132            sz = strlen(n);
133            if (sz > *DRELA(&ofh_maxsrvclen, b)) {
134                *DRELA(&ofh_maxsrvclen, b) = sz;
135            }
136            o->ofs_hash =
137                of_hash(n);
138            ++i;
139            ++o;
140        }
141        ++j;
142    }
143}
144
145
146static void
147ofh_cpu_init(ofdn_t chosen, ulong b)
148{
149    static struct ofh_ihandle _ih_cpu_0;
150    void *mem = ofd_mem(b);
151    u32 ih = DRELA((ulong)&_ih_cpu_0, b);
152    struct ofh_ihandle *ihp = (struct ofh_ihandle *)((ulong)ih);
153    const char *cpu_type = DRELA((const char*)"cpu",b);
154
155    ofdn_t cpu = ofd_node_find_by_prop(mem, OFD_ROOT,
156                                       DRELA((const char*)"device_type",b),
157                                       cpu_type, 4);
158    ihp->ofi_node = cpu;
159    ofd_prop_add(mem, chosen, DRELA((const char *)"cpu", b),
160                 &ih, sizeof (ih));
161}
162static s32
163mmu_translate(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
164{
165    /* FIXME: need a little more here */
166    nargs = nargs;
167    nrets = nrets;
168    argp = argp;
169    retp = retp;
170    b = b;
171    return OF_SUCCESS;
172}
173
174static void
175ofh_mmu_init(ofdn_t chosen, ulong b)
176{
177    static struct ofh_methods _mmu_methods[] = {
178        { "translate", mmu_translate },
179        { NULL, NULL},
180    };
181    static struct ofh_ihandle _ih_mmu = {
182        .ofi_methods = _mmu_methods,
183    };
184    void *mem = ofd_mem(b);
185    u32 ih = DRELA((ulong)&_ih_mmu, b);
186
187    ofd_prop_add(mem, chosen, DRELA((const char *)"mmu", b),
188                 &ih, sizeof (ih));
189}
190
191static void
192ofh_chosen_init(ulong b)
193{
194    ofdn_t ph;
195    void *mem = ofd_mem(b);
196
197    ph = ofd_node_find(mem, DRELA((const char *)"/chosen", b));
198
199    ofh_vty_init(ph, b);
200    ofh_cpu_init(ph, b);
201    ofh_mmu_init(ph, b);
202}
203
204static void
205ofh_options_init(ulong b)
206{
207    void *mem = ofd_mem(b);
208    ofdn_t options;
209    u32 size = 1 << 20;
210    u32 base = b;
211    char buf[20];
212    int i;
213
214
215    /* fixup the ihandle */
216    options = ofd_node_find(mem,
217                            DRELA((const char *)"options", b));
218
219    i = snprintf(buf, sizeof (buf), "0x%x", base);
220    ofd_prop_add(mem, options, DRELA((const char *)"real-base", b),
221                 buf, i);
222
223    i = snprintf(buf,sizeof (buf), "0x%x", size);
224    ofd_prop_add(mem, options, DRELA((const char *)"real-size", b),
225                 buf, i);
226}
227
228static void
229ofh_init(ulong b)
230{
231    ulong sz = (ulong)_end - (ulong)__bss_start;
232    /* clear bss */
233    memset(__bss_start + b, 0, sz);
234
235    ofh_service_init(b);
236    ofh_chosen_init(b);
237    ofh_options_init(b);
238}
239
240static ofh_func_t *
241ofh_lookup(const char *service, ulong b)
242{
243    int j;
244    u32 hash;
245    struct ofh_srvc *o;
246    struct ofh_srvc *ofs[] = {
247        DRELA(&ofh_srvc[0], b),
248        DRELA(&ofh_isa_srvc[0], b),
249        NULL
250    };
251    u32 sz;
252
253    sz = *DRELA(&ofh_maxsrvclen, b);
254
255    if (strnlen(service, sz + 1) > sz) {
256        return NULL;
257    }
258
259    hash = of_hash(service);
260
261    j = 0;
262    while (ofs[j] != NULL) {
263        /* yes this could be quicker */
264        o = &ofs[j][0];
265        while (o->ofs_name != NULL) {
266            if (o->ofs_hash == hash) {
267                const char *n = o->ofs_name;
268                if (strcmp(service, n) == 0) {
269                    return o->ofs_func;
270                }
271            }
272            ++o;
273        }
274        ++j;
275    }
276    return NULL;
277}
278
279s32
280ofh_nosup(u32 nargs __attribute__ ((unused)),
281        u32 nrets __attribute__ ((unused)),
282        s32 argp[] __attribute__ ((unused)),
283        s32 retp[] __attribute__ ((unused)),
284        ulong b __attribute__ ((unused)))
285{
286    return OF_FAILURE;
287}
288
289s32
290ofh_test_method(u32 nargs, u32 nrets, s32 argp[], s32 retp[], ulong b)
291{
292    if (nargs == 2) {
293        if (nrets == 1) {
294            s32 *ap = DRELA(&ofh_active_package, b);
295            u32 service = (s32)argp[0];
296            const char *method = (const char *)(ulong)argp[1];
297            s32 *stat = &retp[0];
298
299            (void)ap; (void)service; (void)method;
300
301            *stat = 0;
302            /* we do not do this yet */
303            return OF_FAILURE;
304        }
305    }
306    return OF_FAILURE;
307}
308extern u32 _ofh_inited[0];
309extern u32 _ofh_lastarg[0];
310
311s32
312ofh_handler(struct ofh_args *args, ulong b)
313{
314    u32 *inited = (u32 *)DRELA(&_ofh_inited[0],b);
315    u32 *lastarg = (u32 *)DRELA(&_ofh_lastarg[0],b);
316    ofh_func_t *f;
317
318    if (*inited == 0) {
319        ofh_init(b);
320
321        if ((ulong)ofd_mem(b) < (ulong)_end + b) {
322            static const char msg[] = "PANIC: OFD and BSS collide\n";
323            s32 dummy;
324
325            ofh_cons_write(DRELA(&msg[0], b), sizeof (msg), &dummy);
326            for (;;);
327        }
328
329        *inited = 1;
330    }
331
332    *lastarg = (ulong)args;
333
334    f = ofh_lookup((char *)((ulong)args->ofa_service), b);
335
336    if (f == ((ofh_func_t *)~0UL)) {
337        /* do test */
338        if (args->ofa_nargs == 1) {
339            if (args->ofa_nreturns == 1) {
340                char *name = (char *)(ulong)args->ofa_args[0];
341                if (ofh_lookup(name, b) != NULL) {
342                    args->ofa_args[args->ofa_nargs] =
343                        OF_SUCCESS;
344                    return OF_SUCCESS;
345                }
346            }
347        }
348        return OF_FAILURE;
349
350    } else if (f != NULL) {
351        return leap(args->ofa_nargs,
352                    args->ofa_nreturns,
353                    args->ofa_args,
354                    &args->ofa_args[args->ofa_nargs],
355                    b, f);
356    }
357    return OF_FAILURE;
358}
359
360/*
361 * The following code exists solely to run the handler code standalone
362 */
363void
364__ofh_start(void)
365{
366    s32 ret;
367    u32 of_stdout;
368    u32 ihandle;
369    char buf[1024];
370    u32 args_buf[sizeof (struct ofh_args) + (sizeof (u32) * 10)];
371    struct ofh_args *args;
372
373    args = (struct ofh_args *)args_buf;
374
375    args->ofa_service = (u32)"finddevice";
376    args->ofa_nargs     = 1;
377    args->ofa_nreturns  = 1;
378    args->ofa_args[0]   = (u32)"/";
379    args->ofa_args[1]   = -1;
380    ret = ofh_start(args);
381
382    if (ret == OF_SUCCESS) {
383        args->ofa_service   = (u32)"finddevice";
384        args->ofa_nargs     = 1;
385        args->ofa_nreturns  = 1;
386        args->ofa_args[0]   = (u32)"/chosen";
387        args->ofa_args[1]   = -1;
388        ret = ofh_start(args);
389    }
390
391    if (ret == OF_SUCCESS) {
392        u32 phandle = args->ofa_args[1];
393
394        args->ofa_service   = (u32)"getprop";
395        args->ofa_nargs     = 4;
396        args->ofa_nreturns  = 1;
397        args->ofa_args[0]   = phandle;
398        args->ofa_args[1]   = (ulong)"stdout";
399        args->ofa_args[2]   = (ulong)&of_stdout;
400        args->ofa_args[3]   = sizeof(of_stdout);
401        args->ofa_args[4]   = -1;
402        ret = ofh_start(args);
403    }
404
405    ihandle = *(u32 *)((ulong)args->ofa_args[2]);
406
407    if (ret == OF_SUCCESS) {
408        /* instance to path */
409        args->ofa_service   = (u32)"instance-to-path";
410        args->ofa_nargs     = 3;
411        args->ofa_nreturns  = 1;
412        args->ofa_args[0]   = ihandle;
413        args->ofa_args[1]   = (ulong)buf;
414        args->ofa_args[2]   = sizeof (buf);
415        args->ofa_args[3]   = -1;
416        ret = ofh_start(args);
417
418    }
419
420    if (ret == OF_SUCCESS) {
421        /* open rtas */
422        args->ofa_service   = (u32)"open";
423        args->ofa_nargs     = 1;
424        args->ofa_nreturns  = 1;
425        args->ofa_args[0]   = (u32)"/rtas";
426        ret = ofh_start(args);
427        if (ret == OF_SUCCESS) {
428            u32 ir = args->ofa_args[1];
429            args->ofa_service   = (u32)"call-method";
430            args->ofa_nargs     = 3;
431            args->ofa_nreturns  = 2;
432            args->ofa_args[0]   = (ulong)"instantiate-rtas";
433            args->ofa_args[1]   = ir;
434            args->ofa_args[2]   = (ulong)buf;
435
436            ret = ofh_start(args);
437        }
438    }
439
440    if (ret == OF_SUCCESS) {
441        const char msg[] = "This is a test";
442        u32 msgsz = sizeof(msg) - 1; /* Includes \0 */
443
444        args->ofa_service   = (u32)"write";
445        args->ofa_nargs     = 3;
446        args->ofa_nreturns  = 1;
447        args->ofa_args[0]   = ihandle;
448        args->ofa_args[1]   = (ulong)msg;
449        args->ofa_args[2]   = msgsz;
450        args->ofa_args[3]   = -1;
451        ret = ofh_start(args);
452    }
453
454}
Note: See TracBrowser for help on using the repository browser.