OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [sim/] [ppc/] [emul_chirp.c] - Blame information for rev 578

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1997, Andrew Cagney <cagney@highland.com.au>
4
 
5
    This program is free software; you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation; either version 2 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program; if not, write to the Free Software
17
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 
19
    */
20
 
21
 
22
#ifndef _EMUL_CHIRP_C_
23
#define _EMUL_CHIRP_C_
24
 
25
/* Note: this module is called via a table.  There is no benefit in
26
   making it inline */
27
 
28
#include "emul_generic.h"
29
#include "emul_chirp.h"
30
 
31
#ifdef HAVE_STRING_H
32
#include <string.h>
33
#else
34
#ifdef HAVE_STRINGS_H
35
#include <strings.h>
36
#endif
37
#endif
38
 
39
#ifdef HAVE_UNISTD_H
40
#include <unistd.h>
41
#endif
42
 
43
#ifndef STATIC_INLINE_EMUL_CHIRP
44
#define STATIC_INLINE_EMUL_CHIRP STATIC_INLINE
45
#endif
46
 
47
 
48
/* EMULATION
49
 
50
 
51
   OpenFirmware - IEEE Standard for Boot (Initialization
52
   Configuration) Firmware.
53
 
54
 
55
   DESCRIPTION
56
 
57
 
58
   BUGS
59
 
60
 
61
   This code assumes that the memory node has #address-cells and
62
   #size-cells set to one.  For future implementations, this may not
63
   be the case.
64
 
65
   */
66
 
67
 
68
 
69
 
70
/* Descriptor of the open boot services being emulated */
71
 
72
typedef int (chirp_handler)
73
     (os_emul_data *data,
74
      cpu *processor,
75
      unsigned_word cia);
76
 
77
typedef struct _chirp_services {
78
  const char *name;
79
  chirp_handler *handler;
80
} chirp_services;
81
 
82
 
83
/* The OpenBoot emulation is, at any time either waiting for a client
84
   request or waiting on a client callback */
85
typedef enum {
86
  serving,
87
  emulating,
88
  faulting,
89
} chirp_emul_state;
90
 
91
struct _os_emul_data {
92
  chirp_emul_state state;
93
  unsigned_word return_address;
94
  unsigned_word arguments;
95
  unsigned_word n_args;
96
  unsigned_word n_returns;
97
  chirp_services *service;
98
  device *root;
99
  chirp_services *services;
100
  /* configuration */
101
  unsigned_word memory_size;
102
  unsigned_word real_base;
103
  unsigned_word real_size;
104
  unsigned_word virt_base;
105
  unsigned_word virt_size;
106
  int real_mode;
107
  int little_endian;
108
  int floating_point_available;
109
  int interrupt_prefix;
110
  unsigned_word load_base;
111
  /* hash table */
112
  unsigned_word nr_page_table_entry_groups;
113
  unsigned_word htab_offset;
114
  unsigned_word htab_ra;
115
  unsigned_word htab_va;
116
  unsigned_word sizeof_htab;
117
  /* virtual address of htab */
118
  unsigned_word stack_offset;
119
  unsigned_word stack_ra;
120
  unsigned_word stack_va;
121
  unsigned_word sizeof_stack;
122
  /* addresses of emulation instructions virtual/real */
123
  unsigned_word code_offset;
124
  unsigned_word code_va;
125
  unsigned_word code_ra;
126
  unsigned_word sizeof_code;
127
  unsigned_word code_client_va;
128
  unsigned_word code_client_ra;
129
  unsigned_word code_callback_va;
130
  unsigned_word code_callback_ra;
131
  unsigned_word code_loop_va;
132
  unsigned_word code_loop_ra;
133
};
134
 
135
 
136
/* returns the name of the corresponding Ihandle */
137
static const char *
138
ihandle_name(device_instance *ihandle)
139
{
140
  if (ihandle == NULL)
141
    return "";
142
  else
143
    return device_name(device_instance_device(ihandle));
144
}
145
 
146
 
147
 
148
/* Read/write the argument list making certain that all values are
149
   converted to/from host byte order.
150
 
151
   In the below only n_args+n_returns is read/written */
152
 
153
static int
154
chirp_read_t2h_args(void *args,
155
                    int sizeof_args,
156
                    int n_args,
157
                    int n_returns,
158
                    os_emul_data *data,
159
                    cpu *processor,
160
                    unsigned_word cia)
161
{
162
  unsigned_cell *words;
163
  int i;
164
  /* check against the number of arguments specified by the client
165
     program */
166
  if ((n_args >= 0 && data->n_args != n_args)
167
      || (n_returns >= 0 && data->n_returns != n_returns)) {
168
    TRACE(trace_os_emul, ("%s - invalid nr of args - n_args=%ld, n_returns=%ld\n",
169
                          data->service->name,
170
                          (long)data->n_args,
171
                          (long)data->n_returns));
172
    return -1;
173
  }
174
  /* check that there is enough space */
175
  if (sizeof(unsigned_cell) * (data->n_args + data->n_returns) > sizeof_args)
176
    return -1;
177
  /* bring in the data */
178
  memset(args, 0, sizeof_args);
179
  emul_read_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
180
                   sizeof(unsigned_cell) * (data->n_args + data->n_returns),
181
                   processor, cia);
182
  /* convert all words to host format */
183
  words = args;
184
  for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
185
    words[i] = T2H_cell(words[i]);
186
  return 0;
187
}
188
 
189
static void
190
chirp_write_h2t_args(void *args,
191
                     int sizeof_args,
192
                     os_emul_data *data,
193
                     cpu *processor,
194
                     unsigned_word cia)
195
{
196
  int i;
197
  unsigned_cell *words;
198
  /* convert to target everything */
199
  words = args;
200
  for (i = 0; i < (sizeof_args / sizeof(unsigned_cell)); i++)
201
    words[i] = H2T_cell(words[i]);
202
  /* bring in the data */
203
  emul_write_buffer(args, data->arguments + 3 * sizeof(unsigned_cell),
204
                    sizeof(unsigned_cell) * (data->n_args + data->n_returns),
205
                    processor, cia);
206
}
207
 
208
 
209
/* OpenBoot emulation functions */
210
 
211
/* client interface */
212
 
213
static int
214
chirp_emul_test(os_emul_data *data,
215
                cpu *processor,
216
                unsigned_word cia)
217
{
218
  struct test_args {
219
    /*in*/
220
    unsigned_cell name; /*string*/
221
    /*out*/
222
    unsigned_cell missing;
223
  } args;
224
  char name[32];
225
  chirp_services *service = NULL;
226
  /* read in the arguments */
227
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
228
    return -1;
229
  emul_read_string(name, args.name, sizeof(name),
230
                   processor, cia);
231
  TRACE(trace_os_emul, ("test - in - name=`%s'\n", name));
232
  /* see if we know about the service */
233
  service = data->services;
234
  while (service->name != NULL && strcmp(service->name, name) != 0) {
235
    service++;
236
  }
237
  if (service->name == NULL)
238
    args.missing = -1;
239
  else
240
    args.missing = 0;
241
  /* write the arguments back out */
242
  TRACE(trace_os_emul, ("test - out - missing=%ld\n",
243
                        (long)args.missing));
244
  chirp_write_h2t_args(&args,
245
                       sizeof(args),
246
                       data,
247
                       processor, cia);
248
  return 0;
249
}
250
 
251
 
252
/* Device tree */
253
 
254
static int
255
chirp_emul_peer(os_emul_data *data,
256
                cpu *processor,
257
                unsigned_word cia)
258
{
259
  struct peer_args {
260
    /*in*/
261
    unsigned_cell phandle;
262
    /*out*/
263
    unsigned_cell sibling_phandle;
264
  } args;
265
  device *phandle;
266
  device *sibling_phandle = NULL;
267
  /* read in the arguments */
268
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
269
    return -1;
270
  phandle = external_to_device(data->root, args.phandle);
271
  TRACE(trace_os_emul, ("peer - in - phandle=0x%lx(0x%lx`%s')\n",
272
                        (unsigned long)args.phandle,
273
                        (unsigned long)phandle,
274
                        (phandle == NULL ? "" : device_name(phandle))));
275
  /* find the peer */
276
  if (args.phandle == 0) {
277
    sibling_phandle = data->root;
278
    args.sibling_phandle = device_to_external(sibling_phandle);
279
  }
280
  else if (phandle == NULL) {
281
    sibling_phandle = NULL;
282
    args.sibling_phandle = -1;
283
  }
284
  else {
285
    sibling_phandle = device_sibling(phandle);
286
    if (sibling_phandle == NULL)
287
      args.sibling_phandle = 0;
288
    else
289
      args.sibling_phandle = device_to_external(sibling_phandle);
290
  }
291
  /* write the arguments back out */
292
  TRACE(trace_os_emul, ("peer - out - sibling_phandle=0x%lx(0x%lx`%s')\n",
293
                        (unsigned long)args.sibling_phandle,
294
                        (unsigned long)sibling_phandle,
295
                        (sibling_phandle == NULL ? "" : device_name(sibling_phandle))));
296
  chirp_write_h2t_args(&args,
297
                       sizeof(args),
298
                       data,
299
                       processor, cia);
300
  return 0;
301
}
302
 
303
static int
304
chirp_emul_child(os_emul_data *data,
305
                 cpu *processor,
306
                 unsigned_word cia)
