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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 578 markom
/*  This file is part of the program psim.
2
 
3
    Copyright (C) 1994-1996, 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 _HW_PHB_C_
23
#define _HW_PHB_C_
24
 
25
#include "device_table.h"
26
 
27
#include "hw_phb.h"
28
 
29
#include "corefile.h"
30
 
31
#ifdef HAVE_STDLIB_H
32
#include <stdlib.h>
33
#endif
34
 
35
#include <ctype.h>
36
 
37
 
38
/* DEVICE
39
 
40
 
41
   phb - PCI Host Bridge
42
 
43
 
44
   DESCRIPTION
45
 
46
 
47
   PHB implements a model of the PCI-host bridge described in the PPCP
48
   document.
49
 
50
   For bridge devices, Open Firmware specifies that the <<ranges>>
51
   property be used to specify the mapping of address spaces between a
52
   bridges parent and child busses.  This PHB model configures itsself
53
   according to the information specified in its ranges property.  The
54
   <<ranges>> property is described in detail in the Open Firmware
55
   documentation.
56
 
57
   For DMA transfers, any access to a PCI address space which falls
58
   outside of the mapped memory space is assumed to be a transfer
59
   intended for the parent bus.
60
 
61
 
62
   PROPERTIES
63
 
64
 
65
   ranges = <my-phys-addr> <parent-phys-addr> <my-size> ...  (required)
66
 
67
   Define a number of mappings from the parent bus to one of this
68
   devices PCI busses.  The exact format of the <<parent-phys-addr>>
69
   is parent bus dependant.  The format of <<my-phys-addr>> is
70
   described in the Open Firmware PCI bindings document (note that the
71
   address must be non-relocatable).
72
 
73
 
74
   #address-cells = 3  (required)
75
 
76
   Number of cells used by an Open Firmware PCI address.  This
77
   property must be defined before specifying the <<ranges>> property.
78
 
79
 
80
   #size-cells = 2  (required)
81
 
82
   Number of cells used by an Open Firmware PCI size.  This property
83
   must be defined before specifying the <<ranges>> property.
84
 
85
 
86
   EXAMPLES
87
 
88
 
89
   Enable tracing:
90
 
91
   |  $ psim \
92
   |    -t phb-device \
93
 
94
 
95
   Since device tree entries that are specified on the command line
96
   are added before most of the device tree has been built it is often
97
   necessary to explictly add certain device properties and thus
98
   ensure they are already present in the device tree.  For the
99
   <<phb>> one such property is parent busses <<#address-cells>>.
100
 
101
   |    -o '/#address-cells 1' \
102
 
103
 
104
   Create the PHB remembering to include the cell size properties:
105
 
106
   |    -o '/phb@0x80000000/#address-cells 3' \
107
   |    -o '/phb@0x80000000/#size-cells 2' \
108
 
109
 
110
   Specify that the memory address range <<0x80000000>> to
111
   <<0x8fffffff>> should map directly onto the PCI memory address
112
   space while the processor address range <<0xc0000000>> to
113
   <<0xc000ffff>> should map onto the PCI I/O address range starting
114
   at location zero:
115
 
116
   |    -o '/phb@0x80000000/ranges \
117
   |                nm0,0,0,80000000 0x80000000 0x10000000 \
118
   |                ni0,0,0,0 0xc0000000 0x10000' \
119
 
120
 
121
   Insert a 4k <<nvram>> into slot zero of the PCI bus.  Have it
122
   directly accessible in both the I/O (address <<0x100>>) and memory
123
   (address 0x80001000) spaces:
124
 
125
   |    -o '/phb@0x80000000/nvram@0/assigned-addresses \
126
   |                nm0,0,10,80001000 4096 \
127
   |                ni0,0,14,100 4096'
128
   |    -o '/phb@0x80000000/nvram@0/reg \
129
   |                0 0 \
130
   |                i0,0,14,0 4096'
131
   |    -o '/phb@0x80000000/nvram@0/alternate-reg \
132
   |                0 0 \
133
   |                m0,0,10,0 4096'
134
 
135
   The <<assigned-address>> property corresponding to what (if it were
136
   implemented) be found in the config base registers while the
137
   <<reg>> and <<alternative-reg>> properties indicating the location
138
   of registers within each address space.
139
 
140
   Of the possible addresses, only the non-relocatable versions are
141
   used when attaching the device to the bus.
142
 
143
 
144
   BUGS
145
 
146
 
147
   The implementation of the PCI configuration space is left as an
148
   exercise for the reader.  Such a restriction should only impact on
149
   systems wanting to dynamically configure devices on the PCI bus.
150
 
151
   The <<CHRP>> document specfies additional (optional) functionality
152
   of the primary PHB. The implementation of such functionality is
153
   left as an exercise for the reader.
154
 
155
   The Open Firmware PCI bus bindings document (rev 1.6 and 2.0) is
156
   unclear on the value of the "ss" bits for a 64bit memory address.
157
   The correct value, as used by this module, is 0b11.
158
 
159
   The Open Firmware PCI bus bindings document (rev 1.6) suggests that
160
   the register field of non-relocatable PCI address should be zero.
161
   Unfortunatly, PCI addresses specified in the <<assigned-addresses>>
162
   property must be both non-relocatable and have non-zero register
163
   fields.
164
 
165
   The unit-decode method is not inserting a bus number into any
166
   address that it decodes.  Instead the bus-number is left as zero.
167
 
168
   Support for aliased memory and I/O addresses is left as an exercise
169
   for the reader.
170
 
171
   Support for interrupt-ack and special cycles are left as an
172
   exercise for the reader.  One issue to consider when attempting
173
   this exercise is how to specify the address of the int-ack and
174
   special cycle register.  Hint: <</8259-interrupt-ackowledge>> is
175
   the wrong answer.
176
 
177
   Children of this node can only use the client callback interface
178
   when attaching themselves to the <<phb>>.
179
 
180
 
181
   REFERENCES
182
 
183
 
184
   http://playground.sun.com/1275/home.html#OFDbusPCI
185
 
186
 
187
   */
