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 #ifdef HAVE_STDLIB_H 31 #include <stdlib.h> 32 #endif 33 34 #include <ctype.h> 35 36 37 /* DEVICE 38 39 40 phb - PCI Host Bridge 41 42 43 DESCRIPTION 44 45 46 PHB implements a model of the PCI-host bridge described in the PPCP 47 document. 48 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 54 documentation. 55 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. 59 60 61 PROPERTIES 62 63 64 ranges = <my-phys-addr> <parent-phys-addr> <my-size> ... (required) 65 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). 71 72 73 #address-cells = 3 (required) 74 75 Number of cells used by an Open Firmware PCI address. This 76 property must be defined before specifying the <<ranges>> property. 77 78 79 #size-cells = 2 (required) 80 81 Number of cells used by an Open Firmware PCI size. This property 82 must be defined before specifying the <<ranges>> property. 83 84 85 EXAMPLES 86 87 88 Enable tracing: 89 90 | $ psim \ 91 | -t phb-device \ 92 93 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>>. 99 100 | -o '/#address-cells 1' \ 101 102 103 Create the PHB remembering to include the cell size properties: 104 105 | -o '/phb@0x80000000/#address-cells 3' \ 106 | -o '/phb@0x80000000/#size-cells 2' \ 107 108 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 113 at location zero: 114 115 | -o '/phb@0x80000000/ranges \ 116 | nm0,0,0,80000000 0x80000000 0x10000000 \ 117 | ni0,0,0,0 0xc0000000 0x10000' \ 118 119 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: 123 124 | -o '/phb@0x80000000/nvram@0/assigned-addresses \ 125 | nm0,0,10,80001000 4096 \ 126 | ni0,0,14,100 4096' 127 | -o '/phb@0x80000000/nvram@0/reg \ 128 | 0 0 \ 129 | i0,0,14,0 4096' 130 | -o '/phb@0x80000000/nvram@0/alternate-reg \ 131 | 0 0 \ 132 | m0,0,10,0 4096' 133 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. 138 139 Of the possible addresses, only the non-relocatable versions are 140 used when attaching the device to the bus. 141 142 143 BUGS 144 145 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. 149 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. 153 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. 157 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 162 fields. 163 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. 166 167 Support for aliased memory and I/O addresses is left as an exercise 168 for the reader. 169 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 174 the wrong answer. 175 176 Children of this node can only use the client callback interface 177 when attaching themselves to the <<phb>>. 178 179 180 REFERENCES 181 182 183 http://playground.sun.com/1275/home.html#OFDbusPCI 184 185 186 */ 187 188 189 typedef struct _phb_space { 190 core *map; 191 core_map *readable; 192 core_map *writeable; 193 unsigned_word parent_base; 194 int parent_space; 195 unsigned_word my_base; 196 int my_space; 197 unsigned size; 198 const char *name; 199 } phb_space; 200 201 typedef struct _hw_phb_device { 202 phb_space space[nr_hw_phb_spaces]; 203 } hw_phb_device; 204 205 206 static const char * 207 hw_phb_decode_name(hw_phb_decode level) 208 { 209 switch (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"; 214 } 215 } 216 217 218 static void 219 hw_phb_init_address(device *me) 220 { 221 hw_phb_device *phb = device_data(me); 222 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"); 228 229 /* (re) initialize each PCI space */ 230 { 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); 235 pci_space->size = 0; 236 } 237 } 238 239 /* decode each of the ranges properties entering the information 240 into the space table */ 241 { 242 range_property_spec range; 243 int ranges_entry; 244 245 for (ranges_entry = 0; 246 device_find_range_array_property(me, "ranges", ranges_entry, 247 &range); 248 ranges_entry++) { 249 int my_attach_space; 250 unsigned_word my_attach_address; 251 int parent_attach_space; 252 unsigned_word parent_attach_address; 253 unsigned size; 254 phb_space *pci_space; 255 /* convert the addresses into something meaningful */ 256 device_address_to_attach_address(me, &range.child_address, 257 &my_attach_space, 258 &my_attach_address, 259 me); 260 device_address_to_attach_address(device_parent(me), 261 &range.parent_address, 262 &parent_attach_space, 263 &parent_attach_address, 264 me); 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", 271 pci_space->name); 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), 278 attach_callback, 279 parent_attach_space, parent_attach_address, size, 280 access_read_write_exec, 281 me); 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, 285 pci_space->name, 286 (unsigned long)my_attach_address, 287 (unsigned long)size)); 288 } 289 290 if (ranges_entry == 0) { 291 device_error(me, "Missing or empty ranges property"); 292 } 293 294 } 295 296 } 297 298 static void 299 hw_phb_attach_address(device *me, 300 attach_type type, 301 int space, 302 unsigned_word addr, 303 unsigned nr_bytes, 304 access_type access, 305 device *client) /*callback/default*/ 306 { 307 hw_phb_device *phb = device_data(me); 308 phb_space *pci_space; 309 /* sanity checks */ 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", 324 device_path(client), 325 hw_phb_decode_name(type), 326 pci_space->name, 327 (unsigned long)addr, 328 (unsigned long)nr_bytes)); 329 core_attach(pci_space->map, 330 type, 331 space, 332 access, 333 addr, 334 nr_bytes, 335 client); 336 } 337 338 339 /* Extract/set various fields from a PCI unit address. 340 341 Note: only the least significant 32 bits of each cell is used. 342 343 Note: for PPC MSB is 0 while for PCI it is 31. */ 344 345 346 /* relocatable bit n */ 347 348 static unsigned 349 extract_n(const device_unit *address) 350 { 351 return EXTRACTED32(address->cells[0], 0, 0); 352 } 353 354 static void 355 set_n(device_unit *address) 356 { 357 BLIT32(address->cells[0], 0, 1); 358 } 359 360 361 /* prefetchable bit p */ 362 363 static unsigned 364 extract_p(const device_unit *address) 365 { 366 ASSERT(address->nr_cells == 3); 367 return EXTRACTED32(address->cells[0], 1, 1); 368 } 369 370 static void 371 set_p(device_unit *address) 372 { 373 BLIT32(address->cells[0], 1, 1); 374 } 375 376 377 /* aliased bit t */ 378 379 static unsigned 380 extract_t(const device_unit *address) 381 { 382 ASSERT(address->nr_cells == 3); 383 return EXTRACTED32(address->cells[0], 2, 2); 384 } 385 386 static void 387 set_t(device_unit *address) 388 { 389 BLIT32(address->cells[0], 2, 1); 390 } 391 392 393 /* space code ss */ 394 395 typedef enum { 396 ss_config_code = 0, 397 ss_io_code = 1, 398 ss_32bit_memory_code = 2, 399 ss_64bit_memory_code = 3, 400 } ss_type; 401 402 static ss_type 403 extract_ss(const device_unit *address) 404 { 405 ASSERT(address->nr_cells == 3); 406 return EXTRACTED32(address->cells[0], 6, 7); 407 } 408 409 static void 410 set_ss(device_unit *address, ss_type val) 411 { 412 MBLIT32(address->cells[0], 6, 7, val); 413 } 414 415 416 /* bus number bbbbbbbb */ 417 418 #if 0 419 static unsigned 420 extract_bbbbbbbb(const device_unit *address) 421 { 422 ASSERT(address->nr_cells == 3); 423 return EXTRACTED32(address->cells[0], 8, 15); 424 } 425 #endif 426 427 #if 0 428 static void 429 set_bbbbbbbb(device_unit *address, unsigned val) 430 { 431 MBLIT32(address->cells[0], 8, 15, val); 432 } 433 #endif 434 435 436 /* device number ddddd */ 437 438 static unsigned 439 extract_ddddd(const device_unit *address) 440 { 441 ASSERT(address->nr_cells == 3); 442 return EXTRACTED32(address->cells[0], 16, 20); 443 } 444 445 static void 446 set_ddddd(device_unit *address, unsigned val) 447 { 448 MBLIT32(address->cells[0], 16, 20, val); 449 } 450 451 452 /* function number fff */ 453 454 static unsigned 455 extract_fff(const device_unit *address) 456 { 457 ASSERT(address->nr_cells == 3); 458 return EXTRACTED32(address->cells[0], 21, 23); 459 } 460 461 static void 462 set_fff(device_unit *address, unsigned val) 463 { 464 MBLIT32(address->cells[0], 21, 23, val); 465 } 466 467 468 /* register number rrrrrrrr */ 469 470 static unsigned 471 extract_rrrrrrrr(const device_unit *address) 472 { 473 ASSERT(address->nr_cells == 3); 474 return EXTRACTED32(address->cells[0], 24, 31); 475 } 476 477 static void 478 set_rrrrrrrr(device_unit *address, unsigned val) 479 { 480 MBLIT32(address->cells[0], 24, 31, val); 481 } 482 483 484 /* MSW of 64bit address hh..hh */ 485 486 static unsigned 487 extract_hh_hh(const device_unit *address) 488 { 489 ASSERT(address->nr_cells == 3); 490 return address->cells[1]; 491 } 492 493 static void 494 set_hh_hh(device_unit *address, unsigned val) 495 { 496 address->cells[2] = val; 497 } 498 499 500 /* LSW of 64bit address ll..ll */ 501 502 static unsigned 503 extract_ll_ll(const device_unit *address) 504 { 505 ASSERT(address->nr_cells == 3); 506 return address->cells[2]; 507 } 508 509 static void 510 set_ll_ll(device_unit *address, unsigned val) 511 { 512 address->cells[2] = val; 513 } 514 515 516 /* Convert PCI textual bus address into a device unit */ 517 518 static int 519 hw_phb_unit_decode(device *me, 520 const char *unit, 521 device_unit *address) 522 { 523 char *end = NULL; 524 const char *chp = unit; 525 unsigned long val; 526 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)); 530 531 if (unit == NULL) 532 return 0; 533 534 address->nr_cells = 3; 535 536 if (isxdigit(*chp)) { 537 set_ss(address, ss_config_code); 538 } 539 else { 540 541 /* non-relocatable? */ 542 if (*chp == 'n') { 543 set_n(address); 544 chp++; 545 } 546 547 /* address-space? */ 548 if (*chp == 'i') { 549 set_ss(address, ss_io_code); 550 chp++; 551 } 552 else if (*chp == 'm') { 553 set_ss(address, ss_32bit_memory_code); 554 chp++; 555 } 556 else if (*chp == 'x') { 557 set_ss(address, ss_64bit_memory_code); 558 chp++; 559 } 560 else 561 device_error(me, "Problem parsing PCI address %s", unit); 562 563 /* possible alias */ 564 if (*chp == 't') { 565 if (extract_ss(address) == ss_64bit_memory_code) 566 device_error(me, "Invalid alias bit in PCI address %s", unit); 567 set_t(address); 568 chp++; 569 } 570 571 /* possible p */ 572 if (*chp == 'p') { 573 if (extract_ss(address) != ss_32bit_memory_code) 574 device_error(me, "Invalid prefetchable bit (p) in PCI address %s", 575 unit); 576 set_p(address); 577 chp++; 578 } 579 580 } 581 582 /* required DD */ 583 if (!isxdigit(*chp)) 584 device_error(me, "Missing device number in PCI address %s", unit); 585 val = strtoul(chp, &end, 16); 586 if (chp == end) 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", 590 val, unit); 591 set_ddddd(address, val); 592 chp = end; 593 594 /* For config space, the F is optional */ 595 if (extract_ss(address) == ss_config_code 596 && (isspace(*chp) || *chp == '\0')) 597 return chp - unit; 598 599 /* function number F */ 600 if (*chp != ',') 601 device_error(me, "Missing function number in PCI address %s", unit); 602 chp++; 603 val = strtoul(chp, &end, 10); 604 if (chp == end) 605 device_error(me, "Problem parsing function number in PCI address %s", 606 unit); 607 if ((val & 7) != val) 608 device_error(me, "Function number (%ld) out of range (0..7) in PCI address %s", 609 (long)val, unit); 610 set_fff(address, val); 611 chp = end; 612 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", 617 unit); 618 return chp - unit; 619 } 620 621 /* register number RR */ 622 if (*chp != ',') 623 device_error(me, "Missing register number in PCI address %s", unit); 624 chp++; 625 val = strtoul(chp, &end, 16); 626 if (chp == end) 627 device_error(me, "Problem parsing register number in PCI address %s", 628 unit); 629 switch (extract_ss(address)) { 630 case ss_io_code: 631 #if 0 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); 638 #endif 639 break; 640 case ss_32bit_memory_code: 641 #if 0 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", 648 val, unit); 649 #endif 650 break; 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", 657 val, unit); 658 case ss_config_code: 659 device_error(me, "internal error"); 660 } 661 if ((val & 0xff) != val) 662 device_error(me, "Register number (0x%lx) out of range (0..0xff) in PCI address %s", 663 val, unit); 664 set_rrrrrrrr(address, val); 665 chp = end; 666 667 /* address */ 668 if (*chp != ',') 669 device_error(me, "Missing address in PCI address %s", unit); 670 chp++; 671 switch (extract_ss(address)) { 672 case ss_io_code: 673 case ss_32bit_memory_code: 674 val = strtoul(chp, &end, 16); 675 if (chp == end) 676 device_error(me, "Problem parsing address in PCI address %s", unit); 677 switch (extract_ss(address)) { 678 case ss_io_code: 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", 682 val, unit); 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", 686 val, unit); 687 break; 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", 691 val, unit); 692 if (!extract_t(address) && (val & 0xffffffff) != val) 693 device_error(me, "32bit memory address (0x%lx) out of range in PCI address %s", 694 val, unit); 695 break; 696 case ss_64bit_memory_code: 697 case ss_config_code: 698 device_error(me, "internal error"); 699 } 700 set_ll_ll(address, val); 701 chp = end; 702 break; 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); 707 break; 708 case ss_config_code: 709 device_error(me, "internal error"); 710 break; 711 } 712 713 /* finished? */ 714 if (!isspace(*chp) && *chp != '\0') 715 device_error(me, "Problem parsing PCI address %s", unit); 716 717 return chp - unit; 718 } 719 720 721 /* Convert PCI device unit into its corresponding textual 722 representation */ 723 724 static int 725 hw_phb_unit_encode(device *me, 726 const device_unit *unit_address, 727 char *buf, 728 int sizeof_buf) 729 { 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 */ 740 sprintf(buf, "%x", 741 extract_ddddd(unit_address)); 742 } 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)); 752 } 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)); 763 } 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)); 775 } 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)); 786 } 787 else { 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]); 792 } 793 if (strlen(buf) > sizeof_buf) 794 error("buffer overflow"); 795 return strlen(buf); 796 } 797 798 799 static int 800 hw_phb_address_to_attach_address(device *me, 801 const device_unit *address, 802 int *attach_space, 803 unsigned_word *attach_address, 804 device *client) 805 { 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"); 810 811 /* directly decode the address/space */ 812 *attach_address = address->cells[2]; 813 switch (extract_ss(address)) { 814 case ss_config_code: 815 *attach_space = hw_phb_config_space; 816 break; 817 case ss_io_code: 818 *attach_space = hw_phb_io_space; 819 break; 820 case ss_32bit_memory_code: 821 case ss_64bit_memory_code: 822 *attach_space = hw_phb_memory_space; 823 break; 824 } 825 826 /* if non-relocatable finished */ 827 if (extract_n(address)) 828 return 1; 829 830 /* make memory and I/O addresses absolute */ 831 if (*attach_space == hw_phb_io_space 832 || *attach_space == hw_phb_memory_space) { 833 int reg_nr; 834 reg_property_spec assigned; 835 if (extract_ss(address) == ss_64bit_memory_code) 836 device_error(me, "64bit memory address not unsuported"); 837 for (reg_nr = 0; 838 device_find_reg_array_property(client, "assigned-addresses", reg_nr, 839 &assigned); 840 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", 849 device_path(client), 850 (unsigned long)extract_rrrrrrrr(address)); 851 *attach_address += assigned.address.cells[2]; 852 return 0; 853 } 854 } 855 device_error(me, "client %s missing base address register 0x%lx in assigned-addresses property", 856 device_path(client), 857 (unsigned long)extract_rrrrrrrr(address)); 858 } 859 860 return 0; 861 } 862 863 864 static int 865 hw_phb_size_to_attach_size(device *me, 866 const device_unit *size, 867 unsigned *nr_bytes, 868 device *client) 869 { 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]; 876 } 877 878 879 static const phb_space * 880 find_phb_space(hw_phb_device *phb, 881 unsigned_word addr, 882 unsigned nr_bytes) 883 { 884 hw_phb_spaces space; 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)) { 890 return pci_space; 891 } 892 } 893 return NULL; 894 } 895 896 897 static unsigned_word 898 map_phb_addr(const phb_space *space, 899 unsigned_word addr) 900 { 901 return addr - space->parent_base + space->my_base; 902 } 903 904 905 906 static unsigned 907 hw_phb_io_read_buffer(device *me, 908 void *dest, 909 int space, 910 unsigned_word addr, 911 unsigned nr_bytes, 912 cpu *processor, 913 unsigned_word cia) 914 { 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) 919 return 0; 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, 923 nr_bytes)); 924 return core_map_read_buffer(pci_space->readable, 925 dest, bus_addr, nr_bytes); 926 } 927 928 929 static unsigned 930 hw_phb_io_write_buffer(device *me, 931 const void *source, 932 int space, 933 unsigned_word addr, 934 unsigned nr_bytes, 935 cpu *processor, 936 unsigned_word cia) 937 { 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) 942 return 0; 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, 946 nr_bytes)); 947 return core_map_write_buffer(pci_space->writeable, source, 948 bus_addr, nr_bytes); 949 } 950 951 952 static unsigned 953 hw_phb_dma_read_buffer(device *me, 954 void *dest, 955 int space, 956 unsigned_word addr, 957 unsigned nr_bytes) 958 { 959 hw_phb_device *phb = (hw_phb_device*)device_data(me); 960 const phb_space *pci_space; 961 /* find the 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"); 971 /* do it */ 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, 976 addr, nr_bytes); 977 } 978 979 980 static unsigned 981 hw_phb_dma_write_buffer(device *me, 982 const void *source, 983 int space, 984 unsigned_word addr, 985 unsigned nr_bytes, 986 int violate_read_only_section) 987 { 988 hw_phb_device *phb = (hw_phb_device*)device_data(me); 989 const phb_space *pci_space; 990 /* find the 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"); 1000 /* do it */ 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, 1005 addr, nr_bytes, 1006 violate_read_only_section); 1007 } 1008 1009 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, 1017 hw_phb_unit_encode, 1018 hw_phb_address_to_attach_address, 1019 hw_phb_size_to_attach_size } 1020 }; 1021 1022 1023 static void * 1024 hw_phb_create(const char *name, 1025 const device_unit *unit_address, 1026 const char *args) 1027 { 1028 /* create the descriptor */ 1029 hw_phb_device *phb = ZALLOC(hw_phb_device); 1030 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); 1038 switch (space_nr) { 1039 case hw_phb_memory_space: 1040 pci_space->name = "memory"; 1041 break; 1042 case hw_phb_io_space: 1043 pci_space->name = "I/O"; 1044 break; 1045 case hw_phb_config_space: 1046 pci_space->name = "config"; 1047 break; 1048 case hw_phb_special_space: 1049 pci_space->name = "special"; 1050 break; 1051 default: 1052 error ("internal error"); 1053 break; 1054 } 1055 } 1056 1057 return phb; 1058 } 1059 1060 1061 const device_descriptor hw_phb_device_descriptor[] = { 1062 { "phb", hw_phb_create, &hw_phb_callbacks }, 1063 { "pci", NULL, &hw_phb_callbacks }, 1064 { NULL, }, 1065 }; 1066 1067 #endif /* _HW_PHB_ */ 1068