307
{
308
  struct child_args {
309
    /*in*/
310
    unsigned_cell phandle;
311
    /*out*/
312
    unsigned_cell child_phandle;
313
  } args;
314
  device *phandle;
315
  device *child_phandle;
316
  /* read the arguments in */
317
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
318
    return -1;
319
  phandle = external_to_device(data->root, args.phandle);
320
  TRACE(trace_os_emul, ("child - in - phandle=0x%lx(0x%lx`%s')\n",
321
                        (unsigned long)args.phandle,
322
                        (unsigned long)phandle,
323
                        (phandle == NULL ? "" : device_name(phandle))));
324
  /* find a child */
325
  if (args.phandle == 0
326
      || phandle == NULL) {
327
    child_phandle = NULL;
328
    args.child_phandle = -1;
329
  }
330
  else {
331
    child_phandle = device_child(phandle);
332
    if (child_phandle == NULL)
333
      args.child_phandle = 0;
334
    else
335
      args.child_phandle = device_to_external(child_phandle);
336
  }
337
  /* write the result out */
338
  TRACE(trace_os_emul, ("child - out - child_phandle=0x%lx(0x%lx`%s')\n",
339
                        (unsigned long)args.child_phandle,
340
                        (unsigned long)child_phandle,
341
                        (child_phandle == NULL ? "" : device_name(child_phandle))));
342
  chirp_write_h2t_args(&args,
343
                       sizeof(args),
344
                       data,
345
                       processor, cia);
346
  return 0;
347
}
348
 
349
static int
350
chirp_emul_parent(os_emul_data *data,
351
                  cpu *processor,
352
                  unsigned_word cia)
353
{
354
  struct parent_args {
355
    /*in*/
356
    unsigned_cell phandle;
357
    /*out*/
358
    unsigned_cell parent_phandle;
359
  } args;
360
  device *phandle;
361
  device *parent_phandle;
362
  /* read the args in */
363
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
364
    return -1;
365
  phandle = external_to_device(data->root, args.phandle);
366
  TRACE(trace_os_emul, ("parent - in - phandle=0x%lx(0x%lx`%s')\n",
367
                        (unsigned long)args.phandle,
368
                        (unsigned long)phandle,
369
                        (phandle == NULL ? "" : device_name(phandle))));
370
  /* find a parent */
371
  if (args.phandle == 0
372
      || phandle == NULL) {
373
    parent_phandle = NULL;
374
    args.parent_phandle = -1;
375
  }
376
  else {
377
    parent_phandle = device_parent(phandle);
378
    if (parent_phandle == NULL)
379
      args.parent_phandle = 0;
380
    else
381
      args.parent_phandle = device_to_external(parent_phandle);
382
  }
383
  /* return the result */
384
  TRACE(trace_os_emul, ("parent - out - parent_phandle=0x%lx(0x%lx`%s')\n",
385
                        (unsigned long)args.parent_phandle,
386
                        (unsigned long)parent_phandle,
387
                        (parent_phandle == NULL ? "" : device_name(parent_phandle))));
388
  chirp_write_h2t_args(&args,
389
                       sizeof(args),
390
                       data,
391
                       processor, cia);
392
  return 0;
393
}
394
 
395
static int
396
chirp_emul_instance_to_package(os_emul_data *data,
397
                               cpu *processor,
398
                               unsigned_word cia)
399
{
400
  struct instance_to_package_args {
401
    /*in*/
402
    unsigned_cell ihandle;
403
    /*out*/
404
    unsigned_cell phandle;
405
  } args;
406
  device_instance *ihandle;
407
  device *phandle = NULL;
408
  /* read the args in */
409
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
410
    return -1;
411
  ihandle = external_to_device_instance(data->root, args.ihandle);
412
  TRACE(trace_os_emul, ("instance-to-package - in - ihandle=0x%lx(0x%lx`%s')\n",
413
                        (unsigned long)args.ihandle,
414
                        (unsigned long)ihandle,
415
                        ihandle_name(ihandle)));
416
  /* find the corresponding phandle */
417
  if (ihandle == NULL) {
418
    phandle = NULL;
419
    args.phandle = -1;
420
  }
421
  else {
422
    phandle = device_instance_device(ihandle);
423
    args.phandle = device_to_external(phandle);
424
  }
425
  /* return the result */
426
  TRACE(trace_os_emul, ("instance-to-package - out - phandle=0x%lx(0x%lx`%s')\n",
427
                        (unsigned long)args.phandle,
428
                        (unsigned long)phandle,
429
                        (phandle == NULL ? "" : device_name(phandle))));
430
  chirp_write_h2t_args(&args,
431
                       sizeof(args),
432
                       data,
433
                       processor, cia);
434
  return 0;
435
}
436
 
437
static int
438
chirp_emul_getproplen(os_emul_data *data,
439
                      cpu *processor,
440
                      unsigned_word cia)
441
{
442
  struct getproplen_args {
443
    /*in*/
444
    unsigned_cell phandle;
445
    unsigned_cell name;
446
    /*out*/
447
    unsigned_cell proplen;
448
  } args;
449
  char name[32];
450
  device *phandle;
451
  /* read the args in */
452
  if (chirp_read_t2h_args(&args, sizeof(args), 2, 1, data, processor, cia))
453
    return -1;
454
  phandle = external_to_device(data->root, args.phandle);
455
  emul_read_string(name,
456
                   args.name,
457
                   sizeof(name),
458
                   processor, cia);
459
  TRACE(trace_os_emul, ("getproplen - in - phandle=0x%lx(0x%lx`%s') name=`%s'\n",
460
                        (unsigned long)args.phandle,
461
                        (unsigned long)phandle,
462
                        (phandle == NULL ? "" : device_name(phandle)),
463
                        name));
464
  /* find our prop and get its length */
465
  if (args.phandle == 0
466
      || phandle == NULL) {
467
    args.proplen = -1;
468
  }
469
  else {
470
    const device_property *prop = device_find_property(phandle, name);
471
    if (prop == (device_property*)0) {
472
      args.proplen = -1;
473
    }
474
    else {
475
      args.proplen = prop->sizeof_array;
476
    }
477
  }
478
  /* return the result */
479
  TRACE(trace_os_emul, ("getproplen - out - proplen=%ld\n",
480
                        (unsigned long)args.proplen));
481
  chirp_write_h2t_args(&args,
482
                       sizeof(args),
483
                       data,
484
                       processor, cia);
485
  return 0;
486
}
487
 
488
static int
489
chirp_emul_getprop(os_emul_data *data,
490
                   cpu *processor,
491
                   unsigned_word cia)
492
{
493
  struct getprop_args {
494
    /*in*/
495
    unsigned_cell phandle;
496
    unsigned_cell name;
497
    unsigned_cell buf;
498
    unsigned_cell buflen;
499
    /*out*/
500
    unsigned_cell size;
501
  } args;
502
  char name[32];
503
  device *phandle;
504
  /* read in the args, the return is optional */
505
  if (chirp_read_t2h_args(&args, sizeof(args), 4, -1, data, processor, cia))
506
    return -1;
507
  phandle = external_to_device(data->root, args.phandle);
508
  emul_read_string(name,
509
                   args.name,
510
                   sizeof(name),
511
                   processor, cia);
512
  TRACE(trace_os_emul, ("getprop - in - phandle=0x%lx(0x%lx`%s') name=`%s' buf=0x%lx buflen=%ld\n",
513
                        (unsigned long)args.phandle,
514
                        (unsigned long)phandle,
515
                        (phandle == NULL ? "" : device_name(phandle)),
516
                        name,
517
                        (unsigned long)args.buf,
518
                        (unsigned long)args.buflen));
519
  /* get the property */
520
  if (args.phandle == 0
521
      || phandle == NULL) {
522
    args.size = -1;
523
  }
524
  else {
525
    const device_property *prop = device_find_property(phandle, name);
526
    if (prop == NULL) {
527
      args.size = -1;
528
    }
529
    else {
530
      int size = args.buflen;
531
      if (size > prop->sizeof_array)
532
        size = prop->sizeof_array;
533
      emul_write_buffer(prop->array, args.buf,
534
                        size,
535
                        processor, cia);
536
      args.size = size;
537
      switch (prop->type) {
538
      case string_property:
539
        TRACE(trace_os_emul, ("getprop - string `%s'\n",
540
                              device_find_string_property(phandle, name)));
541
        break;
542
      case ihandle_property:
543
        TRACE(trace_os_emul, ("getprop - ihandle=0x%lx(0x%lx`%s')\n",
544
                              BE2H_cell(*(unsigned_cell*)prop->array),
545
                              (unsigned long)device_find_ihandle_property(phandle, name),
546
                              ihandle_name(device_find_ihandle_property(phandle, name))));
547
        break;
548
      default:
549
        break;
550
      }
551
    }
552
  }
553
  /* write back the result */
554
  if (data->n_returns == 0)
555
    TRACE(trace_os_emul, ("getprop - out - size=%ld (not returned)\n",
556
                          (unsigned long)args.size));
557
  else {
558
    TRACE(trace_os_emul, ("getprop - out - size=%ld\n",
559
                          (unsigned long)args.size));
560
    chirp_write_h2t_args(&args,
561
                         sizeof(args),
562
                         data,
563
                         processor, cia);
564
  }
565
  return 0;
566
}
567
 
568
static int
569
chirp_emul_nextprop(os_emul_data *data,
570
                    cpu *processor,
571
                    unsigned_word cia)