188
 
189
 
190
typedef struct _phb_space {
191
  core *map;
192
  core_map *readable;
193
  core_map *writeable;
194
  unsigned_word parent_base;
195
  int parent_space;
196
  unsigned_word my_base;
197
  int my_space;
198
  unsigned size;
199
  const char *name;
200
} phb_space;
201
 
202
typedef struct _hw_phb_device  {
203
  phb_space space[nr_hw_phb_spaces];
204
} hw_phb_device;
205
 
206
 
207
static const char *
208
hw_phb_decode_name(hw_phb_decode level)
209
{
210
  switch (level) {
211
  case hw_phb_normal_decode: return "normal";
212
  case hw_phb_subtractive_decode: return "subtractive";
213
  case hw_phb_master_abort_decode: return "master-abort";
214
  default: return "invalid decode";
215
  }
216
}
217
 
218
 
219
static void
220
hw_phb_init_address(device *me)
221
{
222
  hw_phb_device *phb = device_data(me);
223
 
224
  /* check some basic properties */
225
  if (device_nr_address_cells(me) != 3)
226
    device_error(me, "incorrect #address-cells");
227
  if (device_nr_size_cells(me) != 2)
228
    device_error(me, "incorrect #size-cells");
229
 
230
  /* (re) initialize each PCI space */
231
  {
232
    hw_phb_spaces space_nr;
233
    for (space_nr = 0; space_nr < nr_hw_phb_spaces; space_nr++) {
234
      phb_space *pci_space = &phb->space[space_nr];
235
      core_init(pci_space->map);
236
      pci_space->size = 0;
237
    }
238
  }
239
 
240
  /* decode each of the ranges properties entering the information
241
     into the space table */
242
  {
243
    range_property_spec range;
244
    int ranges_entry;
245
 
246
    for (ranges_entry = 0;
247
         device_find_range_array_property(me, "ranges", ranges_entry,
248
                                          &range);
249
         ranges_entry++) {
250
      int my_attach_space;
251
      unsigned_word my_attach_address;
252
      int parent_attach_space;
253
      unsigned_word parent_attach_address;
254
      unsigned size;
255
      phb_space *pci_space;
256
      /* convert the addresses into something meaningful */
257
      device_address_to_attach_address(me, &range.child_address,
258
                                       &my_attach_space,
259
                                       &my_attach_address,
260
                                       me);
261
      device_address_to_attach_address(device_parent(me),
262
                                       &range.parent_address,
263
                                       &parent_attach_space,
264
                                       &parent_attach_address,
265
                                       me);
266
      device_size_to_attach_size(me, &range.size, &size, me);
267
      if (my_attach_space < 0 || my_attach_space >= nr_hw_phb_spaces)
268
        device_error(me, "ranges property contains an invalid address space");
269
      pci_space = &phb->space[my_attach_space];
270
      if (pci_space->size != 0)
271
        device_error(me, "ranges property contains duplicate mappings for %s address space",
272
                     pci_space->name);
273
      pci_space->parent_base = parent_attach_address;
274
      pci_space->parent_space = parent_attach_space;
275
      pci_space->my_base = my_attach_address;
276
      pci_space->my_space = my_attach_space;
277
      pci_space->size = size;
278
      device_attach_address(device_parent(me),
279
                            attach_callback,
280
                            parent_attach_space, parent_attach_address, size,
281
                            access_read_write_exec,
282
                            me);
283
      DTRACE(phb, ("map %d:0x%lx to %s:0x%lx (0x%lx bytes)\n",
284
                   (int)parent_attach_space,
285
                   (unsigned long)parent_attach_address,
286
                   pci_space->name,
287
                   (unsigned long)my_attach_address,
288
                   (unsigned long)size));
289
    }
290
 
291
    if (ranges_entry == 0) {
292
      device_error(me, "Missing or empty ranges property");
293
    }
294
 
295
  }
296
 
297
}
298
 
