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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gdb/] [gdb-6.8/] [sim/] [ppc/] [device.c] - Blame information for rev 26

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 26 jlechner
/*  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 _DEVICE_C_
23
#define _DEVICE_C_
24
 
25
#include <stdio.h>
26
 
27
#include "device_table.h"
28
#include "cap.h"
29
 
30
#include "events.h"
31
#include "psim.h"
32
 
33
#ifdef HAVE_STDLIB_H
34
#include <stdlib.h>
35
#endif
36
 
37
#ifdef HAVE_STRING_H
38
#include <string.h>
39
#else
40
#ifdef HAVE_STRINGS_H
41
#include <strings.h>
42
#endif
43
#endif
44
 
45
#include <ctype.h>
46
 
47
STATIC_INLINE_DEVICE (void) clean_device_properties(device *);
48
 
49
/* property entries */
50
 
51
typedef struct _device_property_entry device_property_entry;
52
struct _device_property_entry {
53
  device_property_entry *next;
54
  device_property *value;
55
  const void *init_array;
56
  unsigned sizeof_init_array;
57
};
58
 
59
 
60
/* Interrupt edges */
61
 
62
typedef struct _device_interrupt_edge device_interrupt_edge;
63
struct _device_interrupt_edge {
64
  int my_port;
65
  device *dest;
66
  int dest_port;
67
  device_interrupt_edge *next;
68
  object_disposition disposition;
69
};
70
 
71
STATIC_INLINE_DEVICE\
72
(void)
73
attach_device_interrupt_edge(device_interrupt_edge **list,
74
                             int my_port,
75
                             device *dest,
76
                             int dest_port,
77
                             object_disposition disposition)
78
{
79
  device_interrupt_edge *new_edge = ZALLOC(device_interrupt_edge);
80
  new_edge->my_port = my_port;
81
  new_edge->dest = dest;
82
  new_edge->dest_port = dest_port;
83
  new_edge->next = *list;
84
  new_edge->disposition = disposition;
85
  *list = new_edge;
86
}
87
 
88
STATIC_INLINE_DEVICE\
89
(void)
90
detach_device_interrupt_edge(device *me,
91
                             device_interrupt_edge **list,
92
                             int my_port,
93
                             device *dest,
94
                             int dest_port)
95
{
96
  while (*list != NULL) {
97
    device_interrupt_edge *old_edge = *list;
98
    if (old_edge->dest == dest
99
        && old_edge->dest_port == dest_port
100
        && old_edge->my_port == my_port) {
101
      if (old_edge->disposition == permenant_object)
102
        device_error(me, "attempt to delete permenant interrupt");
103
      *list = old_edge->next;
104
      zfree(old_edge);
105
      return;
106
    }
107
  }
108
  device_error(me, "attempt to delete unattached interrupt");
109
}
110
 
111
STATIC_INLINE_DEVICE\
112
(void)
113
clean_device_interrupt_edges(device_interrupt_edge **list)
114
{
115
  while (*list != NULL) {
116
    device_interrupt_edge *old_edge = *list;
117
    switch (old_edge->disposition) {
118
    case permenant_object:
119
      list = &old_edge->next;
120
      break;
121
    case tempoary_object:
122
      *list = old_edge->next;
123
      zfree(old_edge);
124
      break;
125
    }
126
  }
127
}
128
 
129
 
130
/* A device */
131
 
132
struct _device {
133
 
134
  /* my name is ... */
135
  const char *name;
136
  device_unit unit_address;
137
  const char *path;
138
  int nr_address_cells;
139
  int nr_size_cells;
140
 
141
  /* device tree */
142
  device *parent;
143
  device *children;
144
  device *sibling;
145
 
146
  /* its template methods */
147
  void *data; /* device specific data */
148
  const device_callbacks *callback;
149
 
150
  /* device properties */
151
  device_property_entry *properties;
152
 
153
  /* interrupts */
154
  device_interrupt_edge *interrupt_destinations;
155
 
156
  /* any open instances of this device */
157
  device_instance *instances;
158
 
159
  /* the internal/external mappings and other global requirements */
160
  cap *ihandles;
161
  cap *phandles;
162
  psim *system;
163
 
164
  /* debugging */
165
  int trace;
166
};
167
 
168
 
169
/* an instance of a device */
170
struct _device_instance {
171
  void *data;
172
  char *args;
173
  char *path;
174
  const device_instance_callbacks *callback;
175
  /* the root instance */
176
  device *owner;
177
  device_instance *next;
178
  /* interposed instance */
179
  device_instance *parent;
180
  device_instance *child;
181
};
182
 
183
 
184
 
185
/* creation */
186
 
187
STATIC_INLINE_DEVICE\
188
(const char *)
189
device_full_name(device *leaf,
190
                 char *buf,
191
                 unsigned sizeof_buf)
192
{
193
  /* get a buffer */
194
  char full_name[1024];
195
  if (buf == (char*)0) {
196
    buf = full_name;
197
    sizeof_buf = sizeof(full_name);
198
  }
199
 
200
  /* construct a name */
201
  if (leaf->parent == NULL) {
202
    if (sizeof_buf < 1)
203
      error("device_full_name: buffer overflow");
204
    *buf = '\0';
205
  }
206
  else {
207
    char unit[1024];
208
    device_full_name(leaf->parent, buf, sizeof_buf);
209
    if (leaf->parent != NULL
210
        && device_encode_unit(leaf->parent,
211
                              &leaf->unit_address,
212
                              unit+1,
213
                              sizeof(unit)-1) > 0)
214
      unit[0] = '@';
215
    else
216
      unit[0] = '\0';
217
    if (strlen(buf) + strlen("/") + strlen(leaf->name) + strlen(unit)
218
        >= sizeof_buf)
219
      error("device_full_name: buffer overflow");
220
    strcat(buf, "/");
221
    strcat(buf, leaf->name);
222
    strcat (buf, unit);
223
  }
224
 
225
  /* return it usefully */
226
  if (buf == full_name)
227
    buf = (char *) strdup(full_name);
228
  return buf;
229
}
230
 
231
STATIC_INLINE_DEVICE\
232
(device *)
233
device_create_from(const char *name,
234
                   const device_unit *unit_address,
235
                   void *data,
236
                   const device_callbacks *callbacks,
237
                   device *parent)
238
{
239
  device *new_device = ZALLOC(device);
240
 
241
  /* insert it into the device tree */
242
  new_device->parent = parent;
243
  new_device->children = NULL;
244
  if (parent != NULL) {
245
    device **sibling = &parent->children;
246
    while ((*sibling) != NULL)
247
      sibling = &(*sibling)->sibling;
248
    *sibling = new_device;
249
  }
250
 
251
  /* give it a name */
252
  new_device->name = (char *) strdup(name);
253
  new_device->unit_address = *unit_address;
254
  new_device->path = device_full_name(new_device, NULL, 0);
255
 
256
  /* its template */
257
  new_device->data = data;
258
  new_device->callback = callbacks;
259
 
260
  /* its properties - already null */
261
  /* interrupts - already null */
262
 
263
  /* mappings - if needed */
264
  if (parent == NULL) {
265
    new_device->ihandles = cap_create(name);
266
    new_device->phandles = cap_create(name);
267
  }
268
  else {
269
    new_device->ihandles = device_root(parent)->ihandles;
270
    new_device->phandles = device_root(parent)->phandles;
271
  }
272
 
273
  cap_add(new_device->phandles, new_device);
274
  return new_device;
275
}
276
 
277
 
278
 
279
INLINE_DEVICE\
280
(device *)
281
device_create(device *parent,
282
              const char *base,
283
              const char *name,
284
              const char *unit_address,
285
              const char *args)