572
{
573
  struct nextprop_args {
574
    /*in*/
575
    unsigned_cell phandle;
576
    unsigned_cell previous;
577
    unsigned_cell buf;
578
    /*out*/
579
    unsigned_cell flag;
580
  } args;
581
  char previous[32];
582
  device *phandle;
583
  /* read in the args */
584
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
585
    return -1;
586
  phandle = external_to_device(data->root, args.phandle);
587
  emul_read_string(previous,
588
                   args.previous,
589
                   sizeof(previous),
590
                   processor, cia);
591
  TRACE(trace_os_emul, ("nextprop - in - phandle=0x%lx(0x%lx`%s') previous=`%s' buf=0x%lx\n",
592
                        (unsigned long)args.phandle,
593
                        (unsigned long)phandle,
594
                        (phandle == NULL ? "" : device_name(phandle)),
595
                        previous,
596
                        (unsigned long)args.buf));
597
  /* find the next property */
598
  if (args.phandle == 0
599
      || phandle == NULL) {
600
    args.flag = -1;
601
  }
602
  else {
603
    const device_property *prev_prop = device_find_property(phandle, previous);
604
    if (prev_prop == NULL) {
605
      args.flag = -1; /* name invalid */
606
    }
607
    else {
608
      const device_property *next_prop;
609
      next_prop = device_next_property(prev_prop);
610
      if (next_prop == NULL) {
611
        args.flag = 0; /* last property */
612
      }
613
      else {
614
        emul_write_buffer(next_prop->name, args.buf, strlen(next_prop->name),
615
                          processor, cia);
616
        TRACE(trace_os_emul, ("nextprop - name=`%s'\n", next_prop->name));
617
        args.flag = 1; /* worked ok */
618
      }
619
    }
620
  }
621
  /* write back the result */
622
  TRACE(trace_os_emul, ("nextprop - out - flag=%ld\n",
623
                        (unsigned long)args.flag));
624
  chirp_write_h2t_args(&args,
625
                       sizeof(args),
626
                       data,
627
                       processor, cia);
628
  return 0;
629
}
630
 
631
#if 0
632
static int
633
chirp_emul_setprop(os_emul_data *data,
634
                   cpu *processor,
635
                   unsigned_word cia)
636
{
637
  error("chirp: setprop method not implemented\n");
638
  return 0;
639
}
640
#endif
641
 
642
static int
643
chirp_emul_canon(os_emul_data *data,
644
                 cpu *processor,
645
                 unsigned_word cia)
646
{
647
  struct canon_args {
648
    /*in*/
649
    unsigned_cell device_specifier;
650
    unsigned_cell buf;
651
    unsigned_cell buflen;
652
    /*out*/
653
    unsigned_cell length;
654
  } args;
655
  char device_specifier[1024];
656
  device *phandle;
657
  const char *path;
658
  int length;
659
  /* read in the args */
660
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
661
    return -1;
662
  emul_read_string(device_specifier,
663
                   args.device_specifier,
664
                   sizeof(device_specifier),
665
                   processor, cia);
666
  TRACE(trace_os_emul, ("canon - in - device_specifier=`%s' buf=0x%lx buflen=%lx\n",
667
                        device_specifier,
668
                        (unsigned long)args.buf,
669
                        (unsigned long)args.buflen));
670
  /* canon the name */
671
  phandle = tree_find_device(data->root, device_specifier);
672
  if (phandle == NULL) {
673
    length = -1;
674
    path = "";
675
    args.length = -1;
676
  }
677
  else {
678
    path = device_path(phandle);
679
    length = strlen(path);
680
    if (length >= args.buflen)
681
      length = args.buflen - 1;
682
    emul_write_buffer(path, args.buf, length,
683
                      processor, cia);
684
    args.length = length;
685
  }
686
  /* write back the result */
687
  TRACE(trace_os_emul, ("canon - out - length=%ld buf=`%s'\n",
688
                        (unsigned long)args.length,
689
                        path));
690
  chirp_write_h2t_args(&args,
691
                       sizeof(args),
692
                       data,
693
                       processor, cia);
694
  return 0;
695
}
696
 
697
static int
698
chirp_emul_finddevice(os_emul_data *data,
699
                      cpu *processor,
700
                      unsigned_word cia)
701
{
702
  struct finddevice_args {
703
    /*in*/
704
    unsigned_cell device_specifier;
705
    /*out*/
706
    unsigned_cell phandle;
707
  } args;
708
  char device_specifier[1024];
709
  device *phandle;
710
  /* get the args */
711
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
712
    return -1;
713
  emul_read_string(device_specifier,
714
                   args.device_specifier,
715
                   sizeof(device_specifier),
716
                   processor, cia);
717
  TRACE(trace_os_emul, ("finddevice - in - device_specifier=`%s'\n",
718
                        device_specifier));
719
  /* find the device */
720
  phandle = tree_find_device(data->root, device_specifier);
721
  if (phandle == NULL)
722
    args.phandle = -1;
723
  else
724
    args.phandle = device_to_external(phandle);
725
  /* return its phandle */
726
  TRACE(trace_os_emul, ("finddevice - out - phandle=0x%lx(0x%lx`%s')\n",
727
                        (unsigned long)args.phandle,
728
                        (unsigned long)phandle,
729
                        (phandle == NULL ? "" : device_name(phandle))));
730
  chirp_write_h2t_args(&args,
731
                       sizeof(args),
732
                       data,
733
                       processor, cia);
734
  return 0;
735
}
736
 
737
static int
738
chirp_emul_instance_to_path(os_emul_data *data,
739
                            cpu *processor,
740
                            unsigned_word cia)
741
{
742
  struct instance_to_path_args {
743
    /*in*/
744
    unsigned_cell ihandle;
745
    unsigned_cell buf;
746
    unsigned_cell buflen;
747
    /*out*/
748
    unsigned_cell length;
749
  } args;
750
  device_instance *ihandle;
751
  const char *path;
752
  int length;
753
  /* get the args */
754
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
755
    return -1;
756
  ihandle = external_to_device_instance(data->root, args.ihandle);
757
  TRACE(trace_os_emul, ("instance-to-path - in - ihandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
758
                        (unsigned long)args.ihandle,
759
                        (unsigned long)ihandle,
760
                        ihandle_name(ihandle),
761
                        (unsigned long)args.buf,
762
                        (unsigned long)args.buflen));
763
  /* get the devices name */
764
  if (ihandle == NULL) {
765
    args.length = -1;
766
    path = "(null)";
767
  }
768
  else {
769
    path = device_instance_path(ihandle);
770
    length = strlen(path);
771
    if (length >= args.buflen)
772
      length = args.buflen - 1;
773
    emul_write_buffer(path, args.buf, length,
774
                      processor, cia);
775
    args.length = length;
776
  }
777
  /* return its phandle */
778
  TRACE(trace_os_emul, ("instance-to-path - out - length=%ld buf=`%s')\n",
779
                        (unsigned long)args.length,
780
                        path));
781
  chirp_write_h2t_args(&args,
782
                       sizeof(args),
783
                       data,
784
                       processor, cia);
785
  return 0;
786
}
787
 
788
static int
789
chirp_emul_package_to_path(os_emul_data *data,
790
                           cpu *processor,
791
                           unsigned_word cia)
792
{
793
  struct package_to_path_args {
794
    /*in*/
795
    unsigned_cell phandle;
796
    unsigned_cell buf;
797
    unsigned_cell buflen;
798
    /*out*/
799
    unsigned_cell length;
800
  } args;
801
  device *phandle;
802
  const char *path;
803
  /* get the args */
804
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
805
    return -1;
806
  phandle = external_to_device(data->root, args.phandle);
807
  TRACE(trace_os_emul, ("package-to-path - in - phandle=0x%lx(0x%lx`%s') buf=0x%lx buflen=%ld\n",
808
                        (unsigned long)args.phandle,
809
                        (unsigned long)phandle,
810
                        (phandle == NULL ? "" : device_name(phandle)),
811
                        (unsigned long)args.buf,
812
                        (unsigned long)args.buflen));
813
  /* get the devices name */
814
  if (phandle == NULL) {
815
    args.length = -1;
816
    path = "(null)";
817
  }
818
  else {
819
    int length;
820
    path = device_path(phandle);
821
    length = strlen(path);
822
    if (length >= args.buflen)
823
      length = args.buflen - 1;
824
    emul_write_buffer(path, args.buf, length,
825
                      processor, cia);
826
    args.length = length;
827
  }
828
  /* return its phandle */
829
  TRACE(trace_os_emul, ("package-to-path - out - length=%ld buf=`%s')\n",
830
                        (unsigned long)args.length,
831
                        path));
832
  chirp_write_h2t_args(&args,
833
                       sizeof(args),
834
                       data,
835
                       processor, cia);
836
  return 0;
837
}
838
 
839
static int
840
chirp_emul_call_method(os_emul_data *data,
841
                       cpu *processor,
842
                       unsigned_word cia)