299
static void
300
hw_phb_attach_address(device *me,
301
                      attach_type type,
302
                      int space,
303
                      unsigned_word addr,
304
                      unsigned nr_bytes,
305
                      access_type access,
306
                      device *client) /*callback/default*/
307
{
308
  hw_phb_device *phb = device_data(me);
309
  phb_space *pci_space;
310
  /* sanity checks */
311
  if (space < 0 || space >= nr_hw_phb_spaces)
312
    device_error(me, "attach space (%d) specified by %s invalid",
313
                 space, device_path(client));
314
  pci_space = &phb->space[space];
315
  if (addr + nr_bytes > pci_space->my_base + pci_space->size
316
      || addr < pci_space->my_base)
317
    device_error(me, "attach addr (0x%lx) specified by %s outside of bus address range",
318
                 (unsigned long)addr, device_path(client));
319
  if (type != hw_phb_normal_decode
320
      && type != hw_phb_subtractive_decode)
321
    device_error(me, "attach type (%d) specified by %s invalid",
322
                 type, device_path(client));
323
  /* attach it to the relevent bus */
324
  DTRACE(phb, ("attach %s - %s %s:0x%lx (0x%lx bytes)\n",
325
               device_path(client),
326
               hw_phb_decode_name(type),
327
               pci_space->name,
328
               (unsigned long)addr,
329
               (unsigned long)nr_bytes));
330
  core_attach(pci_space->map,
331
              type,
332
              space,
333
              access,
334
              addr,
335
              nr_bytes,
336
              client);
337
}
338
 
339
 
340
/* Extract/set various fields from a PCI unit address.
341
 
342
   Note: only the least significant 32 bits of each cell is used.
343
 
344
   Note: for PPC MSB is 0 while for PCI it is 31. */
345
 
346
 
347
/* relocatable bit n */
348
 
349
static unsigned
350
extract_n(const device_unit *address)
351
{
352
  return EXTRACTED32(address->cells[0], 0, 0);
353
}
354
 
355
static void
356
set_n(device_unit *address)
357
{
358
  BLIT32(address->cells[0], 0, 1);
359
}
360
 
361
 
362
/* prefetchable bit p */
363
 
364
static unsigned
365
extract_p(const device_unit *address)
366
{
367
  ASSERT(address->nr_cells == 3);
368
  return EXTRACTED32(address->cells[0], 1, 1);
369
}
370
 
371
static void
372
set_p(device_unit *address)
373
{
374
  BLIT32(address->cells[0], 1, 1);
375
}
376
 
377
 
378
/* aliased bit t */
379
 
380
static unsigned
381
extract_t(const device_unit *address)
382
{
383
  ASSERT(address->nr_cells == 3);
384
  return EXTRACTED32(address->cells[0], 2, 2);
385
}
386
 
387
static void
388
set_t(device_unit *address)
389
{
390
  BLIT32(address->cells[0], 2, 1);
391
}
392
 
393
 
394
/* space code ss */
395
 
396
typedef enum {
397
  ss_config_code = 0,
398
  ss_io_code = 1,
399
  ss_32bit_memory_code = 2,
400
  ss_64bit_memory_code = 3,
401
} ss_type;
402
 
403
static ss_type
404
extract_ss(const device_unit *address)
405
{
406
  ASSERT(address->nr_cells == 3);
407
  return EXTRACTED32(address->cells[0], 6, 7);
408
}
409
 
410
static void
411
set_ss(device_unit *address, ss_type val)
412
{
413
  MBLIT32(address->cells[0], 6, 7, val);
414
}
415
 
416
 
417
/* bus number bbbbbbbb */
418
 
419
#if 0
420
static unsigned
421
extract_bbbbbbbb(const device_unit *address)
422
{
423
  ASSERT(address->nr_cells == 3);
424
  return EXTRACTED32(address->cells[0], 8, 15);
425
}
426
#endif
427
 
428
#if 0
429
static void
430
set_bbbbbbbb(device_unit *address, unsigned val)
431
{
432
  MBLIT32(address->cells[0], 8, 15, val);
433
}
434
#endif
435
 
436
 
437
/* device number ddddd */
438
 