286
{
287
  const device_descriptor *const *table;
288
  for (table = device_table; *table != NULL; table++) {
289
    const device_descriptor *descr;
290
    for (descr = *table; descr->name != NULL; descr++) {
291
      if (strcmp(base, descr->name) == 0) {
292
        device_unit address = { 0 };
293
        void *data = NULL;
294
        if (parent != NULL)
295
          if (device_decode_unit(parent, unit_address, &address) < 0)
296
            device_error(parent, "invalid address %s for device %s",
297
                         unit_address, name);
298
        if (descr->creator != NULL)
299
          data = descr->creator(name, &address, args);
300
        return device_create_from(name, &address, data,
301
                                  descr->callbacks, parent);
302
      }
303
    }
304
  }
305
  device_error(parent, "attempt to attach unknown device %s", name);
306
  return NULL;
307
}
308
 
309
 
310
 
311
INLINE_DEVICE\
312
(void)
313
device_usage(int verbose)
314
{
315
  const device_descriptor *const *table;
316
  if (verbose == 1) {
317
    int pos = 0;
318
    for (table = device_table; *table != NULL; table++) {
319
      const device_descriptor *descr;
320
      for (descr = *table; descr->name != NULL; descr++) {
321
        pos += strlen(descr->name) + 2;
322
        if (pos > 75) {
323
          pos = strlen(descr->name) + 2;
324
          printf_filtered("\n");
325
        }
326
        printf_filtered("  %s", descr->name);
327
      }
328
      printf_filtered("\n");
329
    }
330
  }
331
  if (verbose > 1) {
332
    for (table = device_table; *table != NULL; table++) {
333
      const device_descriptor *descr;
334
      for (descr = *table; descr->name != NULL; descr++) {
335
        printf_filtered("  %s:\n", descr->name);
336
        /* interrupt ports */
337
        if (descr->callbacks->interrupt.ports != NULL) {
338
          const device_interrupt_port_descriptor *ports =
339
            descr->callbacks->interrupt.ports;
340
          printf_filtered("    interrupt ports:");
341
          while (ports->name != NULL) {
342
            printf_filtered(" %s", ports->name);
343
            ports++;
344
          }
345
          printf_filtered("\n");
346
        }
347
        /* general info */
348
        if (descr->callbacks->usage != NULL)
349
          descr->callbacks->usage(verbose);
350
      }
351
    }
352
  }
353
}
354
 
355
 
356
 
357
 
358
 
359
/* Device node: */
360
 
361
INLINE_DEVICE\
362
(device *)
363
device_parent(device *me)
364
{
365
  return me->parent;
366
}
367
 
368
INLINE_DEVICE\
369
(device *)
370
device_root(device *me)
371
{
372
  ASSERT(me != NULL);
373
  while (me->parent != NULL)
374
    me = me->parent;
375
  return me;
376
}
377
 
378
INLINE_DEVICE\
379
(device *)
380
device_sibling(device *me)
381
{
382
  return me->sibling;
383
}
384
 
385
INLINE_DEVICE\
386
(device *)
387
device_child(device *me)
388
{
389
  return me->children;
390
}
391
 
392
INLINE_DEVICE\
393
(const char *)
394
device_name(device *me)
395
{
396
  return me->name;
397
}
398
 
399
INLINE_DEVICE\
400
(const char *)
401
device_path(device *me)
402
{
403
  return me->path;
404
}
405
 
406
INLINE_DEVICE\
407
(void *)
408
device_data(device *me)
409
{
410
  return me->data;
411
}
412
 
413
INLINE_DEVICE\
414
(psim *)
415
device_system(device *me)
416
{
417
  return me->system;
418
}
419
 
420
INLINE_DEVICE\
421
(const device_unit *)
422
device_unit_address(device *me)
423
{
424
  return &me->unit_address;
425
}
426
 
427
 
428
INLINE_DEVICE\
429
(int)
430
device_address_to_attach_address(device *me,
431
                                 const device_unit *address,
432
                                 int *attach_space,
433
                                 unsigned_word *attach_address,
434
                                 device *client)
435
{
436
  if (me->callback->convert.address_to_attach_address == NULL)
437
    device_error(me, "no convert.address_to_attach_address method");
438
  return me->callback->convert.address_to_attach_address(me, address, attach_space, attach_address, client);
439
}
440
 
441
 
442
INLINE_DEVICE\
443
(int)
444
device_size_to_attach_size(device *me,
445
                           const device_unit *size,
446
                           unsigned *nr_bytes,
447
                           device *client)
448
{
449
  if (me->callback->convert.size_to_attach_size == NULL)
450
    device_error(me, "no convert.size_to_attach_size method");
451
  return me->callback->convert.size_to_attach_size(me, size, nr_bytes, client);
452
}
453
 
454
 
455
INLINE_DEVICE\
456
(int)
457
device_decode_unit(device *bus,
458
                   const char *unit,
459
                   device_unit *address)
460
{
461
  if (bus->callback->convert.decode_unit == NULL)
462
    device_error(bus, "no convert.decode_unit method");
463
  return bus->callback->convert.decode_unit(bus, unit, address);
464
}
465
 
466
 
467
INLINE_DEVICE\
468
(int)
469
device_encode_unit(device *bus,
470
                   const device_unit *unit_address,
471
                   char *buf,
472
                   int sizeof_buf)
473
{
474
  if (bus->callback->convert.encode_unit == NULL)
475
    device_error(bus, "no convert.encode_unit method");
476
  return bus->callback->convert.encode_unit(bus, unit_address, buf, sizeof_buf);
477
}
478
 
479
INLINE_DEVICE\
480
(unsigned)
481
device_nr_address_cells(device *me)
482
{
483
  if (me->nr_address_cells == 0) {
484
    if (device_find_property(me, "#address-cells") != NULL)
485
      me->nr_address_cells = device_find_integer_property(me, "#address-cells");
486
    else
487
      me->nr_address_cells = 2;
488
  }
489
  return me->nr_address_cells;
490
}
491
 
492
INLINE_DEVICE\
493
(unsigned)
494
device_nr_size_cells(device *me)
495
{
496
  if (me->nr_size_cells == 0) {
497
    if (device_find_property(me, "#size-cells") != NULL)
498
      me->nr_size_cells = device_find_integer_property(me, "#size-cells");
499
    else
500
      me->nr_size_cells = 1;
501
  }
502
  return me->nr_size_cells;
503
}
504
 
505
 
506
 
507
/* device-instance: */
508
 
509
INLINE_DEVICE\
510
(device_instance *)
511
device_create_instance_from(device *me,
512
                            device_instance *parent,
513
                            void *data,
514
                            const char *path,
515
                            const char *args,
516
                            const device_instance_callbacks *callbacks)
517
{
518
  device_instance *instance = ZALLOC(device_instance);
519
  if ((me == NULL) == (parent == NULL))
520
    device_error(me, "can't have both parent instance and parent device");
521
  /*instance->unit*/
522
  /* link this instance into the devices list */
523
  if (me != NULL) {
524
    ASSERT(parent == NULL);
525
    instance->owner = me;
526
    instance->parent = NULL;
527
    /* link this instance into the front of the devices instance list */
528
    instance->next = me->instances;
529
    me->instances = instance;
530
  }
531
  if (parent != NULL) {
532
    device_instance **previous;
533
    ASSERT(parent->child == NULL);
534
    parent->child = instance;
535
    ASSERT(me == NULL);
536
    instance->owner = parent->owner;
537
    instance->parent = parent;
538
    /* in the devices instance list replace the parent instance with
539
       this one */
540
    instance->next = parent->next;
541
    /* replace parent with this new node */
542
    previous = &instance->owner->instances;
543
    while (*previous != parent) {
544
      ASSERT(*previous != NULL);
545
      previous = &(*previous)->next;
546
    }
547
    *previous = instance;
548
  }
549
  instance->data = data;
550
  instance->args = (args == NULL ? NULL : (char *) strdup(args));
551
  instance->path = (path == NULL ? NULL : (char *) strdup(path));
552
  instance->callback = callbacks;
553
  cap_add(instance->owner->ihandles, instance);
554
  return instance;
555
}
556
 
557
 
558
INLINE_DEVICE\
559
(device_instance *)
560
device_create_instance(device *me,
561
                       const char *path,
562
                       const char *args)