843
{
844
  struct call_method_args {
845
    /*in*/
846
    unsigned_cell method;
847
    unsigned_cell ihandle;
848
    /*in/out*/
849
    unsigned_cell stack[13]; /*6in + 6out + catch */
850
  } args;
851
  char method[32];
852
  device_instance *ihandle;
853
  /* some useful info about our mini stack */
854
  int n_stack_args;
855
  int n_stack_returns;
856
  int stack_catch_result;
857
  int stack_returns;
858
  /* read the args */
859
  if (chirp_read_t2h_args(&args, sizeof(args), -1, -1, data, processor, cia))
860
    return -1;
861
  emul_read_string(method,
862
                   args.method,
863
                   sizeof(method),
864
                   processor, cia);
865
  ihandle = external_to_device_instance(data->root, args.ihandle);
866
  n_stack_args = data->n_args - 2;
867
  n_stack_returns = data->n_returns - 1;
868
  stack_catch_result = n_stack_args;
869
  stack_returns = stack_catch_result + 1;
870
  TRACE(trace_os_emul, ("call-method - in - n_args=%ld n_returns=%ld method=`%s' ihandle=0x%lx(0x%lx`%s')\n",
871
                        (unsigned long)data->n_args,
872
                        (unsigned long)data->n_returns,
873
                        method,
874
                        (unsigned long)args.ihandle,
875
                        (unsigned long)ihandle,
876
                        ihandle_name(ihandle)));
877
  /* see if we can emulate this method */
878
  if (ihandle == NULL) {
879
    /* OpenFirmware doesn't define this error */
880
    error("chirp: invalid ihandle passed to call-method method");
881
  }
882
  else {
883
    args.stack[stack_catch_result] =
884
      device_instance_call_method(ihandle,
885
                                  method,
886
                                  n_stack_args,
887
                                  &args.stack[0],
888
                                  n_stack_returns,
889
                                  &args.stack[stack_returns]);
890
  }
891
  /* finished */
892
  TRACE(trace_os_emul, ("call-method - out - catch-result=%ld\n",
893
                        (unsigned long)args.stack[stack_catch_result]));
894
  chirp_write_h2t_args(&args,
895
                       sizeof(args),
896
                       data,
897
                       processor, cia);
898
  return 0;
899
}
900
 
901
 
902
/* Device I/O */
903
 
904
static int
905
chirp_emul_open(os_emul_data *data,
906
                cpu *processor,
907
                unsigned_word cia)
908
{
909
  struct open_args {
910
    /*in*/
911
    unsigned_cell device_specifier;
912
    /*out*/
913
    unsigned_cell ihandle;
914
  } args;
915
  char device_specifier[1024];
916
  device_instance *ihandle;
917
  /* read the args */
918
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
919
    return -1;
920
  emul_read_string(device_specifier,
921
                   args.device_specifier,
922
                   sizeof(device_specifier),
923
                   processor, cia);
924
  TRACE(trace_os_emul, ("open - in - device_specifier=`%s'\n",
925
                        device_specifier));
926
  /* open the device */
927
  ihandle = tree_instance(data->root, device_specifier);
928
  if (ihandle == NULL)
929
    args.ihandle = -1;
930
  else
931
    args.ihandle = device_instance_to_external(ihandle);
932
  /* return the ihandle result */
933
  TRACE(trace_os_emul, ("open - out - ihandle=0x%lx(0x%lx`%s')\n",
934
                        (unsigned long)args.ihandle,
935
                        (unsigned long)ihandle,
936
                        ihandle_name(ihandle)));
937
  chirp_write_h2t_args(&args,
938
                       sizeof(args),
939
                       data,
940
                       processor, cia);
941
  return 0;
942
}
943
 
944
static int
945
chirp_emul_close(os_emul_data *data,
946
                 cpu *processor,
947
                 unsigned_word cia)
948
{
949
  struct close_args {
950
    /*in*/
951
    unsigned_cell ihandle;
952
    /*out*/
953
  } args;
954
  device_instance *ihandle;
955
  /* read the args */
956
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 0, data, processor, cia))
957
    return -1;
958
  ihandle = external_to_device_instance(data->root, args.ihandle);
959
  TRACE(trace_os_emul, ("close - in - ihandle=0x%lx(0x%lx`%s')\n",
960
                        (unsigned long)args.ihandle,
961
                        (unsigned long)ihandle,
962
                        ihandle_name(ihandle)));
963
  /* close the device */
964
  if (ihandle == NULL) {
965
    /* OpenFirmware doesn't define this error */
966
    error("chirp: invalid ihandle passed to close method");
967
  }
968
  else {
969
    device_instance_delete(ihandle);
970
  }
971
  /* return the ihandle result */
972
  TRACE(trace_os_emul, ("close - out\n"));
973
  chirp_write_h2t_args(&args,
974
                       sizeof(args),
975
                       data,
976
                       processor, cia);
977
  return 0;
978
}
979
 
980
static int
981
chirp_emul_read(os_emul_data *data,
982
                cpu *processor,
983
                unsigned_word cia)
984
{
985
  struct read_args {
986
    /*in*/
987
    unsigned_cell ihandle;
988
    unsigned_cell addr;
989
    unsigned_cell len;
990
    /*out*/
991
    unsigned_cell actual;
992
  } args;
993
  char buf[1024];
994
  device_instance *ihandle;
995
  /* read the args */
996
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
997
    return -1;
998
  ihandle = external_to_device_instance(data->root, args.ihandle);
999
  TRACE(trace_os_emul, ("read - in - ihandle=0x%lx(0x%lx`%s') addr=0x%lx len=%ld\n",
1000
                        (unsigned long)args.ihandle,
1001
                        (unsigned long)ihandle,
1002
                        ihandle_name(ihandle),
1003
                        (unsigned long)args.addr,
1004
                        (unsigned long)args.len));
1005
  if (ihandle == NULL) {
1006
    /* OpenFirmware doesn't define this error */
1007
    error("chirp: invalid ihandle passed to read method");
1008
  }
1009
  else {
1010
    /* do the reads */
1011
    int actual = 0;
1012
    while (actual < args.len) {
1013
      int remaining = args.len - actual;
1014
      int to_read = (remaining <= sizeof(buf) ? remaining : sizeof(buf));
1015
      int nr_read = device_instance_read(ihandle, buf, to_read);
1016
      if (nr_read < 0) {
1017
        actual = nr_read; /* the error */
1018
        break;
1019
      }
1020
      else if (nr_read == 0) {
1021
        break;
1022
      }
1023
      emul_write_buffer(buf,
1024
                        args.addr + actual,
1025
                        nr_read,
1026
                        processor, cia);
1027
      actual += nr_read;
1028
    }
1029
    if (actual >= 0) {
1030
      args.actual = actual;
1031
      if (actual < sizeof(buf))
1032
        buf[actual] = '\0';
1033
      else
1034
        buf[sizeof(buf) - 1] = '\0';
1035
    }
1036
    else {
1037
      switch (actual) {
1038
      case sim_io_eof:
1039
        args.actual = 0;
1040
        break;
1041
      case sim_io_not_ready:
1042
        ASSERT(sim_io_not_ready == -2);
1043
        args.actual = sim_io_not_ready;
1044
        break;
1045
      default:
1046
        error("Bad error value %ld", (long)actual);
1047
        break;
1048
      }
1049
    }
1050
  }
1051
  /* return the result */
1052
  TRACE(trace_os_emul, ("read - out - actual=%ld `%s'\n",
1053
                        (long)args.actual,
1054
                        ((args.actual > 0 && args.actual < sizeof(buf)) ? buf : "")
1055
                        ));
1056
  chirp_write_h2t_args(&args,
1057
                       sizeof(args),
1058
                       data,
1059
                       processor, cia);
1060
  return 0;
1061
}
1062
 
1063
static int
1064
chirp_emul_write(os_emul_data *data,
1065
                 cpu *processor,
1066
                 unsigned_word cia)
1067
{
1068
  struct write_args {
1069
    /*in*/
1070
    unsigned_cell ihandle;
1071
    unsigned_cell addr;
1072
    unsigned_cell len;
1073
    /*out*/
1074
    unsigned_cell actual;
1075
  } args;
1076
  char buf[1024];
1077
  device_instance *ihandle;
1078
  int actual;
1079
  /* get the args */
1080
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
1081
    return -1;
1082
  actual = args.len;
1083
  if (actual >= sizeof(buf))
1084
    actual = sizeof(buf) - 1;
1085
  emul_read_buffer(buf,
1086
                   args.addr,
1087
                   actual,
1088
                   processor, cia);
1089
  buf[actual] = '\0';
1090
  ihandle = external_to_device_instance(data->root, args.ihandle);
1091
  TRACE(trace_os_emul, ("write - in - ihandle=0x%lx(0x%lx`%s') `%s' (%ld)\n",
1092
                        (unsigned long)args.ihandle,
1093
                        (unsigned long)ihandle,
1094
                        ihandle_name(ihandle),
1095
                        buf, (long)actual));
1096
  if (ihandle == NULL) {
1097
    /* OpenFirmware doesn't define this error */
1098
    error("chirp: invalid ihandle passed to write method");
1099
  }
1100
  else {
1101
    /* write it out */
1102
    actual = device_instance_write(ihandle, buf, actual);
1103
    if (actual < 0)
1104
      args.actual = 0;
1105
    else
1106
      args.actual = actual;
1107
  }
1108
  /* return the result */
1109
  TRACE(trace_os_emul, ("write - out - actual=%ld\n",
1110
                        (long)args.actual));
1111
  chirp_write_h2t_args(&args,
1112
                       sizeof(args),
1113
                       data,
1114
                       processor, cia);
1115
  return 0;
1116
}
1117
 
1118
static int
1119
chirp_emul_seek(os_emul_data *data,
1120
                cpu *processor,
1121
                unsigned_word cia)
