hw_phb.c revision 1.1.1.1
1/* 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 190typedef 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 202typedef struct _hw_phb_device { 203 phb_space space[nr_hw_phb_spaces]; 204} hw_phb_device; 205 206 207static const char * 208hw_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 219static void 220hw_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 299static void 300hw_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 349static unsigned 350extract_n(const device_unit *address) 351{ 352 return EXTRACTED32(address->cells[0], 0, 0); 353} 354 355static void 356set_n(device_unit *address) 357{ 358 BLIT32(address->cells[0], 0, 1); 359} 360 361 362/* prefetchable bit p */ 363 364static unsigned 365extract_p(const device_unit *address) 366{ 367 ASSERT(address->nr_cells == 3); 368 return EXTRACTED32(address->cells[0], 1, 1); 369} 370 371static void 372set_p(device_unit *address) 373{ 374 BLIT32(address->cells[0], 1, 1); 375} 376 377 378/* aliased bit t */ 379 380static unsigned 381extract_t(const device_unit *address) 382{ 383 ASSERT(address->nr_cells == 3); 384 return EXTRACTED32(address->cells[0], 2, 2); 385} 386 387static void 388set_t(device_unit *address) 389{ 390 BLIT32(address->cells[0], 2, 1); 391} 392 393 394/* space code ss */ 395 396typedef 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 403static ss_type 404extract_ss(const device_unit *address) 405{ 406 ASSERT(address->nr_cells == 3); 407 return EXTRACTED32(address->cells[0], 6, 7); 408} 409 410static void 411set_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 420static unsigned 421extract_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 429static void 430set_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 439static unsigned 440extract_ddddd(const device_unit *address) 441{ 442 ASSERT(address->nr_cells == 3); 443 return EXTRACTED32(address->cells[0], 16, 20); 444} 445 446static void 447set_ddddd(device_unit *address, unsigned val) 448{ 449 MBLIT32(address->cells[0], 16, 20, val); 450} 451 452 453/* function number fff */ 454 455static unsigned 456extract_fff(const device_unit *address) 457{ 458 ASSERT(address->nr_cells == 3); 459 return EXTRACTED32(address->cells[0], 21, 23); 460} 461 462static void 463set_fff(device_unit *address, unsigned val) 464{ 465 MBLIT32(address->cells[0], 21, 23, val); 466} 467 468 469/* register number rrrrrrrr */ 470 471static unsigned 472extract_rrrrrrrr(const device_unit *address) 473{ 474 ASSERT(address->nr_cells == 3); 475 return EXTRACTED32(address->cells[0], 24, 31); 476} 477 478static void 479set_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 487static unsigned 488extract_hh_hh(const device_unit *address) 489{ 490 ASSERT(address->nr_cells == 3); 491 return address->cells[1]; 492} 493 494static void 495set_hh_hh(device_unit *address, unsigned val) 496{ 497 address->cells[2] = val; 498} 499 500 501/* LSW of 64bit address ll..ll */ 502 503static unsigned 504extract_ll_ll(const device_unit *address) 505{ 506 ASSERT(address->nr_cells == 3); 507 return address->cells[2]; 508} 509 510static void 511set_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 519static int 520hw_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 725static int 726hw_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 800static int 801hw_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 865static int 866hw_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 880static const phb_space * 881find_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 898static unsigned_word 899map_phb_addr(const phb_space *space, 900 unsigned_word addr) 901{ 902 return addr - space->parent_base + space->my_base; 903} 904 905 906 907static unsigned 908hw_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 930static unsigned 931hw_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 953static unsigned 954hw_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 981static unsigned 982hw_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 1011static 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 1024static void * 1025hw_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 1062const 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_ */ 1069