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 2 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 #include "device_table.h"
47 PHB implements a model of the PCI-host bridge described in the PPCP
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
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.
65 ranges = <my-phys-addr> <parent-phys-addr> <my-size> ... (required)
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).
74 #address-cells = 3 (required)
76 Number of cells used by an Open Firmware PCI address. This
77 property must be defined before specifying the <<ranges>> property.
80 #size-cells = 2 (required)
82 Number of cells used by an Open Firmware PCI size. This property
83 must be defined before specifying the <<ranges>> property.
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>>.
101 | -o '/#address-cells 1' \
104 Create the PHB remembering to include the cell size properties:
106 | -o '/phb@0x80000000/#address-cells 3' \
107 | -o '/phb@0x80000000/#size-cells 2' \
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
116 | -o '/phb@0x80000000/ranges \
117 | nm0,0,0,80000000 0x80000000 0x10000000 \
118 | ni0,0,0,0 0xc0000000 0x10000' \
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:
125 | -o '/phb@0x80000000/nvram@0/assigned-addresses \
126 | nm0,0,10,80001000 4096 \
128 | -o '/phb@0x80000000/nvram@0/reg \
131 | -o '/phb@0x80000000/nvram@0/alternate-reg \
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.
140 Of the possible addresses, only the non-relocatable versions are
141 used when attaching the device to the bus.
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.
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.
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.
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
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.
168 Support for aliased memory and I/O addresses is left as an exercise
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
177 Children of this node can only use the client callback interface
178 when attaching themselves to the <<phb>>.
184 http://playground.sun.com/1275/home.html#OFDbusPCI
190 typedef struct _phb_space
{
194 unsigned_word parent_base
;
196 unsigned_word my_base
;
202 typedef struct _hw_phb_device
{
203 phb_space space
[nr_hw_phb_spaces
];
208 hw_phb_decode_name(hw_phb_decode 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";
220 hw_phb_init_address(device
*me
)
222 hw_phb_device
*phb
= device_data(me
);
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");
230 /* (re) initialize each PCI space */
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
);
240 /* decode each of the ranges properties entering the information
241 into the space table */
243 range_property_spec range
;
246 for (ranges_entry
= 0;
247 device_find_range_array_property(me
, "ranges", ranges_entry
,
251 unsigned_word my_attach_address
;
252 int parent_attach_space
;
253 unsigned_word parent_attach_address
;
255 phb_space
*pci_space
;
256 /* convert the addresses into something meaningful */
257 device_address_to_attach_address(me
, &range
.child_address
,
261 device_address_to_attach_address(device_parent(me
),
262 &range
.parent_address
,
263 &parent_attach_space
,
264 &parent_attach_address
,
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",
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
),
280 parent_attach_space
, parent_attach_address
, size
,
281 access_read_write_exec
,
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
,
287 (unsigned long)my_attach_address
,
288 (unsigned long)size
));
291 if (ranges_entry
== 0) {
292 device_error(me
, "Missing or empty ranges property");
300 hw_phb_attach_address(device
*me
,
306 device
*client
) /*callback/default*/
308 hw_phb_device
*phb
= device_data(me
);
309 phb_space
*pci_space
;
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",
326 hw_phb_decode_name(type
),
329 (unsigned long)nr_bytes
));
330 core_attach(pci_space
->map
,
340 /* Extract/set various fields from a PCI unit address.
342 Note: only the least significant 32 bits of each cell is used.
344 Note: for PPC MSB is 0 while for PCI it is 31. */
347 /* relocatable bit n */
350 extract_n(const device_unit
*address
)
352 return EXTRACTED32(address
->cells
[0], 0, 0);
356 set_n(device_unit
*address
)
358 BLIT32(address
->cells
[0], 0, 1);
362 /* prefetchable bit p */
365 extract_p(const device_unit
*address
)
367 ASSERT(address
->nr_cells
== 3);
368 return EXTRACTED32(address
->cells
[0], 1, 1);
372 set_p(device_unit
*address
)
374 BLIT32(address
->cells
[0], 1, 1);
381 extract_t(const device_unit
*address
)
383 ASSERT(address
->nr_cells
== 3);
384 return EXTRACTED32(address
->cells
[0], 2, 2);
388 set_t(device_unit
*address
)
390 BLIT32(address
->cells
[0], 2, 1);
399 ss_32bit_memory_code
= 2,
400 ss_64bit_memory_code
= 3,
404 extract_ss(const device_unit
*address
)
406 ASSERT(address
->nr_cells
== 3);
407 return EXTRACTED32(address
->cells
[0], 6, 7);
411 set_ss(device_unit
*address
, ss_type val
)
413 MBLIT32(address
->cells
[0], 6, 7, val
);
417 /* bus number bbbbbbbb */
421 extract_bbbbbbbb(const device_unit
*address
)
423 ASSERT(address
->nr_cells
== 3);
424 return EXTRACTED32(address
->cells
[0], 8, 15);
430 set_bbbbbbbb(device_unit
*address
, unsigned val
)
432 MBLIT32(address
->cells
[0], 8, 15, val
);
437 /* device number ddddd */
440 extract_ddddd(const device_unit
*address
)
442 ASSERT(address
->nr_cells
== 3);
443 return EXTRACTED32(address
->cells
[0], 16, 20);
447 set_ddddd(device_unit
*address
, unsigned val
)
449 MBLIT32(address
->cells
[0], 16, 20, val
);
453 /* function number fff */
456 extract_fff(const device_unit
*address
)
458 ASSERT(address
->nr_cells
== 3);
459 return EXTRACTED32(address
->cells
[0], 21, 23);
463 set_fff(device_unit
*address
, unsigned val
)
465 MBLIT32(address
->cells
[0], 21, 23, val
);
469 /* register number rrrrrrrr */
472 extract_rrrrrrrr(const device_unit
*address
)
474 ASSERT(address
->nr_cells
== 3);
475 return EXTRACTED32(address
->cells
[0], 24, 31);
479 set_rrrrrrrr(device_unit
*address
, unsigned val
)
481 MBLIT32(address
->cells
[0], 24, 31, val
);
485 /* MSW of 64bit address hh..hh */
488 extract_hh_hh(const device_unit
*address
)
490 ASSERT(address
->nr_cells
== 3);
491 return address
->cells
[1];
495 set_hh_hh(device_unit
*address
, unsigned val
)
497 address
->cells
[2] = val
;
501 /* LSW of 64bit address ll..ll */
504 extract_ll_ll(const device_unit
*address
)
506 ASSERT(address
->nr_cells
== 3);
507 return address
->cells
[2];
511 set_ll_ll(device_unit
*address
, unsigned val
)
513 address
->cells
[2] = val
;
517 /* Convert PCI textual bus address into a device unit */
520 hw_phb_unit_decode(device
*me
,
522 device_unit
*address
)
525 const char *chp
= unit
;
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
));
535 address
->nr_cells
= 3;
537 if (isxdigit(*chp
)) {
538 set_ss(address
, ss_config_code
);
542 /* non-relocatable? */
550 set_ss(address
, ss_io_code
);
553 else if (*chp
== 'm') {
554 set_ss(address
, ss_32bit_memory_code
);
557 else if (*chp
== 'x') {
558 set_ss(address
, ss_64bit_memory_code
);
562 device_error(me
, "Problem parsing PCI address %s", unit
);
566 if (extract_ss(address
) == ss_64bit_memory_code
)
567 device_error(me
, "Invalid alias bit in PCI address %s", unit
);
574 if (extract_ss(address
) != ss_32bit_memory_code
)
575 device_error(me
, "Invalid prefetchable bit (p) in PCI address %s",
585 device_error(me
, "Missing device number in PCI address %s", unit
);
586 val
= strtoul(chp
, &end
, 16);
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",
592 set_ddddd(address
, val
);
595 /* For config space, the F is optional */
596 if (extract_ss(address
) == ss_config_code
597 && (isspace(*chp
) || *chp
== '\0'))
600 /* function number F */
602 device_error(me
, "Missing function number in PCI address %s", unit
);
604 val
= strtoul(chp
, &end
, 10);
606 device_error(me
, "Problem parsing function number in PCI address %s",
608 if ((val
& 7) != val
)
609 device_error(me
, "Function number (%ld) out of range (0..7) in PCI address %s",
611 set_fff(address
, val
);
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",
622 /* register number RR */
624 device_error(me
, "Missing register number in PCI address %s", unit
);
626 val
= strtoul(chp
, &end
, 16);
628 device_error(me
, "Problem parsing register number in PCI address %s",
630 switch (extract_ss(address
)) {
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
);
641 case ss_32bit_memory_code
:
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",
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",
660 device_error(me
, "internal error");
662 if ((val
& 0xff) != val
)
663 device_error(me
, "Register number (0x%lx) out of range (0..0xff) in PCI address %s",
665 set_rrrrrrrr(address
, val
);
670 device_error(me
, "Missing address in PCI address %s", unit
);
672 switch (extract_ss(address
)) {
674 case ss_32bit_memory_code
:
675 val
= strtoul(chp
, &end
, 16);
677 device_error(me
, "Problem parsing address in PCI address %s", unit
);
678 switch (extract_ss(address
)) {
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",
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",
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",
693 if (!extract_t(address
) && (val
& 0xffffffff) != val
)
694 device_error(me
, "32bit memory address (0x%lx) out of range in PCI address %s",
697 case ss_64bit_memory_code
:
699 device_error(me
, "internal error");
701 set_ll_ll(address
, val
);
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
);
710 device_error(me
, "internal error");
715 if (!isspace(*chp
) && *chp
!= '\0')
716 device_error(me
, "Problem parsing PCI address %s", unit
);
722 /* Convert PCI device unit into its corresponding textual
726 hw_phb_unit_encode(device
*me
,
727 const device_unit
*unit_address
,
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 */
742 extract_ddddd(unit_address
));
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
));
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
));
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
));
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
));
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]);
794 if (strlen(buf
) > sizeof_buf
)
795 error("buffer overflow");
801 hw_phb_address_to_attach_address(device
*me
,
802 const device_unit
*address
,
804 unsigned_word
*attach_address
,
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");
812 /* directly decode the address/space */
813 *attach_address
= address
->cells
[2];
814 switch (extract_ss(address
)) {
816 *attach_space
= hw_phb_config_space
;
819 *attach_space
= hw_phb_io_space
;
821 case ss_32bit_memory_code
:
822 case ss_64bit_memory_code
:
823 *attach_space
= hw_phb_memory_space
;
827 /* if non-relocatable finished */
828 if (extract_n(address
))
831 /* make memory and I/O addresses absolute */
832 if (*attach_space
== hw_phb_io_space
833 || *attach_space
== hw_phb_memory_space
) {
835 reg_property_spec assigned
;
836 if (extract_ss(address
) == ss_64bit_memory_code
)
837 device_error(me
, "64bit memory address not unsuported");
839 device_find_reg_array_property(client
, "assigned-addresses", 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",
851 (unsigned long)extract_rrrrrrrr(address
));
852 *attach_address
+= assigned
.address
.cells
[2];
856 device_error(me
, "client %s missing base address register 0x%lx in assigned-addresses property",
858 (unsigned long)extract_rrrrrrrr(address
));
866 hw_phb_size_to_attach_size(device
*me
,
867 const device_unit
*size
,
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];
880 static const phb_space
*
881 find_phb_space(hw_phb_device
*phb
,
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
)) {
899 map_phb_addr(const phb_space
*space
,
902 return addr
- space
->parent_base
+ space
->my_base
;
908 hw_phb_io_read_buffer(device
*me
,
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
)
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
,
925 return core_map_read_buffer(pci_space
->readable
,
926 dest
, bus_addr
, nr_bytes
);
931 hw_phb_io_write_buffer(device
*me
,
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
)
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
,
948 return core_map_write_buffer(pci_space
->writeable
, source
,
954 hw_phb_dma_read_buffer(device
*me
,
960 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
961 const phb_space
*pci_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");
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
,
982 hw_phb_dma_write_buffer(device
*me
,
987 int violate_read_only_section
)
989 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
990 const phb_space
*pci_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");
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
,
1007 violate_read_only_section
);
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
,
1019 hw_phb_address_to_attach_address
,
1020 hw_phb_size_to_attach_size
}
1025 hw_phb_create(const char *name
,
1026 const device_unit
*unit_address
,
1029 /* create the descriptor */
1030 hw_phb_device
*phb
= ZALLOC(hw_phb_device
);
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
);
1040 case hw_phb_memory_space
:
1041 pci_space
->name
= "memory";
1043 case hw_phb_io_space
:
1044 pci_space
->name
= "I/O";
1046 case hw_phb_config_space
:
1047 pci_space
->name
= "config";
1049 case hw_phb_special_space
:
1050 pci_space
->name
= "special";
1053 error ("internal error");
1062 const device_descriptor hw_phb_device_descriptor
[] = {
1063 { "phb", hw_phb_create
, &hw_phb_callbacks
},
1064 { "pci", NULL
, &hw_phb_callbacks
},
1068 #endif /* _HW_PHB_ */