563
{
564
  /* create the instance */
565
  if (me->callback->instance_create == NULL)
566
    device_error(me, "no instance_create method");
567
  return me->callback->instance_create(me, path, args);
568
}
569
 
570
 
571
STATIC_INLINE_DEVICE\
572
(void)
573
clean_device_instances(device *me)
574
{
575
  device_instance **instance = &me->instances;
576
  while (*instance != NULL) {
577
    device_instance *old_instance = *instance;
578
    device_instance_delete(old_instance);
579
    instance = &me->instances;
580
  }
581
}
582
 
583
 
584
INLINE_DEVICE\
585
(void)
586
device_instance_delete(device_instance *instance)
587
{
588
  device *me = instance->owner;
589
  if (instance->callback->delete == NULL)
590
    device_error(me, "no delete method");
591
  instance->callback->delete(instance);
592
  if (instance->args != NULL)
593
    zfree(instance->args);
594
  if (instance->path != NULL)
595
    zfree(instance->path);
596
  if (instance->child == NULL) {
597
    /* only remove leaf nodes */
598
    device_instance **curr = &me->instances;
599
    while (*curr != instance) {
600
      ASSERT(*curr != NULL);
601
      curr = &(*curr)->next;
602
    }
603
    *curr = instance->next;
604
  }
605
  else {
606
    /* check it isn't in the instance list */
607
    device_instance *curr = me->instances;
608
    while (curr != NULL) {
609
      ASSERT(curr != instance);
610
      curr = curr->next;
611
    }
612
    /* unlink the child */
613
    ASSERT(instance->child->parent == instance);
614
    instance->child->parent = NULL;
615
  }
616
  cap_remove(me->ihandles, instance);
617
  zfree(instance);
618
}
619
 
620
INLINE_DEVICE\
621
(int)
622
device_instance_read(device_instance *instance,
623
                     void *addr,
624
                     unsigned_word len)
625
{
626
  device *me = instance->owner;
627
  if (instance->callback->read == NULL)
628
    device_error(me, "no read method");
629
  return instance->callback->read(instance, addr, len);
630
}
631
 
632
INLINE_DEVICE\
633
(int)
634
device_instance_write(device_instance *instance,
635
                      const void *addr,
636
                      unsigned_word len)
637
{
638
  device *me = instance->owner;
639
  if (instance->callback->write == NULL)
640
    device_error(me, "no write method");
641
  return instance->callback->write(instance, addr, len);
642
}
643
 
644
INLINE_DEVICE\
645
(int)
646
device_instance_seek(device_instance *instance,
647
                     unsigned_word pos_hi,
648
                     unsigned_word pos_lo)
649
{
650
  device *me = instance->owner;
651
  if (instance->callback->seek == NULL)
652
    device_error(me, "no seek method");
653
  return instance->callback->seek(instance, pos_hi, pos_lo);
654
}
655
 
656
INLINE_DEVICE\
657
(int)
658
device_instance_call_method(device_instance *instance,
659
                            const char *method_name,
660
                            int n_stack_args,
661
                            unsigned_cell stack_args[/*n_stack_args*/],
662
                            int n_stack_returns,
663
                            unsigned_cell stack_returns[/*n_stack_args*/])
664
{
665
  device *me = instance->owner;
666
  const device_instance_methods *method = instance->callback->methods;
667
  if (method == NULL) {
668
    device_error(me, "no methods (want %s)", method_name);
669
  }
670
  while (method->name != NULL) {
671
    if (strcmp(method->name, method_name) == 0) {
672
      return method->method(instance,
673
                            n_stack_args, stack_args,
674
                            n_stack_returns, stack_returns);
675
    }
676
    method++;
677
  }
678
  device_error(me, "no %s method", method_name);
679
  return 0;
680
}
681
 
682
 
683
INLINE_DEVICE\
684
(device *)
685
device_instance_device(device_instance *instance)
686
{
687
  return instance->owner;
688
}
689
 
690
INLINE_DEVICE\
691
(const char *)
692
device_instance_path(device_instance *instance)
693
{
694
  return instance->path;
695
}
696
 
697
INLINE_DEVICE\
698
(void *)
699
device_instance_data(device_instance *instance)
700
{
701
  return instance->data;
702
}
703
 
704
 
705
 
706
/* Device Properties: */
707
 
708
STATIC_INLINE_DEVICE\
709
(device_property_entry *)
710
find_property_entry(device *me,
711
                     const char *property)
712
{
713
  device_property_entry *entry;
714
  ASSERT(property != NULL);
715
  entry = me->properties;
716
  while (entry != NULL) {
717
    if (strcmp(entry->value->name, property) == 0)
718
      return entry;
719
    entry = entry->next;
720
  }
721
  return NULL;
722
}
723
 
724
STATIC_INLINE_DEVICE\
725
(void)
726
device_add_property(device *me,
727
                    const char *property,
728
                    device_property_type type,
729
                    const void *init_array,
730
                    unsigned sizeof_init_array,
731
                    const void *array,
732
                    unsigned sizeof_array,
733
                    const device_property *original,
734
                    object_disposition disposition)
735
{
736
  device_property_entry *new_entry = NULL;
737
  device_property *new_value = NULL;
738
 
739
  /* find the list end */
740
  device_property_entry **insertion_point = &me->properties;
741
  while (*insertion_point != NULL) {
742
    if (strcmp((*insertion_point)->value->name, property) == 0)
743
      return;
744
    insertion_point = &(*insertion_point)->next;
745
  }
746
 
747
  /* create a new value */
748
  new_value = ZALLOC(device_property);
749
  new_value->name = (char *) strdup(property);
750
  new_value->type = type;
751
  if (sizeof_array > 0) {
752
    void *new_array = zalloc(sizeof_array);
753
    memcpy(new_array, array, sizeof_array);
754
    new_value->array = new_array;
755
    new_value->sizeof_array = sizeof_array;
756
  }
757
  new_value->owner = me;
758
  new_value->original = original;
759
  new_value->disposition = disposition;
760
 
761
  /* insert the value into the list */
762
  new_entry = ZALLOC(device_property_entry);
763
  *insertion_point = new_entry;
764
  if (sizeof_init_array > 0) {
765
    void *new_init_array = zalloc(sizeof_init_array);
766
    memcpy(new_init_array, init_array, sizeof_init_array);
767
    new_entry->init_array = new_init_array;
768
    new_entry->sizeof_init_array = sizeof_init_array;
769
  }
770
  new_entry->value = new_value;
771
}
772
 
773
 
774
/* local - not available externally */
775
STATIC_INLINE_DEVICE\
776
(void)
777
device_set_property(device *me,
778
                    const char *property,
779
                    device_property_type type,
780
                    const void *array,
781
                    int sizeof_array)
782
{
783
  /* find the property */
784
  device_property_entry *entry = find_property_entry(me, property);
785
  if (entry != NULL) {
786
    /* existing property - update it */
787
    void *new_array = 0;
788
    device_property *value = entry->value;
789
    /* check the type matches */
790
    if (value->type != type)
791
      device_error(me, "conflict between type of new and old value for property %s", property);
792
    /* replace its value */
793
    if (value->array != NULL)
794
      zfree((void*)value->array);
795
    new_array = (sizeof_array > 0
796
                 ? zalloc(sizeof_array)
797
                 : (void*)0);
798
    value->array = new_array;
799
    value->sizeof_array = sizeof_array;
800
    if (sizeof_array > 0)
801
      memcpy(new_array, array, sizeof_array);
802
    return;
803
  }
804
  else {
805
    /* new property - create it */
806
    device_add_property(me, property, type,
807
                        NULL, 0, array, sizeof_array,
808
                        NULL, tempoary_object);
809
  }
810
}
811
 
812
 