439
static unsigned
440
extract_ddddd(const device_unit *address)
441
{
442
  ASSERT(address->nr_cells == 3);
443
  return EXTRACTED32(address->cells[0], 16, 20);
444
}
445
 
446
static void
447
set_ddddd(device_unit *address, unsigned val)
448
{
449
  MBLIT32(address->cells[0], 16, 20, val);
450
}
451
 
452
 
453
/* function number fff */
454
 
455
static unsigned
456
extract_fff(const device_unit *address)
457
{
458
  ASSERT(address->nr_cells == 3);
459
  return EXTRACTED32(address->cells[0], 21, 23);
460
}
461
 
462
static void
463
set_fff(device_unit *address, unsigned val)
464
{
465
  MBLIT32(address->cells[0], 21, 23, val);
466
}
467
 
468
 
469
/* register number rrrrrrrr */
470
 
471
static unsigned
472
extract_rrrrrrrr(const device_unit *address)
473
{
474
  ASSERT(address->nr_cells == 3);
475
  return EXTRACTED32(address->cells[0], 24, 31);
476
}
477
 
478
static void
479
set_rrrrrrrr(device_unit *address, unsigned val)
480
{
481
  MBLIT32(address->cells[0], 24, 31, val);
482
}
483
 
484
 
485
/* MSW of 64bit address hh..hh */
486
 
487
static unsigned
488
extract_hh_hh(const device_unit *address)
489
{
490
  ASSERT(address->nr_cells == 3);
491
  return address->cells[1];
492
}
493
 
494
static void
495
set_hh_hh(device_unit *address, unsigned val)
496
{
497
  address->cells[2] = val;
498
}
499
 
500
 
501
/* LSW of 64bit address ll..ll */
502
 
503
static unsigned
504
extract_ll_ll(const device_unit *address)
505
{
506
  ASSERT(address->nr_cells == 3);
507
  return address->cells[2];
508
}
509
 
510
static void
511
set_ll_ll(device_unit *address, unsigned val)
512
{
513
  address->cells[2] = val;
514
}
515
 
516
 
517
/* Convert PCI textual bus address into a device unit */
518
 
519
static int
520
hw_phb_unit_decode(device *me,
521
                   const char *unit,
522
                   device_unit *address)
