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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [sim/] [common/] [hw-base.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1181 sfurman
/* The common simulator framework for GDB, the GNU Debugger.
2
 
3
   Copyright 2002 Free Software Foundation, Inc.
4
 
5
   Contributed by Andrew Cagney and Red Hat.
6
 
7
   This file is part of GDB.
8
 
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 2 of the License, or
12
   (at your option) any later version.
13
 
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
 
19
   You should have received a copy of the GNU General Public License
20
   along with this program; if not, write to the Free Software
21
   Foundation, Inc., 59 Temple Place - Suite 330,
22
   Boston, MA 02111-1307, USA.  */
23
 
24
 
25
#include "hw-main.h"
26
#include "hw-base.h"
27
 
28
 
29
#ifdef HAVE_STRING_H
30
#include <string.h>
31
#else
32
#ifdef HAVE_STRINGS_H
33
#include <strings.h>
34
#endif
35
#endif
36
 
37
#if HAVE_STDLIB_H
38
#include <stdlib.h>
39
#endif
40
 
41
#include <ctype.h>
42
 
43
#include "hw-config.h"
44
 
45
struct hw_base_data {
46
  int finished_p;
47
  const struct hw_descriptor *descriptor;
48
  hw_delete_callback *to_delete;
49
};
50
 
51
static int
52
generic_hw_unit_decode (struct hw *bus,
53
                        const char *unit,
54
                        hw_unit *phys)
55
{
56
  memset (phys, 0, sizeof (*phys));
57
  if (unit == NULL)
58
    return 0;
59
  else
60
    {
61
      int nr_cells = 0;
62
      const int max_nr_cells = hw_unit_nr_address_cells (bus);
63
      while (1)
64
        {
65
          char *end = NULL;
66
          unsigned long val;
67
          val = strtoul (unit, &end, 0);
68
          /* parse error? */
69
          if (unit == end)
70
            return -1;
71
          /* two many cells? */
72
          if (nr_cells >= max_nr_cells)
73
            return -1;
74
          /* save it */
75
          phys->cells[nr_cells] = val;
76
          nr_cells++;
77
          unit = end;
78
          /* more to follow? */
79
          if (isspace (*unit) || *unit == '\0')
80
            break;
81
          if (*unit != ',')
82
            return -1;
83
          unit++;
84
        }
85
      if (nr_cells < max_nr_cells) {
86
        /* shift everything to correct position */
87
        int i;
88
        for (i = 1; i <= nr_cells; i++)
89
          phys->cells[max_nr_cells - i] = phys->cells[nr_cells - i];
90
        for (i = 0; i < (max_nr_cells - nr_cells); i++)
91
          phys->cells[i] = 0;
92
      }
93
      phys->nr_cells = max_nr_cells;
94
      return max_nr_cells;
95
  }
96
}
97
 
98
static int
99
generic_hw_unit_encode (struct hw *bus,
100
                        const hw_unit *phys,
101
                        char *buf,
102
                        int sizeof_buf)
103
{
104
  int i;
105
  int len;
106
  char *pos = buf;
107
  /* skip leading zero's */
108
  for (i = 0; i < phys->nr_cells; i++)
109
    {
110
      if (phys->cells[i] != 0)
111
        break;
112
    }
113
  /* don't output anything if empty */
114
  if (phys->nr_cells == 0)
115
    {
116
      strcpy(pos, "");
117
      len = 0;
118
    }
119
  else if (i == phys->nr_cells)
120
    {
121
      /* all zero */
122
      strcpy(pos, "0");
123
      len = 1;
124
    }
125
  else
126
    {
127
      for (; i < phys->nr_cells; i++)
128
        {
129
          if (pos != buf) {
130
            strcat(pos, ",");
131
            pos = strchr(pos, '\0');
132
          }
133
          if (phys->cells[i] < 10)
134
            sprintf (pos, "%ld", (unsigned long)phys->cells[i]);
135
          else
136
            sprintf (pos, "0x%lx", (unsigned long)phys->cells[i]);
137
          pos = strchr(pos, '\0');
138
        }
139
      len = pos - buf;
140
    }
141
  if (len >= sizeof_buf)
142
    hw_abort (NULL, "generic_unit_encode - buffer overflow\n");
143
  return len;
144
}
145
 
146
static int
147
generic_hw_unit_address_to_attach_address (struct hw *me,
148
                                           const hw_unit *address,
149
                                           int *attach_space,
150
                                           unsigned_word *attach_address,
151
                                           struct hw *client)
152
{
153
  int i;
154
  for (i = 0; i < address->nr_cells - 2; i++)
155
    {
156
      if (address->cells[i] != 0)
157
        hw_abort (me, "Only 32bit addresses supported");
158
    }
159
  if (address->nr_cells >= 2)
160
    *attach_space = address->cells[address->nr_cells - 2];
161
  else
162
    *attach_space = 0;
163
  *attach_address = address->cells[address->nr_cells - 1];
164
  return 1;
165
}
166
 
167
static int
168
generic_hw_unit_size_to_attach_size (struct hw *me,
169
                                     const hw_unit *size,
170
                                     unsigned *nr_bytes,
171
                                     struct hw *client)
172
{
173
  int i;
174
  for (i = 0; i < size->nr_cells - 1; i++)
175
    {
176
      if (size->cells[i] != 0)
177
        hw_abort (me, "Only 32bit sizes supported");
178
    }
179
  *nr_bytes = size->cells[0];
180
  return *nr_bytes;
181
}
182
 
183
 
184
/* ignore/passthrough versions of each function */
185
 
186
static void
187
passthrough_hw_attach_address (struct hw *me,
188
                               int level,
189
                               int space,
190
                               address_word addr,
191
                               address_word nr_bytes,
192
                               struct hw *client) /*callback/default*/
193
{
194
  if (hw_parent (me) == NULL)
195
    hw_abort (client, "hw_attach_address: no parent attach method");
196
  hw_attach_address (hw_parent (me), level,
197
                     space, addr, nr_bytes,
198
                     client);
199
}
200
 
201
static void
202
passthrough_hw_detach_address (struct hw *me,
203
                               int level,
204
                               int space,
205
                               address_word addr,
206
                               address_word nr_bytes,
207
                               struct hw *client) /*callback/default*/
208
{
209
  if (hw_parent (me) == NULL)
210
    hw_abort (client, "hw_attach_address: no parent attach method");
211
  hw_detach_address (hw_parent (me), level,
212
                     space, addr, nr_bytes,
213
                     client);
214
}
215
 
216
static unsigned
217
panic_hw_io_read_buffer (struct hw *me,
218
                         void *dest,
219
                         int space,
220
                         unsigned_word addr,
221
                         unsigned nr_bytes)
222
{
223
  hw_abort (me, "no io-read method");
224
  return 0;
225
}
226
 
227
static unsigned
228
panic_hw_io_write_buffer (struct hw *me,
229
                          const void *source,
230
                          int space,
231
                          unsigned_word addr,
232
                          unsigned nr_bytes)
233
{
234
  hw_abort (me, "no io-write method");
235
  return 0;
236
}
237
 
238
static unsigned
239
passthrough_hw_dma_read_buffer (struct hw *me,
240
                                void *dest,
241
                                int space,
242
                                unsigned_word addr,
243
                                unsigned nr_bytes)
244
{
245
  if (hw_parent (me) == NULL)
246
    hw_abort (me, "no parent dma-read method");
247
  return hw_dma_read_buffer (hw_parent (me), dest,
248
                             space, addr, nr_bytes);
249
}
250
 
251
static unsigned
252
passthrough_hw_dma_write_buffer (struct hw *me,
253
                                 const void *source,
254
                                 int space,
255
                                 unsigned_word addr,
256
                                 unsigned nr_bytes,
257
                                 int violate_read_only_section)
258
{
259
  if (hw_parent (me) == NULL)
260
    hw_abort (me, "no parent dma-write method");
261
  return hw_dma_write_buffer (hw_parent (me), source,
262
                              space, addr,
263
                              nr_bytes,
264
                              violate_read_only_section);
265
}
266
 
267
static void
268
ignore_hw_delete (struct hw *me)
269
{
270
  /* NOP */
271
}
272
 
273
 
274
 
275
 
276
static const char *
277
full_name_of_hw (struct hw *leaf,
278
                 char *buf,
279
                 unsigned sizeof_buf)
280
{
281
  /* get a buffer */
282
  char full_name[1024];
283
  if (buf == (char*)0)
284
    {
285
      buf = full_name;
286
      sizeof_buf = sizeof (full_name);
287
    }
288
 
289
  /* use head recursion to construct the path */
290
 
291
  if (hw_parent (leaf) == NULL)
292
    /* root */
293
    {
294
      if (sizeof_buf < 1)
295
        hw_abort (leaf, "buffer overflow");
296
      *buf = '\0';
297
    }
298
  else
299
    /* sub node */
300
    {
301
      char unit[1024];
302
      full_name_of_hw (hw_parent (leaf), buf, sizeof_buf);
303
      if (hw_unit_encode (hw_parent (leaf),
304
                          hw_unit_address (leaf),
305
                          unit + 1,
306
                          sizeof (unit) - 1)
307
          > 0)
308
        unit[0] = '@';
309
      else
310
        unit[0] = '\0';
311
      if (strlen (buf) + strlen ("/") + strlen (hw_name (leaf)) + strlen (unit)
312
          >= sizeof_buf)
313
        hw_abort (leaf, "buffer overflow");
314
      strcat (buf, "/");
315
      strcat (buf, hw_name (leaf));
316
      strcat (buf, unit);
317
    }
318
 
319
  /* return it usefully */
320
  if (buf == full_name)
321
    buf = hw_strdup (leaf, full_name);
322
  return buf;
323
}
324
 
325
struct hw *
326
hw_create (struct sim_state *sd,
327
           struct hw *parent,
328
           const char *family,
329
           const char *name,
330
           const char *unit,
331
           const char *args)
332
{
333
 /* NOTE: HW must be allocated using ZALLOC, others use HW_ZALLOC */
334
  struct hw *hw = ZALLOC (struct hw);
335
 
336
  /* our identity */
337
  hw->family_of_hw = hw_strdup (hw, family);
338
  hw->name_of_hw = hw_strdup (hw, name);
339
  hw->args_of_hw = hw_strdup (hw, args);
340
 
341
  /* a hook into the system */
342
  if (sd != NULL)
343
    hw->system_of_hw = sd;
344
  else if (parent != NULL)
345
    hw->system_of_hw = hw_system (parent);
346
  else
347
    hw_abort (parent, "No system found");
348
 
349
  /* in a tree */
350
  if (parent != NULL)
351
    {
352
      struct hw **sibling = &parent->child_of_hw;
353
      while ((*sibling) != NULL)
354
        sibling = &(*sibling)->sibling_of_hw;
355
      *sibling = hw;
356
      hw->parent_of_hw = parent;
357
    }
358
 
359
  /* top of tree */
360
  if (parent != NULL)
361
    {
362
      struct hw *root = parent;
363
      while (root->parent_of_hw != NULL)
364
        root = root->parent_of_hw;
365
      hw->root_of_hw = root;
366
    }
367
 
368
  /* a unique identifier for the device on the parents bus */
369
  if (parent != NULL)
370
    {
371
      hw_unit_decode (parent, unit, &hw->unit_address_of_hw);
372
    }
373
 
374
  /* Determine our path */
375
  if (parent != NULL)
376
    hw->path_of_hw = full_name_of_hw (hw, NULL, 0);
377
  else
378
    hw->path_of_hw = "/";
379
 
380
  /* create our base type */
381
  hw->base_of_hw = HW_ZALLOC (hw, struct hw_base_data);
382
  hw->base_of_hw->finished_p = 0;
383
 
384
  /* our callbacks */
385
  set_hw_io_read_buffer (hw, panic_hw_io_read_buffer);
386
  set_hw_io_write_buffer (hw, panic_hw_io_write_buffer);
387
  set_hw_dma_read_buffer (hw, passthrough_hw_dma_read_buffer);
388
  set_hw_dma_write_buffer (hw, passthrough_hw_dma_write_buffer);
389
  set_hw_unit_decode (hw, generic_hw_unit_decode);
390
  set_hw_unit_encode (hw, generic_hw_unit_encode);
391
  set_hw_unit_address_to_attach_address (hw, generic_hw_unit_address_to_attach_address);
392
  set_hw_unit_size_to_attach_size (hw, generic_hw_unit_size_to_attach_size);
393
  set_hw_attach_address (hw, passthrough_hw_attach_address);
394
  set_hw_detach_address (hw, passthrough_hw_detach_address);
395
  set_hw_delete (hw, ignore_hw_delete);
396
 
397
  /* locate a descriptor */
398
  {
399
    const struct hw_descriptor **table;
400
    for (table = hw_descriptors;
401
         *table != NULL;
402
         table++)
403
      {
404
        const struct hw_descriptor *entry;
405
        for (entry = *table;
406
             entry->family != NULL;
407
             entry++)
408
          {
409
            if (strcmp (family, entry->family) == 0)
410
              {
411
                hw->base_of_hw->descriptor = entry;
412
                break;
413
              }
414
          }
415
      }
416
    if (hw->base_of_hw->descriptor == NULL)
417
      {
418
        hw_abort (parent, "Unknown device `%s'", family);
419
      }
420
  }
421
 
422
  /* Attach dummy ports */
423
  create_hw_alloc_data (hw);
424
  create_hw_property_data (hw);
425
  create_hw_port_data (hw);
426
  create_hw_event_data (hw);
427
  create_hw_handle_data (hw);
428
  create_hw_instance_data (hw);
429
 
430
  return hw;
431
}
432
 
433
 
434
int
435
hw_finished_p (struct hw *me)
436
{
437
  return (me->base_of_hw->finished_p);
438
}
439
 
440
void
441
hw_finish (struct hw *me)
442
{
443
  if (hw_finished_p (me))
444
    hw_abort (me, "Attempt to finish finished device");
445
 
446
  /* Fill in the (hopefully) defined address/size cells values */
447
  if (hw_find_property (me, "#address-cells") != NULL)
448
    me->nr_address_cells_of_hw_unit =
449
      hw_find_integer_property (me, "#address-cells");
450
  else
451
    me->nr_address_cells_of_hw_unit = 2;
452
  if (hw_find_property (me, "#size-cells") != NULL)
453
    me->nr_size_cells_of_hw_unit =
454
      hw_find_integer_property (me, "#size-cells");
455
  else
456
    me->nr_size_cells_of_hw_unit = 1;
457
 
458
  /* Fill in the (hopefully) defined trace variable */
459
  if (hw_find_property (me, "trace?") != NULL)
460
    me->trace_of_hw_p = hw_find_boolean_property (me, "trace?");
461
  /* allow global variable to define default tracing */
462
  else if (! hw_trace_p (me)
463
           && hw_find_property (hw_root (me), "global-trace?") != NULL
464
           && hw_find_boolean_property (hw_root (me), "global-trace?"))
465
    me->trace_of_hw_p = 1;
466
 
467
 
468
  /* Allow the real device to override any methods */
469
  me->base_of_hw->descriptor->to_finish (me);
470
  me->base_of_hw->finished_p = 1;
471
}
472
 
473
 
474
void
475
hw_delete (struct hw *me)
476
{
477
  /* give the object a chance to tidy up */
478
  me->base_of_hw->to_delete (me);
479
 
480
  delete_hw_instance_data (me);
481
  delete_hw_handle_data (me);
482
  delete_hw_event_data (me);
483
  delete_hw_port_data (me);
484
  delete_hw_property_data (me);
485
 
486
  /* now unlink us from the tree */
487
  if (hw_parent (me))
488
    {
489
      struct hw **sibling = &hw_parent (me)->child_of_hw;
490
      while (*sibling != NULL)
491
        {
492
          if (*sibling == me)
493
            {
494
              *sibling = me->sibling_of_hw;
495
              me->sibling_of_hw = NULL;
496
              me->parent_of_hw = NULL;
497
              break;
498
            }
499
        }
500
    }
501
 
502
  /* some sanity checks */
503
  if (hw_child (me) != NULL)
504
    {
505
      hw_abort (me, "attempt to delete device with children");
506
    }
507
  if (hw_sibling (me) != NULL)
508
    {
509
      hw_abort (me, "attempt to delete device with siblings");
510
    }
511
 
512
  /* blow away all memory belonging to the device */
513
  delete_hw_alloc_data (me);
514
 
515
  /* finally */
516
  zfree (me);
517
}
518
 
519
void
520
set_hw_delete (struct hw *hw, hw_delete_callback method)
521
{
522
  hw->base_of_hw->to_delete = method;
523
}
524
 
525
 
526
/* Go through the devices various reg properties for those that
527
   specify attach addresses */
528
 
529
 
530
void
531
do_hw_attach_regs (struct hw *hw)
532
{
533
  static const char *(reg_property_names[]) = {
534
    "attach-addresses",
535
    "assigned-addresses",
536
    "reg",
537
    "alternate-reg" ,
538
    NULL
539
  };
540
  const char **reg_property_name;
541
  int nr_valid_reg_properties = 0;
542
  for (reg_property_name = reg_property_names;
543
       *reg_property_name != NULL;
544
       reg_property_name++)
545
    {
546
      if (hw_find_property (hw, *reg_property_name) != NULL)
547
        {
548
          reg_property_spec reg;
549
          int reg_entry;
550
          for (reg_entry = 0;
551
               hw_find_reg_array_property (hw, *reg_property_name, reg_entry,
552
                                           &reg);
553
               reg_entry++)
554
            {
555
              unsigned_word attach_address;
556
              int attach_space;
557
              unsigned attach_size;
558
              if (!hw_unit_address_to_attach_address (hw_parent (hw),
559
                                                      &reg.address,
560
                                                      &attach_space,
561
                                                      &attach_address,
562
                                                      hw))
563
                continue;
564
              if (!hw_unit_size_to_attach_size (hw_parent (hw),
565
                                                &reg.size,
566
                                                &attach_size, hw))
567
                continue;
568
              hw_attach_address (hw_parent (hw),
569
                                 0,
570
                                 attach_space, attach_address, attach_size,
571
                                 hw);
572
              nr_valid_reg_properties++;
573
            }
574
          /* if first option matches don't try for any others */
575
          if (reg_property_name == reg_property_names)
576
            break;
577
        }
578
    }
579
}

powered by: WebSVN 2.1.0

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