813
STATIC_INLINE_DEVICE\
814
(void)
815
clean_device_properties(device *me)
816
{
817
  device_property_entry **delete_point = &me->properties;
818
  while (*delete_point != NULL) {
819
    device_property_entry *current = *delete_point;
820
    switch (current->value->disposition) {
821
    case permenant_object:
822
      /* zap the current value, will be initialized later */
823
      ASSERT(current->init_array != NULL);
824
      if (current->value->array != NULL) {
825
        zfree((void*)current->value->array);
826
        current->value->array = NULL;
827
      }
828
      delete_point = &(*delete_point)->next;
829
      break;
830
    case tempoary_object:
831
      /* zap the actual property, was created during simulation run */
832
      ASSERT(current->init_array == NULL);
833
      *delete_point = current->next;
834
      if (current->value->array != NULL)
835
        zfree((void*)current->value->array);
836
      zfree(current->value);
837
      zfree(current);
838
      break;
839
    }
840
  }
841
}
842
 
843
 
844
INLINE_DEVICE\
845
(void)
846
device_init_static_properties(device *me,
847
                              void *data)
848
{
849
  device_property_entry *property;
850
  for (property = me->properties;
851
       property != NULL;
852
       property = property->next) {
853
    ASSERT(property->init_array != NULL);
854
    ASSERT(property->value->array == NULL);
855
    ASSERT(property->value->disposition == permenant_object);
856
    switch (property->value->type) {
857
    case array_property:
858
    case boolean_property:
859
    case range_array_property:
860
    case reg_array_property:
861
    case string_property:
862
    case string_array_property:
863
    case integer_property:
864
      /* delete the property, and replace it with the original */
865
      device_set_property(me, property->value->name,
866
                          property->value->type,
867
                          property->init_array,
868
                          property->sizeof_init_array);
869
      break;
870
    case ihandle_property:
871
      break;
872
    }
873
  }
874
}
875
 
876
 
877
INLINE_DEVICE\
878
(void)
879
device_init_runtime_properties(device *me,
880
                               void *data)
881
{
882
  device_property_entry *property;
883
  for (property = me->properties;
884
       property != NULL;
885
       property = property->next) {
886
    switch (property->value->disposition) {
887
    case permenant_object:
888
      switch (property->value->type) {
889
      case ihandle_property:
890
        {
891
          device_instance *ihandle;
892
          ihandle_runtime_property_spec spec;
893
          ASSERT(property->init_array != NULL);
894
          ASSERT(property->value->array == NULL);
895
          device_find_ihandle_runtime_property(me, property->value->name, &spec);
896
          ihandle = tree_instance(me, spec.full_path);
897
          device_set_ihandle_property(me, property->value->name, ihandle);
898
          break;
899
        }
900
      case array_property:
901
      case boolean_property:
902
      case range_array_property:
903
      case integer_property:
904
      case reg_array_property:
905
      case string_property:
906
      case string_array_property:
907
        ASSERT(property->init_array != NULL);
908
        ASSERT(property->value->array != NULL);
909
        break;
910
      }
911
      break;
912
    case tempoary_object:
913
      ASSERT(property->init_array == NULL);
914
      ASSERT(property->value->array != NULL);
915
      break;
916
    }
917
  }
918
}
919
 
920
 
921
INLINE_DEVICE\
922
(const device_property *)
923
device_next_property(const device_property *property)
924
{
925
  /* find the property in the list */
926
  device *owner = property->owner;
927
  device_property_entry *entry = owner->properties;
928
  while (entry != NULL && entry->value != property)
929
    entry = entry->next;
930
  /* now return the following property */
931
  ASSERT(entry != NULL); /* must be a member! */
932
  if (entry->next != NULL)
933
    return entry->next->value;
934
  else
935
    return NULL;
936
}
937
 
938
 
939
INLINE_DEVICE\
940
(const device_property *)
941
device_find_property(device *me,
942
                     const char *property)
943
{
944
  if (me == NULL) {
945
    return NULL;
946
  }
947
  else if (property == NULL || strcmp(property, "") == 0) {
948
    if (me->properties == NULL)
949
      return NULL;
950
    else
951
      return me->properties->value;
952
  }
953
  else {
954
    device_property_entry *entry = find_property_entry(me, property);
955
    if (entry != NULL)
956
      return entry->value;
957
  }
958
  return NULL;
959
}
960
 
961
 
962
INLINE_DEVICE\
963
(void)
964
device_add_array_property(device *me,
965
                          const char *property,
966
                          const void *array,
967
                          int sizeof_array)
968
{
969
  device_add_property(me, property, array_property,
970
                      array, sizeof_array, array, sizeof_array,
971
                      NULL, permenant_object);
972
}
973
 
974
INLINE_DEVICE\
975
(void)
976
device_set_array_property(device *me,
977
                          const char *property,
978
                          const void *array,
979
                          int sizeof_array)
980
{
981
  device_set_property(me, property, array_property, array, sizeof_array);
982
}
983
 
984
INLINE_DEVICE\
985
(const device_property *)
986
device_find_array_property(device *me,
987
                           const char *property)
988
{
989
  const device_property *node;
990
  node = device_find_property(me, property);
991
  if (node == (device_property*)0
992
      || node->type != array_property)
993
    device_error(me, "property %s not found or of wrong type", property);
994
  return node;
995
}
996
 
997
 
998
INLINE_DEVICE\
999
(void)
1000
device_add_boolean_property(device *me,
1001
                            const char *property,
1002
                            int boolean)
1003
{
1004
  signed32 new_boolean = (boolean ? -1 : 0);
1005
  device_add_property(me, property, boolean_property,
1006
                      &new_boolean, sizeof(new_boolean),
1007
                      &new_boolean, sizeof(new_boolean),
1008
                      NULL, permenant_object);
1009
}
1010
 
1011
INLINE_DEVICE\
1012
(int)
1013
device_find_boolean_property(device *me,
1014
                             const char *property)
1015
{
1016
  const device_property *node;
1017
  unsigned_cell boolean;
1018
  node = device_find_property(me, property);
1019
  if (node == (device_property*)0
1020
      || node->type != boolean_property)
1021
    device_error(me, "property %s not found or of wrong type", property);
1022
  ASSERT(sizeof(boolean) == node->sizeof_array);
1023
  memcpy(&boolean, node->array, sizeof(boolean));
1024
  return boolean;
1025
}
1026
 
1027
 
1028
INLINE_DEVICE\
1029
(void)
1030
device_add_ihandle_runtime_property(device *me,
1031
                                    const char *property,
1032
                                    const ihandle_runtime_property_spec *ihandle)
1033
{
1034
  /* enter the full path as the init array */
1035
  device_add_property(me, property, ihandle_property,
1036
                      ihandle->full_path, strlen(ihandle->full_path) + 1,
1037
                      NULL, 0,
1038
                      NULL, permenant_object);
1039
}
1040
 
1041
INLINE_DEVICE\
1042
(void)
1043
device_find_ihandle_runtime_property(device *me,
1044
                                     const char *property,
1045
                                     ihandle_runtime_property_spec *ihandle)
1046
{
1047
  device_property_entry *entry = find_property_entry(me, property);
1048
  TRACE(trace_devices,
1049
        ("device_find_ihandle_runtime_property(me=0x%lx, property=%s)\n",
1050
         (long)me, property));
1051
  if (entry == NULL
1052
      || entry->value->type != ihandle_property
1053
      || entry->value->disposition != permenant_object)
1054
    device_error(me, "property %s not found or of wrong type", property);
1055
  ASSERT(entry->init_array != NULL);
1056
  /* the full path */
1057
  ihandle->full_path = entry->init_array;
1058
}
1059
 
1060
 
1061
 
1062
INLINE_DEVICE\
1063
(void)
1064
device_set_ihandle_property(device *me,
1065
                            const char *property,
1066
                            device_instance *ihandle)
1067
{
1068
  unsigned_cell cells;
1069
  cells = H2BE_cell(device_instance_to_external(ihandle));
1070
  device_set_property(me, property, ihandle_property,
1071
                      &cells, sizeof(cells));
1072
 
1073
}
1074
 
1075
INLINE_DEVICE\
1076
(device_instance *)
1077
device_find_ihandle_property(device *me,
1078
                             const char *property)