523
{
524
  char *end = NULL;
525
  const char *chp = unit;
526
  unsigned long val;
527
 
528
  if (device_nr_address_cells(me) != 3)
529
    device_error(me, "PCI bus should have #address-cells == 3");
530
  memset(address, 0, sizeof(*address));
531
 
532
  if (unit == NULL)
533
    return 0;
534
 
535
  address->nr_cells = 3;
536
 
537
  if (isxdigit(*chp)) {
538
    set_ss(address, ss_config_code);
539
  }
540
  else {
541
 
542
    /* non-relocatable? */
543
    if (*chp == 'n') {
544
      set_n(address);
545
      chp++;
546
    }
547
 
548
    /* address-space? */
549
    if (*chp == 'i') {
550
      set_ss(address, ss_io_code);
551
      chp++;
552
    }
553
    else if (*chp == 'm') {
554
      set_ss(address, ss_32bit_memory_code);
555
      chp++;
556
    }
557
    else if (*chp == 'x') {
558
      set_ss(address, ss_64bit_memory_code);
559
      chp++;
560
    }
561
    else
562
      device_error(me, "Problem parsing PCI address %s", unit);
563
 
564
    /* possible alias */
565
    if (*chp == 't') {
566
      if (extract_ss(address) == ss_64bit_memory_code)
567
        device_error(me, "Invalid alias bit in PCI address %s", unit);
568
      set_t(address);
569
      chp++;
570
    }
571
 
572
    /* possible p */
573
    if (*chp == 'p') {
574
      if (extract_ss(address) != ss_32bit_memory_code)
575
        device_error(me, "Invalid prefetchable bit (p) in PCI address %s",
576
                     unit);
577
      set_p(address);
578
      chp++;
579
    }
580
 
581
  }
582
 
583
  /* required DD */
584
  if (!isxdigit(*chp))
585
    device_error(me, "Missing device number in PCI address %s", unit);
586
  val = strtoul(chp, &end, 16);
587
  if (chp == end)
588
    device_error(me, "Problem parsing device number in PCI address %s", unit);
589
  if ((val & 0x1f) != val)
590
    device_error(me, "Device number (0x%lx) out of range (0..0x1f) in PCI address %s",
591
                 val, unit);
592
  set_ddddd(address, val);
593
  chp = end;
594
 
595
  /* For config space, the F is optional */
596
  if (extract_ss(address) == ss_config_code
597
      && (isspace(*chp) || *chp == '\0'))
598
    return chp - unit;
599
 
600
  /* function number F */
601
  if (*chp != ',')
602
    device_error(me, "Missing function number in PCI address %s", unit);
603
  chp++;
604
  val = strtoul(chp, &end, 10);
605
  if (chp == end)
606
    device_error(me, "Problem parsing function number in PCI address %s",
607
                 unit);
608
  if ((val & 7) != val)
609
    device_error(me, "Function number (%ld) out of range (0..7) in PCI address %s",
610
                 (long)val, unit);
611
  set_fff(address, val);
612
  chp = end;
613
 
614
  /* for config space, must be end */
615
  if (extract_ss(address) == ss_config_code) {
616
    if (!isspace(*chp) && *chp != '\0')
617
      device_error(me, "Problem parsing PCI config address %s",
618
                   unit);
619
    return chp - unit;
620
  }
621
 
622
  /* register number RR */
623
  if (*chp != ',')
624
    device_error(me, "Missing register number in PCI address %s", unit);
625
  chp++;
626
  val = strtoul(chp, &end, 16);
627
  if (chp == end)
628
    device_error(me, "Problem parsing register number in PCI address %s",
629
                 unit);
630
  switch (extract_ss(address)) {
631
  case ss_io_code:
632
#if 0
633
    if (extract_n(address) && val != 0)
634
      device_error(me, "non-relocatable I/O register must be zero in PCI address %s", unit);
635
    else if (!extract_n(address)
636
             && val != 0x10 && val != 0x14 && val != 0x18
637
             && val != 0x1c && val != 0x20 && val != 0x24)
638
      device_error(me, "I/O register invalid in PCI address %s", unit);
639
#endif
640
    break;
641
  case ss_32bit_memory_code:
642
#if 0
643
    if (extract_n(address) && val != 0)
644
      device_error(me, "non-relocatable memory register must be zero in PCI address %s", unit);
645
    else if (!extract_n(address)
646
             && val != 0x10 && val != 0x14 && val != 0x18
647
             && val != 0x1c && val != 0x20 && val != 0x24 && val != 0x30)
648
      device_error(me, "I/O register (0x%lx) invalid in PCI address %s",
649
                   val, unit);
650
#endif
651
    break;
652
  case ss_64bit_memory_code:
653
    if (extract_n(address) && val != 0)
654
      device_error(me, "non-relocatable 32bit memory register must be zero in PCI address %s", unit);
655
    else if (!extract_n(address)
656
             && val != 0x10 && val != 0x18 && val != 0x20)
657
      device_error(me, "Register number (0x%lx) invalid in 64bit PCI address %s",
658
                   val, unit);
659
  case ss_config_code:
660
    device_error(me, "internal error");
661
  }
662
  if ((val & 0xff) != val)
663
    device_error(me, "Register number (0x%lx) out of range (0..0xff) in PCI address %s",
664
                 val, unit);
665
  set_rrrrrrrr(address, val);
666
  chp = end;
667
 
668
  /* address */
669
  if (*chp != ',')
670
    device_error(me, "Missing address in PCI address %s", unit);
671
  chp++;
672
  switch (extract_ss(address)) {
673
  case ss_io_code:
674
  case ss_32bit_memory_code:
675
    val = strtoul(chp, &end, 16);
676
    if (chp == end)
677
      device_error(me, "Problem parsing address in PCI address %s", unit);
678
    switch (extract_ss(address)) {
679
    case ss_io_code:
680
      if (extract_n(address) && extract_t(address)
681
          && (val & 1024) != val)
682
        device_error(me, "10bit aliased non-relocatable address (0x%lx) out of range in PCI address %s",
683
                     val, unit);
684
      if (!extract_n(address) && extract_t(address)
685
          && (val & 0xffff) != val)
686
        device_error(me, "64k relocatable address (0x%lx) out of range in PCI address %s",
687
                     val, unit);
688
      break;
689
    case ss_32bit_memory_code:
690
      if (extract_t(address) && (val & 0xfffff) != val)
691
        device_error(me, "1mb memory address (0x%lx) out of range in PCI address %s",
692
                     val, unit);
693
      if (!extract_t(address) && (val & 0xffffffff) != val)
694
        device_error(me, "32bit memory address (0x%lx) out of range in PCI address %s",
695
                     val, unit);
696
      break;
697
    case ss_64bit_memory_code:
698
    case ss_config_code:
699
      device_error(me, "internal error");
700
    }
701
    set_ll_ll(address, val);
702
    chp = end;
703
    break;
704
  case ss_64bit_memory_code:
705
    device_error(me, "64bit addresses unimplemented");
706
    set_hh_hh(address, val);
707
    set_ll_ll(address, val);
708
    break;
709
  case ss_config_code:
710
    device_error(me, "internal error");
711
    break;
712
  }
713
 
714
  /* finished? */
715
  if (!isspace(*chp) && *chp != '\0')
716
    device_error(me, "Problem parsing PCI address %s", unit);
717
 
718
  return chp - unit;
719
}
720
 
