VirtualBox

source: vbox/trunk/src/VBox/Devices/Bus/DevPCI.cpp@ 2392

Last change on this file since 2392 was 2038, checked in by vboxsync, 18 years ago

less strict check for failures caused by MMIO2.

  • Property svn:eol-style set to native
File size: 52.2 KB
Line 
1/** @file
2 *
3 * PCI Device.
4 */
5
6/*
7 * Copyright (C) 2006 InnoTek Systemberatung GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * If you received this file as part of a commercial VirtualBox
18 * distribution, then only the terms of your commercial VirtualBox
19 * license agreement apply instead of the previous paragraph.
20 *
21 * --------------------------------------------------------------------
22 *
23 * This code is based on:
24 *
25 * QEMU PCI bus manager
26 *
27 * Copyright (c) 2004 Fabrice Bellard
28 *
29 * Permission is hereby granted, free of charge, to any person obtaining a copy
30 * of this software and associated documentation files (the "Software"), to deal
31 * in the Software without restriction, including without limitation the rights
32 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33 * copies of the Software, and to permit persons to whom the Software is
34 * furnished to do so, subject to the following conditions:
35 *
36 * The above copyright notice and this permission notice shall be included in
37 * all copies or substantial portions of the Software.
38 *
39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
42 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45 * THE SOFTWARE.
46 */
47
48/*******************************************************************************
49* Header Files *
50*******************************************************************************/
51#define LOG_GROUP LOG_GROUP_DEV_PCI
52/* Hack to get PCIDEVICEINT declare at the right point - include "PCIInternal.h". */
53#define PCI_INCLUDE_PRIVATE
54#include "vl_vbox.h"
55#include <VBox/pci.h>
56#include <VBox/pdm.h>
57#include <VBox/err.h>
58
59#include <VBox/log.h>
60#include <iprt/assert.h>
61
62#include "Builtins.h"
63
64
65/*******************************************************************************
66* Defined Constants And Macros *
67*******************************************************************************/
68/** @def PCI_LOCK
69 * Acquires the PDM lock. This is a NOP if locking is disabled. */
70/** @def PCI_UNLOCK
71 * Releases the PDM lock. This is a NOP if locking is disabled. */
72#ifdef VBOX_WITH_PDM_LOCK
73# define PCI_LOCK(pDevIns, rc) \
74 do { \
75 int rc2 = PDMINS2DATA(pDevIns, PCIBus *)->CTXALLSUFF(pPciHlp)->pfnLock((pDevIns), rc); \
76 if (rc2 != VINF_SUCCESS) \
77 return rc2; \
78 } while (0)
79# define PCI_UNLOCK(pDevIns) \
80 PDMINS2DATA(pDevIns, PCIBus *)->CTXALLSUFF(pPciHlp)->pfnUnlock(pDevIns)
81#else /* !VBOX_WITH_PDM_LOCK */
82# define PCI_LOCK(pThis, rc) do { } while (0)
83# define PCI_UNLOCK(pThis) do { } while (0)
84#endif /* !VBOX_WITH_PDM_LOCK */
85
86
87/*******************************************************************************
88* Structures and Typedefs *
89*******************************************************************************/
90/**
91 * PIIX3 ISA Bridge state.
92 */
93typedef struct PIIX3State
94{
95 /** The PCI device of the bridge. */
96 PCIDEVICE dev;
97} PIIX3State, PIIX3, *PPIIX3;
98
99
100/** Maximum number of PCI devices.
101 * Defined like this to make interrupt handling simple. */
102#define PCI_DEVICES_MAX 64
103/** Number of uint32_t entries needed make a bitmask of the interrupts. */
104#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
105
106/**
107 * PCI Globals.
108 *
109 * @remark
110 * These are currently put in the PCIBus structure since we've
111 * only got one PCI bus in the current VM configurations. This
112 * makes life somewhat simpler in GC.
113 */
114typedef struct PCIGLOBALS
115{
116 /** Irq levels for the four PCI Irqs. */
117 uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
118 /** The base address for PCI assigned MMIO addresses. */
119 RTGCPHYS pci_mem_base;
120 /** The next I/O port address which the PCI BIOS will use. */
121 uint32_t pci_bios_io_addr;
122 /** The next MMIO address which the PCI BIOS will use. */
123 uint32_t pci_bios_mem_addr;
124 /** I/O APIC usage flag */
125 bool fUseIoApic;
126 /** I/O APIC irq levels */
127 uint32_t pci_apic_irq_levels[8][PCI_IRQ_WORDS];
128 /** ACPI IRQ level */
129 uint32_t acpi_irq_level;
130 /** ACPI PIC IRQ */
131 int acpi_irq;
132} PCIGLOBALS;
133/** Pointer to per VM data. */
134typedef PCIGLOBALS *PPCIGLOBALS;
135
136
137/**
138 * PCI Bus instance.
139 */
140typedef struct PCIBus
141{
142 /** IRQ index */
143 uint32_t uIrqIndex;
144 /** Bus number. */
145 int32_t iBus;
146 /** Start device number. */
147 int32_t iDevSearch;
148 /** Config register. */
149 uint32_t uConfigReg;
150 /** Array of PCI devices. */
151 HCPTRTYPE(PPCIDEVICE) devices[256];
152
153 /** HC pointer to the device instance. */
154 PPDMDEVINSHC pDevInsHC;
155 /** Pointer to the PCI R3 helpers. */
156 PCPDMPCIHLPR3 pPciHlpR3;
157
158 /** GC pointer to the device instance. */
159 PPDMDEVINSGC pDevInsGC;
160 /** Pointer to the PCI GC helpers. */
161 PCPDMPCIHLPGC pPciHlpGC;
162 /** Pointer to the PCI R0 helpers. */
163 PCPDMPCIHLPR0 pPciHlpR0;
164
165 /** The PCI device for the PCI bridge. */
166 PCIDEVICE PciDev;
167 /** ISA bridge state. */
168 PIIX3 PIIX3State;
169 /** The global data.
170 * Since we've only got one bus at present, we put it here to keep things simple. */
171 PCIGLOBALS Globals;
172} PCIBUS;
173/** Pointer to a PCIBUS instance. */
174typedef PCIBUS *PPCIBUS;
175typedef PCIBUS PCIBus;
176
177
178/** Converts a bus instance pointer to a device instance pointer. */
179#define PCIBUS2DEVINS(pPciBus) ((pPciBus)->CTXSUFF(pDevIns))
180/** Converts a device instance pointer to a PCIGLOBALS pointer. */
181#define DEVINS2PCIGLOBALS(pDevIns) ((PPCIGLOBALS)(&PDMINS2DATA(pDevIns, PPCIBUS)->Globals))
182/** Converts a bus instance pointer to a PCIGLOBALS pointer. */
183#define PCIBUS2PCIGLOBALS(pPciBus) ((PPCIGLOBALS)(&pPciBus->Globals))
184
185
186#ifndef VBOX_DEVICE_STRUCT_TESTCASE
187/*******************************************************************************
188* Internal Functions *
189*******************************************************************************/
190__BEGIN_DECLS
191
192PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel);
193
194__END_DECLS
195
196
197#define DEBUG_PCI
198
199#define PCI_VENDOR_ID 0x00 /* 16 bits */
200#define PCI_DEVICE_ID 0x02 /* 16 bits */
201#define PCI_COMMAND 0x04 /* 16 bits */
202#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
203#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
204#define PCI_CLASS_DEVICE 0x0a /* Device class */
205#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
206#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
207#define PCI_MIN_GNT 0x3e /* 8 bits */
208#define PCI_MAX_LAT 0x3f /* 8 bits */
209
210#ifdef IN_RING3
211
212static void pci_addr_writel(PCIBus *s, uint32_t addr, uint32_t val)
213{
214 s->uConfigReg = val;
215}
216
217static uint32_t pci_addr_readl(PCIBus *s, uint32_t addr)
218{
219 return s->uConfigReg;
220}
221
222static void pci_update_mappings(PCIDevice *d)
223{
224 PCIIORegion *r;
225 int cmd, i;
226 uint32_t last_addr, new_addr, config_ofs;
227
228 cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
229 for(i = 0; i < PCI_NUM_REGIONS; i++) {
230 r = &d->Int.s.aIORegions[i];
231 if (i == PCI_ROM_SLOT) {
232 config_ofs = 0x30;
233 } else {
234 config_ofs = 0x10 + i * 4;
235 }
236 if (r->size != 0) {
237 if (r->type & PCI_ADDRESS_SPACE_IO) {
238 if (cmd & PCI_COMMAND_IO) {
239 new_addr = le32_to_cpu(*(uint32_t *)(d->config +
240 config_ofs));
241 new_addr = new_addr & ~(r->size - 1);
242 last_addr = new_addr + r->size - 1;
243 /* NOTE: we have only 64K ioports on PC */
244 if (last_addr <= new_addr || new_addr == 0 ||
245 last_addr >= 0x10000) {
246 new_addr = ~0U;
247 }
248 } else {
249 new_addr = ~0U;
250 }
251 } else {
252 if (cmd & PCI_COMMAND_MEMORY) {
253 new_addr = le32_to_cpu(*(uint32_t *)(d->config +
254 config_ofs));
255 /* the ROM slot has a specific enable bit */
256 if (i == PCI_ROM_SLOT && !(new_addr & 1))
257 goto no_mem_map;
258 new_addr = new_addr & ~(r->size - 1);
259 last_addr = new_addr + r->size - 1;
260 /* NOTE: we do not support wrapping */
261 /* XXX: as we cannot support really dynamic
262 mappings, we handle specific values as invalid
263 mappings. */
264 if (last_addr <= new_addr || new_addr == 0 ||
265 last_addr == ~0U) {
266 new_addr = ~0U;
267 }
268 } else {
269 no_mem_map:
270 new_addr = ~0U;
271 }
272 }
273 /* now do the real mapping */
274 if (new_addr != r->addr) {
275 if (r->addr != ~0U) {
276 if (r->type & PCI_ADDRESS_SPACE_IO) {
277 int devclass;
278 /* NOTE: specific hack for IDE in PC case:
279 only one byte must be mapped. */
280 devclass = d->config[0x0a] | (d->config[0x0b] << 8);
281 if (devclass == 0x0101 && r->size == 4) {
282 int rc = d->pDevIns->pDevHlp->pfnIOPortDeregister(d->pDevIns, r->addr + 2, 1);
283 AssertRC(rc);
284 } else {
285 int rc = d->pDevIns->pDevHlp->pfnIOPortDeregister(d->pDevIns, r->addr, r->size);
286 AssertRC(rc);
287 }
288 } else {
289 int rc = d->pDevIns->pDevHlp->pfnMMIODeregister(d->pDevIns,
290 r->addr + PCIBUS2PCIGLOBALS(d->Int.s.pBus)->pci_mem_base,
291 r->size);
292#if 0 /** @todo deal correctly with deregistration of MMIO2 ranges and such like. */
293 AssertMsg(VBOX_SUCCESS(rc) || !strcmp(d->name, "vga") || !strcmp(d->name, "VMMDev"), ("rc=%Vrc d=%s\n", rc, d->name)); NOREF(rc);
294#else /* less strict check */
295 AssertMsg(VBOX_SUCCESS(rc) || rc == VERR_IOM_MMIO_RANGE_NOT_FOUND, ("rc=%Vrc d=%s\n", rc, d->name)); NOREF(rc);
296#endif
297 }
298 }
299 r->addr = new_addr;
300 if (r->addr != ~0U) {
301 int rc = r->map_func(d, i,
302 r->addr + (r->type & PCI_ADDRESS_SPACE_IO ? 0 : PCIBUS2PCIGLOBALS(d->Int.s.pBus)->pci_mem_base),
303 r->size, (PCIADDRESSSPACE)(r->type));
304 AssertRC(rc);
305 }
306 }
307 }
308 }
309}
310
311static uint32_t pci_default_read_config(PCIDevice *d,
312 uint32_t address, int len)
313{
314 uint32_t val;
315 switch(len) {
316 case 1:
317 val = d->config[address];
318 break;
319 case 2:
320 val = le16_to_cpu(*(uint16_t *)(d->config + address));
321 break;
322 default:
323 case 4:
324 val = le32_to_cpu(*(uint32_t *)(d->config + address));
325 break;
326 }
327 return val;
328}
329
330static void pci_default_write_config(PCIDevice *d,
331 uint32_t address, uint32_t val, int len)
332{
333 int can_write, i;
334 uint32_t end, addr;
335
336 if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
337 (address >= 0x30 && address < 0x34))) {
338 PCIIORegion *r;
339 int reg;
340
341 if ( address >= 0x30 ) {
342 reg = PCI_ROM_SLOT;
343 }else{
344 reg = (address - 0x10) >> 2;
345 }
346 r = &d->Int.s.aIORegions[reg];
347 if (r->size == 0)
348 goto default_config;
349 /* compute the stored value */
350 if (reg == PCI_ROM_SLOT) {
351 /* keep ROM enable bit */
352 val &= (~(r->size - 1)) | 1;
353 } else {
354 val &= ~(r->size - 1);
355 val |= r->type;
356 }
357 *(uint32_t *)(d->config + address) = cpu_to_le32(val);
358 pci_update_mappings(d);
359 return;
360 }
361 default_config:
362 /* not efficient, but simple */
363 addr = address;
364 for(i = 0; i < len; i++) {
365 /* default read/write accesses */
366 switch(d->config[0x0e]) {
367 case 0x00:
368 case 0x80:
369 switch(addr) {
370 case 0x00:
371 case 0x01:
372 case 0x02:
373 case 0x03:
374 case 0x08:
375 case 0x09:
376 case 0x0a:
377 case 0x0b:
378 case 0x0e:
379 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: /* base */
380 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
381 case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
382 case 0x30: case 0x31: case 0x32: case 0x33: /* rom */
383 case 0x3d:
384 can_write = 0;
385 break;
386 default:
387 can_write = 1;
388 break;
389 }
390 break;
391 default:
392 case 0x01:
393 switch(addr) {
394 case 0x00:
395 case 0x01:
396 case 0x02:
397 case 0x03:
398 case 0x08:
399 case 0x09:
400 case 0x0a:
401 case 0x0b:
402 case 0x0e:
403 case 0x38: case 0x39: case 0x3a: case 0x3b: /* rom */
404 case 0x3d:
405 can_write = 0;
406 break;
407 default:
408 can_write = 1;
409 break;
410 }
411 break;
412 }
413 if (can_write) {
414 d->config[addr] = val;
415 }
416 addr++;
417 val >>= 8;
418 }
419
420 end = address + len;
421 if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
422 /* if the command register is modified, we must modify the mappings */
423 pci_update_mappings(d);
424 }
425}
426
427static void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
428{
429 PCIDevice *pci_dev;
430 int config_addr, iBus;
431
432 Log(("pci_data_write: addr=%08x val=%08x len=%d\n", s->uConfigReg, val, len));
433
434 if (!(s->uConfigReg & (1 << 31))) {
435 return;
436 }
437 if ((s->uConfigReg & 0x3) != 0) {
438 return;
439 }
440 iBus = (s->uConfigReg >> 16) & 0xff;
441 if (iBus != 0)
442 return;
443 pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff];
444 if (!pci_dev)
445 return;
446 config_addr = (s->uConfigReg & 0xfc) | (addr & 3);
447 Log(("pci_config_write: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
448 pci_dev->Int.s.pfnConfigWrite(pci_dev, config_addr, val, len);
449}
450
451static uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
452{
453 PCIDevice *pci_dev;
454 int config_addr, iBus;
455 uint32_t val;
456
457 if (!(s->uConfigReg & (1 << 31)))
458 goto fail;
459 if ((s->uConfigReg & 0x3) != 0)
460 goto fail;
461 iBus = (s->uConfigReg >> 16) & 0xff;
462 if (iBus != 0)
463 goto fail;
464 pci_dev = s->devices[(s->uConfigReg >> 8) & 0xff];
465 if (!pci_dev) {
466 fail:
467 switch(len) {
468 case 1:
469 val = 0xff;
470 break;
471 case 2:
472 val = 0xffff;
473 break;
474 default:
475 case 4:
476 val = 0xffffffff;
477 break;
478 }
479 goto the_end;
480 }
481 config_addr = (s->uConfigReg & 0xfc) | (addr & 3);
482 val = pci_dev->Int.s.pfnConfigRead(pci_dev, config_addr, len);
483 Log(("pci_config_read: %s: addr=%02x val=%08x len=%d\n", pci_dev->name, config_addr, val, len));
484 the_end:
485 return val;
486}
487
488#endif /* IN_RING3 */
489
490
491/* return the global irq number corresponding to a given device irq
492 pin. We could also use the bus number to have a more precise
493 mapping. */
494static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
495{
496 int slot_addend;
497 slot_addend = (pci_dev->devfn >> 3) - 1;
498 return (irq_num + slot_addend) & 3;
499}
500
501static inline int pci_slot_get_apic_pirq(PCIDevice *pci_dev, int irq_num)
502{
503 return (irq_num + (pci_dev->devfn >> 3)) & 7;
504}
505
506static inline int get_pci_irq_apic_level(PPCIGLOBALS pGlobals, int irq_num)
507{
508 int apic_level;
509 apic_level = ((pGlobals->pci_apic_irq_levels[irq_num][0] |
510 pGlobals->pci_apic_irq_levels[irq_num][1]) != 0);
511 return apic_level;
512}
513
514static void apic_set_irq(PPCIBUS pBus, PCIDevice *pci_dev, int irq_num1, int level, int acpi_irq)
515{
516 PPCIGLOBALS pGlobals = PCIBUS2PCIGLOBALS(pBus);
517 int shift, apic_irq, apic_level;
518 uint32_t *p;
519
520 if (acpi_irq == -1) {
521 int uIrqIndex = pci_dev->Int.s.iIrq;
522 int irq_num = pci_slot_get_apic_pirq(pci_dev, irq_num1);
523 p = &pGlobals->pci_apic_irq_levels[irq_num][uIrqIndex >> 5];
524 shift = (uIrqIndex & 0x1f);
525 *p = (*p & ~(1 << shift)) | (level << shift);
526 apic_irq = irq_num + 0x10;
527 apic_level = get_pci_irq_apic_level(pGlobals, irq_num);
528 Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d irq_num1=%d\n",
529 HCSTRING(pci_dev->name), irq_num1, level, apic_irq, apic_level, irq_num));
530 } else {
531 apic_irq = acpi_irq;
532 apic_level = level;
533 Log3(("apic_set_irq: %s: irq_num1=%d level=%d apic_irq=%d apic_level=%d\n",
534 HCSTRING(pci_dev->name), irq_num1, level, apic_irq, apic_level));
535 }
536
537 pBus->CTXALLSUFF(pPciHlp)->pfnIoApicSetIrq(CTXSUFF(pBus->pDevIns), apic_irq, apic_level);
538}
539
540static inline int get_pci_irq_level(PPCIGLOBALS pGlobals, int irq_num)
541{
542 int pic_level;
543#if (PCI_IRQ_WORDS == 2)
544 pic_level = ((pGlobals->pci_irq_levels[irq_num][0] |
545 pGlobals->pci_irq_levels[irq_num][1]) != 0);
546#else
547 {
548 int i;
549 pic_level = 0;
550 for(i = 0; i < PCI_IRQ_WORDS; i++) {
551 if (pGlobals->pci_irq_levels[irq_num][i]) {
552 pic_level = 1;
553 break;
554 }
555 }
556 }
557#endif
558 return pic_level;
559}
560
561/**
562 * Set the IRQ for a PCI device.
563 *
564 * @param pDevIns Device instance of the PCI Bus.
565 * @param pPciDev The PCI device structure.
566 * @param iIrq IRQ number to set.
567 * @param iLevel IRQ level.
568 */
569PDMBOTHCBDECL(void) pciSetIrq(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel)
570{
571 PPCIBUS pBus = PDMINS2DATA(pDevIns, PPCIBUS);
572 PPCIGLOBALS pGlobals = PCIBUS2PCIGLOBALS(pBus);
573 uint8_t *pbCfg = pBus->PIIX3State.dev.config;
574 const bool fIsAcpiDevice = pPciDev->config[2] == 0x13 && pPciDev->config[3] == 0x71;
575 const bool fIsApicEnabled = pGlobals->fUseIoApic && pbCfg[0xde] == 0xbe && pbCfg[0xad] == 0xef;
576 int pic_irq, pic_level;
577 uint32_t *p;
578
579 /* apic only */
580 if (fIsApicEnabled)
581 {
582 if (fIsAcpiDevice)
583 /*
584 * ACPI needs special treatment since SCI is hardwired and
585 * should not be affected by PCI IRQ routing tables at the
586 * same time SCI IRQ is shared in PCI sense hence this
587 * kludge (i.e. we fetch the hardwired value from ACPIs
588 * PCI device configuration space).
589 */
590 apic_set_irq(pBus, pPciDev, -1, iLevel, pPciDev->config[0x3c]);
591 else
592 apic_set_irq(pBus, pPciDev, iIrq, iLevel, -1);
593 return;
594 }
595
596 if (fIsAcpiDevice)
597 {
598 /* As per above treat ACPI in a special way */
599 pic_irq = pPciDev->config[0x3c];
600 pGlobals->acpi_irq = pic_irq;
601 pGlobals->acpi_irq_level = iLevel;
602 }
603 else
604 {
605 int shift, irq_num, uIrqIndex;
606 irq_num = pci_slot_get_pirq(pPciDev, iIrq);
607 uIrqIndex = pPciDev->Int.s.iIrq;
608 p = &pGlobals->pci_irq_levels[irq_num][uIrqIndex >> 5];
609 shift = (uIrqIndex & 0x1f);
610 *p = (*p & ~(1 << shift)) | (iLevel << shift);
611
612 /* now we change the pic irq level according to the piix irq mappings */
613 pic_irq = pbCfg[0x60 + irq_num];
614 if (pic_irq >= 16)
615 return;
616 }
617
618 /* the pic level is the logical OR of all the PCI irqs mapped to it */
619 pic_level = 0;
620 if (pic_irq == pbCfg[0x60])
621 pic_level |= get_pci_irq_level(pGlobals, 0);
622 if (pic_irq == pbCfg[0x61])
623 pic_level |= get_pci_irq_level(pGlobals, 1);
624 if (pic_irq == pbCfg[0x62])
625 pic_level |= get_pci_irq_level(pGlobals, 2);
626 if (pic_irq == pbCfg[0x63])
627 pic_level |= get_pci_irq_level(pGlobals, 3);
628 if (pic_irq == pGlobals->acpi_irq)
629 pic_level |= pGlobals->acpi_irq_level;
630
631 Log3(("piix3_set_irq: %s: iLevel=%d iIrq=%d pic_irq=%d pic_level=%d\n",
632 HCSTRING(pPciDev->name), iLevel, iIrq, pic_irq, pic_level));
633 pBus->CTXALLSUFF(pPciHlp)->pfnIsaSetIrq(CTXSUFF(pBus->pDevIns), pic_irq, pic_level);
634}
635
636#ifdef IN_RING3
637
638static void piix3_reset(PIIX3State *d)
639{
640 uint8_t *pci_conf = d->dev.config;
641
642 pci_conf[0x04] = 0x07; /* master, memory and I/O */
643 pci_conf[0x05] = 0x00;
644 pci_conf[0x06] = 0x00;
645 pci_conf[0x07] = 0x02; /* PCI_status_devsel_medium */
646 pci_conf[0x4c] = 0x4d;
647 pci_conf[0x4e] = 0x03;
648 pci_conf[0x4f] = 0x00;
649 pci_conf[0x60] = 0x80;
650 pci_conf[0x69] = 0x02;
651 pci_conf[0x70] = 0x80;
652 pci_conf[0x76] = 0x0c;
653 pci_conf[0x77] = 0x0c;
654 pci_conf[0x78] = 0x02;
655 pci_conf[0x79] = 0x00;
656 pci_conf[0x80] = 0x00;
657 pci_conf[0x82] = 0x02; /* Get rid of the Linux guest "Enabling Passive Release" PCI quirk warning. */
658 pci_conf[0xa0] = 0x08;
659 pci_conf[0xa0] = 0x08;
660 pci_conf[0xa2] = 0x00;
661 pci_conf[0xa3] = 0x00;
662 pci_conf[0xa4] = 0x00;
663 pci_conf[0xa5] = 0x00;
664 pci_conf[0xa6] = 0x00;
665 pci_conf[0xa7] = 0x00;
666 pci_conf[0xa8] = 0x0f;
667 pci_conf[0xaa] = 0x00;
668 pci_conf[0xab] = 0x00;
669 pci_conf[0xac] = 0x00;
670 pci_conf[0xae] = 0x00;
671}
672
673static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
674{
675 PCIBus *s = d->Int.s.pBus;
676 s->uConfigReg = 0x80000000 | (s->iBus << 16) |
677 (d->devfn << 8) | addr;
678 pci_data_write(s, 0, val, 4);
679}
680
681static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
682{
683 PCIBus *s = d->Int.s.pBus;
684 s->uConfigReg = 0x80000000 | (s->iBus << 16) |
685 (d->devfn << 8) | (addr & ~3);
686 pci_data_write(s, addr & 3, val, 2);
687}
688
689static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
690{
691 PCIBus *s = d->Int.s.pBus;
692 s->uConfigReg = 0x80000000 | (s->iBus << 16) |
693 (d->devfn << 8) | (addr & ~3);
694 pci_data_write(s, addr & 3, val, 1);
695}
696
697static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
698{
699 PCIBus *s = d->Int.s.pBus;
700 s->uConfigReg = 0x80000000 | (s->iBus << 16) |
701 (d->devfn << 8) | (addr & ~3);
702 return pci_data_read(s, addr & 3, 2);
703}
704
705static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
706{
707 PCIBus *s = d->Int.s.pBus;
708 s->uConfigReg = 0x80000000 | (s->iBus << 16) |
709 (d->devfn << 8) | (addr & ~3);
710 return pci_data_read(s, addr & 3, 1);
711}
712
713/* host irqs corresponding to PCI irqs A-D */
714static const uint8_t pci_irqs[4] = { 11, 9, 11, 9 }; /* bird: added const */
715
716static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
717{
718 PCIIORegion *r;
719 uint16_t cmd;
720 uint32_t ofs;
721
722 if ( region_num == PCI_ROM_SLOT ) {
723 ofs = 0x30;
724 }else{
725 ofs = 0x10 + region_num * 4;
726 }
727
728 pci_config_writel(d, ofs, addr);
729 r = &d->Int.s.aIORegions[region_num];
730
731 /* enable memory mappings */
732 cmd = pci_config_readw(d, PCI_COMMAND);
733 if ( region_num == PCI_ROM_SLOT )
734 cmd |= 2;
735 else if (r->type & PCI_ADDRESS_SPACE_IO)
736 cmd |= 1;
737 else
738 cmd |= 2;
739 pci_config_writew(d, PCI_COMMAND, cmd);
740}
741
742static void pci_bios_init_device(PCIDevice *d)
743{
744 int devclass;
745 PCIIORegion *r;
746 uint32_t *paddr;
747 int i, pin, pic_irq, vendor_id, device_id;
748
749 devclass = pci_config_readw(d, PCI_CLASS_DEVICE);
750 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
751 device_id = pci_config_readw(d, PCI_DEVICE_ID);
752 switch(devclass)
753 {
754 case 0x0101:
755 if (vendor_id == 0x8086 && device_id == 0x7010) {
756 /* PIIX3 IDE */
757 pci_config_writew(d, 0x40, 0x8000); /* enable IDE0 */
758 pci_config_writew(d, 0x42, 0x8000); /* enable IDE1 */
759 goto default_map;
760 } else {
761 /* IDE: we map it as in ISA mode */
762 pci_set_io_region_addr(d, 0, 0x1f0);
763 pci_set_io_region_addr(d, 1, 0x3f4);
764 pci_set_io_region_addr(d, 2, 0x170);
765 pci_set_io_region_addr(d, 3, 0x374);
766 }
767 break;
768 case 0x0300:
769 if (vendor_id != 0x80ee)
770 goto default_map;
771 /* VGA: map frame buffer to default Bochs VBE address */
772 pci_set_io_region_addr(d, 0, 0xE0000000);
773 break;
774 case 0x0800:
775 /* PIC */
776 vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
777 device_id = pci_config_readw(d, PCI_DEVICE_ID);
778 if (vendor_id == 0x1014) {
779 /* IBM */
780 if (device_id == 0x0046 || device_id == 0xFFFF) {
781 /* MPIC & MPIC2 */
782 pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
783 }
784 }
785 break;
786 case 0xff00:
787 if (vendor_id == 0x0106b &&
788 (device_id == 0x0017 || device_id == 0x0022)) {
789 /* macio bridge */
790 pci_set_io_region_addr(d, 0, 0x80800000);
791 }
792 break;
793 default:
794 default_map:
795 /* default memory mappings */
796 for(i = 0; i < PCI_NUM_REGIONS; i++) {
797 r = &d->Int.s.aIORegions[i];
798
799 if (r->size) {
800 if (r->type & PCI_ADDRESS_SPACE_IO)
801 paddr = &PCIBUS2PCIGLOBALS(d->Int.s.pBus)->pci_bios_io_addr;
802 else
803 paddr = &PCIBUS2PCIGLOBALS(d->Int.s.pBus)->pci_bios_mem_addr;
804 *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
805 pci_set_io_region_addr(d, i, *paddr);
806 *paddr += r->size;
807 }
808 }
809 break;
810 }
811
812 /* map the interrupt */
813 pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
814 if (pin != 0) {
815 pin = pci_slot_get_pirq(d, pin - 1);
816 pic_irq = pci_irqs[pin];
817 pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
818 }
819}
820
821/* -=-=-=-=-=- wrappers -=-=-=-=-=- */
822
823/**
824 * Port I/O Handler for PCI address OUT operations.
825 *
826 * @returns VBox status code.
827 *
828 * @param pDevIns The device instance.
829 * @param pvUser User argument - ignored.
830 * @param uPort Port number used for the IN operation.
831 * @param u32 The value to output.
832 * @param cb The value size in bytes.
833 */
834static DECLCALLBACK(int) pciIOPortAddressWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
835{
836 Log(("pciIOPortAddressWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
837 NOREF(pvUser);
838 if (cb == 4)
839 {
840 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
841 pci_addr_writel(PDMINS2DATA(pDevIns, PCIBus *), Port, u32);
842 PCI_UNLOCK(pDevIns);
843 }
844 /* else: 440FX does "pass through to the bus" for other writes, what ever that means.
845 * Linux probes for cmd640 using byte writes/reads during ide init. We'll just ignore it. */
846 return VINF_SUCCESS;
847}
848
849/**
850 * Port I/O Handler for PCI address IN operations.
851 *
852 * @returns VBox status code.
853 *
854 * @param pDevIns The device instance.
855 * @param pvUser User argument - ignored.
856 * @param uPort Port number used for the IN operation.
857 * @param pu32 Where to store the result.
858 * @param cb Number of bytes read.
859 */
860static DECLCALLBACK(int) pciIOPortAddressRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
861{
862 NOREF(pvUser);
863 if (cb == 4)
864 {
865 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
866 *pu32 = pci_addr_readl(PDMINS2DATA(pDevIns, PCIBus *), Port);
867 PCI_UNLOCK(pDevIns);
868 Log(("pciIOPortAddressRead: Port=%#x cb=%d -> %#x\n", Port, cb, *pu32));
869 return VINF_SUCCESS;
870 }
871 /* else: 440FX does "pass through to the bus" for other writes, what ever that means.
872 * Linux probes for cmd640 using byte writes/reads during ide init. We'll just ignore it. */
873 Log(("pciIOPortAddressRead: Port=%#x cb=%d VERR_IOM_IOPORT_UNUSED\n", Port, cb));
874 return VERR_IOM_IOPORT_UNUSED;
875}
876
877
878/**
879 * Port I/O Handler for PCI data OUT operations.
880 *
881 * @returns VBox status code.
882 *
883 * @param pDevIns The device instance.
884 * @param pvUser User argument - ignored.
885 * @param uPort Port number used for the IN operation.
886 * @param u32 The value to output.
887 * @param cb The value size in bytes.
888 */
889static DECLCALLBACK(int) pciIOPortDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
890{
891 Log(("pciIOPortDataWrite: Port=%#x u32=%#x cb=%d\n", Port, u32, cb));
892 NOREF(pvUser);
893 if (!(Port % cb))
894 {
895 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_WRITE);
896 pci_data_write(PDMINS2DATA(pDevIns, PCIBus *), Port, u32, cb);
897 PCI_UNLOCK(pDevIns);
898 }
899 else
900 AssertMsgFailed(("Write to port %#x u32=%#x cb=%d\n", Port, u32, cb));
901 return VINF_SUCCESS;
902}
903
904
905/**
906 * Port I/O Handler for PCI data IN operations.
907 *
908 * @returns VBox status code.
909 *
910 * @param pDevIns The device instance.
911 * @param pvUser User argument - ignored.
912 * @param uPort Port number used for the IN operation.
913 * @param pu32 Where to store the result.
914 * @param cb Number of bytes read.
915 */
916static DECLCALLBACK(int) pciIOPortDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
917{
918 NOREF(pvUser);
919 if (!(Port % cb))
920 {
921 PCI_LOCK(pDevIns, VINF_IOM_HC_IOPORT_READ);
922 *pu32 = pci_data_read(PDMINS2DATA(pDevIns, PCIBus *), Port, cb);
923 PCI_UNLOCK(pDevIns);
924 Log(("pciIOPortDataRead: Port=%#x cb=%#x -> %#x\n", Port, cb, *pu32));
925 return VINF_SUCCESS;
926 }
927 AssertMsgFailed(("Read from port %#x cb=%d\n", Port, cb));
928 return VERR_IOM_IOPORT_UNUSED;
929}
930
931
932/**
933 * Saves a state of the PCI device.
934 *
935 * @returns VBox status code.
936 * @param pDevIns Device instance of the PCI Bus.
937 * @param pPciDev Pointer to PCI device.
938 * @param pSSMHandle The handle to save the state to.
939 */
940static DECLCALLBACK(int) pciGenericSaveExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)
941{
942 return SSMR3PutMem(pSSMHandle, &pPciDev->config[0], sizeof(pPciDev->config));
943}
944
945
946/**
947 * Loads a saved PCI device state.
948 *
949 * @returns VBox status code.
950 * @param pDevIns Device instance of the PCI Bus.
951 * @param pPciDev Pointer to PCI device.
952 * @param pSSMHandle The handle to the saved state.
953 */
954static DECLCALLBACK(int) pciGenericLoadExec(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle)
955{
956 return SSMR3GetMem(pSSMHandle, &pPciDev->config[0], sizeof(pPciDev->config));
957}
958
959
960/**
961 * Saves a state of the PCI device.
962 *
963 * @returns VBox status code.
964 * @param pDevIns The device instance.
965 * @param pPciDev Pointer to PCI device.
966 * @param pSSMHandle The handle to save the state to.
967 */
968static DECLCALLBACK(int) pciSaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle)
969{
970 uint32_t i;
971 PPCIBUS pData = PDMINS2DATA(pDevIns, PPCIBUS);
972 PPCIGLOBALS pGlobals = PCIBUS2PCIGLOBALS(pData);
973
974 /*
975 * Bus state data.
976 */
977 SSMR3PutU32(pSSMHandle, pData->uConfigReg);
978 SSMR3PutBool(pSSMHandle, pGlobals->fUseIoApic);
979 SSMR3PutU32(pSSMHandle, ~0); /* separator */
980
981 /*
982 * Iterate all the devices.
983 */
984 for (i = 0; i < ELEMENTS(pData->devices); i++)
985 {
986 PPCIDEVICE pDev = pData->devices[i];
987 if (pDev)
988 {
989 int rc;
990 SSMR3PutU32(pSSMHandle, i);
991 SSMR3PutMem(pSSMHandle, pDev->config, sizeof(pDev->config));
992 rc = SSMR3PutS32(pSSMHandle, pDev->Int.s.iIrq);
993 if (VBOX_FAILURE(rc))
994 return rc;
995 }
996 }
997 return SSMR3PutU32(pSSMHandle, ~0); /* terminator */
998}
999
1000/**
1001 * Loads a saved PCI device state.
1002 *
1003 * @returns VBox status code.
1004 * @param pDevIns The device instance.
1005 * @param pSSMHandle The handle to the saved state.
1006 * @param u32Version The data unit version number.
1007 */
1008static DECLCALLBACK(int) pciLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t u32Version)
1009{
1010 PPCIBUS pData = PDMINS2DATA(pDevIns, PPCIBUS);
1011 PPCIGLOBALS pGlobals = PCIBUS2PCIGLOBALS(pData);
1012 uint32_t u32;
1013 uint32_t i;
1014 int rc;
1015
1016 /*
1017 * Check the version.
1018 */
1019 if (u32Version > 2)
1020 {
1021 AssertFailed();
1022 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
1023 }
1024
1025 /*
1026 * Bus state data.
1027 */
1028 SSMR3GetU32(pSSMHandle, &pData->uConfigReg);
1029 if (u32Version > 1)
1030 SSMR3GetBool(pSSMHandle, &pGlobals->fUseIoApic);
1031
1032 /* separator */
1033 rc = SSMR3GetU32(pSSMHandle, &u32);
1034 if (VBOX_FAILURE(rc))
1035 return rc;
1036 if (u32 != (uint32_t)~0)
1037 {
1038 AssertMsgFailed(("u32=%#x\n", u32));
1039 return rc;
1040 }
1041
1042 /*
1043 * Iterate all the devices.
1044 */
1045 for (i = 0;; i++)
1046 {
1047 PCIDEVICE DevTmp;
1048 PPCIDEVICE pDev;
1049
1050 /* index / terminator */
1051 rc = SSMR3GetU32(pSSMHandle, &u32);
1052 if (VBOX_FAILURE(rc))
1053 return rc;
1054 if (u32 == (uint32_t)~0)
1055 break;
1056 if ( u32 >= ELEMENTS(pData->devices)
1057 || u32 < i)
1058 {
1059 AssertMsgFailed(("u32=%#x i=%#x\n", u32, i));
1060 return rc;
1061 }
1062
1063 /* skip forward to the device checking that no new devices are present. */
1064 for (; i < u32; i++)
1065 {
1066 if (pData->devices[i])
1067 {
1068 LogRel(("New device in slot %#x, %s\n", i, pData->devices[i]->name));
1069 AssertFailed();
1070 return VERR_SSM_LOAD_CONFIG_MISMATCH;
1071 }
1072 }
1073
1074 /* check that it's still around. */
1075 pDev = pData->devices[i];
1076 if (!pDev)
1077 {
1078 LogRel(("Device in slot %#x has been removed!\n", i, pDev->name));
1079 AssertFailed();
1080 return VERR_SSM_LOAD_CONFIG_MISMATCH;
1081 }
1082
1083 /* restore it */
1084 SSMR3GetMem(pSSMHandle, DevTmp.config, sizeof(DevTmp.config));
1085 rc = SSMR3GetS32(pSSMHandle, &DevTmp.Int.s.iIrq);
1086 if (VBOX_FAILURE(rc))
1087 return rc;
1088
1089 /* match the vendor id assuming that this will never be changed. */
1090 if ( DevTmp.config[0] != pDev->config[0]
1091 || DevTmp.config[1] != pDev->config[1])
1092 {
1093 LogRel(("Device in slot %#x (%s) vendor id mismatch! saved=%.4Vhxs current=%.4Vhxs\n",
1094 i, pDev->name, DevTmp.config, pDev->config));
1095 AssertFailed();
1096 return VERR_SSM_LOAD_CONFIG_MISMATCH;
1097 }
1098
1099 /* commit the loaded device config. */
1100 memcpy(pDev->config, DevTmp.config, sizeof(pDev->config));
1101 if (DevTmp.Int.s.iIrq >= PCI_DEVICES_MAX) {
1102 AssertMsgFailed (("Device %s: Too many devices %d (max=%d)\n",
1103 pDev->name, DevTmp.Int.s.iIrq, PCI_DEVICES_MAX));
1104 return VERR_TOO_MUCH_DATA;
1105 }
1106
1107 pDev->Int.s.iIrq = DevTmp.Int.s.iIrq;
1108 }
1109 return VINF_SUCCESS;
1110}
1111
1112
1113/* -=-=-=-=-=- real code -=-=-=-=-=- */
1114
1115
1116/**
1117 * Registers the device with the default PCI bus.
1118 *
1119 * @returns VBox status code.
1120 * @param pBus The bus to register with.
1121 * @param iDev The PCI device ordinal.
1122 * @param pPciDev The PCI device structure.
1123 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique.
1124 */
1125static void pciRegisterInternal(PPCIBUS pBus, int iDev, PPCIDEVICE pPciDev, const char *pszName)
1126{
1127 Assert(!pBus->devices[iDev]);
1128 pPciDev->devfn = iDev;
1129 pPciDev->name = pszName;
1130 pPciDev->Int.s.pBus = pBus;
1131 pPciDev->Int.s.pfnConfigRead = pci_default_read_config;
1132 pPciDev->Int.s.pfnConfigWrite = pci_default_write_config;
1133 AssertMsg(pBus->uIrqIndex < PCI_DEVICES_MAX,
1134 ("Device %s: Too many devices %d (max=%d)\n",
1135 pszName, pBus->uIrqIndex, PCI_DEVICES_MAX));
1136 pPciDev->Int.s.iIrq = pBus->uIrqIndex++;
1137 pBus->devices[iDev] = pPciDev;
1138 Log(("PCI: Registered device %d function %d (%#x) '%s'.\n",
1139 iDev >> 3, iDev & 7, 0x80000000 | (iDev << 8), pszName));
1140}
1141
1142
1143/**
1144 * Registers the device with the default PCI bus.
1145 *
1146 * @returns VBox status code.
1147 * @param pDevIns Device instance of the PCI Bus.
1148 * @param pPciDev The PCI device structure.
1149 * Any PCI enabled device must keep this in it's instance data!
1150 * Fill in the PCI data config before registration, please.
1151 * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique.
1152 * @param iDev The PCI device number. Use a negative value for auto assigning one.
1153 */
1154static DECLCALLBACK(int) pciRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev)
1155{
1156 PPCIBUS pBus = PDMINS2DATA(pDevIns, PPCIBUS);
1157
1158 /*
1159 * Check input.
1160 */
1161 if ( !pszName
1162 || !pPciDev
1163 || iDev >= (int)ELEMENTS(pBus->devices)
1164 || (iDev >= 0 && iDev <= 8))
1165 {
1166 AssertMsgFailed(("Invalid argument! pszName=%s pPciDev=%p iDev=%d\n", pszName, pPciDev, iDev));
1167 return VERR_INVALID_PARAMETER;
1168 }
1169
1170 /*
1171 * Find device slot.
1172 */
1173 if (iDev < 0)
1174 {
1175 /*
1176 * Special check for the IDE controller which is our function 1 device
1177 * before searching.
1178 */
1179 if ( !strcmp(pszName, "piix3ide")
1180 && !pBus->devices[9])
1181 iDev = 9;
1182 else
1183 {
1184 Assert(!(pBus->iDevSearch % 8));
1185 for (iDev = pBus->iDevSearch; iDev < (int)ELEMENTS(pBus->devices); iDev += 8)
1186 if ( !pBus->devices[iDev]
1187 && !pBus->devices[iDev + 1]
1188 && !pBus->devices[iDev + 2]
1189 && !pBus->devices[iDev + 3]
1190 && !pBus->devices[iDev + 4]
1191 && !pBus->devices[iDev + 5]
1192 && !pBus->devices[iDev + 6]
1193 && !pBus->devices[iDev + 7])
1194 break;
1195 if (iDev >= (int)ELEMENTS(pBus->devices))
1196 {
1197 AssertMsgFailed(("Couldn't find free spot!\n"));
1198 return VERR_PDM_TOO_PCI_MANY_DEVICES;
1199 }
1200 }
1201 pPciDev->Int.s.fRequestedDevFn = false;
1202 }
1203 else
1204 {
1205 /*
1206 * An explicit request.
1207 *
1208 * If the slot is occupied we'll have to relocate the device
1209 * currently occupying it first. This can only be done if the
1210 * existing device wasn't explicitly assigned. Also we limit
1211 * ourselves to function 0 devices.
1212 *
1213 * If you start setting devices + function in the
1214 * config, do it for all pci devices!
1215 */
1216 AssertReleaseMsg(iDev > 8, ("iDev=%d pszName=%s\n", iDev, pszName));
1217 if (pBus->devices[iDev])
1218 {
1219 int iDevRel;
1220 AssertReleaseMsg(!(iDev % 8), ("PCI Configuration Conflict! iDev=%d pszName=%s clashes with %s\n",
1221 iDev, pszName, pBus->devices[iDev]->name));
1222 if ( pBus->devices[iDev]->Int.s.fRequestedDevFn
1223 || (pBus->devices[iDev + 1] && pBus->devices[iDev + 1]->Int.s.fRequestedDevFn)
1224 || (pBus->devices[iDev + 2] && pBus->devices[iDev + 2]->Int.s.fRequestedDevFn)
1225 || (pBus->devices[iDev + 3] && pBus->devices[iDev + 3]->Int.s.fRequestedDevFn)
1226 || (pBus->devices[iDev + 4] && pBus->devices[iDev + 4]->Int.s.fRequestedDevFn)
1227 || (pBus->devices[iDev + 5] && pBus->devices[iDev + 5]->Int.s.fRequestedDevFn)
1228 || (pBus->devices[iDev + 6] && pBus->devices[iDev + 6]->Int.s.fRequestedDevFn)
1229 || (pBus->devices[iDev + 7] && pBus->devices[iDev + 7]->Int.s.fRequestedDevFn))
1230 {
1231 AssertReleaseMsgFailed(("Configuration error:'%s' and '%s' are both configured as device %d\n",
1232 pszName, pBus->devices[iDev]->name, iDev));
1233 return VERR_INTERNAL_ERROR;
1234 }
1235
1236 /* Find free slot for the device(s) we're moving and move them. */
1237 for (iDevRel = pBus->iDevSearch; iDevRel < (int)ELEMENTS(pBus->devices); iDevRel += 8)
1238 {
1239 if ( !pBus->devices[iDevRel]
1240 && !pBus->devices[iDevRel + 1]
1241 && !pBus->devices[iDevRel + 2]
1242 && !pBus->devices[iDevRel + 3]
1243 && !pBus->devices[iDevRel + 4]
1244 && !pBus->devices[iDevRel + 5]
1245 && !pBus->devices[iDevRel + 6]
1246 && !pBus->devices[iDevRel + 7])
1247 {
1248 int i = 0;
1249 for (i = 0; i < 8; i++)
1250 {
1251 if (!pBus->devices[iDev + i])
1252 continue;
1253 Log(("PCI: relocating '%s' from slot %#x to %#x\n", pBus->devices[iDev + i]->name, iDev + i, iDevRel + i));
1254 pBus->devices[iDevRel + i] = pBus->devices[iDev + i];
1255 pBus->devices[iDevRel + i]->devfn = i;
1256 pBus->devices[iDev + i] = NULL;
1257 }
1258 }
1259 }
1260 if (pBus->devices[iDev])
1261 {
1262 AssertMsgFailed(("Couldn't find free spot!\n"));
1263 return VERR_PDM_TOO_PCI_MANY_DEVICES;
1264 }
1265 } /* if conflict */
1266 pPciDev->Int.s.fRequestedDevFn = true;
1267 }
1268
1269 /*
1270 * Register the device.
1271 */
1272 pciRegisterInternal(pBus, iDev, pPciDev, pszName);
1273 return VINF_SUCCESS;
1274}
1275
1276
1277static DECLCALLBACK(int) pciIORegionRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
1278{
1279 PPCIIOREGION pRegion;
1280
1281 /*
1282 * Validate.
1283 */
1284 if ( enmType != PCI_ADDRESS_SPACE_MEM
1285 && enmType != PCI_ADDRESS_SPACE_IO
1286 && enmType != PCI_ADDRESS_SPACE_MEM_PREFETCH)
1287 {
1288 AssertMsgFailed(("Invalid enmType=%#x? Or was this a bitmask after all...\n", enmType));
1289 return VERR_INVALID_PARAMETER;
1290 }
1291 if ((unsigned)iRegion >= PCI_NUM_REGIONS)
1292 {
1293 AssertMsgFailed(("Invalid iRegion=%d PCI_NUM_REGIONS=%d\n", iRegion, PCI_NUM_REGIONS));
1294 return VERR_INVALID_PARAMETER;
1295 }
1296
1297 /*
1298 * Register the I/O region.
1299 */
1300 pRegion = &pPciDev->Int.s.aIORegions[iRegion];
1301 pRegion->addr = ~0U;
1302 pRegion->size = cbRegion;
1303 pRegion->type = enmType;
1304 pRegion->map_func = pfnCallback;
1305 return VINF_SUCCESS;
1306}
1307
1308
1309/**
1310 * Called to perform the job of the bios.
1311 *
1312 * @returns VBox status.
1313 * @param pDevIns Device instance of the first bus.
1314 */
1315static DECLCALLBACK(int) pciFakePCIBIOS(PPDMDEVINS pDevIns)
1316{
1317 int rc;
1318 unsigned i;
1319 uint8_t elcr[2] = {0, 0};
1320 PPCIGLOBALS pGlobals = DEVINS2PCIGLOBALS(pDevIns);
1321 PPCIBUS pBus = PDMINS2DATA(pDevIns, PPCIBUS);
1322 PVM pVM = PDMDevHlpGetVM(pDevIns);
1323 Assert(pVM);
1324
1325 /*
1326 * Set the start addresses.
1327 */
1328 pGlobals->pci_bios_io_addr = 0xc000;
1329 pGlobals->pci_bios_mem_addr = 0xf0000000;
1330
1331 /*
1332 * Activate IRQ mappings.
1333 */
1334 for (i = 0; i < 4; i++)
1335 {
1336 uint8_t irq = pci_irqs[i];
1337 /* Set to trigger level. */
1338 elcr[irq >> 3] |= (1 << (irq & 7));
1339 /* Activate irq remapping in PIIX3. */
1340 pci_config_writeb(&pBus->PIIX3State.dev, 0x60 + i, irq);
1341 }
1342
1343 /* Tell to the PIC. */
1344 rc = IOMIOPortWrite(pVM, 0x4d0, elcr[0], sizeof(uint8_t));
1345 if (rc == VINF_SUCCESS)
1346 rc = IOMIOPortWrite(pVM, 0x4d1, elcr[1], sizeof(uint8_t));
1347 if (rc != VINF_SUCCESS)
1348 {
1349 AssertMsgFailed(("Writing to PIC failed!\n"));
1350 return VBOX_SUCCESS(rc) ? VERR_INTERNAL_ERROR : rc;
1351 }
1352
1353 /*
1354 * Init the devices.
1355 */
1356 for (i = 0; i < ELEMENTS(pBus->devices); i++)
1357 {
1358 if (pBus->devices[i])
1359 {
1360 Log2(("PCI: Initializing device %d (%#x) '%s'\n",
1361 i, 0x80000000 | (i << 8), pBus->devices[i]->name));
1362 pci_bios_init_device(pBus->devices[i]);
1363 }
1364 }
1365 return VINF_SUCCESS;
1366}
1367
1368
1369/**
1370 * @copydoc FNPDMDEVRELOCATE
1371 */
1372static DECLCALLBACK(void) pciRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
1373{
1374 PPCIBUS pBus = PDMINS2DATA(pDevIns, PPCIBUS);
1375 pBus->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
1376 pBus->pPciHlpGC = pBus->pPciHlpR3->pfnGetGCHelpers(pDevIns);
1377}
1378
1379
1380/**
1381 * Construct a PCI Bus device instance for a VM.
1382 *
1383 * @returns VBox status.
1384 * @param pDevIns The device instance data.
1385 * If the registration structure is needed, pDevIns->pDevReg points to it.
1386 * @param iInstance Instance number. Use this to figure out which registers and such to use.
1387 * The device number is also found in pDevIns->iInstance, but since it's
1388 * likely to be freqently used PDM passes it as parameter.
1389 * @param pCfgHandle Configuration node handle for the device. Use this to obtain the configuration
1390 * of the device instance. It's also found in pDevIns->pCfgHandle, but like
1391 * iInstance it's expected to be used a bit in this function.
1392 */
1393static DECLCALLBACK(int) pciConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
1394{
1395 PPCIGLOBALS pGlobals = DEVINS2PCIGLOBALS(pDevIns);
1396 PPCIBUS pBus = PDMINS2DATA(pDevIns, PPCIBUS);
1397 PDMPCIBUSREG PciBusReg;
1398 int rc;
1399 bool fGCEnabled;
1400 bool fR0Enabled;
1401 bool fUseIoApic;
1402 Assert(iInstance == 0);
1403
1404 /*
1405 * Validate and read configuration.
1406 */
1407 if (!CFGMR3AreValuesValid(pCfgHandle, "IOAPIC\0" "GCEnabled\0R0Enabled\0"))
1408 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
1409
1410 /* query whether we got an IOAPIC */
1411 rc = CFGMR3QueryBool(pCfgHandle, "IOAPIC", &fUseIoApic);
1412 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1413 fUseIoApic = false;
1414 else if (VBOX_FAILURE(rc))
1415 return PDMDEV_SET_ERROR(pDevIns, rc,
1416 N_("Configuration error: Failed to query boolean value \"IOAPIC\"."));
1417
1418 /* check if GC code is enabled. */
1419 rc = CFGMR3QueryBool(pCfgHandle, "GCEnabled", &fGCEnabled);
1420 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1421 fGCEnabled = true;
1422 else if (VBOX_FAILURE(rc))
1423 return PDMDEV_SET_ERROR(pDevIns, rc,
1424 N_("Configuration error: Failed to query boolean value \"GCEnabled\"."));
1425 Log(("PCI: fGCEnabled=%d\n", fGCEnabled));
1426
1427 /* check if R0 code is enabled. */
1428 rc = CFGMR3QueryBool(pCfgHandle, "R0Enabled", &fR0Enabled);
1429 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
1430 fR0Enabled = true;
1431 else if (VBOX_FAILURE(rc))
1432 return PDMDEV_SET_ERROR(pDevIns, rc,
1433 N_("Configuration error: Failed to query boolean value \"R0Enabled\"."));
1434 Log(("PCI: fR0Enabled=%d\n", fR0Enabled));
1435
1436 /*
1437 * Init data and register the PCI bus.
1438 */
1439 pGlobals->pci_mem_base = 0;
1440 pGlobals->pci_bios_io_addr = 0xc000;
1441 pGlobals->pci_bios_mem_addr = 0xf0000000;
1442 memset(&pGlobals->pci_irq_levels, 0, sizeof(pGlobals->pci_irq_levels));
1443 pGlobals->fUseIoApic = fUseIoApic;
1444 memset(&pGlobals->pci_apic_irq_levels, 0, sizeof(pGlobals->pci_apic_irq_levels));
1445
1446 pBus->pDevInsHC = pDevIns;
1447 pBus->pDevInsGC = PDMDEVINS_2_GCPTR(pDevIns);
1448
1449 PciBusReg.u32Version = PDM_PCIBUSREG_VERSION;
1450 PciBusReg.pfnRegisterHC = pciRegister;
1451 PciBusReg.pfnIORegionRegisterHC = pciIORegionRegister;
1452 PciBusReg.pfnSetIrqHC = pciSetIrq;
1453 PciBusReg.pfnSaveExecHC = pciGenericSaveExec;
1454 PciBusReg.pfnLoadExecHC = pciGenericLoadExec;
1455 PciBusReg.pfnFakePCIBIOSHC = pciFakePCIBIOS;
1456 PciBusReg.pszSetIrqGC = fGCEnabled ? "pciSetIrq" : NULL;
1457 PciBusReg.pszSetIrqR0 = fR0Enabled ? "pciSetIrq" : NULL;
1458 rc = pDevIns->pDevHlp->pfnPCIBusRegister(pDevIns, &PciBusReg, &pBus->pPciHlpR3);
1459 if (VBOX_FAILURE(rc))
1460 return PDMDEV_SET_ERROR(pDevIns, rc,
1461 N_("Failed to register ourselves as a PCI Bus"));
1462
1463 pBus->pPciHlpGC = pBus->pPciHlpR3->pfnGetGCHelpers(pDevIns);
1464 pBus->pPciHlpR0 = pBus->pPciHlpR3->pfnGetR0Helpers(pDevIns);
1465
1466 /*
1467 * Fill in PCI configs and add them to the bus.
1468 */
1469 /* i440FX */
1470 pBus->PciDev.config[0x00] = 0x86; /* vendor_id: Intel */
1471 pBus->PciDev.config[0x01] = 0x80;
1472 pBus->PciDev.config[0x02] = 0x37; /* device_id: */
1473 pBus->PciDev.config[0x03] = 0x12;
1474 pBus->PciDev.config[0x08] = 0x02; /* revision */
1475 pBus->PciDev.config[0x0a] = 0x00; /* class_sub = host2pci */
1476 pBus->PciDev.config[0x0b] = 0x06; /* class_base = PCI_bridge */
1477 pBus->PciDev.config[0x0e] = 0x00; /* header_type */
1478 pBus->PciDev.pDevIns = pDevIns;
1479 pBus->PciDev.Int.s.fRequestedDevFn= true;
1480 pciRegisterInternal(pBus, 0, &pBus->PciDev, "i440FX");
1481
1482 /* PIIX3 */
1483 pBus->PIIX3State.dev.config[0x00] = 0x86; /* vendor: Intel */
1484 pBus->PIIX3State.dev.config[0x01] = 0x80;
1485 pBus->PIIX3State.dev.config[0x02] = 0x00; /* device_id: 82371SB PIIX3 PCI-to-ISA bridge (Step A1) */
1486 pBus->PIIX3State.dev.config[0x03] = 0x70;
1487 pBus->PIIX3State.dev.config[0x0a] = 0x01; /* class_sub = PCI_ISA */
1488 pBus->PIIX3State.dev.config[0x0b] = 0x06; /* class_base = PCI_bridge */
1489 pBus->PIIX3State.dev.config[0x0e] = 0x80; /* header_type = PCI_multifunction, generic */
1490 pBus->PIIX3State.dev.pDevIns = pDevIns;
1491 pBus->PciDev.Int.s.fRequestedDevFn= true;
1492 pciRegisterInternal(pBus, 8, &pBus->PIIX3State.dev, "PIIX3");
1493 piix3_reset(&pBus->PIIX3State);
1494
1495 pBus->iDevSearch = 16;
1496
1497 /*
1498 * Register I/O ports and save state.
1499 */
1500 rc = PDMDevHlpIOPortRegister(pDevIns, 0xcf8, 1, NULL, pciIOPortAddressWrite, pciIOPortAddressRead, NULL, NULL, "i440FX (PCI)");
1501 if (VBOX_FAILURE(rc))
1502 return rc;
1503 rc = PDMDevHlpIOPortRegister(pDevIns, 0xcfc, 4, NULL, pciIOPortDataWrite, pciIOPortDataRead, NULL, NULL, "i440FX (PCI)");
1504 if (VBOX_FAILURE(rc))
1505 return rc;
1506 rc = PDMDevHlpSSMRegister(pDevIns, "pci", iInstance, 2, sizeof(*pBus),
1507 NULL, pciSaveExec, NULL, NULL, pciLoadExec, NULL);
1508 if (VBOX_FAILURE(rc))
1509 return rc;
1510
1511 return VINF_SUCCESS;
1512}
1513
1514
1515/**
1516 * The device registration structure.
1517 */
1518const PDMDEVREG g_DevicePCI =
1519{
1520 /* u32Version */
1521 PDM_DEVREG_VERSION,
1522 /* szDeviceName */
1523 "pci",
1524 /* szGCMod */
1525 "VBoxDDGC.gc",
1526 /* szR0Mod */
1527 "VBoxDDR0.r0",
1528 /* pszDescription */
1529 "i440FX PCI bridge and PIIX3 ISA bridge.",
1530 /* fFlags */
1531 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32 | PDM_DEVREG_FLAGS_GC | PDM_DEVREG_FLAGS_R0,
1532 /* fClass */
1533 PDM_DEVREG_CLASS_BUS_PCI | PDM_DEVREG_CLASS_BUS_ISA,
1534 /* cMaxInstances */
1535 1,
1536 /* cbInstance */
1537 sizeof(PCIBUS),
1538 /* pfnConstruct */
1539 pciConstruct,
1540 /* pfnDestruct */
1541 NULL,
1542 /* pfnRelocate */
1543 pciRelocate,
1544 /* pfnIOCtl */
1545 NULL,
1546 /* pfnPowerOn */
1547 NULL,
1548 /* pfnReset */
1549 NULL,
1550 /* pfnSuspend */
1551 NULL,
1552 /* pfnResume */
1553 NULL,
1554 /* pfnAttach */
1555 NULL,
1556 /* pfnDetach */
1557 NULL,
1558 /* pfnQueryInterface */
1559 NULL,
1560 /* pfnInitComplete */
1561 NULL
1562};
1563#endif /* IN_RING3 */
1564#endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette