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