1122
{
1123
  struct seek_args {
1124
    /*in*/
1125
    unsigned_cell ihandle;
1126
    unsigned_cell pos_hi;
1127
    unsigned_cell pos_lo;
1128
    /*out*/
1129
    unsigned_cell status;
1130
  } args;
1131
  int status;
1132
  device_instance *ihandle;
1133
  /* get the args */
1134
  if (chirp_read_t2h_args(&args, sizeof(args), 3, 1, data, processor, cia))
1135
    return -1;
1136
  ihandle = external_to_device_instance(data->root, args.ihandle);
1137
  TRACE(trace_os_emul, ("seek - in - ihandle=0x%lx(0x%lx`%s') pos.hi=0x%lx pos.lo=0x%lx\n",
1138
                        (unsigned long)args.ihandle,
1139
                        (unsigned long)ihandle,
1140
                        ihandle_name(ihandle),
1141
                        args.pos_hi, args.pos_lo));
1142
  if (ihandle == NULL) {
1143
    /* OpenFirmware doesn't define this error */
1144
    error("chirp: invalid ihandle passed to seek method");
1145
  }
1146
  else {
1147
    /* seek it out */
1148
    status = device_instance_seek(ihandle, args.pos_hi, args.pos_lo);
1149
    args.status = status;
1150
  }
1151
  /* return the result */
1152
  TRACE(trace_os_emul, ("seek - out - status=%ld\n",
1153
                        (long)args.status));
1154
  chirp_write_h2t_args(&args,
1155
                       sizeof(args),
1156
                       data,
1157
                       processor, cia);
1158
  return 0;
1159
}
1160
 
1161
 
1162
/* memory */
1163
 
1164
static int
1165
chirp_emul_claim(os_emul_data *data,
1166
                 cpu *processor,
1167
                 unsigned_word cia)
1168
{
1169
  /* NOTE: the client interface claim routine is *very* different to
1170
     the "claim" method described in IEEE-1275 appendix A.  The latter
1171
     uses real addresses while this uses virtual (effective)
1172
     addresses. */
1173
  struct claim_args {
1174
    /* in */
1175
    unsigned_cell virt;
1176
    unsigned_cell size;
1177
    unsigned_cell align;
1178
    /* out */
1179
    unsigned_cell baseaddr;
1180
  } args;
1181
  /* read the args */
1182
  if (chirp_read_t2h_args(&args, sizeof(args),
1183
                          3 /*n_args*/, 1 /*n_returns*/,
1184
                          data, processor, cia))
1185
    return -1;
1186
  TRACE(trace_os_emul, ("claim - in - virt=0x%lx size=%ld align=%d\n",
1187
                        (unsigned long)args.virt,
1188
                        (long int)args.size,
1189
                        (int)args.align));
1190
  /* use the memory device to allocate (real) memory at the requested
1191
     address */
1192
  {
1193
    device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
1194
    unsigned_cell mem_in[3];
1195
    unsigned_cell mem_out[1];
1196
    mem_in[0] = args.align; /*top-of-stack*/
1197
    mem_in[1] = args.size;
1198
    mem_in[2] = args.virt;
1199
    if (device_instance_call_method(memory, "claim",
1200
                                    3, mem_in, 1, mem_out) < 0)
1201
      error("chirp: claim failed to allocate memory virt=0x%lx size=%ld align=%d",
1202
            (unsigned long)args.virt,
1203
            (long int)args.size,
1204
            (int)args.align);
1205
    args.baseaddr = mem_out[0];
1206
  }
1207
  /* if using virtual addresses, create a 1-1 map of this address space */
1208
  if (!data->real_mode) {
1209
    error("chirp: claim method does not support virtual mode");
1210
  }
1211
  /* return the base address */
1212
  TRACE(trace_os_emul, ("claim - out - baseaddr=0x%lx\n",
1213
                        (unsigned long)args.baseaddr));
1214
  chirp_write_h2t_args(&args,
1215
                       sizeof(args),
1216
                       data,
1217
                       processor, cia);
1218
  return 0;
1219
}
1220
 
1221
static int
1222
chirp_emul_release(os_emul_data *data,
1223
                   cpu *processor,
1224
                   unsigned_word cia)
1225
{
1226
  /* NOTE: the client interface release routine is *very* different to
1227
     the "claim" method described in IEEE-1275 appendix A.  The latter
1228
     uses real addresses while this uses virtual (effective)
1229
     addresses. */
1230
  struct claim_args {
1231
    /* in */
1232
    unsigned_cell virt;
1233
    unsigned_cell size;
1234
    /* out */
1235
  } args;
1236
  /* read the args */
1237
  if (chirp_read_t2h_args(&args, sizeof(args),
1238
                          2 /*n_args*/, 0 /*n_returns*/,
1239
                          data, processor, cia))
1240
    return -1;
1241
  TRACE(trace_os_emul, ("release - in - virt=0x%lx size=%ld\n",
1242
                        (unsigned long)args.virt,
1243
                        (long int)args.size));
1244
  /* use the memory device to release (real) memory at the requested
1245
     address */
1246
  {
1247
    device_instance *memory = tree_find_ihandle_property(data->root, "/chosen/memory");
1248
    unsigned_cell mem_in[2];
1249
    mem_in[0] = args.size;
1250
    mem_in[1] = args.virt;
1251
    if (device_instance_call_method(memory, "release",
1252
                                    2, mem_in, 0, NULL) < 0)
1253
      error("chirp: claim failed to release memory virt=0x%lx size=%ld",
1254
            (unsigned long)args.virt,
1255
            (long int)args.size);
1256
  }
1257
  /* if using virtual addresses, remove the 1-1 map of this address space */
1258
  if (!data->real_mode) {
1259
    error("chirp: release method does not support virtual mode");
1260
  }
1261
  /* return the base address */
1262
  TRACE(trace_os_emul, ("release - out\n"));
1263
  chirp_write_h2t_args(&args,
1264
                       sizeof(args),
1265
                       data,
1266
                       processor, cia);
1267
  return 0;
1268
}
1269
 
1270
 
1271
/* Control transfer */
1272
 
1273
static int
1274
chirp_emul_boot(os_emul_data *data,
1275
                cpu *processor,
1276
                unsigned_word cia)
1277
{
1278
  /* unlike OpenFirmware this one can take an argument */
1279
  struct boot_args {
1280
    /*in*/
1281
    unsigned_cell bootspec;
1282
    /*out*/
1283
  } args;
1284
  char bootspec[1024];
1285
  /* read in the arguments */
1286
  if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
1287
    cpu_halt(processor, cia, was_exited, -1);
1288
  if (args.bootspec != 0)
1289
    emul_read_string(bootspec, args.bootspec, sizeof(bootspec),
1290
                     processor, cia);
1291
  else
1292
    strcpy(bootspec, "(null)");
1293
  TRACE(trace_os_emul, ("boot - in bootspec=`%s'\n", bootspec));
1294
  /* just report this and exit */
1295
  printf_filtered("chrp: boot %s called, exiting.\n", bootspec);
1296
  cpu_halt(processor, cia, was_exited, 0);
1297
  return 0;
1298
}
1299
 
1300
static int
1301
chirp_emul_enter(os_emul_data *data,
1302
                 cpu *processor,
1303
                 unsigned_word cia)
1304
{
1305
  error("chirp: enter method not implemented\n");
1306
  return 0;
1307
}
1308
 
1309
static int
1310
chirp_emul_exit(os_emul_data *data,
1311
                cpu *processor,
1312
                unsigned_word cia)
1313
{
1314
  /* unlike OpenBoot this one can take an argument */
1315
  struct exit_args {
1316
    /*in*/
1317
    signed_cell status;
1318
    /*out*/
1319
  } args;
1320
  if (chirp_read_t2h_args(&args, sizeof(args), -1, 0, data, processor, cia))
1321
    cpu_halt(processor, cia, was_exited, -1);
1322
  cpu_halt(processor, cia, was_exited, args.status);
1323
  return 0;
1324
}
1325
 
1326
static int
1327
chirp_emul_chain(os_emul_data *data,
1328
                 cpu *processor,
1329
                 unsigned_word cia)
1330
{
1331
  error("chirp: chain method not implemented\n");
1332
  return 0;
1333
}
1334
 
1335
 
1336
/* user interface */
1337
 
1338
static int
1339
chirp_emul_interpret(os_emul_data *data,
1340
                     cpu *processor,
1341
                     unsigned_word cia)
1342
{
1343
  error("chirp: interpret method not implemented\n");
1344
  return 0;
1345
}
1346
 
1347
static int
1348
chirp_emul_set_callback(os_emul_data *data,
1349
                        cpu *processor,
1350
                        unsigned_word cia)
1351
{
1352
  error("chirp: set_callback method not implemented\n");
1353
  return 0;
1354
}
1355
 
1356
static int
1357
chirp_emul_set_symbol_lookup(os_emul_data *data,
1358
                             cpu *processor,
1359
                             unsigned_word cia)
1360
{
1361
  error("chirp: set_symbol_lookup method not implemented\n");
1362
  return 0;
1363
}
1364
 
1365
 
1366
/* Time */
1367
 
1368
static int
1369
chirp_emul_milliseconds(os_emul_data *data,
1370
                        cpu *processor,
1371
                        unsigned_word cia)
