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"
46 PHB implements a model of the PCI-host bridge described in the PPCP
49 For bridge devices, Open Firmware specifies that the <<ranges>>
50 property be used to specify the mapping of address spaces between a
51 bridges parent and child busses. This PHB model configures itsself
52 according to the information specified in its ranges property. The
53 <<ranges>> property is described in detail in the Open Firmware
56 For DMA transfers, any access to a PCI address space which falls
57 outside of the mapped memory space is assumed to be a transfer
58 intended for the parent bus.
64 ranges = <my-phys-addr> <parent-phys-addr> <my-size> ... (required)
66 Define a number of mappings from the parent bus to one of this
67 devices PCI busses. The exact format of the <<parent-phys-addr>>
68 is parent bus dependant. The format of <<my-phys-addr>> is
69 described in the Open Firmware PCI bindings document (note that the
70 address must be non-relocatable).
73 #address-cells = 3 (required)
75 Number of cells used by an Open Firmware PCI address. This
76 property must be defined before specifying the <<ranges>> property.
79 #size-cells = 2 (required)
81 Number of cells used by an Open Firmware PCI size. This property
82 must be defined before specifying the <<ranges>> property.
94 Since device tree entries that are specified on the command line
95 are added before most of the device tree has been built it is often
96 necessary to explictly add certain device properties and thus
97 ensure they are already present in the device tree. For the
98 <<phb>> one such property is parent busses <<#address-cells>>.
100 | -o '/#address-cells 1' \
103 Create the PHB remembering to include the cell size properties:
105 | -o '/phb@0x80000000/#address-cells 3' \
106 | -o '/phb@0x80000000/#size-cells 2' \
109 Specify that the memory address range <<0x80000000>> to
110 <<0x8fffffff>> should map directly onto the PCI memory address
111 space while the processor address range <<0xc0000000>> to
112 <<0xc000ffff>> should map onto the PCI I/O address range starting
115 | -o '/phb@0x80000000/ranges \
116 | nm0,0,0,80000000 0x80000000 0x10000000 \
117 | ni0,0,0,0 0xc0000000 0x10000' \
120 Insert a 4k <<nvram>> into slot zero of the PCI bus. Have it
121 directly accessible in both the I/O (address <<0x100>>) and memory
122 (address 0x80001000) spaces:
124 | -o '/phb@0x80000000/nvram@0/assigned-addresses \
125 | nm0,0,10,80001000 4096 \
127 | -o '/phb@0x80000000/nvram@0/reg \
130 | -o '/phb@0x80000000/nvram@0/alternate-reg \
134 The <<assigned-address>> property corresponding to what (if it were
135 implemented) be found in the config base registers while the
136 <<reg>> and <<alternative-reg>> properties indicating the location
137 of registers within each address space.
139 Of the possible addresses, only the non-relocatable versions are
140 used when attaching the device to the bus.
146 The implementation of the PCI configuration space is left as an
147 exercise for the reader. Such a restriction should only impact on
148 systems wanting to dynamically configure devices on the PCI bus.
150 The <<CHRP>> document specfies additional (optional) functionality
151 of the primary PHB. The implementation of such functionality is
152 left as an exercise for the reader.
154 The Open Firmware PCI bus bindings document (rev 1.6 and 2.0) is
155 unclear on the value of the "ss" bits for a 64bit memory address.
156 The correct value, as used by this module, is 0b11.
158 The Open Firmware PCI bus bindings document (rev 1.6) suggests that
159 the register field of non-relocatable PCI address should be zero.
160 Unfortunatly, PCI addresses specified in the <<assigned-addresses>>
161 property must be both non-relocatable and have non-zero register
164 The unit-decode method is not inserting a bus number into any
165 address that it decodes. Instead the bus-number is left as zero.
167 Support for aliased memory and I/O addresses is left as an exercise
170 Support for interrupt-ack and special cycles are left as an
171 exercise for the reader. One issue to consider when attempting
172 this exercise is how to specify the address of the int-ack and
173 special cycle register. Hint: <</8259-interrupt-ackowledge>> is
176 Children of this node can only use the client callback interface
177 when attaching themselves to the <<phb>>.
183 http://playground.sun.com/1275/home.html#OFDbusPCI
189 typedef struct _phb_space
{
193 unsigned_word parent_base
;
195 unsigned_word my_base
;
201 typedef struct _hw_phb_device
{
202 phb_space space
[nr_hw_phb_spaces
];
207 hw_phb_decode_name(hw_phb_decode level
)
210 case hw_phb_normal_decode
: return "normal";
211 case hw_phb_subtractive_decode
: return "subtractive";
212 case hw_phb_master_abort_decode
: return "master-abort";
213 default: return "invalid decode";
219 hw_phb_init_address(device
*me
)
221 hw_phb_device
*phb
= device_data(me
);
223 /* check some basic properties */
224 if (device_nr_address_cells(me
) != 3)
225 device_error(me
, "incorrect #address-cells");
226 if (device_nr_size_cells(me
) != 2)
227 device_error(me
, "incorrect #size-cells");
229 /* (re) initialize each PCI space */
231 hw_phb_spaces space_nr
;
232 for (space_nr
= 0; space_nr
< nr_hw_phb_spaces
; space_nr
++) {
233 phb_space
*pci_space
= &phb
->space
[space_nr
];
234 core_init(pci_space
->map
);
239 /* decode each of the ranges properties entering the information
240 into the space table */
242 range_property_spec range
;
245 for (ranges_entry
= 0;
246 device_find_range_array_property(me
, "ranges", ranges_entry
,
250 unsigned_word my_attach_address
;
251 int parent_attach_space
;
252 unsigned_word parent_attach_address
;
254 phb_space
*pci_space
;
255 /* convert the addresses into something meaningful */
256 device_address_to_attach_address(me
, &range
.child_address
,
260 device_address_to_attach_address(device_parent(me
),
261 &range
.parent_address
,
262 &parent_attach_space
,
263 &parent_attach_address
,
265 device_size_to_attach_size(me
, &range
.size
, &size
, me
);
266 if (my_attach_space
< 0 || my_attach_space
>= nr_hw_phb_spaces
)
267 device_error(me
, "ranges property contains an invalid address space");
268 pci_space
= &phb
->space
[my_attach_space
];
269 if (pci_space
->size
!= 0)
270 device_error(me
, "ranges property contains duplicate mappings for %s address space",
272 pci_space
->parent_base
= parent_attach_address
;
273 pci_space
->parent_space
= parent_attach_space
;
274 pci_space
->my_base
= my_attach_address
;
275 pci_space
->my_space
= my_attach_space
;
276 pci_space
->size
= size
;
277 device_attach_address(device_parent(me
),
279 parent_attach_space
, parent_attach_address
, size
,
280 access_read_write_exec
,
282 DTRACE(phb
, ("map %d:0x%lx to %s:0x%lx (0x%lx bytes)\n",
283 (int)parent_attach_space
,
284 (unsigned long)parent_attach_address
,
286 (unsigned long)my_attach_address
,
287 (unsigned long)size
));
290 if (ranges_entry
== 0) {
291 device_error(me
, "Missing or empty ranges property");
299 hw_phb_attach_address(device
*me
,
305 device
*client
) /*callback/default*/
307 hw_phb_device
*phb
= device_data(me
);
308 phb_space
*pci_space
;
310 if (space
< 0 || space
>= nr_hw_phb_spaces
)
311 device_error(me
, "attach space (%d) specified by %s invalid",
312 space
, device_path(client
));
313 pci_space
= &phb
->space
[space
];
314 if (addr
+ nr_bytes
> pci_space
->my_base
+ pci_space
->size
315 || addr
< pci_space
->my_base
)
316 device_error(me
, "attach addr (0x%lx) specified by %s outside of bus address range",
317 (unsigned long)addr
, device_path(client
));
318 if (type
!= hw_phb_normal_decode
319 && type
!= hw_phb_subtractive_decode
)
320 device_error(me
, "attach type (%d) specified by %s invalid",
321 type
, device_path(client
));
322 /* attach it to the relevent bus */
323 DTRACE(phb
, ("attach %s - %s %s:0x%lx (0x%lx bytes)\n",
325 hw_phb_decode_name(type
),
328 (unsigned long)nr_bytes
));
329 core_attach(pci_space
->map
,
339 /* Extract/set various fields from a PCI unit address.
341 Note: only the least significant 32 bits of each cell is used.
343 Note: for PPC MSB is 0 while for PCI it is 31. */
346 /* relocatable bit n */
349 extract_n(const device_unit
*address
)
351 return EXTRACTED32(address
->cells
[0], 0, 0);
355 set_n(device_unit
*address
)
357 BLIT32(address
->cells
[0], 0, 1);
361 /* prefetchable bit p */
364 extract_p(const device_unit
*address
)
366 ASSERT(address
->nr_cells
== 3);
367 return EXTRACTED32(address
->cells
[0], 1, 1);
371 set_p(device_unit
*address
)
373 BLIT32(address
->cells
[0], 1, 1);
380 extract_t(const device_unit
*address
)
382 ASSERT(address
->nr_cells
== 3);
383 return EXTRACTED32(address
->cells
[0], 2, 2);
387 set_t(device_unit
*address
)
389 BLIT32(address
->cells
[0], 2, 1);
398 ss_32bit_memory_code
= 2,
399 ss_64bit_memory_code
= 3,
403 extract_ss(const device_unit
*address
)
405 ASSERT(address
->nr_cells
== 3);
406 return EXTRACTED32(address
->cells
[0], 6, 7);
410 set_ss(device_unit
*address
, ss_type val
)
412 MBLIT32(address
->cells
[0], 6, 7, val
);
416 /* bus number bbbbbbbb */
420 extract_bbbbbbbb(const device_unit
*address
)
422 ASSERT(address
->nr_cells
== 3);
423 return EXTRACTED32(address
->cells
[0], 8, 15);
429 set_bbbbbbbb(device_unit
*address
, unsigned val
)
431 MBLIT32(address
->cells
[0], 8, 15, val
);
436 /* device number ddddd */
439 extract_ddddd(const device_unit
*address
)
441 ASSERT(address
->nr_cells
== 3);
442 return EXTRACTED32(address
->cells
[0], 16, 20);
446 set_ddddd(device_unit
*address
, unsigned val
)
448 MBLIT32(address
->cells
[0], 16, 20, val
);
452 /* function number fff */
455 extract_fff(const device_unit
*address
)
457 ASSERT(address
->nr_cells
== 3);
458 return EXTRACTED32(address
->cells
[0], 21, 23);
462 set_fff(device_unit
*address
, unsigned val
)
464 MBLIT32(address
->cells
[0], 21, 23, val
);
468 /* register number rrrrrrrr */
471 extract_rrrrrrrr(const device_unit
*address
)
473 ASSERT(address
->nr_cells
== 3);
474 return EXTRACTED32(address
->cells
[0], 24, 31);
478 set_rrrrrrrr(device_unit
*address
, unsigned val
)
480 MBLIT32(address
->cells
[0], 24, 31, val
);
484 /* MSW of 64bit address hh..hh */
487 extract_hh_hh(const device_unit
*address
)
489 ASSERT(address
->nr_cells
== 3);
490 return address
->cells
[1];
494 set_hh_hh(device_unit
*address
, unsigned val
)
496 address
->cells
[2] = val
;
500 /* LSW of 64bit address ll..ll */
503 extract_ll_ll(const device_unit
*address
)
505 ASSERT(address
->nr_cells
== 3);
506 return address
->cells
[2];
510 set_ll_ll(device_unit
*address
, unsigned val
)
512 address
->cells
[2] = val
;
516 /* Convert PCI textual bus address into a device unit */
519 hw_phb_unit_decode(device
*me
,
521 device_unit
*address
)
524 const char *chp
= unit
;
527 if (device_nr_address_cells(me
) != 3)
528 device_error(me
, "PCI bus should have #address-cells == 3");
529 memset(address
, 0, sizeof(*address
));
534 address
->nr_cells
= 3;
536 if (isxdigit(*chp
)) {
537 set_ss(address
, ss_config_code
);
541 /* non-relocatable? */
549 set_ss(address
, ss_io_code
);
552 else if (*chp
== 'm') {
553 set_ss(address
, ss_32bit_memory_code
);
556 else if (*chp
== 'x') {
557 set_ss(address
, ss_64bit_memory_code
);
561 device_error(me
, "Problem parsing PCI address %s", unit
);
565 if (extract_ss(address
) == ss_64bit_memory_code
)
566 device_error(me
, "Invalid alias bit in PCI address %s", unit
);
573 if (extract_ss(address
) != ss_32bit_memory_code
)
574 device_error(me
, "Invalid prefetchable bit (p) in PCI address %s",
584 device_error(me
, "Missing device number in PCI address %s", unit
);
585 val
= strtoul(chp
, &end
, 16);
587 device_error(me
, "Problem parsing device number in PCI address %s", unit
);
588 if ((val
& 0x1f) != val
)
589 device_error(me
, "Device number (0x%lx) out of range (0..0x1f) in PCI address %s",
591 set_ddddd(address
, val
);
594 /* For config space, the F is optional */
595 if (extract_ss(address
) == ss_config_code
596 && (isspace(*chp
) || *chp
== '\0'))
599 /* function number F */
601 device_error(me
, "Missing function number in PCI address %s", unit
);
603 val
= strtoul(chp
, &end
, 10);
605 device_error(me
, "Problem parsing function number in PCI address %s",
607 if ((val
& 7) != val
)
608 device_error(me
, "Function number (%ld) out of range (0..7) in PCI address %s",
610 set_fff(address
, val
);
613 /* for config space, must be end */
614 if (extract_ss(address
) == ss_config_code
) {
615 if (!isspace(*chp
) && *chp
!= '\0')
616 device_error(me
, "Problem parsing PCI config address %s",
621 /* register number RR */
623 device_error(me
, "Missing register number in PCI address %s", unit
);
625 val
= strtoul(chp
, &end
, 16);
627 device_error(me
, "Problem parsing register number in PCI address %s",
629 switch (extract_ss(address
)) {
632 if (extract_n(address
) && val
!= 0)
633 device_error(me
, "non-relocatable I/O register must be zero in PCI address %s", unit
);
634 else if (!extract_n(address
)
635 && val
!= 0x10 && val
!= 0x14 && val
!= 0x18
636 && val
!= 0x1c && val
!= 0x20 && val
!= 0x24)
637 device_error(me
, "I/O register invalid in PCI address %s", unit
);
640 case ss_32bit_memory_code
:
642 if (extract_n(address
) && val
!= 0)
643 device_error(me
, "non-relocatable memory register must be zero in PCI address %s", unit
);
644 else if (!extract_n(address
)
645 && val
!= 0x10 && val
!= 0x14 && val
!= 0x18
646 && val
!= 0x1c && val
!= 0x20 && val
!= 0x24 && val
!= 0x30)
647 device_error(me
, "I/O register (0x%lx) invalid in PCI address %s",
651 case ss_64bit_memory_code
:
652 if (extract_n(address
) && val
!= 0)
653 device_error(me
, "non-relocatable 32bit memory register must be zero in PCI address %s", unit
);
654 else if (!extract_n(address
)
655 && val
!= 0x10 && val
!= 0x18 && val
!= 0x20)
656 device_error(me
, "Register number (0x%lx) invalid in 64bit PCI address %s",
659 device_error(me
, "internal error");
661 if ((val
& 0xff) != val
)
662 device_error(me
, "Register number (0x%lx) out of range (0..0xff) in PCI address %s",
664 set_rrrrrrrr(address
, val
);
669 device_error(me
, "Missing address in PCI address %s", unit
);
671 switch (extract_ss(address
)) {
673 case ss_32bit_memory_code
:
674 val
= strtoul(chp
, &end
, 16);
676 device_error(me
, "Problem parsing address in PCI address %s", unit
);
677 switch (extract_ss(address
)) {
679 if (extract_n(address
) && extract_t(address
)
680 && (val
& 1024) != val
)
681 device_error(me
, "10bit aliased non-relocatable address (0x%lx) out of range in PCI address %s",
683 if (!extract_n(address
) && extract_t(address
)
684 && (val
& 0xffff) != val
)
685 device_error(me
, "64k relocatable address (0x%lx) out of range in PCI address %s",
688 case ss_32bit_memory_code
:
689 if (extract_t(address
) && (val
& 0xfffff) != val
)
690 device_error(me
, "1mb memory address (0x%lx) out of range in PCI address %s",
692 if (!extract_t(address
) && (val
& 0xffffffff) != val
)
693 device_error(me
, "32bit memory address (0x%lx) out of range in PCI address %s",
696 case ss_64bit_memory_code
:
698 device_error(me
, "internal error");
700 set_ll_ll(address
, val
);
703 case ss_64bit_memory_code
:
704 device_error(me
, "64bit addresses unimplemented");
705 set_hh_hh(address
, val
);
706 set_ll_ll(address
, val
);
709 device_error(me
, "internal error");
714 if (!isspace(*chp
) && *chp
!= '\0')
715 device_error(me
, "Problem parsing PCI address %s", unit
);
721 /* Convert PCI device unit into its corresponding textual
725 hw_phb_unit_encode(device
*me
,
726 const device_unit
*unit_address
,
730 if (unit_address
->nr_cells
!= 3)
731 device_error(me
, "Incorrect number of cells in PCI unit address");
732 if (device_nr_address_cells(me
) != 3)
733 device_error(me
, "PCI bus should have #address-cells == 3");
734 if (extract_ss(unit_address
) == ss_config_code
735 && extract_fff(unit_address
) == 0
736 && extract_rrrrrrrr(unit_address
) == 0
737 && extract_hh_hh(unit_address
) == 0
738 && extract_ll_ll(unit_address
) == 0) {
739 /* DD - Configuration Space address */
741 extract_ddddd(unit_address
));
743 else if (extract_ss(unit_address
) == ss_config_code
744 && extract_fff(unit_address
) != 0
745 && extract_rrrrrrrr(unit_address
) == 0
746 && extract_hh_hh(unit_address
) == 0
747 && extract_ll_ll(unit_address
) == 0) {
748 /* DD,F - Configuration Space */
749 sprintf(buf
, "%x,%d",
750 extract_ddddd(unit_address
),
751 extract_fff(unit_address
));
753 else if (extract_ss(unit_address
) == ss_io_code
754 && extract_hh_hh(unit_address
) == 0) {
755 /* [n]i[t]DD,F,RR,NNNNNNNN - 32bit I/O space */
756 sprintf(buf
, "%si%s%x,%d,%x,%x",
757 extract_n(unit_address
) ? "n" : "",
758 extract_t(unit_address
) ? "t" : "",
759 extract_ddddd(unit_address
),
760 extract_fff(unit_address
),
761 extract_rrrrrrrr(unit_address
),
762 extract_ll_ll(unit_address
));
764 else if (extract_ss(unit_address
) == ss_32bit_memory_code
765 && extract_hh_hh(unit_address
) == 0) {
766 /* [n]m[t][p]DD,F,RR,NNNNNNNN - 32bit memory space */
767 sprintf(buf
, "%sm%s%s%x,%d,%x,%x",
768 extract_n(unit_address
) ? "n" : "",
769 extract_t(unit_address
) ? "t" : "",
770 extract_p(unit_address
) ? "p" : "",
771 extract_ddddd(unit_address
),
772 extract_fff(unit_address
),
773 extract_rrrrrrrr(unit_address
),
774 extract_ll_ll(unit_address
));
776 else if (extract_ss(unit_address
) == ss_32bit_memory_code
) {
777 /* [n]x[p]DD,F,RR,NNNNNNNNNNNNNNNN - 64bit memory space */
778 sprintf(buf
, "%sx%s%x,%d,%x,%x%08x",
779 extract_n(unit_address
) ? "n" : "",
780 extract_p(unit_address
) ? "p" : "",
781 extract_ddddd(unit_address
),
782 extract_fff(unit_address
),
783 extract_rrrrrrrr(unit_address
),
784 extract_hh_hh(unit_address
),
785 extract_ll_ll(unit_address
));
788 device_error(me
, "Invalid PCI unit address 0x%08lx 0x%08lx 0x%08lx",
789 (unsigned long)unit_address
->cells
[0],
790 (unsigned long)unit_address
->cells
[1],
791 (unsigned long)unit_address
->cells
[2]);
793 if (strlen(buf
) > sizeof_buf
)
794 error("buffer overflow");
800 hw_phb_address_to_attach_address(device
*me
,
801 const device_unit
*address
,
803 unsigned_word
*attach_address
,
806 if (address
->nr_cells
!= 3)
807 device_error(me
, "attach address has incorrect number of cells");
808 if (address
->cells
[1] != 0)
809 device_error(me
, "64bit attach address unsupported");
811 /* directly decode the address/space */
812 *attach_address
= address
->cells
[2];
813 switch (extract_ss(address
)) {
815 *attach_space
= hw_phb_config_space
;
818 *attach_space
= hw_phb_io_space
;
820 case ss_32bit_memory_code
:
821 case ss_64bit_memory_code
:
822 *attach_space
= hw_phb_memory_space
;
826 /* if non-relocatable finished */
827 if (extract_n(address
))
830 /* make memory and I/O addresses absolute */
831 if (*attach_space
== hw_phb_io_space
832 || *attach_space
== hw_phb_memory_space
) {
834 reg_property_spec assigned
;
835 if (extract_ss(address
) == ss_64bit_memory_code
)
836 device_error(me
, "64bit memory address not unsuported");
838 device_find_reg_array_property(client
, "assigned-addresses", reg_nr
,
841 if (!extract_n(&assigned
.address
)
842 || extract_rrrrrrrr(&assigned
.address
) == 0)
843 device_error(me
, "client %s has invalid assigned-address property",
844 device_path(client
));
845 if (extract_rrrrrrrr(address
) == extract_rrrrrrrr(&assigned
.address
)) {
846 /* corresponding base register */
847 if (extract_ss(address
) != extract_ss(&assigned
.address
))
848 device_error(me
, "client %s has conflicting types for base register 0x%lx",
850 (unsigned long)extract_rrrrrrrr(address
));
851 *attach_address
+= assigned
.address
.cells
[2];
855 device_error(me
, "client %s missing base address register 0x%lx in assigned-addresses property",
857 (unsigned long)extract_rrrrrrrr(address
));
865 hw_phb_size_to_attach_size(device
*me
,
866 const device_unit
*size
,
870 if (size
->nr_cells
!= 2)
871 device_error(me
, "size has incorrect number of cells");
872 if (size
->cells
[0] != 0)
873 device_error(me
, "64bit size unsupported");
874 *nr_bytes
= size
->cells
[1];
875 return size
->cells
[1];
879 static const phb_space
*
880 find_phb_space(hw_phb_device
*phb
,
885 /* find the space that matches the address */
886 for (space
= 0; space
< nr_hw_phb_spaces
; space
++) {
887 phb_space
*pci_space
= &phb
->space
[space
];
888 if (addr
>= pci_space
->parent_base
889 && (addr
+ nr_bytes
) <= (pci_space
->parent_base
+ pci_space
->size
)) {
898 map_phb_addr(const phb_space
*space
,
901 return addr
- space
->parent_base
+ space
->my_base
;
907 hw_phb_io_read_buffer(device
*me
,
915 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
916 const phb_space
*pci_space
= find_phb_space(phb
, addr
, nr_bytes
);
917 unsigned_word bus_addr
;
918 if (pci_space
== NULL
)
920 bus_addr
= map_phb_addr(pci_space
, addr
);
921 DTRACE(phb
, ("io read - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
922 space
, (unsigned long)addr
, pci_space
->name
, (unsigned long)bus_addr
,
924 return core_map_read_buffer(pci_space
->readable
,
925 dest
, bus_addr
, nr_bytes
);
930 hw_phb_io_write_buffer(device
*me
,
938 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
939 const phb_space
*pci_space
= find_phb_space(phb
, addr
, nr_bytes
);
940 unsigned_word bus_addr
;
941 if (pci_space
== NULL
)
943 bus_addr
= map_phb_addr(pci_space
, addr
);
944 DTRACE(phb
, ("io write - %d:0x%lx -> %s:0x%lx (%u bytes)\n",
945 space
, (unsigned long)addr
, pci_space
->name
, (unsigned long)bus_addr
,
947 return core_map_write_buffer(pci_space
->writeable
, source
,
953 hw_phb_dma_read_buffer(device
*me
,
959 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
960 const phb_space
*pci_space
;
962 if (space
!= hw_phb_memory_space
)
963 device_error(me
, "invalid dma address space %d", space
);
964 pci_space
= &phb
->space
[space
];
965 /* check out the address */
966 if ((addr
>= pci_space
->my_base
967 && addr
<= pci_space
->my_base
+ pci_space
->size
)
968 || (addr
+ nr_bytes
>= pci_space
->my_base
969 && addr
+ nr_bytes
<= pci_space
->my_base
+ pci_space
->size
))
970 device_error(me
, "Do not support DMA into own bus");
972 DTRACE(phb
, ("dma read - %s:0x%lx (%d bytes)\n",
973 pci_space
->name
, addr
, nr_bytes
));
974 return device_dma_read_buffer(device_parent(me
),
975 dest
, pci_space
->parent_space
,
981 hw_phb_dma_write_buffer(device
*me
,
986 int violate_read_only_section
)
988 hw_phb_device
*phb
= (hw_phb_device
*)device_data(me
);
989 const phb_space
*pci_space
;
991 if (space
!= hw_phb_memory_space
)
992 device_error(me
, "invalid dma address space %d", space
);
993 pci_space
= &phb
->space
[space
];
994 /* check out the address */
995 if ((addr
>= pci_space
->my_base
996 && addr
<= pci_space
->my_base
+ pci_space
->size
)
997 || (addr
+ nr_bytes
>= pci_space
->my_base
998 && addr
+ nr_bytes
<= pci_space
->my_base
+ pci_space
->size
))
999 device_error(me
, "Do not support DMA into own bus");
1001 DTRACE(phb
, ("dma write - %s:0x%lx (%d bytes)\n",
1002 pci_space
->name
, addr
, nr_bytes
));
1003 return device_dma_write_buffer(device_parent(me
),
1004 source
, pci_space
->parent_space
,
1006 violate_read_only_section
);
1010 static device_callbacks
const hw_phb_callbacks
= {
1011 { hw_phb_init_address
, },
1012 { hw_phb_attach_address
, },
1013 { hw_phb_io_read_buffer
, hw_phb_io_write_buffer
},
1014 { hw_phb_dma_read_buffer
, hw_phb_dma_write_buffer
},
1015 { NULL
, }, /* interrupt */
1016 { hw_phb_unit_decode
,
1018 hw_phb_address_to_attach_address
,
1019 hw_phb_size_to_attach_size
}
1024 hw_phb_create(const char *name
,
1025 const device_unit
*unit_address
,
1028 /* create the descriptor */
1029 hw_phb_device
*phb
= ZALLOC(hw_phb_device
);
1031 /* create the core maps now */
1032 hw_phb_spaces space_nr
;
1033 for (space_nr
= 0; space_nr
< nr_hw_phb_spaces
; space_nr
++) {
1034 phb_space
*pci_space
= &phb
->space
[space_nr
];
1035 pci_space
->map
= core_create();
1036 pci_space
->readable
= core_readable(pci_space
->map
);
1037 pci_space
->writeable
= core_writeable(pci_space
->map
);
1039 case hw_phb_memory_space
:
1040 pci_space
->name
= "memory";
1042 case hw_phb_io_space
:
1043 pci_space
->name
= "I/O";
1045 case hw_phb_config_space
:
1046 pci_space
->name
= "config";
1048 case hw_phb_special_space
:
1049 pci_space
->name
= "special";
1052 error ("internal error");
1061 const device_descriptor hw_phb_device_descriptor
[] = {
1062 { "phb", hw_phb_create
, &hw_phb_callbacks
},
1063 { "pci", NULL
, &hw_phb_callbacks
},
1067 #endif /* _HW_PHB_ */