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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [common/] [hw-base.c] - Blame information for rev 856

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

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

powered by: WebSVN 2.1.0

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