1372
{
1373
  struct test_args {
1374
    /*in*/
1375
    /*out*/
1376
    unsigned_cell ms;
1377
  } args;
1378
  unsigned64 time;
1379
  /* read in the arguments */
1380
  if (chirp_read_t2h_args(&args, sizeof(args), 1, 1, data, processor, cia))
1381
    return -1;
1382
  /* make up a number */
1383
  time = event_queue_time(psim_event_queue(cpu_system(processor))) / 1000000;
1384
  args.ms = time;
1385
  /* write the arguments back out */
1386
  TRACE(trace_os_emul, ("milliseconds - out - ms=%ld\n",
1387
                        (unsigned long)args.ms));
1388
  chirp_write_h2t_args(&args,
1389
                       sizeof(args),
1390
                       data,
1391
                       processor, cia);
1392
  return 0;
1393
}
1394
 
1395
 
1396
 
1397
 
1398
static chirp_services services[] = {
1399
 
1400
  /* client interface */
1401
  { "test", chirp_emul_test },
1402
 
1403
  /* device tree */
1404
  { "peer", chirp_emul_peer },
1405
  { "child", chirp_emul_child },
1406
  { "parent", chirp_emul_parent },
1407
  { "instance-to-package", chirp_emul_instance_to_package },
1408
  { "getproplen", chirp_emul_getproplen },
1409
  { "getprop", chirp_emul_getprop },
1410
  { "nextprop", chirp_emul_nextprop },
1411
  /* { "setprop", chirp_emul_setprop }, */
1412
  { "canon", chirp_emul_canon },
1413
  { "finddevice", chirp_emul_finddevice },
1414
  { "instance-to-path", chirp_emul_instance_to_path },
1415
  { "package-to-path", chirp_emul_package_to_path },
1416
  { "call-method", chirp_emul_call_method },
1417
 
1418
  /* device I/O */
1419
  { "open", chirp_emul_open },
1420
  { "close", chirp_emul_close },
1421
  { "read", chirp_emul_read },
1422
  { "write", chirp_emul_write },
1423
  { "seek", chirp_emul_seek },
1424
  { "write", chirp_emul_write },
1425
 
1426
  /* memory */
1427
  { "claim", chirp_emul_claim },
1428
  { "release", chirp_emul_release },
1429
 
1430
  /* control transfer */
1431
  { "boot", chirp_emul_boot },
1432
  { "enter", chirp_emul_enter },
1433
  { "exit", chirp_emul_exit },
1434
  { "chain", chirp_emul_chain },
1435
 
1436
  /* user interface */
1437
  { "interpret", chirp_emul_interpret },
1438
  { "set_callback", chirp_emul_set_callback },
1439
  { "set_symbol_lookup", chirp_emul_set_symbol_lookup },
1440
 
1441
  /* time */
1442
  { "milliseconds", chirp_emul_milliseconds },
1443
 
1444
  { 0, /* sentinal */ },
1445
};
1446
 
1447
 
1448
/* main handlers */
1449
 
1450
/* Any starting address greater than this is assumed to be an Chirp
1451
   rather than VEA */
1452
 
1453
#ifndef CHIRP_START_ADDRESS
1454
#define CHIRP_START_ADDRESS 0x80000000
1455
#endif
1456
#ifndef CHIRP_LOAD_BASE
1457
#define CHIRP_LOAD_BASE -1
1458
#endif
1459
 
1460
 
1461
typedef struct _chirp_note_desc {
1462
  signed32 real_mode;
1463
  signed32 real_base;
1464
  signed32 real_size;
1465
  signed32 virt_base;
1466
  signed32 virt_size;
1467
  signed32 load_base;
1468
} chirp_note_desc;
1469
 
1470
typedef enum {
1471
  note_missing,
1472
  note_found,
1473
  note_correct,
1474
} note_found_status;
1475
typedef struct _chirp_note {
1476
  chirp_note_desc desc;
1477
  note_found_status found;
1478
} chirp_note;
1479
 
1480
typedef struct _chirp_note_head {
1481
  unsigned32 namesz;
1482
  unsigned32 descsz;
1483
  unsigned32 type;
1484
} chirp_note_head;
1485
 
1486
static void
1487
map_over_chirp_note(bfd *image,
1488
                    asection *sect,
1489
                    PTR obj)
1490
{
1491
  chirp_note *note = (chirp_note*)obj;
1492
  if (strcmp(sect->name, ".note") == 0) {
1493
    chirp_note_head head;
1494
    char name[16];
1495
    /* check the head */
1496
    if (!bfd_get_section_contents(image, sect,
1497
                                  &head, 0, sizeof(head)))
1498
      return;
1499
    head.namesz = bfd_get_32(image, (void*)&head.namesz);
1500
    head.descsz = bfd_get_32(image, (void*)&head.descsz);
1501
    head.type = bfd_get_32(image, (void*)&head.type);
1502
    if (head.type != 0x1275)
1503
      return;
1504
    /* check the name field */
1505
    if (head.namesz > sizeof(name)) {
1506
      error("chirp: note name too long (%d > %d)\n", (int)head.namesz, sizeof(name));
1507
    }
1508
    if (!bfd_get_section_contents(image, sect,
1509
                                  name, sizeof(head), head.namesz)) {
1510
      error("chirp: note name unreadable\n");
1511
    }
1512
    if (strcmp(name, "PowerPC") != 0) {
1513
      printf_filtered("chirp: note name (%s) not `PowerPC'\n", name);
1514
    }
1515
    /* check the size */
1516
    if (head.descsz == sizeof(note->desc) - sizeof(signed32)) {
1517
      sim_io_printf_filtered("chirp: note descriptor missing load-base\n");
1518
    }
1519
    else if (head.descsz != sizeof(note->desc)) {
1520
      sim_io_printf_filtered("chirp: note descriptor of wrong size\n");
1521
      note->found = note_found;
1522
      return;
1523
    }
1524
    note->found = note_correct;
1525
    /* get the contents */
1526
    if (!bfd_get_section_contents(image, sect,
1527
                                  &note->desc, /* page align start */
1528
                                  ((sizeof(head) + head.namesz) + 3) & ~3,
1529
                                  head.descsz)) {
1530
      error("chirp: note descriptor unreadable\n");
1531
    }
1532
    note->desc.real_mode = bfd_get_32(image, (void*)&note->desc.real_mode);
1533
    note->desc.real_base = bfd_get_32(image, (void*)&note->desc.real_base);
1534
    note->desc.real_size = bfd_get_32(image, (void*)&note->desc.real_size);
1535
    note->desc.virt_base = bfd_get_32(image, (void*)&note->desc.virt_base);
1536
    note->desc.virt_size = bfd_get_32(image, (void*)&note->desc.virt_size);
1537
    if (head.descsz == sizeof(note->desc))
1538
      note->desc.load_base = bfd_get_32(image, (void*)&note->desc.load_base);
1539
    else
1540
      note->desc.load_base = CHIRP_LOAD_BASE;
1541
  }
1542
}
1543
 
1544
 
1545
static os_emul_data *
1546
emul_chirp_create(device *root,
1547
                  bfd *image,
1548
                  const char *name)