1079
{
1080
  const device_property *node;
1081
  unsigned_cell ihandle;
1082
  device_instance *instance;
1083
 
1084
  node = device_find_property(me, property);
1085
  if (node == NULL || node->type != ihandle_property)
1086
    device_error(me, "property %s not found or of wrong type", property);
1087
  if (node->array == NULL)
1088
    device_error(me, "runtime property %s not yet initialized", property);
1089
 
1090
  ASSERT(sizeof(ihandle) == node->sizeof_array);
1091
  memcpy(&ihandle, node->array, sizeof(ihandle));
1092
  instance = external_to_device_instance(me, BE2H_cell(ihandle));
1093
  ASSERT(instance != NULL);
1094
  return instance;
1095
}
1096
 
1097
 
1098
INLINE_DEVICE\
1099
(void)
1100
device_add_integer_property(device *me,
1101
                            const char *property,
1102
                            signed_cell integer)
1103
{
1104
  H2BE(integer);
1105
  device_add_property(me, property, integer_property,
1106
                      &integer, sizeof(integer),
1107
                      &integer, sizeof(integer),
1108
                      NULL, permenant_object);
1109
}
1110
 
1111
INLINE_DEVICE\
1112
(signed_cell)
1113
device_find_integer_property(device *me,
1114
                             const char *property)
1115
{
1116
  const device_property *node;
1117
  signed_cell integer;
1118
  TRACE(trace_devices,
1119
        ("device_find_integer(me=0x%lx, property=%s)\n",
1120
         (long)me, property));
1121
  node = device_find_property(me, property);
1122
  if (node == (device_property*)0
1123
      || node->type != integer_property)
1124
    device_error(me, "property %s not found or of wrong type", property);
1125
  ASSERT(sizeof(integer) == node->sizeof_array);
1126
  memcpy(&integer, node->array, sizeof(integer));
1127
  return BE2H_cell(integer);
1128
}
1129
 
1130
INLINE_DEVICE\
1131
(int)
1132
device_find_integer_array_property(device *me,
1133
                                   const char *property,
1134
                                   unsigned index,
1135
                                   signed_cell *integer)
1136
{
1137
  const device_property *node;
1138
  int sizeof_integer = sizeof(*integer);
1139
  signed_cell *cell;
1140
  TRACE(trace_devices,
1141
        ("device_find_integer(me=0x%lx, property=%s)\n",
1142
         (long)me, property));
1143
 
1144
  /* check things sane */
1145
  node = device_find_property(me, property);
1146
  if (node == (device_property*)0
1147
      || (node->type != integer_property
1148
          && node->type != array_property))
1149
    device_error(me, "property %s not found or of wrong type", property);
1150
  if ((node->sizeof_array % sizeof_integer) != 0)
1151
    device_error(me, "property %s contains an incomplete number of cells", property);
1152
  if (node->sizeof_array <= sizeof_integer * index)
1153
    return 0;
1154
 
1155
  /* Find and convert the value */
1156
  cell = ((signed_cell*)node->array) + index;
1157
  *integer = BE2H_cell(*cell);
1158
 
1159
  return node->sizeof_array / sizeof_integer;
1160
}
1161
 
1162
 
1163
STATIC_INLINE_DEVICE\
1164
(unsigned_cell *)
1165
unit_address_to_cells(const device_unit *unit,
1166
                      unsigned_cell *cell,
1167
                      int nr_cells)
1168
{
1169
  int i;
1170
  ASSERT(nr_cells == unit->nr_cells);
1171
  for (i = 0; i < unit->nr_cells; i++) {
1172
    *cell = H2BE_cell(unit->cells[i]);
1173
    cell += 1;
1174
  }
1175
  return cell;
1176
}
1177
 
1178
 
1179
STATIC_INLINE_DEVICE\
1180
(const unsigned_cell *)
1181
cells_to_unit_address(const unsigned_cell *cell,
1182
                      device_unit *unit,
1183
                      int nr_cells)
1184
{
1185
  int i;
1186
  memset(unit, 0, sizeof(*unit));
1187
  unit->nr_cells = nr_cells;
1188
  for (i = 0; i < unit->nr_cells; i++) {
1189
    unit->cells[i] = BE2H_cell(*cell);
1190
    cell += 1;
1191
  }
1192
  return cell;
1193
}
1194
 
1195
 
1196
STATIC_INLINE_DEVICE\
1197
(unsigned)
1198
nr_range_property_cells(device *me,
1199
                        int nr_ranges)
1200
{
1201
  return ((device_nr_address_cells(me)
1202
           + device_nr_address_cells(device_parent(me))
1203
           + device_nr_size_cells(me))
1204
          ) * nr_ranges;
1205
}
1206
 
1207
INLINE_DEVICE\
1208
(void)
1209
device_add_range_array_property(device *me,
1210
                                const char *property,
1211
                                const range_property_spec *ranges,
1212
                                unsigned nr_ranges)
1213
{
1214
  unsigned sizeof_cells = (nr_range_property_cells(me, nr_ranges)
1215
                           * sizeof(unsigned_cell));
1216
  unsigned_cell *cells = zalloc(sizeof_cells);
1217
  unsigned_cell *cell;
1218
  int i;
1219
 
1220
  /* copy the property elements over */
1221
  cell = cells;
1222
  for (i = 0; i < nr_ranges; i++) {
1223
    const range_property_spec *range = &ranges[i];
1224
    /* copy the child address */
1225
    cell = unit_address_to_cells(&range->child_address, cell,
1226
                                 device_nr_address_cells(me));
1227
    /* copy the parent address */
1228
    cell = unit_address_to_cells(&range->parent_address, cell,
1229
                                 device_nr_address_cells(device_parent(me)));
1230
    /* copy the size */
1231
    cell = unit_address_to_cells(&range->size, cell,
1232
                                 device_nr_size_cells(me));
1233
  }
1234
  ASSERT(cell == &cells[nr_range_property_cells(me, nr_ranges)]);
1235
 
1236
  /* add it */
1237
  device_add_property(me, property, range_array_property,
1238
                      cells, sizeof_cells,
1239
                      cells, sizeof_cells,
1240
                      NULL, permenant_object);
1241
 
1242
  zfree(cells);
1243
}
1244
 
1245
INLINE_DEVICE\
1246
(int)
1247
device_find_range_array_property(device *me,
1248
                                 const char *property,
1249
                                 unsigned index,
1250
                                 range_property_spec *range)
1251
{
1252
  const device_property *node;
1253
  unsigned sizeof_entry = (nr_range_property_cells(me, 1)
1254
                           * sizeof(unsigned_cell));
1255
  const unsigned_cell *cells;
1256
 
1257
  /* locate the property */
1258
  node = device_find_property(me, property);
1259
  if (node == (device_property*)0
1260
      || node->type != range_array_property)
1261
    device_error(me, "property %s not found or of wrong type", property);
1262
 
1263
  /* aligned ? */
1264
  if ((node->sizeof_array % sizeof_entry) != 0)
1265
    device_error(me, "property %s contains an incomplete number of entries",
1266
                 property);
1267
 
1268
  /* within bounds? */
1269
  if (node->sizeof_array < sizeof_entry * (index + 1))
1270
    return 0;
1271
 
1272
  /* find the range of interest */
1273
  cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
1274
 
1275
  /* copy the child address out - converting as we go */
1276
  cells = cells_to_unit_address(cells, &range->child_address,
1277
                                device_nr_address_cells(me));
1278
 
1279
  /* copy the parent address out - converting as we go */
1280
  cells = cells_to_unit_address(cells, &range->parent_address,
1281
                                device_nr_address_cells(device_parent(me)));
1282
 
1283
  /* copy the size - converting as we go */
1284
  cells = cells_to_unit_address(cells, &range->size,
1285
                                device_nr_size_cells(me));
1286
 
1287
  return node->sizeof_array / sizeof_entry;
1288
}
1289
 
1290
 
1291
STATIC_INLINE_DEVICE\
1292
(unsigned)
1293
nr_reg_property_cells(device *me,
1294
                      int nr_regs)
1295
{
1296
  return (device_nr_address_cells(device_parent(me))
1297
          + device_nr_size_cells(device_parent(me))
1298
          ) * nr_regs;
1299
}
1300
 
