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