721
 
722
/* Convert PCI device unit into its corresponding textual
723
   representation */
724
 
725
static int
726
hw_phb_unit_encode(device *me,
727
                   const device_unit *unit_address,
728
                   char *buf,
729
                   int sizeof_buf)
730
{
731
  if (unit_address->nr_cells != 3)
732
    device_error(me, "Incorrect number of cells in PCI unit address");
733
  if (device_nr_address_cells(me) != 3)
734
    device_error(me, "PCI bus should have #address-cells == 3");
735
  if (extract_ss(unit_address) == ss_config_code
736
      && extract_fff(unit_address) == 0
737
      && extract_rrrrrrrr(unit_address) == 0
738
      && extract_hh_hh(unit_address) == 0
739
      && extract_ll_ll(unit_address) == 0) {
740
    /* DD - Configuration Space address */
741
    sprintf(buf, "%x",
742
            extract_ddddd(unit_address));
743
  }
744
  else if (extract_ss(unit_address) == ss_config_code
745
           && extract_fff(unit_address) != 0
746
           && extract_rrrrrrrr(unit_address) == 0
747
           && extract_hh_hh(unit_address) == 0
748
           && extract_ll_ll(unit_address) == 0) {
749
    /* DD,F - Configuration Space */
750
    sprintf(buf, "%x,%d",
751
            extract_ddddd(unit_address),
752
            extract_fff(unit_address));
753
  }
754
  else if (extract_ss(unit_address) == ss_io_code
755
           && extract_hh_hh(unit_address) == 0) {
756
    /* [n]i[t]DD,F,RR,NNNNNNNN - 32bit I/O space */
757
    sprintf(buf, "%si%s%x,%d,%x,%x",
758
            extract_n(unit_address) ? "n" : "",
759
            extract_t(unit_address) ? "t" : "",
760
            extract_ddddd(unit_address),
761
            extract_fff(unit_address),
762
            extract_rrrrrrrr(unit_address),
763
            extract_ll_ll(unit_address));
764
  }
765
  else if (extract_ss(unit_address) == ss_32bit_memory_code
766
           && extract_hh_hh(unit_address) == 0) {
767
    /* [n]m[t][p]DD,F,RR,NNNNNNNN - 32bit memory space */
768
    sprintf(buf, "%sm%s%s%x,%d,%x,%x",
769
            extract_n(unit_address) ? "n" : "",
770
            extract_t(unit_address) ? "t" : "",
771
            extract_p(unit_address) ? "p" : "",
772
            extract_ddddd(unit_address),
773
            extract_fff(unit_address),
774
            extract_rrrrrrrr(unit_address),
775
            extract_ll_ll(unit_address));
776
  }
777
  else if (extract_ss(unit_address) == ss_32bit_memory_code) {
778
    /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN - 64bit memory space */
779
    sprintf(buf, "%sx%s%x,%d,%x,%x%08x",
780
            extract_n(unit_address) ? "n" : "",
781
            extract_p(unit_address) ? "p" : "",
782
            extract_ddddd(unit_address),
783
            extract_fff(unit_address),
784
            extract_rrrrrrrr(unit_address),
785
            extract_hh_hh(unit_address),
786
            extract_ll_ll(unit_address));
787
  }
788
  else {
789
    device_error(me, "Invalid PCI unit address 0x%08lx 0x%08lx 0x%08lx",
790
                 (unsigned long)unit_address->cells[0],
791
                 (unsigned long)unit_address->cells[1],
792
                 (unsigned long)unit_address->cells[2]);
793
  }
794
  if (strlen(buf) > sizeof_buf)
795
    error("buffer overflow");
796
  return strlen(buf);
797
}
798
 
799
 
800
static int
801
hw_phb_address_to_attach_address(device *me,
802
                                 const device_unit *address,
803
                                 int *attach_space,
804
                                 unsigned_word *attach_address,
805
                                 device *client)