1301
INLINE_DEVICE\
1302
(void)
1303
device_add_reg_array_property(device *me,
1304
                              const char *property,
1305
                              const reg_property_spec *regs,
1306
                              unsigned nr_regs)
1307
{
1308
  unsigned sizeof_cells = (nr_reg_property_cells(me, nr_regs)
1309
                           * sizeof(unsigned_cell));
1310
  unsigned_cell *cells = zalloc(sizeof_cells);
1311
  unsigned_cell *cell;
1312
  int i;
1313
 
1314
  /* copy the property elements over */
1315
  cell = cells;
1316
  for (i = 0; i < nr_regs; i++) {
1317
    const reg_property_spec *reg = &regs[i];
1318
    /* copy the address */
1319
    cell = unit_address_to_cells(&reg->address, cell,
1320
                                 device_nr_address_cells(device_parent(me)));
1321
    /* copy the size */
1322
    cell = unit_address_to_cells(&reg->size, cell,
1323
                                 device_nr_size_cells(device_parent(me)));
1324
  }
1325
  ASSERT(cell == &cells[nr_reg_property_cells(me, nr_regs)]);
1326
 
1327
  /* add it */
1328
  device_add_property(me, property, reg_array_property,
1329
                      cells, sizeof_cells,
1330
                      cells, sizeof_cells,
1331
                      NULL, permenant_object);
1332
 
1333
  zfree(cells);
1334
}
1335
 
1336
INLINE_DEVICE\
1337
(int)
1338
device_find_reg_array_property(device *me,
1339
                               const char *property,
1340
                               unsigned index,
1341
                               reg_property_spec *reg)
1342
{
1343
  const device_property *node;
1344
  unsigned sizeof_entry = (nr_reg_property_cells(me, 1)
1345
                           * sizeof(unsigned_cell));
1346
  const unsigned_cell *cells;
1347
 
1348
  /* locate the property */
1349
  node = device_find_property(me, property);
1350
  if (node == (device_property*)0
1351
      || node->type != reg_array_property)
1352
    device_error(me, "property %s not found or of wrong type", property);
1353
 
1354
  /* aligned ? */
1355
  if ((node->sizeof_array % sizeof_entry) != 0)
1356
    device_error(me, "property %s contains an incomplete number of entries",
1357
                 property);
1358
 
1359
  /* within bounds? */
1360
  if (node->sizeof_array < sizeof_entry * (index + 1))
1361
    return 0;
1362
 
1363
  /* find the range of interest */
1364
  cells = (unsigned_cell*)((char*)node->array + sizeof_entry * index);
1365
 
1366
  /* copy the address out - converting as we go */
1367
  cells = cells_to_unit_address(cells, &reg->address,
1368
                                device_nr_address_cells(device_parent(me)));
1369
 
1370
  /* copy the size out - converting as we go */
1371
  cells = cells_to_unit_address(cells, &reg->size,
1372
                                device_nr_size_cells(device_parent(me)));
1373
 
1374
  return node->sizeof_array / sizeof_entry;
1375
}
1376
 
1377
 
1378
INLINE_DEVICE\
1379
(void)
1380
device_add_string_property(device *me,
1381
                           const char *property,
1382
                           const char *string)
1383
{
1384
  device_add_property(me, property, string_property,
1385
                      string, strlen(string) + 1,
1386
                      string, strlen(string) + 1,
1387
                      NULL, permenant_object);
1388
}
1389
 
1390
INLINE_DEVICE\
1391
(const char *)
1392
device_find_string_property(device *me,
1393
                            const char *property)
1394
{
1395
  const device_property *node;
1396
  const char *string;
1397
  node = device_find_property(me, property);
1398
  if (node == (device_property*)0
1399
      || node->type != string_property)
1400
    device_error(me, "property %s not found or of wrong type", property);
1401
  string = node->array;
1402
  ASSERT(strlen(string) + 1 == node->sizeof_array);
1403
  return string;
1404
}
1405
 
1406
INLINE_DEVICE\
1407
(void)
1408
device_add_string_array_property(device *me,
1409
                                 const char *property,
1410
                                 const string_property_spec *strings,
1411
                                 unsigned nr_strings)
1412
{
1413
  int sizeof_array;
1414
  int string_nr;
1415
  char *array;
1416
  char *chp;
1417
  if (nr_strings == 0)
1418
    device_error(me, "property %s must be non-null", property);
1419
  /* total up the size of the needed array */
1420
  for (sizeof_array = 0, string_nr = 0;
1421
       string_nr < nr_strings;
1422
       string_nr ++) {
1423
    sizeof_array += strlen(strings[string_nr]) + 1;
1424
  }
1425
  /* create the array */
1426
  array = (char*)zalloc(sizeof_array);
1427
  chp = array;
1428
  for (string_nr = 0;
1429
       string_nr < nr_strings;
1430
       string_nr++) {
1431
    strcpy(chp, strings[string_nr]);
1432
    chp += strlen(chp) + 1;
1433
  }
1434
  ASSERT(chp == array + sizeof_array);
1435
  /* now enter it */
1436
  device_add_property(me, property, string_array_property,
1437
                      array, sizeof_array,
1438
                      array, sizeof_array,
1439
                      NULL, permenant_object);
1440
}
1441
 
1442
INLINE_DEVICE\
1443
(int)
1444
device_find_string_array_property(device *me,
1445
                                  const char *property,
1446
                                  unsigned index,
1447
                                  string_property_spec *string)
1448
{
1449
  const device_property *node;
1450
  node = device_find_property(me, property);
1451
  if (node == (device_property*)0)
1452
    device_error(me, "property %s not found", property);
1453
  switch (node->type) {
1454
  default:
1455
    device_error(me, "property %s of wrong type", property);
1456
    break;
1457
  case string_property:
1458
    if (index == 0) {
1459
      *string = node->array;
1460
      ASSERT(strlen(*string) + 1 == node->sizeof_array);
1461
      return 1;
1462
    }
1463
    break;
1464
  case array_property:
1465
    if (node->sizeof_array == 0
1466
        || ((char*)node->array)[node->sizeof_array - 1] != '\0')
1467
      device_error(me, "property %s invalid for string array", property);
1468
    /* FALL THROUGH */
1469
  case string_array_property:
1470
    ASSERT(node->sizeof_array > 0);
1471
    ASSERT(((char*)node->array)[node->sizeof_array - 1] == '\0');
1472
    {
1473
      const char *chp = node->array;
1474
      int nr_entries = 0;
1475
      /* count the number of strings, keeping an eye out for the one
1476
         we're looking for */
1477
      *string = chp;
1478
      do {
1479
        if (*chp == '\0') {
1480
          /* next string */
1481
          nr_entries++;
1482
          chp++;
1483
          if (nr_entries == index)
1484
            *string = chp;
1485
        }
1486
        else {
1487
          chp++;
1488
        }
1489
      } while (chp < (char*)node->array + node->sizeof_array);
1490
      if (index < nr_entries)
1491
        return nr_entries;
1492
      else {
1493
        *string = NULL;
1494
        return 0;
1495
      }
1496
    }
1497
    break;
1498
  }
1499
  return 0;
1500
}
1501
 
1502
INLINE_DEVICE\
1503
(void)
1504
device_add_duplicate_property(device *me,
1505
                              const char *property,
1506
                              const device_property *original)
1507
{
1508
  device_property_entry *master;
1509
  TRACE(trace_devices,
1510
        ("device_add_duplicate_property(me=0x%lx, property=%s, ...)\n",
1511
         (long)me, property));
1512
  if (original->disposition != permenant_object)
1513
    device_error(me, "Can only duplicate permenant objects");
1514
  /* find the original's master */
1515
  master = original->owner->properties;
1516
  while (master->value != original) {
1517
    master = master->next;
1518
    ASSERT(master != NULL);
1519
  }
1520
  /* now duplicate it */
1521
  device_add_property(me, property,
1522
                      original->type,
1523
                      master->init_array, master->sizeof_init_array,
1524
                      original->array, original->sizeof_array,
1525
                      original, permenant_object);
1526
}
1527
 