1549
{
1550
  os_emul_data *chirp;
1551
  device *node;
1552
  chirp_note note;
1553
  int i;
1554
 
1555
  /* Sanity check that this really is the chosen emulation */
1556
  if (name == NULL && image == NULL)
1557
    return NULL;
1558
  if (name != NULL
1559
      && strcmp(name, "ob") != 0
1560
      && strcmp(name, "ieee1274") != 0
1561
      && strcmp(name, "chrp") != 0
1562
      && strcmp(name, "chirp") != 0
1563
      && strcmp(name, "openboot") != 0)
1564
    return NULL;
1565
 
1566
  /* look for an elf note section, enter its values into the device tree */
1567
  memset(&note, 0, sizeof(note));
1568
  if (image != NULL)
1569
    bfd_map_over_sections(image, map_over_chirp_note, &note);
1570
  if (name == NULL && image != NULL && note.found == note_missing)
1571
    return NULL;
1572
 
1573
  /* Assume that it is a chirp emulation */
1574
 
1575
  chirp = ZALLOC(os_emul_data);
1576
  chirp->root = root;
1577
  chirp->services = services;
1578
 
1579
  /* the root node */
1580
  tree_parse(root, "/name \"gpl,clayton");
1581
 
1582
  /* default options */
1583
  emul_add_tree_options(root, image, "chirp", "oea",
1584
 
1585
 
1586
  /* hardware */
1587
  emul_add_tree_hardware(root);
1588
 
1589
  /* basic information */
1590
  chirp->memory_size
1591
    = tree_find_integer_property(root, "/openprom/options/oea-memory-size");
1592
  chirp->little_endian
1593
    = tree_find_boolean_property(root, "/options/little-endian?");
1594
  chirp->floating_point_available
1595
    = tree_find_boolean_property(root, "/openprom/options/floating-point?");
1596
  chirp->interrupt_prefix =
1597
    tree_find_integer_property(root, "/openprom/options/oea-interrupt-prefix");
1598
 
1599
 
1600
  /* Perform an interum layout of the openboot firmware in memory */
1601
 
1602
 
1603
  /* a page for firmware calls */
1604
  chirp->sizeof_code = 4096;
1605
  chirp->code_offset = 0x4000; /* possible space for interrupt table */
1606
 
1607
  /* the stack */
1608
  chirp->sizeof_stack = 32 * 1024;
1609
  chirp->stack_offset = chirp->code_offset + chirp->sizeof_code;
1610
 
1611
  /* the hash table */
1612
  if (!note.desc.real_mode) {
1613
    chirp->nr_page_table_entry_groups = (chirp->memory_size < 0x800000
1614
                                         ? 1024 /* min allowed */
1615
                                         : (chirp->memory_size / 4096 / 2));
1616
    chirp->sizeof_htab = chirp->nr_page_table_entry_groups * 64;
1617
  }
1618
  chirp->htab_offset = chirp->stack_offset + chirp->sizeof_stack;
1619
 
1620
  /* the actual amount of space needed */
1621
  chirp->real_size = chirp->htab_offset + chirp->sizeof_htab;
1622
 
1623
 
1624
  /* now go through and see if it fits in what is available */
1625
 
1626
 
1627
  /* resolve real-mode? */
1628
  if (note.found == note_correct)
1629
    chirp->real_mode = note.desc.real_mode;
1630
  else if (tree_find_property(root, "/options/real-mode?") != NULL)
1631
    chirp->real_mode = tree_find_boolean_property(root, "/options/real-mode?");
1632
  else
1633
    chirp->real_mode = 0;
1634
  if (tree_find_property(root, "/options/real-mode?") != NULL) {
1635
    if (!chirp->real_mode
1636
        != !tree_find_boolean_property(root, "/options/real-mode?"))
1637
      error("chirp: /options/real-mode? conflicts with note section\n");
1638
  }
1639
  else
1640
    tree_parse(root, "/options/real-mode? %s",
1641
               chirp->real_mode ? "true" : "false");
1642
 
1643
  /* resolve real-base */
1644
  if (note.found == note_correct
1645
      && note.desc.real_base != (signed32)-1)
1646
    chirp->real_base = note.desc.real_base;
1647
  else if (tree_find_property(root, "/options/real-base") != NULL)
1648
    chirp->real_base = tree_find_integer_property(root, "/options/real-base");
1649
  else
1650
    chirp->real_base = chirp->memory_size - chirp->real_size;
1651
  if (tree_find_property(root, "/options/real-base") != NULL) {
1652
    if (chirp->real_base != tree_find_integer_property(root, "/options/real-base"))
1653
      error("chirp: /options/real-base conflicts with note section\n");
1654
  }
1655
  else
1656
    tree_parse(root, "/options/real-base 0x%lx",
1657
               (unsigned long)chirp->real_base);
1658
 
1659
  /* resolve real-size */
1660
  if (note.found == note_correct
1661
      && note.desc.real_size != (signed32)-1
1662
      && note.desc.real_size != 0
1663
      && chirp->real_size > note.desc.real_size)
1664
    error("chirp: insufficient physical memory for firmware\n");
1665
  if (tree_find_property(root, "/options/real-size") != NULL) {
1666
    if (chirp->real_size > tree_find_integer_property(root, "/options/real-size"))
1667
      error("chirp: /options/real-size conflicts with note section\n");
1668
  }
1669
  else
1670
    tree_parse(root, "/options/real-size 0x%lx",
1671
               (unsigned long)chirp->real_size);
1672
 
1673
  /* resolve virt-base */
1674
  if (chirp->real_mode)
1675
    chirp->virt_base = chirp->real_base;
1676
  else if (note.found == note_correct && note.desc.virt_base != -1)
1677
    chirp->virt_base = note.desc.virt_base;
1678
  else if (tree_find_property(root, "/options/virt-base") != NULL)
1679
    chirp->virt_base = tree_find_integer_property(root, "/options/virt-base");
1680
  else
1681
    chirp->virt_base = CHIRP_START_ADDRESS;
1682
  if (tree_find_property(root, "/options/virt-base") != NULL) {
1683
    unsigned_word virt_base = tree_find_integer_property(root, "/options/virt-base");
1684
    if (virt_base != -1 && chirp->virt_base != virt_base)
1685
      error("chirp: /options/virt-base conflicts with note section\n");
1686
  }
1687
  else
1688
    tree_parse(root, "/options/virt-base 0x%lx",
1689
               chirp->real_mode ? -1 : (unsigned long)chirp->virt_base);
1690
 
1691
  /* resolve virt-size */
1692
  chirp->virt_size = chirp->real_size;
1693
  if (note.found == note_correct
1694
     && note.desc.virt_size != (signed32)-1
1695
      && note.desc.virt_size != 0
1696
      && !chirp->real_mode
1697
      && chirp->virt_size > note.desc.virt_size)
1698
    error("chirp: insufficent virtual memory for firmware\n");
1699
  if (tree_find_property(root, "/options/virt-size") != NULL) {
1700
    if (chirp->virt_size > tree_find_integer_property(root, "/options/virt-size"))
1701
      error("chirp: /options/virt-size conflicts with note section\n");
1702
  }
1703
  else
1704
    tree_parse(root, "/options/virt-size 0x%lx",
1705
               chirp->real_mode ? -1 : (unsigned long)chirp->virt_size);
1706
 
1707
  /* resolve load-base */
1708
  if (note.found == note_correct
1709
      && note.desc.load_base != (signed32)-1)
1710
    chirp->load_base = note.desc.load_base;
1711
  else if (tree_find_property(root, "/options/load-base") != NULL)
1712
    chirp->load_base = tree_find_integer_property(root, "/options/load-base");
1713
  else
1714
    chirp->load_base = CHIRP_LOAD_BASE;
1715
  if (tree_find_property(root, "/options/load-base") != NULL) {
1716
    if (chirp->load_base != tree_find_integer_property(root, "/options/load-base"))
1717
      error("chirp: /options/load-base conflicts with note section\n");
1718
  }
1719
  else
1720
    tree_parse(root, "/options/load-base 0x%lx",
1721
               (unsigned long)chirp->load_base);
1722
 
1723
  /* now adjust the preliminary firmware addresses to final values */
1724
  chirp->code_ra = chirp->code_offset + chirp->real_base;
1725
  chirp->stack_ra = chirp->stack_offset + chirp->real_base;
1726
  chirp->htab_ra = chirp->htab_offset + chirp->real_base;
1727
 
1728
  /* the virtual addresses.  In real mode these are real addresses. */
1729
 
1730
  chirp->code_va = chirp->code_offset + chirp->virt_base;
1731
  chirp->stack_va = chirp->stack_offset + chirp->virt_base;
1732
  chirp->htab_va = chirp->htab_offset + chirp->virt_base;
1733
 
1734
  chirp->code_client_va = chirp->code_va;
1735
  chirp->code_client_ra = chirp->code_ra;
1736
 
1737
  chirp->code_callback_va = chirp->code_client_va + 16;
1738
  chirp->code_callback_ra = chirp->code_client_ra + 16;
1739
 
1740
  chirp->code_loop_va = chirp->code_callback_va + 16;
1741
  chirp->code_loop_ra = chirp->code_callback_ra + 16;
1742
 
1743
  /* initialization */
1744
 
1745
  tree_parse(root, "/openprom/init");
1746
  tree_parse(root, "/openprom/init/register");
1747
  tree_parse(root, "/openprom/init/register/0.pc 0x%lx",
1748
             (unsigned long)bfd_get_start_address(image));
1749
  tree_parse(root, "/openprom/init/register/pc 0x%lx",
1750
             (unsigned long)chirp->code_loop_va);
1751
  tree_parse(root, "/openprom/init/register/msr 0x%x",
1752
             (msr_machine_check_enable
1753
              | (chirp->real_mode
1754
                 ? 0
1755
                 : (msr_instruction_relocate
1756
                    | msr_data_relocate))
1757
              | (chirp->little_endian
1758
                 ? (msr_little_endian_mode
1759
                    | msr_interrupt_little_endian_mode)
1760
                 : 0)
1761
              | (chirp->floating_point_available
1762
                 ? msr_floating_point_available
1763
                 : 0)
1764
              | (chirp->interrupt_prefix
1765
                 ? msr_interrupt_prefix
1766
                 : 0)
1767
              ));
1768
  tree_parse(root, "/openprom/init/register/sdr1 0x%lx",
1769
             (unsigned long)(chirp->htab_ra
1770
                             | MASK32(16, 22)
1771
                             | ((chirp->sizeof_htab - 1) >> 16)));
1772
  /* make certain that the segment registers map straight through */
1773
  for (i = 0; i < 16; i++) {
1774
    tree_parse(root, "/openprom/init/register/sr%d 0x%lx",
1775
               i, (unsigned long)i);
1776
  }
1777
 
1778
  /* establish an initial state for all processors */
1779
 
1780
 
1781
  /* the client interface address */
1782
  tree_parse(root, "/openprom/init/register/r5 0x%lx",
1783
             (unsigned long)chirp->code_client_va);
1784
  /* a stack */
1785
  tree_parse(root, "/openprom/init/register/sp 0x%lx",
1786
             (unsigned long)(chirp->stack_va + chirp->sizeof_stack - 16));
1787
  /* in chrp mode any arguments end up being concatinated */
1788
  tree_parse(root, "/openprom/init/stack/stack-type chirp");
1789
 
1790
 
1791
  /* client interface - emul-call followed by return instruction */
1792
 
1793
 
1794
  node = tree_parse(root, "/openprom/init/data@0x%lx",
1795
                    (unsigned long)chirp->code_client_ra);
1796
  tree_parse(node, "./psim,description \"client-interface instruction");
1797
  tree_parse(node, "./real-address 0x%lx",
1798
             (unsigned long)chirp->code_client_ra);
1799
  tree_parse(node, "./data 0x%lx",
1800
             (unsigned long)emul_call_instruction);
1801
 
1802
  node = tree_parse(root, "/openprom/init/data@0x%lx",
1803
                    (unsigned long)(chirp->code_client_ra + 4));
1804
  tree_parse(node, "./psim,description \"client-interface return instruction");
1805
  tree_parse(node, "./real-address 0x%lx",
1806
             (unsigned long)(chirp->code_client_ra + 4));
1807
  tree_parse(node, "./data 0x%lx",
1808
             (unsigned long)emul_blr_instruction);
1809
 
1810
 
1811
  /* return address for client callbacks - an emul-call instruction
1812
     that is again followed by a return instruction */
1813
 
1814
 
1815
  node = tree_parse(root, "/openprom/init/data@0x%lx",
1816
                    (unsigned long)chirp->code_callback_ra);
1817
  tree_parse(node, "./psim,description \"client-callback instruction");
1818
  tree_parse(node, "./real-address 0x%lx",
1819
             (unsigned long)chirp->code_callback_ra);
1820
  tree_parse(node, "./data 0x%lx",
1821
             (unsigned long)emul_call_instruction);
1822
 
1823
  node = tree_parse(root, "/openprom/init/data@0x%lx",
1824
                    (unsigned long)(chirp->code_callback_ra + 4));
1825
  tree_parse(node, "./psim,description \"client-callback return instruction");
1826
  tree_parse(node, "./real-address 0x%lx",
1827
             (unsigned long)(chirp->code_callback_ra + 4));
1828
  tree_parse(node, "./data 0x%lx",
1829
             (unsigned long)emul_blr_instruction);
1830
 
1831
  /* loop to keep other processors busy */
1832
 
1833
  node = tree_parse(root, "/openprom/init/data@0x%lx",
1834
                    (unsigned long)chirp->code_loop_ra);
1835
  tree_parse(node, "./psim,description \"processor busy loop");
1836
  tree_parse(node, "./real-address 0x%lx",
1837
             (unsigned long)chirp->code_loop_ra);
1838
  tree_parse(node, "./data 0x%lx",
1839
             (unsigned long)emul_loop_instruction);
1840
 
1841
  /* hash table */
1842
 
1843
  /* create a hash table */
1844
 
1845
  if (!chirp->real_mode) {
1846
    node = tree_parse(root, "/openprom/init/htab@0x%lx",
1847
                      (unsigned long)chirp->htab_ra);
1848
    tree_parse(node, "./claim 0");
1849
    tree_parse(node, "./real-address 0x%lx",
1850
               (unsigned long)chirp->htab_ra);
1851
    tree_parse(node, "./nr-bytes 0x%lx",
1852
               (unsigned long)chirp->sizeof_htab);
1853
  }
1854
 
1855
  /* map in the stack */
1856
 
1857
  if (!chirp->real_mode) {
1858
    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1859
                      (unsigned long)chirp->stack_ra);
1860
    tree_parse(node, "./psim,description \"map in the stack");
1861
    tree_parse(node, "./claim 1");
1862
    tree_parse(node, "./virtual-address 0x%lx",
1863
               (unsigned long)chirp->stack_va);
1864
    tree_parse(node, "./real-address 0x%lx",
1865
               (unsigned long)chirp->stack_ra);
1866
    tree_parse(node, "./nr-bytes 0x%lx",
1867
               (unsigned long)chirp->sizeof_stack);
1868
    tree_parse(node, "./wimg %d", 0x7);
1869
    tree_parse(node, "./pp %d", 0x2);
1870
  }
1871
 
1872
  /* map in the chrp openboot callback code */
1873
 
1874
  if (!chirp->real_mode) {
1875
    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1876
                      (unsigned long)chirp->code_ra);
1877
    tree_parse(node, "./psim,description \"map in chrp openboot callback code");
1878
    tree_parse(node, "./claim 1");
1879
    tree_parse(node, "./virtual-address 0x%lx",
1880
               (unsigned long)chirp->code_va);
1881
    tree_parse(node, "./real-address 0x%lx",
1882
               (unsigned long)chirp->code_ra);
1883
    tree_parse(node, "./nr-bytes 0x%lx",
1884
               (unsigned long)chirp->sizeof_code);
1885
    tree_parse(node, "./wimg %d", 0x7);
1886
    tree_parse(node, "./pp %d", 0x2);
1887
  }