806
{
807
  if (address->nr_cells != 3)
808
    device_error(me, "attach address has incorrect number of cells");
809
  if (address->cells[1] != 0)
810
    device_error(me, "64bit attach address unsupported");
811
 
812
  /* directly decode the address/space */
813
  *attach_address = address->cells[2];
814
  switch (extract_ss(address)) {
815
  case ss_config_code:
816
    *attach_space = hw_phb_config_space;
817
    break;
818
  case ss_io_code:
819
    *attach_space = hw_phb_io_space;
820
    break;
821
  case ss_32bit_memory_code:
822
  case ss_64bit_memory_code:
823
    *attach_space = hw_phb_memory_space;
824
    break;
825
  }
826
 
827
  /* if non-relocatable finished */
828
  if (extract_n(address))
829
    return 1;
830
 
831
  /* make memory and I/O addresses absolute */
832
  if (*attach_space == hw_phb_io_space
833
      || *attach_space == hw_phb_memory_space) {
834
    int reg_nr;
835
    reg_property_spec assigned;
836
    if (extract_ss(address) == ss_64bit_memory_code)
837
      device_error(me, "64bit memory address not unsuported");
838
    for (reg_nr = 0;
839
         device_find_reg_array_property(client, "assigned-addresses", reg_nr,
840
                                        &assigned);
841
         reg_nr++) {
842
      if (!extract_n(&assigned.address)
843
          || extract_rrrrrrrr(&assigned.address) == 0)
844
        device_error(me, "client %s has invalid assigned-address property",
845
                     device_path(client));
846
      if (extract_rrrrrrrr(address) == extract_rrrrrrrr(&assigned.address)) {
847
        /* corresponding base register */
848
        if (extract_ss(address) != extract_ss(&assigned.address))
849
          device_error(me, "client %s has conflicting types for base register 0x%lx",
850
                       device_path(client),
851
                       (unsigned long)extract_rrrrrrrr(address));
852
        *attach_address += assigned.address.cells[2];
853
        return 0;
854
      }
855
    }
856
    device_error(me, "client %s missing base address register 0x%lx in assigned-addresses property",
857
                 device_path(client),
858
                 (unsigned long)extract_rrrrrrrr(address));
859
  }
860
 
861
  return 0;
862
}
863
 
864
 
865
static int
866
hw_phb_size_to_attach_size(device *me,
867
                           const device_unit *size,
868
                           unsigned *nr_bytes,
869
                           device *client)
870
{
871
  if (size->nr_cells != 2)
872
    device_error(me, "size has incorrect number of cells");
873
  if (size->cells[0] != 0)
874
    device_error(me, "64bit size unsupported");
875
  *nr_bytes = size->cells[1];
876
  return size->cells[1];
877
}
878
 
879
 
880
static const phb_space *
881
find_phb_space(hw_phb_device *phb,
882
               unsigned_word addr,
883
               unsigned nr_bytes)
884
{
885
  hw_phb_spaces space;
886
  /* find the space that matches the address */
887
  for (space = 0; space < nr_hw_phb_spaces; space++) {
888
    phb_space *pci_space = &phb->space[space];
889
    if (addr >= pci_space->parent_base
890
        && (addr + nr_bytes) <= (pci_space->parent_base + pci_space->size)) {
891
      return pci_space;
892
    }
893
  }
894
  return NULL;
895
}
896
 
897
 
898
static unsigned_word
899
map_phb_addr(const phb_space *space,
900
             unsigned_word addr)
901
{
902
  return addr - space->parent_base + space->my_base;
903
}
904
 
905
 
906
 
907
static unsigned
908
hw_phb_io_read_buffer(device *me,
909
                      void *dest,
910
                      int space,
911
                      unsigned_word addr,
912
                      unsigned nr_bytes,
913
                      cpu *processor,
914
                      unsigned_word cia)
915
{
916
  hw_phb_device *phb = (hw_phb_device*)device_data(me);
917
  const phb_space *pci_space = find_phb_space(phb, addr, nr_bytes);
918
  unsigned_word bus_addr;
919
  if (pci_space == NULL)
920
    return 0;
921
  bus_addr = map_phb_addr(pci_space, addr);
922
  DTRACE(phb, ("io read - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
923
               space, (unsigned long)addr, pci_space->name, (unsigned long)bus_addr,
924
               nr_bytes));
925
  return core_map_read_buffer(pci_space->readable,
926
                              dest, bus_addr, nr_bytes);
927
}
928
 
929
 
930
static unsigned
931
hw_phb_io_write_buffer(device *me,
932
                       const void *source,
933
                       int space,
934
                       unsigned_word addr,
935
                       unsigned nr_bytes,
936
                       cpu *processor,
937
                       unsigned_word cia)
938
{
939
  hw_phb_device *phb = (hw_phb_device*)device_data(me);
940
  const phb_space *pci_space = find_phb_space(phb, addr, nr_bytes);
941
  unsigned_word bus_addr;
942
  if (pci_space == NULL)
943
    return 0;
944
  bus_addr = map_phb_addr(pci_space, addr);
945
  DTRACE(phb, ("io write - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
946
               space, (unsigned long)addr, pci_space->name, (unsigned long)bus_addr,
947
               nr_bytes));
948
  return core_map_write_buffer(pci_space->writeable, source,
949
                               bus_addr, nr_bytes);
950
}
951
 