1528
 
1529
 
1530
/* Device Hardware: */
1531
 
1532
INLINE_DEVICE\
1533
(unsigned)
1534
device_io_read_buffer(device *me,
1535
                      void *dest,
1536
                      int space,
1537
                      unsigned_word addr,
1538
                      unsigned nr_bytes,
1539
                      cpu *processor,
1540
                      unsigned_word cia)
1541
{
1542
  if (me->callback->io.read_buffer == NULL)
1543
    device_error(me, "no io.read_buffer method");
1544
  return me->callback->io.read_buffer(me, dest, space,
1545
                                      addr, nr_bytes,
1546
                                      processor, cia);
1547
}
1548
 
1549
INLINE_DEVICE\
1550
(unsigned)
1551
device_io_write_buffer(device *me,
1552
                       const void *source,
1553
                       int space,
1554
                       unsigned_word addr,
1555
                       unsigned nr_bytes,
1556
                       cpu *processor,
1557
                       unsigned_word cia)
1558
{
1559
  if (me->callback->io.write_buffer == NULL)
1560
    device_error(me, "no io.write_buffer method");
1561
  return me->callback->io.write_buffer(me, source, space,
1562
                                       addr, nr_bytes,
1563
                                       processor, cia);
1564
}
1565
 
1566
INLINE_DEVICE\
1567
(unsigned)
1568
device_dma_read_buffer(device *me,
1569
                       void *dest,
1570
                       int space,
1571
                       unsigned_word addr,
1572
                       unsigned nr_bytes)
1573
{
1574
  if (me->callback->dma.read_buffer == NULL)
1575
    device_error(me, "no dma.read_buffer method");
1576
  return me->callback->dma.read_buffer(me, dest, space,
1577
                                       addr, nr_bytes);
1578
}
1579
 
1580
INLINE_DEVICE\
1581
(unsigned)
1582
device_dma_write_buffer(device *me,
1583
                        const void *source,
1584
                        int space,
1585
                        unsigned_word addr,
1586
                        unsigned nr_bytes,
1587
                        int violate_read_only_section)
1588
{
1589
  if (me->callback->dma.write_buffer == NULL)
1590
    device_error(me, "no dma.write_buffer method");
1591
  return me->callback->dma.write_buffer(me, source, space,
1592
                                        addr, nr_bytes,
1593
                                        violate_read_only_section);
1594
}
1595
 
1596
INLINE_DEVICE\
1597
(void)
1598
device_attach_address(device *me,
1599
                      attach_type attach,
1600
                      int space,
1601
                      unsigned_word addr,
1602
                      unsigned nr_bytes,
1603
                      access_type access,
1604
                      device *client) /*callback/default*/
1605
{
1606
  if (me->callback->address.attach == NULL)
1607
    device_error(me, "no address.attach method");
1608
  me->callback->address.attach(me, attach, space,
1609
                               addr, nr_bytes, access, client);
1610
}
1611
 
1612
INLINE_DEVICE\
1613
(void)
1614
device_detach_address(device *me,
1615
                      attach_type attach,
1616
                      int space,
1617
                      unsigned_word addr,
1618
                      unsigned nr_bytes,
1619
                      access_type access,
1620
                      device *client) /*callback/default*/
1621
{
1622
  if (me->callback->address.detach == NULL)
1623
    device_error(me, "no address.detach method");
1624
  me->callback->address.detach(me, attach, space,
1625
                               addr, nr_bytes, access, client);
1626
}
1627
 
1628
 
1629
 
1630
/* Interrupts: */
1631
 
1632
INLINE_DEVICE(void)
1633
device_interrupt_event(device *me,
1634
                       int my_port,
1635
                       int level,
1636
                       cpu *processor,
1637
                       unsigned_word cia)
1638
{
1639
  int found_an_edge = 0;
1640
  device_interrupt_edge *edge;
1641
  /* device's interrupt lines directly connected */
1642
  for (edge = me->interrupt_destinations;
1643
       edge != NULL;
1644
       edge = edge->next) {
1645
    if (edge->my_port == my_port) {
1646
      if (edge->dest->callback->interrupt.event == NULL)
1647
        device_error(me, "no interrupt method");
1648
      edge->dest->callback->interrupt.event(edge->dest,
1649
                                            edge->dest_port,
1650
                                            me,
1651
                                            my_port,
1652
                                            level,
1653
                                            processor, cia);
1654
      found_an_edge = 1;
1655
    }
1656
  }
1657
  if (!found_an_edge) {
1658
    device_error(me, "No interrupt edge for port %d", my_port);
1659
  }
1660
}
1661
 
1662
INLINE_DEVICE\
1663
(void)
1664
device_interrupt_attach(device *me,
1665
                        int my_port,
1666
                        device *dest,
1667
                        int dest_port,
1668
                        object_disposition disposition)
1669
{
1670
  attach_device_interrupt_edge(&me->interrupt_destinations,
1671
                               my_port,
1672
                               dest,
1673
                               dest_port,
1674
                               disposition);
1675
}
1676
 
1677
INLINE_DEVICE\
1678
(void)
1679
device_interrupt_detach(device *me,
1680
                        int my_port,
1681
                        device *dest,
1682
                        int dest_port)
1683
{
1684
  detach_device_interrupt_edge(me,
1685
                               &me->interrupt_destinations,
1686
                               my_port,
1687
                               dest,
1688
                               dest_port);
1689
}
1690
 
1691
INLINE_DEVICE\
1692
(void)
1693
device_interrupt_traverse(device *me,
1694
                          device_interrupt_traverse_function *handler,
1695
                          void *data)
1696
{
1697
  device_interrupt_edge *interrupt_edge;
1698
  for (interrupt_edge = me->interrupt_destinations;
1699
       interrupt_edge != NULL;
1700
       interrupt_edge = interrupt_edge->next) {
1701
    handler(me, interrupt_edge->my_port,
1702
            interrupt_edge->dest, interrupt_edge->dest_port,
1703
            data);
1704
  }
1705
}
1706
 
1707
INLINE_DEVICE\
1708
(int)
1709
device_interrupt_decode(device *me,
1710
                        const char *port_name,
1711
                        port_direction direction)
1712
{
1713
  if (port_name == NULL || port_name[0] == '\0')
1714
    return 0;
1715
  if (isdigit(port_name[0])) {
1716
    return strtoul(port_name, NULL, 0);
1717
  }
1718
  else {
1719
    const device_interrupt_port_descriptor *ports =
1720
      me->callback->interrupt.ports;
1721
    if (ports != NULL) {
1722
      while (ports->name != NULL) {
1723
        if (ports->direction == bidirect_port
1724
            || ports->direction == direction) {
1725
          if (ports->nr_ports > 0) {
1726
            int len = strlen(ports->name);
1727
            if (strncmp(port_name, ports->name, len) == 0) {
1728
              if (port_name[len] == '\0')
1729
                return ports->number;
1730
              else if(isdigit(port_name[len])) {
1731
                int port = ports->number + strtoul(&port_name[len], NULL, 0);
1732
                if (port >= ports->number + ports->nr_ports)
1733
                  device_error(me, "Interrupt port %s out of range",
1734
                               port_name);
1735
                return port;
1736
              }
1737
            }
1738
          }
1739
          else if (strcmp(port_name, ports->name) == 0)
1740
            return ports->number;
1741
        }
1742
        ports++;
1743
      }
1744
    }
1745
  }
1746
  device_error(me, "Unreconized interrupt port %s", port_name);
1747
  return 0;
1748
}
1749
 
1750
INLINE_DEVICE\
1751
(int)
1752
device_interrupt_encode(device *me,
1753
                        int port_number,
1754
                        char *buf,
1755
                        int sizeof_buf,
1756
                        port_direction direction)
