1 /* This file is part of the program psim.
3 Copyright (C) 1994-1996, Andrew Cagney <cagney@highland.com.au>
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 3 of the License, or
8 (at your option) any later version.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
24 #include "device_table.h"
43 PHB implements a model of the PCI-host bridge described in the PPCP
46 For bridge devices, Open Firmware specifies that the <<ranges>>
47 property be used to specify the mapping of address spaces between a
48 bridges parent and child busses. This PHB model configures itsself
49 according to the information specified in its ranges property. The
50 <<ranges>> property is described in detail in the Open Firmware
53 For DMA transfers, any access to a PCI address space which falls
54 outside of the mapped memory space is assumed to be a transfer
55 intended for the parent bus.
61 ranges = <my-phys-addr> <parent-phys-addr> <my-size> ... (required)
63 Define a number of mappings from the parent bus to one of this
64 devices PCI busses. The exact format of the <<parent-phys-addr>>
65 is parent bus dependant. The format of <<my-phys-addr>> is
66 described in the Open Firmware PCI bindings document (note that the
67 address must be non-relocatable).
70 #address-cells = 3 (required)
72 Number of cells used by an Open Firmware PCI address. This
73 property must be defined before specifying the <<ranges>> property.
76 #size-cells = 2 (required)
78 Number of cells used by an Open Firmware PCI size. This property
79 must be defined before specifying the <<ranges>> property.
91 Since device tree entries that are specified on the command line
92 are added before most of the device tree has been built it is often
93 necessary to explictly add certain device properties and thus
94 ensure they are already present in the device tree. For the
95 <<phb>> one such property is parent busses <<#address-cells>>.
97 | -o '/#address-cells 1' \
100 Create the PHB remembering to include the cell size properties:
102 | -o '/phb@0x80000000/#address-cells 3' \
103 | -o '/phb@0x80000000/#size-cells 2' \
106 Specify that the memory address range <<0x80000000>> to
107 <<0x8fffffff>> should map directly onto the PCI memory address
108 space while the processor address range <<0xc0000000>> to
109 <<0xc000ffff>> should map onto the PCI I/O address range starting
112 | -o '/phb@0x80000000/ranges \
113 | nm0,0,0,80000000 0x80000000 0x10000000 \
114 | ni0,0,0,0 0xc0000000 0x10000' \
117 Insert a 4k <<nvram>> into slot zero of the PCI bus. Have it
118 directly accessible in both the I/O (address <<0x100>>) and memory
119 (address 0x80001000) spaces:
121 | -o '/phb@0x80000000/nvram@0/assigned-addresses \
122 | nm0,0,10,80001000 4096 \
124 | -o '/phb@0x80000000/nvram@0/reg \
127 | -o '/phb@0x80000000/nvram@0/alternate-reg \
131 The <<assigned-address>> property corresponding to what (if it were
132 implemented) be found in the config base registers while the
133 <<reg>> and <<alternative-reg>> properties indicating the location
134 of registers within each address space.
136 Of the possible addresses, only the non-relocatable versions are
137 used when attaching the device to the bus.
143 The implementation of the PCI configuration space is left as an
144 exercise for the reader. Such a restriction should only impact on
145 systems wanting to dynamically configure devices on the PCI bus.
147 The <<CHRP>> document specfies additional (optional) functionality
148 of the primary PHB. The implementation of such functionality is
149 left as an exercise for the reader.
151 The Open Firmware PCI bus bindings document (rev 1.6 and 2.0) is
152 unclear on the value of the "ss" bits for a 64bit memory address.
153 The correct value, as used by this module, is 0b11.
155 The Open Firmware PCI bus bindings document (rev 1.6) suggests that
156 the register field of non-relocatable PCI address should be zero.
157 Unfortunatly, PCI addresses specified in the <<assigned-addresses>>
158 property must be both non-relocatable and have non-zero register
161 The unit-decode method is not inserting a bus number into any
162 address that it decodes. Instead the bus-number is left as zero.
164 Support for aliased memory and I/O addresses is left as an exercise
167 Support for interrupt-ack and special cycles are left as an
168 exercise for the reader. One issue to consider when attempting
169 this exercise is how to specify the address of the int-ack and
170 special cycle register. Hint: <</8259-interrupt-ackowledge>> is
173 Children of this node can only use the client callback interface
174 when attaching themselves to the <<phb>>.
180 http://playground.sun.com/1275/home.html#OFDbusPCI
186 typedef struct _phb_space
{
190 unsigned_word parent_base
;
192 unsigned_word my_base
;
198 typedef struct _hw_phb_device
{
199 phb_space space
[nr_hw_phb_spaces
];
204 hw_phb_decode_name(hw_phb_decode level
)
207 case hw_phb_normal_decode
: return "normal";
208 case hw_phb_subtractive_decode
: return "subtractive";
209 case hw_phb_master_abort_decode
: return "master-abort";
210 default: return "invalid decode";
216 hw_phb_init_address(device
*me
)
218 hw_phb_device
*phb
= device_data(me
);
220 /* check some basic properties */
221 if (device_nr_address_cells(me
) != 3)
222 device_error(me
, "incorrect #address-cells");
223 if (device_nr_size_cells(me
) != 2)
224 device_error(me
, "incorrect #size-cells");
226 /* (re) initialize each PCI space */
228 hw_phb_spaces space_nr
;
229 for (space_nr
= 0; space_nr
< nr_hw_phb_spaces
; space_nr
++) {
230 phb_space
*pci_space
= &phb
->space
[space_nr
];
231 core_init(pci_space
->map
);
236 /* decode each of the ranges properties entering the information
237 into the space table */
239 range_property_spec range
;
242 for (ranges_entry
= 0;
243 device_find_range_array_property(me
, "ranges", ranges_entry
,
247 unsigned_word my_attach_address
;
248 int parent_attach_space
;
249 unsigned_word parent_attach_address
;
251 phb_space
*pci_space
;
252 /* convert the addresses into something meaningful */
253 device_address_to_attach_address(me
, &range
.child_address
,
257 device_address_to_attach_address(device_parent(me
),
258 &range
.parent_address
,
259 &parent_attach_space
,
260 &parent_attach_address
,
262 device_size_to_attach_size(me
, &range
.size
, &size
, me
);
263 if (my_attach_space
< 0 || my_attach_space
>= nr_hw_phb_spaces
)
264 device_error(me
, "ranges property contains an invalid address space");
265 pci_space
= &phb
->space
[my_attach_space
];
266 if (pci_space
->size
!= 0)
267 device_error(me
, "ranges property contains duplicate mappings for %s address space",
269 pci_space
->parent_base
= parent_attach_address
;
270 pci_space
->parent_space
= parent_attach_space
;
271 pci_space
->my_base
= my_attach_address
;
272 pci_space
->my_space
= my_attach_space
;
273 pci_space
->size
= size
;
274 device_attach_address(device_parent(me
),
276 parent_attach_space
, parent_attach_address
, size
,
277 access_read_write_exec
,
279 DTRACE(phb
, ("map %d:0x%lx to %s:0x%lx (0x%lx bytes)\n",
280 (int)parent_attach_space
,
281 (unsigned long)parent_attach_address
,
283 (unsigned long)my_attach_address
,
284 (unsigned long)size
));
287 if (ranges_entry
== 0) {
288 device_error(me
, "Missing or empty ranges property");
296 hw_phb_attach_address(device
*me
,
302 device
*client
) /*callback/default*/
304 hw_phb_device
*phb
= device_data(me
);
305 phb_space
*pci_space
;
306 hw_phb_decode phb_type
= (hw_phb_decode
)type
;
308 if (space
< 0 || space
>= nr_hw_phb_spaces
)
309 device_error(me
, "attach space (%d) specified by %s invalid",
310 space
, device_path(client
));
311 pci_space
= &phb
->space
[space
];
312 if (addr
+ nr_bytes
> pci_space
->my_base
+ pci_space
->size
313 || addr
< pci_space
->my_base
)
314 device_error(me
, "attach addr (0x%lx) specified by %s outside of bus address range",
315 (unsigned long)addr
, device_path(client
));
316 if (phb_type
!= hw_phb_normal_decode
&& phb_type
!= hw_phb_subtractive_decode
)
317 device_error(me
, "attach type (%d) specified by %s invalid",
318 type
, device_path(client
));
319 /* attach it to the relevent bus */
320 DTRACE(phb
, ("attach %s - %s %s:0x%lx (0x%lx bytes)\n",
322 hw_phb_decode_name(phb_type
),
325 (unsigned long)nr_bytes
));
326 core_attach(pci_space
->map
,
336 /* Extract/set various fields from a PCI unit address.
338 Note: only the least significant 32 bits of each cell is used.
340 Note: for PPC MSB is 0 while for PCI it is 31. */
343 /* relocatable bit n */
346 extract_n(const device_unit
*address
)
348 return EXTRACTED32(address
->cells
[0], 0, 0);
352 set_n(device_unit
*address
)
354 BLIT32(address
->cells
[0], 0, 1);
358 /* prefetchable bit p */
361 extract_p(const device_unit
*address
)
363 ASSERT(address
->nr_cells
== 3);
364 return EXTRACTED32(address
->cells
[0], 1, 1);
368 set_p(device_unit
*address
)
370 BLIT32(address
->cells
[0], 1, 1);
377 extract_t(const device_unit
*address
)
379 ASSERT(address
->nr_cells
== 3);
380 return EXTRACTED32(address
->cells
[0], 2, 2);
384 set_t(device_unit
*address
)
386 BLIT32(address
->cells
[0], 2, 1);
395 ss_32bit_memory_code
= 2,
396 ss_64bit_memory_code
= 3,
400 extract_ss(const device_unit
*address
)
402 ASSERT(address
->nr_cells
== 3);
403 return EXTRACTED32(address
->cells
[0], 6, 7);
407 set_ss(device_unit
*address
, ss_type val
)
409 MBLIT32(address
->cells
[0], 6, 7, val
);
413 /* bus number bbbbbbbb */
417 extract_bbbbbbbb(const device_unit
*address
)
419 ASSERT(address
->nr_cells
== 3);
420 return EXTRACTED32(address
->cells
[0], 8, 15);
426 set_bbbbbbbb(device_unit
*address
, unsigned val
)
428 MBLIT32(address
->cells
[0], 8, 15, val
);
433 /* device number ddddd */
436 extract_ddddd(const device_unit
*address
)
438 ASSERT(address
->nr_cells
== 3);
439 return EXTRACTED32(address
->cells
[0], 16, 20);
443 set_ddddd(device_unit
*address
, unsigned val
)
445 MBLIT32(address
->cells
[0], 16, 20, val
);
449 /* function number fff */
452 extract_fff(const device_unit
*address
)
454 ASSERT(address
->nr_cells
== 3);
455 return EXTRACTED32(address
->cells
[0], 21, 23);
459 set_fff(device_unit
*address
, unsigned val
)
461 MBLIT32(address
->cells
[0], 21, 23, val
);
465 /* register number rrrrrrrr */
468 extract_rrrrrrrr(const device_unit
*address
)
470 ASSERT(address
->nr_cells
== 3);
471 return EXTRACTED32(address
->cells
[0], 24, 31);
475 set_rrrrrrrr(device_unit
*address
, unsigned val
)
477 MBLIT32(address
->cells
[0], 24, 31, val
);
481 /* MSW of 64bit address hh..hh */
484 extract_hh_hh(const device_unit
*address
)
486 ASSERT(address
->nr_cells
== 3);
487 return address
->cells
[1];
491 set_hh_hh(device_unit
*address
, unsigned val
)
493 address
->cells
[2] = val
;
497 /* LSW of 64bit address ll..ll */
500 extract_ll_ll(const device_unit
*address
)
502 ASSERT(address
->nr_cells
== 3);
503 return address
->cells
[2];
507 set_ll_ll(device_unit
*address
, unsigned val
)
509 address
->cells
[2] = val
;
513 /* Convert PCI textual bus address into a device unit */
516 hw_phb_unit_decode(device
*me
,
518 device_unit
*address
)
521 const char *chp
= unit
;
524 if (device_nr_address_cells(me
) != 3)
525 device_error(me
, "PCI bus should have #address-cells == 3");
526 memset(address
, 0, sizeof(*address
));
531 address
->nr_cells
= 3;
533 if (isxdigit(*chp
)) {
534 set_ss(address
, ss_config_code
);
538 /* non-relocatable? */
546 set_ss(address
, ss_io_code
);
549 else if (*chp
== 'm') {
550 set_ss(address
, ss_32bit_memory_code
);
553 else if (*chp
== 'x') {
554 set_ss(address
, ss_64bit_memory_code
);
558 device_error(me
, "Problem parsing PCI address %s", unit
);
562 if (extract_ss(address
) == ss_64bit_memory_code
)
563 device_error(me
, "Invalid alias bit in PCI address %s", unit
);
570 if (extract_ss(address
) != ss_32bit_memory_code
)
571 device_error(me
, "Invalid prefetchable bit (p) in PCI address %s",
581 device_error(me
, "Missing device number in PCI address %s", unit
);
582 val
= strtoul(chp
, &end
, 16);
584 device_error(me
, "Problem parsing device number in PCI address %s", unit
);
585 if ((val
& 0x1f) != val
)
586 device_error(me
, "Device number (0x%lx) out of range (0..0x1f) in PCI address %s",
588 set_ddddd(address
, val
);
591 /* For config space, the F is optional */
592 if (extract_ss(address
) == ss_config_code
593 && (isspace(*chp
) || *chp
== '\0'))
596 /* function number F */
598 device_error(me
, "Missing function number in PCI address %s", unit
);
600 val
= strtoul(chp
, &end
, 10);
602 device_error(me
, "Problem parsing function number in PCI address %s",
604 if ((val
& 7) != val
)
605 device_error(me
, "Function number (%ld) out of range (0..7) in PCI address %s",
607 set_fff(address
, val
);
610 /* for config space, must be end */
611 if (extract_ss(address
) == ss_config_code
) {
612 if (!isspace(*chp
) && *chp
!= '\0')
613 device_error(me
, "Problem parsing PCI config address %s",
618 /* register number RR */
620 device_error(me
, "Missing register number in PCI address %s", unit
);
622 val
= strtoul(chp
, &end
, 16);
624 device_error(me
, "Problem parsing register number in PCI address %s",
626 switch (extract_ss(address
)) {
629 if (extract_n(address
) && val
!= 0)
630 device_error(me
, "non-relocatable I/O register must be zero in PCI address %s", unit
);
631 else if (!extract_n(address
)
632 && val
!= 0x10 && val
!= 0x14 && val
!= 0x18
633 && val
!= 0x1c && val
!= 0x20 && val
!= 0x24)
634 device_error(me
, "I/O register invalid in PCI address %s", unit
);
637 case ss_32bit_memory_code
:
639 if (extract_n(address
) && val
!= 0)
640 device_error(me
, "non-relocatable memory register must be zero in PCI address %s", unit
);
641 else if (!extract_n(address
)
642 && val
!= 0x10 && val
!= 0x14 && val
!= 0x18
643 && val
!= 0x1c && val
!= 0x20 && val
!= 0x24 && val
!= 0x30)
644 device_error(me
, "I/O register (0x%lx) invalid in PCI address %s",
648 case ss_64bit_memory_code
:
649 if (extract_n(address
) && val
!= 0)
650 device_error(me
, "non-relocatable 32bit memory register must be zero in PCI address %s", unit
);
651 else if (!extract_n(address
)
652 && val
!= 0x10 && val
!= 0x18 && val
!= 0x20)
653 device_error(me
, "Register number (0x%lx) invalid in 64bit PCI address %s",
657 device_error(me
, "internal error");
659 if ((val
& 0xff) != val
)
660 device_error(me
, "Register number (0x%lx) out of range (0..0xff) in PCI address %s",
662 set_rrrrrrrr(address
, val
);
667 device_error(me
, "Missing address in PCI address %s", unit
);
669 switch (extract_ss(address
)) {
671 case ss_32bit_memory_code
:
672 val
= strtoul(chp
, &end
, 16);
674 device_error(me
, "Problem parsing address in PCI address %s", unit
);
675 switch (extract_ss(address
)) {
677 if (extract_n(address
) && extract_t(address
)
678 && (val
& 1024) != val
)
679 device_error(me
, "10bit aliased non-relocatable address (0x%lx) out of range in PCI address %s",
681 if (!extract_n(address
) && extract_t(address
)
682 && (val
& 0xffff) != val
)
683 device_error(me
, "64k relocatable address (0x%lx) out of range in PCI address %s",
686 case ss_32bit_memory_code
:
687 if (extract_t(address
) && (val
& 0xfffff) != val
)
688 device_error(me
, "1mb memory address (0x%lx) out of range in PCI address %s",
690 if (!extract_t(address
) && (val
& 0xffffffff) != val
)
691 device_error(me
, "32bit memory address (0x%lx) out of range in PCI address %s",
694 case ss_64bit_memory_code
:
696 device_error(me
, "internal error");
698 set_ll_ll(address
, val
);
701 case ss_64bit_memory_code
:
702 device_error(me
, "64bit addresses unimplemented");
703 set_hh_hh(address
, val
);
704 set_ll_ll(address
, val
);
707 device_error(me
, "internal error");
712 if (!isspace(*chp
) && *chp
!= '\0')
713 device_error(me
, "Problem parsing PCI address %s", unit
);
719 /* Convert PCI device unit into its corresponding textual
723 hw_phb_unit_encode(device
*me
,
724 const device_unit
*unit_address
,
728 if (unit_address
->nr_cells
!= 3)
729 device_error(me
, "Incorrect number of cells in PCI unit address");
730 if (device_nr_address_cells(me
) != 3)
731 device_error(me
, "PCI bus should have #address-cells == 3");
732 if (extract_ss(unit_address
) == ss_config_code
733 && extract_fff(unit_address
) == 0
734 && extract_rrrrrrrr(unit_address
) == 0
735 && extract_hh_hh(unit_address
) == 0
736 && extract_ll_ll(unit_address
) == 0) {
737 /* DD - Configuration Space address */
739 extract_ddddd(unit_address
));
741 else if (extract_ss(unit_address
) == ss_config_code
742 && extract_fff(unit_address
) != 0
743 && extract_rrrrrrrr(unit_address
) == 0
744 && extract_hh_hh(unit_address
) == 0
745 && extract_ll_ll(unit_address
) == 0) {
746 /* DD,F - Configuration Space */
747 sprintf(buf
, "%x,%d",
748 extract_ddddd(unit_address
),
749 extract_fff(unit_address
));
751 else if (extract_ss(unit_address
) == ss_io_code
752 && extract_hh_hh(unit_address
) == 0) {
753 /* [n]i[t]DD,F,RR,NNNNNNNN - 32bit I/O space */
754 sprintf(buf
, "%si%s%x,%d,%x,%x",
755 extract_n(unit_address
) ? "n" : "",
756 extract_t(unit_address
) ? "t" : "",
757 extract_ddddd(unit_address
),
758 extract_fff(unit_address
),
759 extract_rrrrrrrr(unit_address
),
760 extract_ll_ll(unit_address
));
762 else if (extract_ss(unit_address
) == ss_32bit_memory_code
763 && extract_hh_hh(unit_address
) == 0) {
764 /* [n]m[t][p]DD,F,RR,NNNNNNNN - 32bit memory space */
765 sprintf(buf
, "%sm%s%s%x,%d,%x,%x",
766 extract_n(unit_address
) ? "n" : "",
767 extract_t(unit_address
) ? "t" : "",
768 extract_p(unit_address
) ? "p" : "",
769 extract_ddddd(unit_address
),
770 extract_fff(unit_address
),
771 extract_rrrrrrrr(unit_address
),
772 extract_ll_ll(unit_address
));
774 else if (extract_ss(unit_address
) == ss_32bit_memory_code
) {
775 /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN - 64bit memory space */
776 sprintf(buf
, "%sx%s%x,%d,%x,%x%08x",
777 extract_n(unit_address
) ? "n" : "",
778 extract_p(unit_address
) ? "p" : "",
779 extract_ddddd(unit_address
),
780 extract_fff(unit_address
),
781 extract_rrrrrrrr(unit_address
),
782 extract_hh_hh(unit_address
),
783 extract_ll_ll(unit_address
));
786 device_error(me
, "Invalid PCI unit address 0x%08lx 0x%08lx 0x%08lx",
787 (unsigned long)unit_address
->cells
[0],
788 (unsigned long)unit_address
->cells
[1],
789 (unsigned long)unit_address
->cells
[2]);
791 if (strlen(buf
) > sizeof_buf
)
792 error("buffer overflow");
798 hw_phb_address_to_attach_address(device
*me
,
799 const device_unit
*address
,
801 unsigned_word
*attach_address
,
804 if (address
->nr_cells
!= 3)
805 device_error(me
, "attach address has incorrect number of cells");
806 if (address
->cells
[1] != 0)
807 device_error(me
, "64bit attach address unsupported");
809 /* directly decode the address/space */
810 *attach_address
= address
->cells
[2];
811 switch (extract_ss(address
)) {
813 *attach_space
= hw_phb_config_space
;
816 *attach_space
= hw_phb_io_space
;
818 case ss_32bit_memory_code
:
819 case ss_64bit_memory_code
:
820 *attach_space
= hw_phb_memory_space
;
824 /* if non-relocatable finished */
825 if (extract_n(address
))
828 /* make memory and I/O addresses absolute */
829 if (*attach_space
== hw_phb_io_space
830 || *attach_space
== hw_phb_memory_space
) {
832 reg_property_spec assigned
;
833 if (extract_ss(address
) == ss_64bit_memory_code
)
834 device_error(me
, "64bit memory address not unsuported");
836 device_find_reg_array_property(client
, "assigned-addresses", reg_nr
,
839 if (!extract_n(&assigned
.address
)
840 || extract_rrrrrrrr(&assigned
.address
) == 0)
841 device_error(me
, "client %s has invalid assigned-address property",
842 device_path(client
));
843 if (extract_rrrrrrrr(address
) == extract_rrrrrrrr(&assigned
.address
)) {
844 /* corresponding base register */
845 if (extract_ss(address
) != extract_ss(&assigned
.address
))
846 device_error(me
, "client %s has conflicting types for base register 0x%lx",
848 (unsigned long)extract_rrrrrrrr(address
));
849 *attach_address
+= assigned
.address
.cells
[2];
853 device_error(me
, "client %s missing base address register 0x%lx in assigned-addresses property",
855 (unsigned long)extract_rrrrrrrr(address
));
863 hw_phb_size_to_attach_size(device
*me
,
864 const device_unit
*size
,
868 if (size
->nr_cells
!= 2)
869 device_error(me
, "size has incorrect number of cells");
870 if (size
->cells
[0] != 0)
871 device_error(me
, "64bit size unsupported");
872 *nr_bytes
= size
->cells
[1];
873 return size
->cells
[1];
877 static const phb_space
*
878 find_phb_space(hw_phb_device
*phb
,
883 /* find the space that matches the address */
884 for (space
= 0; space
< nr_hw_phb_spaces
; space
++) {
885 phb_space
*pci_space
= &phb
->space
[space
];
886 if (addr
>= pci_space
->parent_base
887 && (addr
+ nr_bytes
) <= (pci_space
->parent_base
+ pci_space
->size
)) {
896 map_phb_addr(const phb_space
*space
,
899 return addr
- space
->parent_base
+ space
->my_base
;
905 hw_phb_io_read_buffer(device
*me
,
913 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
914 const phb_space
*pci_space
= find_phb_space(phb
, addr
, nr_bytes
);
915 unsigned_word bus_addr
;
916 if (pci_space
== NULL
)
918 bus_addr
= map_phb_addr(pci_space
, addr
);
919 DTRACE(phb
, ("io read - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
920 space
, (unsigned long)addr
, pci_space
->name
, (unsigned long)bus_addr
,
922 return core_map_read_buffer(pci_space
->readable
,
923 dest
, bus_addr
, nr_bytes
);
928 hw_phb_io_write_buffer(device
*me
,
936 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
937 const phb_space
*pci_space
= find_phb_space(phb
, addr
, nr_bytes
);
938 unsigned_word bus_addr
;
939 if (pci_space
== NULL
)
941 bus_addr
= map_phb_addr(pci_space
, addr
);
942 DTRACE(phb
, ("io write - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
943 space
, (unsigned long)addr
, pci_space
->name
, (unsigned long)bus_addr
,
945 return core_map_write_buffer(pci_space
->writeable
, source
,
951 hw_phb_dma_read_buffer(device
*me
,
957 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
958 const phb_space
*pci_space
;
960 if (space
!= hw_phb_memory_space
)
961 device_error(me
, "invalid dma address space %d", space
);
962 pci_space
= &phb
->space
[space
];
963 /* check out the address */
964 if ((addr
>= pci_space
->my_base
965 && addr
<= pci_space
->my_base
+ pci_space
->size
)
966 || (addr
+ nr_bytes
>= pci_space
->my_base
967 && addr
+ nr_bytes
<= pci_space
->my_base
+ pci_space
->size
))
968 device_error(me
, "Do not support DMA into own bus");
970 DTRACE(phb
, ("dma read - %s:0x%lx (%d bytes)\n",
971 pci_space
->name
, (unsigned long)addr
, nr_bytes
));
972 return device_dma_read_buffer(device_parent(me
),
973 dest
, pci_space
->parent_space
,
979 hw_phb_dma_write_buffer(device
*me
,
984 int violate_read_only_section
)
986 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
987 const phb_space
*pci_space
;
989 if (space
!= hw_phb_memory_space
)
990 device_error(me
, "invalid dma address space %d", space
);
991 pci_space
= &phb
->space
[space
];
992 /* check out the address */
993 if ((addr
>= pci_space
->my_base
994 && addr
<= pci_space
->my_base
+ pci_space
->size
)
995 || (addr
+ nr_bytes
>= pci_space
->my_base
996 && addr
+ nr_bytes
<= pci_space
->my_base
+ pci_space
->size
))
997 device_error(me
, "Do not support DMA into own bus");
999 DTRACE(phb
, ("dma write - %s:0x%lx (%d bytes)\n",
1000 pci_space
->name
, (unsigned long)addr
, nr_bytes
));
1001 return device_dma_write_buffer(device_parent(me
),
1002 source
, pci_space
->parent_space
,
1004 violate_read_only_section
);
1008 static device_callbacks
const hw_phb_callbacks
= {
1009 { hw_phb_init_address
, },
1010 { hw_phb_attach_address
, },
1011 { hw_phb_io_read_buffer
, hw_phb_io_write_buffer
},
1012 { hw_phb_dma_read_buffer
, hw_phb_dma_write_buffer
},
1013 { NULL
, }, /* interrupt */
1014 { hw_phb_unit_decode
,
1016 hw_phb_address_to_attach_address
,
1017 hw_phb_size_to_attach_size
}
1022 hw_phb_create(const char *name
,
1023 const device_unit
*unit_address
,
1026 /* create the descriptor */
1027 hw_phb_device
*phb
= ZALLOC(hw_phb_device
);
1029 /* create the core maps now */
1030 hw_phb_spaces space_nr
;
1031 for (space_nr
= 0; space_nr
< nr_hw_phb_spaces
; space_nr
++) {
1032 phb_space
*pci_space
= &phb
->space
[space_nr
];
1033 pci_space
->map
= core_create();
1034 pci_space
->readable
= core_readable(pci_space
->map
);
1035 pci_space
->writeable
= core_writeable(pci_space
->map
);
1037 case hw_phb_memory_space
:
1038 pci_space
->name
= "memory";
1040 case hw_phb_io_space
:
1041 pci_space
->name
= "I/O";
1043 case hw_phb_config_space
:
1044 pci_space
->name
= "config";
1046 case hw_phb_special_space
:
1047 pci_space
->name
= "special";
1050 error ("internal error");
1059 const device_descriptor hw_phb_device_descriptor
[] = {
1060 { "phb", hw_phb_create
, &hw_phb_callbacks
},
1061 { "pci", NULL
, &hw_phb_callbacks
},
1065 #endif /* _HW_PHB_ */