952
 
953
static unsigned
954
hw_phb_dma_read_buffer(device *me,
955
                       void *dest,
956
                       int space,
957
                       unsigned_word addr,
958
                       unsigned nr_bytes)
959
{
960
  hw_phb_device *phb = (hw_phb_device*)device_data(me);
961
  const phb_space *pci_space;
962
  /* find the space */
963
  if (space != hw_phb_memory_space)
964
    device_error(me, "invalid dma address space %d", space);
965
  pci_space = &phb->space[space];
966
  /* check out the address */
967
  if ((addr >= pci_space->my_base
968
       && addr <= pci_space->my_base + pci_space->size)
969
      || (addr + nr_bytes >= pci_space->my_base
970
          && addr + nr_bytes <= pci_space->my_base + pci_space->size))
971
    device_error(me, "Do not support DMA into own bus");
972
  /* do it */
973
  DTRACE(phb, ("dma read - %s:0x%lx (%d bytes)\n",
974
               pci_space->name, addr, nr_bytes));
975
  return device_dma_read_buffer(device_parent(me),
976
                                dest, pci_space->parent_space,
977
                                addr, nr_bytes);
978
}
979
 
980
 
981
static unsigned
982
hw_phb_dma_write_buffer(device *me,
983
                        const void *source,
984
                        int space,
985
                        unsigned_word addr,
986
                        unsigned nr_bytes,
987
                        int violate_read_only_section)
988
{
989
  hw_phb_device *phb = (hw_phb_device*)device_data(me);
990
  const phb_space *pci_space;
991
  /* find the space */
992
  if (space != hw_phb_memory_space)
993
    device_error(me, "invalid dma address space %d", space);
994
  pci_space = &phb->space[space];
995
  /* check out the address */
996
  if ((addr >= pci_space->my_base
997
       && addr <= pci_space->my_base + pci_space->size)
998
      || (addr + nr_bytes >= pci_space->my_base
999
          && addr + nr_bytes <= pci_space->my_base + pci_space->size))
1000
    device_error(me, "Do not support DMA into own bus");
1001
  /* do it */
1002
  DTRACE(phb, ("dma write - %s:0x%lx (%d bytes)\n",
1003
               pci_space->name, addr, nr_bytes));
1004
  return device_dma_write_buffer(device_parent(me),
1005
                                 source, pci_space->parent_space,
1006
                                 addr, nr_bytes,
1007
                                 violate_read_only_section);
1008
}
1009
 
1010
 
1011
static device_callbacks const hw_phb_callbacks = {
1012
  { hw_phb_init_address, },
1013
  { hw_phb_attach_address, },
1014
  { hw_phb_io_read_buffer, hw_phb_io_write_buffer },
1015
  { hw_phb_dma_read_buffer, hw_phb_dma_write_buffer },
1016
  { NULL, }, /* interrupt */
1017
  { hw_phb_unit_decode,
1018
    hw_phb_unit_encode,
1019
    hw_phb_address_to_attach_address,
1020
    hw_phb_size_to_attach_size }
1021
};
1022
 
1023
 
1024
static void *
1025
hw_phb_create(const char *name,
1026
              const device_unit *unit_address,
1027
              const char *args)
1028
{
1029
  /* create the descriptor */
1030
  hw_phb_device *phb = ZALLOC(hw_phb_device);
1031
 
1032
  /* create the core maps now */
1033
  hw_phb_spaces space_nr;
1034
  for (space_nr = 0; space_nr < nr_hw_phb_spaces; space_nr++) {
1035
    phb_space *pci_space = &phb->space[space_nr];
1036
    pci_space->map = core_create();
1037
    pci_space->readable = core_readable(pci_space->map);
1038
    pci_space->writeable = core_writeable(pci_space->map);
1039
    switch (space_nr) {
1040
    case hw_phb_memory_space:
1041
      pci_space->name = "memory";
1042
      break;
1043
    case hw_phb_io_space:
1044
      pci_space->name = "I/O";
1045
      break;
1046
    case hw_phb_config_space:
1047
      pci_space->name = "config";
1048
      break;
1049
    case hw_phb_special_space:
1050
      pci_space->name = "special";
1051
      break;
1052
    default:
1053
      error ("internal error");
1054
      break;
1055
    }
1056
  }
1057
 
1058
  return phb;
1059
}
1060
 
1061
 
1062
const device_descriptor hw_phb_device_descriptor[] = {
1063
  { "phb", hw_phb_create, &hw_phb_callbacks },
1064
  { "pci", NULL, &hw_phb_callbacks },
1065
  { NULL, },
1066
};
1067
 
1068
#endif /* _HW_PHB_ */

powered by: WebSVN 2.1.0

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