1757
{
1758
  const device_interrupt_port_descriptor *ports = NULL;
1759
  ports = me->callback->interrupt.ports;
1760
  if (ports != NULL) {
1761
    while (ports->name != NULL) {
1762
      if (ports->direction == bidirect_port
1763
          || ports->direction == direction) {
1764
        if (ports->nr_ports > 0) {
1765
          if (port_number >= ports->number
1766
              && port_number < ports->number + ports->nr_ports) {
1767
            strcpy(buf, ports->name);
1768
            sprintf(buf + strlen(buf), "%d", port_number - ports->number);
1769
            if (strlen(buf) >= sizeof_buf)
1770
              error("device_interrupt_encode: buffer overflow");
1771
            return strlen(buf);
1772
          }
1773
        }
1774
        else {
1775
          if (ports->number == port_number) {
1776
            if (strlen(ports->name) >= sizeof_buf)
1777
              error("device_interrupt_encode: buffer overflow");
1778
            strcpy(buf, ports->name);
1779
            return strlen(buf);
1780
          }
1781
        }
1782
      }
1783
      ports++;
1784
    }
1785
  }
1786
  sprintf(buf, "%d", port_number);
1787
  if (strlen(buf) >= sizeof_buf)
1788
    error("device_interrupt_encode: buffer overflow");
1789
  return strlen(buf);
1790
}
1791
 
1792
 
1793
 
1794
/* IOCTL: */
1795
 
1796
EXTERN_DEVICE\
1797
(int)
1798
device_ioctl(device *me,
1799
             cpu *processor,
1800
             unsigned_word cia,
1801
             device_ioctl_request request,
1802
             ...)
1803
{
1804
  int status;
1805
  va_list ap;
1806
  va_start(ap, request);
1807
  if (me->callback->ioctl == NULL)
1808
    device_error(me, "no ioctl method");
1809
  status = me->callback->ioctl(me, processor, cia, request, ap);
1810
  va_end(ap);
1811
  return status;
1812
}
1813
 
1814
 
1815
 
1816
/* I/O */
1817
 
1818
EXTERN_DEVICE\
1819
(void volatile)
1820
device_error(device *me,
1821
             const char *fmt,
1822
             ...)
1823
{
1824
  char message[1024];
1825
  va_list ap;
1826
  /* format the message */
1827
  va_start(ap, fmt);
1828
  vsprintf(message, fmt, ap);
1829
  va_end(ap);
1830
  /* sanity check */
1831
  if (strlen(message) >= sizeof(message))
1832
    error("device_error: buffer overflow");
1833
  if (me == NULL)
1834
    error("device: %s", message);
1835
  else if (me->path != NULL && me->path[0] != '\0')
1836
    error("%s: %s", me->path, message);
1837
  else if (me->name != NULL && me->name[0] != '\0')
1838
    error("%s: %s", me->name, message);
1839
  else
1840
    error("device: %s", message);
1841
  while(1);
1842
}
1843
 
1844
INLINE_DEVICE\
1845
(int)
1846
device_trace(device *me)
1847
{
1848
  return me->trace;
1849
}
1850
 
1851
 
1852
/* External representation */
1853
 
1854
INLINE_DEVICE\
1855
(device *)
1856
external_to_device(device *tree_member,
1857
                   unsigned_cell phandle)
1858
{
1859
  device *me = cap_internal(tree_member->phandles, phandle);
1860
  return me;
1861
}
1862
 
1863
INLINE_DEVICE\
1864
(unsigned_cell)
1865
device_to_external(device *me)
1866
{
1867
  unsigned_cell phandle = cap_external(me->phandles, me);
1868
  return phandle;
1869
}
1870
 
1871
INLINE_DEVICE\
1872
(device_instance *)
1873
external_to_device_instance(device *tree_member,
1874
                            unsigned_cell ihandle)
1875
{
1876
  device_instance *instance = cap_internal(tree_member->ihandles, ihandle);
1877
  return instance;
1878
}
1879
 
1880
INLINE_DEVICE\
1881
(unsigned_cell)
1882
device_instance_to_external(device_instance *instance)
1883
{
1884
  unsigned_cell ihandle = cap_external(instance->owner->ihandles, instance);
1885
  return ihandle;
1886
}
1887
 
1888
 
1889
/* Map onto the event functions */
1890
 
1891
INLINE_DEVICE\
1892
(event_entry_tag)
1893
device_event_queue_schedule(device *me,
1894
                            signed64 delta_time,
1895
                            device_event_handler *handler,
1896
                            void *data)
1897
{
1898
  return event_queue_schedule(psim_event_queue(me->system),
1899
                              delta_time,
1900
                              handler,
1901
                              data);
1902
}
1903
 
1904
INLINE_DEVICE\
1905
(void)
1906
device_event_queue_deschedule(device *me,
1907
                              event_entry_tag event_to_remove)
1908
{
1909
  event_queue_deschedule(psim_event_queue(me->system),
1910
                         event_to_remove);
1911
}
1912
 
1913
INLINE_DEVICE\
1914
(signed64)
1915
device_event_queue_time(device *me)
1916
{
1917
  return event_queue_time(psim_event_queue(me->system));
1918
}
1919
 
1920
 
1921
/* Initialization: */
1922
 
1923
 
1924
INLINE_DEVICE\
1925
(void)
1926
device_clean(device *me,
1927
             void *data)
1928
{
1929
  psim *system;
1930
  system = (psim*)data;
1931
  TRACE(trace_device_init, ("device_clean - initializing %s", me->path));
1932
  clean_device_interrupt_edges(&me->interrupt_destinations);
1933
  clean_device_instances(me);
1934
  clean_device_properties(me);
1935
}
1936
 
1937
/* Device initialization: */
1938
 
1939
INLINE_DEVICE\
1940
(void)
1941
device_init_address(device *me,
1942
                    void *data)
1943
{
1944
  psim *system = (psim*)data;
1945
  int nr_address_cells;
1946
  int nr_size_cells;
1947
  TRACE(trace_device_init, ("device_init_address - initializing %s", me->path));
1948
 
1949
  /* ensure the cap database is valid */
1950
  if (me->parent == NULL) {
1951
    cap_init(me->ihandles);
1952
    cap_init(me->phandles);
1953
  }
1954
 
1955
  /* some basics */
1956
  me->system = system; /* misc things not known until now */
1957
  me->trace = (device_find_property(me, "trace")
1958
               ? device_find_integer_property(me, "trace")
1959
               : 0);
1960
 
1961
  /* Ensure that the first address found in the reg property matches
1962
     anything that was specified as part of the devices name */
1963
  if (device_find_property(me, "reg") != NULL) {
1964
    reg_property_spec unit;
1965
    device_find_reg_array_property(me, "reg", 0, &unit);
1966
    if (memcmp(device_unit_address(me), &unit.address, sizeof(unit.address))
1967
        != 0)
1968
      device_error(me, "Unit address as specified by the reg property in conflict with the value previously specified in the devices path");
1969
  }
1970
 
1971
  /* ensure that the devices #address/size-cells is consistent */
1972
  nr_address_cells = device_nr_address_cells(me);
1973
  if (device_find_property(me, "#address-cells") != NULL
1974
      && (nr_address_cells
1975
          != device_find_integer_property(me, "#address-cells")))
1976
    device_error(me, "#address-cells property used before defined");
1977
  nr_size_cells = device_nr_size_cells(me);
1978
  if (device_find_property(me, "#size-cells") != NULL
1979
      && (nr_size_cells
1980
          != device_find_integer_property(me, "#size-cells")))
1981
    device_error(me, "#size-cells property used before defined");
1982
 
1983
  /* now init it */
1984
  if (me->callback->init.address != NULL)
1985
    me->callback->init.address(me);
1986
}
1987
 
1988
INLINE_DEVICE\
1989
(void)
1990
device_init_data(device *me,
1991
                    void *data)
1992
{
1993
  TRACE(trace_device_init, ("device_init_data - initializing %s", me->path));
1994
  if (me->callback->init.data != NULL)
1995
    me->callback->init.data(me);
1996
}
1997
 
1998
#endif /* _DEVICE_C_ */

powered by: WebSVN 2.1.0

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