Changeset 13189 in vbox for trunk/src/VBox/Devices/Bus
- Timestamp:
- Oct 11, 2008 12:36:11 PM (16 years ago)
- Location:
- trunk/src/VBox/Devices/Bus
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPCI.cpp
r12977 r13189 58 58 #include "../Builtins.h" 59 59 60 /******************************************************************************* 61 * Structures and Typedefs * 62 *******************************************************************************/ 63 /** 64 * PIIX3 ISA Bridge state. 65 */ 66 typedef struct PIIX3State 67 { 68 /** The PCI device of the bridge. */ 69 PCIDEVICE dev; 70 } PIIX3State, PIIX3, *PPIIX3; 71 72 /** 73 * PCI Bus instance. 74 */ 75 typedef struct PCIBus 76 { 77 /** Bus number. */ 78 int32_t iBus; 79 /** Start device number. */ 80 int32_t iDevSearch; 81 82 #if HC_ARCH_BITS == 64 83 uint32_t Alignment0[2]; 84 #endif 85 86 /** Array of PCI devices. */ 87 R3PTRTYPE(PPCIDEVICE) devices[256]; 88 89 /** R3 pointer to the device instance. */ 90 PPDMDEVINSR3 pDevInsR3; 91 /** Pointer to the PCI R3 helpers. */ 92 PCPDMPCIHLPR3 pPciHlpR3; 93 94 /** R0 pointer to the device instance. */ 95 PPDMDEVINSR0 pDevInsR0; 96 /** Pointer to the PCI R0 helpers. */ 97 PCPDMPCIHLPR0 pPciHlpR0; 98 99 /** RC pointer to the device instance. */ 100 PPDMDEVINSRC pDevInsRC; 101 /** Pointer to the PCI RC helpers. */ 102 PCPDMPCIHLPRC pPciHlpRC; 103 104 /** The PCI device for the PCI bridge. */ 105 PCIDEVICE PciDev; 106 107 } PCIBUS; 108 /** Pointer to a PCIBUS instance. */ 109 typedef PCIBUS *PPCIBUS; 110 typedef PCIBUS PCIBus; 111 112 /** @def PCI_IRQ_PINS 113 * Number of pins for interrupts (PIRQ#0...PIRQ#3) 114 */ 115 #define PCI_IRQ_PINS 4 116 117 /** @def PCI_APIC_IRQ_PINS 118 * Number of pins for interrupts if the APIC is used. 119 */ 120 #define PCI_APIC_IRQ_PINS 8 121 122 /** 123 * PCI Globals - This is the host-to-pci bridge and the root bus. 124 */ 125 typedef struct PCIGLOBALS 126 { 127 /** Irq levels for the four PCI Irqs. 128 * These count how many devices asserted 129 * the IRQ line. If greater 0 an IRQ is sent to the guest. 130 * If it drops to 0 the IRQ is deasserted. 131 */ 132 volatile uint32_t pci_irq_levels[PCI_IRQ_PINS]; 133 134 #if 1 /* Will be moved into the BIOS soon. */ 135 /** The next I/O port address which the PCI BIOS will use. */ 136 uint32_t pci_bios_io_addr; 137 /** The next MMIO address which the PCI BIOS will use. */ 138 uint32_t pci_bios_mem_addr; 139 /** Actual bus number. */ 140 uint8_t uBus; 141 #endif 142 143 /** I/O APIC usage flag */ 144 bool fUseIoApic; 145 /** I/O APIC irq levels */ 146 volatile uint32_t pci_apic_irq_levels[PCI_APIC_IRQ_PINS]; 147 /** ACPI IRQ level */ 148 uint32_t acpi_irq_level; 149 /** ACPI PIC IRQ */ 150 int acpi_irq; 151 /** Config register. */ 152 uint32_t uConfigReg; 153 154 /** R3 pointer to the device instance. */ 155 PPDMDEVINSR3 pDevInsR3; 156 /** R0 pointer to the device instance. */ 157 PPDMDEVINSR0 pDevInsR0; 158 /** RC pointer to the device instance. */ 159 PPDMDEVINSRC pDevInsRC; 160 161 #if HC_ARCH_BITS == 64 162 uint32_t Alignment0; 163 #endif 164 165 /** ISA bridge state. */ 166 PIIX3 PIIX3State; 167 /** PCI bus which is attached to the host-to-PCI bridge. */ 168 PCIBUS PciBus; 169 170 } PCIGLOBALS; 171 /** Pointer to per VM data. */ 172 typedef PCIGLOBALS *PPCIGLOBALS; 60 173 61 174 /******************************************************************************* 62 175 * Defined Constants And Macros * 63 176 *******************************************************************************/ 177 178 /** Converts a bus instance pointer to a device instance pointer. */ 179 #define PCIBUS_2_DEVINS(pPciBus) ((pPciBus)->CTX_SUFF(pDevIns)) 180 /** Converts a device instance pointer to a PCIGLOBALS pointer. */ 181 #define DEVINS_2_PCIGLOBALS(pDevIns) ((PPCIGLOBALS)(PDMINS_2_DATA(pDevIns, PPCIGLOBALS))) 182 /** Converts a device instance pointer to a PCIBUS pointer. */ 183 #define DEVINS_2_PCIBUS(pDevIns) ((PPCIBUS)(&PDMINS_2_DATA(pDevIns, PPCIGLOBALS)->PciBus)) 184 185 /** Converts a pointer to a PCI bus instance to a PCIGLOBALS pointer. 186 * @note This works only if the bus number is 0!!! 187 */ 188 #define PCIBUS_2_PCIGLOBALS(pPciBus) ( (PPCIGLOBALS)((uintptr_t)(pPciBus) - RT_OFFSETOF(PCIGLOBALS, PciBus)) ) 189 64 190 /** @def PCI_LOCK 65 191 * Acquires the PDM lock. This is a NOP if locking is disabled. */ … … 68 194 #define PCI_LOCK(pDevIns, rc) \ 69 195 do { \ 70 int rc2 = PDMINS_2_DATA(pDevIns, PCIBus *)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \196 int rc2 = DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnLock((pDevIns), rc); \ 71 197 if (rc2 != VINF_SUCCESS) \ 72 198 return rc2; \ 73 199 } while (0) 74 200 #define PCI_UNLOCK(pDevIns) \ 75 PDMINS_2_DATA(pDevIns, PCIBus *)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns) 76 77 78 /******************************************************************************* 79 * Structures and Typedefs * 80 *******************************************************************************/ 81 /** 82 * PIIX3 ISA Bridge state. 83 */ 84 typedef struct PIIX3State 85 { 86 /** The PCI device of the bridge. */ 87 PCIDEVICE dev; 88 } PIIX3State, PIIX3, *PPIIX3; 89 90 91 /** Maximum number of PCI devices. 92 * Defined like this to make interrupt handling simple. */ 93 #define PCI_DEVICES_MAX 64 94 /** Number of uint32_t entries needed make a bitmask of the interrupts. */ 95 #define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32) 96 97 /** 98 * PCI Globals. 99 * 100 * @remark 101 * These are currently put in the PCIBus structure since we've 102 * only got one PCI bus in the current VM configurations. This 103 * makes life somewhat simpler in RC. 104 */ 105 typedef struct PCIGLOBALS 106 { 107 /** Irq levels for the four PCI Irqs. */ 108 uint32_t pci_irq_levels[4][PCI_IRQ_WORDS]; 109 /** The base address for PCI assigned MMIO addresses. */ 110 RTGCPHYS32 pci_mem_base; 111 /** The next I/O port address which the PCI BIOS will use. */ 112 uint32_t pci_bios_io_addr; 113 /** The next MMIO address which the PCI BIOS will use. */ 114 uint32_t pci_bios_mem_addr; 115 /** I/O APIC usage flag */ 116 bool fUseIoApic; 117 /** I/O APIC irq levels */ 118 uint32_t pci_apic_irq_levels[8][PCI_IRQ_WORDS]; 119 /** ACPI IRQ level */ 120 uint32_t acpi_irq_level; 121 /** ACPI PIC IRQ */ 122 int acpi_irq; 123 } PCIGLOBALS; 124 /** Pointer to per VM data. */ 125 typedef PCIGLOBALS *PPCIGLOBALS; 126 127 128 /** 129 * PCI Bus instance. 130 */ 131 typedef struct PCIBus 132 { 133 /** IRQ index */ 134 uint32_t uIrqIndex; 135 /** Bus number. */ 136 int32_t iBus; 137 /** Start device number. */ 138 int32_t iDevSearch; 139 /** Config register. */ 140 uint32_t uConfigReg; 141 /** Array of PCI devices. */ 142 R3PTRTYPE(PPCIDEVICE) devices[256]; 143 144 /** R3 pointer to the device instance. */ 145 PPDMDEVINSR3 pDevInsR3; 146 /** Pointer to the PCI R3 helpers. */ 147 PCPDMPCIHLPR3 pPciHlpR3; 148 149 /** R0 pointer to the device instance. */ 150 PPDMDEVINSR0 pDevInsR0; 151 /** Pointer to the PCI R0 helpers. */ 152 PCPDMPCIHLPR0 pPciHlpR0; 153 154 /** RC pointer to the device instance. */ 155 PPDMDEVINSRC pDevInsRC; 156 /** Pointer to the PCI RC helpers. */ 157 PCPDMPCIHLPRC pPciHlpRC; 158 159 /** The PCI device for the PCI bridge. */ 160 PCIDEVICE PciDev; 161 /** ISA bridge state. */ 162 PIIX3 PIIX3State; 163 /** The global data. 164 * Since we've only got one bus at present, we put it here to keep things simple. */ 165 PCIGLOBALS Globals; 166 } PCIBUS; 167 /** Pointer to a PCIBUS instance. */ 168 typedef PCIBUS *PPCIBUS; 169 typedef PCIBUS PCIBus; 170 171 172 /** Converts a bus instance pointer to a device instance pointer. */ 173 #define PCIBUS_2_DEVINS(pPciBus) ((pPciBus)->CTX_SUFF(pDevIns)) 174 /** Converts a device instance pointer to a PCIGLOBALS pointer. */ 175 #define DEVINS_2_PCIGLOBALS(pDevIns) ((PPCIGLOBALS)(&PDMINS_2_DATA(pDevIns, PPCIBUS)->Globals)) 176 /** Converts a bus instance pointer to a PCIGLOBALS pointer. */ 177 #define PCIBUS_2_PCIGLOBALS(pPciBus) ((PPCIGLOBALS)(&pPciBus->Globals)) 178 201 DEVINS_2_PCIBUS(pDevIns)->CTX_SUFF(pPciHlp)->pfnUnlock(pDevIns) 202 203 /** @def VBOX_PCI_SAVED_STATE_VERSION 204 * Saved state version of the PCI bus device. 205 */ 206 #define VBOX_PCI_SAVED_STATE_VERSION 3 179 207 180 208 #ifndef VBOX_DEVICE_STRUCT_TESTCASE … … 185 213 186 214 PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel); 215 PDMBOTHCBDECL(void) pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel); 187 216 188 217 __END_DECLS 189 218 190 191 219 #define DEBUG_PCI 192 220 193 #define PCI_VENDOR_ID 0x00/* 16 bits */194 #define PCI_DEVICE_ID 0x02/* 16 bits */195 #define PCI_COMMAND 0x04/* 16 bits */196 #define PCI_COMMAND_IO 0x1/* Enable response in I/O space */197 #define PCI_COMMAND_MEMORY 0x2/* Enable response in Memory space */198 #define PCI_CLASS_DEVICE 199 #define PCI_INTERRUPT_LINE 0x3c/* 8 bits */200 #define PCI_INTERRUPT_PIN 0x3d/* 8 bits */201 #define PCI_MIN_GNT 0x3e/* 8 bits */202 #define PCI_MAX_LAT 0x3f/* 8 bits */221 #define PCI_VENDOR_ID 0x00 /* 16 bits */ 222 #define PCI_DEVICE_ID 0x02 /* 16 bits */ 223 #define PCI_COMMAND 0x04 /* 16 bits */ 224 #define PCI_COMMAND_IO 0x01 /* Enable response in I/O space */ 225 #define PCI_COMMAND_MEMORY 0x02 /* Enable response in Memory space */ 226 #define PCI_CLASS_DEVICE 0x0a /* Device class */ 227 #define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ 228 #define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ 229 #define PCI_MIN_GNT 0x3e /* 8 bits */ 230 #define PCI_MAX_LAT 0x3f /* 8 bits */ 203 231 204 232 #ifdef IN_RING3 205 233 206 static void pci_addr_writel(P CIBus *s, uint32_t addr, uint32_t val)207 { 208 s->uConfigReg = val;209 } 210 211 static uint32_t pci_addr_readl(P CIBus *s, uint32_t addr)212 { 213 return s->uConfigReg;234 static void pci_addr_writel(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val) 235 { 236 pGlobals->uConfigReg = val; 237 } 238 239 static uint32_t pci_addr_readl(PPCIGLOBALS pGlobals, uint32_t addr) 240 { 241 return pGlobals->uConfigReg; 214 242 } 215 243 216 244 static void pci_update_mappings(PCIDevice *d) 217 245 { 218 PPCIBUS pBus = d->Int.s. pBus;246 PPCIBUS pBus = d->Int.s.CTX_SUFF(pBus); 219 247 PCIIORegion *r; 220 248 int cmd, i; … … 282 310 } 283 311 } else { 284 RTGCPHYS GCPhysBase = r->addr + PCIBUS_2_PCIGLOBALS(pBus)->pci_mem_base;312 RTGCPHYS GCPhysBase = r->addr; 285 313 int rc; 286 314 if (pBus->pPciHlpR3->pfnIsMMIO2Base(pBus->pDevInsR3, d->pDevIns, GCPhysBase)) … … 299 327 if (r->addr != ~0U) { 300 328 int rc = r->map_func(d, i, 301 r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : PCIBUS_2_PCIGLOBALS(pBus)->pci_mem_base),329 r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : 0), 302 330 r->size, (PCIADDRESSSPACE)(r->type)); 303 331 AssertRC(rc); … … 411 439 } 412 440 #ifdef VBOX 413 441 /* status register: only clear bits by writing a '1' at the corresponding bit */ 414 442 if (addr == 0x06) 415 443 { … … 437 465 } 438 466 439 static void pci_data_write(P CIBus *s, uint32_t addr, uint32_t val, int len)467 static void pci_data_write(PPCIGLOBALS pGlobals, uint32_t addr, uint32_t val, int len) 440 468 { 441 469 PCIDevice *pci_dev; 442 int config_addr, iBus; 443 444 Log(("pci_data_write: addr=%08x val=%08x len=%d\n", s->uConfigReg, val, len)); 445 446 if (!(s->uConfigReg & (1 << 31))) { 470 uint8_t iBus, iDevice; 471 uint32_t config_addr; 472 473 Log(("pci_data_write: addr=%08x val=%08x len=%d\n", pGlobals->uConfigReg, val, len)); 474 475 if (!(pGlobals->uConfigReg & (1 << 31))) { 447 476 return; 448 477 } 449 if (( s->uConfigReg & 0x3) != 0) {478 if ((pGlobals->uConfigReg & 0x3) != 0) { 450 479 return; 451 480 } 452 iBus = (s->uConfigReg >> 16) & 0xff; 481 iBus = (pGlobals->uConfigReg >> 16) & 0xff; 482 iDevice = (pGlobals->uConfigReg >> 8) & 0xff; 483 config_addr = (pGlobals->uConfigReg & 0xfc) | (addr & 3); 453 484 if (iBus != 0) 454 return; 455 pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff]; 456 if (!pci_dev) 457 return; 458 config_addr = (s->uConfigReg & 0xfc) | (addr & 3); 459 Log(("pci_config_write: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len)); 460 pci_dev->Int.s.pfnConfigWrite(pci_dev, config_addr, val, len); 461 } 462 463 static uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len) 464 { 465 PCIDevice *pci_dev; 466 int config_addr, iBus; 485 { 486 /* 487 * Search for a fitting bridge. Becuase we don't support multi function devices at the moment 488 * we only search all devices with function 0 to speed things up. 489 * If no bridge is found the write will be ignored. 490 */ 491 for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8) 492 { 493 /* 494 * Examine secondary and subordinate bus number. 495 * If the target bus is in the range we pass the request on to the bridge. 496 */ 497 PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev]; 498 if (!pBridgeDevice) 499 continue; 500 if (!pBridgeDevice->Int.s.fPciToPciBridge) 501 continue; 502 503 if ( iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS] 504 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS]) 505 { 506 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite); 507 508 /* Start the journey... */ 509 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, val, len); 510 } 511 } 512 } 513 else 514 { 515 pci_dev = pGlobals->PciBus.devices[iDevice]; 516 if (!pci_dev) 517 return; 518 Log(("pci_config_write: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len)); 519 pci_dev->Int.s.pfnConfigWrite(pci_dev, config_addr, val, len); 520 } 521 } 522 523 static uint32_t pci_data_read(PPCIGLOBALS pGlobals, uint32_t addr, int len) 524 { 525 uint8_t iBus, iDevice; 526 uint32_t config_addr; 467 527 uint32_t val; 468 528 469 if (!( s->uConfigReg & (1 << 31)))529 if (!(pGlobals->uConfigReg & (1 << 31))) 470 530 goto fail; 471 if (( s->uConfigReg & 0x3) != 0)531 if ((pGlobals->uConfigReg & 0x3) != 0) 472 532 goto fail; 473 iBus = (s->uConfigReg >> 16) & 0xff; 533 iBus = (pGlobals->uConfigReg >> 16) & 0xff; 534 iDevice = (pGlobals->uConfigReg >> 8) & 0xff; 535 config_addr = (pGlobals->uConfigReg & 0xfc) | (addr & 3); 474 536 if (iBus != 0) 475 goto fail; 476 pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff]; 477 if (!pci_dev) { 478 fail: 479 switch(len) { 480 case 1: 481 val = 0xff; 482 break; 483 case 2: 484 val = 0xffff; 485 break; 486 default: 487 case 4: 488 val = 0xffffffff; 489 break; 490 } 491 goto the_end; 492 } 493 config_addr = (s->uConfigReg & 0xfc) | (addr & 3); 494 val = pci_dev->Int.s.pfnConfigRead(pci_dev, config_addr, len); 495 Log(("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len)); 537 { 538 /* 539 * Search for a fitting bridge. Becuase we don't support multi function devices at the moment 540 * we only search all devices with function 0 to speed things up. 541 * If no bridge is found the read will be ignored. 542 */ 543 for (uint32_t iDev = pGlobals->PciBus.iDevSearch; iDev < RT_ELEMENTS(pGlobals->PciBus.devices); iDev += 8) 544 { 545 /* 546 * Examine secondary and subordinate bus number. 547 * If the target bus is in the range we pass the request on to the bridge. 548 */ 549 PPCIDEVICE pBridgeDevice = pGlobals->PciBus.devices[iDev]; 550 if (!pBridgeDevice) 551 continue; 552 if (!pBridgeDevice->Int.s.fPciToPciBridge) 553 continue; 554 555 if ( iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS] 556 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS]) 557 { 558 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead); 559 560 val = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, config_addr, len); 561 } 562 } 563 } 564 else 565 { 566 PCIDevice *pci_dev; 567 568 pci_dev = pGlobals->PciBus.devices[iDevice]; 569 if (!pci_dev) { 570 fail: 571 switch(len) { 572 case 1: 573 val = 0xff; 574 break; 575 case 2: 576 val = 0xffff; 577 break; 578 default: 579 case 4: 580 val = 0xffffffff; 581 break; 582 } 583 goto the_end; 584 } 585 val = pci_dev->Int.s.pfnConfigRead(pci_dev, config_addr, len); 586 Log(("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len)); 587 } 588 496 589 the_end: 497 590 return val; … … 503 596 /* return the global irq number corresponding to a given device irq 504 597 pin. We could also use the bus number to have a more precise 505 mapping. */ 506 static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num) 598 mapping. 599 This is the implementation note described in the PCI spec chapter 2.2.6 */ 600 static inline int pci_slot_get_pirq(uint8_t uDevFn, int irq_num) 507 601 { 508 602 int slot_addend; 509 slot_addend = ( pci_dev->devfn >> 3) - 1;603 slot_addend = (uDevFn >> 3) - 1; 510 604 return (irq_num + slot_addend) & 3; 511 605 } 512 606 513 static inline int pci_slot_get_apic_pirq( PCIDevice *pci_dev, int irq_num)514 { 515 return (irq_num + ( pci_dev->devfn >> 3)) & 7;607 static inline int pci_slot_get_apic_pirq(uint8_t uDevFn, int irq_num) 608 { 609 return (irq_num + (uDevFn >> 3)) & 7; 516 610 } 517 611 518 612 static inline int get_pci_irq_apic_level(PPCIGLOBALS pGlobals, int irq_num) 519 613 { 520 int apic_level;521 apic_level = ((pGlobals->pci_apic_irq_levels[irq_num][0] | 522 pGlobals->pci_apic_irq_levels[irq_num][1]) != 0); 523 return apic_level; 524 } 525 526 static void apic_set_irq(PPCIBUS pBus, PCIDevice *pci_dev, int irq_num1, int level, int acpi_irq) 527 { 614 return (pGlobals->pci_apic_irq_levels[irq_num] != 0); 615 } 616 617 static void apic_set_irq(PPCIBUS pBus, uint8_t uDevFn, PCIDevice *pPciDev, int irq_num1, int iLevel, int acpi_irq) 618 { 619 /* This is only allowed to be called with a pointer to the host bus. */ 620 AssertMsg(pBus->iBus == 0, ("iBus=%u\n", pBus->iBus)); 621 528 622 if (acpi_irq == -1) { 529 int shift, apic_irq, apic_level; 530 uint32_t *p; 623 int apic_irq, apic_level; 531 624 PPCIGLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pBus); 532 int uIrqIndex = pci_dev->Int.s.iIrq; 533 int irq_num = pci_slot_get_apic_pirq(pci_dev, irq_num1); 534 535 p = &pGlobals->pci_apic_irq_levels[irq_num][uIrqIndex >> 5]; 536 shift = (uIrqIndex & 0x1f); 537 *p = (*p & ~(1 << shift)) | ((level & PDM_IRQ_LEVEL_HIGH) << shift); 625 int irq_num = pci_slot_get_apic_pirq(uDevFn, irq_num1); 626 627 if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_HIGH) 628 ASMAtomicIncU32(&pGlobals->pci_apic_irq_levels[irq_num]); 629 else if ((iLevel & PDM_IRQ_LEVEL_HIGH) == PDM_IRQ_LEVEL_LOW) 630 ASMAtomicDecU32(&pGlobals->pci_apic_irq_levels[irq_num]); 631 538 632 apic_irq = irq_num + 0x10; 539 633 apic_level = get_pci_irq_apic_level(pGlobals, irq_num); 540 634 Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d\n", 541 R3STRING(p ci_dev->name), irq_num1, level, apic_irq, apic_level, irq_num));635 R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num)); 542 636 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level); 543 637 544 if ((level & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) { 545 *p = (*p & ~(1 << shift)); 638 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) { 639 ASMAtomicDecU32(&pGlobals->pci_apic_irq_levels[irq_num]); 640 pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW; 546 641 apic_level = get_pci_irq_apic_level(pGlobals, irq_num); 547 642 Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d (flop)\n", 548 R3STRING(p ci_dev->name), irq_num1, level, apic_irq, apic_level, irq_num));643 R3STRING(pPciDev->name), irq_num1, iLevel, apic_irq, apic_level, irq_num)); 549 644 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), apic_irq, apic_level); 550 645 } 551 646 } else { 552 647 Log3(("apic_set_irq: %s: irq_num1=%d level=%d acpi_irq=%d\n", 553 R3STRING(p ci_dev->name), irq_num1, level, acpi_irq));554 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), acpi_irq, level);648 R3STRING(pPciDev->name), irq_num1, iLevel, acpi_irq)); 649 pBus->CTX_SUFF(pPciHlp)->pfnIoApicSetIrq(pBus->CTX_SUFF(pDevIns), acpi_irq, iLevel); 555 650 } 556 651 } … … 558 653 static inline int get_pci_irq_level(PPCIGLOBALS pGlobals, int irq_num) 559 654 { 560 int pic_level; 561 #if (PCI_IRQ_WORDS == 2) 562 pic_level = ((pGlobals->pci_irq_levels[irq_num][0] | 563 pGlobals->pci_irq_levels[irq_num][1]) != 0); 564 #else 565 { 566 int i; 655 return (pGlobals->pci_irq_levels[irq_num] != 0); 656 } 657 658 /** 659 * Set the IRQ for a PCI device on the host bus - shared by host bus and bridge. 660 * 661 * @param pDevIns Device instance of the host PCI Bus. 662 * @param uDevFn The device number on the host bus which will raise the IRQ 663 * @param pPciDev The PCI device structure which raised the interrupt. 664 * @param iIrq IRQ number to set. 665 * @param iLevel IRQ level. 666 * @remark uDevFn and pPciDev->devfn are not the same if the device is behind a bridge. 667 * In that case uDevFn will be the slot of the bridge which is needed to calculate the 668 * PIRQ value. 669 */ 670 static void pciSetIrqInternal(PPCIGLOBALS pGlobals, uint8_t uDevFn, PPCIDEVICE pPciDev, int iIrq, int iLevel) 671 { 672 PPCIBUS pBus = &pGlobals->PciBus; 673 uint8_t *pbCfg = pGlobals->PIIX3State.dev.config; 674 const bool fIsAcpiDevice = pPciDev->config[2] == 0x13 && pPciDev->config[3] == 0x71; 675 const bool fIsApicEnabled = pGlobals->fUseIoApic && pbCfg[0xde] == 0xbe && pbCfg[0xad] == 0xef; 676 int pic_irq, pic_level; 677 678 /* Check if the state changed. */ 679 if (pPciDev->Int.s.uIrqPinState != iLevel) 680 { 681 pPciDev->Int.s.uIrqPinState = (iLevel & PDM_IRQ_LEVEL_HIGH); 682 683 /* apic only */ 684 if (fIsApicEnabled) 685 { 686 if (fIsAcpiDevice) 687 /* 688 * ACPI needs special treatment since SCI is hardwired and 689 * should not be affected by PCI IRQ routing tables at the 690 * same time SCI IRQ is shared in PCI sense hence this 691 * kludge (i.e. we fetch the hardwired value from ACPIs 692 * PCI device configuration space). 693 */ 694 apic_set_irq(pBus, uDevFn, pPciDev, -1, iLevel, pPciDev->config[PCI_INTERRUPT_LINE]); 695 else 696 apic_set_irq(pBus, uDevFn, pPciDev, iIrq, iLevel, -1); 697 return; 698 } 699 700 if (fIsAcpiDevice) 701 { 702 /* As per above treat ACPI in a special way */ 703 pic_irq = pPciDev->config[PCI_INTERRUPT_LINE]; 704 pGlobals->acpi_irq = pic_irq; 705 pGlobals->acpi_irq_level = iLevel & PDM_IRQ_LEVEL_HIGH; 706 } 707 else 708 { 709 int irq_num; 710 irq_num = pci_slot_get_pirq(uDevFn, iIrq); 711 712 if (pPciDev->Int.s.uIrqPinState == PDM_IRQ_LEVEL_HIGH) 713 ASMAtomicIncU32(&pGlobals->pci_irq_levels[irq_num]); 714 else if (pPciDev->Int.s.uIrqPinState == PDM_IRQ_LEVEL_LOW) 715 ASMAtomicDecU32(&pGlobals->pci_irq_levels[irq_num]); 716 717 /* now we change the pic irq level according to the piix irq mappings */ 718 pic_irq = pbCfg[0x60 + irq_num]; 719 if (pic_irq >= 16) 720 { 721 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) 722 { 723 ASMAtomicDecU32(&pGlobals->pci_irq_levels[irq_num]); 724 pPciDev->Int.s.uIrqPinState = PDM_IRQ_LEVEL_LOW; 725 } 726 727 return; 728 } 729 } 730 731 /* the pic level is the logical OR of all the PCI irqs mapped to it */ 567 732 pic_level = 0; 568 for(i = 0; i < PCI_IRQ_WORDS; i++) { 569 if (pGlobals->pci_irq_levels[irq_num][i]) { 570 pic_level = 1; 571 break; 572 } 573 } 574 } 575 #endif 576 return pic_level; 577 } 578 579 /** 580 * Set the IRQ for a PCI device. 733 if (pic_irq == pbCfg[0x60]) 734 pic_level |= get_pci_irq_level(pGlobals, 0); 735 if (pic_irq == pbCfg[0x61]) 736 pic_level |= get_pci_irq_level(pGlobals, 1); 737 if (pic_irq == pbCfg[0x62]) 738 pic_level |= get_pci_irq_level(pGlobals, 2); 739 if (pic_irq == pbCfg[0x63]) 740 pic_level |= get_pci_irq_level(pGlobals, 3); 741 if (pic_irq == pGlobals->acpi_irq) 742 pic_level |= pGlobals->acpi_irq_level; 743 744 Log3(("pciSetIrq: %s: iLevel=%d iIrq=%d pic_irq=%d pic_level=%d\n", 745 R3STRING(pPciDev->name), iLevel, iIrq, pic_irq, pic_level)); 746 pBus->CTX_SUFF(pPciHlp)->pfnIsaSetIrq(pBus->CTX_SUFF(pDevIns), pic_irq, pic_level); 747 748 /** @todo optimize pci irq flip-flop some rainy day. */ 749 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) 750 pciSetIrqInternal(pGlobals, uDevFn, pPciDev, iIrq, PDM_IRQ_LEVEL_LOW); 751 } 752 } 753 754 /** 755 * Set the IRQ for a PCI device on the host bus. 581 756 * 582 757 * @param pDevIns Device instance of the PCI Bus. … … 587 762 PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel) 588 763 { 589 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 590 PPCIGLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pBus); 591 uint8_t *pbCfg = pBus->PIIX3State.dev.config; 592 const bool fIsAcpiDevice = pPciDev->config[2] == 0x13 && pPciDev->config[3] == 0x71; 593 const bool fIsApicEnabled = pGlobals->fUseIoApic && pbCfg[0xde] == 0xbe && pbCfg[0xad] == 0xef; 594 int pic_irq, pic_level; 595 uint32_t *p; 596 597 /* apic only */ 598 if (fIsApicEnabled) 599 { 600 if (fIsAcpiDevice) 601 /* 602 * ACPI needs special treatment since SCI is hardwired and 603 * should not be affected by PCI IRQ routing tables at the 604 * same time SCI IRQ is shared in PCI sense hence this 605 * kludge (i.e. we fetch the hardwired value from ACPIs 606 * PCI device configuration space). 607 */ 608 apic_set_irq(pBus, pPciDev, -1, iLevel, pPciDev->config[0x3c]); 609 else 610 apic_set_irq(pBus, pPciDev, iIrq, iLevel, -1); 611 return; 612 } 613 614 if (fIsAcpiDevice) 615 { 616 /* As per above treat ACPI in a special way */ 617 pic_irq = pPciDev->config[0x3c]; 618 pGlobals->acpi_irq = pic_irq; 619 pGlobals->acpi_irq_level = iLevel & PDM_IRQ_LEVEL_HIGH; 620 } 621 else 622 { 623 int shift, irq_num, uIrqIndex; 624 irq_num = pci_slot_get_pirq(pPciDev, iIrq); 625 uIrqIndex = pPciDev->Int.s.iIrq; 626 p = &pGlobals->pci_irq_levels[irq_num][uIrqIndex >> 5]; 627 shift = (uIrqIndex & 0x1f); 628 *p = (*p & ~(1 << shift)) | ((iLevel & PDM_IRQ_LEVEL_HIGH) << shift); 629 630 /* now we change the pic irq level according to the piix irq mappings */ 631 pic_irq = pbCfg[0x60 + irq_num]; 632 if (pic_irq >= 16) 633 { 634 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) 635 *p = (*p & ~(1 << shift)); 636 return; 637 } 638 } 639 640 /* the pic level is the logical OR of all the PCI irqs mapped to it */ 641 pic_level = 0; 642 if (pic_irq == pbCfg[0x60]) 643 pic_level |= get_pci_irq_level(pGlobals, 0); 644 if (pic_irq == pbCfg[0x61]) 645 pic_level |= get_pci_irq_level(pGlobals, 1); 646 if (pic_irq == pbCfg[0x62]) 647 pic_level |= get_pci_irq_level(pGlobals, 2); 648 if (pic_irq == pbCfg[0x63]) 649 pic_level |= get_pci_irq_level(pGlobals, 3); 650 if (pic_irq == pGlobals->acpi_irq) 651 pic_level |= pGlobals->acpi_irq_level; 652 653 Log3(("piix3_set_irq: %s: iLevel=%d iIrq=%d pic_irq=%d pic_level=%d\n", 654 R3STRING(pPciDev->name), iLevel, iIrq, pic_irq, pic_level)); 655 pBus->CTX_SUFF(pPciHlp)->pfnIsaSetIrq(pBus->CTX_SUFF(pDevIns), pic_irq, pic_level); 656 657 /** @todo optimize pci irq flip-flop some rainy day. */ 658 if ((iLevel & PDM_IRQ_LEVEL_FLIP_FLOP) == PDM_IRQ_LEVEL_FLIP_FLOP) 659 pciSetIrq(pDevIns, pPciDev, iIrq, PDM_IRQ_LEVEL_LOW); 764 pciSetIrqInternal(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), pPciDev->devfn, pPciDev, iIrq, iLevel); 660 765 } 661 766 … … 697 802 } 698 803 699 static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val) 700 { 701 PCIBus *s = d->Int.s.pBus; 702 s->uConfigReg = 0x80000000 | (s->iBus << 16) | 703 (d->devfn << 8) | addr; 704 pci_data_write(s, 0, val, 4); 705 } 706 707 static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val) 708 { 709 PCIBus *s = d->Int.s.pBus; 710 s->uConfigReg = 0x80000000 | (s->iBus << 16) | 711 (d->devfn << 8) | (addr & ~3); 712 pci_data_write(s, addr & 3, val, 2); 713 } 714 715 static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val) 716 { 717 PCIBus *s = d->Int.s.pBus; 718 s->uConfigReg = 0x80000000 | (s->iBus << 16) | 719 (d->devfn << 8) | (addr & ~3); 720 pci_data_write(s, addr & 3, val, 1); 721 } 722 723 static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr) 724 { 725 PCIBus *s = d->Int.s.pBus; 726 s->uConfigReg = 0x80000000 | (s->iBus << 16) | 727 (d->devfn << 8) | (addr & ~3); 728 return pci_data_read(s, addr & 3, 2); 729 } 730 731 static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr) 732 { 733 PCIBus *s = d->Int.s.pBus; 734 s->uConfigReg = 0x80000000 | (s->iBus << 16) | 735 (d->devfn << 8) | (addr & ~3); 736 return pci_data_read(s, addr & 3, 1); 804 static void pci_config_writel(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val) 805 { 806 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 807 (uDevFn << 8) | addr; 808 pci_data_write(pGlobals, 0, val, 4); 809 } 810 811 static void pci_config_writew(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val) 812 { 813 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 814 (uDevFn << 8) | (addr & ~3); 815 pci_data_write(pGlobals, addr & 3, val, 2); 816 } 817 818 static void pci_config_writeb(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr, uint32_t val) 819 { 820 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 821 (uDevFn << 8) | (addr & ~3); 822 pci_data_write(pGlobals, addr & 3, val, 1); 823 } 824 825 static uint32_t pci_config_readl(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr) 826 { 827 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 828 (uDevFn << 8) | addr; 829 return pci_data_read(pGlobals, 0, 4); 830 } 831 832 static uint32_t pci_config_readw(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr) 833 { 834 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 835 (uDevFn << 8) | (addr & ~3); 836 return pci_data_read(pGlobals, addr & 3, 2); 837 } 838 839 static uint32_t pci_config_readb(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint32_t addr) 840 { 841 pGlobals->uConfigReg = 0x80000000 | (uBus << 16) | 842 (uDevFn << 8) | (addr & ~3); 843 return pci_data_read(pGlobals, addr & 3, 1); 737 844 } 738 845 … … 740 847 static const uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; /* bird: added const */ 741 848 742 static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr) 743 { 744 PCIIORegion *r; 849 static void pci_set_io_region_addr(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, int region_num, uint32_t addr) 850 { 745 851 uint16_t cmd; 746 852 uint32_t ofs; 747 853 748 if ( region_num == PCI_ROM_SLOT ) {854 if ( region_num == PCI_ROM_SLOT ) 749 855 ofs = 0x30; 750 }else{856 else 751 857 ofs = 0x10 + region_num * 4; 752 } 753 754 pci_config_writel(d, ofs, addr);755 r = &d->Int.s.aIORegions[region_num];756 757 /* enable memory mappings*/758 cmd = pci_config_readw( d, PCI_COMMAND);858 859 /* Read memory type first. */ 860 uint8_t uRessourceType = pci_config_readb(pGlobals, uBus, uDevFn, ofs); 861 AssertMsg(uRessourceType != 0xff, ("Device non existent\n")); 862 863 /* Read command register. */ 864 cmd = pci_config_readw(pGlobals, uBus, uDevFn, PCI_COMMAND); 759 865 if ( region_num == PCI_ROM_SLOT ) 760 866 cmd |= 2; 761 else if (r->type & PCI_ADDRESS_SPACE_IO) 762 cmd |= 1; 763 else 764 cmd |= 2; 765 pci_config_writew(d, PCI_COMMAND, cmd); 766 } 767 768 static void pci_bios_init_device(PCIDevice *d) 769 { 770 int devclass; 867 else if ((uRessourceType & 0x01) == 1) /* Test if region is I/O space. */ 868 cmd |= 1; /* Enable I/O space access. */ 869 else /* The region is MMIO. */ 870 cmd |= 2; /* Enable MMIO access. */ 871 872 /* Write address of the device. */ 873 pci_config_writel(pGlobals, uBus, uDevFn, ofs, addr); 874 875 /* enable memory mappings */ 876 pci_config_writew(pGlobals, uBus, uDevFn, PCI_COMMAND, cmd); 877 } 878 879 static void pci_bios_init_device(PPCIGLOBALS pGlobals, uint8_t uBus, uint8_t uDevFn, uint8_t cBridgeDepth, uint8_t *paBridgePositions) 880 { 771 881 PCIIORegion *r; 772 882 uint32_t *paddr; 773 int i, pin, pic_irq, vendor_id, device_id; 774 775 devclass = pci_config_readw(d, PCI_CLASS_DEVICE); 776 vendor_id = pci_config_readw(d, PCI_VENDOR_ID); 777 device_id = pci_config_readw(d, PCI_DEVICE_ID); 778 switch(devclass) 779 { 780 case 0x0101: 781 if (vendor_id == 0x8086 && 782 (device_id == 0x7010 || device_id == 0x7111)) { 783 /* PIIX3 or PIIX4 IDE */ 784 pci_config_writew(d, 0x40, 0x8000); /* enable IDE0 */ 785 pci_config_writew(d, 0x42, 0x8000); /* enable IDE1 */ 786 goto default_map; 787 } else { 788 /* IDE: we map it as in ISA mode */ 789 pci_set_io_region_addr(d, 0, 0x1f0); 790 pci_set_io_region_addr(d, 1, 0x3f4); 791 pci_set_io_region_addr(d, 2, 0x170); 792 pci_set_io_region_addr(d, 3, 0x374); 793 } 794 break; 795 case 0x0300: 796 if (vendor_id != 0x80ee) 797 goto default_map; 798 /* VGA: map frame buffer to default Bochs VBE address */ 799 pci_set_io_region_addr(d, 0, 0xE0000000); 800 break; 801 case 0x0800: 802 /* PIC */ 803 vendor_id = pci_config_readw(d, PCI_VENDOR_ID); 804 device_id = pci_config_readw(d, PCI_DEVICE_ID); 805 if (vendor_id == 0x1014) { 806 /* IBM */ 807 if (device_id == 0x0046 || device_id == 0xFFFF) { 808 /* MPIC & MPIC2 */ 809 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000); 883 int i, pin, pic_irq; 884 uint16_t devclass, vendor_id, device_id; 885 886 devclass = pci_config_readw(pGlobals, uBus, uDevFn, PCI_CLASS_DEVICE); 887 vendor_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_VENDOR_ID); 888 device_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_DEVICE_ID); 889 890 /* Check if device is present. */ 891 if (vendor_id != 0xffff) 892 { 893 switch(devclass) 894 { 895 case 0x0101: 896 if ( (vendor_id == 0x8086) 897 && (device_id == 0x7010 || device_id == 0x7111)) 898 { 899 /* PIIX3 or PIIX4 IDE */ 900 pci_config_writew(pGlobals, uBus, uDevFn, 0x40, 0x8000); /* enable IDE0 */ 901 pci_config_writew(pGlobals, uBus, uDevFn, 0x42, 0x8000); /* enable IDE1 */ 902 goto default_map; 903 } 904 else 905 { 906 /* IDE: we map it as in ISA mode */ 907 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x1f0); 908 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 1, 0x3f4); 909 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 2, 0x170); 910 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 3, 0x374); 911 } 912 break; 913 case 0x0300: 914 if (vendor_id != 0x80ee) 915 goto default_map; 916 /* VGA: map frame buffer to default Bochs VBE address */ 917 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0xE0000000); 918 break; 919 case 0x0800: 920 /* PIC */ 921 vendor_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_VENDOR_ID); 922 device_id = pci_config_readw(pGlobals, uBus, uDevFn, PCI_DEVICE_ID); 923 if (vendor_id == 0x1014) 924 { 925 /* IBM */ 926 if (device_id == 0x0046 || device_id == 0xFFFF) 927 { 928 /* MPIC & MPIC2 */ 929 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x80800000 + 0x00040000); 930 } 931 } 932 break; 933 case 0xff00: 934 if ( (vendor_id == 0x0106b) 935 && (device_id == 0x0017 || device_id == 0x0022)) 936 { 937 /* macio bridge */ 938 pci_set_io_region_addr(pGlobals, uBus, uDevFn, 0, 0x80800000); 939 } 940 break; 941 case 0x0604: 942 { 943 /* Init PCI-to-PCI bridge. */ 944 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_PRIMARY_BUS, uBus); 945 946 AssertMsg(pGlobals->uBus < 255, ("Too many bridges on the bus\n")); 947 pGlobals->uBus++; 948 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SECONDARY_BUS, pGlobals->uBus); 949 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, 0xff); /* Temporary until we know how many other bridges are behind this one. */ 950 951 /* Add position of this bridge into the array. */ 952 paBridgePositions[cBridgeDepth+1] = (uDevFn >> 3); 953 954 /* 955 * The I/O range for the bridge must be aligned to a 4KB boundary. 956 * This does not change anything really as the access to the device is not going 957 * through the bridge but we want to be compliant to the spec. 958 */ 959 if ((pGlobals->pci_bios_io_addr % 4096) != 0) 960 pGlobals->pci_bios_io_addr = RT_ALIGN_32(pGlobals->pci_bios_io_addr, 4*1024); 961 Log(("%s: Aligned I/O start address. New address %#x\n", __FUNCTION__, pGlobals->pci_bios_io_addr)); 962 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_IO_BASE, (pGlobals->pci_bios_io_addr >> 8) & 0xf0); 963 964 /* The MMIO range for the bridge must be aligned to a 1MB boundary. */ 965 if ((pGlobals->pci_bios_mem_addr % (1024 * 1024)) != 0) 966 pGlobals->pci_bios_mem_addr = RT_ALIGN_32(pGlobals->pci_bios_mem_addr, 1024*1024); 967 Log(("%s: Aligned MMIO start address. New address %#x\n", __FUNCTION__, pGlobals->pci_bios_mem_addr)); 968 pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_BASE, (pGlobals->pci_bios_mem_addr >> 16) & UINT32_C(0xffff0)); 969 970 /* Save values to compare later to. */ 971 uint32_t u32IoAddressBase = pGlobals->pci_bios_io_addr; 972 uint32_t u32MMIOAddressBase = pGlobals->pci_bios_mem_addr; 973 974 /* Init devices behind the bridge and possibly other bridges as well. */ 975 for (int i = 0; i <= 255; i++) 976 pci_bios_init_device(pGlobals, uBus + 1, i, cBridgeDepth + 1, paBridgePositions); 977 978 /* The number of bridges behind the this one is now available. */ 979 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_SUBORDINATE_BUS, pGlobals->uBus); 980 981 /* 982 * Set I/O limit register. If there is no device with I/O space behind the bridge 983 * we set a lower value than in the base register. 984 * The result with a real bridge is that no I/O transactions are passed to the secondary 985 * interface. Again this doesn't really matter here but we want to be compliant to the spec. 986 */ 987 if ((u32IoAddressBase != pGlobals->pci_bios_io_addr) && ((pGlobals->pci_bios_io_addr % 4096) != 0)) 988 { 989 /* The upper boundary must be one byte less than a 4KB boundary. */ 990 pGlobals->pci_bios_io_addr = RT_ALIGN_32(pGlobals->pci_bios_io_addr, 4*1024); 991 } 992 pci_config_writeb(pGlobals, uBus, uDevFn, VBOX_PCI_IO_LIMIT, ((pGlobals->pci_bios_io_addr >> 8) & 0xf0) - 1); 993 994 /* Same with the MMIO limit register but with 1MB boundary here. */ 995 if ((u32MMIOAddressBase != pGlobals->pci_bios_mem_addr) && ((pGlobals->pci_bios_mem_addr % (1024 * 1024)) != 0)) 996 { 997 /* The upper boundary must be one byte less than a 1MB boundary. */ 998 pGlobals->pci_bios_mem_addr = RT_ALIGN_32(pGlobals->pci_bios_mem_addr, 1024*1024); 999 } 1000 pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_MEMORY_LIMIT, ((pGlobals->pci_bios_mem_addr >> 16) & UINT32_C(0xfff0)) - 1); 1001 1002 /* 1003 * Set the prefetch base and limit registers. We currently have no device with a prefetchable region 1004 * which may be behind a bridge. Thatswhy it is unconditionally disabled here atm by writing a higher value into 1005 * the base register than in the limit register. 1006 */ 1007 pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_BASE, 0xfff0); 1008 pci_config_writew(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_LIMIT, 0x0); 1009 pci_config_writel(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, 0x00); 1010 pci_config_writel(pGlobals, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, 0x00); 1011 break; 810 1012 } 811 } 812 break; 813 case 0xff00: 814 if (vendor_id == 0x0106b && 815 (device_id == 0x0017 || device_id == 0x0022)) { 816 /* macio bridge */ 817 pci_set_io_region_addr(d, 0, 0x80800000); 818 } 819 break; 820 default: 821 default_map: 822 /* default memory mappings */ 823 for(i = 0; i < PCI_NUM_REGIONS; i++) { 824 r = &d->Int.s.aIORegions[i]; 825 826 if (r->size) { 827 if (r->type & PCI_ADDRESS_SPACE_IO) 828 paddr = &PCIBUS_2_PCIGLOBALS(d->Int.s.pBus)->pci_bios_io_addr; 829 else 830 paddr = &PCIBUS_2_PCIGLOBALS(d->Int.s.pBus)->pci_bios_mem_addr; 831 *paddr = (*paddr + r->size - 1) & ~(r->size - 1); 832 pci_set_io_region_addr(d, i, *paddr); 833 *paddr += r->size; 1013 default: 1014 default_map: 1015 { 1016 /* default memory mappings */ 1017 /* 1018 * PCI_NUM_REGIONS is 7 bcause of the rom region but there are only 6 base address register defined by the PCi spec. 1019 * Leaving only PCI_NUM_REGIONS would cause reading another and enabling a memory region which does not exist. 1020 */ 1021 for(i = 0; i < (PCI_NUM_REGIONS-1); i++) 1022 { 1023 uint32_t u32Size; 1024 uint8_t u8RessourceType; 1025 uint32_t u32Address = 0x10 + i * 4; 1026 1027 /* Calculate size. */ 1028 u8RessourceType = pci_config_readb(pGlobals, uBus, uDevFn, u32Address); 1029 pci_config_writel(pGlobals, uBus, uDevFn, u32Address, UINT32_C(0xffffffff)); 1030 u32Size = pci_config_readl(pGlobals, uBus, uDevFn, u32Address); 1031 /* Clear ressource information depending on ressource type. */ 1032 if ((u8RessourceType & 0x01) == 1) /* I/O */ 1033 u32Size &= ~(0x01); 1034 else /* MMIO */ 1035 u32Size &= ~(0x0f); 1036 1037 /* 1038 * Invert all bits and add 1 to get size of the region. 1039 * (From PCI implementation note) 1040 */ 1041 if (((u8RessourceType & 0x01) == 1) && (u32Size & UINT32_C(0xffff0000)) == 0) 1042 u32Size = (~(u32Size | UINT32_C(0xffff0000))) + 1; 1043 else 1044 u32Size = (~u32Size) + 1; 1045 1046 Log(("%s: Size of region %u for device %d on bus %d is %u\n", __FUNCTION__, i, uDevFn, uBus, u32Size)); 1047 1048 if (u32Size) 1049 { 1050 if ((u8RessourceType & 0x01) == 1) 1051 paddr = &pGlobals->pci_bios_io_addr; 1052 else 1053 paddr = &pGlobals->pci_bios_mem_addr; 1054 *paddr = (*paddr + u32Size - 1) & ~(u32Size - 1); 1055 Log(("%s: Start address of %s region %u is %#x\n", __FUNCTION__, ((u8RessourceType & 0x01) == 1 ? "I/O" : "MMIO"), i, *paddr)); 1056 pci_set_io_region_addr(pGlobals, uBus, uDevFn, i, *paddr); 1057 *paddr += u32Size; 1058 Log(("%s: New address is %#x\n", __FUNCTION__, *paddr)); 1059 } 1060 } 1061 break; 834 1062 } 835 1063 } 836 break; 837 } 838 839 /* map the interrupt */ 840 pin = pci_config_readb(d, PCI_INTERRUPT_PIN); 841 if (pin != 0) { 842 pin = pci_slot_get_pirq(d, pin - 1); 843 pic_irq = pci_irqs[pin]; 844 pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq); 1064 1065 /* map the interrupt */ 1066 pin = pci_config_readb(pGlobals, uBus, uDevFn, PCI_INTERRUPT_PIN); 1067 if (pin != 0) 1068 { 1069 uint8_t uBridgeDevFn = uDevFn; 1070 pin--; 1071 1072 /* We need to go up to the host bus to see which irq this device will assert there. */ 1073 while (cBridgeDepth != 0) 1074 { 1075 /* Get the pin the device would assert on the bridge. */ 1076 pin = ((uBridgeDevFn >> 3) + pin) & 3; 1077 uBridgeDevFn = paBridgePositions[cBridgeDepth]; 1078 cBridgeDepth--; 1079 } 1080 1081 pin = pci_slot_get_pirq(uDevFn, pin); 1082 pic_irq = pci_irqs[pin]; 1083 pci_config_writeb(pGlobals, uBus, uDevFn, PCI_INTERRUPT_LINE, pic_irq); 1084 } 845 1085 } 846 1086 } … … 866 1106 { 867 1107 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE); 868 pci_addr_writel(PDMINS_2_DATA(pDevIns, P CIBus *), Port, u32);1108 pci_addr_writel(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32); 869 1109 PCI_UNLOCK(pDevIns); 870 1110 } … … 891 1131 { 892 1132 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ); 893 *pu32 = pci_addr_readl(PDMINS_2_DATA(pDevIns, P CIBus *), Port);1133 *pu32 = pci_addr_readl(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port); 894 1134 PCI_UNLOCK(pDevIns); 895 1135 Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32)); … … 921 1161 { 922 1162 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE); 923 pci_data_write(PDMINS_2_DATA(pDevIns, P CIBus *), Port, u32, cb);1163 pci_data_write(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, u32, cb); 924 1164 PCI_UNLOCK(pDevIns); 925 1165 } … … 947 1187 { 948 1188 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ); 949 *pu32 = pci_data_read(PDMINS_2_DATA(pDevIns, P CIBus *), Port, cb);1189 *pu32 = pci_data_read(PDMINS_2_DATA(pDevIns, PPCIGLOBALS), Port, cb); 950 1190 PCI_UNLOCK(pDevIns); 951 1191 Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x\n", Port, cb, *pu32)); … … 996 1236 { 997 1237 uint32_t i; 998 PPCI BUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);999 PPCI GLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pThis);1238 PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS); 1239 PPCIBUS pBus = &pThis->PciBus; 1000 1240 1001 1241 /* … … 1003 1243 */ 1004 1244 SSMR3PutU32(pSSMHandle, pThis->uConfigReg); 1005 SSMR3PutBool(pSSMHandle, pGlobals->fUseIoApic); 1245 SSMR3PutBool(pSSMHandle, pThis->fUseIoApic); 1246 /* 1247 * Save IRQ states. 1248 */ 1249 for (uint8_t i = 0; i < PCI_IRQ_PINS; i++) 1250 SSMR3PutU32(pSSMHandle, pThis->pci_irq_levels[i]); 1251 for (uint8_t i = 0; i < PCI_APIC_IRQ_PINS; i++) 1252 SSMR3PutU32(pSSMHandle, pThis->pci_apic_irq_levels[i]); 1253 1254 SSMR3PutU32(pSSMHandle, pThis->acpi_irq_level); 1255 SSMR3PutS32(pSSMHandle, pThis->acpi_irq); 1256 1006 1257 SSMR3PutU32(pSSMHandle, ~0); /* separator */ 1007 1258 … … 1009 1260 * Iterate all the devices. 1010 1261 */ 1011 for (i = 0; i < RT_ELEMENTS(p This->devices); i++)1012 { 1013 PPCIDEVICE pDev = p This->devices[i];1262 for (i = 0; i < RT_ELEMENTS(pBus->devices); i++) 1263 { 1264 PPCIDEVICE pDev = pBus->devices[i]; 1014 1265 if (pDev) 1015 1266 { … … 1017 1268 SSMR3PutU32(pSSMHandle, i); 1018 1269 SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config)); 1019 rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.iIrq); 1270 1271 rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState); 1020 1272 if (RT_FAILURE(rc)) 1021 1273 return rc; … … 1035 1287 static DECLCALLBACK(int) pciLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version) 1036 1288 { 1037 PPCI BUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS);1038 PPCI GLOBALS pGlobals = PCIBUS_2_PCIGLOBALS(pThis);1289 PPCIGLOBALS pThis = PDMINS_2_DATA(pDevIns, PPCIGLOBALS); 1290 PPCIBUS pBus = &pThis->PciBus; 1039 1291 uint32_t u32; 1040 1292 uint32_t i; … … 1044 1296 * Check the version. 1045 1297 */ 1046 if (u32Version > 2)1298 if (u32Version > VBOX_PCI_SAVED_STATE_VERSION) 1047 1299 { 1048 1300 AssertFailed(); … … 1055 1307 SSMR3GetU32(pSSMHandle, &pThis->uConfigReg); 1056 1308 if (u32Version > 1) 1057 SSMR3GetBool(pSSMHandle, &pGlobals->fUseIoApic); 1309 SSMR3GetBool(pSSMHandle, &pThis->fUseIoApic); 1310 1311 /* Load IRQ states. */ 1312 if (u32Version > 2) 1313 { 1314 for (uint8_t i = 0; i < PCI_IRQ_PINS; i++) 1315 SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_irq_levels[i]); 1316 for (uint8_t i = 0; i < PCI_APIC_IRQ_PINS; i++) 1317 SSMR3GetU32(pSSMHandle, (uint32_t *)&pThis->pci_apic_irq_levels[i]); 1318 1319 SSMR3GetU32(pSSMHandle, &pThis->acpi_irq_level); 1320 SSMR3GetS32(pSSMHandle, &pThis->acpi_irq); 1321 } 1058 1322 1059 1323 /* separator */ … … 1078 1342 if (u32 == (uint32_t)~0) 1079 1343 break; 1080 if ( u32 >= RT_ELEMENTS(p This->devices)1344 if ( u32 >= RT_ELEMENTS(pBus->devices) 1081 1345 || u32 < i) 1082 1346 { … … 1088 1352 for (; i < u32; i++) 1089 1353 { 1090 if (p This->devices[i])1354 if (pBus->devices[i]) 1091 1355 { 1092 LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, p This->devices[i]->name,1093 PCIDevGetVendorId(p This->devices[i]), PCIDevGetDeviceId(pThis->devices[i])));1356 LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name, 1357 PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i]))); 1094 1358 if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT) 1095 1359 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH); … … 1097 1361 } 1098 1362 1099 /* get the data */ 1363 /* Get the data */ 1364 DevTmp.Int.s.uIrqPinState = ~0; /* Invalid value in case we have an older saved state to force a state change in pciSetIrq. */ 1100 1365 SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config)); 1101 rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.iIrq); 1102 if (RT_FAILURE(rc)) 1103 return rc; 1366 if (u32Version < 3) 1367 { 1368 int32_t i32Temp; 1369 /* Irq value not needed anymore. */ 1370 rc = SSMR3GetS32(pSSMHandle, &i32Temp); 1371 if (RT_FAILURE(rc)) 1372 return rc; 1373 } 1374 else 1375 { 1376 rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState); 1377 if (RT_FAILURE(rc)) 1378 return rc; 1379 } 1104 1380 1105 1381 /* check that it's still around. */ 1106 pDev = p This->devices[i];1382 pDev = pBus->devices[i]; 1107 1383 if (!pDev) 1108 1384 { … … 1125 1401 /* commit the loaded device config. */ 1126 1402 memcpy(pDev->config, DevTmp.config, sizeof(pDev->config)); 1127 if (DevTmp.Int.s.iIrq >= PCI_DEVICES_MAX) 1128 { 1129 LogRel(("Device %s: Too many devices %d (max=%d)\n", pDev->name, DevTmp.Int.s.iIrq, PCI_DEVICES_MAX)); 1130 AssertFailedReturn(VERR_TOO_MUCH_DATA); 1131 } 1132 1133 pDev->Int.s.iIrq = DevTmp.Int.s.iIrq; 1134 } 1403 1404 pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState; 1405 } 1406 1135 1407 return VINF_SUCCESS; 1136 1408 } … … 1141 1413 1142 1414 /** 1143 * Registers the device with the defaultPCI bus.1415 * Registers the device with the specified PCI bus. 1144 1416 * 1145 1417 * @returns VBox status code. … … 1149 1421 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique. 1150 1422 */ 1151 static void pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName) 1152 { 1153 Assert(!pBus->devices[iDev]); 1154 pPciDev->devfn = iDev; 1155 pPciDev->name = pszName; 1156 pPciDev->Int.s.pBus = pBus; 1157 pPciDev->Int.s.pfnConfigRead = pci_default_read_config; 1158 pPciDev->Int.s.pfnConfigWrite = pci_default_write_config; 1159 AssertMsg(pBus->uIrqIndex < PCI_DEVICES_MAX, 1160 ("Device %s: Too many devices %d (max=%d)\n", 1161 pszName, pBus->uIrqIndex, PCI_DEVICES_MAX)); 1162 pPciDev->Int.s.iIrq = pBus->uIrqIndex++; 1163 pBus->devices[iDev] = pPciDev; 1164 Log(("PCI: Registered device %d function %d (%#x) '%s'.\n", 1165 iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName)); 1166 } 1167 1168 1169 /** 1170 * Registers the device with the default PCI bus. 1171 * 1172 * @returns VBox status code. 1173 * @param pDevIns Device instance of the PCI Bus. 1174 * @param pPciDev The PCI device structure. 1175 * Any PCI enabled device must keep this in it's instance data! 1176 * Fill in the PCI data config before registration, please. 1177 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique. 1178 * @param iDev The PCI device number. Use a negative value for auto assigning one. 1179 */ 1180 static DECLCALLBACK(int) pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev) 1181 { 1182 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1183 1184 /* 1185 * Check input. 1186 */ 1187 if ( !pszName 1188 || !pPciDev 1189 || iDev >= (int)RT_ELEMENTS(pBus->devices) 1190 || (iDev >= 0 && iDev <= 8)) 1191 { 1192 AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev)); 1193 return VERR_INVALID_PARAMETER; 1194 } 1195 1423 static int pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName) 1424 { 1196 1425 /* 1197 1426 * Find device slot. … … 1240 1469 * config, do it for all pci devices! 1241 1470 */ 1242 AssertReleaseMsg(iDev > 8, ("iDev=%d pszName=%s\n", iDev, pszName));1471 //AssertReleaseMsg(iDev > 8 || pBus->iBus != 0, ("iDev=%d pszName=%s\n", iDev, pszName)); 1243 1472 if (pBus->devices[iDev]) 1244 1473 { … … 1293 1522 } 1294 1523 1524 Assert(!pBus->devices[iDev]); 1525 pPciDev->devfn = iDev; 1526 pPciDev->name = pszName; 1527 pPciDev->Int.s.pBusR3 = pBus; 1528 pPciDev->Int.s.pBusR0 = MMHyperR3ToR0(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus); 1529 pPciDev->Int.s.pBusRC = MMHyperR3ToRC(PDMDevHlpGetVM(pBus->CTX_SUFF(pDevIns)), pBus); 1530 pPciDev->Int.s.pfnConfigRead = pci_default_read_config; 1531 pPciDev->Int.s.pfnConfigWrite = pci_default_write_config; 1532 pBus->devices[iDev] = pPciDev; 1533 Log(("PCI: Registered device %d function %d (%#x) '%s'.\n", 1534 iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName)); 1535 1536 return VINF_SUCCESS; 1537 } 1538 1539 1540 /** 1541 * Registers the device with the default PCI bus. 1542 * 1543 * @returns VBox status code. 1544 * @param pDevIns Device instance of the PCI Bus. 1545 * @param pPciDev The PCI device structure. 1546 * Any PCI enabled device must keep this in it's instance data! 1547 * Fill in the PCI data config before registration, please. 1548 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique. 1549 * @param iDev The PCI device number. Use a negative value for auto assigning one. 1550 */ 1551 static DECLCALLBACK(int) pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev) 1552 { 1553 PPCIBUS pBus = DEVINS_2_PCIBUS(pDevIns); 1554 1555 /* 1556 * Check input. 1557 */ 1558 if ( !pszName 1559 || !pPciDev 1560 || iDev >= (int)RT_ELEMENTS(pBus->devices) 1561 || (iDev >= 0 && iDev <= 8)) 1562 { 1563 AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev)); 1564 return VERR_INVALID_PARAMETER; 1565 } 1566 1295 1567 /* 1296 1568 * Register the device. 1297 1569 */ 1298 pciRegisterInternal(pBus, iDev, pPciDev, pszName); 1299 return VINF_SUCCESS; 1570 return pciRegisterInternal(pBus, iDev, pPciDev, pszName); 1300 1571 } 1301 1572 … … 1303 1574 static DECLCALLBACK(int) pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback) 1304 1575 { 1305 1306 1576 /* 1307 1577 * Validate. … … 1328 1598 pRegion->type = enmType; 1329 1599 pRegion->map_func = pfnCallback; 1600 1601 /* Set type in the config space. */ 1602 uint32_t u32Address = 0x10 + iRegion * 4; 1603 uint32_t u32Value = (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH ? (1 << 3) : 0) 1604 | (enmType == PCI_ADDRESS_SPACE_IO ? 1 : 0); 1605 *(uint32_t *)(pPciDev->config + u32Address) = RT_H2LE_U32(u32Value); 1606 1330 1607 return VINF_SUCCESS; 1331 1608 } … … 1359 1636 unsigned i; 1360 1637 uint8_t elcr[2] = {0, 0}; 1361 PPCIGLOBALS pGlobals = DEVINS_2_PCIGLOBALS(pDevIns); 1362 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1638 PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS); 1363 1639 PVM pVM = PDMDevHlpGetVM(pDevIns); 1364 1640 Assert(pVM); … … 1369 1645 pGlobals->pci_bios_io_addr = 0xc000; 1370 1646 pGlobals->pci_bios_mem_addr = UINT32_C(0xf0000000); 1647 pGlobals->uBus = 0; 1371 1648 1372 1649 /* … … 1379 1656 elcr[irq >> 3] |= (1 << (irq & 7)); 1380 1657 /* Activate irq remapping in PIIX3. */ 1381 pci_config_writeb( &pBus->PIIX3State.dev, 0x60 + i, irq);1658 pci_config_writeb(pGlobals, 0, pGlobals->PIIX3State.dev.devfn, 0x60 + i, irq); 1382 1659 } 1383 1660 … … 1395 1672 * Init the devices. 1396 1673 */ 1397 for (i = 0; i < RT_ELEMENTS(pBus->devices); i++) 1674 for (i = 0; i < 256; i++) 1675 { 1676 uint8_t aBridgePositions[256]; 1677 1678 memset(aBridgePositions, 0, sizeof(aBridgePositions)); 1679 Log2(("PCI: Initializing device %d (%#x)\n", 1680 i, 0x80000000 | (i << 8))); 1681 pci_bios_init_device(pGlobals, 0, i, 0, aBridgePositions); 1682 } 1683 1684 return VINF_SUCCESS; 1685 } 1686 1687 /** 1688 * @copydoc FNPDMDEVRELOCATE 1689 */ 1690 static DECLCALLBACK(void) pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 1691 { 1692 PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS); 1693 PPCIBUS pBus = &pGlobals->PciBus; 1694 pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1695 1696 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns); 1697 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1698 1699 /* Relocate RC pointers for the attached pci devices. */ 1700 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++) 1398 1701 { 1399 1702 if (pBus->devices[i]) 1400 { 1401 Log2(("PCI: Initializing device %d (%#x) '%s'\n", 1402 i, 0x80000000 | (i << 8), pBus->devices[i]->name)); 1403 pci_bios_init_device(pBus->devices[i]); 1404 } 1405 } 1406 return VINF_SUCCESS; 1407 } 1408 1409 /** 1410 * @copydoc FNPDMDEVRELOCATE 1411 */ 1412 static DECLCALLBACK(void) pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 1413 { 1414 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1415 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1416 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns); 1417 } 1418 1419 1420 /** 1421 * Construct a PCI Bus device instance for a VM. 1703 pBus->devices[i]->Int.s.pBusRC += offDelta; 1704 } 1705 } 1706 1707 1708 /** 1709 * Construct a host to PCI Bus device instance for a VM. 1422 1710 * 1423 1711 * @returns VBox status. … … 1467 1755 * Init data and register the PCI bus. 1468 1756 */ 1469 PPCIGLOBALS pGlobals = DEVINS_2_PCIGLOBALS(pDevIns); 1470 pGlobals->pci_mem_base = 0; 1757 PPCIGLOBALS pGlobals = PDMINS_2_DATA(pDevIns, PPCIGLOBALS); 1471 1758 pGlobals->pci_bios_io_addr = 0xc000; 1472 1759 pGlobals->pci_bios_mem_addr = 0xf0000000; 1473 memset( &pGlobals->pci_irq_levels, 0, sizeof(pGlobals->pci_irq_levels));1760 memset((void *)&pGlobals->pci_irq_levels, 0, sizeof(pGlobals->pci_irq_levels)); 1474 1761 pGlobals->fUseIoApic = fUseIoApic; 1475 memset(&pGlobals->pci_apic_irq_levels, 0, sizeof(pGlobals->pci_apic_irq_levels)); 1476 1477 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1478 pBus->pDevInsR3 = pDevIns; 1479 pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1480 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1762 memset((void *)&pGlobals->pci_apic_irq_levels, 0, sizeof(pGlobals->pci_apic_irq_levels)); 1763 1764 pGlobals->pDevInsR3 = pDevIns; 1765 pGlobals->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1766 pGlobals->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1767 1768 pGlobals->PciBus.pDevInsR3 = pDevIns; 1769 pGlobals->PciBus.pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 1770 pGlobals->PciBus.pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 1481 1771 1482 1772 PDMPCIBUSREG PciBusReg; 1773 PPCIBUS pBus = &pGlobals->PciBus; 1483 1774 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION; 1484 1775 PciBusReg.pfnRegisterR3 = pciRegister; … … 1498 1789 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS, 1499 1790 N_("PCI helper version mismatch; got %#x expected %#x"), 1500 1791 pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION); 1501 1792 1502 1793 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns); … … 1519 1810 1520 1811 /* PIIX3 */ 1521 PCIDevSetVendorId( &p Bus->PIIX3State.dev, 0x8086); /* Intel */1522 PCIDevSetDeviceId( &p Bus->PIIX3State.dev, 0x7000); /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */1523 PCIDevSetClassSub( &p Bus->PIIX3State.dev, 0x01); /* PCI_ISA */1524 PCIDevSetClassBase( &p Bus->PIIX3State.dev, 0x06); /* PCI_bridge */1525 PCIDevSetHeaderType(&p Bus->PIIX3State.dev, 0x80); /* PCI_multifunction, generic */1526 1527 p Bus->PIIX3State.dev.pDevIns = pDevIns;1528 p Bus->PciDev.Int.s.fRequestedDevFn= true;1529 pciRegisterInternal(pBus, 8, &p Bus->PIIX3State.dev, "PIIX3");1530 piix3_reset(&p Bus->PIIX3State);1812 PCIDevSetVendorId( &pGlobals->PIIX3State.dev, 0x8086); /* Intel */ 1813 PCIDevSetDeviceId( &pGlobals->PIIX3State.dev, 0x7000); /* 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */ 1814 PCIDevSetClassSub( &pGlobals->PIIX3State.dev, 0x01); /* PCI_ISA */ 1815 PCIDevSetClassBase( &pGlobals->PIIX3State.dev, 0x06); /* PCI_bridge */ 1816 PCIDevSetHeaderType(&pGlobals->PIIX3State.dev, 0x80); /* PCI_multifunction, generic */ 1817 1818 pGlobals->PIIX3State.dev.pDevIns = pDevIns; 1819 pGlobals->PIIX3State.dev.Int.s.fRequestedDevFn= true; 1820 pciRegisterInternal(pBus, 8, &pGlobals->PIIX3State.dev, "PIIX3"); 1821 piix3_reset(&pGlobals->PIIX3State); 1531 1822 1532 1823 pBus->iDevSearch = 16; … … 1541 1832 if (RT_FAILURE(rc)) 1542 1833 return rc; 1543 rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, 2, sizeof(*pBus),1834 rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus), 1544 1835 NULL, pciSaveExec, NULL, NULL, pciLoadExec, NULL); 1545 1836 if (RT_FAILURE(rc)) … … 1572 1863 1, 1573 1864 /* cbInstance */ 1574 sizeof(PCI BUS),1865 sizeof(PCIGLOBALS), 1575 1866 /* pfnConstruct */ 1576 1867 pciConstruct, … … 1606 1897 }; 1607 1898 #endif /* IN_RING3 */ 1899 1900 /** 1901 * Set the IRQ for a PCI device on a secondary bus. 1902 * 1903 * @param pDevIns Device instance of the PCI Bus. 1904 * @param pPciDev The PCI device structure. 1905 * @param iIrq IRQ number to set. 1906 * @param iLevel IRQ level. 1907 */ 1908 PDMBOTHCBDECL(void) pcibridgeSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel) 1909 { 1910 /* 1911 * The PCI-to-PCI bridge specification defines how the interrupt pins 1912 * are routed from the secondary to the primary bus (see chapter 9). 1913 * iIrq gives the interrupt pin the pci device asserted. 1914 * We change iIrq here according to the spec and call the SetIrq function 1915 * of our parent passing the device which asserted the interrupt instead of the device of the bridge. 1916 */ 1917 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1918 int iIrqPinBridge = 0; 1919 uint8_t uDevFnBridge; 1920 1921 /* Walk the chain until we reach the host bus. */ 1922 while (pBus->iBus != 0) 1923 { 1924 uDevFnBridge = pBus->PciDev.devfn; 1925 iIrqPinBridge = ((uDevFnBridge >> 3) + iIrqPinBridge) & 3; 1926 /* Get the parent. */ 1927 pBus = pBus->PciDev.Int.s.CTX_SUFF(pBus); 1928 } 1929 1930 AssertMsg(pBus->iBus == 0, ("This is not the host pci bus iBus=%d\n", pBus->iBus)); 1931 pciSetIrqInternal(PCIBUS_2_PCIGLOBALS(pBus), uDevFnBridge, pPciDev, iIrqPinBridge, iLevel); 1932 } 1933 1934 #ifdef IN_RING3 1935 1936 static void pcibridgeConfigWrite(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb) 1937 { 1938 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1939 1940 LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u u32Value=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, u32Value, cb)); 1941 1942 /* If the current bus is not the target bus search for the bus which contains the device. */ 1943 if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS]) 1944 { 1945 /* 1946 * Search for a fitting bridge. Becuase we don't support multi function devices at the moment 1947 * we only search all devices with function 0 to speed things up. 1948 * If no bridge is found the write will be ignored. 1949 */ 1950 for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8) 1951 { 1952 /* 1953 * Examine secondary and subordinate bus number. 1954 * If the target bus is in the range we pass the request on to the bridge. 1955 */ 1956 PPCIDEVICE pBridgeDevice = pBus->devices[iDev]; 1957 if (!pBridgeDevice) 1958 continue; 1959 if (!pBridgeDevice->Int.s.fPciToPciBridge) 1960 continue; 1961 1962 if ( iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS] 1963 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS]) 1964 { 1965 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigWrite); 1966 1967 pBridgeDevice->Int.s.pfnBridgeConfigWrite(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, u32Value, cb); 1968 } 1969 } 1970 } 1971 else 1972 { 1973 /* This is the target bus, pass the write to the device. */ 1974 PPCIDEVICE pPciDev = pBus->devices[iDevice]; 1975 if (pPciDev) 1976 { 1977 Log(("%s: %s: addr=%02x val=%08x len=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb)); 1978 pPciDev->Int.s.pfnConfigWrite(pPciDev, u32Address, u32Value, cb); 1979 } 1980 } 1981 } 1982 1983 static uint32_t pcibridgeConfigRead(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb) 1984 { 1985 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 1986 uint32_t u32Value = 0xffffffff; /* Return value in case there is no device. */ 1987 1988 LogFlowFunc((": pDevIns=%p iBus=%d iDevice=%d u32Address=%u cb=%d\n", pDevIns, iBus, iDevice, u32Address, cb)); 1989 1990 /* If the current bus is not the target bus search for the bus which contains the device. */ 1991 if (iBus != pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS]) 1992 { 1993 /* 1994 * Search for a fitting bridge. Because we don't support multi function devices at the moment 1995 * we only search all devices with function 0 to speed things up. 1996 * If no bridge is found the read will return 0xffffffff. 1997 */ 1998 for (uint32_t iDev = pBus->iDevSearch; iDev < RT_ELEMENTS(pBus->devices); iDev += 8) 1999 { 2000 /* 2001 * Examine secondary and subordinate bus number. 2002 * If the target bus is in the range we pass the request on to the bridge. 2003 */ 2004 PPCIDEVICE pBridgeDevice = pBus->devices[iDev]; 2005 if (!pBridgeDevice) 2006 continue; 2007 if (!pBridgeDevice->Int.s.fPciToPciBridge) 2008 continue; 2009 2010 if ( iBus >= pBridgeDevice->config[VBOX_PCI_SECONDARY_BUS] 2011 && iBus <= pBridgeDevice->config[VBOX_PCI_SUBORDINATE_BUS]) 2012 { 2013 AssertPtr(pBridgeDevice->Int.s.pfnBridgeConfigRead); 2014 2015 u32Value = pBridgeDevice->Int.s.pfnBridgeConfigRead(pBridgeDevice->pDevIns, iBus, iDevice, u32Address, cb); 2016 } 2017 } 2018 } 2019 else 2020 { 2021 /* This is the target bus, pass the read to the device. */ 2022 PPCIDEVICE pPciDev = pBus->devices[iDevice]; 2023 if (pPciDev) 2024 { 2025 u32Value = pPciDev->Int.s.pfnConfigRead(pPciDev, u32Address, cb); 2026 Log(("%s: %s: u32Address=%02x u32Value=%08x cb=%d\n", __FUNCTION__, pPciDev->name, u32Address, u32Value, cb)); 2027 } 2028 } 2029 2030 return u32Value; 2031 } 2032 2033 /** 2034 * Saves a state of a PCI bridge device. 2035 * 2036 * @returns VBox status code. 2037 * @param pDevIns The device instance. 2038 * @param pPciDev Pointer to PCI device. 2039 * @param pSSMHandle The handle to save the state to. 2040 */ 2041 static DECLCALLBACK(int) pcibridgeSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle) 2042 { 2043 uint32_t i; 2044 PPCIBUS pThis = PDMINS_2_DATA(pDevIns, PPCIBUS); 2045 2046 /* 2047 * Iterate all the devices. 2048 */ 2049 for (i = 0; i < RT_ELEMENTS(pThis->devices); i++) 2050 { 2051 PPCIDEVICE pDev = pThis->devices[i]; 2052 if (pDev) 2053 { 2054 int rc; 2055 SSMR3PutU32(pSSMHandle, i); 2056 SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config)); 2057 2058 rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.uIrqPinState); 2059 if (RT_FAILURE(rc)) 2060 return rc; 2061 } 2062 } 2063 return SSMR3PutU32(pSSMHandle, ~0); /* terminator */ 2064 } 2065 2066 /** 2067 * Loads a saved PCI bridge device state. 2068 * 2069 * @returns VBox status code. 2070 * @param pDevIns The device instance. 2071 * @param pSSMHandle The handle to the saved state. 2072 * @param u32Version The data unit version number. 2073 */ 2074 static DECLCALLBACK(int) pcibridgeLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version) 2075 { 2076 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 2077 uint32_t u32; 2078 uint32_t i; 2079 int rc; 2080 2081 /* 2082 * Check the version. 2083 */ 2084 if (u32Version > VBOX_PCI_SAVED_STATE_VERSION) 2085 { 2086 AssertFailed(); 2087 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION; 2088 } 2089 2090 /* 2091 * Iterate all the devices. 2092 */ 2093 for (i = 0;; i++) 2094 { 2095 PCIDEVICE DevTmp; 2096 PPCIDEVICE pDev; 2097 2098 /* index / terminator */ 2099 rc = SSMR3GetU32(pSSMHandle, &u32); 2100 if (RT_FAILURE(rc)) 2101 return rc; 2102 if (u32 == (uint32_t)~0) 2103 break; 2104 if ( u32 >= RT_ELEMENTS(pBus->devices) 2105 || u32 < i) 2106 { 2107 AssertMsgFailed(("u32=%#x i=%#x\n", u32, i)); 2108 return rc; 2109 } 2110 2111 /* skip forward to the device checking that no new devices are present. */ 2112 for (; i < u32; i++) 2113 { 2114 if (pBus->devices[i]) 2115 { 2116 LogRel(("New device in slot %#x, %s (vendor=%#06x device=%#06x)\n", i, pBus->devices[i]->name, 2117 PCIDevGetVendorId(pBus->devices[i]), PCIDevGetDeviceId(pBus->devices[i]))); 2118 if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT) 2119 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH); 2120 } 2121 } 2122 2123 /* get the data */ 2124 DevTmp.Int.s.uIrqPinState = 0; 2125 SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config)); 2126 rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.uIrqPinState); 2127 if (RT_FAILURE(rc)) 2128 return rc; 2129 2130 /* check that it's still around. */ 2131 pDev = pBus->devices[i]; 2132 if (!pDev) 2133 { 2134 LogRel(("Device in slot %#x has been removed! vendor=%#06x device=%#06x\n", i, 2135 PCIDevGetVendorId(&DevTmp), PCIDevGetDeviceId(&DevTmp))); 2136 if (SSMR3HandleGetAfter(pSSMHandle) != SSMAFTER_DEBUG_IT) 2137 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH); 2138 continue; 2139 } 2140 2141 /* match the vendor id assuming that this will never be changed. */ 2142 if ( DevTmp.config[0] != pDev->config[0] 2143 || DevTmp.config[1] != pDev->config[1]) 2144 { 2145 LogRel(("Device in slot %#x (%s) vendor id mismatch! saved=%.4Vhxs current=%.4Vhxs\n", 2146 i, pDev->name, DevTmp.config, pDev->config)); 2147 AssertFailedReturn(VERR_SSM_LOAD_CONFIG_MISMATCH); 2148 } 2149 2150 /* commit the loaded device config. */ 2151 memcpy(pDev->config, DevTmp.config, sizeof(pDev->config)); 2152 2153 pDev->Int.s.uIrqPinState = DevTmp.Int.s.uIrqPinState; 2154 } 2155 2156 return VINF_SUCCESS; 2157 } 2158 2159 /** 2160 * @copydoc FNPDMDEVRESET 2161 */ 2162 static DECLCALLBACK(void) pcibridgeReset(PPDMDEVINS pDevIns) 2163 { 2164 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 2165 2166 /* Reset config space to default values. */ 2167 pBus->PciDev.config[VBOX_PCI_PRIMARY_BUS] = 0; 2168 pBus->PciDev.config[VBOX_PCI_SECONDARY_BUS] = 0; 2169 pBus->PciDev.config[VBOX_PCI_SUBORDINATE_BUS] = 0; 2170 } 2171 2172 /** 2173 * @copydoc FNPDMDEVRELOCATE 2174 */ 2175 static DECLCALLBACK(void) pcibridgeRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 2176 { 2177 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 2178 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 2179 2180 /* Relocate RC pointers for the attached pci devices. */ 2181 for (uint32_t i = 0; i < RT_ELEMENTS(pBus->devices); i++) 2182 { 2183 if (pBus->devices[i]) 2184 pBus->devices[i]->Int.s.pBusRC += offDelta; 2185 } 2186 } 2187 2188 /** 2189 * Registers the device with the default PCI bus. 2190 * 2191 * @returns VBox status code. 2192 * @param pDevIns Device instance of the PCI Bus. 2193 * @param pPciDev The PCI device structure. 2194 * Any PCI enabled device must keep this in it's instance data! 2195 * Fill in the PCI data config before registration, please. 2196 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique. 2197 * @param iDev The PCI device number. Use a negative value for auto assigning one. 2198 */ 2199 static DECLCALLBACK(int) pcibridgeRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev) 2200 { 2201 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 2202 2203 /* 2204 * Check input. 2205 */ 2206 if ( !pszName 2207 || !pPciDev 2208 || iDev >= (int)RT_ELEMENTS(pBus->devices)) 2209 { 2210 AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev)); 2211 return VERR_INVALID_PARAMETER; 2212 } 2213 2214 /* 2215 * Register the device. 2216 */ 2217 return pciRegisterInternal(pBus, iDev, pPciDev, pszName); 2218 } 2219 2220 /** 2221 * Construct a PCI bridge device instance for a VM. 2222 * 2223 * @returns VBox status. 2224 * @param pDevIns The device instance data. 2225 * If the registration structure is needed, pDevIns->pDevReg points to it. 2226 * @param iInstance Instance number. Use this to figure out which registers and such to use. 2227 * The device number is also found in pDevIns->iInstance, but since it's 2228 * likely to be freqently used PDM passes it as parameter. 2229 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration 2230 * of the device instance. It's also found in pDevIns->pCfgHandle, but like 2231 * iInstance it's expected to be used a bit in this function. 2232 */ 2233 static DECLCALLBACK(int) pcibridgeConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle) 2234 { 2235 int rc; 2236 2237 /* 2238 * Validate and read configuration. 2239 */ 2240 if (!CFGMR3AreValuesValid(pCfgHandle, "GCEnabled\0" "R0Enabled\0")) 2241 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES; 2242 2243 /* check if RC code is enabled. */ 2244 bool fGCEnabled; 2245 rc = CFGMR3QueryBoolDef(pCfgHandle, "GCEnabled", &fGCEnabled, true); 2246 if (RT_FAILURE(rc)) 2247 return PDMDEV_SET_ERROR(pDevIns, rc, 2248 N_("Configuration error: Failed to query boolean value \"GCEnabled\"")); 2249 2250 /* check if R0 code is enabled. */ 2251 bool fR0Enabled; 2252 rc = CFGMR3QueryBoolDef(pCfgHandle, "R0Enabled", &fR0Enabled, true); 2253 if (RT_FAILURE(rc)) 2254 return PDMDEV_SET_ERROR(pDevIns, rc, 2255 N_("Configuration error: Failed to query boolean value \"R0Enabled\"")); 2256 Log(("PCI: fGCEnabled=%RTbool fR0Enabled=%RTbool\n", fGCEnabled, fR0Enabled)); 2257 2258 /* 2259 * Init data and register the PCI bus. 2260 */ 2261 PPCIBUS pBus = PDMINS_2_DATA(pDevIns, PPCIBUS); 2262 pBus->pDevInsR3 = pDevIns; 2263 pBus->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 2264 pBus->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 2265 2266 PDMPCIBUSREG PciBusReg; 2267 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION; 2268 PciBusReg.pfnRegisterR3 = pcibridgeRegister; 2269 PciBusReg.pfnIORegionRegisterR3 = pciIORegionRegister; 2270 PciBusReg.pfnSetConfigCallbacksR3 = pciSetConfigCallbacks; 2271 PciBusReg.pfnSetIrqR3 = pcibridgeSetIrq; 2272 PciBusReg.pfnSaveExecR3 = pciGenericSaveExec; 2273 PciBusReg.pfnLoadExecR3 = pciGenericLoadExec; 2274 PciBusReg.pfnFakePCIBIOSR3 = NULL; /* Only needed for the first bus. */ 2275 PciBusReg.pszSetIrqRC = fGCEnabled ? "pcibridgeSetIrq" : NULL; 2276 PciBusReg.pszSetIrqR0 = fR0Enabled ? "pcibridgeSetIrq" : NULL; 2277 rc = pDevIns->pDevHlpR3->pfnPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3); 2278 if (RT_FAILURE(rc)) 2279 return PDMDEV_SET_ERROR(pDevIns, rc, 2280 N_("Failed to register ourselves as a PCI Bus")); 2281 if (pBus->pPciHlpR3->u32Version != PDM_PCIHLPR3_VERSION) 2282 return PDMDevHlpVMSetError(pDevIns, VERR_VERSION_MISMATCH, RT_SRC_POS, 2283 N_("PCI helper version mismatch; got %#x expected %#x"), 2284 pBus->pPciHlpR3->u32Version, PDM_PCIHLPR3_VERSION); 2285 2286 pBus->pPciHlpRC = pBus->pPciHlpR3->pfnGetRCHelpers(pDevIns); 2287 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns); 2288 2289 /* 2290 * Fill in PCI configs and add them to the bus. 2291 */ 2292 PCIDevSetVendorId( &pBus->PciDev, 0x8086); /* Intel */ 2293 PCIDevSetDeviceId( &pBus->PciDev, 0x2448); /* 82801 Mobile PCI bridge. */ 2294 PCIDevSetRevisionId(&pBus->PciDev, 0xf2); 2295 PCIDevSetClassSub( &pBus->PciDev, 0x04); /* pci2pci */ 2296 PCIDevSetClassBase( &pBus->PciDev, 0x06); /* PCI_bridge */ 2297 PCIDevSetClassProg( &pBus->PciDev, 0x01); /* Supports subtractive decoding. */ 2298 PCIDevSetHeaderType(&pBus->PciDev, 0x01); /* Single function device which adheres to the PCI-to-PCI bridge spec. */ 2299 PCIDevSetCommand( &pBus->PciDev, 0x00); 2300 PCIDevSetStatus( &pBus->PciDev, 0x20); /* 66MHz Capable. */ 2301 PCIDevSetInterruptLine(&pBus->PciDev, 0x00); /* This device does not assert interrupts. */ 2302 2303 /* 2304 * This device does not generate interrupts. Interrupt delivery from 2305 * devices attached to the bus is unaffected. 2306 */ 2307 PCIDevSetInterruptPin (&pBus->PciDev, 0x00); 2308 2309 pBus->PciDev.pDevIns = pDevIns; 2310 pBus->PciDev.Int.s.fPciToPciBridge = true; 2311 pBus->PciDev.Int.s.pfnBridgeConfigRead = pcibridgeConfigRead; 2312 pBus->PciDev.Int.s.pfnBridgeConfigWrite = pcibridgeConfigWrite; 2313 2314 /* 2315 * Register this PCI bridge. The called function will take care on which bus we will get registered. 2316 */ 2317 rc = PDMDevHlpPCIRegister (pDevIns, &pBus->PciDev); 2318 if (RT_FAILURE(rc)) 2319 return rc; 2320 2321 pBus->iDevSearch = 0; 2322 /* 2323 * The iBus property doesn't really represent the bus number 2324 * because the guest and the BIOS can choose different bus numbers 2325 * for them. 2326 * The bus number is mainly for the setIrq function to indicate 2327 * when the host bus is reached which will have iBus = 0. 2328 * Thathswhy the + 1. 2329 */ 2330 pBus->iBus = iInstance + 1; 2331 2332 /* 2333 * Register SSM handlers. We use the same saved state version as for the host bridge 2334 * to make changes easier. 2335 */ 2336 rc = PDMDevHlpSSMRegister(pDevIns, "pcibridge", iInstance, VBOX_PCI_SAVED_STATE_VERSION, sizeof(*pBus), 2337 NULL, pcibridgeSaveExec, NULL, NULL, pcibridgeLoadExec, NULL); 2338 if (RT_FAILURE(rc)) 2339 return rc; 2340 2341 return VINF_SUCCESS; 2342 } 2343 2344 /** 2345 * The device registration structure 2346 * for the PCI-to-PCI bridge. 2347 */ 2348 const PDMDEVREG g_DevicePCIBridge = 2349 { 2350 /* u32Version */ 2351 PDM_DEVREG_VERSION, 2352 /* szDeviceName */ 2353 "pcibridge", 2354 /* szGCMod */ 2355 "VBoxDDGC.gc", 2356 /* szR0Mod */ 2357 "VBoxDDR0.r0", 2358 /* pszDescription */ 2359 "82801 Mobile PCI to PCI bridge", 2360 /* fFlags */ 2361 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0, 2362 /* fClass */ 2363 PDM_DEVREG_CLASS_BUS_PCI, 2364 /* cMaxInstances */ 2365 ~0, 2366 /* cbInstance */ 2367 sizeof(PCIBUS), 2368 /* pfnConstruct */ 2369 pcibridgeConstruct, 2370 /* pfnDestruct */ 2371 NULL, 2372 /* pfnRelocate */ 2373 pcibridgeRelocate, 2374 /* pfnIOCtl */ 2375 NULL, 2376 /* pfnPowerOn */ 2377 NULL, 2378 /* pfnReset */ 2379 pcibridgeReset, 2380 /* pfnSuspend */ 2381 NULL, 2382 /* pfnResume */ 2383 NULL, 2384 /* pfnAttach */ 2385 NULL, 2386 /* pfnDetach */ 2387 NULL, 2388 /* pfnQueryInterface */ 2389 NULL, 2390 /* pfnInitComplete */ 2391 NULL, 2392 /* pfnPowerOff */ 2393 NULL, 2394 /* pfnSoftReset */ 2395 NULL, 2396 /* u32VersionEnd */ 2397 PDM_DEVREG_VERSION 2398 }; 2399 2400 #endif /* IN_RING3 */ 1608 2401 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */ -
trunk/src/VBox/Devices/Bus/PCIInternal.h
r11230 r13189 41 41 42 42 /** 43 * Callback function for reading from the PCI configuration space. 44 * 45 * @returns The register value. 46 * @param pDevIns Pointer to the device instance of the PCI bus. 47 * @param iBus The bus number this device is on. 48 * @param iDevice The number of the device on the bus. 49 * @param Address The configuration space register address. [0..255] 50 * @param cb The register size. [1,2,4] 51 */ 52 typedef DECLCALLBACK(uint32_t) FNPCIBRIDGECONFIGREAD(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, unsigned cb); 53 /** Pointer to a FNPCICONFIGREAD() function. */ 54 typedef FNPCIBRIDGECONFIGREAD *PFNPCIBRIDGECONFIGREAD; 55 /** Pointer to a PFNPCICONFIGREAD. */ 56 typedef PFNPCIBRIDGECONFIGREAD *PPFNPCIBRIDGECONFIGREAD; 57 58 /** 59 * Callback function for writing to the PCI configuration space. 60 * 61 * @param pDevIns Pointer to the device instance of the PCI bus. 62 * @param iBus The bus number this device is on. 63 * @param iDevice The number of the device on the bus. 64 * @param Address The configuration space register address. [0..255] 65 * @param u32Value The value that's being written. The number of bits actually used from 66 * this value is determined by the cb parameter. 67 * @param cb The register size. [1,2,4] 68 */ 69 typedef DECLCALLBACK(void) FNPCIBRIDGECONFIGWRITE(PPDMDEVINSR3 pDevIns, uint8_t iBus, uint8_t iDevice, uint32_t u32Address, uint32_t u32Value, unsigned cb); 70 /** Pointer to a FNPCICONFIGWRITE() function. */ 71 typedef FNPCIBRIDGECONFIGWRITE *PFNPCIBRIDGECONFIGWRITE; 72 /** Pointer to a PFNPCICONFIGWRITE. */ 73 typedef PFNPCIBRIDGECONFIGWRITE *PPFNPCIBRIDGECONFIGWRITE; 74 75 /** 43 76 * PCI Device - Internal data. 44 77 */ … … 47 80 /** I/O regions. */ 48 81 PCIIOREGION aIORegions[PCI_NUM_REGIONS]; 49 /** Pointer to the PCI bus of the device. */ 50 R3PTRTYPE(struct PCIBus *) pBus; 82 /** Pointer to the PCI bus of the device. - R3 ptr */ 83 R3PTRTYPE(struct PCIBus *) pBusR3; 84 /** Pointer to the PCI bus of the device. - R0 ptr */ 85 R0PTRTYPE(struct PCIBus *) pBusR0; 86 /** Pointer to the PCI bus of the device. - RC ptr */ 87 RCPTRTYPE(struct PCIBus *) pBusRC; 88 89 #if HC_ARCH_BITS == 64 90 uint32_t Alignment0; 91 #endif 92 51 93 /** Read config callback. */ 52 94 R3PTRTYPE(PFNPCICONFIGREAD) pfnConfigRead; 53 95 /** Write config callback. */ 54 96 R3PTRTYPE(PFNPCICONFIGWRITE) pfnConfigWrite; 55 /** The irq assigned to the device. */ 56 int32_t iIrq; 97 98 #if HC_ARCH_BITS == 64 99 uint32_t Alignment1; 100 #endif 101 57 102 /** Set if the specific device fun was requested by PDM. 58 103 * If clear the device and it's functions can be relocated to satisfy the slot request of another device. */ 59 104 bool fRequestedDevFn; 105 /** Flag whether the device is a pci-to-pci bridge. */ 106 bool fPciToPciBridge; 107 /** Current state of the IRQ pin of the device. */ 108 int32_t uIrqPinState; 109 110 #if HC_ARCH_BITS == 64 111 uint32_t Alignment2; 112 #endif 113 114 /** Read config callback for PCI bridges to pass requests 115 * to devices on another bus. 116 */ 117 R3PTRTYPE(PFNPCIBRIDGECONFIGREAD) pfnBridgeConfigRead; 118 /** Write config callback for PCI bridges to pass requests 119 * to devices on another bus. 120 */ 121 R3PTRTYPE(PFNPCIBRIDGECONFIGWRITE) pfnBridgeConfigWrite; 122 60 123 } PCIDEVICEINT; 61 124
Note:
See TracChangeset
for help on using the changeset viewer.