1888
 
1889
  /* map in the program to run */
1890
 
1891
  if (chirp->real_mode) {
1892
    node = tree_parse(node, "/openprom/init/load-binary");
1893
    tree_parse(node, "./psim,description \"load the binary");
1894
    tree_parse(node, "./file-name %s", bfd_get_filename(image));
1895
    tree_parse(node, "./claim 1");
1896
  }
1897
  else {
1898
    node = tree_parse(root, "/openprom/init/htab/pte@0x%lx",
1899
                      (unsigned long)chirp->load_base);
1900
    tree_parse(node, "./psim,description \"load & map the binary");
1901
    tree_parse(node, "./claim 1");
1902
    tree_parse(node, "./file-name \"%s", bfd_get_filename(image));
1903
    tree_parse(node, "./wimg %d", 0x7);
1904
    tree_parse(node, "./pp %d", 0x2);
1905
  }
1906
 
1907
  return chirp;
1908
}
1909
 
1910
static void
1911
emul_chirp_init(os_emul_data *emul_data,
1912
                int nr_cpus)
1913
{
1914
  emul_data->state = serving;
1915
}
1916
 
1917
static int
1918
emul_chirp_instruction_call(cpu *processor,
1919
                            unsigned_word cia,
1920
                            unsigned_word ra,
1921
                            os_emul_data *emul_data)
1922
{
1923
  unsigned_word service_name_addr;
1924
  unsigned_word result;
1925
  char service_buf[32];
1926
  char *service_name;
1927
  chirp_services *service;
1928
 
1929
  switch (emul_data->state) {
1930
 
1931
  case serving:
1932
    /* we are waiting on an OpenBoot request from the client program
1933
       via the client interface */
1934
    if (cia != emul_data->code_client_va)
1935
      return 0;
1936
    emul_data->return_address = LR;
1937
    emul_data->arguments = cpu_registers(processor)->gpr[3];
1938
    /* try to determine what to do */
1939
    service_name_addr = emul_read_word(cpu_registers(processor)->gpr[3],
1940
                                       processor, cia);
1941
    service_name = emul_read_string(service_buf, service_name_addr,
1942
                                    sizeof(service_buf), processor, cia);
1943
    emul_data->n_args = emul_read_word(emul_data->arguments + sizeof(unsigned_cell),
1944
                                       processor, cia);
1945
    emul_data->n_returns = emul_read_word(emul_data->arguments + 2 * sizeof(unsigned_cell),
1946
                                          processor, cia);
1947
    /* verify what was passed */
1948
    if (service_name_addr == 0
1949
        || service_name == NULL) {
1950
      error("OpenFirmware called with invalid (NULL) service name from 0x%lx with args 0x%lx\n",
1951
            (unsigned long)emul_data->return_address,
1952
            (unsigned long)emul_data->arguments);
1953
    }
1954
    if (emul_data->n_args > 6) { /* See iee1275 requirements on nr returns */
1955
      error("OpenFirmware service %s called from 0x%lx with args 0x%lx, too many args (%d)\n",
1956
            (unsigned long)emul_data->return_address,
1957
            (unsigned long)emul_data->arguments,
1958
            emul_data->n_returns);
1959
    }
1960
    if (emul_data->n_returns > 6) {
1961
      error("OpenFirmware service %s called from 0x%lx with args 0x%lx,  with too many returns (%d)\n",
1962
            (unsigned long)emul_data->return_address,
1963
            (unsigned long)emul_data->arguments,
1964
            emul_data->n_args);
1965
    }
1966
    /* look it up */
1967
    TRACE(trace_os_emul, ("%s called from 0x%lx with args 0x%lx\n",
1968
                          service_name,
1969
                          (unsigned long)emul_data->return_address,
1970
                          (unsigned long)emul_data->arguments));
1971
    service = services;
1972
    while (service->name != NULL && strcmp(service->name, service_name) != 0)
1973
      service++;
1974
    /* found or not? */
1975
    if (service->name == NULL) {
1976
      error("OpenBoot service `%s' not found\n", service_name);
1977
      TRACE(trace_os_emul, ("%s not found\n", service_name));
1978
      cpu_registers(processor)->gpr[3] = -1;
1979
    }
1980
    else {
1981
      emul_data->service = service;
1982
      /* call upon it */
1983
      result = service->handler(emul_data, processor, cia);
1984
      if (result != 0)
1985
        TRACE(trace_os_emul, ("%s aborted with %ld\n", service_name, (long)result));
1986
      cpu_registers(processor)->gpr[3] = result;
1987
    }
1988
    break;
1989
 
1990
  default:
1991
    error("emul_chirp_instruction_call() unknown internal state\n");
1992
    result = -1;
1993
    break;
1994
 
1995
  }
1996
 
1997
  /* return to caller - instruction following this is a function return */
1998
  return 1;
1999
}
2000
 
2001
const os_emul emul_chirp = {
2002
  "chirp",
2003
  emul_chirp_create,
2004
  emul_chirp_init,
2005
  NULL, /*system_call*/
2006
  emul_chirp_instruction_call,
2007
 
2008
};
2009
 
2010
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.